]>
Commit | Line | Data |
---|---|---|
212380e3 AC |
1 | /************************************************************************ |
2 | * IRC - Internet Relay Chat, src/match.c | |
3 | * Copyright (C) 1990 Jarkko Oikarinen | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation; either version 1, or (at your option) | |
8 | * any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, write to the Free Software | |
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
18 | * | |
212380e3 AC |
19 | */ |
20 | #include "stdinc.h" | |
9b8e9eb3 | 21 | #include "defaults.h" |
212380e3 AC |
22 | #include "client.h" |
23 | #include "ircd.h" | |
4562c604 | 24 | #include "match.h" |
77d3d2db | 25 | #include "s_assert.h" |
212380e3 AC |
26 | |
27 | /* | |
28 | * Compare if a given string (name) matches the given | |
29 | * mask (which can contain wild cards: '*' - match any | |
30 | * number of chars, '?' - match any single character. | |
31 | * | |
32 | * return 1, if match | |
33 | * 0, if no match | |
34 | * | |
35 | * Originally by Douglas A Lewis (dalewis@acsu.buffalo.edu) | |
36 | * Rewritten by Timothy Vogelsang (netski), net@astrolink.org | |
37 | */ | |
38 | ||
39 | /** Check a string against a mask. | |
40 | * This test checks using traditional IRC wildcards only: '*' means | |
41 | * match zero or more characters of any type; '?' means match exactly | |
42 | * one character of any type. | |
43 | * | |
44 | * @param[in] mask Wildcard-containing mask. | |
45 | * @param[in] name String to check against \a mask. | |
46 | * @return Zero if \a mask matches \a name, non-zero if no match. | |
47 | */ | |
48 | int match(const char *mask, const char *name) | |
49 | { | |
50 | const char *m = mask, *n = name; | |
51 | const char *m_tmp = mask, *n_tmp = name; | |
52 | int star_p; | |
53 | ||
54 | s_assert(mask != NULL); | |
55 | s_assert(name != NULL); | |
56 | ||
57 | for (;;) | |
58 | { | |
59 | switch (*m) | |
60 | { | |
61 | case '\0': | |
62 | if (!*n) | |
63 | return 1; | |
64 | backtrack: | |
65 | if (m_tmp == mask) | |
66 | return 0; | |
67 | m = m_tmp; | |
68 | n = ++n_tmp; | |
69 | break; | |
70 | case '*': | |
71 | case '?': | |
72 | for (star_p = 0;; m++) | |
73 | { | |
74 | if (*m == '*') | |
75 | star_p = 1; | |
76 | else if (*m == '?') | |
77 | { | |
78 | if (!*n++) | |
79 | goto backtrack; | |
80 | } | |
81 | else | |
82 | break; | |
83 | } | |
84 | if (star_p) | |
85 | { | |
86 | if (!*m) | |
87 | return 1; | |
88 | else | |
89 | { | |
90 | m_tmp = m; | |
7e6b5384 | 91 | for (n_tmp = n; *n && irctolower(*n) != irctolower(*m); n++); |
212380e3 AC |
92 | } |
93 | } | |
94 | /* and fall through */ | |
95 | default: | |
96 | if (!*n) | |
97 | return (*m != '\0' ? 0 : 1); | |
7e6b5384 | 98 | if (irctolower(*m) != irctolower(*n)) |
212380e3 AC |
99 | goto backtrack; |
100 | m++; | |
101 | n++; | |
102 | break; | |
103 | } | |
104 | } | |
105 | } | |
106 | ||
df251055 JT |
107 | /** Check a mask against a mask. |
108 | * This test checks using traditional IRC wildcards only: '*' means | |
109 | * match zero or more characters of any type; '?' means match exactly | |
110 | * one character of any type. | |
111 | * The difference between mask_match() and match() is that in mask_match() | |
112 | * a '?' in mask does not match a '*' in name. | |
113 | * | |
114 | * @param[in] mask Existing wildcard-containing mask. | |
115 | * @param[in] name New wildcard-containing mask. | |
116 | * @return 1 if \a name is equal to or more specific than \a mask, 0 otherwise. | |
117 | */ | |
118 | int mask_match(const char *mask, const char *name) | |
119 | { | |
120 | const char *m = mask, *n = name; | |
121 | const char *m_tmp = mask, *n_tmp = name; | |
122 | int star_p; | |
123 | ||
124 | s_assert(mask != NULL); | |
125 | s_assert(name != NULL); | |
126 | ||
127 | for (;;) | |
128 | { | |
129 | switch (*m) | |
130 | { | |
131 | case '\0': | |
132 | if (!*n) | |
133 | return 1; | |
134 | backtrack: | |
135 | if (m_tmp == mask) | |
136 | return 0; | |
137 | m = m_tmp; | |
138 | n = ++n_tmp; | |
139 | break; | |
140 | case '*': | |
141 | case '?': | |
142 | for (star_p = 0;; m++) | |
143 | { | |
144 | if (*m == '*') | |
145 | star_p = 1; | |
146 | else if (*m == '?') | |
147 | { | |
148 | /* changed for mask_match() */ | |
149 | if (*n == '*' || !*n) | |
150 | goto backtrack; | |
151 | n++; | |
152 | } | |
153 | else | |
154 | break; | |
155 | } | |
156 | if (star_p) | |
157 | { | |
158 | if (!*m) | |
159 | return 1; | |
160 | else | |
161 | { | |
162 | m_tmp = m; | |
7e6b5384 | 163 | for (n_tmp = n; *n && irctolower(*n) != irctolower(*m); n++); |
df251055 JT |
164 | } |
165 | } | |
166 | /* and fall through */ | |
167 | default: | |
168 | if (!*n) | |
169 | return (*m != '\0' ? 0 : 1); | |
7e6b5384 | 170 | if (irctolower(*m) != irctolower(*n)) |
df251055 JT |
171 | goto backtrack; |
172 | m++; | |
173 | n++; | |
174 | break; | |
175 | } | |
176 | } | |
177 | } | |
178 | ||
179 | ||
7eecdd68 JT |
180 | #define MATCH_MAX_CALLS 512 /* ACK! This dies when it's less that this |
181 | and we have long lines to parse */ | |
212380e3 | 182 | /** Check a string against a mask. |
7eecdd68 JT |
183 | * This test checks using extended wildcards: '*' means match zero |
184 | * or more characters of any type; '?' means match exactly one | |
185 | * character of any type; '#' means match exactly one character that | |
186 | * is a number; '@' means match exactly one character that is a | |
187 | * letter; '\s' means match a space. | |
212380e3 | 188 | * |
55abcbb2 | 189 | * This function supports escaping, so that a wildcard may be matched |
212380e3 AC |
190 | * exactly. |
191 | * | |
192 | * @param[in] mask Wildcard-containing mask. | |
193 | * @param[in] name String to check against \a mask. | |
194 | * @return Zero if \a mask matches \a name, non-zero if no match. | |
195 | */ | |
7eecdd68 JT |
196 | int |
197 | match_esc(const char *mask, const char *name) | |
212380e3 | 198 | { |
7eecdd68 JT |
199 | const unsigned char *m = (const unsigned char *)mask; |
200 | const unsigned char *n = (const unsigned char *)name; | |
201 | const unsigned char *ma = (const unsigned char *)mask; | |
202 | const unsigned char *na = (const unsigned char *)name; | |
203 | int wild = 0; | |
204 | int calls = 0; | |
205 | int quote = 0; | |
206 | int match1 = 0; | |
212380e3 AC |
207 | |
208 | s_assert(mask != NULL); | |
209 | s_assert(name != NULL); | |
210 | ||
7eecdd68 JT |
211 | if(!mask || !name) |
212 | return 0; | |
213 | ||
214 | /* if the mask is "*", it matches everything */ | |
215 | if((*m == '*') && (*(m + 1) == '\0')) | |
216 | return 1; | |
217 | ||
218 | while(calls++ < MATCH_MAX_CALLS) | |
212380e3 | 219 | { |
7eecdd68 JT |
220 | if(quote) |
221 | quote++; | |
222 | if(quote == 3) | |
223 | quote = 0; | |
224 | if(*m == '\\' && !quote) | |
212380e3 | 225 | { |
7eecdd68 JT |
226 | m++; |
227 | quote = 1; | |
228 | continue; | |
229 | } | |
230 | if(!quote && *m == '*') | |
231 | { | |
232 | /* | |
233 | * XXX - shouldn't need to spin here, the mask should have been | |
234 | * collapsed before match is called | |
235 | */ | |
236 | while(*m == '*') | |
237 | m++; | |
238 | ||
239 | wild = 1; | |
240 | ma = m; | |
241 | na = n; | |
242 | ||
243 | if(*m == '\\') | |
244 | { | |
245 | m++; | |
246 | /* This means it is an invalid mask -A1kmm. */ | |
247 | if(!*m) | |
248 | return 0; | |
249 | quote++; | |
250 | continue; | |
251 | } | |
252 | } | |
253 | ||
254 | if(!*m) | |
255 | { | |
256 | if(!*n) | |
257 | return 1; | |
258 | if(quote) | |
259 | return 0; | |
5ef68b13 JT |
260 | for(m--; (m > (const unsigned char *)mask) && (*m == '?'); m--) |
261 | ; | |
7eecdd68 JT |
262 | |
263 | if(*m == '*' && (m > (const unsigned char *)mask)) | |
264 | return 1; | |
265 | if(!wild) | |
266 | return 0; | |
267 | m = ma; | |
268 | n = ++na; | |
269 | } | |
270 | else if(!*n) | |
271 | { | |
272 | /* | |
273 | * XXX - shouldn't need to spin here, the mask should have been | |
274 | * collapsed before match is called | |
275 | */ | |
276 | if(quote) | |
277 | return 0; | |
278 | while(*m == '*') | |
279 | m++; | |
280 | return (*m == 0); | |
281 | } | |
282 | ||
283 | if(quote) | |
7e6b5384 | 284 | match1 = *m == 's' ? *n == ' ' : irctolower(*m) == irctolower(*n); |
7eecdd68 JT |
285 | else if(*m == '?') |
286 | match1 = 1; | |
287 | else if(*m == '@') | |
288 | match1 = IsLetter(*n); | |
289 | else if(*m == '#') | |
290 | match1 = IsDigit(*n); | |
291 | else | |
7e6b5384 | 292 | match1 = irctolower(*m) == irctolower(*n); |
7eecdd68 JT |
293 | if(match1) |
294 | { | |
295 | if(*m) | |
296 | m++; | |
297 | if(*n) | |
298 | n++; | |
299 | } | |
300 | else | |
301 | { | |
302 | if(!wild) | |
303 | return 0; | |
304 | m = ma; | |
305 | n = ++na; | |
212380e3 AC |
306 | } |
307 | } | |
7eecdd68 | 308 | return 0; |
212380e3 AC |
309 | } |
310 | ||
4b11f391 | 311 | int comp_with_mask(void *addr, void *dest, unsigned int mask) |
212380e3 AC |
312 | { |
313 | if (memcmp(addr, dest, mask / 8) == 0) | |
314 | { | |
315 | int n = mask / 8; | |
d8f0b5d7 | 316 | unsigned char m = (0xFF << (8 - (mask % 8))); |
4b11f391 | 317 | if (mask % 8 == 0 || (((unsigned char *) addr)[n] & m) == (((unsigned char *) dest)[n] & m)) |
212380e3 AC |
318 | { |
319 | return (1); | |
320 | } | |
321 | } | |
322 | return (0); | |
323 | } | |
324 | ||
4b11f391 | 325 | int comp_with_mask_sock(struct sockaddr *addr, struct sockaddr *dest, unsigned int mask) |
212380e3 AC |
326 | { |
327 | void *iaddr = NULL; | |
328 | void *idest = NULL; | |
329 | ||
330 | if (addr->sa_family == AF_INET) | |
331 | { | |
29c92cf9 JB |
332 | iaddr = &((struct sockaddr_in *)(void *)addr)->sin_addr; |
333 | idest = &((struct sockaddr_in *)(void *)dest)->sin_addr; | |
212380e3 | 334 | } |
212380e3 AC |
335 | else |
336 | { | |
29c92cf9 JB |
337 | iaddr = &((struct sockaddr_in6 *)(void *)addr)->sin6_addr; |
338 | idest = &((struct sockaddr_in6 *)(void *)dest)->sin6_addr; | |
212380e3 AC |
339 | |
340 | } | |
212380e3 AC |
341 | |
342 | return (comp_with_mask(iaddr, idest, mask)); | |
343 | } | |
344 | ||
345 | /* | |
346 | * match_ips() | |
347 | * | |
348 | * Input - cidr ip mask, address | |
349 | */ | |
350 | int match_ips(const char *s1, const char *s2) | |
351 | { | |
e7046ee5 | 352 | struct rb_sockaddr_storage ipaddr, maskaddr; |
212380e3 AC |
353 | char mask[BUFSIZE]; |
354 | char address[HOSTLEN + 1]; | |
355 | char *len; | |
356 | void *ipptr, *maskptr; | |
357 | int cidrlen, aftype; | |
358 | ||
4d5a902f AJ |
359 | rb_strlcpy(mask, s1, sizeof(mask)); |
360 | rb_strlcpy(address, s2, sizeof(address)); | |
212380e3 AC |
361 | |
362 | len = strrchr(mask, '/'); | |
363 | if (len == NULL) | |
364 | return 0; | |
365 | ||
366 | *len++ = '\0'; | |
367 | ||
368 | cidrlen = atoi(len); | |
441da2f2 | 369 | if (cidrlen <= 0) |
212380e3 AC |
370 | return 0; |
371 | ||
212380e3 AC |
372 | if (strchr(mask, ':') && strchr(address, ':')) |
373 | { | |
441da2f2 JT |
374 | if (cidrlen > 128) |
375 | return 0; | |
376 | ||
212380e3 AC |
377 | aftype = AF_INET6; |
378 | ipptr = &((struct sockaddr_in6 *)&ipaddr)->sin6_addr; | |
379 | maskptr = &((struct sockaddr_in6 *)&maskaddr)->sin6_addr; | |
380 | } | |
de293496 | 381 | else if (!strchr(mask, ':') && !strchr(address, ':')) |
212380e3 | 382 | { |
441da2f2 JT |
383 | if (cidrlen > 32) |
384 | return 0; | |
385 | ||
212380e3 AC |
386 | aftype = AF_INET; |
387 | ipptr = &((struct sockaddr_in *)&ipaddr)->sin_addr; | |
388 | maskptr = &((struct sockaddr_in *)&maskaddr)->sin_addr; | |
389 | } | |
390 | else | |
391 | return 0; | |
392 | ||
83e5941c JT |
393 | if (rb_inet_pton(aftype, address, ipptr) <= 0) |
394 | return 0; | |
395 | if (rb_inet_pton(aftype, mask, maskptr) <= 0) | |
396 | return 0; | |
212380e3 AC |
397 | if (comp_with_mask(ipptr, maskptr, cidrlen)) |
398 | return 1; | |
399 | else | |
400 | return 0; | |
401 | } | |
402 | ||
403 | /* match_cidr() | |
404 | * | |
405 | * Input - mask, address | |
406 | * Ouput - 1 = Matched 0 = Did not match | |
407 | */ | |
408 | ||
409 | int match_cidr(const char *s1, const char *s2) | |
410 | { | |
e7046ee5 | 411 | struct rb_sockaddr_storage ipaddr, maskaddr; |
212380e3 AC |
412 | char mask[BUFSIZE]; |
413 | char address[NICKLEN + USERLEN + HOSTLEN + 6]; | |
414 | char *ipmask; | |
415 | char *ip; | |
416 | char *len; | |
417 | void *ipptr, *maskptr; | |
418 | int cidrlen, aftype; | |
419 | ||
4d5a902f AJ |
420 | rb_strlcpy(mask, s1, sizeof(mask)); |
421 | rb_strlcpy(address, s2, sizeof(address)); | |
212380e3 AC |
422 | |
423 | ipmask = strrchr(mask, '@'); | |
424 | if (ipmask == NULL) | |
425 | return 0; | |
426 | ||
427 | *ipmask++ = '\0'; | |
428 | ||
429 | ip = strrchr(address, '@'); | |
430 | if (ip == NULL) | |
431 | return 0; | |
432 | *ip++ = '\0'; | |
433 | ||
434 | ||
435 | len = strrchr(ipmask, '/'); | |
436 | if (len == NULL) | |
437 | return 0; | |
438 | ||
439 | *len++ = '\0'; | |
440 | ||
441 | cidrlen = atoi(len); | |
4dbd5e07 | 442 | if (cidrlen <= 0) |
212380e3 AC |
443 | return 0; |
444 | ||
212380e3 AC |
445 | if (strchr(ip, ':') && strchr(ipmask, ':')) |
446 | { | |
4dbd5e07 JT |
447 | if (cidrlen > 128) |
448 | return 0; | |
449 | ||
212380e3 AC |
450 | aftype = AF_INET6; |
451 | ipptr = &((struct sockaddr_in6 *)&ipaddr)->sin6_addr; | |
452 | maskptr = &((struct sockaddr_in6 *)&maskaddr)->sin6_addr; | |
453 | } | |
de293496 | 454 | else if (!strchr(ip, ':') && !strchr(ipmask, ':')) |
212380e3 | 455 | { |
4dbd5e07 JT |
456 | if (cidrlen > 32) |
457 | return 0; | |
458 | ||
212380e3 AC |
459 | aftype = AF_INET; |
460 | ipptr = &((struct sockaddr_in *)&ipaddr)->sin_addr; | |
461 | maskptr = &((struct sockaddr_in *)&maskaddr)->sin_addr; | |
462 | } | |
463 | else | |
464 | return 0; | |
465 | ||
83e5941c JT |
466 | if (rb_inet_pton(aftype, ip, ipptr) <= 0) |
467 | return 0; | |
468 | if (rb_inet_pton(aftype, ipmask, maskptr) <= 0) | |
469 | return 0; | |
212380e3 AC |
470 | if (comp_with_mask(ipptr, maskptr, cidrlen) && match(mask, address)) |
471 | return 1; | |
472 | else | |
473 | return 0; | |
474 | } | |
475 | ||
476 | /* collapse() | |
477 | * | |
478 | * collapses a string containing multiple *'s. | |
479 | */ | |
480 | char *collapse(char *pattern) | |
481 | { | |
482 | char *p = pattern, *po = pattern; | |
483 | char c; | |
484 | int f = 0; | |
485 | ||
486 | if (p == NULL) | |
487 | return NULL; | |
488 | ||
489 | while ((c = *p++)) | |
490 | { | |
491 | if (c == '*') | |
492 | { | |
493 | if (!(f & 1)) | |
494 | *po++ = '*'; | |
495 | f |= 1; | |
496 | } | |
497 | else | |
498 | { | |
499 | *po++ = c; | |
500 | f &= ~1; | |
501 | } | |
502 | } | |
503 | *po++ = 0; | |
504 | ||
505 | return pattern; | |
506 | } | |
507 | ||
508 | /* collapse_esc() | |
509 | * | |
510 | * The collapse() function with support for escaping characters | |
511 | */ | |
512 | char *collapse_esc(char *pattern) | |
513 | { | |
514 | char *p = pattern, *po = pattern; | |
515 | char c; | |
516 | int f = 0; | |
517 | ||
518 | if (p == NULL) | |
519 | return NULL; | |
520 | ||
521 | while ((c = *p++)) | |
522 | { | |
523 | if (!(f & 2) && c == '*') | |
524 | { | |
525 | if (!(f & 1)) | |
526 | *po++ = '*'; | |
527 | f |= 1; | |
528 | } | |
529 | else if (!(f & 2) && c == '\\') | |
530 | { | |
531 | *po++ = '\\'; | |
532 | f |= 2; | |
533 | } | |
534 | else | |
535 | { | |
536 | *po++ = c; | |
537 | f &= ~3; | |
538 | } | |
539 | } | |
540 | *po++ = 0; | |
541 | return pattern; | |
542 | } | |
543 | ||
544 | /* | |
545 | * irccmp - case insensitive comparison of two 0 terminated strings. | |
546 | * | |
547 | * returns 0, if s1 equal to s2 | |
548 | * <0, if s1 lexicographically less than s2 | |
549 | * >0, if s1 lexicographically greater than s2 | |
550 | */ | |
551 | int irccmp(const char *s1, const char *s2) | |
552 | { | |
553 | const unsigned char *str1 = (const unsigned char *)s1; | |
554 | const unsigned char *str2 = (const unsigned char *)s2; | |
555 | int res; | |
556 | ||
557 | s_assert(s1 != NULL); | |
558 | s_assert(s2 != NULL); | |
559 | ||
7e6b5384 | 560 | while ((res = irctoupper(*str1) - irctoupper(*str2)) == 0) |
212380e3 AC |
561 | { |
562 | if (*str1 == '\0') | |
563 | return 0; | |
564 | str1++; | |
565 | str2++; | |
566 | } | |
567 | return (res); | |
568 | } | |
569 | ||
570 | int ircncmp(const char *s1, const char *s2, int n) | |
571 | { | |
572 | const unsigned char *str1 = (const unsigned char *)s1; | |
573 | const unsigned char *str2 = (const unsigned char *)s2; | |
574 | int res; | |
575 | s_assert(s1 != NULL); | |
576 | s_assert(s2 != NULL); | |
577 | ||
7e6b5384 | 578 | while ((res = irctoupper(*str1) - irctoupper(*str2)) == 0) |
212380e3 AC |
579 | { |
580 | str1++; | |
581 | str2++; | |
582 | n--; | |
583 | if (n == 0 || (*str1 == '\0' && *str2 == '\0')) | |
584 | return 0; | |
585 | } | |
586 | return (res); | |
587 | } | |
588 | ||
a7d4a0ab EK |
589 | void matchset_for_client(struct Client *who, struct matchset *m) |
590 | { | |
591 | unsigned hostn = 0; | |
592 | unsigned ipn = 0; | |
593 | ||
594 | struct sockaddr_in ip4; | |
595 | ||
596 | sprintf(m->host[hostn++], "%s!%s@%s", who->name, who->username, who->host); | |
55ed78da EK |
597 | |
598 | if (!IsIPSpoof(who)) | |
599 | { | |
600 | sprintf(m->ip[ipn++], "%s!%s@%s", who->name, who->username, who->sockhost); | |
601 | } | |
602 | ||
a7d4a0ab EK |
603 | if (who->localClient->mangledhost != NULL) |
604 | { | |
605 | /* if host mangling mode enabled, also check their real host */ | |
606 | if (!strcmp(who->host, who->localClient->mangledhost)) | |
607 | { | |
608 | sprintf(m->host[hostn++], "%s!%s@%s", who->name, who->username, who->orighost); | |
609 | } | |
610 | /* if host mangling mode not enabled and no other spoof, | |
611 | * also check the mangled form of their host */ | |
612 | else if (!IsDynSpoof(who)) | |
613 | { | |
614 | sprintf(m->host[hostn++], "%s!%s@%s", who->name, who->username, who->localClient->mangledhost); | |
615 | } | |
616 | } | |
55ed78da | 617 | if (!IsIPSpoof(who) && GET_SS_FAMILY(&who->localClient->ip) == AF_INET6 && |
a7d4a0ab EK |
618 | rb_ipv4_from_ipv6((const struct sockaddr_in6 *)&who->localClient->ip, &ip4)) |
619 | { | |
620 | int n = sprintf(m->ip[ipn++], "%s!%s@", who->name, who->username); | |
621 | rb_inet_ntop_sock((struct sockaddr *)&ip4, | |
622 | m->ip[ipn] + n, sizeof m->ip[ipn] - n); | |
623 | } | |
624 | ||
625 | for (int i = hostn; i < ARRAY_SIZE(m->host); i++) | |
626 | { | |
627 | m->host[i][0] = '\0'; | |
628 | } | |
629 | for (int i = ipn; i < ARRAY_SIZE(m->ip); i++) | |
630 | { | |
631 | m->ip[i][0] = '\0'; | |
632 | } | |
633 | } | |
634 | ||
635 | bool client_matches_mask(struct Client *who, const char *mask) | |
636 | { | |
637 | static struct matchset ms; | |
638 | matchset_for_client(who, &ms); | |
639 | return matches_mask(&ms, mask); | |
640 | } | |
641 | ||
642 | bool matches_mask(const struct matchset *m, const char *mask) | |
643 | { | |
644 | for (int i = 0; i < ARRAY_SIZE(m->host); i++) | |
645 | { | |
646 | if (m->host[i][0] == '\0') | |
647 | break; | |
648 | if (match(mask, m->host[i])) | |
649 | return true; | |
650 | } | |
651 | for (int i = 0; i < ARRAY_SIZE(m->ip); i++) | |
652 | { | |
653 | if (m->ip[i][0] == '\0') | |
654 | break; | |
655 | if (match(mask, m->ip[i])) | |
656 | return true; | |
657 | if (match_cidr(mask, m->ip[i])) | |
658 | return true; | |
659 | } | |
660 | return false; | |
661 | } | |
662 | ||
7e6b5384 | 663 | const unsigned char irctolower_tab[] = { |
212380e3 AC |
664 | 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, |
665 | 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, | |
666 | 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, | |
667 | 0x1e, 0x1f, | |
668 | ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')', | |
669 | '*', '+', ',', '-', '.', '/', | |
670 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | |
671 | ':', ';', '<', '=', '>', '?', | |
672 | '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', | |
673 | 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', | |
674 | 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', | |
675 | '_', | |
676 | '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', | |
677 | 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', | |
678 | 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', | |
679 | 0x7f, | |
680 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, | |
681 | 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, | |
682 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, | |
683 | 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, | |
684 | 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, | |
685 | 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, | |
686 | 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, | |
687 | 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, | |
688 | 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, | |
689 | 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, | |
690 | 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, | |
691 | 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, | |
692 | 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, | |
693 | 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, | |
694 | 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, | |
695 | 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff | |
696 | }; | |
697 | ||
7e6b5384 | 698 | const unsigned char irctoupper_tab[] = { |
212380e3 AC |
699 | 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, |
700 | 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, | |
701 | 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, | |
702 | 0x1e, 0x1f, | |
703 | ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')', | |
704 | '*', '+', ',', '-', '.', '/', | |
705 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | |
706 | ':', ';', '<', '=', '>', '?', | |
707 | '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', | |
708 | 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', | |
709 | 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', | |
710 | 0x5f, | |
711 | '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', | |
712 | 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', | |
713 | 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', | |
714 | 0x7f, | |
715 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, | |
716 | 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, | |
717 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, | |
718 | 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, | |
719 | 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, | |
720 | 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, | |
721 | 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, | |
722 | 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, | |
723 | 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, | |
724 | 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, | |
725 | 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, | |
726 | 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, | |
727 | 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, | |
728 | 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, | |
729 | 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, | |
730 | 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff | |
731 | }; | |
732 | ||
733 | /* | |
734 | * CharAttrs table | |
735 | * | |
736 | * NOTE: RFC 1459 sez: anything but a ^G, comma, or space is allowed | |
737 | * for channel names | |
738 | */ | |
f3b84221 | 739 | unsigned int CharAttrs[] = { |
212380e3 AC |
740 | /* 0 */ CNTRL_C, |
741 | /* 1 */ CNTRL_C | CHAN_C | NONEOS_C, | |
742 | /* 2 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C, | |
743 | /* 3 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C, | |
744 | /* 4 */ CNTRL_C | CHAN_C | NONEOS_C, | |
745 | /* 5 */ CNTRL_C | CHAN_C | NONEOS_C, | |
746 | /* 6 */ CNTRL_C | CHAN_C | NONEOS_C, | |
747 | /* 7 BEL */ CNTRL_C | NONEOS_C, | |
748 | /* 8 \b */ CNTRL_C | CHAN_C | NONEOS_C, | |
749 | /* 9 \t */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C, | |
750 | /* 10 \n */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C | EOL_C, | |
751 | /* 11 \v */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C, | |
752 | /* 12 \f */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C, | |
753 | /* 13 \r */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C | EOL_C, | |
754 | /* 14 */ CNTRL_C | CHAN_C | NONEOS_C, | |
755 | /* 15 */ CNTRL_C | CHAN_C | NONEOS_C, | |
756 | /* 16 */ CNTRL_C | CHAN_C | NONEOS_C, | |
757 | /* 17 */ CNTRL_C | CHAN_C | NONEOS_C, | |
758 | /* 18 */ CNTRL_C | CHAN_C | NONEOS_C, | |
759 | /* 19 */ CNTRL_C | CHAN_C | NONEOS_C, | |
760 | /* 20 */ CNTRL_C | CHAN_C | NONEOS_C, | |
761 | /* 21 */ CNTRL_C | CHAN_C | NONEOS_C, | |
762 | /* 22 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C, | |
763 | /* 23 */ CNTRL_C | CHAN_C | NONEOS_C, | |
764 | /* 24 */ CNTRL_C | CHAN_C | NONEOS_C, | |
765 | /* 25 */ CNTRL_C | CHAN_C | NONEOS_C, | |
766 | /* 26 */ CNTRL_C | CHAN_C | NONEOS_C, | |
767 | /* 27 */ CNTRL_C | CHAN_C | NONEOS_C, | |
768 | /* 28 */ CNTRL_C | CHAN_C | NONEOS_C, | |
b19d3c51 | 769 | /* 29 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C, |
212380e3 AC |
770 | /* 30 */ CNTRL_C | CHAN_C | NONEOS_C, |
771 | /* 31 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C, | |
772 | /* SP */ PRINT_C | SPACE_C, | |
773 | /* ! */ PRINT_C | KWILD_C | CHAN_C | NONEOS_C, | |
774 | /* " */ PRINT_C | CHAN_C | NONEOS_C, | |
775 | /* # */ PRINT_C | MWILD_C | CHANPFX_C | CHAN_C | NONEOS_C, | |
f2edb2be | 776 | /* $ */ PRINT_C | CHAN_C | NONEOS_C, |
212380e3 AC |
777 | /* % */ PRINT_C | CHAN_C | NONEOS_C, |
778 | /* & */ PRINT_C | CHANPFX_C | CHAN_C | NONEOS_C, | |
779 | /* ' */ PRINT_C | CHAN_C | NONEOS_C, | |
780 | /* ( */ PRINT_C | CHAN_C | NONEOS_C, | |
781 | /* ) */ PRINT_C | CHAN_C | NONEOS_C, | |
e5d9ca18 | 782 | /* * */ PRINT_C | KWILD_C | MWILD_C | CHAN_C | NONEOS_C, |
212380e3 AC |
783 | /* + */ PRINT_C | CHAN_C | NONEOS_C, |
784 | /* , */ PRINT_C | NONEOS_C, | |
785 | /* - */ PRINT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
786 | /* . */ PRINT_C | KWILD_C | CHAN_C | NONEOS_C | USER_C | HOST_C | SERV_C, | |
9a180ae3 | 787 | /* / */ PRINT_C | CHAN_C | NONEOS_C | HOST_C, |
212380e3 AC |
788 | /* 0 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, |
789 | /* 1 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
790 | /* 2 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
791 | /* 3 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
792 | /* 4 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
793 | /* 5 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
794 | /* 6 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
795 | /* 7 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
796 | /* 8 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
797 | /* 9 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
798 | /* : */ PRINT_C | CHAN_C | NONEOS_C | HOST_C, | |
799 | /* ; */ PRINT_C | CHAN_C | NONEOS_C, | |
800 | /* < */ PRINT_C | CHAN_C | NONEOS_C, | |
801 | /* = */ PRINT_C | CHAN_C | NONEOS_C, | |
802 | /* > */ PRINT_C | CHAN_C | NONEOS_C, | |
803 | /* ? */ PRINT_C | KWILD_C | MWILD_C | CHAN_C | NONEOS_C, | |
804 | /* @ */ PRINT_C | KWILD_C | MWILD_C | CHAN_C | NONEOS_C, | |
805 | /* A */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
806 | /* B */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
807 | /* C */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
808 | /* D */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
809 | /* E */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
810 | /* F */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
811 | /* G */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
812 | /* H */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
813 | /* I */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
814 | /* J */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
815 | /* K */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
816 | /* L */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
817 | /* M */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
818 | /* N */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
819 | /* O */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
820 | /* P */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
821 | /* Q */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
822 | /* R */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
823 | /* S */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
824 | /* T */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
825 | /* U */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
826 | /* V */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
827 | /* W */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
828 | /* X */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
829 | /* Y */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
830 | /* Z */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
831 | /* [ */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C, | |
832 | /* \ */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C, | |
833 | /* ] */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C, | |
834 | /* ^ */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C, | |
835 | /* _ */ PRINT_C | NICK_C | CHAN_C | NONEOS_C | USER_C, | |
836 | /* ` */ PRINT_C | NICK_C | CHAN_C | NONEOS_C | USER_C, | |
837 | /* a */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
838 | /* b */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
839 | /* c */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
840 | /* d */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
841 | /* e */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
842 | /* f */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
843 | /* g */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
844 | /* h */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
845 | /* i */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
846 | /* j */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
847 | /* k */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
848 | /* l */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
849 | /* m */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
850 | /* n */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
851 | /* o */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
852 | /* p */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
853 | /* q */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
854 | /* r */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
855 | /* s */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
856 | /* t */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
857 | /* u */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
858 | /* v */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
859 | /* w */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
860 | /* x */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
861 | /* y */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
862 | /* z */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C, | |
863 | /* { */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C, | |
864 | /* | */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C, | |
865 | /* } */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C, | |
866 | /* ~ */ PRINT_C | ALPHA_C | CHAN_C | NONEOS_C | USER_C, | |
867 | /* del */ CHAN_C | NONEOS_C, | |
868 | /* 0x80 */ CHAN_C | NONEOS_C, | |
869 | /* 0x81 */ CHAN_C | NONEOS_C, | |
870 | /* 0x82 */ CHAN_C | NONEOS_C, | |
871 | /* 0x83 */ CHAN_C | NONEOS_C, | |
872 | /* 0x84 */ CHAN_C | NONEOS_C, | |
873 | /* 0x85 */ CHAN_C | NONEOS_C, | |
874 | /* 0x86 */ CHAN_C | NONEOS_C, | |
875 | /* 0x87 */ CHAN_C | NONEOS_C, | |
876 | /* 0x88 */ CHAN_C | NONEOS_C, | |
877 | /* 0x89 */ CHAN_C | NONEOS_C, | |
878 | /* 0x8A */ CHAN_C | NONEOS_C, | |
879 | /* 0x8B */ CHAN_C | NONEOS_C, | |
880 | /* 0x8C */ CHAN_C | NONEOS_C, | |
881 | /* 0x8D */ CHAN_C | NONEOS_C, | |
882 | /* 0x8E */ CHAN_C | NONEOS_C, | |
883 | /* 0x8F */ CHAN_C | NONEOS_C, | |
884 | /* 0x90 */ CHAN_C | NONEOS_C, | |
885 | /* 0x91 */ CHAN_C | NONEOS_C, | |
886 | /* 0x92 */ CHAN_C | NONEOS_C, | |
887 | /* 0x93 */ CHAN_C | NONEOS_C, | |
888 | /* 0x94 */ CHAN_C | NONEOS_C, | |
889 | /* 0x95 */ CHAN_C | NONEOS_C, | |
890 | /* 0x96 */ CHAN_C | NONEOS_C, | |
891 | /* 0x97 */ CHAN_C | NONEOS_C, | |
892 | /* 0x98 */ CHAN_C | NONEOS_C, | |
893 | /* 0x99 */ CHAN_C | NONEOS_C, | |
894 | /* 0x9A */ CHAN_C | NONEOS_C, | |
895 | /* 0x9B */ CHAN_C | NONEOS_C, | |
896 | /* 0x9C */ CHAN_C | NONEOS_C, | |
897 | /* 0x9D */ CHAN_C | NONEOS_C, | |
898 | /* 0x9E */ CHAN_C | NONEOS_C, | |
899 | /* 0x9F */ CHAN_C | NONEOS_C, | |
900 | /* 0xA0 */ CHAN_C | FCHAN_C | NONEOS_C, | |
901 | /* 0xA1 */ CHAN_C | NONEOS_C, | |
902 | /* 0xA2 */ CHAN_C | NONEOS_C, | |
903 | /* 0xA3 */ CHAN_C | NONEOS_C, | |
904 | /* 0xA4 */ CHAN_C | NONEOS_C, | |
905 | /* 0xA5 */ CHAN_C | NONEOS_C, | |
906 | /* 0xA6 */ CHAN_C | NONEOS_C, | |
907 | /* 0xA7 */ CHAN_C | NONEOS_C, | |
908 | /* 0xA8 */ CHAN_C | NONEOS_C, | |
909 | /* 0xA9 */ CHAN_C | NONEOS_C, | |
910 | /* 0xAA */ CHAN_C | NONEOS_C, | |
911 | /* 0xAB */ CHAN_C | NONEOS_C, | |
912 | /* 0xAC */ CHAN_C | NONEOS_C, | |
913 | /* 0xAD */ CHAN_C | NONEOS_C, | |
914 | /* 0xAE */ CHAN_C | NONEOS_C, | |
915 | /* 0xAF */ CHAN_C | NONEOS_C, | |
916 | /* 0xB0 */ CHAN_C | NONEOS_C, | |
917 | /* 0xB1 */ CHAN_C | NONEOS_C, | |
918 | /* 0xB2 */ CHAN_C | NONEOS_C, | |
919 | /* 0xB3 */ CHAN_C | NONEOS_C, | |
920 | /* 0xB4 */ CHAN_C | NONEOS_C, | |
921 | /* 0xB5 */ CHAN_C | NONEOS_C, | |
922 | /* 0xB6 */ CHAN_C | NONEOS_C, | |
923 | /* 0xB7 */ CHAN_C | NONEOS_C, | |
924 | /* 0xB8 */ CHAN_C | NONEOS_C, | |
925 | /* 0xB9 */ CHAN_C | NONEOS_C, | |
926 | /* 0xBA */ CHAN_C | NONEOS_C, | |
927 | /* 0xBB */ CHAN_C | NONEOS_C, | |
928 | /* 0xBC */ CHAN_C | NONEOS_C, | |
929 | /* 0xBD */ CHAN_C | NONEOS_C, | |
930 | /* 0xBE */ CHAN_C | NONEOS_C, | |
931 | /* 0xBF */ CHAN_C | NONEOS_C, | |
932 | /* 0xC0 */ CHAN_C | NONEOS_C, | |
933 | /* 0xC1 */ CHAN_C | NONEOS_C, | |
934 | /* 0xC2 */ CHAN_C | NONEOS_C, | |
935 | /* 0xC3 */ CHAN_C | NONEOS_C, | |
936 | /* 0xC4 */ CHAN_C | NONEOS_C, | |
937 | /* 0xC5 */ CHAN_C | NONEOS_C, | |
938 | /* 0xC6 */ CHAN_C | NONEOS_C, | |
939 | /* 0xC7 */ CHAN_C | NONEOS_C, | |
940 | /* 0xC8 */ CHAN_C | NONEOS_C, | |
941 | /* 0xC9 */ CHAN_C | NONEOS_C, | |
942 | /* 0xCA */ CHAN_C | NONEOS_C, | |
943 | /* 0xCB */ CHAN_C | NONEOS_C, | |
944 | /* 0xCC */ CHAN_C | NONEOS_C, | |
945 | /* 0xCD */ CHAN_C | NONEOS_C, | |
946 | /* 0xCE */ CHAN_C | NONEOS_C, | |
947 | /* 0xCF */ CHAN_C | NONEOS_C, | |
948 | /* 0xD0 */ CHAN_C | NONEOS_C, | |
949 | /* 0xD1 */ CHAN_C | NONEOS_C, | |
950 | /* 0xD2 */ CHAN_C | NONEOS_C, | |
951 | /* 0xD3 */ CHAN_C | NONEOS_C, | |
952 | /* 0xD4 */ CHAN_C | NONEOS_C, | |
953 | /* 0xD5 */ CHAN_C | NONEOS_C, | |
954 | /* 0xD6 */ CHAN_C | NONEOS_C, | |
955 | /* 0xD7 */ CHAN_C | NONEOS_C, | |
956 | /* 0xD8 */ CHAN_C | NONEOS_C, | |
957 | /* 0xD9 */ CHAN_C | NONEOS_C, | |
958 | /* 0xDA */ CHAN_C | NONEOS_C, | |
959 | /* 0xDB */ CHAN_C | NONEOS_C, | |
960 | /* 0xDC */ CHAN_C | NONEOS_C, | |
961 | /* 0xDD */ CHAN_C | NONEOS_C, | |
962 | /* 0xDE */ CHAN_C | NONEOS_C, | |
963 | /* 0xDF */ CHAN_C | NONEOS_C, | |
964 | /* 0xE0 */ CHAN_C | NONEOS_C, | |
965 | /* 0xE1 */ CHAN_C | NONEOS_C, | |
966 | /* 0xE2 */ CHAN_C | NONEOS_C, | |
967 | /* 0xE3 */ CHAN_C | NONEOS_C, | |
968 | /* 0xE4 */ CHAN_C | NONEOS_C, | |
969 | /* 0xE5 */ CHAN_C | NONEOS_C, | |
970 | /* 0xE6 */ CHAN_C | NONEOS_C, | |
971 | /* 0xE7 */ CHAN_C | NONEOS_C, | |
972 | /* 0xE8 */ CHAN_C | NONEOS_C, | |
973 | /* 0xE9 */ CHAN_C | NONEOS_C, | |
974 | /* 0xEA */ CHAN_C | NONEOS_C, | |
975 | /* 0xEB */ CHAN_C | NONEOS_C, | |
976 | /* 0xEC */ CHAN_C | NONEOS_C, | |
977 | /* 0xED */ CHAN_C | NONEOS_C, | |
978 | /* 0xEE */ CHAN_C | NONEOS_C, | |
979 | /* 0xEF */ CHAN_C | NONEOS_C, | |
980 | /* 0xF0 */ CHAN_C | NONEOS_C, | |
981 | /* 0xF1 */ CHAN_C | NONEOS_C, | |
982 | /* 0xF2 */ CHAN_C | NONEOS_C, | |
983 | /* 0xF3 */ CHAN_C | NONEOS_C, | |
984 | /* 0xF4 */ CHAN_C | NONEOS_C, | |
985 | /* 0xF5 */ CHAN_C | NONEOS_C, | |
986 | /* 0xF6 */ CHAN_C | NONEOS_C, | |
987 | /* 0xF7 */ CHAN_C | NONEOS_C, | |
988 | /* 0xF8 */ CHAN_C | NONEOS_C, | |
989 | /* 0xF9 */ CHAN_C | NONEOS_C, | |
990 | /* 0xFA */ CHAN_C | NONEOS_C, | |
991 | /* 0xFB */ CHAN_C | NONEOS_C, | |
992 | /* 0xFC */ CHAN_C | NONEOS_C, | |
993 | /* 0xFD */ CHAN_C | NONEOS_C, | |
994 | /* 0xFE */ CHAN_C | NONEOS_C, | |
995 | /* 0xFF */ CHAN_C | NONEOS_C | |
996 | }; |