1    | /***************************************
2    |   $Revision: 1.9 $
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 <strings.h>
31   | #include <libgen.h>
32   | #include <glib.h>
33   | 
34   | #include "isnic.h"
35   | #include "bitmask.h"
36   | #include "which_keytypes.h"
37   | 
38   | 
39   | #define DOMAINNAME "^[ ]*[a-zA-Z0-9--]*(\\.[a-zA-Z0-9--]+)*[ ]*$"
40   | 
41   | #define LEN_MIN 0
42   | #define LEN_MAX 32
43   | 
44   | #define NETLEN 16
45   | #define NETQUADS 4
46   | #define NETQUAD_MIN 0
47   | #define NETQUAD_MAX 255
48   | 
49   | #define ASNUM_MIN 1
50   | #define ASNUM_MAX 65535
51   | #define ASNUM_NUMOFFSET 2   /* XXX - (This is really kludgy!) Offset to the number bit of ASNUM */
52   | 
53   | #define VALIDIP6 "^[0-9A-F]{1,4}(:[0-9A-F]{1,4}){7}$"
54   | /*
55   |   XXX Why doesn't this work?
56   | #define NET "^([0-9]{1,3}.){4}$"
57   | */
58   | #define NET "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"
59   | 
60   | #define ASNUM "^AS[1-9]+[0-9]*$"
61   | 
62   | #define NETNAME "^[A-Z][A-Z0-9-]*$"
63   | 
64   | #define MAINTAINER "^[A-Z][A-Z0-9-]*$"
65   | 
66   | #define LIMERICK "^LIM-[A-Z0-9-]+$"
67   | 
68   | #define KEYCERT "^PGPKEY-[0-9A-F]{8}$"
69   | 
70   | #define ASMACRO "^AS-[A-Z]+$"
71   | 
72   | #define ROUTESETNAME "^RS-[A-Z0-9-]*$"
73   | 
74   | #define ASSETNAME "^AS-[A-Z0-9-]*$"
75   | 
76   | #define AUTONICPREFIXREGULAR "^AUTO-"
77   | 
78   | /*
79   |   XXX This seems to be the same as the Perl code.  But I don't see where a " " is allowed for.
80   |   I.e. Perl -> ^[a-zA-Z][\w\-\.\'\|\`]*$
81   |   Does \w include [ ;:,?/}{()+*#] ?
82   | #define NAME_B "^[a-zA-Z][a-zA-Z_0-9.'|`-]*$"
83   | */
84   | #define NAME_B "^[a-zA-Z][a-zA-Z_0-9.'|`;:,?/}{()+*#&-]*$"
85   | 
86   | #define PHONE_A "^[ ]*[+][0-9 ]*[(]{0,1}[0-9 -]+[)]{0,1}[0-9 -]*(ext\\.){0,1}[0-9 ]*$"
87   | 
88   | #define VALIDIP4PREFIX
89   | 
90   | #define EMAIL "^[.a-zA-Z0-9--]*@[a-zA-Z0-9--]*(\\.[a-zA-Z0-9--]+)*$"
91   | 
92   | 
93   | /*+ Keytype strings +*/
94   | char * const Keytypes[] = {
95   |   "name",
96   |   "nic_hdl",
97   |   "email",
98   |   "mntner",
99   |   "key_cert",
100  |   "iprange",
101  |   "ipprefix",
102  |   "ip6prefix",
103  |   "netname",
104  |   "net6name",
105  |   "autnum",
106  |   "assetname",
107  |   "routesetname",
108  |   "domain",
109  |   "hostname",
110  |   "limerick",
111  |   NULL
112  | }; /* Keytypes[] */
113  | 
114  | /*+ Peerword strings +*/
115  | const char * Peerword[] = {
116  |                "EGP",
117  |                "BGP",
118  |                "BGP4",
119  |                "IDRP",
120  |                "IGP",
121  |                "HELLO",
122  |                "IGRP",
123  |                "EIGRP",
124  |                "OSPF",
125  |                "ISIS",
126  |                "RIP",
127  |                "RIP2",
128  |                "OTHER",
129  |                ""
130  | }; /* Peerword[] */
131  | 
132  | static int matching(char *string, char left_c, char right_c) { 
133  |   int result;
134  | 
135  |   int i;
136  |   int length;
137  |   int count=0;
138  | 
139  |   length = strlen(string);
140  | 
141  |   for(i=0; i < length; i++) {
142  | /*
143  |     switch ((int)string[i]) {
144  |       case left_c:
145  |       break;
146  | 
147  |       case right_c:
148  |         count--;
149  |       break;
150  | 
151  |       default:
152  |     }
153  | */
154  |     if (string[i] == left_c) {
155  |       count++;
156  |     }
157  |     if (string[i] == right_c) {
158  |       count--;
159  |     }
160  |   }
161  | 
162  |   if (count == 0) {
163  |     /* Matching characters */
164  |     result=1;
165  |   }
166  |   else {
167  |     /* Non-matching characters */
168  |     result=0;
169  |   }
170  | 
171  |   return result;
172  | 
173  | } /* matching() */
174  | 
175  | 
176  | static int perform_regex_test(const char *pattern, char *string) {
177  |   char *return_value;
178  |   int match;
179  | 
180  |   char *re;
181  | 
182  |   re = regcmp(pattern, (char*)0);
183  |   if (regex(re, string) == NULL) {
184  |     match = 0;
185  |   }
186  |   else {
187  |     match = 1;
188  |   }
189  | 
190  |   free(re);
191  | 
192  |   return match;
193  | 
194  | }
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  |   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  |   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  |   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  | static int isphone_b(char *string) {
635  |   /*
636  |   printf("isphone_b\n");
637  | */
638  |   int result='-';
639  | 
640  |   result = isparen(string);
641  | 
642  |   return result;
643  | }
644  | static int isphone_ab(char *string) {
645  |   /*
646  |   printf("isphone_ab\n");
647  | */
648  |   int result='-';
649  | 
650  |   /* Note: the different logic here because I use 0 to be a match and 1 to not be a match.
651  |      The Perl code uses the opposite. - ottrey */
652  |   result = !(!isphone_a(string) && !isphone_b(string));
653  | 
654  |   return result;
655  | }
656  | static int isphone(char *string) {
657  |   /*
658  |   printf("isphone\n");
659  | */
660  |   int result='-';
661  | 
662  |   return result;
663  | }
664  | 
665  | static int isemail(char *string) {
666  |   /*
667  |   printf("isemail\n");
668  | */
669  |   int result='-';
670  | 
671  |   result = perform_regex_test(EMAIL, string);
672  |   
673  |   return result;
674  | }
675  | 
676  | static int isbrace(char *string) {
677  |   /*
678  |   printf("isbrace\n");
679  | */
680  |   int result='-';
681  | 
682  |   result=matching(string, '{', '}');
683  | 
684  |   return result;
685  | }
686  | 
687  | static int isparen(char *string) {
688  |   /*
689  |   printf("isparen\n");
690  | */
691  |   int result='-';
692  | 
693  |   result=matching(string, '(', ')');
694  | 
695  |   return result;
696  | }
697  | 
698  | 
699  | 
700  | 
701  | 
702  | 
703  | 
704  | 
705  | 
706  | 
707  | 
708  | 
709  | 
710  | /* ****** The new bunch  ******* */
711  | static int wk_is_name(char *key) {
712  | 
713  |   /* Everything matches to name */
714  |   return 1;
715  | 
716  | } /* wk_is_name() */
717  | 
718  | static int wk_is_nic_hdl(char *key) {
719  | 
720  |   return isnichandle(key);
721  | 
722  | } /* wk_is_nic_hdl() */
723  | 
724  | static int wk_is_email(char *key) {
725  | 
726  |   return isemail(key);
727  | 
728  | } /* wk_is_email() */
729  | 
730  | static int wk_is_mntner(char *key) {
731  | 
732  |   return ismaintainer(key);
733  | 
734  | } /* wk_is_mntner() */
735  | 
736  | static int wk_is_key_cert(char *key) {
737  |   int result=1;
738  | 
739  |   result = perform_regex_test(KEYCERT, key);
740  | 
741  |   return result;
742  | 
743  | } /* wk_is_key_cert() */
744  | 
745  | static int wk_is_iprange(char *key) {
746  |   int result=1;
747  | 
748  |   /* XXX This is not very strict - but will cut out a lot of invalids */
749  |   /* XXX And has been given a bad name and does a few things. */
750  |   /* XXX This needs work. */
751  | #define IPRANGE "^[0-9./ -]*$"
752  |   result = perform_regex_test(IPRANGE, key);
753  | 
754  |   return result;
755  | 
756  | } /* wk_is_iprange() */
757  | 
758  | static int wk_is_ipprefix(char *key) {
759  |   int result=1;
760  | 
761  |   /* XXX INSERT check here! */
762  |   return result;
763  | 
764  | } /* wk_is_iprange() */
765  | 
766  | static int wk_is_ip6prefix(char *key) {
767  | 
768  |   return isipv6prefix_a(key);
769  | 
770  | } /* wk_is_ip6prefix() */
771  | 
772  | static int wk_is_netname(char *key) {
773  |   
774  |   return isnetname(key);
775  | 
776  | } /* wk_is_netname() */
777  | 
778  | /* XXX Note: This function uses the same call as wk_is_netname(). */
779  | static int wk_is_net6name(char *key) {
780  |   
781  |   return isnetname(key);
782  | 
783  | } /* wk_is_netname() */
784  | 
785  | static int wk_is_autnum(char *key) {
786  | 
787  |   return isasnum(key);
788  | 
789  | } /* wk_is_autnum() */
790  | 
791  | static int wk_is_assetname(char *key) {
792  |   int result=1;
793  | 
794  |   result = perform_regex_test(ASSETNAME, key);
795  | 
796  |   return result;
797  | 
798  | } /* wk_is_assetname() */
799  | 
800  | static int wk_is_routesetname(char *key) {
801  |   int result=1;
802  | 
803  |   result = perform_regex_test(ROUTESETNAME, key);
804  | 
805  |   return result;
806  | 
807  | } /* wk_is_routesetname() */
808  | 
809  | static int wk_is_domain(char *key) {
810  | 
811  |   return isdomname(key);
812  | 
813  | } /* wk_is_domname() */
814  | 
815  | static int wk_is_hostname(char *key) {
816  | 
817  |   /* XXX Why is there a hostname & a domainname? */
818  |   /* Answer - hostname can be a domainname or an IP */
819  |   return (isdomname(key) || wk_is_iprange(key));
820  | 
821  | } /* wk_is_hostname() */
822  | 
823  | static int wk_is_limerick(char *key) {
824  | 
825  |   return islimerick(key);
826  | 
827  | } /* wk_is_limerick() */
828  | 
829  | 
830  | /* WK_to_string() */
831  | /*++++++++++++++++++++++++++++++++++++++
832  |   Convert the which keytypes bitmap into a string.
833  | 
834  |   mask_t wk The which keytypes mask to be converted.
835  | 
836  |   More:
837  |   +html+ <PRE>
838  |   Authors:
839  |         ottrey
840  |   +html+ </PRE><DL COMPACT>
841  |   +html+ <DT>Online References:
842  |   +html+ <DD><UL>
843  |   +html+ </UL></DL>
844  | 
845  |   ++++++++++++++++++++++++++++++++++++++*/
846  | char *WK_to_string(mask_t wk) {
847  | 
848  |   return MA_to_string(wk, Keytypes);
849  | 
850  | } /* WK_to_string() */
851  | 
852  | 
853  | /* WK_new() */
854  | /*++++++++++++++++++++++++++++++++++++++
855  |   Create a new which keytypes bitmap.
856  | 
857  |   char *key The key to be examined.
858  | 
859  |   More:
860  |   +html+ <PRE>
861  |   Authors:
862  |         ottrey
863  |   +html+ </PRE><DL COMPACT>
864  |   +html+ <DT>Online References:
865  |   +html+ <DD><UL>
866  |   +html+ </UL></DL>
867  | 
868  |   ++++++++++++++++++++++++++++++++++++++*/
869  | mask_t WK_new(char *key) {
870  |   mask_t wk; 
871  | 
872  |   wk = MA_new(MA_END);
873  | 
874  |   MA_set(&wk, WK_NAME,         wk_is_name(key));
875  |   MA_set(&wk, WK_NIC_HDL,      wk_is_nic_hdl(key));
876  |   MA_set(&wk, WK_EMAIL,        wk_is_email(key));
877  |   MA_set(&wk, WK_MNTNER,       wk_is_mntner(key));
878  |   MA_set(&wk, WK_KEY_CERT,     wk_is_key_cert(key));
879  |   MA_set(&wk, WK_IPRANGE,      wk_is_iprange(key));
880  |   MA_set(&wk, WK_IPPREFIX,     wk_is_ipprefix(key));
881  |   MA_set(&wk, WK_IP6PREFIX,    wk_is_ip6prefix(key));
882  |   MA_set(&wk, WK_NETNAME,      wk_is_netname(key));
883  |   MA_set(&wk, WK_NET6NAME,     wk_is_net6name(key));
884  |   MA_set(&wk, WK_AUTNUM,       wk_is_autnum(key));
885  |   MA_set(&wk, WK_ASSETNAME,    wk_is_assetname(key));
886  |   MA_set(&wk, WK_ROUTESETNAME, wk_is_routesetname(key));
887  |   MA_set(&wk, WK_DOMAIN,       wk_is_domain(key));
888  |   MA_set(&wk, WK_HOSTNAME,     wk_is_hostname(key));
889  |   MA_set(&wk, WK_LIMERICK,     wk_is_limerick(key));
890  | 
891  |   return wk;
892  | 
893  | } /* WK_new() */