1    | /***************************************
2    |   $Revision: 1.11 $
3    | 
4    |   Example code: Determine which keys to look for.
5    |   
6    |   This is based on the C code that was reversed engineered from existing Perl
7    |   code.  (~ottrey/which_table/which_table.c)
8    | 
9    |   ******************/ /******************
10   |   Copyright (c) 1999                              RIPE NCC
11   |  
12   |   All Rights Reserved
13   |   
14   |   Permission to use, copy, modify, and distribute this software and its
15   |   documentation for any purpose and without fee is hereby granted,
16   |   provided that the above copyright notice appear in all copies and that
17   |   both that copyright notice and this permission notice appear in
18   |   supporting documentation, and that the name of the author not be
19   |   used in advertising or publicity pertaining to distribution of the
20   |   software without specific, written prior permission.
21   |   
22   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
23   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
24   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
25   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
26   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
27   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28   |   ***************************************/
29   | #include <stdio.h>
30   | #include <stdlib.h>
31   | #include <strings.h>
32   | #include <libgen.h>
33   | #include <glib.h>
34   | 
35   | #include "isnic.h"
36   | #include "bitmask.h"
37   | #include "which_keytypes.h"
38   | #include "memwrap.h"
39   | 
40   | 
41   | #define DOMAINNAME "^[ ]*[a-zA-Z0-9--]*(\\.[a-zA-Z0-9--]+)*[ ]*$"
42   | 
43   | #define LEN_MIN 0
44   | #define LEN_MAX 32
45   | 
46   | #define NETLEN 16
47   | #define NETQUADS 4
48   | #define NETQUAD_MIN 0
49   | #define NETQUAD_MAX 255
50   | 
51   | #define ASNUM_MIN 1
52   | #define ASNUM_MAX 65535
53   | #define ASNUM_NUMOFFSET 2   /* XXX - (This is really kludgy!) Offset to the number bit of ASNUM */
54   | 
55   | #define VALIDIP6 "^[0-9A-F]{1,4}(:[0-9A-F]{1,4}){7}$"
56   | /*
57   |   XXX Why doesn't this work?
58   | #define NET "^([0-9]{1,3}.){4}$"
59   | */
60   | #define NET "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"
61   | 
62   | #define ASNUM "^AS[1-9]+[0-9]*$"
63   | 
64   | #define NETNAME "^[A-Z][A-Z0-9-]*$"
65   | 
66   | #define MAINTAINER "^[A-Z][A-Z0-9-]*$"
67   | 
68   | #define LIMERICK "^LIM-[A-Z0-9-]+$"
69   | 
70   | #define KEYCERT "^PGPKEY-[0-9A-F]{8}$"
71   | 
72   | #define ASMACRO "^AS-[A-Z]+$"
73   | 
74   | #define ROUTESETNAME "^RS-[A-Z0-9-]*$"
75   | 
76   | #define ASSETNAME "^AS-[A-Z0-9-]*$"
77   | 
78   | #define AUTONICPREFIXREGULAR "^AUTO-"
79   | 
80   | /*
81   |   XXX This seems to be the same as the Perl code.  But I don't see where a " " is allowed for.
82   |   I.e. Perl -> ^[a-zA-Z][\w\-\.\'\|\`]*$
83   |   Does \w include [ ;:,?/}{()+*#] ?
84   | #define NAME_B "^[a-zA-Z][a-zA-Z_0-9.'|`-]*$"
85   | */
86   | #define NAME_B "^[a-zA-Z][a-zA-Z_0-9.'|`;:,?/}{()+*#&-]*$"
87   | 
88   | #define PHONE_A "^[ ]*[+][0-9 ]*[(]{0,1}[0-9 -]+[)]{0,1}[0-9 -]*(ext\\.){0,1}[0-9 ]*$"
89   | 
90   | #define VALIDIP4PREFIX
91   | 
92   | #define EMAIL "^[.a-zA-Z0-9--]*@[a-zA-Z0-9--]*(\\.[a-zA-Z0-9--]+)*$"
93   | 
94   | 
95   | /*+ Keytype strings +*/
96   | char * const Keytypes[] = {
97   |   "name",
98   |   "nic_hdl",
99   |   "email",
100  |   "mntner",
101  |   "key_cert",
102  |   "iprange",
103  |   "ipprefix",
104  |   "ip6prefix",
105  |   "netname",
106  |   "net6name",
107  |   "autnum",
108  |   "assetname",
109  |   "routesetname",
110  |   "domain",
111  |   "hostname",
112  |   "limerick",
113  |   NULL
114  | }; /* Keytypes[] */
115  | 
116  | /*+ Peerword strings +*/
117  | const char * Peerword[] = {
118  |                "EGP",
119  |                "BGP",
120  |                "BGP4",
121  |                "IDRP",
122  |                "IGP",
123  |                "HELLO",
124  |                "IGRP",
125  |                "EIGRP",
126  |                "OSPF",
127  |                "ISIS",
128  |                "RIP",
129  |                "RIP2",
130  |                "OTHER",
131  |                ""
132  | }; /* Peerword[] */
133  | 
134  | static int matching(char *string, char left_c, char right_c) { 
135  |   int result;
136  | 
137  |   int i;
138  |   int length;
139  |   int count=0;
140  | 
141  |   length = strlen(string);
142  | 
143  |   for(i=0; i < length; i++) {
144  | /*
145  |     switch ((int)string[i]) {
146  |       case left_c:
147  |       break;
148  | 
149  |       case right_c:
150  |         count--;
151  |       break;
152  | 
153  |       default:
154  |     }
155  | */
156  |     if (string[i] == left_c) {
157  |       count++;
158  |     }
159  |     if (string[i] == right_c) {
160  |       count--;
161  |     }
162  |   }
163  | 
164  |   if (count == 0) {
165  |     /* Matching characters */
166  |     result=1;
167  |   }
168  |   else {
169  |     /* Non-matching characters */
170  |     result=0;
171  |   }
172  | 
173  |   return result;
174  | 
175  | } /* matching() */
176  | 
177  | 
178  | static int perform_regex_test(const char *pattern, char *string) {
179  |   int match;
180  | 
181  |   char *re;
182  | 
183  |   re = regcmp(pattern, (char*)0);
184  |   if (regex(re, string) == NULL) {
185  |     match = 0;
186  |   }
187  |   else {
188  |     match = 1;
189  |   }
190  | 
191  |   wr_free(re);
192  | 
193  |   return match;
194  | } /* perform_regex_test() */
195  | 
196  | static int isipv6prefix_a(char *string) {
197  | /*
198  |   printf("isipv6prefix\n");
199  | */
200  |   int result='-';
201  | 
202  |   result = perform_regex_test(VALIDIP6, string);
203  | 
204  |   return result;
205  | }
206  | 
207  | static int isipv6prefix(char *string) {
208  | /*
209  |   printf("isipv6prefix\n");
210  | */
211  |   int result='-';
212  | 
213  |   return result;
214  | }
215  | 
216  | static int islen(char *string) {
217  |   /*
218  |   printf("islen\n");
219  | */
220  |   int result='-';
221  |   int length;
222  | 
223  |   length = strlen(string);
224  | 
225  |   if ((length <= LEN_MAX) && (length >= LEN_MIN)) {
226  |     /* A valid length */
227  |     result=1;
228  |   }
229  |   else if (length < 0) {
230  |     /* An invalid length */
231  |     result=-1;
232  |   }
233  |   else {
234  |     /* An invalid length */
235  |     result=0;
236  |   }
237  | 
238  |   return result;
239  | }
240  | 
241  | static int isnet(char *string) {
242  |   /*
243  |   printf("isnet\n");
244  | */
245  |   int result='-';
246  |   int i;
247  |   int quad_value;
248  |   gchar **quad_value_strs;
249  | 
250  |   /* First check if the string is in quad form */
251  |   result = perform_regex_test(NET, string);
252  | 
253  |   /* Then check if the quad values are between NETQUAD_MIN and NETQUAD_MAX */
254  |   if (result == 1) {
255  |     quad_value_strs = g_strsplit(string, ".", 0);
256  |     for (i=0; quad_value_strs[i] != NULL; i++) {
257  |       quad_value = atoi(quad_value_strs[i]);
258  |       if ((quad_value < NETQUAD_MIN) || (quad_value > NETQUAD_MAX)) {
259  |         /* an invalid value */
260  |         result=0;
261  |         break;
262  |       }
263  |     }
264  |   }
265  | 
266  |   return result;
267  | }
268  | 
269  | static int isasnum(char *string) {
270  |   /*
271  |   printf("isasnum\n");
272  | */
273  |   int result='-';
274  |   int as_value;
275  | 
276  |   /* First check if the string matches an ASNUM */
277  |   result = perform_regex_test(ASNUM, string);
278  | 
279  |   /* Then check if the value is between ASNUM_MIN and ASNUM_MAX */
280  |   if (result == 1) {
281  |     as_value = atoi(string+ASNUM_NUMOFFSET);
282  |     if ((as_value < ASNUM_MIN) || (as_value > ASNUM_MAX)) {
283  |       /* an invalid value */
284  |       result=0;
285  |     }
286  |   }
287  |   
288  |   return result;
289  | }
290  | 
291  | static int isnetname(char *string) {
292  |   /*
293  |   printf("isnetname\n");
294  | */
295  |   int result='-';
296  | 
297  |   result = perform_regex_test(NETNAME, string);
298  | 
299  |   return result;
300  | }
301  | 
302  | static int ismaintainer(char *string) {
303  |   /*
304  |   printf("ismaintainer\n");
305  | */
306  |   int result='-';
307  | 
308  |   result = perform_regex_test(MAINTAINER, string);
309  | 
310  |   return result;
311  | }
312  | 
313  | static int islimerick(char *string) {
314  |   /*
315  |   printf("islimerick\n");
316  | */
317  |   int result='-';
318  | 
319  |   result = perform_regex_test(LIMERICK, string);
320  | 
321  |   return result;
322  | }
323  | 
324  | /*******************************************************
325  |     # the problem is as follows:
326  |     #
327  |     # we can never find out which NIC handles are possible on the
328  |     # globe since we don't know that they exist
329  |     #
330  |     # we want to solve this with once with DNS :
331  |     #
332  |     # RIPE.registries.int     CNAME whois.ripe.net
333  |     # InterNIC.registries.int CNAME whois.internic.net
334  |     # and so on...
335  | 
336  |     #
337  |     # 1) it first does a basic syntax check
338  |     #
339  |     #    notes:
340  |     #
341  |     #    - catches InterNIC handles
342  |     #    - catches the JP|JP-JP APNIC exceptions
343  |     #    - limits the number of initials to three with a good reason:
344  |     #      we have a much better chance to find syntax errors like:
345  |     #      RIPE-DK13 and other problems like this
346  |     #
347  |     # 2) checks for valid suffixes
348  |     #    - all 'source:' attribute values from sites that we mirror
349  |     #      are allowed
350  |     #    - country codes are allowed for APNIC compatibility
351  |     #    - APNIC AP|CC-AU exceptions are handled correctly
352  |     #    - -ORG organization InterNIC handles
353  |     #    - -ARIN ARIN handles
354  |     #    - -ORG-ARIN ARIN handles
355  | ********************************************************/
356  | static int isnichandle_joao(char *nichdl) {
357  | 
358  |   char *regexp, *match;
359  |   char ret[1024];
360  |   char *suffix;
361  | 
362  |   int i;
363  | 
364  | /* set ret to the empty string */
365  |   ret[0]='\0';
366  | /** Return if there are any lower case characters */
367  | 
368  |   regexp = regcmp("[a-z]",(char *)0);
369  |   match = regex(regexp,nichdl);
370  |   wr_free(regexp);
371  |   if (match) return 0;
372  | 
373  | /* 
374  |   # Japanese NIC handles
375  |   #
376  |   # leading zeros in the number part *are* allowed
377  |   #
378  |   # e.g. AB021JP AB199JP-JP
379  |   #
380  | */
381  |   regexp = regcmp("[A-Z]{2}[0-9]{3}JP(-JP){0,1}",(char *)0);
382  |   match =  regex(regexp,nichdl);
383  |   wr_free(regexp);
384  |   if (match) return 1;
385  | 
386  | /*
387  |   # Standard NIC handles
388  |   #
389  |   # leading zeros in the number part are *not* allowed
390  |   #
391  |   # InterNIC - TBQ, IP4
392  |   # RIPE format - AB1-RIPE
393  |   # APNIC use two letter country code suffix
394  |   # Austraila have used -1-AU, -2-AU, -CC-AU suffix.
395  |   # Internic used -ORG suffix
396  |   # ARIN use -ARIN suffix
397  |   # ARIN also use -ORG-ARIN suffix
398  |   #
399  | */
400  |   regexp = regcmp("^[A-Z]{2,4}([1-9][0-9]{0,5}){0,1}((-[^ ]+){0,1})$0$",(char *)0);
401  |   match =  regex(regexp,nichdl,ret);
402  | 
403  |   wr_free(regexp);
404  | 
405  |   if (match == NULL) {
406  |     return 0;
407  |   } else {
408  |     if (ret[0] == '\0') {
409  |       return 1;
410  |     } else {
411  | /*   strip leading '-' */
412  |       suffix = ret+1;
413  | /* suffix of local sources */
414  |       for (i=0;i<=NUM_NICPOSTFIX;i++) {
415  |         if ( !strcmp(suffix,nicpostfix[i]) ) {
416  |           return 1;
417  |         }
418  |       }
419  | /* country codes */
420  |       for (i=0;i<NUM_COUNTRIES;i++) {
421  |         if ( !strcmp(suffix,countries[i]) ) {
422  |           return 1;
423  |         }
424  |       }
425  | /* special suffix */
426  |       for (i=0;i<NUM_SPECIAL;i++) {
427  |         if ( !strcmp(suffix,special[i]) ) {
428  |           return 1;
429  |         }
430  |       }
431  |     }
432  |   }
433  |   return 0;
434  | } /* isnichandle_joao() */
435  | 
436  | 
437  | static int isnichandle(char *string) {
438  |   return isnichandle_joao(string);
439  | }
440  | 
441  | static int isaskeyword(char *string) {
442  |   /*
443  |   printf("isaskeyword\n");
444  | */
445  |   int result='-';
446  | 
447  |   return result;
448  | }
449  | 
450  | static int isasmacro(char *string) {
451  |   /*
452  |   printf("isasmacro\n");
453  | */
454  |   int result='-';
455  | 
456  |   result = perform_regex_test(ASMACRO, string);
457  | 
458  |   return result;
459  | }
460  | 
461  | static int isclnskeyword(char *string) {
462  |   /*
463  |   printf("isclnskeyword\n");
464  | */
465  |   int result='-';
466  | 
467  |   return result;
468  | }
469  | 
470  | static int ispeerkeyword(char *string) {
471  |   /*
472  |   printf("ispeerkeyword\n");
473  | */
474  |   int result='-';
475  |   int i;
476  | 
477  |   result=0;
478  |   for (i=0; Peerword[i] != ""; i++) {
479  |     if ( strcmp(Peerword[i], string) == 0 ) {
480  |       result=1;
481  |       break;
482  |     }
483  |   }
484  | 
485  |   return result;
486  | }
487  | 
488  | static int isnetlist(char *string) {
489  |   /*
490  |   printf("isnetlist\n");
491  | */
492  |   int result='-';
493  | 
494  |   return result;
495  | }
496  | 
497  | static int iscommunity(char *string) {
498  |   /*
499  |   printf("iscommunity\n");
500  | */
501  |   int result='-';
502  | 
503  |   return result;
504  | }
505  | 
506  | static int isaspref(char *string) {
507  |   /*
508  |   printf("isaspref\n");
509  | */
510  |   int result='-';
511  | 
512  |   return result;
513  | }
514  | 
515  | static int isnetnum(char *string) {
516  |   /*
517  |   printf("isnetnum\n");
518  | */
519  |   int result='-';
520  | 
521  |   /* XXX - I don't see the difference between isnet and isnetnum */
522  |   result=isnet(string);
523  | 
524  |   return result;
525  | }
526  | 
527  | static int isipaddr(char *string) {
528  |   /*
529  |   printf("isipaddr\n");
530  | */
531  |   int result='-';
532  | 
533  |   return result;
534  | }
535  | 
536  | static int ismask(char *string) {
537  |   /*
538  |   printf("ismask\n");
539  | */
540  |   int result='-';
541  | 
542  |   return result;
543  | }
544  | 
545  | static int isclnsprefix(char *string) {
546  |   /*
547  |   printf("isclnsprefix\n");
548  | */
549  |   int result='-';
550  | 
551  |   return result;
552  | }
553  | 
554  | static int issubdomname(char *string) {
555  |   /*
556  |   printf("issubdomname\n");
557  | */
558  |   int result='-';
559  | 
560  |   result = perform_regex_test(DOMAINNAME, string);
561  | 
562  |   return result;
563  | }
564  | 
565  | static int isdomname(char *string) {
566  |   /*
567  |   printf("isdomname\n");
568  | */
569  |   int result='-';
570  | 
571  |   result = perform_regex_test(DOMAINNAME, string);
572  | 
573  |   return result;
574  | }
575  | 
576  | /*
577  |  I split the isname up into isname_a & isname_b.  And created isname_ab to join them together.
578  |   - So I can test it properly.  -ottrey
579  |  */
580  | static int isname_a(char *string) {
581  |   /*
582  |   printf("isname_a\n");
583  | */
584  |   int result='-';
585  | 
586  |   result = perform_regex_test(AUTONICPREFIXREGULAR, string);
587  | 
588  |   return result;
589  | }
590  | 
591  | static int isname_b(char *string) {
592  |   /*
593  |   printf("isname_b\n");
594  | */
595  |   int result='-';
596  | 
597  |   result = perform_regex_test(NAME_B, string);
598  | 
599  |   return result;
600  | }
601  | 
602  | static int isname_ab(char *string) {
603  |   /*
604  |   printf("isname_ab\n");
605  | */
606  |   int result='-';
607  | 
608  |   /* Note: the different logic here because I use 0 to be a match and 1 to not be a match.
609  |      The Perl code uses the opposite. - ottrey */
610  |   result = !(isname_a(string) && !isname_b(string));
611  | 
612  |   return result;
613  | }
614  | 
615  | static int isname(char *string) {
616  |   /*
617  |   printf("isname\n");
618  | */
619  |   int result='-';
620  | 
621  |   return result;
622  | }
623  | 
624  | static int isphone_a(char *string) {
625  |   /*
626  |   printf("isphone_a\n");
627  | */
628  |   int result='-';
629  | 
630  |   result = perform_regex_test(PHONE_A, string);
631  |   
632  |   return result;
633  | }
634  | 
635  | static int isparen(char *string) {
636  |   /*
637  |   printf("isparen\n");
638  | */
639  |   int result='-';
640  | 
641  |   result=matching(string, '(', ')');
642  | 
643  |   return result;
644  | }
645  | 
646  | static int isphone_b(char *string) {
647  |   /*
648  |   printf("isphone_b\n");
649  | */
650  |   int result='-';
651  | 
652  |   result = isparen(string);
653  | 
654  |   return result;
655  | }
656  | 
657  | static int isphone_ab(char *string) {
658  |   /*
659  |   printf("isphone_ab\n");
660  | */
661  |   int result='-';
662  | 
663  |   /* Note: the different logic here because I use 0 to be a match and 1 to not be a match.
664  |      The Perl code uses the opposite. - ottrey */
665  |   result = !(!isphone_a(string) && !isphone_b(string));
666  | 
667  |   return result;
668  | }
669  | 
670  | static int isphone(char *string) {
671  |   /*
672  |   printf("isphone\n");
673  | */
674  |   int result='-';
675  | 
676  |   return result;
677  | }
678  | 
679  | static int isemail(char *string) {
680  |   /*
681  |   printf("isemail\n");
682  | */
683  |   int result='-';
684  | 
685  |   result = perform_regex_test(EMAIL, string);
686  |   
687  |   return result;
688  | }
689  | 
690  | static int isbrace(char *string) {
691  |   /*
692  |   printf("isbrace\n");
693  | */
694  |   int result='-';
695  | 
696  |   result=matching(string, '{', '}');
697  | 
698  |   return result;
699  | }
700  | 
701  | 
702  | 
703  | 
704  | 
705  | 
706  | 
707  | 
708  | 
709  | 
710  | 
711  | 
712  | 
713  | /* ****** The new bunch  ******* */
714  | static int wk_is_name(char *key) {
715  | 
716  |   /* Everything matches to name */
717  |   return 1;
718  | 
719  | } /* wk_is_name() */
720  | 
721  | static int wk_is_nic_hdl(char *key) {
722  | 
723  |   return isnichandle(key);
724  | 
725  | } /* wk_is_nic_hdl() */
726  | 
727  | static int wk_is_email(char *key) {
728  | 
729  |   return isemail(key);
730  | 
731  | } /* wk_is_email() */
732  | 
733  | static int wk_is_mntner(char *key) {
734  | 
735  |   return ismaintainer(key);
736  | 
737  | } /* wk_is_mntner() */
738  | 
739  | static int wk_is_key_cert(char *key) {
740  |   int result=1;
741  | 
742  |   result = perform_regex_test(KEYCERT, key);
743  | 
744  |   return result;
745  | 
746  | } /* wk_is_key_cert() */
747  | 
748  | static int wk_is_iprange(char *key) {
749  |   int result=1;
750  | 
751  |   /* XXX This is not very strict - but will cut out a lot of invalids */
752  |   /* XXX And has been given a bad name and does a few things. */
753  |   /* XXX This needs work. */
754  | #define IPRANGE "^[0-9./ -]*$"
755  |   result = perform_regex_test(IPRANGE, key);
756  | 
757  |   return result;
758  | 
759  | } /* wk_is_iprange() */
760  | 
761  | static int wk_is_ipprefix(char *key) {
762  |   int result=1;
763  | 
764  |   /* XXX INSERT check here! */
765  |   return result;
766  | 
767  | } /* wk_is_iprange() */
768  | 
769  | static int wk_is_ip6prefix(char *key) {
770  | 
771  |   return isipv6prefix_a(key);
772  | 
773  | } /* wk_is_ip6prefix() */
774  | 
775  | static int wk_is_netname(char *key) {
776  |   
777  |   return isnetname(key);
778  | 
779  | } /* wk_is_netname() */
780  | 
781  | /* XXX Note: This function uses the same call as wk_is_netname(). */
782  | static int wk_is_net6name(char *key) {
783  |   
784  |   return isnetname(key);
785  | 
786  | } /* wk_is_netname() */
787  | 
788  | static int wk_is_autnum(char *key) {
789  | 
790  |   return isasnum(key);
791  | 
792  | } /* wk_is_autnum() */
793  | 
794  | static int wk_is_assetname(char *key) {
795  |   int result=1;
796  | 
797  |   result = perform_regex_test(ASSETNAME, key);
798  | 
799  |   return result;
800  | 
801  | } /* wk_is_assetname() */
802  | 
803  | static int wk_is_routesetname(char *key) {
804  |   int result=1;
805  | 
806  |   result = perform_regex_test(ROUTESETNAME, key);
807  | 
808  |   return result;
809  | 
810  | } /* wk_is_routesetname() */
811  | 
812  | static int wk_is_domain(char *key) {
813  | 
814  |   return isdomname(key);
815  | 
816  | } /* wk_is_domname() */
817  | 
818  | static int wk_is_hostname(char *key) {
819  | 
820  |   /* XXX Why is there a hostname & a domainname? */
821  |   /* Answer - hostname can be a domainname or an IP */
822  |   return (isdomname(key) || wk_is_iprange(key));
823  | 
824  | } /* wk_is_hostname() */
825  | 
826  | static int wk_is_limerick(char *key) {
827  | 
828  |   return islimerick(key);
829  | 
830  | } /* wk_is_limerick() */
831  | 
832  | 
833  | /* WK_to_string() */
834  | /*++++++++++++++++++++++++++++++++++++++
835  |   Convert the which keytypes bitmap into a string.
836  | 
837  |   mask_t wk The which keytypes mask to be converted.
838  | 
839  |   More:
840  |   +html+ <PRE>
841  |   Authors:
842  |         ottrey
843  |   +html+ </PRE><DL COMPACT>
844  |   +html+ <DT>Online References:
845  |   +html+ <DD><UL>
846  |   +html+ </UL></DL>
847  | 
848  |   ++++++++++++++++++++++++++++++++++++++*/
849  | char *WK_to_string(mask_t wk) {
850  | 
851  |   return MA_to_string(wk, Keytypes);
852  | 
853  | } /* WK_to_string() */
854  | 
855  | 
856  | /* WK_new() */
857  | /*++++++++++++++++++++++++++++++++++++++
858  |   Create a new which keytypes bitmap.
859  | 
860  |   char *key The key to be examined.
861  | 
862  |   More:
863  |   +html+ <PRE>
864  |   Authors:
865  |         ottrey
866  |   +html+ </PRE><DL COMPACT>
867  |   +html+ <DT>Online References:
868  |   +html+ <DD><UL>
869  |   +html+ </UL></DL>
870  | 
871  |   ++++++++++++++++++++++++++++++++++++++*/
872  | mask_t WK_new(char *key) {
873  |   mask_t wk; 
874  | 
875  |   wk = MA_new(MA_END);
876  | 
877  |   MA_set(&wk, WK_NAME,         wk_is_name(key));
878  |   MA_set(&wk, WK_NIC_HDL,      wk_is_nic_hdl(key));
879  |   MA_set(&wk, WK_EMAIL,        wk_is_email(key));
880  |   MA_set(&wk, WK_MNTNER,       wk_is_mntner(key));
881  |   MA_set(&wk, WK_KEY_CERT,     wk_is_key_cert(key));
882  |   MA_set(&wk, WK_IPRANGE,      wk_is_iprange(key));
883  |   MA_set(&wk, WK_IPPREFIX,     wk_is_ipprefix(key));
884  |   MA_set(&wk, WK_IP6PREFIX,    wk_is_ip6prefix(key));
885  |   MA_set(&wk, WK_NETNAME,      wk_is_netname(key));
886  |   MA_set(&wk, WK_NET6NAME,     wk_is_net6name(key));
887  |   MA_set(&wk, WK_AUTNUM,       wk_is_autnum(key));
888  |   MA_set(&wk, WK_ASSETNAME,    wk_is_assetname(key));
889  |   MA_set(&wk, WK_ROUTESETNAME, wk_is_routesetname(key));
890  |   MA_set(&wk, WK_DOMAIN,       wk_is_domain(key));
891  |   MA_set(&wk, WK_HOSTNAME,     wk_is_hostname(key));
892  |   MA_set(&wk, WK_LIMERICK,     wk_is_limerick(key));
893  | 
894  |   return wk;
895  | 
896  | } /* WK_new() */