modules/wk/which_keytypes.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- wk_regex_init
- wk_is_name
- wk_is_domain
- wk_is_hostname
- WK_to_string
- WK_new
1 /***************************************
2 $Revision: 1.24 $
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 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 #include <stdio.h>
31 #include <stdlib.h>
32 #include <strings.h>
33 #include <glib.h>
34 #include <pthread.h>
35
36 #include "bitmask.h"
37 #include "memwrap.h"
38
39 #define WK_IMPL
40 #include "which_keytypes.h"
41 #include <regex.h>
42
43 #define DOMAINNAME "^[ ]*[a-zA-Z0-9-]*(\\.[a-zA-Z0-9-]+)*[ ]*$"
44 /* add a constraint: there must be at least one character in the domain name
45 because the TLD must not be composed of digits only */
46 #define DOMAINALPHA "[a-zA-Z]"
47
48 #define VALIDIP6PREFIX "^[0-9A-F:]*:[0-9A-F:/]*$" /* at least one colon */
49 /* "^[0-9A-F]{1,4}(:[0-9A-F]{1,4}){7}$"*/
50
51 /* AS numbers, prepared for 32-bit AS numbers */
52 #define ASNUM "^AS[1-9][0-9]{0,9}$"
53
54 /* AS numbers, prepared for 32-bit AS numbers */
55 #define ASRANGE "^AS[1-9][0-9]{0,9}[ ]*([-][ ]*AS[1-9][0-9]{0,9}){0,1}$" /* [ ]*(-[ ]*AS[0-9]+)? */
56
57 #define NETNAME "^[A-Z][A-Z0-9_-]*$"
58
59 #define MAINTAINER "^[A-Z][A-Z0-9_-]*$"
60
61 #define LIMERICK "^LIM-[A-Z0-9_-]+$"
62
63 #define KEYCERT "^PGPKEY-[0-9A-F]{8}$"
64
65 /* made less restrictive to make consistent with other sets ... shane */
66 /* made to match what we're actually looking for - shane */
67 /*#define ROUTESETNAME "^RS-[A-Z0-9_:-]*$"*/
68 #define ROUTESETNAME "(^|:)RS-[A-Z0-9_-]*[A-Z0-9](:|$)"
69
70 /* made less restrictive to make consistent with other sets ... shane */
71 /* made to match what we're actually looking for - shane */
72 /*#define ASSETNAME "^AS-[A-Z0-9_:-]*$"*/
73 #define ASSETNAME "(^|:)AS-[A-Z0-9_-]*[A-Z0-9](:|$)"
74
75 #define AUTONICPREFIXREGULAR "^AUTO-"
76
77 #define IPRANGE "^[0-9]{1,3}(\\.[0-9]{1,3}){0,3}[ ]*-[ ]*[0-9]{1,3}(\\.[0-9]{1,3}){0,3}$"
78
79 #define IPADDRESS "^[0-9.]+$"
80
81 #define IPPREFIX "^[0-9.]+/[0-9]+$"
82
83 /*#define PEERINGSET "^PRNG-"*/
84 #define PEERINGSET "(^|:)PRNG-[A-Z0-9_-]*[A-Z0-9](:|$)"
85
86 /*#define FILTERSET "^FLTR-"*/
87 #define FILTERSET "(^|:)FLTR-[A-Z0-9_-]*[A-Z0-9](:|$)"
88
89 /*#define RTRSET "^RTRS-"*/
90 #define RTRSET "(^|:)RTRS-[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 };
130 #define WK_REGEX_LIST_LEN (sizeof(wk_regex_list)/sizeof(wk_regex_list[0]))
131
132 /* regular expressions used by wk_is_name() */
133 static regex_t ipaddress;
134 static regex_t ipprefix;
135 static regex_t validip6prefix;
136
137 /* regular expression used by isdomname() */
138 static regex_t domainname;
139 static regex_t domainalpha;
140
141 /* initialize regular expressions */
142 static void
143 wk_regex_init ()
/* [<][>][^][v][top][bottom][index][help] */
144 {
145 int i;
146 int errcode;
147
148 /* initialize our table */
149 for (i=0; i<WK_REGEX_LIST_LEN; i++) {
150 errcode = regcomp(&wk_regex_list[i].regex,
151 wk_regex_list[i].pattern,
152 REG_EXTENDED|REG_NOSUB);
153 dieif(errcode != 0);
154 }
155
156 /* add some special cases used by our other functions */
157 errcode = regcomp(&ipaddress, IPADDRESS, REG_EXTENDED|REG_NOSUB);
158 dieif(errcode != 0);
159 errcode = regcomp(&ipprefix, IPPREFIX, REG_EXTENDED|REG_NOSUB);
160 dieif(errcode != 0);
161 errcode = regcomp(&validip6prefix, VALIDIP6PREFIX, REG_EXTENDED|REG_NOSUB);
162 dieif(errcode != 0);
163 errcode = regcomp(&domainname, DOMAINNAME, REG_EXTENDED|REG_NOSUB);
164 dieif(errcode != 0);
165 errcode = regcomp(&domainalpha, DOMAINALPHA, REG_EXTENDED|REG_NOSUB);
166 dieif(errcode != 0);
167 }
168
169
170 /* see if the key looks like it could be a name */
171 static unsigned int
172 wk_is_name (char *key)
/* [<][>][^][v][top][bottom][index][help] */
173 {
174 /* if it's an address, it cannot be a name */
175 if (regexec(&ipaddress, key, 0, NULL, 0) == 0) {
176 return 0;
177 }
178 if (regexec(&ipprefix, key, 0, NULL, 0) == 0) {
179 return 0;
180 }
181 if (regexec(&validip6prefix, key, 0, NULL, 0) == 0) {
182 return 0;
183 }
184
185 /* Everything apart from addresses matches to name */
186 return 1;
187 } /* wk_is_name() */
188
189 /* check for domain name */
190 static unsigned int
191 wk_is_domain (char *key)
/* [<][>][^][v][top][bottom][index][help] */
192 {
193 /* if it matches the general domain name search, and contains an */
194 /* alphabetic character, consider it a possible domain name */
195 if (regexec(&domainname, key, 0, NULL, 0) == 0) {
196 if (regexec(&domainalpha, key, 0, NULL, 0) == 0) {
197 return 1;
198 }
199 }
200 return 0;
201 }
202
203 /* check for a host name (could be a domain, or an IP) */
204 static unsigned int
205 wk_is_hostname (char *key)
/* [<][>][^][v][top][bottom][index][help] */
206 {
207 /* Fix - should check for IPADDRESS, not IPRANGE. - Shane */
208 return (wk_is_domain(key) || (regexec(&ipaddress, key, 0, NULL, 0) == 0));
209 } /* wk_is_hostname() */
210
211 /* WK_to_string() */
212 /*++++++++++++++++++++++++++++++++++++++
213 Convert the which keytypes bitmap into a string.
214
215 mask_t wk The which keytypes mask to be converted.
216
217 More:
218 +html+ <PRE>
219 Authors:
220 ottrey
221 +html+ </PRE><DL COMPACT>
222 +html+ <DT>Online References:
223 +html+ <DD><UL>
224 +html+ </UL></DL>
225
226 ++++++++++++++++++++++++++++++++++++++*/
227 char *
228 WK_to_string (mask_t wk)
/* [<][>][^][v][top][bottom][index][help] */
229 {
230
231 return MA_to_string(wk, Keytypes);
232
233 } /* WK_to_string() */
234
235 /* WK_new() */
236 /*++++++++++++++++++++++++++++++++++++++
237 Create a new which keytypes bitmap.
238
239 This checks the string to see which keys it looks like. This helps
240 us decide what SQL tables (or radix trees) we need to query for a
241 match.
242
243 char *key The key to be examined.
244
245 More:
246 +html+ <PRE>
247 Authors:
248 ottrey
249 shane
250 +html+ </PRE><DL COMPACT>
251 +html+ <DT>Online References:
252 +html+ <DD><UL>
253 +html+ </UL></DL>
254
255 ++++++++++++++++++++++++++++++++++++++*/
256 mask_t
257 WK_new (char *key)
/* [<][>][^][v][top][bottom][index][help] */
258 {
259 static pthread_once_t once_control = { PTHREAD_ONCE_INIT };
260
261 mask_t wk;
262 int i;
263
264 /* initialize our regular expressions on the first call */
265 pthread_once(&once_control, wk_regex_init);
266
267 /* empty bitmask */
268 wk = MA_new(MA_END);
269
270 /* search regular expressions in the list */
271 for (i=0; i<WK_REGEX_LIST_LEN; i++) {
272 if (regexec(&wk_regex_list[i].regex, key, 0, NULL, 0) == 0) {
273 MA_set(&wk, wk_regex_list[i].key_type, 1);
274 }
275 }
276
277 /* check our more complicated key patterns */
278 MA_set(&wk, WK_NAME, wk_is_name(key));
279 MA_set(&wk, WK_DOMAIN, wk_is_domain(key));
280 MA_set(&wk, WK_HOSTNAME, wk_is_hostname(key));
281
282 /* return resulting bitmask */
283 return wk;
284
285 } /* WK_new() */