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() */