//  $Id: schema_rpsl.cc,v 1.2 2000/08/03 11:16:31 engin Exp $
//
//  Copyright (c) 1994 by the University of Southern California
//  All rights reserved.
//
//  Permission to use, copy, modify, and distribute this software and its
//  documentation in source and binary forms for lawful non-commercial
//  purposes and without fee is hereby granted, provided that the above
//  copyright notice appear in all copies and that both the copyright
//  notice and this permission notice appear in supporting documentation,
//  and that any documentation, advertising materials, and other materials
//  related to such distribution and use acknowledge that the software was
//  developed by the University of Southern California, Information
//  Sciences Institute. The name of the USC may not be used to endorse or
//  promote products derived from this software without specific prior
//  written permission.
//
//  THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
//  REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
//  PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
//  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
//  TITLE, AND NON-INFRINGEMENT.
//
//  IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
//  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
//  OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
//  OR PERFORMANCE OF THIS SOFTWARE.
//
//  Questions concerning this software should be directed to 
//  ratoolset@isi.edu.
//
//  Author(s): Cengiz Alaettinoglu <cengiz@ISI.EDU>

#include "config.h"

#include <fstream.h>
#include <cstring>
#include "gnu/std.h"

#include "schema.hh"
#include "object.hh"
#include "rpsl.y.hh"
#include "rptype.hh"

#define NO          0
#define PRS         1
#define MAN         1
#define SNG         1
#define HDN         1
#define KEY         1
#define IDX         1
#define OBS         1


char Schema::dictionary_text[] = "";

#define CMN_ATTRS "
attr:  notify           syntax(email),                                         optional,  multiple
attr:  remarks                                                                 optional,  multiple
attr:  source           syntax(special,source),                                mandatory, single,   internal
attr:  integrity        syntax(rpsl_word),                                     optional, single,   internal
attr:  changed          syntax(special, changed),                              mandatory,  multiple
attr:  delete                                                                  optional,  single, deleted
attr:  override                                                                optional,  single"

static char base_text[] = "class: dictionary        
attr:  dictionary       syntax(rpsl_word),                                     mandatory, single,   key
attr:  rp-attribute     syntax(special,rp-attribute),                          optional,  multiple
attr:  typedef          syntax(special,typedef),                               optional,  multiple
attr:  protocol         syntax(special,protocol),                              optional,  multiple            
attr:  notify           syntax(email),                                         optional,  multiple
attr:  remarks                                                                 optional,  multiple
attr:  source           syntax(rpsl_word),                                     mandatory, single,   internal
attr:  integrity        syntax(rpsl_word),                                     optional, single,   internal
attr:  changed          optional,  multiple
attr:  deleted                                                                 optional,  single, deleted  
attr:  descr                                                                   mandatory, single
attr:  mnt-by           syntax(list of rpsl_word),                             mandatory, multiple, lookup
attr:  tech-c                                                                  mandatory, multiple, lookup
attr:  admin-c                                                                 optional,  multiple, lookup

dictionary: rpsl
descr:   rpsl dictionary
admin-c: Cengiz Alaettinoglu
tech-c: Cengiz Alaettinoglu
mnt-by: MNT-CENGIZ
changed: cengiz@isi.edu 19980324
source: RPS-WG
typedef: ListOfIPv4Prefix list of Address_Prefix
typedef: Date integer[19000000,20000000]
typedef: as_number-as_set_name union as_number, as_set_name
typedef: ListOfas_number list of as_number
typedef: ListOfas_number-as_set_name list of as_number-as_set_name
typedef: ListOfas_set_name  list of as_set_name
typedef: ListOfroute_set_name  list of route_set_name
typedef: as_number-as_set_name-route_set_name-IPv4Prefix
         union as_number, as_set_name, route_set_name, Address_Prefix
typedef: ListOfas_number-as_set_name-route_set_name-IPv4Prefix
         list of as_number-as_set_name-route_set_name-IPv4Prefix
typedef: ListOfrpsl_word List of rpsl_word
rp-attribute: # preference, smaller values represent higher preferences
              pref
              operator=(integer[0, 65535])  
rp-attribute: # BGP multi_exit_discriminator attribute
              med    
              operator=(union integer[0, 65535], enum[igp_cost])
              # to set med to the IGP metric: med = igp_cost;
              #operator=(enum[igp_cost])
rp-attribute: # BGP destination preference attribute (dpa)
              dpa    
              operator=(integer[0, 65535])  
rp-attribute: # BGP aspath attribute
              aspath
              # prepends AS numbers from last to first order
              prepend(as_number, ...)
typedef:      # a community value in RPSL is either
              #  - a 4 byte integer
              #  - internet, no_export, no_advertise (see RFC-1997)
              community_elm union
              integer[1, 4294967295],
              enum[internet, no_export, no_advertise]
typedef:      # list of community values { 40, no_export, 3561:70}
              community_list
              list of community_elm
#typedef:      # source list
#              sources enum[RIPE, APNIC, MCI, INTERNIC, ARIN]  
#typedef:      country enum[NL, GB, UK, NL, DE, TR, PL, PT, IE, RU, AU, JP, TO, AT, IT] 
rp-attribute: # BGP community attribute
              community 
              # set to a list of communities
              operator=(community_list)
              # order independent equality comparison
              operator==(community_list)    
              # append community values                              
              operator.=(community_list)
              append(community_elm, ...)
              # delete community values
              delete(community_elm, ...)
              # a filter: true if one of community values is contained
              contains(community_elm, ...)
              # shortcut to contains: community(no_export, {3561,70})
              operator()(community_elm, ...)
rp-attribute: # next hop router in a static route
              next-hop 
              operator=(ipv4_address)       # a router address
              operator=(enum[self])         # router's own address
rp-attribute: # cost of a static route
              cost 
              operator=(integer[0, 65535])
protocol: BGP4
          # as number of the peer router
          MANDATORY asno(as_number)
          # enable flap damping
          OPTIONAL flap_damp()        
          OPTIONAL flap_damp(integer[0,65535],# penalty per flap
                             integer[0,65535],# penalty value for supression
                             integer[0,65535],# penalty value for reuse
                             integer[0,65535],# halflife in secs when up
                             integer[0,65535],# halflife in secs when down
                             integer[0,65535])# maximum penalty
protocol: OSPF
protocol: RIP
protocol: IGRP
protocol: IS-IS
protocol: STATIC
protocol: RIPng
protocol: DVMRP
protocol: PIM-DM
protocol: PIM-SM
protocol: CBT
protocol: MOSPF
";

static char classes_text[] = "class: mntner
attr:  mntner           syntax(rpsl_word),                                     mandatory, single,   key
attr:  auth             syntax(special, auth),                                 mandatory, multiple
attr:  upd-to           syntax(email),                                         mandatory, multiple
attr:  mnt-nfy          syntax(email),                                         optional,  multiple                   " CMN_ATTRS "
attr:  descr                                                                   mandatory, multiple 
attr:  mnt-by           syntax(list of rpsl_word),                             mandatory, multiple, lookup
attr:  admin-c          syntax(special,nichdl),                                mandatory, multiple, lookup
attr:  tech-c           syntax(special,nichdl),                                optional,  multiple, lookup

class: person
attr:  person           syntax(special,person),                                mandatory, single,   lookup
attr:  nic-hdl          syntax(special,nichdl),                                mandatory, single,   key
attr:  address                                                                 mandatory, multiple
attr:  phone            syntax(special,phone),                                 mandatory, multiple
attr:  fax-no           syntax(special,phone),                                 optional,  multiple
attr:  e-mail           syntax(email),                                         optional,  multiple, lookup           " CMN_ATTRS "
attr:  mnt-by           syntax(list of rpsl_word),                             optional,  multiple, lookup

class: role
attr:  role             syntax(special,person),                                mandatory, single,   lookup
attr:  nic-hdl          syntax(special,nichdl),                                mandatory, single,   key
attr:  address                                                                 mandatory, multiple
attr:  phone            syntax(special,phone),                                 mandatory, multiple
attr:  fax-no           syntax(special,phone),                                 optional,  multiple
attr:  e-mail           syntax(email),                                         mandatory, multiple, lookup
attr:  trouble                                                                 optional,  multiple                   " CMN_ATTRS "
attr:  mnt-by           syntax(list of rpsl_word),                             optional,  multiple, lookup
attr:  admin-c          syntax(special,nichdl),                                mandatory, multiple, lookup
attr:  tech-c           syntax(special,nichdl),                                mandatory, multiple, lookup

class: route
attr:  route            syntax(address_prefix),                                mandatory, single,   key, lookup
attr:  origin           syntax(as_number),                                     mandatory, single,   key, lookup
attr:  member-of        syntax(ListOfroute_set_name),                          optional,  multiple, lookup
attr:  inject           syntax(special, inject),                               optional,  multiple
attr:  components       syntax(special, components),                           optional,  single
attr:  aggr-bndry       syntax(special, aggr-bndry),                           optional,  single
attr:  aggr-mtd         syntax(special, aggr-mtd),                             optional,  single
attr:  export-comps     syntax(special, filter),                               optional,  single
attr:  holes            syntax(ListOfIPv4Prefix),                              optional,  multiple                   " CMN_ATTRS "
attr:  descr                                                                   mandatory, single
attr:  mnt-by           syntax(list of rpsl_word),                             mandatory, multiple, lookup
attr:  admin-c          syntax(special,nichdl),                                optional,  multiple, lookup
attr:  tech-c           syntax(special,nichdl),                                optional,  multiple, lookup
attr:  cross-nfy        syntax(list of rpsl_word),                             optional,  multiple
attr:  cross-mnt        syntax(list of rpsl_word),                             optional,  multiple

class: route-set
attr:  route-set        syntax(route_set_name),                                mandatory, single,   key
attr:  members          syntax(special, rs-members),                           optional,  multiple, lookup 
attr:  mbrs-by-ref      syntax(list of rpsl_Word),                             optional,  multiple, lookup           " CMN_ATTRS "
attr:  descr                                                                   mandatory, single
attr:  mnt-by           syntax(list of rpsl_word),                             mandatory, multiple, lookup
attr:  admin-c          syntax(special,nichdl),                                mandatory, multiple, lookup
attr:  tech-c           syntax(special,nichdl),                                mandatory, multiple, lookup

class: as-set
attr:  as-set           syntax(as_set_name),                                   mandatory, single,   key
attr:  members          syntax(list of union as_number, as_set_name),          optional,  multiple, lookup     
attr:  mbrs-by-ref      syntax(list of rpsl_word),                             optional,  multiple, lookup           " CMN_ATTRS "
attr:  descr                                                                   mandatory, single
attr:  mnt-by           syntax(list of rpsl_word),                             mandatory, multiple, lookup
attr:  admin-c          syntax(special,nichdl),                                mandatory, multiple, lookup
attr:  tech-c           syntax(special,nichdl),                                mandatory, multiple, lookup

class: rtr-set
attr:  rtr-set        syntax(rtr_set_name),                                       mandatory, single,   key
attr:  members        syntax(list of union rtr_set_name, dns_name, ipv4_address), optional,  multiple, lookup 
attr:  mbrs-by-ref    syntax(list of rpsl_Word),                               	  optional,  multiple, lookup           " CMN_ATTRS "
attr:  descr                                                                   	  mandatory, single
attr:  mnt-by         syntax(list of rpsl_word),                               	  mandatory, multiple, lookup
attr:  admin-c        syntax(special,nichdl),                                  	  mandatory, multiple, lookup
attr:  tech-c         syntax(special,nichdl),                                  	  mandatory, multiple, lookup

class: peering-set
attr:  peering-set    syntax(peering_set_name),                                   mandatory, single,   key
attr:  peering        syntax(special, peering),                                   mandatory, multiple                   " CMN_ATTRS "
attr:  descr                                                                   	  mandatory, single
attr:  mnt-by         syntax(list of rpsl_word),                               	  mandatory, multiple, lookup
attr:  admin-c        syntax(special,nichdl),                                 	  mandatory, multiple, lookup
attr:  tech-c         syntax(special,nichdl),                                  	  mandatory, multiple, lookup

class: filter-set
attr:  filter-set       syntax(filter_set_name),                               mandatory, single,   key
attr:  filter           syntax(special, filter),                               mandatory, single                       " CMN_ATTRS "
attr:  descr                                                                   mandatory, single
attr:  mnt-by           syntax(list of rpsl_word),                             mandatory, multiple, lookup
attr:  admin-c          syntax(special,nichdl),                                mandatory, multiple, lookup
attr:  tech-c           syntax(special,nichdl),                                mandatory, multiple, lookup

class: aut-num
attr:  aut-num          syntax(as_number),                                     mandatory, single,   key
attr:  as-name          syntax(rpsl_word),                                     optional, single,   lookup
attr:  member-of        syntax(List Of AS_set_name),                           optional,  multiple, lookup
attr:  import           syntax(special,import),                                optional,  multiple
attr:  export           syntax(special,export),                                optional,  multiple
attr:  default          syntax(special,default),                               optional,  multiple                   " CMN_ATTRS "
attr:  descr                                                                   mandatory, multiple 
attr:  mnt-by           syntax(list of rpsl_word),                             mandatory, multiple, lookup
attr:  mnt-routes       syntax(special, mnt-routes),                           optional,  multiple, lookup
attr:  admin-c          syntax(special,nichdl),                                mandatory, multiple, lookup
attr:  tech-c           syntax(special,nichdl),                                mandatory, multiple, lookup
attr:  cross-nfy        syntax(list of rpsl_word),                             optional,  multiple
attr:  cross-mnt        syntax(list of rpsl_word),                             optional,  multiple

class: inet-rtr
attr:  inet-rtr         syntax(dns_name),                                      mandatory, single,   key
attr:  alias            syntax(dns_name),                                      optional,  multiple, lookup
attr:  local-as         syntax(as_number),                                     mandatory, single,   lookup
attr:  ifaddr           syntax(special,ifaddr),                                mandatory, multiple
attr:  peer             syntax(special,peer),                                  optional,  multiple                   " CMN_ATTRS "
attr:  member-of        syntax(List Of rtr_set_name),                          optional,  multiple, lookup
attr:  descr                                                                   optional,  multiple 
attr:  mnt-by           syntax(list of rpsl_word),                             mandatory, multiple, lookup
attr:  admin-c          syntax(special,nichdl),                                mandatory, multiple, lookup
attr:  tech-c           syntax(special,nichdl),                                mandatory, multiple, lookup

class: inetnum
attr:  inetnum          syntax(range of ipv4_address),                         mandatory, single,   key
attr:  netname          syntax(rpsl_word),                                     mandatory, single,   lookup
attr:  country          syntax(special, country),                              mandatory, multiple
attr:  rev-srv                                                                 optional,  multiple, lookup
attr:  status           syntax(special,status_inet),                           mandatory, single
attr:  mnt-lower        syntax(ListOfrpsl_word),                               optional,  multiple                   " CMN_ATTRS "
attr:  descr                                                                   mandatory, multiple 
attr:  mnt-by           syntax(list of rpsl_word),                             optional,  multiple, lookup
attr:  admin-c          syntax(special,nichdl),                                mandatory, multiple, lookup
attr:  tech-c           syntax(special,nichdl),                                mandatory, multiple, lookup

class: inet6num
attr:  inet6num          syntax(ipv6_prefix),                                  mandatory, single,   key
attr:  netname           syntax(rpsl_word),                                    mandatory, single,   lookup
attr:  country           syntax(special, country),                             mandatory, multiple
attr:  rev-srv                                                                 optional,  multiple, lookup
attr:  status                                                                  optional, generated, single
attr:  mnt-lower        syntax(ListOfrpsl_word),                               optional,  multiple                   " CMN_ATTRS "
attr:  descr                                                                   mandatory, multiple 
attr:  mnt-by           syntax(list of rpsl_word),                             optional,  multiple, lookup
attr:  admin-c          syntax(special,nichdl),                                mandatory, multiple, lookup
attr:  tech-c           syntax(special,nichdl),                                mandatory, multiple, lookup

class: domain
attr:  domain           syntax(union dns_name, rpsl_word),                     mandatory, single,   key
attr:  sub-dom                                                                 optional,  multiple, lookup
attr:  dom-net                                                                 optional,  multiple
attr:  zone-c          syntax(special,nichdl),                                 mandatory, multiple, lookup
attr:  nserver                                                                 optional,  multiple, lookup
attr:  refer           syntax(special, refer),    optional, single
attr:  mnt-lower        syntax(ListOfrpsl_word),                               optional,  multiple                   " CMN_ATTRS "
attr:  descr                                                                   mandatory, multiple 
attr:  mnt-by           syntax(list of rpsl_word),                             optional,  multiple, lookup
attr:  admin-c          syntax(special,nichdl),                                mandatory, multiple, lookup
attr:  tech-c           syntax(special,nichdl),                                mandatory, multiple, lookup

class: limerick
attr:  limerick                                                                mandatory, single,   key
attr:  text                                                                    mandatory, multiple
attr:  author          syntax(special,nichdl),                                 mandatory, multiple, lookup           " CMN_ATTRS "
attr:  descr                                                                   optional,  single
attr:  mnt-by           syntax(list of rpsl_word),                             mandatory, multiple, lookup
attr:  admin-c          syntax(special,nichdl),                                mandatory, multiple, lookup

class: as-block
attr:  as-block         syntax(union as_number, range of as_number),           mandatory, single,   key
attr:  mnt-lower        syntax(ListOfrpsl_word),                               optional,  multiple                   " CMN_ATTRS "
attr:  descr                                                                   mandatory, single
attr:  mnt-by           syntax(list of rpsl_word),                             mandatory,  multiple, lookup
attr:  admin-c          syntax(special,nichdl),                                mandatory, multiple, lookup
attr:  tech-c           syntax(special,nichdl),                                mandatory, multiple, lookup

class: key-cert
attr:  key-cert       mandatory, single,    key,        syntax(keycrtname)
attr:  method         generated, optional, single,      syntax(rpsl_word)
attr:  owner          generated, optional, multiple
attr:  fingerpr       generated, optional, single
attr:  certif         mandatory, single                        " CMN_ATTRS "
attr:  mnt-by         mandatory, multiple, lookup,      syntax(list of rpsl_word)

class: peval   
attr:  peval            syntax(special,filter),                                 optional,  single

class: repository
attr:  repository           mandatory,  single,  key,   syntax(rpsl_word)
attr:  query-address        mandatory,  multiple
attr:  response-auth-type   mandatory,  multiple
attr:  submit-address       mandatory,  multiple
attr:  submit-auth-type     mandatory,  multiple
attr:  repository-cert      mandatory,  multiple
attr:  expire               mandatory,  single
attr:  heartbeat-interval   mandatory,  single
attr:  descr                optional,   multiple
attr:  admin-c              mandatory,  multiple, lookup
attr:  tech-c               mandatory,  multiple, lookup
attr:  mnt-by               mandatory,  multiple, lookup " CMN_ATTRS "
";

void Schema::addClass(AttrClass *clss) {
   classes[lastClass++] = clss;
}

void Schema::initializeBase() {
   static bool initializeBaseDone = false;
   if (initializeBaseDone)
      return;
   initializeBaseDone = true;

   AttrClass *classClass = new AttrClass(strdup("class"));
   AttrClass *clss = NULL;

   addClass(classClass);
   classClass->addAttr(new AttrAttr(strdup("class"), ATTR_GENERIC, 
				    RPType::newRPType("rpsl_word"),
				    AttrAttr::LOOKUP));
   classClass->addAttr(new AttrAttr(strdup("attr"), ATTR_ATTR,    
				    (RPType *) NULL, 
				    AttrAttr::MULTIVALUED));

   dictionary = initializeFromString(base_text, "dictionary");
}

List<Object> *Schema::initializeFromFile(char *filename) {
   Object *o;
   const AttrAttr *attr;
   char *class_name;
   bool code = true;
   List<Object> *result = new List<Object>;
   AttrClass *clss = NULL;

   initializeBase();

   ifstream in(filename);
   if (!in)
      return result;

   while (in) {
      o = new Object;
      code = o->read(in);
      if (! code) {
	 delete o;
	 continue;
      }

      code = o->scan();
      if (o->has_error)
	 delete o;
      else {
	 if (! strcasecmp(o->type->name, "class")) {
	    AttrGenericIterator<ItemWORD> cname(o, "class");
	    AttrIterator<AttrAttr>  attrItr(o, "attr");
	    char *name = cname.first()->word;

	    addClass(clss = new AttrClass(strdup(name)));
	    clss->object = o;
	    //cerr << "Reading "<< name << " class definition..." << endl;
	    
	    for (attr = attrItr.first(); attr; attr = attrItr.next())
	       clss->addAttr((AttrAttr *) attr);

	 } 

         result->append(o);
      }
   }

   return result;
}

Object *Schema::initializeFromString(char *class_text, char *lookFor) {
   Object *o;
   const AttrAttr *attr;
   char *class_name;
   Object *result = (Object *) NULL;
   AttrClass *clss = NULL;
   int count = 0;

   initializeBase();

   do {
      count++;
      o = new Object;
      if (count == 2 && ! dictionary)
	 dictionary = o;

      o->scan(class_text, strlen(class_text));

      if (o->has_error)
	 delete o;
      else {
	 if (!strcasecmp(o->type->name, "class")) {
	    AttrGenericIterator<ItemWORD> cname(o, "class");
	    AttrIterator<AttrAttr>  attrItr(o, "attr");
	    char *name = cname.first()->word;

	    addClass(clss = new AttrClass(strdup(name)));
	    clss->object = o;
	    // cerr << "Reading "<< name << " class definition..." << endl;

	    for (attr = attrItr.first(); attr; attr = attrItr.next())
	       clss->addAttr((AttrAttr *) attr);

	    //delete o;
	 }

	 if (lookFor && ! strcasecmp(o->type->name, lookFor))
	    result = o;
      }

      class_text = strstr(class_text, "\n\n");
      if (class_text)
	 class_text += 2;
   } while (class_text);

   return result;
}

void Schema::initialize() {
   initializeBase();
   initializeFromString(classes_text);
}

static RPSLKeyword rpsl_keywords[] = {
   RPSLKeyword("true",     KEYW_TRUE,     1),
   RPSLKeyword("false",    KEYW_FALSE,    1),
   RPSLKeyword("action",   KEYW_ACTION,   1),
   RPSLKeyword("accept",   KEYW_ACCEPT,   1),
   RPSLKeyword("announce", KEYW_ANNOUNCE, 1),
   RPSLKeyword("from",     KEYW_FROM,     1),
   RPSLKeyword("to",       KEYW_TO,       1),
   RPSLKeyword("at",       KEYW_AT,       1),
   RPSLKeyword("any",      KEYW_ANY,      1),
   RPSLKeyword("protocol", KEYW_PROTOCOL, 1),
   RPSLKeyword("into",     KEYW_INTO,     1),
   RPSLKeyword("refine",   KEYW_REFINE,   1),
   RPSLKeyword("except",   KEYW_EXCEPT,   1),
   RPSLKeyword("static",   KEYW_STATIC,   1),
   RPSLKeyword("networks", KEYW_NETWORKS, 1),
   RPSLKeyword("masklen",  KEYW_MASKLEN,  1),
   RPSLKeyword("peeras",   KEYW_PEERAS,   1),

   RPSLKeyword("atomic",   KEYW_ATOMIC,   1),
   RPSLKeyword("inbound",  KEYW_INBOUND,  1),
   RPSLKeyword("outbound", KEYW_OUTBOUND, 1),

   RPSLKeyword("or",       OP_OR ,        1),
   RPSLKeyword("and",      OP_AND,        1),
   RPSLKeyword("not",      OP_NOT,        1),

   RPSLKeyword("union",        KEYW_UNION,        1),
   RPSLKeyword("range",        KEYW_RANGE,        1),
   RPSLKeyword("list",         KEYW_LIST,         1),
   RPSLKeyword("of",           KEYW_OF,           1),
   RPSLKeyword("operator",     KEYW_OPERATOR,     1),
   RPSLKeyword("upon",         KEYW_UPON,         1),
   RPSLKeyword("have-components", KEYW_HAVE_COMPONENTS, 1),
   RPSLKeyword("exclude",      KEYW_EXCLUDE,      1),

   RPSLKeyword("syntax",       KEYW_SYNTAX,       1),
   RPSLKeyword("special",      KEYW_SPECIAL,      1),
   RPSLKeyword("optional",     KEYW_OPTIONAL,     1),
   RPSLKeyword("mandatory",    KEYW_MANDATORY,    1),
   RPSLKeyword("internal",     KEYW_INTERNAL,     1),
   RPSLKeyword("single",       KEYW_SINGLEVALUED, 1),
   RPSLKeyword("multiple",     KEYW_MULTIVALUED,  1),
   RPSLKeyword("lookup",       KEYW_LOOKUP,       1),
   RPSLKeyword("key",          KEYW_KEY,          1),
   RPSLKeyword("deleted",      KEYW_DELETED,      1),
   RPSLKeyword("generated",    KEYW_GENERATED,    1),
   RPSLKeyword("none",         KEYW_NONE,         1),
   RPSLKeyword("mail-from",    KEYW_MAILFROM,     1),
   RPSLKeyword("crypt-pw",     KEYW_CRYPTPW,      1),
   RPSLKeyword("assigned",     KEYW_ASSIGNED,     1),
   RPSLKeyword("allocated",    KEYW_ALLOCATED,    1),
   RPSLKeyword("PA",           KEYW_PA,           1),
   RPSLKeyword("PI",           KEYW_PI,           1),
   RPSLKeyword("unspecified",  KEYW_UNSPECIFIED,  1),
   RPSLKeyword("ext",          KEYW_EXT,          1),
   RPSLKeyword("simple",       KEYW_SIMPLE,       1),
   RPSLKeyword("ripe",         KEYW_RIPE,         1),
   RPSLKeyword("internic",     KEYW_INTERNIC,     1),
   RPSLKeyword("clientaddress",KEYW_CLIENTADDRESS,1),
   RPSLKeyword(NULL,       0,             0)
};

static RPSLKeyword rpsl_rules[] = {
   RPSLKeyword("changed",           ATTR_CHANGED,           1),
   RPSLKeyword("import",            ATTR_IMPORT,            1),
   RPSLKeyword("export",            ATTR_EXPORT,            1),
   RPSLKeyword("default",           ATTR_DEFAULT,           1),
   RPSLKeyword("ifaddr",            ATTR_IFADDR,            1),
   RPSLKeyword("peer",              ATTR_PEER,              1),
   RPSLKeyword("rp-attribute",      ATTR_RP_ATTR,           1),
   RPSLKeyword("typedef",           ATTR_TYPEDEF,           1),
   RPSLKeyword("protocol",          ATTR_PROTOCOL,          1),
   RPSLKeyword("filter",            ATTR_FILTER,            1),
   RPSLKeyword("peering",           ATTR_PEERING,           1),
   RPSLKeyword("blobs",             ATTR_BLOBS,             1),
   RPSLKeyword("mnt-routes",        ATTR_MNT_ROUTES,        1),
   RPSLKeyword("components",        ATTR_COMPONENTS,        1),
   RPSLKeyword("inject",            ATTR_INJECT,            1),
   RPSLKeyword("aggr-mtd",          ATTR_AGGR_MTD,          1),
   RPSLKeyword("aggr-bndry",        ATTR_AGGR_BNDRY,        1),
   RPSLKeyword("rs-members",        ATTR_RS_MEMBERS,        1),
   RPSLKeyword("nichdl",            ATTR_NICHDL,            1),
   RPSLKeyword("auth",              ATTR_AUTH,              1),
   RPSLKeyword("status_inet",       ATTR_STATUS_INET,       1),
   RPSLKeyword("phone",             ATTR_PHONE,             1),
   RPSLKeyword("source",            ATTR_SOURCE,            1),
   RPSLKeyword("refer",             ATTR_REFER,             1),
   RPSLKeyword("country",           ATTR_COUNTRY,           1),
   RPSLKeyword("person",            ATTR_PERSON,            1),
   RPSLKeyword(NULL, 0,                                     1)
};

Schema schema(rpsl_keywords, rpsl_rules);
