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