Source File wk/which_keytypes.c

    1    | /***************************************
    2    |   $Revision: 1.29 $
    3    |
    4    |   which_keytypes:  Determine which keys to look for.
    5    |
    6    |   This is based on the existing Perl code.
    7    |
    8    |   Authors: ottrey, marek
    9    |
    10   |   ******************/ /******************
    11   |   Copyright (c) 1999,2000,2001,2002               RIPE NCC
    12   |
    13   |   All Rights Reserved
    14   |
    15   |   Permission to use, copy, modify, and distribute this software and its
    16   |   documentation for any purpose and without fee is hereby granted,
    17   |   provided that the above copyright notice appear in all copies and that
    18   |   both that copyright notice and this permission notice appear in
    19   |   supporting documentation, and that the name of the author not be
    20   |   used in advertising or publicity pertaining to distribution of the
    21   |   software without specific, written prior permission.
    22   |
    23   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
    24   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
    25   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
    26   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    27   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    28   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    29   |   ***************************************/
    30   |
    31   | #define  WK_IMPL
    32   | #include "rip.h"
    33   |
    34   | #include <stdio.h>
    35   | #include <stdlib.h>
    36   | #include <strings.h>
    37   | #include <glib.h>
    38   | #include <pthread.h>
    39   | #include <regex.h>
    40   |
    41   | #define DOMAINNAME "^[ ]*[a-zA-Z0-9/-]*(\\.[a-zA-Z0-9-]+)*[ ]*$"
    42   | /* add a constraint: there must be at least one character in the domain name
    43   |    because the TLD must not be composed of digits only */
    44   | #define DOMAINALPHA  "[a-zA-Z]"
    45   |
    46   | #define VALIDIP6PREFIX "^[0-9A-F:]*:[0-9A-F:/]*$"     /* at least one colon */
    47   | /* "^[0-9A-F]{1,4}(:[0-9A-F]{1,4}){7}$"*/
    48   |
    49   | /* AS numbers, prepared for 32-bit AS numbers */
    50   | #define ASNUM "^AS[1-9][0-9]{0,9}$"
    51   |
    52   | /* AS numbers, prepared for 32-bit AS numbers */
    53   | #define ASRANGE "^AS[1-9][0-9]{0,9}[ ]*([-][ ]*AS[1-9][0-9]{0,9}){0,1}$"   /* [ ]*(-[ ]*AS[0-9]+)?   */
    54   |
    55   | #define NETNAME "^[A-Z][A-Z0-9_-]*$"
    56   |
    57   | #define MAINTAINER "^[A-Z][A-Z0-9_-]*$"
    58   |
    59   | #define LIMERICK "^LIM-[A-Z0-9_-]+$"
    60   |
    61   | #define KEYCERT "^PGPKEY-[0-9A-F]{8}$"
    62   |
    63   | /* made less restrictive to make consistent with other sets ... shane */
    64   | /* made to match what we're actually looking for - shane */
    65   | /*#define ROUTESETNAME "^RS-[A-Z0-9_:-]*$"*/
    66   | #define ROUTESETNAME "(^|:)RS-[A-Z0-9_-]*[A-Z0-9](:|$)"
    67   |
    68   | /* made less restrictive to make consistent with other sets ... shane */
    69   | /* made to match what we're actually looking for - shane */
    70   | /*#define ASSETNAME "^AS-[A-Z0-9_:-]*$"*/
    71   | #define ASSETNAME "(^|:)AS-[A-Z0-9_-]*[A-Z0-9](:|$)"
    72   |
    73   | #define AUTONICPREFIXREGULAR "^AUTO-"
    74   |
    75   | #define IPRANGE "^[0-9]{1,3}(\\.[0-9]{1,3}){0,3}[ ]*-[ ]*[0-9]{1,3}(\\.[0-9]{1,3}){0,3}$"
    76   |
    77   | #define IPADDRESS "^[0-9.]+$"
    78   |
    79   | #define IPPREFIX "^[0-9.]+/[0-9]+$"
    80   |
    81   | /*#define PEERINGSET "^PRNG-"*/
    82   | #define PEERINGSET "(^|:)PRNG-[A-Z0-9_-]*[A-Z0-9](:|$)"
    83   |
    84   | /*#define FILTERSET  "^FLTR-"*/
    85   | #define FILTERSET "(^|:)FLTR-[A-Z0-9_-]*[A-Z0-9](:|$)"
    86   |
    87   | /*#define RTRSET     "^RTRS-"*/
    88   | #define RTRSET "(^|:)RTRS-[A-Z0-9_-]*[A-Z0-9](:|$)"
    89   |
    90   | #define IRT "^IRT-[A-Z0-9_-]+[A-Z0-9]$"
    91   |
    92   | #define NICHANDLE "^[A-Z0-9-]+$"
    93   |
    94   | /*
    95   |   XXX This seems to be the same as the Perl code.  But I don't see where a " " is allowed for.
    96   |   I.e. Perl -> ^[a-zA-Z][\w\-\.\'\|\`]*$
    97   |   Does \w include [ ;:,?/}{()+*#] ?
    98   | #define NAME_B "^[a-zA-Z][a-zA-Z_0-9.'|`-]*$"
    99   | */
    100  | #define NAME_B "^[a-zA-Z][a-zA-Z_0-9.'|`;:,?/}{()+*#&-]*$"
    101  |
    102  | #define EMAIL "@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*$"
    103  |
    104  | /* structure for simple keys, with a single regular expression to match */
    105  | /* NOTE: the WK_NAME, WK_DOMAIN, and WK_HOSTNAME are not handled here   */
    106  | struct {
    107  |     int key_type;		/* identifier for key, e.g. WK_RTRSET */
    108  |     char *pattern;		/* string for regular expression */
    109  |     regex_t regex;		/* regular expression */
    110  | } wk_regex_list[] = {
    111  |     { WK_NIC_HDL,       NICHANDLE },
    112  |     { WK_EMAIL,         EMAIL },
    113  |     { WK_MNTNER,        MAINTAINER },
    114  |     { WK_KEY_CERT,      KEYCERT },
    115  |     { WK_IPRANGE,       IPRANGE },
    116  |     { WK_IPADDRESS,     IPADDRESS },
    117  |     { WK_IPPREFIX,      IPPREFIX },
    118  |     { WK_IP6PREFIX,     VALIDIP6PREFIX },
    119  |     { WK_NETNAME,       NETNAME },
    120  |     { WK_NET6NAME,      NETNAME },
    121  |     { WK_AUTNUM,        ASNUM },
    122  |     { WK_ASSETNAME,     ASSETNAME },
    123  |     { WK_ROUTESETNAME,  ROUTESETNAME },
    124  |     { WK_LIMERICK,      LIMERICK },
    125  |     { WK_ASRANGE,       ASRANGE },
    126  |     { WK_PEERINGSET,    PEERINGSET },
    127  |     { WK_FILTERSET,     FILTERSET },
    128  |     { WK_RTRSET,        RTRSET },
    129  |     { WK_IRT,           IRT }
    130  | };
    131  | #define WK_REGEX_LIST_LEN  (sizeof(wk_regex_list)/sizeof(wk_regex_list[0]))
    132  |
    133  | /* regular expressions used by wk_is_name() */
    134  | static regex_t ipaddress;
    135  | static regex_t ipprefix;
    136  | static regex_t validip6prefix;
    137  |
    138  | /* regular expression used by isdomname() */
    139  | static regex_t domainname;
    140  | static regex_t domainalpha;
    141  |
    142  | /* initialize regular expressions */
    143  | static void
    144  | wk_regex_init ()
    145  | {
    146  |     int i;
    147  |     int errcode;
    148  |
    149  |     /* initialize our table */
    150  |     for (i=0; i<WK_REGEX_LIST_LEN; i++) {
    151  |         errcode = regcomp(&wk_regex_list[i].regex,
    152  | 	                  wk_regex_list[i].pattern,
    153  | 		          REG_EXTENDED|REG_NOSUB);
    154  |         dieif(errcode != 0);
    155  |     }
    156  |
    157  |     /* add some special cases used by our other functions */
    158  |     errcode = regcomp(&ipaddress, IPADDRESS, REG_EXTENDED|REG_NOSUB);
    159  |     dieif(errcode != 0);
    160  |     errcode = regcomp(&ipprefix, IPPREFIX, REG_EXTENDED|REG_NOSUB);
    161  |     dieif(errcode != 0);
    162  |     errcode = regcomp(&validip6prefix, VALIDIP6PREFIX, REG_EXTENDED|REG_NOSUB);
    163  |     dieif(errcode != 0);
    164  |     errcode = regcomp(&domainname, DOMAINNAME, REG_EXTENDED|REG_NOSUB);
    165  |     dieif(errcode != 0);
    166  |     errcode = regcomp(&domainalpha, DOMAINALPHA, REG_EXTENDED|REG_NOSUB);
    167  |     dieif(errcode != 0);
    168  | }
    169  |
    170  |
    171  | /* see if the key looks like it could be a name */
    172  | static unsigned int
    173  | wk_is_name (char *key)
    174  | {
    175  |     /* if it's an address, it cannot be a name */
    176  |     if (regexec(&ipaddress, key, 0, NULL, 0) == 0) {
    177  |         return 0;
    178  |     }
    179  |     if (regexec(&ipprefix, key, 0, NULL, 0) == 0) {
    180  |         return 0;
    181  |     }
    182  |     if (regexec(&validip6prefix, key, 0, NULL, 0) == 0) {
    183  |         return 0;
    184  |     }
    185  |
    186  |     /* Everything apart from addresses matches to name */
    187  |     return 1;
    188  | } /* wk_is_name() */
    189  |
    190  | /* check for domain name */
    191  | static unsigned int
    192  | wk_is_domain (char *key)
    193  | {
    194  |     /* if it matches the general domain name search, and contains an */
    195  |     /* alphabetic character, consider it a possible domain name */
    196  |     if (regexec(&domainname, key, 0, NULL, 0) == 0) {
    197  |         if (regexec(&domainalpha, key, 0, NULL, 0) == 0) {
    198  | 	    return 1;
    199  | 	}
    200  |     }
    201  |     return 0;
    202  | }
    203  |
    204  | /* check for a host name (could be a domain, or an IP) */
    205  | static unsigned int
    206  | wk_is_hostname (char *key)
    207  | {
    208  |     /* Fix - should check for IPADDRESS, not IPRANGE.  - Shane */
    209  |     return (wk_is_domain(key) || (regexec(&ipaddress, key, 0, NULL, 0) == 0));
    210  | } /* wk_is_hostname() */
    211  |
    212  | /* WK_to_string() */
    213  | /*++++++++++++++++++++++++++++++++++++++
    214  |   Convert the which keytypes bitmap into a string.
    215  |
    216  |   mask_t wk The which keytypes mask to be converted.
    217  |
    218  |   More:
    219  |   +html+ <PRE>
    220  |   Authors:
    221  |         ottrey
    222  |   +html+ </PRE><DL COMPACT>
    223  |   +html+ <DT>Online References:
    224  |   +html+ <DD><UL>
    225  |   +html+ </UL></DL>
    226  |
    227  |   ++++++++++++++++++++++++++++++++++++++*/
    228  | char *
    229  | WK_to_string (mask_t wk)
    230  | {
    231  |
    232  |   return MA_to_string(wk, Keytypes);
    233  |
    234  | } /* WK_to_string() */
    235  |
    236  | /* WK_new() */
    237  | /*++++++++++++++++++++++++++++++++++++++
    238  |   Create a new which keytypes bitmap.
    239  |
    240  |   This checks the string to see which keys it looks like.  This helps
    241  |   us decide what SQL tables (or radix trees) we need to query for a
    242  |   match.
    243  |
    244  |   char *key The key to be examined.
    245  |
    246  |   More:
    247  |   +html+ <PRE>
    248  |   Authors:
    249  |         ottrey
    250  | 	shane
    251  |   +html+ </PRE><DL COMPACT>
    252  |   +html+ <DT>Online References:
    253  |   +html+ <DD><UL>
    254  |   +html+ </UL></DL>
    255  |
    256  |   ++++++++++++++++++++++++++++++++++++++*/
    257  | mask_t
    258  | WK_new (char *key)
    259  | {
    260  |   static pthread_once_t once_control = PTHREAD_ONCE_INIT;
    261  |
    262  |   mask_t wk;
    263  |   int i;
    264  |
    265  |   /* initialize our regular expressions on the first call */
    266  |   pthread_once(&once_control, wk_regex_init);
    267  |
    268  |   /* empty bitmask */
    269  |   wk = MA_new(MA_END);
    270  |
    271  |   /* search regular expressions in the list */
    272  |   for (i=0; i<WK_REGEX_LIST_LEN; i++) {
    273  |       if (regexec(&wk_regex_list[i].regex, key, 0, NULL, 0) == 0) {
    274  |           MA_set(&wk, wk_regex_list[i].key_type, 1);
    275  |       }
    276  |   }
    277  |
    278  |   /* check our more complicated key patterns */
    279  |   MA_set(&wk, WK_NAME,         wk_is_name(key));
    280  |   MA_set(&wk, WK_DOMAIN,       wk_is_domain(key));
    281  |   MA_set(&wk, WK_HOSTNAME,     wk_is_hostname(key));
    282  |
    283  |   /* return resulting bitmask */
    284  |   return wk;
    285  |
    286  | } /* WK_new() */