modules/wk/which_keytypes.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. matching
  2. perform_regex_test
  3. isipv6prefix_a
  4. isipv6prefix
  5. islen
  6. isnet
  7. isasnum
  8. isnetname
  9. ismaintainer
  10. islimerick
  11. isnichandle_joao
  12. isnichandle
  13. isaskeyword
  14. isasmacro
  15. isclnskeyword
  16. ispeerkeyword
  17. isnetlist
  18. iscommunity
  19. isaspref
  20. isnetnum
  21. isipaddr
  22. ismask
  23. isclnsprefix
  24. issubdomname
  25. isdomname
  26. isname_a
  27. isname_b
  28. isname_ab
  29. isname
  30. isphone_a
  31. isphone_b
  32. isphone_ab
  33. isphone
  34. isemail
  35. isbrace
  36. isparen
  37. wk_is_name
  38. wk_is_nic_hdl
  39. wk_is_email
  40. wk_is_mntner
  41. wk_is_key_cert
  42. wk_is_iprange
  43. wk_is_ipprefix
  44. wk_is_ip6prefix
  45. wk_is_netname
  46. wk_is_net6name
  47. wk_is_autnum
  48. wk_is_assetname
  49. wk_is_routesetname
  50. wk_is_domain
  51. wk_is_hostname
  52. wk_is_limerick
  53. WK_to_string
  54. WK_new

/***************************************
  $Revision: 1.8 $

  Example code: Determine which keys to look for.
  
  This is based on the C code that was reversed engineered from existing Perl
  code.  (~ottrey/which_table/which_table.c)

  ******************/ /******************
  Copyright (c) 1999                              RIPE NCC
 
  All Rights Reserved
  
  Permission to use, copy, modify, and distribute this software and its
  documentation for any purpose and without fee is hereby granted,
  provided that the above copyright notice appear in all copies and that
  both that copyright notice and this permission notice appear in
  supporting documentation, and that the name of the author not be
  used in advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.
  
  THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  ***************************************/
#include <stdio.h>
#include <strings.h>
#include <libgen.h>
#include "isnic.h"
#include "bitmask.h"
#include "which_keytypes.h"


#define DOMAINNAME "^[ ]*[a-zA-Z0-9--]*(\\.[a-zA-Z0-9--]+)*[ ]*$"

#define LEN_MIN 0
#define LEN_MAX 32

#define NETLEN 16
#define NETQUADS 4
#define NETQUAD_MIN 0
#define NETQUAD_MAX 255

#define ASNUM_MIN 1
#define ASNUM_MAX 65535
#define ASNUM_NUMOFFSET 2   /* XXX - (This is really kludgy!) Offset to the number bit of ASNUM */

#define VALIDIP6 "^[0-9A-F]{1,4}(:[0-9A-F]{1,4}){7}$"
/*
  XXX Why doesn't this work?
#define NET "^([0-9]{1,3}.){4}$"
*/
#define NET "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"

#define ASNUM "^AS[1-9]+[0-9]*$"

#define NETNAME "^[A-Z][A-Z0-9-]*$"

#define MAINTAINER "^[A-Z][A-Z0-9-]*$"

#define LIMERICK "^LIM-[A-Z0-9-]+$"

#define KEYCERT "^PGPKEY-[0-9A-F]{8}$"

#define ASMACRO "^AS-[A-Z]+$"

#define ROUTESETNAME "^RS-[A-Z0-9-]*$"

#define ASSETNAME "^AS-[A-Z0-9-]*$"

#define AUTONICPREFIXREGULAR "^AUTO-"

/*
  XXX This seems to be the same as the Perl code.  But I don't see where a " " is allowed for.
  I.e. Perl -> ^[a-zA-Z][\w\-\.\'\|\`]*$
  Does \w include [ ;:,?/}{()+*#] ?
#define NAME_B "^[a-zA-Z][a-zA-Z_0-9.'|`-]*$"
*/
#define NAME_B "^[a-zA-Z][a-zA-Z_0-9.'|`;:,?/}{()+*#&-]*$"

#define PHONE_A "^[ ]*[+][0-9 ]*[(]{0,1}[0-9 -]+[)]{0,1}[0-9 -]*(ext\\.){0,1}[0-9 ]*$"

#define VALIDIP4PREFIX

#define EMAIL "^[.a-zA-Z0-9--]*@[a-zA-Z0-9--]*(\\.[a-zA-Z0-9--]+)*$"


/*+ Keytype strings +*/
char * const Keytypes[] = {
  "name",
  "nic_hdl",
  "email",
  "mntner",
  "key_cert",
  "iprange",
  "ipprefix",
  "ip6prefix",
  "netname",
  "net6name",
  "autnum",
  "assetname",
  "routesetname",
  "domain",
  "hostname",
  "limerick",
  NULL
}; /* Keytypes[] */

/*+ Peerword strings +*/
const char * Peerword[] = {
               "EGP",
               "BGP",
               "BGP4",
               "IDRP",
               "IGP",
               "HELLO",
               "IGRP",
               "EIGRP",
               "OSPF",
               "ISIS",
               "RIP",
               "RIP2",
               "OTHER",
               ""
}; /* Peerword[] */

static int matching(char *string, char left_c, char right_c) { 
/* [<][>][^][v][top][bottom][index][help] */
  int result;

  int i;
  int length;
  int count=0;

  length = strlen(string);

  for(i=0; i < length; i++) {
/*
    switch ((int)string[i]) {
      case left_c:
      break;

      case right_c:
        count--;
      break;

      default:
    }
*/
    if (string[i] == left_c) {
      count++;
    }
    if (string[i] == right_c) {
      count--;
    }
  }

  if (count == 0) {
    /* Matching characters */
    result=1;
  }
  else {
    /* Non-matching characters */
    result=0;
  }

  return result;

} /* matching() */


static int perform_regex_test(const char *pattern, char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  char *return_value;
  int match;

  char *re;

  re = regcmp(pattern, (char*)0);
  if (regex(re, string) == NULL) {
    match = 0;
  }
  else {
    match = 1;
  }

  free(re);

  return match;

}

static int isipv6prefix_a(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
/*
  printf("isipv6prefix\n");
*/
  int result='-';

  result = perform_regex_test(VALIDIP6, string);

  return result;
}

static int isipv6prefix(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
/*
  printf("isipv6prefix\n");
*/
  int result='-';

  return result;
}

static int islen(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("islen\n");
*/
  int result='-';
  int length;

  length = strlen(string);

  if ((length <= LEN_MAX) && (length >= LEN_MIN)) {
    /* A valid length */
    result=1;
  }
  else if (length < 0) {
    /* An invalid length */
    result=-1;
  }
  else {
    /* An invalid length */
    result=0;
  }

  return result;
}

static int isnet(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isnet\n");
*/
  int result='-';
  char tmp_string[NETLEN];
  int quad_value;
  char *quad_value_str;

  /* First check if the string is in quad form */
  result = perform_regex_test(NET, string);

  /* Then check if the quad values are between NETQUAD_MIN and NETQUAD_MAX */
  if (result == 1) {
    strncpy(tmp_string, string, NETLEN);
    quad_value_str = strtok(tmp_string, ".");
    while (quad_value_str != NULL) {
      quad_value = atoi(quad_value_str);
      if ((quad_value < NETQUAD_MIN) || (quad_value > NETQUAD_MAX)) {
        /* an invalid value */
        result=0;
        break;
      }
      quad_value_str = strtok(NULL, ".");
    }
  }

  return result;
}

static int isasnum(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isasnum\n");
*/
  int result='-';
  int as_value;

  /* First check if the string matches an ASNUM */
  result = perform_regex_test(ASNUM, string);

  /* Then check if the value is between ASNUM_MIN and ASNUM_MAX */
  if (result == 1) {
    as_value = atoi(string+ASNUM_NUMOFFSET);
    if ((as_value < ASNUM_MIN) || (as_value > ASNUM_MAX)) {
      /* an invalid value */
      result=0;
    }
  }
  
  return result;
}

static int isnetname(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isnetname\n");
*/
  int result='-';

  result = perform_regex_test(NETNAME, string);

  return result;
}

static int ismaintainer(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("ismaintainer\n");
*/
  int result='-';

  result = perform_regex_test(MAINTAINER, string);

  return result;
}

static int islimerick(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("islimerick\n");
*/
  int result='-';

  result = perform_regex_test(LIMERICK, string);

  return result;
}

/*******************************************************
    # the problem is as follows:
    #
    # we can never find out which NIC handles are possible on the
    # globe since we don't know that they exist
    #
    # we want to solve this with once with DNS :
    #
    # RIPE.registries.int     CNAME whois.ripe.net
    # InterNIC.registries.int CNAME whois.internic.net
    # and so on...

    #
    # 1) it first does a basic syntax check
    #
    #    notes:
    #
    #    - catches InterNIC handles
    #    - catches the JP|JP-JP APNIC exceptions
    #    - limits the number of initials to three with a good reason:
    #      we have a much better chance to find syntax errors like:
    #      RIPE-DK13 and other problems like this
    #
    # 2) checks for valid suffixes
    #    - all 'source:' attribute values from sites that we mirror
    #      are allowed
    #    - country codes are allowed for APNIC compatibility
    #    - APNIC AP|CC-AU exceptions are handled correctly
    #    - -ORG organization InterNIC handles
    #    - -ARIN ARIN handles
    #    - -ORG-ARIN ARIN handles
********************************************************/
static int isnichandle_joao(char *nichdl) {
/* [<][>][^][v][top][bottom][index][help] */

  char *regexp, *match;
  char ret[1024];
  char *suffix;

  int i;

/* set ret to the empty string *.
  ret[0]='\0';
/** Return if there are any lower case characters */

  regexp = regcmp("[a-z]",(char *)0);
  match = regex(regexp,nichdl);
  free(regexp);
  if (match) return 0;

/* 
  # Japanese NIC handles
  #
  # leading zeros in the number part *are* allowed
  #
  # e.g. AB021JP AB199JP-JP
  #
*/
  regexp = regcmp("[A-Z]{2}[0-9]{3}JP(-JP){0,1}",(char *)0);
  match =  regex(regexp,nichdl);
  free(regexp);
  if (match) return 1;

/*
  # Standard NIC handles
  #
  # leading zeros in the number part are *not* allowed
  #
  # InterNIC - TBQ, IP4
  # RIPE format - AB1-RIPE
  # APNIC use two letter country code suffix
  # Austraila have used -1-AU, -2-AU, -CC-AU suffix.
  # Internic used -ORG suffix
  # ARIN use -ARIN suffix
  # ARIN also use -ORG-ARIN suffix
  #
*/
  regexp = regcmp("^[A-Z]{2,4}([1-9][0-9]{0,5}){0,1}((-[^ ]+){0,1})$0$",(char *)0);
  match =  regex(regexp,nichdl,ret);

  free(regexp);

  if (match == NULL) {
    return 0;
  } else {
    if (ret[0] == '\0') {
      return 1;
    } else {
/*   strip leading '-' */
      suffix = ret+1;
/* suffix of local sources */
      for (i=0;i<=NUM_NICPOSTFIX;i++) {
        if ( !strcmp(suffix,nicpostfix[i]) ) {
          return 1;
        }
      }
/* country codes */
      for (i=0;i<NUM_COUNTRIES;i++) {
        if ( !strcmp(suffix,countries[i]) ) {
          return 1;
        }
      }
/* special suffix */
      for (i=0;i<NUM_SPECIAL;i++) {
        if ( !strcmp(suffix,special[i]) ) {
          return 1;
        }
      }
    }
  }
  return 0;
} /* isnichandle_joao() */


static int isnichandle(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  return isnichandle_joao(string);
}

static int isaskeyword(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isaskeyword\n");
*/
  int result='-';

  return result;
}

static int isasmacro(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isasmacro\n");
*/
  int result='-';

  result = perform_regex_test(ASMACRO, string);

  return result;
}

static int isclnskeyword(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isclnskeyword\n");
*/
  int result='-';

  return result;
}

static int ispeerkeyword(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("ispeerkeyword\n");
*/
  int result='-';
  int i;

  result=0;
  for (i=0; Peerword[i] != ""; i++) {
    if ( strcmp(Peerword[i], string) == 0 ) {
      result=1;
      break;
    }
  }

  return result;
}

static int isnetlist(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isnetlist\n");
*/
  int result='-';

  return result;
}

static int iscommunity(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("iscommunity\n");
*/
  int result='-';

  return result;
}

static int isaspref(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isaspref\n");
*/
  int result='-';

  return result;
}

static int isnetnum(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isnetnum\n");
*/
  int result='-';

  /* XXX - I don't see the difference between isnet and isnetnum */
  result=isnet(string);

  return result;
}

static int isipaddr(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isipaddr\n");
*/
  int result='-';

  return result;
}

static int ismask(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("ismask\n");
*/
  int result='-';

  return result;
}

static int isclnsprefix(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isclnsprefix\n");
*/
  int result='-';

  return result;
}

static int issubdomname(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("issubdomname\n");
*/
  int result='-';

  result = perform_regex_test(DOMAINNAME, string);

  return result;
}

static int isdomname(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isdomname\n");
*/
  int result='-';

  result = perform_regex_test(DOMAINNAME, string);

  return result;
}

/*
 I split the isname up into isname_a & isname_b.  And created isname_ab to join them together.
  - So I can test it properly.  -ottrey
 */
static int isname_a(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isname_a\n");
*/
  int result='-';

  result = perform_regex_test(AUTONICPREFIXREGULAR, string);

  return result;
}

static int isname_b(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isname_b\n");
*/
  int result='-';

  result = perform_regex_test(NAME_B, string);

  return result;
}

static int isname_ab(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isname_ab\n");
*/
  int result='-';

  /* Note: the different logic here because I use 0 to be a match and 1 to not be a match.
     The Perl code uses the opposite. - ottrey */
  result = !(isname_a(string) && !isname_b(string));

  return result;
}

static int isname(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isname\n");
*/
  int result='-';

  return result;
}

static int isphone_a(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isphone_a\n");
*/
  int result='-';

  result = perform_regex_test(PHONE_A, string);
  
  return result;
}
static int isphone_b(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isphone_b\n");
*/
  int result='-';

  result = isparen(string);

  return result;
}
static int isphone_ab(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isphone_ab\n");
*/
  int result='-';

  /* Note: the different logic here because I use 0 to be a match and 1 to not be a match.
     The Perl code uses the opposite. - ottrey */
  result = !(!isphone_a(string) && !isphone_b(string));

  return result;
}
static int isphone(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isphone\n");
*/
  int result='-';

  return result;
}

static int isemail(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isemail\n");
*/
  int result='-';

  result = perform_regex_test(EMAIL, string);
  
  return result;
}

static int isbrace(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isbrace\n");
*/
  int result='-';

  result=matching(string, '{', '}');

  return result;
}

static int isparen(char *string) {
/* [<][>][^][v][top][bottom][index][help] */
  /*
  printf("isparen\n");
*/
  int result='-';

  result=matching(string, '(', ')');

  return result;
}













/* ****** The new bunch  ******* */
static int wk_is_name(char *key) {
/* [<][>][^][v][top][bottom][index][help] */

  /* Everything matches to name */
  return 1;

} /* wk_is_name() */

static int wk_is_nic_hdl(char *key) {
/* [<][>][^][v][top][bottom][index][help] */

  return isnichandle(key);

} /* wk_is_nic_hdl() */

static int wk_is_email(char *key) {
/* [<][>][^][v][top][bottom][index][help] */

  return isemail(key);

} /* wk_is_email() */

static int wk_is_mntner(char *key) {
/* [<][>][^][v][top][bottom][index][help] */

  return ismaintainer(key);

} /* wk_is_mntner() */

static int wk_is_key_cert(char *key) {
/* [<][>][^][v][top][bottom][index][help] */
  int result=1;

  result = perform_regex_test(KEYCERT, key);

  return result;

} /* wk_is_key_cert() */

static int wk_is_iprange(char *key) {
/* [<][>][^][v][top][bottom][index][help] */
  int result=1;

  /* XXX This is not very strict - but will cut out a lot of invalids */
  /* XXX And has been given a bad name and does a few things. */
  /* XXX This needs work. */
#define IPRANGE "^[0-9./ -]*$"
  result = perform_regex_test(IPRANGE, key);

  return result;

} /* wk_is_iprange() */

static int wk_is_ipprefix(char *key) {
/* [<][>][^][v][top][bottom][index][help] */
  int result=1;

  /* XXX INSERT check here! */
  return result;

} /* wk_is_iprange() */

static int wk_is_ip6prefix(char *key) {
/* [<][>][^][v][top][bottom][index][help] */

  return isipv6prefix_a(key);

} /* wk_is_ip6prefix() */

static int wk_is_netname(char *key) {
/* [<][>][^][v][top][bottom][index][help] */
  
  return isnetname(key);

} /* wk_is_netname() */

/* XXX Note: This function uses the same call as wk_is_netname(). */
static int wk_is_net6name(char *key) {
/* [<][>][^][v][top][bottom][index][help] */
  
  return isnetname(key);

} /* wk_is_netname() */

static int wk_is_autnum(char *key) {
/* [<][>][^][v][top][bottom][index][help] */

  return isasnum(key);

} /* wk_is_autnum() */

static int wk_is_assetname(char *key) {
/* [<][>][^][v][top][bottom][index][help] */
  int result=1;

  result = perform_regex_test(ASSETNAME, key);

  return result;

} /* wk_is_assetname() */

static int wk_is_routesetname(char *key) {
/* [<][>][^][v][top][bottom][index][help] */
  int result=1;

  result = perform_regex_test(ROUTESETNAME, key);

  return result;

} /* wk_is_routesetname() */

static int wk_is_domain(char *key) {
/* [<][>][^][v][top][bottom][index][help] */

  return isdomname(key);

} /* wk_is_domname() */

static int wk_is_hostname(char *key) {
/* [<][>][^][v][top][bottom][index][help] */

  /* XXX Why is there a hostname & a domainname? */
  /* Answer - hostname can be a domainname or an IP */
  return (isdomname(key) || wk_is_iprange(key));

} /* wk_is_hostname() */

static int wk_is_limerick(char *key) {
/* [<][>][^][v][top][bottom][index][help] */

  return islimerick(key);

} /* wk_is_limerick() */


/* WK_to_string() */
/*++++++++++++++++++++++++++++++++++++++
  Convert the which keytypes bitmap into a string.

  mask_t wk The which keytypes mask to be converted.

  More:
  +html+ <PRE>
  Authors:
        ottrey
  +html+ </PRE><DL COMPACT>
  +html+ <DT>Online References:
  +html+ <DD><UL>
  +html+ </UL></DL>

  ++++++++++++++++++++++++++++++++++++++*/
char *WK_to_string(mask_t wk) {
/* [<][>][^][v][top][bottom][index][help] */

  return MA_to_string(wk, Keytypes);

} /* WK_to_string() */


/* WK_new() */
/*++++++++++++++++++++++++++++++++++++++
  Create a new which keytypes bitmap.

  char *key The key to be examined.

  More:
  +html+ <PRE>
  Authors:
        ottrey
  +html+ </PRE><DL COMPACT>
  +html+ <DT>Online References:
  +html+ <DD><UL>
  +html+ </UL></DL>

  ++++++++++++++++++++++++++++++++++++++*/
mask_t WK_new(char *key) {
/* [<][>][^][v][top][bottom][index][help] */
  mask_t wk; 

  wk = MA_new(MA_END);

  MA_set(&wk, WK_NAME,         wk_is_name(key));
  MA_set(&wk, WK_NIC_HDL,      wk_is_nic_hdl(key));
  MA_set(&wk, WK_EMAIL,        wk_is_email(key));
  MA_set(&wk, WK_MNTNER,       wk_is_mntner(key));
  MA_set(&wk, WK_KEY_CERT,     wk_is_key_cert(key));
  MA_set(&wk, WK_IPRANGE,      wk_is_iprange(key));
  MA_set(&wk, WK_IPPREFIX,     wk_is_ipprefix(key));
  MA_set(&wk, WK_IP6PREFIX,    wk_is_ip6prefix(key));
  MA_set(&wk, WK_NETNAME,      wk_is_netname(key));
  MA_set(&wk, WK_NET6NAME,     wk_is_net6name(key));
  MA_set(&wk, WK_AUTNUM,       wk_is_autnum(key));
  MA_set(&wk, WK_ASSETNAME,    wk_is_assetname(key));
  MA_set(&wk, WK_ROUTESETNAME, wk_is_routesetname(key));
  MA_set(&wk, WK_DOMAIN,       wk_is_domain(key));
  MA_set(&wk, WK_HOSTNAME,     wk_is_hostname(key));
  MA_set(&wk, WK_LIMERICK,     wk_is_limerick(key));

  return wk;

} /* WK_new() */

/* [<][>][^][v][top][bottom][index][help] */