match.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           match.cpp  -  description
00003                              -------------------
00004     begin                : Thu Dec 9 2004
00005     copyright            : (C) 2004 by VooDooMan
00006     email                : vdmfun@hotmail.com
00007  ***************************************************************************/
00008 
00009 /************************************************************************
00010  *   IRC - Internet Relay Chat, common/match.c
00011  *   Copyright (C) 1990 Jarkko Oikarinen
00012  *   Copyright (C) 2004 by Marian VooDooMan Meravy (vdmfun@hotmail.com)
00013  *                      (re-coded from C to C++)
00014  *
00015  *   This program is free software; you can redistribute it and/or modify
00016  *   it under the terms of the GNU General Public License as published by
00017  *   the Free Software Foundation; either version 1, or (at your option)
00018  *   any later version.
00019  *
00020  *   This program is distributed in the hope that it will be useful,
00021  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  *   GNU General Public License for more details.
00024  *
00025  *   You should have received a copy of the GNU General Public License
00026  *   along with this program; if not, write to the Free Software
00027  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00028  */
00029 
00030 /*!
00031     \file
00032     \brief Provides wildcard checks
00033 */
00034 
00035 #include <ctype.h>
00036 #include <string.h>
00037 #ifdef _WIN32
00038 #   include <winsock2.h>
00039 #endif
00040 #include <stdio.h>
00041 
00042 #include "match.h"
00043 #include "win_sock.h"
00044 
00045 #include "params.h"
00046 
00047 // do NOT touch this define! It doesn't mean if to use IPv6, but rather if to use IPv6 matching!
00048 #define INET6
00049 
00050 #ifdef __alpha
00051 typedef unsigned int uint32;
00052 #else
00053 typedef unsigned long uint32;
00054 #endif
00055 
00056 unsigned char tolowertab[] =
00057       { 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
00058         0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
00059         0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
00060         0x1e, 0x1f,
00061         ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
00062         '*', '+', ',', '-', '.', '/',
00063         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
00064         ':', ';', '<', '=', '>', '?',
00065         '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
00066         'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
00067         't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
00068         '_',
00069         '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
00070         'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
00071         't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
00072         0x7f,
00073         0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
00074         0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
00075         0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
00076         0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
00077         0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
00078         0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
00079         0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
00080         0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
00081         0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
00082         0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
00083         0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
00084         0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
00085         0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
00086         0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
00087         0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
00088         0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
00089 
00090 unsigned char touppertab[] =
00091       { 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
00092         0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
00093         0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
00094         0x1e, 0x1f,
00095         ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
00096         '*', '+', ',', '-', '.', '/',
00097         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
00098         ':', ';', '<', '=', '>', '?',
00099         '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
00100         'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
00101         'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
00102         0x5f,
00103         '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
00104         'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
00105         'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
00106         0x7f,
00107         0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
00108         0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
00109         0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
00110         0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
00111         0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
00112         0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
00113         0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
00114         0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
00115         0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
00116         0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
00117         0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
00118         0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
00119         0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
00120         0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
00121         0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
00122         0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
00123 
00124 //#ifdef INET6
00125 
00126 // BEGIN by VooDooMan
00127 #if defined(IN6_IS_ADDR_V4MAPPED)
00128 #   undef IN6_IS_ADDR_V4MAPPED
00129 #endif
00130 // END   by VooDooMan
00131 
00132 # define MYDUMMY_SIZE 128
00133 # define bcopy(a,b,c) memmove((b),(a),(c))
00134 #define IN6_IS_ADDR_V4MAPPED(a)         \
00135     ((((u_int32_t*)(a))[0] == 0) \
00136     && (((u_int32_t*)(a))[1] == 0) \
00137     && (((u_int32_t*)(a))[2] == htonl(0xffff)))
00138 
00139 #define u_int32_t uint32
00140 #define u_char unsigned char
00141 #define IN6ADDRSZ       16
00142 #define INADDRSZ        4
00143 #define INT16SZ         2
00144 
00145 /*!
00146     \brief Decompresses "::" from IPv6 numeric address; if other address (or possibly hostname given) returns untouched
00147     \author VooDooMan
00148     \version 1
00149     \date 2005
00150     \param src Source address
00151     \return Returns uncompressed address
00152 */
00153 const char* ipv6_decompress(char* src)
00154 {
00155     static char res[1024];
00156     if(strstr(src,":")==NULL)
00157         return src;
00158     if(strstr(src,"::")==NULL)
00159         return src;
00160     //bool ok=true;
00161     int expected_num_frags=8;
00162     if(strstr(src,".")!=NULL)
00163         expected_num_frags=7;
00164     int num_frags=0;
00165     int num_size=0;
00166     bool got=false;
00167     unsigned int i1;
00168     for(i1=0; i1<strlen(src)+1; i1++) { // +1 here is not typo! we need to process zero-terminator as well!
00169         if(src[i1]==':' || src[i1]==0) {
00170             if(/*num_size>4 ||*/ num_frags>expected_num_frags)
00171                 return src; // error
00172             num_size=0;
00173             if(i1>0 && src[i1-1]==':')
00174                 got=true;
00175             else
00176                 if((i1>0 && src[i1-1]!=':') && i1>0)
00177                     num_frags++;
00178         } else {
00179             num_size++;
00180         }
00181     }
00182     if(!got)
00183         return src;
00184     if(num_frags>8)
00185         return src;
00186     bool need_colon=false;
00187     int i2=0;
00188     for(i1=0; i1<strlen(src); i1++) {
00189         if(i2>sizeof(res)-8)
00190             return src;
00191         if(src[i1]==':' && i1>0 && src[i1-1]==':') {
00192             for(int i3=0; i3<expected_num_frags-num_frags; i3++) {
00193                 if(i2>sizeof(res)-8)
00194                     return src;
00195                 if(i2>0 && res[i2-1]!=':')
00196                     res[i2++]=':';
00197                 res[i2++]='0';
00198                 need_colon=true;
00199             }
00200         } else {
00201             if(!(i1==0 && src[i1]==':')) {
00202                 if(need_colon)
00203                     res[i2++]=':';
00204                 if(!need_colon)
00205                     res[i2++]=src[i1];
00206                 if(need_colon && src[i1]!=':')
00207                     res[i2++]=src[i1];
00208             }
00209             need_colon=false;
00210         }
00211     }
00212     res[i2++]=0;
00213     return res;
00214 }
00215 
00216 static const char *inet_ntop4 (const u_char *src, char *dst, size_t size)
00217 {
00218   char tmp [sizeof("255.255.255.255")];
00219 
00220   if ((size_t)sprintf(tmp,"%u.%u.%u.%u",src[0],src[1],src[2],src[3]) > size)
00221   {
00222     //SOCK_ERRNO (ENOSPC);
00223     return (NULL);
00224   }
00225   return strcpy (dst, tmp);
00226 }
00227 
00228 //#if defined(USE_IPV6)
00229 
00230 /*const char *inet_ntop6 (const u_char *src, char *dst, size_t size)
00231 {
00232   /*
00233    * Note that int32_t and int16_t need only be "at least" large enough
00234    * to contain a value of the specified size.  On some systems, like
00235    * Crays, there is no such thing as an integer variable with 16 bits.
00236    * Keep this in mind if you think this function should have been coded
00237    * to use pointer overlays.  All the world's not a VAX.
00238    *
00239   char  tmp [sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
00240   char *tp;
00241   struct {
00242     long base;
00243     long len;
00244   } best, cur;
00245   u_long words [IN6ADDRSZ / INT16SZ];
00246   int    i;
00247 
00248   /* Preprocess:
00249    *  Copy the input (bytewise) array into a wordwise array.
00250    *  Find the longest run of 0x00's in src[] for :: shorthanding.
00251    *
00252   memset (words, 0, sizeof(words));
00253   for (i = 0; i < IN6ADDRSZ; i++)
00254       words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
00255 
00256   best.base = -1;
00257   cur.base  = -1;
00258   for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
00259   {
00260     if (words[i] == 0)
00261     {
00262       if (cur.base == -1)
00263            cur.base = i, cur.len = 1;
00264       else cur.len++;
00265     }
00266     else if (cur.base != -1)
00267     {
00268       if (best.base == -1 || cur.len > best.len)
00269          best = cur;
00270       cur.base = -1;
00271     }
00272   }
00273   if ((cur.base != -1) && (best.base == -1 || cur.len > best.len))
00274      best = cur;
00275 
00276   if (best.base != -1 && best.len < 2)
00277      best.base = -1;
00278 
00279   /* Format the result.
00280    *
00281   tp = tmp;
00282   for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
00283   {
00284     /* Are we inside the best run of 0x00's?
00285      *
00286     if (best.base != -1 && i >= best.base && i < (best.base + best.len))
00287     {
00288       if (i == best.base)
00289          *tp++ = ':';
00290       continue;
00291     }
00292 
00293     /* Are we following an initial run of 0x00s or any real hex?
00294      *
00295     if (i != 0)
00296        *tp++ = ':';
00297 
00298     /* Is this address an encapsulated IPv4?
00299      *
00300     if (i == 6 && best.base == 0 &&
00301         (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
00302     {
00303       if (!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp)))
00304       {
00305         //SOCK_ERRNO (ENOSPC);
00306         return (NULL);
00307       }
00308       tp += strlen (tp);
00309       break;
00310     }
00311     tp += sprintf (tp, "%lX", words[i]);
00312   }
00313 }*/
00314 
00315 #ifdef SPRINTF_CHAR
00316 # define SPRINTF(x) strlen(sprintfx)
00317 #else
00318 # define SPRINTF(x) ((size_t)sprintf x)
00319 #endif
00320 
00321 
00322 /* const char *
00323  * inet_ntop6(src, dst, size)
00324  *      convert IPv6 binary address into presentation (printable) format
00325  * author:
00326  *      Paul Vixie, 1996.
00327  */
00328 const char * inet_ntop6(const u_char *src, char *dst, size_t size)
00329 {
00330         /*
00331          * Note that int32_t and int16_t need only be "at least" large enough
00332          * to contain a value of the specified size.  On some systems, like
00333          * Crays, there is no such thing as an integer variable with 16 bits.
00334          * Keep this in mind if you think this function should have been coded
00335          * to use pointer overlays.  All the world's not a VAX.
00336          */
00337         char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
00338         struct { int base, len; } best, cur;
00339         u_int words[IN6ADDRSZ / INT16SZ];
00340         int i;
00341 
00342         /*
00343          * Preprocess:
00344          *      Copy the input (bytewise) array into a wordwise array.
00345 
00346          *      Find the longest run of 0x00's in src[] for :: shorthanding.
00347          */
00348         memset(words, '\0', sizeof words);
00349         for (i = 0; i < IN6ADDRSZ; i++)
00350                 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
00351         best.base = -1;
00352         cur.base = -1;
00353         for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
00354                 if (words[i] == 0) {
00355                         if (cur.base == -1)
00356                                 cur.base = i, cur.len = 1;
00357                         else
00358                                 cur.len++;
00359                 } else {
00360                         if (cur.base != -1) {
00361                                 if (best.base == -1 || cur.len > best.len)
00362                                         best = cur;
00363                                 cur.base = -1;
00364                         }
00365                 }
00366         }
00367         if (cur.base != -1) {
00368                 if (best.base == -1 || cur.len > best.len)
00369                         best = cur;
00370         }
00371         if (best.base != -1 && best.len < 2)
00372                 best.base = -1;
00373 
00374         /*
00375          * Format the result.
00376          */
00377         tp = tmp;
00378         for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
00379                 /* Are we inside the best run of 0x00's? */
00380                 if (best.base != -1 && i >= best.base &&
00381                     i < (best.base + best.len)) {
00382                         if (i == best.base)
00383                                 *tp++ = ':';
00384                         continue;
00385                 }
00386 
00387                 /* Are we following an initial run of 0x00s or any real hex? */
00388                 if (i != 0)
00389                         *tp++ = ':';
00390                 /* Is this address an encapsulated IPv4? */
00391                 if (i == 6 && best.base == 0 &&
00392                     (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
00393                         if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
00394                                 return (NULL);
00395                         tp += strlen(tp);
00396                         break;
00397                 }
00398                 tp += SPRINTF((tp, "%x", words[i]));
00399         }
00400         /* Was it a trailing run of 0x00's? */
00401         if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
00402                 *tp++ = ':';
00403         *tp++ = '\0';
00404 
00405         /*
00406          * Check for overflow, copy, and we're done.
00407          */
00408         if ((size_t)(tp - tmp) > size) {
00409                 //errno = ENOSPC;
00410                 return (NULL);
00411         }
00412         strcpy(dst, tmp);
00413         return (dst);
00414 }
00415 
00416 
00417 const char * inet_ntop (int af, const void *src, char *dst, size_t size)
00418 {
00419     switch (af)
00420     {
00421         case AF_INET:
00422             return inet_ntop4 ((const u_char*)src, dst, size);
00423         case AF_INET6:
00424             return inet_ntop6 ((const u_char*)src, dst, size);
00425         default:
00426             return (NULL);
00427     }
00428 }
00429 
00430 /*
00431  * inetntop: return the : notation of a given IPv6 internet number.
00432  *       or the dotted-decimal notation for IPv4
00433  *           make sure the compressed representation (rfc 1884) isn't used.
00434  */
00435 char  *inetntop(int af, const void *in, char *out, size_t the_size)
00436 {
00437   static char local_dummy[MYDUMMY_SIZE];
00438 
00439   if (the_size > sizeof(local_dummy))
00440   {
00441     the_size = sizeof(local_dummy);
00442   }
00443 
00444   if (!inet_ntop(af, in, local_dummy, the_size))
00445   {
00446     /* good that every function calling this one
00447      * checks the return value ... NOT */
00448     return NULL;
00449   }
00450   /* quick and dirty hack to give ipv4 just ipv4 instead of
00451    * ::ffff:ipv4 - Q */
00452   if (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED((const struct in_addr6_ *)in))
00453   {
00454     char  *p;
00455 
00456     if (!(p = strstr(local_dummy, ":ffff:")) &&
00457       !(p = strstr(local_dummy, ":FFFF:")))
00458     {
00459       return NULL;  /* crash and burn */
00460     }
00461     strcpy(out, p + 6);
00462     return out;
00463   }
00464   if (strstr(local_dummy, "::"))
00465       {
00466     char cnt = 0, *cp = local_dummy, *op = out;
00467 
00468     while (*cp)
00469         {
00470       if (*cp == ':')
00471         cnt += 1;
00472       if (*cp++ == '.')
00473           {
00474         cnt += 1;
00475         break;
00476           }
00477         }
00478     cp = local_dummy;
00479     while (*cp)
00480         {
00481       *op++ = *cp++;
00482       if (*(cp-1) == ':' && *cp == ':')
00483           {
00484         if ((cp-1) == local_dummy)
00485             {
00486           op--;
00487           *op++ = '0';
00488           *op++ = ':';
00489             }
00490 
00491         *op++ = '0';
00492         while (cnt++ < 7)
00493             {
00494           *op++ = ':';
00495           *op++ = '0';
00496             }
00497           }
00498         }
00499     if (*(op-1)==':') *op++ = '0';
00500     *op = '\0';
00501 /*#ifndef  CLIENT_COMPILE
00502     Debug((DEBUG_DNS,"Expanding `%s' -> `%s'", local_dummy,
00503            out));
00504 #endif*/
00505       }
00506   else
00507     bcopy(local_dummy, out,  the_size);
00508 
00509   return out;
00510 }
00511 
00512 /* int
00513  * inet_pton4(src, dst, pton)
00514  *      when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand.
00515  *      when last arg is 1: inet_pton(). decimal dotted-quad only.
00516  * return:
00517  *      1 if `src' is a valid input, else 0.
00518  * notice:
00519  *      does not touch `dst' unless it's returning 1.
00520  * author:
00521  *      Paul Vixie, 1996.
00522  */
00523 int
00524 inet_pton4(const char *src, u_char *dst, int pton)
00525 {
00526         u_int val;
00527         u_int digit;
00528         int base, n;
00529         unsigned char c;
00530         u_int parts[4];
00531         register u_int *pp = parts;
00532 
00533         c = *src;
00534         for (;;) {
00535                 /*
00536                  * Collect number up to ``.''.
00537                  * Values are specified as for C:
00538                  * 0x=hex, 0=octal, isdigit=decimal.
00539                  */
00540                 if (!isdigit(c))
00541                         return (0);
00542                 val = 0; base = 10;
00543                 if (c == '0') {
00544                         c = *++src;
00545                         if (c == 'x' || c == 'X')
00546                                 base = 16, c = *++src;
00547                         else if (isdigit(c) && c != '9')
00548                                 base = 8;
00549                 }
00550                 /* inet_pton() takes decimal only */
00551                 if (pton && base != 10)
00552                         return (0);
00553                 for (;;) {
00554                         if (isdigit(c)) {
00555                                 digit = c - '0';
00556                                 if (digit >= base)
00557                                         break;
00558                                 val = (val * base) + digit;
00559                                 c = *++src;
00560                         } else if (base == 16 && isxdigit(c)) {
00561                                 digit = c + 10 - (islower(c) ? 'a' : 'A');
00562                                 if (digit >= 16)
00563                                         break;
00564                                 val = (val << 4) | digit;
00565                                 c = *++src;
00566                         } else
00567                                 break;
00568                 }
00569                 if (c == '.') {
00570                         /*
00571                          * Internet format:
00572                          *      a.b.c.d
00573                          *      a.b.c   (with c treated as 16 bits)
00574                          *      a.b     (with b treated as 24 bits)
00575                          *      a       (with a treated as 32 bits)
00576                          */
00577                         if (pp >= parts + 3)
00578                                 return (0);
00579                         *pp++ = val;
00580                         c = *++src;
00581                 } else
00582                         break;
00583         }
00584         /*
00585          * Check for trailing characters.
00586          */
00587         if (c != '\0' && !isspace(c))
00588                 return (0);
00589         /*
00590          * Concoct the address according to
00591          * the number of parts specified.
00592          */
00593         n = pp - parts + 1;
00594         /* inet_pton() takes dotted-quad only.  it does not take shorthand. */
00595         if (pton && n != 4)
00596                 return (0);
00597         switch (n) {
00598 
00599         case 0:
00600                 return (0);             /* initial nondigit */
00601 
00602         case 1:                         /* a -- 32 bits */
00603                 break;
00604 
00605         case 2:                         /* a.b -- 8.24 bits */
00606                 if (parts[0] > 0xff || val > 0xffffff)
00607                         return (0);
00608                 val |= parts[0] << 24;
00609                 break;
00610 
00611         case 3:                         /* a.b.c -- 8.8.16 bits */
00612                 if ((parts[0] | parts[1]) > 0xff || val > 0xffff)
00613                         return (0);
00614                 val |= (parts[0] << 24) | (parts[1] << 16);
00615                 break;
00616 
00617         case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
00618                 if ((parts[0] | parts[1] | parts[2] | val) > 0xff)
00619                         return (0);
00620                 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
00621                 break;
00622         }
00623         if (dst) {
00624                 val = htonl(val);
00625                 memcpy(dst, &val, INADDRSZ);
00626         }
00627         return (1);
00628 }
00629 
00630 /* int
00631  * inet_pton6(src, dst)
00632  *      convert presentation level address to network order binary form.
00633  * return:
00634  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
00635  * notice:
00636  *      (1) does not touch `dst' unless it's returning 1.
00637  *      (2) :: in a full address is silently ignored.
00638  *          NB by VooDooMan: 2005-06-29: Added decompress :: addresses first, so it should work
00639  * credit:
00640  *      inspired by Mark Andrews.
00641  * author:
00642  *      Paul Vixie, 1996.
00643  */
00644 int
00645 inet_pton6(const char *src, u_char *dst)
00646 {
00647     if(src) {
00648         src=ipv6_decompress((char*)src);
00649     }
00650 
00651         static const char xdigits_l[] = "0123456789abcdef",
00652                           xdigits_u[] = "0123456789ABCDEF";
00653         u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
00654         const char *xdigits, *curtok;
00655         int ch, saw_xdigit;
00656         u_int val;
00657 
00658         memset((tp = tmp), '\0', IN6ADDRSZ);
00659         endp = tp + IN6ADDRSZ;
00660         colonp = NULL;
00661         /* Leading :: requires some special handling. */
00662         if (*src == ':')
00663                 if (*++src != ':')
00664                         return (0);
00665         curtok = src;
00666         saw_xdigit = 0;
00667         val = 0;
00668         while ((ch = *src++) != '\0') {
00669                 const char *pch;
00670 
00671                 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
00672                         pch = strchr((xdigits = xdigits_u), ch);
00673                 if (pch != NULL) {
00674                         val <<= 4;
00675                         val |= (pch - xdigits);
00676                         if (val > 0xffff)
00677                                 return (0);
00678                         saw_xdigit = 1;
00679                         continue;
00680                 }
00681                 if (ch == ':') {
00682                         curtok = src;
00683                         if (!saw_xdigit) {
00684                                 if (colonp)
00685                                         return (0);
00686                                 colonp = tp;
00687                                 continue;
00688                         } else if (*src == '\0')
00689                                 return (0);
00690                         if (tp + INT16SZ > endp)
00691                                 return (0);
00692                         *tp++ = (u_char) (val >> 8) & 0xff;
00693                         *tp++ = (u_char) val & 0xff;
00694                         saw_xdigit = 0;
00695                         val = 0;
00696                         continue;
00697                 }
00698                 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
00699                     inet_pton4(curtok, tp, 1) > 0) {
00700                         tp += INADDRSZ;
00701                         saw_xdigit = 0;
00702                         break;  /* '\0' was seen by inet_pton4(). */
00703                 }
00704                 return (0);
00705         }
00706         if (saw_xdigit) {
00707                 if (tp + INT16SZ > endp)
00708                         return (0);
00709                 *tp++ = (u_char) (val >> 8) & 0xff;
00710                 *tp++ = (u_char) val & 0xff;
00711         }
00712         if (colonp != NULL) {
00713                 /*
00714                  * Since some memmove()'s erroneously fail to handle
00715                  * overlapping regions, we'll do the shift by hand.
00716                  */
00717                 const int n = tp - colonp;
00718                 int i;
00719 
00720                 if (tp == endp)
00721                         return (0);
00722                 for (i = 1; i <= n; i++) {
00723                         endp[- i] = colonp[n - i];
00724                         colonp[n - i] = 0;
00725                 }
00726                 tp = endp;
00727         }
00728         if (tp != endp)
00729                 return (0);
00730         memcpy(dst, tmp, IN6ADDRSZ);
00731         return (1);
00732 }
00733 
00734 /* int
00735  * inet_pton(af, src, dst)
00736  *      convert from presentation format (which usually means ASCII printable)
00737  *      to network format (which is usually some kind of binary format).
00738  * return:
00739  *      1 if the address was valid for the specified address family
00740  *      0 if the address wasn't valid (`dst' is untouched in this case)
00741  *      -1 if some other error occurred (`dst' is untouched in this case, too)
00742  * author:
00743  *      Paul Vixie, 1996.
00744  */
00745 int
00746 inet_pton(int af, const char *src, void *dst)
00747 {
00748 
00749         switch (af) {
00750         case AF_INET:
00751                 return (inet_pton4(src, (unsigned char*)dst, 1));
00752         case AF_INET6:
00753                 return (inet_pton6(src, (unsigned char*)dst));
00754         default:
00755                 //errno = EAFNOSUPPORT;
00756                 return (-1);
00757         }
00758         /* NOTREACHED */
00759 }
00760 
00761 /* inetpton(af, src, dst)
00762 **
00763 ** This is a wrapper for inet_pton(), so we can use ipv4 addresses with an
00764 ** af of AF_INET6, and that it gets converted to ipv4 mapped ipv6.
00765 */
00766 int  inetpton(int af, const char *src, void *dst)
00767 {
00768   int  i;
00769 
00770   /* an empty string should listen to all */
00771   if (af == AF_INET6 && *src && !strchr(src, ':'))
00772       {
00773     i = inet_pton(AF_INET, src, dst);
00774 
00775     /* ugly hack */
00776     memcpy((char *)dst + 12, dst, 4);
00777     memset(dst, 0, 10);
00778     memset((char *)dst + 10, 0xff, 2);
00779     return i;
00780       }
00781   return inet_pton(af, src, dst);
00782 }
00783 //#endif
00784 
00785 // BEGIN CHANGE - VooDooMan 2004/08/01 - commented out
00786 //#define   MAX_ITERATIONS   512
00787 // END   CHANGE - VooDooMan 2004/08/01 - commented out
00788 
00789 /*
00790 **  Compare if a given string (name) matches the given
00791 **  mask (which can contain wild cards: '*' - match any
00792 **  number of chars, '?' - match any single character.
00793 **
00794 **   return   0, if match
00795 **      1, if no match
00796 */
00797 
00798 /*
00799 ** match()
00800 ** Iterative matching function, rather than recursive.
00801 ** Written by Douglas A Lewis (dalewis@acsu.buffalo.edu)
00802 */
00803 
00804 #define Reg register
00805 #define u_char unsigned char
00806 
00807 #define  MAX_ITERATIONS  512
00808 /*
00809 **  Compare if a given string (name) matches the given
00810 **  mask (which can contain wild cards: '*' - match any
00811 **  number of chars, '?' - match any single character.
00812 **
00813 **  return  0, if match
00814 **    1, if no match
00815 */
00816 
00817 /*
00818 
00819 ** match()
00820 ** Iterative matching function, rather than recursive.
00821 ** Written by Douglas A Lewis (dalewis@acsu.buffalo.edu)
00822 */
00823 
00824 int  match(char *mask, char *name)
00825 {
00826   Reg  u_char  *m = (u_char *)mask, *n = (u_char *)name;
00827   char  *ma = mask, *na = name;
00828   int  wild = 0, q = 0, calls = 0;
00829 
00830   if (!*mask)
00831     return 1;
00832 
00833   if (mask[0]=='*' && mask[1]=='\0')
00834     return 0;
00835 
00836   while (1)
00837       {
00838 #ifdef  MAX_ITERATIONS
00839           if (calls++ > MAX_ITERATIONS)
00840       break;               
00841 #endif
00842 
00843     if (*m == '*')
00844        {
00845       while (*m == '*')
00846         m++;
00847       wild = 1;
00848       ma = (char *)m;
00849       na = (char *)n;
00850         }
00851 
00852     if (!*m)
00853         {
00854         if (!*n)
00855         return 0;
00856         for (m--; (m > (u_char *)mask) && (*m == '?'); m--)
00857         ;
00858       if ((m > (u_char *)mask) && (*m == '*') &&
00859           (m[-1] != '\\'))
00860         return 0;
00861       if (!wild) 
00862         return 1;
00863       m = (u_char *)ma;
00864       n = (u_char *)++na;
00865         }
00866     else if (!*n)
00867       return 1;
00868     if ((*m == '\\') &&
00869       ((m[1] == '*') || (m[1] == '?') || (m[1] == '#')))
00870         {
00871       m++;
00872       q = 1;
00873         }
00874     else
00875       q = 0;
00876 
00877     if ((tolower(*m) == tolower(*n))
00878       || (*m == '?' && !q)
00879       || (*m == '#' && !q && isdigit(*n)))
00880         {
00881       if (*m)
00882         m++;
00883       if (*n)
00884         n++;
00885         }
00886     else
00887         {
00888       if (!wild)
00889         return 1;
00890       m = (u_char *)ma;
00891       n = (u_char *)++na;
00892         }
00893       }
00894 
00895   return 1;
00896 }
00897 
00898 // BEGIN ADD    - VooDooMan 2004/10/18 - changed
00899 #define u_long unsigned long
00900 
00901 char* index(char* str, char sub)
00902 {
00903     char tmp[2];
00904     tmp[0]=sub;
00905     tmp[1]=0;
00906     return strstr(str,tmp);
00907 }
00908 // END   ADD    - VooDooMan 2004/10/18 - changed
00909 
00910 #define  strncpyzt(x, y, N) do{(void)strncpy(x,y,N);x[N-1]='\0';}while(0)
00911 
00912 /*
00913  * Match address by #IP bitmask (10.11.12.128/27)
00914  * Now should work for IPv6 too.
00915  * returns -1 on error, 0 on match, 1 when NO match.
00916  */
00917 // BEGIN CHANGE - VooDooMan 2004/10/18 - changed
00918 //int    match_ipmask(char *mask, aClient *cptr, int maskwithusername)
00919 int    match_ipmask(char *mask, char* username, in_addr6_ u_addr, int maskwithusername)
00920 // END   CHANGE - VooDooMan 2004/10/18 - changed
00921 {
00922   int  m;
00923   char  *p;
00924 // BEGIN CHANGE - VooDooMan 2004/10/18 - changed
00925 //  struct  IN_ADDR addr;
00926   struct  in_addr6_ addr;
00927 // END   CHANGE - VooDooMan 2004/10/18 - changed
00928   char  dummy[128];
00929   char  *omask;
00930   u_long  lmask;
00931 #ifdef  INET6
00932   int  j;
00933 #endif
00934 
00935   omask = mask;
00936   strncpyzt(dummy, mask, sizeof(dummy));
00937   mask = dummy;
00938   if (maskwithusername && (p = index(mask, '@')))
00939   {
00940     *p = '\0';
00941 // BEGIN CHANGE - VooDooMan 2004/10/18 - changed
00942 //    if (match(mask, cptr->username))
00943     if (match(mask, username))
00944 // END   CHANGE - VooDooMan 2004/10/18 - changed
00945       return 1;
00946     mask = p + 1;
00947   }
00948   if (!(p = index(mask, '/')))
00949     goto badmask;
00950   *p = '\0';
00951   
00952   if (sscanf(p + 1, "%d", &m) != 1)
00953   {
00954     goto badmask;
00955   }
00956   if (!m)
00957     return 0;       /* x.x.x.x/0 always matches */
00958 #ifndef  INET6
00959   if (m < 0 || m > 32)
00960     goto badmask;
00961   lmask = htonl((u_long)0xffffffffL << (32 - m));
00962 // BEGIN CHANGE - VooDooMan 2004/10/18 - changed
00963 //  addr.s_addr = inetaddr(mask);
00964 //  return ((addr.s_addr ^ cptr->ip.s_addr) & lmask) ? 1 : 0;
00965   addr.s_addr=inet_addr(mask);
00966   return ((addr.s_addr ^ u_addr) & lmask) ? 1 : 0;
00967 // END   CHANGE - VooDooMan 2004/10/18 - changed
00968 #else
00969   if (m < 0 || m > 128)
00970     goto badmask;
00971   if (inet_pton(AF_INET6, mask, (void *)addr.bytes) != 1)
00972   {
00973     return -1;
00974   }
00975 
00976   /* Make sure that the ipv4 notation still works. */
00977   if (IN6_IS_ADDR_V4MAPPED(&addr) && m < 96)
00978   {
00979     m += 96;
00980   }
00981 
00982   j = m & 0x1F;  /* number not mutliple of 32 bits */
00983   m >>= 5;  /* number of 32 bits */
00984 
00985   if (m && memcmp((void *)(addr.bytes), 
00986       (void *)(/*cptr->ip.s6_addr*/&(u_addr.bytes)), m << 2))
00987     return 1;
00988 
00989   if (j)
00990   {
00991     lmask = htonl((u_long)0xffffffffL << (32 - j));
00992     if ((((u_int32_t *)(addr.bytes))[m] ^
00993         ((u_int32_t *)(/*cptr->ip.s6_addr*/&(u_addr.bytes)))[m]) & lmask)
00994       return 1;
00995   }
00996 
00997   return 0;
00998 #endif
00999 badmask:
01000 // BEGIN CHANGE - VooDooMan 2004/10/18 - changed
01001 /*  if (maskwithusername)
01002   sendto_flag(SCH_ERROR, "Ignoring bad mask: %s", omask);*/
01003 // END   CHANGE - VooDooMan 2004/10/18 - changed
01004   return -1;
01005 }
01006 
01007 

Generated on Sun Jul 10 03:23:00 2005 for VooDoo cIRCle by doxygen 1.4.3

Hosted by SourceForge.net Logo