Move check_if_ipmask() from support.* to match.*.
[ircu2.10.12-pk.git] / ircd / match.c
1 /*
2  * IRC - Internet Relay Chat, common/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  *
19  * $Id$
20  */
21 #include "config.h"
22
23 #include "match.h"
24 #include "ircd_chattr.h"
25 #include "ircd_string.h"
26 #include "ircd_snprintf.h"
27
28 /*
29  * mmatch()
30  *
31  * Written by Run (carlo@runaway.xs4all.nl), 25-10-96
32  *
33  *
34  * From: Carlo Wood <carlo@runaway.xs4all.nl>
35  * Message-Id: <199609021026.MAA02393@runaway.xs4all.nl>
36  * Subject: [C-Com] Analysis for `mmatch' (was: gline4 problem)
37  * To: coder-com@mail.undernet.org (coder committee)
38  * Date: Mon, 2 Sep 1996 12:26:01 +0200 (MET DST)
39  *
40  * We need a new function `mmatch(const char *old_mask, const char *new_mask)'
41  * which returns `true' likewise the current `match' (start with copying it),
42  * but which treats '*' and '?' in `new_mask' differently (not "\*" and "\?" !)
43  * as follows:  a '*' in `new_mask' does not match a '?' in `old_mask' and
44  * a '?' in `new_mask' does not match a '\?' in `old_mask'.
45  * And ofcourse... a '*' in `new_mask' does not match a '\*' in `old_mask'...
46  * And last but not least, '\?' and '\*' in `new_mask' now become one character.
47  */
48
49 int mmatch(const char *old_mask, const char *new_mask)
50 {
51   const char *m = old_mask;
52   const char *n = new_mask;
53   const char *ma = m;
54   const char *na = n;
55   int wild = 0;
56   int mq = 0, nq = 0;
57
58   while (1)
59   {
60     if (*m == '*')
61     {
62       while (*m == '*')
63         m++;
64       wild = 1;
65       ma = m;
66       na = n;
67     }
68
69     if (!*m)
70     {
71       if (!*n)
72         return 0;
73       for (m--; (m > old_mask) && (*m == '?'); m--)
74         ;
75       if ((*m == '*') && (m > old_mask) && (m[-1] != '\\'))
76         return 0;
77       if (!wild)
78         return 1;
79       m = ma;
80
81       /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
82       if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
83         ++na;
84
85       n = ++na;
86     }
87     else if (!*n)
88     {
89       while (*m == '*')
90         m++;
91       return (*m != 0);
92     }
93     if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
94     {
95       m++;
96       mq = 1;
97     }
98     else
99       mq = 0;
100
101     /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
102     if ((*n == '\\') && ((n[1] == '*') || (n[1] == '?')))
103     {
104       n++;
105       nq = 1;
106     }
107     else
108       nq = 0;
109
110 /*
111  * This `if' has been changed compared to match() to do the following:
112  * Match when:
113  *   old (m)         new (n)         boolean expression
114  *    *               any             (*m == '*' && !mq) ||
115  *    ?               any except '*'  (*m == '?' && !mq && (*n != '*' || nq)) ||
116  * any except * or ?  same as m       (!((*m == '*' || *m == '?') && !mq) &&
117  *                                      ToLower(*m) == ToLower(*n) &&
118  *                                        !((mq && !nq) || (!mq && nq)))
119  *
120  * Here `any' also includes \* and \? !
121  *
122  * After reworking the boolean expressions, we get:
123  * (Optimized to use boolean shortcircuits, with most frequently occuring
124  *  cases upfront (which took 2 hours!)).
125  */
126     if ((*m == '*' && !mq) ||
127         ((!mq || nq) && ToLower(*m) == ToLower(*n)) ||
128         (*m == '?' && !mq && (*n != '*' || nq)))
129     {
130       if (*m)
131         m++;
132       if (*n)
133         n++;
134     }
135     else
136     {
137       if (!wild)
138         return 1;
139       m = ma;
140
141       /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
142       if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
143         ++na;
144
145       n = ++na;
146     }
147   }
148 }
149
150 /*
151  * Compare if a given string (name) matches the given
152  * mask (which can contain wild cards: '*' - match any
153  * number of chars, '?' - match any single character.
154  *
155  * return  0, if match
156  *         1, if no match
157  *
158  *  Originally by Douglas A Lewis (dalewis@acsu.buffalo.edu)
159  *  Rewritten by Timothy Vogelsang (netski), net@astrolink.org
160  */
161
162 int match(const char *mask, const char *name)
163 {
164   const char *m = mask, *n = name;
165   const char *m_tmp = mask, *n_tmp = name;
166   int wild = 0;
167
168   for (;;)
169   {
170     if (*m == '*') {
171       while (*m == '*')  /* clean up any additional wildcards */
172         m++;
173
174       m_tmp = m;
175       n_tmp = n;
176       wild = 1;
177     }
178     if (*m == '\\')  /* next wildcard is disregarded */
179       m++;
180
181     if (!*m) {
182       if (!*n)
183         return 0;  /* match */
184
185       for (m--; (m > mask) && (*m == '?'); m--);
186         ;
187
188       if (*m == '*' && (m > mask))
189         return 0;  /* match */
190
191       if (!wild)
192         return 1;
193
194       m = m_tmp;
195       n = ++n_tmp;
196     }
197     else if (!*n) {
198       while (*m == '*')  /* clean up any additional wildcards */
199         m++;
200
201       return (*m != 0);
202     }
203     if (ToLower(*m) != ToLower(*n) && *m != '?') {
204       if (!wild)
205         return 1;  /* failure! */
206
207       m = m_tmp;
208       n = ++n_tmp;
209     }
210     else {
211       if (*m)
212         m++;
213       if (*n)
214         n++;
215     }
216   }
217
218   return 1;  /* no match! */
219 }
220
221 /*
222  * collapse()
223  * Collapse a pattern string into minimal components.
224  * This particular version is "in place", so that it changes the pattern
225  * which is to be reduced to a "minimal" size.
226  *
227  * (C) Carlo Wood - 6 Oct 1998
228  * Speedup rewrite by Andrea Cocito, December 1998.
229  * Note that this new optimized alghoritm can *only* work in place.
230  */
231
232 char *collapse(char *mask)
233 {
234   int star = 0;
235   char *m = mask;
236   char *b;
237
238   if (m)
239   {
240     do
241     {
242       if ((*m == '*') && ((m[1] == '*') || (m[1] == '?')))
243       {
244         b = m;
245         do
246         {
247           if (*m == '*')
248             star = 1;
249           else
250           {
251             if (star && (*m != '?'))
252             {
253               *b++ = '*';
254               star = 0;
255             };
256             *b++ = *m;
257             if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
258               *b++ = *++m;
259           };
260         }
261         while (*m++);
262         break;
263       }
264       else
265       {
266         if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
267           m++;
268       };
269     }
270     while (*m++);
271   };
272   return mask;
273 }
274
275 /*
276  ***************** Nemesi's matchcomp() / matchexec() **************
277  */
278
279 /* These functions allow the use of "compiled" masks, you compile a mask
280  * by means of matchcomp() that gets the plain text mask as input and writes
281  * its result in the memory locations addressed by the 3 parameters:
282  * - *cmask will contain the text of the compiled mask
283  * - *minlen will contain the lenght of the shortest string that can match 
284  *   the mask
285  * - *charset will contain the minimal set of chars needed to match the mask
286  * You can pass NULL as *charset and it will be simply not returned, but you
287  * MUST pass valid pointers for *minlen and *cmask (wich must be big enough 
288  * to contain the compiled mask text that is in the worst case as long as the 
289  * text of the mask itself in plaintext format) and the return value of 
290  * matchcomp() will be the number of chars actually written there (excluded 
291  * the trailing zero). cmask can be == mask, matchcomp() can work in place.
292  * The {cmask, minlen} couple of values make the real compiled mask and
293  * need to be passed to the functions that use the compiled mask, if you pass
294  * the wrong minlen or something wrong in cmask to one of these expect a
295  * coredump. This means that when you record a compiled mask you must store
296  * *both* these values.
297  * Once compiled the mask can be used to match a string by means of 
298  * matchexec(), it can be printed back to human-readable format by means
299  * of sprintmatch() or it can be compared to another compiled mask by means
300  * of mmexec() that will tell if it completely overrides that mask (a lot like
301  * what mmatch() does for plain text masks).
302  * You can gain a lot of speed in many situations avoiding to matchexec() when:
303  * - The maximum lenght of the field you are about to match() the mask to is
304  *   shorter than minlen, in example when matching abc*def*ghil with a nick:
305  *   It just cannot match since a nick is at most 9 chars long and the mask
306  *   needs at least 10 chars (10 will be the value returned in minlen).
307  * - The charset allowed for the field you are about to match to doesn't
308  *   "contain" the charset returned by matchcomp(), in example when you
309  *   have *.* as mask it makes no sense to try to match it against a nick
310  *   because, again, a nick can't contain a '.', you can check this with
311  *   a simple (charset & NTL_IRCNK) in this case.
312  * - As a special case, since compiled masks are forced to lowercase,
313  *   it would make no sense to use the NTL_LOWER and NTL_UPPER on a compiled
314  *   mask, thus they are reused as follows: if the NTL_LOWER bit of charset
315  *   is set it means that the mask contains only non-wilds chars (i.e. you can
316  *   use strCasecmp() to match it or a direct hash lookup), if the NTL_UPPER
317  *   bit is set it means that it contains only wild chars (and you can
318  *   match it with strlen(field)>=minlen).
319  * Do these optimizations ONLY when the data you are about to pass to
320  * matchexec() are *known* to be invalid in advance, using strChattr() 
321  * or strlen() on the text would be slower than calling matchexec() directly
322  * and let it fail.
323  * Internally a compiled mask contain in the *cmask area the text of
324  * the plain text form of the mask itself with applied the following hacks:
325  * - All characters are forced to lowercase (so that uppercase letters and
326  *   specifically the symbols 'A' and 'Z' are reserved for special use)
327  * - All non-escaped stars '*' are replaced by the letter 'Z'
328  * - All non-escaped question marks '?' are replaced by the letter 'A' 
329  * - All escape characters are removed, the wilds escaped by them are
330  *   then passed by without the escape since they don't collide anymore
331  *   with the real wilds (encoded as A/Z) 
332  * - Finally the part of the mask that follows the last asterisk is
333  *   reversed (byte order mirroring) and moved right after the first
334  *   asterisk.
335  * After all this a mask like:   Head*CHUNK1*chu\*nK2*ch??k3*TaIl 
336  *               .... becomes:   headZliatZchunk1Zchu*nk2ZchAAk3
337  * This can still be printed on a console, more or less understood by an
338  * human and handled with the usual str*() library functions.
339  * When you store somewhere the compiled mask you can avoid storing the
340  * textform of it since it can be "decompiled" by means of sprintmatch(),
341  * but at that time the following things are changed in the mask:
342  * - All chars have been forced to lowercase.
343  * - The mask is collapsed.
344  * The balance point of using compiled masks in terms of CPU is when you expect
345  * to use matchexec() instead of match() at least 20 times on the same mask
346  * or when you expect to use mmexec() instead of mmatch() 3 times.
347  */
348
349  /* 
350     * matchcomp()
351     *
352     * Compiles a mask into a form suitable for using in matchexec().
353   */
354
355 int matchcomp(char *cmask, int *minlen, int *charset, const char *mask)
356 {
357   const char *m = mask;
358   char *b = cmask;
359   char *fs = 0;
360   char *ls = 0;
361   char *x1, *x2;
362   int l1, l2, lmin, loop, sign;
363   int star = 0;
364   int cnt = 0;
365   char ch;
366   int chset = ~0;
367   int chset2 = (NTL_LOWER | NTL_UPPER);
368
369   if (m)
370     while ((ch = *m++))
371       switch (ch)
372       {
373         case '*':
374           star = 1;
375           break;
376         case '?':
377           cnt++;
378           *b++ = 'A';
379           chset2 &= ~NTL_LOWER;
380           break;
381         case '\\':
382           if ((*m == '?') || (*m == '*'))
383             ch = *m++;
384         default:
385           if (star)
386           {
387             ls = b;
388             fs = fs ? fs : b;
389             *b++ = 'Z';
390             chset2 &= ~NTL_LOWER;
391             star = 0;
392           };
393           cnt++;
394           *b = ToLower(ch);
395           chset &= IRCD_CharAttrTab[*b++ - CHAR_MIN];
396           chset2 &= ~NTL_UPPER;
397       };
398
399   if (charset)
400     *charset = (chset | chset2);
401
402   if (star)
403   {
404     ls = b;
405     fs = (fs ? fs : b);
406     *b++ = 'Z';
407   };
408
409   if (ls)
410   {
411     for (x1 = ls + 1, x2 = (b - 1); x1 < x2; x1++, x2--)
412     {
413       ch = *x1;
414       *x1 = *x2;
415       *x2 = ch;
416     };
417     l1 = (ls - fs);
418     l2 = (b - ls);
419     x1 = fs;
420     while ((lmin = (l1 < l2) ? l1 : l2))
421     {
422       x2 = x1 + l1;
423       for (loop = 0; loop < lmin; loop++)
424       {
425         ch = x1[loop];
426         x1[loop] = x2[loop];
427         x2[loop] = ch;
428       };
429       x1 += lmin;
430       sign = l1 - l2;
431       l1 -= (sign < 0) ? 0 : lmin;
432       l2 -= (sign > 0) ? 0 : lmin;
433     };
434   };
435
436   *b = '\0';
437   *minlen = cnt;
438   return (b - cmask);
439
440 }
441
442 /*
443  * matchexec()
444  *
445  * Executes a match with a mask previosuly compiled with matchcomp()
446  * Note 1: If the mask isn't correctly produced by matchcomp() I will core
447  * Note 2: 'min' MUST be the value returned by matchcomp on that mask,
448  *         or.... I will core even faster :-)
449  * Note 3: This piece of code is not intended to be nice but efficient.
450  */
451
452 int matchexec(const char *string, const char *cmask, int minlen)
453 {
454   const char *s = string - 1;
455   const char *b = cmask - 1;
456   int trash;
457   const char *bb, *bs;
458   char ch;
459
460 tryhead:
461   while ((ToLower(*++s) == *++b) && *s);
462   if (!*s)
463     return ((*b != '\0') && ((*b++ != 'Z') || (*b != '\0')));
464   if (*b != 'Z')
465   {
466     if (*b == 'A')
467       goto tryhead;
468     return 1;
469   };
470
471   bs = s;
472   while (*++s);
473
474   if ((trash = (s - string - minlen)) < 0)
475     return 2;
476
477 trytail:
478   while ((ToLower(*--s) == *++b) && *b && (ToLower(*--s) == *++b) && *b
479       && (ToLower(*--s) == *++b) && *b && (ToLower(*--s) == *++b) && *b);
480   if (*b != 'Z')
481   {
482     if (*b == 'A')
483       goto trytail;
484     return (*b != '\0');
485   };
486
487   s = --bs;
488   bb = b;
489
490   while ((ch = *++b))
491   {
492     while ((ToLower(*++s) != ch))
493       if (--trash < 0)
494         return 4;
495     bs = s;
496
497 trychunk:
498     while ((ToLower(*++s) == *++b) && *b);
499     if (!*b)
500       return 0;
501     if (*b == 'Z')
502     {
503       bs = --s;
504       bb = b;
505       continue;
506     };
507     if (*b == 'A')
508       goto trychunk;
509
510     b = bb;
511     s = bs;
512     if (--trash < 0)
513       return 5;
514   };
515
516   return 0;
517 }
518
519 /*
520  * matchdecomp()
521  * Prints the human readable version of *cmask into *mask, (decompiles
522  * cmask).
523  * The area pointed by *mask MUST be big enough (the mask might be up to
524  * twice the size of its compiled form if it's made all of \? or \*, and
525  * this function can NOT work in place since it might enflate the mask)
526  * The printed mask is not identical to the one that was compiled to cmask,
527  * infact it is 1) forced to all lowercase, 2) collapsed, both things
528  * are supposed to NOT change it's meaning.
529  * It returns the number of chars actually written to *mask;
530  */
531
532 int matchdecomp(char *mask, const char *cmask)
533 {
534   char *rtb = mask;
535   const char *rcm = cmask;
536   const char *begtail, *endtail;
537
538   if (rtb ==0)
539     return (-1);
540
541   if (rcm == 0)
542     return (-2);
543
544   for (; (*rcm != 'Z'); rcm++, rtb++)
545   {
546     if ((*rcm == '?') || (*rcm == '*'))
547       *rtb++ = '\\';
548     if (!((*rtb = ((*rcm == 'A') ? '?' : *rcm))))
549       return (rtb - mask);
550   };
551
552   begtail = rcm++;
553   *rtb++ = '*';
554
555   while (*rcm && (*rcm != 'Z'))
556     rcm++;
557
558   endtail = rcm;
559
560   if (*rcm)
561   {
562     while (*++rcm)
563       switch (*rcm)
564       {
565         case 'A':
566           *rtb++ = '?';
567           break;
568         case 'Z':
569           *rtb++ = '*';
570           break;
571         case '*':
572         case '?':
573           *rtb++ = '\\';
574         default:
575           *rtb++ = *rcm;
576       };
577     *rtb++ = '*';
578   };
579
580   for (rcm = endtail; (--rcm) > begtail; *rtb++ = ((*rcm == 'A') ? '?' : *rcm))
581     if ((*rcm == '?') || (*rcm == '*'))
582       *rtb++ = '\\';
583
584   *rtb = '\0';
585   return (rtb - mask);
586 }
587
588 /*
589  * mmexec()
590  * Checks if a wider compiled mask (wcm/wminlen) completely overrides
591  * a more restrict one (rcm/rminlen), basically what mmatch() does for
592  * non-compiled masks, returns 0 if the override is true (like mmatch()).
593  * "the wider overrides the restrict" means that any string that matches
594  * the restrict one _will_ also match the wider one, always. 
595  * In this we behave differently from mmatch() because in example we return 
596  * true for " a?*cd overrides a*bcd " for wich the override happens for how 
597  * we literally defined it, here mmatch() would have returned false.
598  * The original concepts and the base alghoritm are copied from mmatch() 
599  * written by Run (Carlo Wood), this function is written by
600  * Nemesi (Andrea Cocito)
601  */
602
603 int mmexec(const char *wcm, int wminlen, const char *rcm, int rminlen)
604 {
605   const char *w, *r, *br, *bw, *rx, *rz;
606   int eat, trash;
607
608   /* First of all rm must have enough non-stars to 'contain' wm */
609   if ((trash = rminlen - wminlen) < 0)
610     return 1;
611   w = wcm;
612   r = rcm;
613   eat = 0;
614
615   /* Let's start the game, remember that '*' is mapped to 'Z', '?'
616      is mapped to 'A' and that head?*??*?chunk*???*tail becomes
617      headAAAAZliatAAAZchunk for compiled masks */
618
619   /* Match the head of wm with the head of rm */
620   for (; (*r) && (*r != 'Z') && ((*w == *r) || (*w == 'A')); r++, w++);
621   if (*r == 'Z')
622     while (*w == 'A')           /* Eat extra '?' before '*' in wm if got '*' in rm */
623       w++, eat++;
624   if (*w != 'Z')                /* head1<any>.. can't match head2<any>.. */
625     return ((*w) || (*r)) ? 1 : 0;      /* and head<nul> matches only head<nul> */
626   if (!*++w)
627     return 0;                   /* headZ<nul> matches head<anything>    */
628
629   /* Does rm have any stars in it ? let's check */
630   for (rx = r; *r && (*r != 'Z'); r++);
631   if (!*r)
632   {
633     /* rm has no stars and thus isn't a mask but it's just a flat
634        string: special handling occurs here, note that eat must be 0 here */
635
636     /* match the tail */
637     if (*w != 'Z')
638     {
639       for (; r--, (*w) && ((*w == *r) || (*w == 'A')); w++);
640       if (*w != 'Z')            /* headZliat1<any> fails on head<any>2tail  */
641         return (*w) ? 1 : 0;    /* but headZliat<nul> matches head<any>tail */
642     }
643
644     /* match the chunks */
645     while (1)
646     {                           /* This loop can't break but only return   */
647
648       for (bw = w++; (*w != *rx); rx++) /* Seek the 1st char of the chunk */
649         if (--trash < 0)        /* See if we can trash one more char of rm */
650           return 1;             /* If not we can only fail of course       */
651       for (r = ++rx, w++; (*w) && ((*w == *r) || (*w == 'A')); r++, w++);
652       if (!*w)                  /* Did last loop match the rest of chunk ? */
653         return 0;               /* ... Yes, end of wm, matched !           */
654       if (*w != 'Z')
655       {                         /* ... No, hitted non-star                 */
656         w = bw;                 /* Rollback at beginning of chunk          */
657         if (--trash < 0)        /* Trashed the char where this try started */
658           return 1;             /* if we can't trash more chars fail       */
659       }
660       else
661       {
662         rx = r;                 /* Successfully matched a chunk, move rx   */
663       }                 /* and go on with the next one             */
664     }
665   }
666
667   /* rm has at least one '*' and thus is a 'real' mask */
668   rz = r++;                     /* rx = unused of head, rz = beg-tail */
669
670   /* Match the tail of wm (if any) against the tail of rm */
671   if (*w != 'Z')
672   {
673     for (; (*w) && (*r != 'Z') && ((*w == *r) || (*w == 'A')); w++, r++);
674     if (*r == 'Z')              /* extra '?' before tail are fluff, just flush 'em */
675       while (*w == 'A')
676         w++;
677     if (*w != 'Z')              /* We aren't matching a chunk, can't rollback      */
678       return (*w) ? 1 : 0;
679   }
680
681   /* Match the chunks of wm against what remains of the head of rm */
682   while (1)
683   {
684     bw = w;
685     for (bw++; (rx < rz) && (*bw != *rx); rx++) /* Seek the first           */
686       if (--trash < 0)          /* waste some trash reserve */
687         return 1;
688     if (!(rx < rz))             /* head finished            */
689       break;
690     for (bw++, (br = ++rx);
691         (br < rz) && (*bw) && ((*bw == *br) || (*bw == 'A')); br++, bw++);
692     if (!(br < rz))             /* Note that we didn't use any 'eat' char yet, if  */
693       while (*bw == 'A')        /* there were eat-en chars the head would be over  */
694         bw++, eat++;            /* Happens only at end of head, and eat is still 0 */
695     if (!*bw)
696       return 0;
697     if (*bw != 'Z')
698     {
699       eat = 0;
700       if (!(br < rz))
701       {                         /* If we failed because we got the end of head */
702         trash -= (br - rx);     /* it makes no sense to rollback, just trash   */
703         if (--trash < 0)        /* all the rest of the head wich isn't long    */
704           return 1;             /* enough for this chunk and go out of this    */
705         break;                  /* loop, then we try with the chunks of rm     */
706       };
707       if (--trash < 0)
708         return 1;
709     }
710     else
711     {
712       w = bw;
713       rx = br;
714     }
715   }
716
717   /* Match the unused chunks of wm against the chunks of rm */
718   rx = r;
719   for (; *r && (*r != 'Z'); r++);
720   rz = r;
721   if (*r++)
722   {
723     while (*r)
724     {
725       bw = w;
726       while (eat && *r)         /* the '?' we had eated make us skip as many chars */
727         if (*r++ != 'Z')        /* here, but can't skip stars or trailing zero     */
728           eat--;
729       for (bw++; (*r) && (*bw != *r); r++)
730         if ((*r != 'Z') && (--trash < 0))
731           return 1;
732       if (!*r)
733         break;
734       for ((br = ++r), bw++;
735           (*br) && (*br != 'Z') && ((*bw == *br) || (*bw == 'A')); br++, bw++);
736       if (*br == 'Z')
737         while (*bw == 'A')
738           bw++, eat++;
739       if (!*bw)
740         return 0;
741       if (*bw != 'Z')
742       {
743         eat = 0;
744         if ((!*br) || (*r == 'Z'))
745         {                       /* If we hit the end of rm or a star in it */
746           trash -= (br - r);    /* makes no sense to rollback within this  */
747           if (trash < 0)        /* same chunk of br, skip it all and then  */
748             return 1;           /* either rollback or break this loop if   */
749           if (!*br)             /* it was the end of rm                    */
750             break;
751           r = br;
752         }
753         if (--trash < 0)
754           return 1;
755       }
756       else
757       {
758         r = br;
759         w = bw;
760       }
761     }
762   }
763
764   /* match the remaining chunks of wm against what remains of the tail of rm */
765   r = rz - eat - 1;             /* can't have <nul> or 'Z'within the tail, so just move r */
766   while (r >= rx)
767   {
768     bw = w;
769     for (bw++; (*bw != *r); r--)
770       if (--trash < 0)
771         return 1;
772     if (!(r >= rx))
773       return 1;
774     for ((br = --r), bw++;
775         (*bw) && (br >= rx) && ((*bw == *br) || (*bw == 'A')); br--, bw++);
776     if (!*bw)
777       return 0;
778     if (!(br >= rx))
779       return 1;
780     if (*bw != 'Z')
781     {
782       if (--trash < 0)
783         return 1;
784     }
785     else
786     {
787       r = br;
788       w = bw;
789     }
790   }
791   return 1;                     /* Auch... something left out ? Fail */
792 }
793
794 #include <stdio.h>
795 #include <stdlib.h>
796 #include <string.h>
797 #include <sys/socket.h>
798 #include <netinet/in.h>
799 #include <arpa/inet.h>
800
801 static int ipmask_parse_ipv4(const char *in, struct in_addr *out)
802 {
803   int class;
804   char ipname[16];
805   int ad[4] = { 0 };
806   int bits = 0;
807
808   class = sscanf(in, "%d.%d.%d.%d/%d", &ad[0], &ad[1], &ad[2], &ad[3], &bits);
809   if (class != 5)
810     bits = class * 8;
811   ircd_snprintf(0, ipname, sizeof(ipname), "%d.%d.%d.%d", ad[0], ad[1], ad[2], ad[3]);
812   out->s_addr = inet_addr(ipname);
813   return bits;
814 }
815
816 int check_if_ipmask(const char *mask)
817 {
818   int has_digit = 0;
819   const char *p;
820
821   for (p = mask; *p; ++p)
822     if (*p != '*' && *p != '?' && *p != '.' && *p != '/')
823     {
824       if (!IsDigit(*p))
825         return 0;
826       has_digit = -1;
827     }
828
829   return has_digit;
830 }
831
832 int ipmask_parse(const char *in, struct irc_in_addr *mask, unsigned char *bits_ptr)
833 {
834   struct in_addr ipv4;
835   char *p;
836   int bits = 0;
837
838   if (check_if_ipmask(in)) {
839     bits = ipmask_parse_ipv4(in, &ipv4);
840     mask->in6_16[0] = mask->in6_16[1] = mask->in6_16[2] = 0;
841     mask->in6_16[3] = mask->in6_16[4] = mask->in6_16[5] = 0;
842     memcpy(&mask->in6_16[6], &ipv4.s_addr, sizeof(ipv4.s_addr));
843     bits += 96;
844   } else {
845     if (!(p = strchr(in, '/')))
846       bits = 128;
847     else
848       *p = 0;
849     if (!ircd_aton(mask, in)) {
850       if (p)
851         *p = '/';
852       return 0;
853     }
854     if (p) {
855       bits = atoi(p + 1);
856       *p = '/';
857     }
858   }
859
860   if (bits_ptr)
861     *bits_ptr = bits;
862   return 1;
863 }
864
865 int ipmask_check(const struct irc_in_addr *addr, const struct irc_in_addr *mask, unsigned char bits)
866 {
867   int k;
868
869   for (k = 0; k < 8; k++) {
870     if (bits < 16)
871       return (addr->in6_16[k] & ((unsigned char) (0xffff << (16-bits)))) == mask->in6_16[k];
872     if (addr->in6_16[k] != mask->in6_16[k])
873       return 0;
874     if (!(bits -= 16))
875       return 1;
876   }
877   return -1;
878 }