diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/.cvsignore | 14 | ||||
| -rw-r--r-- | lib/Makefile.am | 6 | ||||
| -rw-r--r-- | lib/command.c | 4 | ||||
| -rw-r--r-- | lib/command.h | 1 | ||||
| -rw-r--r-- | lib/distribute.c | 69 | ||||
| -rw-r--r-- | lib/distribute.h | 3 | ||||
| -rw-r--r-- | lib/filter.c | 12 | ||||
| -rw-r--r-- | lib/if.c | 16 | ||||
| -rw-r--r-- | lib/if_rmap.c | 3 | ||||
| -rw-r--r-- | lib/log.c | 86 | ||||
| -rw-r--r-- | lib/log.h | 9 | ||||
| -rw-r--r-- | lib/md5.c | 73 | ||||
| -rw-r--r-- | lib/md5.h | 3 | ||||
| -rw-r--r-- | lib/memory.c | 14 | ||||
| -rw-r--r-- | lib/memtypes.c | 9 | ||||
| -rw-r--r-- | lib/prefix.c | 314 | ||||
| -rw-r--r-- | lib/prefix.h | 27 | ||||
| -rw-r--r-- | lib/route_types.awk | 187 | ||||
| -rwxr-xr-x | lib/route_types.pl | 199 | ||||
| -rw-r--r-- | lib/route_types.txt | 12 | ||||
| -rw-r--r-- | lib/routemap.h | 1 | ||||
| -rw-r--r-- | lib/smux.c | 7 | ||||
| -rw-r--r-- | lib/sockopt.c | 207 | ||||
| -rw-r--r-- | lib/sockopt.h | 11 | ||||
| -rw-r--r-- | lib/sockunion.c | 47 | ||||
| -rw-r--r-- | lib/sockunion.h | 1 | ||||
| -rw-r--r-- | lib/thread.c | 12 | ||||
| -rw-r--r-- | lib/thread.h | 9 | ||||
| -rw-r--r-- | lib/vty.c | 9 | ||||
| -rw-r--r-- | lib/vty.h | 3 | ||||
| -rw-r--r-- | lib/workqueue.c | 2 | ||||
| -rw-r--r-- | lib/zclient.c | 110 | ||||
| -rw-r--r-- | lib/zclient.h | 14 | ||||
| -rw-r--r-- | lib/zebra.h | 28 | 
34 files changed, 956 insertions, 566 deletions
| diff --git a/lib/.cvsignore b/lib/.cvsignore deleted file mode 100644 index 806696d7..00000000 --- a/lib/.cvsignore +++ /dev/null @@ -1,14 +0,0 @@ -Makefile -Makefile.in -*.o -*.lo -*.la -version.c -version.h -.deps -.nfs* -.libs -.arch-inventory -.arch-ids -memtypes.h -route_types.h diff --git a/lib/Makefile.am b/lib/Makefile.am index 315e919b..890cc5ca 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -29,10 +29,10 @@ pkginclude_HEADERS = \  	privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \  	workqueue.h route_types.h -EXTRA_DIST = regex.c regex-gnu.h memtypes.awk route_types.awk route_types.txt +EXTRA_DIST = regex.c regex-gnu.h memtypes.awk route_types.pl route_types.txt  memtypes.h: $(srcdir)/memtypes.c $(srcdir)/memtypes.awk  	($(GAWK) -f $(srcdir)/memtypes.awk $(srcdir)/memtypes.c > $@) -route_types.h: $(srcdir)/route_types.txt $(srcdir)/route_types.awk -	($(GAWK) -f $(srcdir)/route_types.awk $(srcdir)/route_types.txt > $@) +route_types.h: $(srcdir)/route_types.txt $(srcdir)/route_types.pl +	@PERL@ $(srcdir)/route_types.pl < $(srcdir)/route_types.txt > $@ diff --git a/lib/command.c b/lib/command.c index 264e0f7b..e62a7a7e 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,6 +1,4 @@  /* -   $Id$ -      Command interpreter routine for virtual terminal [aka TeletYpe]     Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -2402,6 +2400,7 @@ DEFUN (config_exit,      case BGP_NODE:      case RIP_NODE:      case RIPNG_NODE: +    case BABEL_NODE:      case OSPF_NODE:      case OSPF6_NODE:      case ISIS_NODE: @@ -2451,6 +2450,7 @@ DEFUN (config_end,      case ZEBRA_NODE:      case RIP_NODE:      case RIPNG_NODE: +    case BABEL_NODE:      case BGP_NODE:      case BGP_VPNV4_NODE:      case BGP_IPV4_NODE: diff --git a/lib/command.h b/lib/command.h index 1275efee..2d708d8e 100644 --- a/lib/command.h +++ b/lib/command.h @@ -78,6 +78,7 @@ enum node_type    TABLE_NODE,			/* rtm_table selection node. */    RIP_NODE,			/* RIP protocol mode node. */     RIPNG_NODE,			/* RIPng protocol mode node. */ +  BABEL_NODE,			/* Babel protocol mode node. */    BGP_NODE,			/* BGP protocol mode which includes BGP4+ */    BGP_VPNV4_NODE,		/* BGP MPLS-VPN PE exchange. */    BGP_IPV4_NODE,		/* BGP IPv4 unicast address family.  */ diff --git a/lib/distribute.c b/lib/distribute.c index 420849da..8d6f6377 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -299,7 +299,6 @@ DEFUN (distribute_list_all,         "Filter outgoing routing updates\n")  {    enum distribute_type type; -  struct distribute *dist;    /* Check of distribute list type. */    if (strncmp (argv[1], "i", 1) == 0) @@ -314,7 +313,7 @@ DEFUN (distribute_list_all,      }    /* Get interface name corresponding distribute list. */ -  dist = distribute_list_set (NULL, type, argv[0]); +  distribute_list_set (NULL, type, argv[0]);    return CMD_SUCCESS;  } @@ -379,7 +378,6 @@ DEFUN (distribute_list,         "Interface name\n")  {    enum distribute_type type; -  struct distribute *dist;    /* Check of distribute list type. */    if (strncmp (argv[1], "i", 1) == 0) @@ -393,7 +391,7 @@ DEFUN (distribute_list,      }    /* Get interface name corresponding distribute list. */ -  dist = distribute_list_set (argv[2], type, argv[0]); +  distribute_list_set (argv[2], type, argv[0]);    return CMD_SUCCESS;  }        @@ -407,7 +405,7 @@ ALIAS (distribute_list,         "Filter outgoing routing updates\n"         "Interface name\n") -DEFUN (no_districute_list, no_distribute_list_cmd, +DEFUN (no_distribute_list, no_distribute_list_cmd,         "no distribute-list WORD (in|out) WORD",         NO_STR         "Filter networks in routing updates\n" @@ -439,7 +437,7 @@ DEFUN (no_districute_list, no_distribute_list_cmd,    return CMD_SUCCESS;  }        -ALIAS (no_districute_list, no_ipv6_distribute_list_cmd, +ALIAS (no_distribute_list, no_ipv6_distribute_list_cmd,         "no distribute-list WORD (in|out) WORD",         NO_STR         "Filter networks in routing updates\n" @@ -448,7 +446,7 @@ ALIAS (no_districute_list, no_ipv6_distribute_list_cmd,         "Filter outgoing routing updates\n"         "Interface name\n") -DEFUN (districute_list_prefix_all, +DEFUN (distribute_list_prefix_all,         distribute_list_prefix_all_cmd,         "distribute-list prefix WORD (in|out)",         "Filter networks in routing updates\n" @@ -458,7 +456,6 @@ DEFUN (districute_list_prefix_all,         "Filter outgoing routing updates\n")  {    enum distribute_type type; -  struct distribute *dist;    /* Check of distribute list type. */    if (strncmp (argv[1], "i", 1) == 0) @@ -473,12 +470,12 @@ DEFUN (districute_list_prefix_all,      }    /* Get interface name corresponding distribute list. */ -  dist = distribute_list_prefix_set (NULL, type, argv[0]); +  distribute_list_prefix_set (NULL, type, argv[0]);    return CMD_SUCCESS;  }        -ALIAS (districute_list_prefix_all, +ALIAS (distribute_list_prefix_all,         ipv6_distribute_list_prefix_all_cmd,         "distribute-list prefix WORD (in|out)",         "Filter networks in routing updates\n" @@ -487,7 +484,7 @@ ALIAS (districute_list_prefix_all,         "Filter incoming routing updates\n"         "Filter outgoing routing updates\n") -DEFUN (no_districute_list_prefix_all, +DEFUN (no_distribute_list_prefix_all,         no_distribute_list_prefix_all_cmd,         "no distribute-list prefix WORD (in|out)",         NO_STR @@ -521,7 +518,7 @@ DEFUN (no_districute_list_prefix_all,    return CMD_SUCCESS;  }        -ALIAS (no_districute_list_prefix_all, +ALIAS (no_distribute_list_prefix_all,         no_ipv6_distribute_list_prefix_all_cmd,         "no distribute-list prefix WORD (in|out)",         NO_STR @@ -531,7 +528,7 @@ ALIAS (no_districute_list_prefix_all,         "Filter incoming routing updates\n"         "Filter outgoing routing updates\n") -DEFUN (districute_list_prefix, distribute_list_prefix_cmd, +DEFUN (distribute_list_prefix, distribute_list_prefix_cmd,         "distribute-list prefix WORD (in|out) WORD",         "Filter networks in routing updates\n"         "Filter prefixes in routing updates\n" @@ -541,7 +538,6 @@ DEFUN (districute_list_prefix, distribute_list_prefix_cmd,         "Interface name\n")  {    enum distribute_type type; -  struct distribute *dist;    /* Check of distribute list type. */    if (strncmp (argv[1], "i", 1) == 0) @@ -556,12 +552,12 @@ DEFUN (districute_list_prefix, distribute_list_prefix_cmd,      }    /* Get interface name corresponding distribute list. */ -  dist = distribute_list_prefix_set (argv[2], type, argv[0]); +  distribute_list_prefix_set (argv[2], type, argv[0]);    return CMD_SUCCESS;  }        -ALIAS (districute_list_prefix, ipv6_distribute_list_prefix_cmd, +ALIAS (distribute_list_prefix, ipv6_distribute_list_prefix_cmd,         "distribute-list prefix WORD (in|out) WORD",         "Filter networks in routing updates\n"         "Filter prefixes in routing updates\n" @@ -570,7 +566,7 @@ ALIAS (districute_list_prefix, ipv6_distribute_list_prefix_cmd,         "Filter outgoing routing updates\n"         "Interface name\n") -DEFUN (no_districute_list_prefix, no_distribute_list_prefix_cmd, +DEFUN (no_distribute_list_prefix, no_distribute_list_prefix_cmd,         "no distribute-list prefix WORD (in|out) WORD",         NO_STR         "Filter networks in routing updates\n" @@ -604,7 +600,7 @@ DEFUN (no_districute_list_prefix, no_distribute_list_prefix_cmd,    return CMD_SUCCESS;  }        -ALIAS (no_districute_list_prefix, no_ipv6_distribute_list_prefix_cmd, +ALIAS (no_distribute_list_prefix, no_ipv6_distribute_list_prefix_cmd,         "no distribute-list prefix WORD (in|out) WORD",         NO_STR         "Filter networks in routing updates\n" @@ -762,22 +758,25 @@ distribute_list_init (int node)                            (int (*) (const void *, const void *)) distribute_cmp);    if(node==RIP_NODE) { -    install_element (RIP_NODE, &distribute_list_all_cmd); -    install_element (RIP_NODE, &no_distribute_list_all_cmd); -    install_element (RIP_NODE, &distribute_list_cmd); -    install_element (RIP_NODE, &no_distribute_list_cmd); -    install_element (RIP_NODE, &distribute_list_prefix_all_cmd); -    install_element (RIP_NODE, &no_distribute_list_prefix_all_cmd); -    install_element (RIP_NODE, &distribute_list_prefix_cmd); -    install_element (RIP_NODE, &no_distribute_list_prefix_cmd); -  } else { -    install_element (RIPNG_NODE, &ipv6_distribute_list_all_cmd); -    install_element (RIPNG_NODE, &no_ipv6_distribute_list_all_cmd); -    install_element (RIPNG_NODE, &ipv6_distribute_list_cmd); -    install_element (RIPNG_NODE, &no_ipv6_distribute_list_cmd); -    install_element (RIPNG_NODE, &ipv6_distribute_list_prefix_all_cmd); -    install_element (RIPNG_NODE, &no_ipv6_distribute_list_prefix_all_cmd); -    install_element (RIPNG_NODE, &ipv6_distribute_list_prefix_cmd); -    install_element (RIPNG_NODE, &no_ipv6_distribute_list_prefix_cmd); +    install_element (node, &distribute_list_all_cmd); +    install_element (node, &no_distribute_list_all_cmd); +    install_element (node, &distribute_list_cmd); +    install_element (node, &no_distribute_list_cmd); +    install_element (node, &distribute_list_prefix_all_cmd); +    install_element (node, &no_distribute_list_prefix_all_cmd); +    install_element (node, &distribute_list_prefix_cmd); +    install_element (node, &no_distribute_list_prefix_cmd); +  } else if (node == RIPNG_NODE || node == BABEL_NODE) { +    /* WARNING: two identical commands installed do a crash, so be worry with +     aliases. For this reason, and because all these commands are aliases, Babel +     is not set with RIP. */ +    install_element (node, &ipv6_distribute_list_all_cmd); +    install_element (node, &no_ipv6_distribute_list_all_cmd); +    install_element (node, &ipv6_distribute_list_cmd); +    install_element (node, &no_ipv6_distribute_list_cmd); +    install_element (node, &ipv6_distribute_list_prefix_all_cmd); +    install_element (node, &no_ipv6_distribute_list_prefix_all_cmd); +    install_element (node, &ipv6_distribute_list_prefix_cmd); +    install_element (node, &no_ipv6_distribute_list_prefix_cmd);    }  } diff --git a/lib/distribute.h b/lib/distribute.h index a1bec03a..5072016f 100644 --- a/lib/distribute.h +++ b/lib/distribute.h @@ -22,6 +22,9 @@  #ifndef _ZEBRA_DISTRIBUTE_H  #define _ZEBRA_DISTRIBUTE_H +#include <zebra.h> +#include "if.h" +  /* Disctirubte list types. */  enum distribute_type  { diff --git a/lib/filter.c b/lib/filter.c index af8d587f..69341824 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -1337,13 +1337,13 @@ DEFUN (no_access_list_all,    master = access->master; -  /* Delete all filter from access-list. */ -  access_list_delete (access); -    /* Run hook function. */    if (master->delete_hook)      (*master->delete_hook) (access); +  /* Delete all filter from access-list. */ +  access_list_delete (access); +    return CMD_SUCCESS;  } @@ -1508,13 +1508,13 @@ DEFUN (no_ipv6_access_list_all,    master = access->master; -  /* Delete all filter from access-list. */ -  access_list_delete (access); -    /* Run hook function. */    if (master->delete_hook)      (*master->delete_hook) (access); +  /* Delete all filter from access-list. */ +  access_list_delete (access); +    return CMD_SUCCESS;  } @@ -429,19 +429,17 @@ if_dump (const struct interface *ifp)    struct listnode *node;    struct connected *c; -  zlog_info ("Interface %s index %d metric %d mtu %d " +  for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c)) +    zlog_info ("Interface %s index %d metric %d mtu %d "  #ifdef HAVE_IPV6 -             "mtu6 %d " +               "mtu6 %d "  #endif /* HAVE_IPV6 */ -             "%s", -	     ifp->name, ifp->ifindex, ifp->metric, ifp->mtu,  +               "%s", +               ifp->name, ifp->ifindex, ifp->metric, ifp->mtu,   #ifdef HAVE_IPV6 -	     ifp->mtu6, +               ifp->mtu6,  #endif /* HAVE_IPV6 */ -	     if_flag_dump (ifp->flags)); -   -  for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c)) -    ; +               if_flag_dump (ifp->flags));  }  /* Interface printing for all interface. */ diff --git a/lib/if_rmap.c b/lib/if_rmap.c index 9774be4b..7d049b87 100644 --- a/lib/if_rmap.c +++ b/lib/if_rmap.c @@ -207,7 +207,6 @@ DEFUN (if_rmap,         "Route map interface name\n")  {    enum if_rmap_type type; -  struct if_rmap *if_rmap;    if (strncmp (argv[1], "i", 1) == 0)      type = IF_RMAP_IN; @@ -219,7 +218,7 @@ DEFUN (if_rmap,        return CMD_WARNING;      } -  if_rmap = if_rmap_set (argv[2], type, argv[0]); +  if_rmap_set (argv[2], type, argv[0]);    return CMD_SUCCESS;  }       @@ -1,6 +1,4 @@  /* - * $Id$ - *   * Logging of zebra   * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro   * @@ -22,6 +20,8 @@   * 02111-1307, USA.     */ +#define QUAGGA_DEFINE_DESC_TABLE +  #include <zebra.h>  #include "log.h" @@ -48,6 +48,7 @@ const char *zlog_proto_names[] =    "BGP",    "OSPF",    "RIPNG", +  "BABEL",    "OSPF6",    "ISIS",    "MASC", @@ -776,7 +777,8 @@ lookup (const struct message *mes, int key)   * provided otherwise.   */  const char * -mes_lookup (const struct message *meslist, int max, int index, const char *none) +mes_lookup (const struct message *meslist, int max, int index, +  const char *none, const char *mesname)  {    int pos = index - meslist[0].key; @@ -799,13 +801,13 @@ mes_lookup (const struct message *meslist, int max, int index, const char *none)  	  {  	    const char *str = (meslist->str ? meslist->str : none); -	    zlog_debug ("message index %d [%s] found in position %d (max is %d)", -		      index, str, i, max); +	    zlog_debug ("message index %d [%s] found in %s at position %d (max is %d)", +		      index, str, mesname, i, max);  	    return str;  	  }        }    } -  zlog_err("message index %d not found (max is %d)", index, max); +  zlog_err("message index %d not found in %s (max is %d)", index, mesname, max);    assert (none);    return none;  } @@ -818,29 +820,6 @@ safe_strerror(int errnum)    return (s != NULL) ? s : "Unknown error";  } -struct zebra_desc_table -{ -  unsigned int type; -  const char *string; -  char chr; -}; - -#define DESC_ENTRY(T,S,C) [(T)] = { (T), (S), (C) } -static const struct zebra_desc_table route_types[] = { -  DESC_ENTRY	(ZEBRA_ROUTE_SYSTEM,	"system",	'X' ), -  DESC_ENTRY	(ZEBRA_ROUTE_KERNEL,	"kernel",	'K' ), -  DESC_ENTRY	(ZEBRA_ROUTE_CONNECT,	"connected",	'C' ), -  DESC_ENTRY	(ZEBRA_ROUTE_STATIC,	"static",	'S' ), -  DESC_ENTRY	(ZEBRA_ROUTE_RIP,	"rip",		'R' ), -  DESC_ENTRY	(ZEBRA_ROUTE_RIPNG,	"ripng",	'R' ), -  DESC_ENTRY	(ZEBRA_ROUTE_OSPF,	"ospf",		'O' ), -  DESC_ENTRY	(ZEBRA_ROUTE_OSPF6,	"ospf6",	'O' ), -  DESC_ENTRY	(ZEBRA_ROUTE_ISIS,	"isis",		'I' ), -  DESC_ENTRY	(ZEBRA_ROUTE_BGP,	"bgp",		'B' ), -  DESC_ENTRY	(ZEBRA_ROUTE_HSLS,	"hsls",		'H' ), -}; -#undef DESC_ENTRY -  #define DESC_ENTRY(T) [(T)] = { (T), (#T), '\0' }  static const struct zebra_desc_table command_types[] = {    DESC_ENTRY	(ZEBRA_INTERFACE_ADD), @@ -865,6 +844,7 @@ static const struct zebra_desc_table command_types[] = {    DESC_ENTRY	(ZEBRA_ROUTER_ID_ADD),    DESC_ENTRY	(ZEBRA_ROUTER_ID_DELETE),    DESC_ENTRY	(ZEBRA_ROUTER_ID_UPDATE), +  DESC_ENTRY	(ZEBRA_HELLO),  };  #undef DESC_ENTRY @@ -930,4 +910,52 @@ proto_name2num(const char *s)         return route_types[i].type;     return -1;  } +  #undef RTSIZE + +int +proto_redistnum(int afi, const char *s) +{ +  if (! s) +    return -1; + +  if (afi == AFI_IP) +    { +      if (strncmp (s, "k", 1) == 0) +	return ZEBRA_ROUTE_KERNEL; +      else if (strncmp (s, "c", 1) == 0) +	return ZEBRA_ROUTE_CONNECT; +      else if (strncmp (s, "s", 1) == 0) +	return ZEBRA_ROUTE_STATIC; +      else if (strncmp (s, "r", 1) == 0) +	return ZEBRA_ROUTE_RIP; +      else if (strncmp (s, "o", 1) == 0) +	return ZEBRA_ROUTE_OSPF; +      else if (strncmp (s, "i", 1) == 0) +	return ZEBRA_ROUTE_ISIS; +      else if (strncmp (s, "bg", 2) == 0) +	return ZEBRA_ROUTE_BGP; +      else if (strncmp (s, "ba", 2) == 0) +	return ZEBRA_ROUTE_BABEL; +    } +  if (afi == AFI_IP6) +    { +      if (strncmp (s, "k", 1) == 0) +	return ZEBRA_ROUTE_KERNEL; +      else if (strncmp (s, "c", 1) == 0) +	return ZEBRA_ROUTE_CONNECT; +      else if (strncmp (s, "s", 1) == 0) +	return ZEBRA_ROUTE_STATIC; +      else if (strncmp (s, "r", 1) == 0) +	return ZEBRA_ROUTE_RIPNG; +      else if (strncmp (s, "o", 1) == 0) +	return ZEBRA_ROUTE_OSPF6; +      else if (strncmp (s, "i", 1) == 0) +	return ZEBRA_ROUTE_ISIS; +      else if (strncmp (s, "bg", 2) == 0) +	return ZEBRA_ROUTE_BGP; +      else if (strncmp (s, "ba", 2) == 0) +	return ZEBRA_ROUTE_BABEL; +    } +  return -1; +} @@ -1,6 +1,4 @@  /* - * $Id$ - *   * Zebra logging funcions.   * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro   * @@ -51,7 +49,8 @@ typedef enum    ZLOG_RIP,    ZLOG_BGP,    ZLOG_OSPF, -  ZLOG_RIPNG,   +  ZLOG_RIPNG, +  ZLOG_BABEL,    ZLOG_OSPF6,    ZLOG_ISIS,    ZLOG_MASC @@ -148,12 +147,12 @@ extern int zlog_reset_file (struct zlog *zl);  extern int zlog_rotate (struct zlog *);  /* For hackey massage lookup and check */ -#define LOOKUP(x, y) mes_lookup(x, x ## _max, y, "(no item found)") +#define LOOKUP(x, y) mes_lookup(x, x ## _max, y, "(no item found)", #x)  extern const char *lookup (const struct message *, int);  extern const char *mes_lookup (const struct message *meslist,                                  int max, int index, -                               const char *no_item); +                               const char *no_item, const char *mesname);  extern const char *zlog_priority[];  extern const char *zlog_proto_names[]; @@ -298,3 +298,76 @@ static void md5_calc(const uint8_t *b64, md5_ctxt * ctxt)  	ctxt->md5_stc += C;  	ctxt->md5_std += D;  } + +/* From RFC 2104 */ +void +hmac_md5(text, text_len, key, key_len, digest) +unsigned char*  text;			/* pointer to data stream */ +int             text_len;		/* length of data stream */ +unsigned char*  key;			/* pointer to authentication key */ +int             key_len;		/* length of authentication key */ +caddr_t         digest;		/* caller digest to be filled in */ + +{ +    MD5_CTX context; +    unsigned char k_ipad[65];    /* inner padding - +				 * key XORd with ipad +				 */ +    unsigned char k_opad[65];    /* outer padding - +				 * key XORd with opad +				 */ +    unsigned char tk[16]; +    int i; +    /* if key is longer than 64 bytes reset it to key=MD5(key) */ +    if (key_len > 64) { + +       MD5_CTX      tctx; + +       MD5Init(&tctx); +       MD5Update(&tctx, key, key_len); +       MD5Final(tk, &tctx); + +       key = tk; +       key_len = 16; +    } + +    /* +     * the HMAC_MD5 transform looks like: +     * +     * MD5(K XOR opad, MD5(K XOR ipad, text)) +     * +     * where K is an n byte key +     * ipad is the byte 0x36 repeated 64 times +     * opad is the byte 0x5c repeated 64 times +     * and text is the data being protected +     */ + +    /* start out by storing key in pads */ +    bzero( k_ipad, sizeof k_ipad); +    bzero( k_opad, sizeof k_opad); +    bcopy( key, k_ipad, key_len); +    bcopy( key, k_opad, key_len); + +    /* XOR key with ipad and opad values */ +    for (i=0; i<64; i++) { +       k_ipad[i] ^= 0x36; +       k_opad[i] ^= 0x5c; +    } +    /* +     * perform inner MD5 +     */ +    MD5Init(&context);			/* init context for 1st +					 * pass */ +    MD5Update(&context, k_ipad, 64);	/* start with inner pad */ +    MD5Update(&context, text, text_len); /* then text of datagram */ +    MD5Final(digest, &context);	/* finish up 1st pass */ +    /* +     * perform outer MD5 +     */ +    MD5Init(&context);			/* init context for 2nd +					 * pass */ +    MD5Update(&context, k_opad, 64);	/* start with outer pad */ +    MD5Update(&context, digest, 16);	/* then results of 1st +					 * hash */ +    MD5Final(digest, &context);	/* finish up 2nd pass */ +} @@ -82,4 +82,7 @@ do {				\  	md5_result((x), (y));	\  } while (0) +/* From RFC 2104 */ +void hmac_md5(unsigned char* text, int text_len, unsigned char* key, int key_len, caddr_t digest); +  #endif /* ! _LIBZEBRA_MD5_H_*/ diff --git a/lib/memory.c b/lib/memory.c index 4090fd90..684ebcff 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -466,6 +466,17 @@ DEFUN (show_memory_ripng,    return CMD_SUCCESS;  } +DEFUN (show_memory_babel, +       show_memory_babel_cmd, +       "show memory babel", +       SHOW_STR +       "Memory statistics\n" +       "Babel memory\n") +{ +  show_memory_vty (vty, memory_list_babel); +  return CMD_SUCCESS; +} +  DEFUN (show_memory_bgp,         show_memory_bgp_cmd,         "show memory bgp", @@ -518,6 +529,7 @@ memory_init (void)    install_element (RESTRICTED_NODE, &show_memory_lib_cmd);    install_element (RESTRICTED_NODE, &show_memory_rip_cmd);    install_element (RESTRICTED_NODE, &show_memory_ripng_cmd); +  install_element (RESTRICTED_NODE, &show_memory_babel_cmd);    install_element (RESTRICTED_NODE, &show_memory_bgp_cmd);    install_element (RESTRICTED_NODE, &show_memory_ospf_cmd);    install_element (RESTRICTED_NODE, &show_memory_ospf6_cmd); @@ -528,6 +540,7 @@ memory_init (void)    install_element (VIEW_NODE, &show_memory_lib_cmd);    install_element (VIEW_NODE, &show_memory_rip_cmd);    install_element (VIEW_NODE, &show_memory_ripng_cmd); +  install_element (VIEW_NODE, &show_memory_babel_cmd);    install_element (VIEW_NODE, &show_memory_bgp_cmd);    install_element (VIEW_NODE, &show_memory_ospf_cmd);    install_element (VIEW_NODE, &show_memory_ospf6_cmd); @@ -539,6 +552,7 @@ memory_init (void)    install_element (ENABLE_NODE, &show_memory_zebra_cmd);    install_element (ENABLE_NODE, &show_memory_rip_cmd);    install_element (ENABLE_NODE, &show_memory_ripng_cmd); +  install_element (ENABLE_NODE, &show_memory_babel_cmd);    install_element (ENABLE_NODE, &show_memory_bgp_cmd);    install_element (ENABLE_NODE, &show_memory_ospf_cmd);    install_element (ENABLE_NODE, &show_memory_ospf6_cmd); diff --git a/lib/memtypes.c b/lib/memtypes.c index dca32caa..245c8d8a 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -5,8 +5,6 @@   *   * The script is sensitive to the format (though not whitespace), see   * the top of memtypes.awk for more details. - * - * $Id$   */  #include "zebra.h" @@ -177,6 +175,13 @@ struct memory_list memory_list_ripng[] =    { -1, NULL }  }; +struct memory_list memory_list_babel[] = +{ +  { MTYPE_BABEL,              "Babel structure"			}, +  { MTYPE_BABEL_IF,           "Babel interface"			}, +  { -1, NULL } +}; +  struct memory_list memory_list_ospf[] =  {    { MTYPE_OSPF_TOP,           "OSPF top"			}, diff --git a/lib/prefix.c b/lib/prefix.c index 61a278ca..a3b1adf8 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -32,6 +32,139 @@  static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,  			         0xf8, 0xfc, 0xfe, 0xff}; +static const struct in6_addr maskbytes6[] = +{ +  /* /0   */ { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /1   */ { { { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /2   */ { { { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /3   */ { { { 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /4   */ { { { 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /5   */ { { { 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /6   */ { { { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /7   */ { { { 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /8   */ { { { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /9   */ { { { 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /10  */ { { { 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /11  */ { { { 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /12  */ { { { 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /13  */ { { { 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /14  */ { { { 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /15  */ { { { 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /16  */ { { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /17  */ { { { 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /18  */ { { { 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /19  */ { { { 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /20  */ { { { 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /21  */ { { { 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /22  */ { { { 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /23  */ { { { 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /24  */ { { { 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /25  */ { { { 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /26  */ { { { 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /27  */ { { { 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /28  */ { { { 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /29  */ { { { 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /30  */ { { { 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /31  */ { { { 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /32  */ { { { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /33  */ { { { 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /34  */ { { { 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /35  */ { { { 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /36  */ { { { 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /37  */ { { { 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /38  */ { { { 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /39  */ { { { 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /40  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /41  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /42  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /43  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /44  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /45  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /46  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /47  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /48  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /49  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /50  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /51  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /52  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /53  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /54  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /55  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /56  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /57  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /58  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /59  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /60  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /61  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /62  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /63  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /64  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /65  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /66  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /67  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /68  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /69  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /70  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /71  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /72  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /73  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /74  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /75  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /76  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /77  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /78  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /79  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /80  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /81  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /82  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /83  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /84  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /85  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /86  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /87  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /88  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /89  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /90  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /91  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /92  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /93  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /94  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /95  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /96  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } }, +  /* /97  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00 } } }, +  /* /98  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00 } } }, +  /* /99  */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00 } } }, +  /* /100 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00 } } }, +  /* /101 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00 } } }, +  /* /102 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00 } } }, +  /* /103 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00 } } }, +  /* /104 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00 } } }, +  /* /105 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00 } } }, +  /* /106 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00 } } }, +  /* /107 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00 } } }, +  /* /108 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00 } } }, +  /* /109 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00 } } }, +  /* /110 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00 } } }, +  /* /111 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00 } } }, +  /* /112 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } } }, +  /* /113 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00 } } }, +  /* /114 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00 } } }, +  /* /115 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00 } } }, +  /* /116 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00 } } }, +  /* /117 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00 } } }, +  /* /118 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00 } } }, +  /* /119 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00 } } }, +  /* /120 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 } } }, +  /* /121 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80 } } }, +  /* /122 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0 } } }, +  /* /123 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0 } } }, +  /* /124 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0 } } }, +  /* /125 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8 } } }, +  /* /126 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc } } }, +  /* /127 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe } } }, +  /* /128 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } } +}; +  /* Number of bits in prefix type. */  #ifndef PNBBY  #define PNBBY 8 @@ -39,6 +172,21 @@ static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,  #define MASKBIT(offset)  ((0xff << (PNBBY - (offset))) & 0xff) +unsigned int +prefix_bit (const u_char *prefix, const u_char prefixlen) +{ +  unsigned int offset = prefixlen / 8; +  unsigned int shift  = 7 - (prefixlen % 8); +   +  return (prefix[offset] >> shift) & 1; +} + +unsigned int +prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen) +{ +  return prefix_bit((const u_char *) &prefix->s6_addr, prefixlen); +} +  /* Address Famiy Identifier to Address Family converter. */  int  afi2family (afi_t afi) @@ -133,11 +281,11 @@ prefix_same (const struct prefix *p1, const struct prefix *p2)    if (p1->family == p2->family && p1->prefixlen == p2->prefixlen)      {        if (p1->family == AF_INET) -	if (IPV4_ADDR_SAME (&p1->u.prefix, &p2->u.prefix)) +	if (IPV4_ADDR_SAME (&p1->u.prefix4.s_addr, &p2->u.prefix4.s_addr))  	  return 1;  #ifdef HAVE_IPV6        if (p1->family == AF_INET6 ) -	if (IPV6_ADDR_SAME (&p1->u.prefix, &p2->u.prefix)) +	if (IPV6_ADDR_SAME (&p1->u.prefix6.s6_addr, &p2->u.prefix6.s6_addr))  	  return 1;  #endif /* HAVE_IPV6 */      } @@ -167,8 +315,8 @@ prefix_cmp (const struct prefix *p1, const struct prefix *p2)    if (p1->family != p2->family || p1->prefixlen != p2->prefixlen)      return 1; -  offset = p1->prefixlen / 8; -  shift = p1->prefixlen % 8; +  offset = p1->prefixlen / PNBBY; +  shift = p1->prefixlen % PNBBY;    if (shift)      if (maskbit[shift] & (pp1[offset] ^ pp2[offset])) @@ -181,6 +329,46 @@ prefix_cmp (const struct prefix *p1, const struct prefix *p2)    return 0;  } +/* + * Count the number of common bits in 2 prefixes. The prefix length is + * ignored for this function; the whole prefix is compared. If the prefix + * address families don't match, return -1; otherwise the return value is + * in range 0 ... maximum prefix length for the address family. + */ +int +prefix_common_bits (const struct prefix *p1, const struct prefix *p2) +{ +  int pos, bit; +  int length = 0; +  u_char xor; + +  /* Set both prefix's head pointer. */ +  const u_char *pp1 = (const u_char *)&p1->u.prefix; +  const u_char *pp2 = (const u_char *)&p2->u.prefix; + +  if (p1->family == AF_INET) +    length = IPV4_MAX_BYTELEN; +#ifdef HAVE_IPV6 +  if (p1->family == AF_INET6) +    length = IPV6_MAX_BYTELEN; +#endif +  if (p1->family != p2->family || !length) +    return -1; + +  for (pos = 0; pos < length; pos++) +    if (pp1[pos] != pp2[pos]) +      break; +  if (pos == length) +    return pos * 8; + +  xor = pp1[pos] ^ pp2[pos]; +  for (bit = 0; bit < 8; bit++) +    if (xor & (1 << (7 - bit))) +      break; + +  return pos * 8 + bit; +} +  /* Return prefix family type string. */  const char *  prefix_family_str (const struct prefix *p) @@ -261,25 +449,20 @@ str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p)    return ret;  } -/* Convert masklen into IP address's netmask. */ +/* Convert masklen into IP address's netmask (network byte order). */  void -masklen2ip (int masklen, struct in_addr *netmask) +masklen2ip (const int masklen, struct in_addr *netmask)  { -  u_char *pnt; -  int bit; -  int offset; +  assert (masklen >= 0 && masklen <= IPV4_MAX_BITLEN); -  memset (netmask, 0, sizeof (struct in_addr)); -  pnt = (unsigned char *) netmask; +  /* left shift is only defined for less than the size of the type. +   * we unconditionally use long long in case the target platform +   * has defined behaviour for << 32 (or has a 64-bit left shift) */ -  offset = masklen / 8; -  bit = masklen % 8; -   -  while (offset--) -    *pnt++ = 0xff; - -  if (bit) -    *pnt = maskbit[bit]; +  if (sizeof(unsigned long long) > 4) +    netmask->s_addr = htonl(0xffffffffULL << (32 - masklen)); +  else +    netmask->s_addr = htonl(masklen ? 0xffffffffU << (32 - masklen) : 0);  }  /* Convert IP address's netmask into integer. We assume netmask is @@ -287,54 +470,22 @@ masklen2ip (int masklen, struct in_addr *netmask)  u_char  ip_masklen (struct in_addr netmask)  { -  u_char len; -  u_char *pnt; -  u_char *end; -  u_char val; - -  len = 0; -  pnt = (u_char *) &netmask; -  end = pnt + 4; - -  while ((pnt < end) && (*pnt == 0xff)) -    { -      len+= 8; -      pnt++; -    }  - -  if (pnt < end) -    { -      val = *pnt; -      while (val) -	{ -	  len++; -	  val <<= 1; -	} -    } -  return len; +  uint32_t tmp = ~ntohl(netmask.s_addr); +  if (tmp) +    /* clz: count leading zeroes. sadly, the behaviour of this builtin +     * is undefined for a 0 argument, even though most CPUs give 32 */ +    return __builtin_clz(tmp); +  else +    return 32;  } -/* Apply mask to IPv4 prefix. */ +/* Apply mask to IPv4 prefix (network byte order). */  void  apply_mask_ipv4 (struct prefix_ipv4 *p)  { -  u_char *pnt; -  int index; -  int offset; - -  index = p->prefixlen / 8; - -  if (index < 4) -    { -      pnt = (u_char *) &p->prefix; -      offset = p->prefixlen % 8; - -      pnt[index] &= maskbit[offset]; -      index++; - -      while (index < 4) -	pnt[index++] = 0; -    } +  struct in_addr mask; +  masklen2ip(p->prefixlen, &mask); +  p->prefix.s_addr &= mask.s_addr;  }  /* If prefix is 0.0.0.0/0 then return 1 else return 0. */ @@ -396,7 +547,7 @@ str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p)        if (ret == 0)  	return 0;        plen = (u_char) atoi (++pnt); -      if (plen > 128) +      if (plen > IPV6_MAX_BITLEN)  	return 0;        p->prefixlen = plen;      } @@ -416,13 +567,13 @@ ip6_masklen (struct in6_addr netmask)    pnt = (unsigned char *) & netmask; -  while ((*pnt == 0xff) && len < 128)  +  while ((*pnt == 0xff) && len < IPV6_MAX_BITLEN)      {        len += 8;        pnt++;      }  -  if (len < 128)  +  if (len < IPV6_MAX_BITLEN)      {        val = *pnt;        while (val)  @@ -435,23 +586,10 @@ ip6_masklen (struct in6_addr netmask)  }  void -masklen2ip6 (int masklen, struct in6_addr *netmask) +masklen2ip6 (const int masklen, struct in6_addr *netmask)  { -  unsigned char *pnt; -  int bit; -  int offset; - -  memset (netmask, 0, sizeof (struct in6_addr)); -  pnt = (unsigned char *) netmask; - -  offset = masklen / 8; -  bit = masklen % 8; - -  while (offset--) -    *pnt++ = 0xff; - -  if (bit) -    *pnt = maskbit[bit]; +  assert (masklen >= 0 && masklen <= IPV6_MAX_BITLEN); +  memcpy (netmask, maskbytes6 + masklen, sizeof (struct in6_addr));  }  void @@ -570,6 +708,20 @@ sockunion2hostprefix (const union sockunion *su)    return NULL;  } +void +prefix2sockunion (const struct prefix *p, union sockunion *su) +{ +  memset (su, 0, sizeof (*su)); + +  su->sa.sa_family = p->family; +  if (p->family == AF_INET) +    su->sin.sin_addr = p->u.prefix4; +#ifdef HAVE_IPV6 +  if (p->family == AF_INET6) +    memcpy (&su->sin6.sin6_addr, &p->u.prefix6, sizeof (struct in6_addr)); +#endif /* HAVE_IPV6 */ +} +  int  prefix_blen (const struct prefix *p)  { diff --git a/lib/prefix.h b/lib/prefix.h index 5f1ff05c..7f0d3607 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -112,6 +112,7 @@ struct prefix_rd  #define IPV4_NET0(a)    ((((u_int32_t) (a)) & 0xff000000) == 0x00000000)  #define IPV4_NET127(a)  ((((u_int32_t) (a)) & 0xff000000) == 0x7f000000)  #define IPV4_LINKLOCAL(a) ((((u_int32_t) (a)) & 0xffff0000) == 0xa9fe0000) +#define IPV4_CLASS_DE(a)  ((((u_int32_t) (a)) & 0xe0000000) == 0xe0000000)  /* Max bit/byte length of IPv6 address. */  #define IPV6_MAX_BYTELEN    16 @@ -127,26 +128,14 @@ struct prefix_rd  /* Prefix's family member. */  #define PREFIX_FAMILY(p)  ((p)->family) -/* Check bit of the prefix. */ -static inline unsigned int -prefix_bit (const u_char *prefix, const u_char prefixlen) -{ -  unsigned int offset = prefixlen / 8; -  unsigned int shift  = 7 - (prefixlen % 8); - -  return (prefix[offset] >> shift) & 1; -} - -static inline unsigned int -prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen) -{ -  return prefix_bit((const u_char *) &prefix->s6_addr, prefixlen); -} -  /* Prototypes. */  extern int afi2family (afi_t);  extern afi_t family2afi (int); +/* Check bit of the prefix. */ +extern unsigned int prefix_bit (const u_char *prefix, const u_char prefixlen); +extern unsigned int prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen); +  extern struct prefix *prefix_new (void);  extern void prefix_free (struct prefix *);  extern const char *prefix_family_str (const struct prefix *); @@ -156,12 +145,14 @@ extern int prefix2str (const struct prefix *, char *, int);  extern int prefix_match (const struct prefix *, const struct prefix *);  extern int prefix_same (const struct prefix *, const struct prefix *);  extern int prefix_cmp (const struct prefix *, const struct prefix *); +extern int prefix_common_bits (const struct prefix *, const struct prefix *);  extern void prefix_copy (struct prefix *dest, const struct prefix *src);  extern void apply_mask (struct prefix *);  extern struct prefix *sockunion2prefix (const union sockunion *dest,                                          const union sockunion *mask);  extern struct prefix *sockunion2hostprefix (const union sockunion *); +extern void prefix2sockunion (const struct prefix *, union sockunion *);  extern struct prefix_ipv4 *prefix_ipv4_new (void);  extern void prefix_ipv4_free (struct prefix_ipv4 *); @@ -175,7 +166,7 @@ extern int prefix_ipv4_any (const struct prefix_ipv4 *);  extern void apply_classful_mask_ipv4 (struct prefix_ipv4 *);  extern u_char ip_masklen (struct in_addr); -extern void masklen2ip (int, struct in_addr *); +extern void masklen2ip (const int, struct in_addr *);  /* returns the network portion of the host address */  extern in_addr_t ipv4_network_addr (in_addr_t hostaddr, int masklen);  /* given the address of a host on a network and the network mask length, @@ -196,7 +187,7 @@ extern void apply_mask_ipv6 (struct prefix_ipv6 *);  	*((struct prefix_ipv6 *)(DST)) = *((const struct prefix_ipv6 *)(SRC));  extern int ip6_masklen (struct in6_addr); -extern void masklen2ip6 (int, struct in6_addr *); +extern void masklen2ip6 (const int, struct in6_addr *);  extern void str2in6_addr (const char *, struct in6_addr *);  extern const char *inet6_ntoa (struct in6_addr); diff --git a/lib/route_types.awk b/lib/route_types.awk deleted file mode 100644 index eb3d382a..00000000 --- a/lib/route_types.awk +++ /dev/null @@ -1,187 +0,0 @@ -# $Id$ -# -# Scan a file of route-type definitions (see eg route_types.txt) and -# generate a corresponding header file with: -# -# - enum of Zserv route-types -# - redistribute strings for the various Quagga daemons -# -# See route_types.txt for the format. -# -# - -BEGIN { -	FS="[,]"; -	 -	# globals -	exitret = 0; -	tcount = 0; -	 -	# formats for output -	## the define format -	redist_def_fmt = "#define QUAGGA_REDIST_STR_%s \\\n"; -	## DEFUN/vty route-type argument -	redist_str_fmt = "\"(%s)\"\n"; -	redist_help_def_fmt = "#define QUAGGA_REDIST_HELP_STR_%s"; -	redist_help_str_fmt = " \\\n  \"%s\\n\""; -	 -	# header -	header = "/* Auto-generated from route_types.txt by " ARGV[0] ". */\n"; -	header = header "/* Do not edit! */\n"; -	header = header "\n#ifndef _QUAGGA_ROUTE_TYPES_H\n"; -	header = header "#define _QUAGGA_ROUTE_TYPES_H\n"; -	footer = "#endif /* _QUAGGA_ROUTE_TYPES_H */\n"; -	printf ("%s\n", header); -} - -# Chomp comment lines -($0 ~ /^#/) {  -	next; -} - -# get rid of the commas, leading/trailling whitespace and -# quotes -{ -	for (i = 1; i <= NF; i++) { -		#print "before:" $i; -		$i = gensub(/^[[:blank:]]*(.*)[,]*.*/, "\\1", "g",$i); -		$i = gensub(/^["](.*)["]$/, "\\1", "g", $i); -		#print "after :" $i; -	} -} - -# 7 field format: -#  type                 cname      daemon  C    4  6  short help -(NF >= 7) { -	#print "7", $1, $0; -	 -	if ($1 in types) { -		print "error: attempt to redefine", $1; -		exitret = 1; -		exit exitret; -	} -	 -	typesbynum[tcount] = $1; -	types[$1,"num"] = tcount++;  -	types[$1,"cname"] = $2; -	types[$1,"daemon"] = $3; -	types[$1,"C"] = $4; -	types[$1,"4"] = strtonum($5); -	types[$1,"6"] = strtonum($6); -	types[$1,"shelp"] = $7; -	 -	#print "num   :", types[$1,"num"] -	#print "cname :", types[$1,"cname"] -	#print "daemon:", types[$1,"daemon"]; -	#print "char  :", types[$1,"C"]; -}; - -# 2 field: type "long description" -(NF == 2) { -	#print "2", $1, $2; -	 -	if (!(($1 SUBSEP "num") in types)) { -		print "error: type", $1, "must be defined before help str"; -		exitret = 2; -		exit exitret; -	} -	 -	types[$1,"lhelp"] = $2; -} - -END { -	if (exitret) -		exit exitret; -	 -	# The enums -	# not yet... -	#printf("enum\n{\n"); -	#for (i = 0; i < tcount; i++) { -	#	type = typesbynum[i]; -	#	if (type != "" && types[type,"num"] == i) -	#		printf ("  %s,\n", type); -	#} -	#printf ("  ZEBRA_ROUTE_MAX,\n};\n\n"); -	 -	# the redistribute defines -	for (i = 0; i < tcount; i++) { -		type = typesbynum[i]; -		 -		# must be a type, and must cross-check against recorded type -		if (type == "" || types[type,"num"] != i) -			continue; -		 -		# ignore route types that can't be redistributed -		if (!(types[type,"4"] || types[type,"6"])) -			continue; -		 -		# must have a daemon name -		if (!((type SUBSEP "daemon") in types)) -			continue; -		if (!(daemon = types[type,"daemon"])) -			continue; -		 -		# might have done this daemon already? -		if (daemon in seen_daemons) -			continue; -		 -		cname = types[type,"cname"]; -		all = all "|" cname; -		rstr = ""; -		hstr = ""; -		 -		# add it to the others -		for (j = 0; j < tcount; j++) { -			# ignore self -			if (i == j) -				continue; -			 -			type2 = typesbynum[j]; -			 -			# type2 must be valid, and self-check. -			if (type2 == "" || types[type2,"num"] != j) -				continue; -			 -			# ignore different route types for the same daemon -			# (eg system/kernel/connected) -			if (types[type2,"daemon"] == daemon) -				continue; -			 -			if ((types[type2,"4"] && types[type,"4"]) \ -			    || (types[type2,"6"] && types[type,"6"])) { -			    	 -			    	if (rstr == "") -			    		rstr = types[type2,"cname"]; -				else -					rstr = rstr "|" types[type2,"cname"]; -				 -				if ((type2 SUBSEP "lhelp") in types) -				  hstr2 = types[type2,"lhelp"]; -				else if ((type2 SUBSEP "shelp") in types) -				  hstr2 = types[type2,"shelp"]; -				else -				  hstr2 = types[type2,"cname"]; -				 -				hstr = hstr sprintf(redist_help_str_fmt, hstr2); -			} -		} -		 -		# dont double-process daemons. -		seen_daemons[daemon] = 1; -		 -		printf("/* %s */\n", daemon); -		printf(redist_def_fmt, toupper(daemon)); -		printf(redist_str_fmt, rstr); -		printf(redist_help_def_fmt, toupper(daemon)); -		printf("%s", hstr); -		printf("\n\n"); -	} -	 -	#printf("#define QUAGGA_REDIST_STR_ALL %s\n",all); -			 -#	for (i = 0; i < lcount; i++) { -#		if (mlists[i] != "") -#			printf (mlistformat "\n", mlists[i]); -#	} -	printf (footer); -} diff --git a/lib/route_types.pl b/lib/route_types.pl new file mode 100755 index 00000000..e1595afc --- /dev/null +++ b/lib/route_types.pl @@ -0,0 +1,199 @@ +#!/usr/bin/perl +## +## Scan a file of route-type definitions (see eg route_types.txt) and +## generate a corresponding header file with: +## +## - enum of Zserv route-types +## - redistribute strings for the various Quagga daemons +## +## See route_types.txt for the format. +## +## +## Copyright (C) 2009 David Lamparter. +## This file is part of GNU Zebra. +## +## GNU Zebra is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by the +## Free Software Foundation; either version 2, or (at your option) any +## later version. +## +## GNU Zebra is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with GNU Zebra; see the file COPYING.  If not, write to the Free +## Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +## 02111-1307, USA. +## + +use strict; + +# input processing +# +my @protos; +my %protodetail; + +my %daemons; + +while (<STDIN>) { +	# skip comments and empty lines +	next if (/^\s*(#|$)/); + +	# strip whitespace +	chomp; +	$_ =~ s/^\s*//; +	$_ =~ s/\s*$//; + +	# match help strings +	if (/^(ZEBRA_ROUTE_[^\s]+)\s*,\s*"(.*)"$/) { +		$protodetail{$1}->{'longhelp'} = $2; +		next; +	} + +	$_ =~ s/\s*,\s*/,/g; + +	# else: 7-field line +	my @f = split(/,/, $_); +	unless (@f == 7) { +		die "invalid input on route_types line $.\n"; +	} + +	my $proto = $f[0]; +	$f[3] = $1 if ($f[3] =~ /^'(.*)'$/); +	$f[6] = $1 if ($f[6] =~ /^"(.*)"$/); + +	$protodetail{$proto} = { +		"number" => scalar @protos, +		"type" => $f[0], +		"cname" => $f[1], +		"daemon" => $f[2], +		"char" => $f[3], +		"ipv4" => int($f[4]), +		"ipv6" => int($f[5]), +		"shorthelp" => $f[6], +	}; +	push @protos, $proto; +	$daemons{$f[2]} = { +		"ipv4" => int($f[4]), +		"ipv6" => int($f[5]) +	} unless ($f[2] eq "NULL"); +} + +# output +printf <<EOF, $ARGV[0]; +/* Auto-generated from route_types.txt by %s. */ +/* Do not edit! */ + +#ifndef _QUAGGA_ROUTE_TYPES_H +#define _QUAGGA_ROUTE_TYPES_H + +/* Zebra route's types. */ +EOF + +push @protos, "ZEBRA_ROUTE_MAX"; +my (@protosv4, @protosv6) = ((), ()); +for (my $c = 0; $c < @protos; $c++) { +	my $p = $protos[$c]; +	printf "#define %-32s %d\n", $p, $c; +	push @protosv4, $p if ($protodetail{$p}->{"ipv4"}); +	push @protosv6, $p if ($protodetail{$p}->{"ipv6"}); +} +pop @protos; + +sub codelist { +	my (@protos) = @_; +	my (@lines) = (); +	my $str = "  \"Codes: "; +	for my $p (@protos) { +		my $s = sprintf("%s - %s, ", +			$protodetail{$p}->{"char"}, +			$protodetail{$p}->{"shorthelp"}); +		if (length($str . $s) > 70) { +			$str =~ s/ $//; +			push @lines, $str . "%s\" \\\n"; +			$str = "  \"       "; +		} +		$str .= $s; +	} +	$str =~ s/ $//; +	push @lines, $str . "%s\" \\\n"; +	push @lines, "  \"       > - selected route, * - FIB route%s%s\", \\\n"; +	my @nl = (); +	for (my $c = 0; $c < @lines + 1; $c++) { +		push @nl, "VTY_NEWLINE" +	} +	return join("", @lines) ."  ". join(", ", @nl); +} + +print "\n"; +printf "#define SHOW_ROUTE_V4_HEADER \\\n%s\n", codelist(@protosv4); +printf "#define SHOW_ROUTE_V6_HEADER \\\n%s\n", codelist(@protosv6); +print "\n"; + +sub collect { +	my ($daemon, $ipv4, $ipv6) = @_; +	my (@names, @help) = ((), ()); +	for my $p (@protos) { +		next if ($protodetail{$p}->{"daemon"} eq $daemon && $daemon ne "zebra"); +		next unless (($ipv4 && $protodetail{$p}->{"ipv4"}) +				|| ($ipv6 && $protodetail{$p}->{"ipv6"})); +		push @names, $protodetail{$p}->{"cname"}; +		push @help, "  \"".$protodetail{$p}->{"longhelp"}."\\n\""; +	} +	return ("\"(" . join("|", @names) . ")\"", join(" \\\n", @help)); +} + +for my $daemon (sort keys %daemons) { +	next unless ($daemons{$daemon}->{"ipv4"} || $daemons{$daemon}->{"ipv6"}); +	printf "/* %s */\n", $daemon; +	if ($daemons{$daemon}->{"ipv4"} && $daemons{$daemon}->{"ipv6"}) { +		my ($names, $help) = collect($daemon, 1, 1); +		printf "#define QUAGGA_REDIST_STR_%s \\\n  %s\n", uc $daemon, $names; +		printf "#define QUAGGA_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help; +		($names, $help) = collect($daemon, 1, 0); +		printf "#define QUAGGA_IP_REDIST_STR_%s \\\n  %s\n", uc $daemon, $names; +		printf "#define QUAGGA_IP_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help; +		($names, $help) = collect($daemon, 0, 1); +		printf "#define QUAGGA_IP6_REDIST_STR_%s \\\n  %s\n", uc $daemon, $names; +		printf "#define QUAGGA_IP6_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help; +	} else { +		my ($names, $help) = collect($daemon, +			$daemons{$daemon}->{"ipv4"}, $daemons{$daemon}->{"ipv6"}); +		printf "#define QUAGGA_REDIST_STR_%s \\\n  %s\n", uc $daemon, $names; +		printf "#define QUAGGA_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help; +	} +	print "\n"; +} + +print <<EOF; + +#ifdef QUAGGA_DEFINE_DESC_TABLE + +struct zebra_desc_table +{ +  unsigned int type; +  const char *string; +  char chr; +}; + +#define DESC_ENTRY(T,S,C) [(T)] = { (T), (S), (C) } +static const struct zebra_desc_table route_types[] = { +EOF + +for (my $c = 0; $c < @protos; $c++) { +	my $p = $protos[$c]; +	printf "  DESC_ENTRY\t(%s\t \"%s\",\t'%s' ),\n", +	       $p.",", $protodetail{$p}->{"cname"}, $protodetail{$p}->{"char"}; +} + +print <<EOF; +}; +#undef DESC_ENTRY + +#endif /* QUAGGA_DEFINE_DESC_TABLE */ + +#endif /* _QUAGGA_ROUTE_TYPES_H */ +EOF + diff --git a/lib/route_types.txt b/lib/route_types.txt index e99cacde..cebf01fc 100644 --- a/lib/route_types.txt +++ b/lib/route_types.txt @@ -42,13 +42,13 @@  ##  type                cname      daemon  C    4  6  short help  ZEBRA_ROUTE_SYSTEM,     system,    NULL,   'X', 0, 0, "Reserved" -ZEBRA_ROUTE_KERNEL,     kernel,    zebra,  'K', 1, 1, NULL -ZEBRA_ROUTE_CONNECT,    connected, zebra,  'C', 1, 1, NULL -ZEBRA_ROUTE_STATIC,     static,    zebra,  'S', 1, 1, NULL +ZEBRA_ROUTE_KERNEL,     kernel,    zebra,  'K', 1, 1, "kernel route" +ZEBRA_ROUTE_CONNECT,    connected, zebra,  'C', 1, 1, "connected" +ZEBRA_ROUTE_STATIC,     static,    zebra,  'S', 1, 1, "static"  ZEBRA_ROUTE_RIP,        rip,       ripd,   'R', 1, 0, "RIP"  ZEBRA_ROUTE_RIPNG,      ripng,     ripngd, 'R', 0, 1, "RIPng"  ZEBRA_ROUTE_OSPF,       ospf,      ospfd,  'O', 1, 0, "OSPF" -ZEBRA_ROUTE_OSPF6,      ospf6,     ospf6d, 'O', 0, 1, "OSPF" +ZEBRA_ROUTE_OSPF6,      ospf6,     ospf6d, 'O', 0, 1, "OSPFv6"  ZEBRA_ROUTE_ISIS,       isis,      isisd,  'I', 1, 1, "IS-IS"  ZEBRA_ROUTE_BGP,        bgp,       bgpd,   'B', 1, 1, "BGP"  # HSLS and OLSR both are AFI independent (so: 1, 1), however @@ -57,7 +57,8 @@ ZEBRA_ROUTE_BGP,        bgp,       bgpd,   'B', 1, 1, "BGP"  # to 'switch on' redist support (direct numeric entry remaining  # possible).  ZEBRA_ROUTE_HSLS,       hsls,      hslsd,  'H', 0, 0, "HSLS" -ZEBRA_ROUTE_OLSR,       olsr,      oslrd,  'o', 0, 0, "OLSR" +ZEBRA_ROUTE_OLSR,       olsr,      olsrd,  'o', 0, 0, "OLSR" +ZEBRA_ROUTE_BABEL,      babel,     babeld, 'A', 1, 1, "Babel"  ## help strings  ZEBRA_ROUTE_SYSTEM, "Reserved route type, for internal use only" @@ -72,3 +73,4 @@ ZEBRA_ROUTE_ISIS,   "Intermediate System to Intermediate System (IS-IS)"  ZEBRA_ROUTE_BGP,    "Border Gateway Protocol (BGP)"  ZEBRA_ROUTE_HSLS,   "Hazy-Sighted Link State Protocol (HSLS)"  ZEBRA_ROUTE_OLSR,   "Optimised Link State Routing (OLSR)" +ZEBRA_ROUTE_BABEL,  "Babel routing protocol (Babel)" diff --git a/lib/routemap.h b/lib/routemap.h index 1402f5c8..ba64553f 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -43,6 +43,7 @@ typedef enum  {    RMAP_RIP,    RMAP_RIPNG, +  RMAP_BABEL,    RMAP_OSPF,    RMAP_OSPF6,    RMAP_BGP, @@ -270,7 +270,6 @@ static void  smux_getresp_send (oid objid[], size_t objid_len, long reqid, long errstat,  		   long errindex, u_char val_type, void *arg, size_t arg_len)  { -  int ret;    u_char buf[BUFSIZ];    u_char *ptr, *h1, *h1e, *h2, *h2e;    size_t len, length; @@ -326,7 +325,7 @@ smux_getresp_send (oid objid[], size_t objid_len, long reqid, long errstat,    if (debug_smux)      zlog_debug ("SMUX getresp send: %td", (ptr - buf)); -  ret = send (smux_sock, buf, (ptr - buf), 0); +  send (smux_sock, buf, (ptr - buf), 0);  }  static u_char * @@ -946,7 +945,7 @@ smux_open (int sock)    u_char *ptr;    size_t len;    long version; -  u_char progname[] = QUAGGA_PROGNAME "-" QUAGGA_VERSION; +  const char progname[] = QUAGGA_PROGNAME "-" QUAGGA_VERSION;    if (debug_smux)      { @@ -977,7 +976,7 @@ smux_open (int sock)    ptr = asn_build_string (ptr, &len,   			  (u_char)  			  (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), -			  progname, strlen (progname)); +			  (const u_char *) progname, strlen (progname));    /* SMUX connection password. */    ptr = asn_build_string (ptr, &len,  diff --git a/lib/sockopt.c b/lib/sockopt.c index 55c6226b..be22827f 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -179,12 +179,25 @@ getsockopt_ipv6_ifindex (struct msghdr *msgh)    return pktinfo->ipi6_ifindex;  } -#endif /* HAVE_IPV6 */ +int +setsockopt_ipv6_tclass(int sock, int tclass) +{ +  int ret = 0; + +#ifdef IPV6_TCLASS /* RFC3542 */ +  ret = setsockopt (sock, IPPROTO_IPV6, IPV6_TCLASS, &tclass, sizeof (tclass)); +  if (ret < 0) +    zlog_warn ("Can't set IPV6_TCLASS option for fd %d to %#x: %s", +	       sock, tclass, safe_strerror(errno)); +#endif +  return ret; +} +#endif /* HAVE_IPV6 */  /*   * Process multicast socket options for IPv4 in an OS-dependent manner. - * Supported options are IP_MULTICAST_IF and IP_{ADD,DROP}_MEMBERSHIP. + * Supported options are IP_{ADD,DROP}_MEMBERSHIP.   *   * Many operating systems have a limit on the number of groups that   * can be joined per socket (where each group and local address @@ -204,121 +217,133 @@ getsockopt_ipv6_ifindex (struct msghdr *msgh)   * allow leaves, or implicitly leave all groups joined to down interfaces.   */  int -setsockopt_multicast_ipv4(int sock,  +setsockopt_ipv4_multicast(int sock,  			int optname,  -			struct in_addr if_addr /* required */,  			unsigned int mcast_addr, -			unsigned int ifindex /* optional: if non-zero, may be -						  used instead of if_addr */) +			unsigned int ifindex)  { +#ifdef HAVE_RFC3678 +  struct group_req gr; +  struct sockaddr_in *si; +  int ret; +  memset (&gr, 0, sizeof(gr)); +  si = (struct sockaddr_in *)&gr.gr_group; +  gr.gr_interface = ifindex; +  si->sin_family = AF_INET; +#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN +  si->sin_len = sizeof(struct sockaddr_in); +#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ +  si->sin_addr.s_addr = mcast_addr; +  ret = setsockopt(sock, IPPROTO_IP, (optname == IP_ADD_MEMBERSHIP) ?  +    MCAST_JOIN_GROUP : MCAST_LEAVE_GROUP, (void *)&gr, sizeof(gr)); +  if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) +    { +      setsockopt(sock, IPPROTO_IP, MCAST_LEAVE_GROUP, (void *)&gr, sizeof(gr)); +      ret = setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, (void *)&gr, sizeof(gr)); +    } +  return ret; -#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX -  /* This is better because it uses ifindex directly */ +#elif defined(HAVE_STRUCT_IP_MREQN_IMR_IFINDEX) && !defined(__FreeBSD__)    struct ip_mreqn mreqn;    int ret; -  switch (optname) -    { -    case IP_MULTICAST_IF: -    case IP_ADD_MEMBERSHIP: -    case IP_DROP_MEMBERSHIP: -      memset (&mreqn, 0, sizeof(mreqn)); +  assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP); +  memset (&mreqn, 0, sizeof(mreqn)); -      if (mcast_addr) -	mreqn.imr_multiaddr.s_addr = mcast_addr; -       -      if (ifindex) -	mreqn.imr_ifindex = ifindex; -      else -	mreqn.imr_address = if_addr; -       -      ret = setsockopt(sock, IPPROTO_IP, optname, -		       (void *)&mreqn, sizeof(mreqn)); -      if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) -        { -	  /* see above: handle possible problem when interface comes back up */ -	  char buf[2][INET_ADDRSTRLEN]; -	  zlog_info("setsockopt_multicast_ipv4 attempting to drop and " -		    "re-add (fd %d, ifaddr %s, mcast %s, ifindex %u)", -		    sock, -		    inet_ntop(AF_INET, &if_addr, buf[0], sizeof(buf[0])), -		    inet_ntop(AF_INET, &mreqn.imr_multiaddr, -			      buf[1], sizeof(buf[1])), ifindex); -	  setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, -		     (void *)&mreqn, sizeof(mreqn)); -	  ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, -			   (void *)&mreqn, sizeof(mreqn)); -        } -      return ret; -      break; - -    default: -      /* Can out and give an understandable error */ -      errno = EINVAL; -      return -1; -      break; +  mreqn.imr_multiaddr.s_addr = mcast_addr; +  mreqn.imr_ifindex = ifindex; +   +  ret = setsockopt(sock, IPPROTO_IP, optname, +                   (void *)&mreqn, sizeof(mreqn)); +  if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) +    { +      /* see above: handle possible problem when interface comes back up */ +      char buf[1][INET_ADDRSTRLEN]; +      zlog_info("setsockopt_ipv4_multicast attempting to drop and " +                "re-add (fd %d, mcast %s, ifindex %u)", +                sock, +                inet_ntop(AF_INET, &mreqn.imr_multiaddr, +                          buf[0], sizeof(buf[0])), ifindex); +      setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, +                 (void *)&mreqn, sizeof(mreqn)); +      ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, +                       (void *)&mreqn, sizeof(mreqn));      } +  return ret;    /* Example defines for another OS, boilerplate off other code in this       function, AND handle optname as per other sections for consistency !! */    /* #elif  defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */    /* Add your favourite OS here! */ -#else /* #if OS_TYPE */  +#elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) /* #if OS_TYPE */     /* standard BSD API */    struct in_addr m;    struct ip_mreq mreq;    int ret; -#ifdef HAVE_BSD_STRUCT_IP_MREQ_HACK -  if (ifindex) -    m.s_addr = htonl(ifindex); -  else -#endif -    m = if_addr; +  assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP); + +  m.s_addr = htonl(ifindex); -  switch (optname) +  memset (&mreq, 0, sizeof(mreq)); +  mreq.imr_multiaddr.s_addr = mcast_addr; +  mreq.imr_interface = m; +   +  ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq)); +  if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))      { -    case IP_MULTICAST_IF: -      return setsockopt (sock, IPPROTO_IP, optname, (void *)&m, sizeof(m));  -      break; - -    case IP_ADD_MEMBERSHIP: -    case IP_DROP_MEMBERSHIP: -      memset (&mreq, 0, sizeof(mreq)); -      mreq.imr_multiaddr.s_addr = mcast_addr; -      mreq.imr_interface = m; -       -      ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq)); -      if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) -        { -	  /* see above: handle possible problem when interface comes back up */ -	  char buf[2][INET_ADDRSTRLEN]; -	  zlog_info("setsockopt_multicast_ipv4 attempting to drop and " -		    "re-add (fd %d, ifaddr %s, mcast %s, ifindex %u)", -		    sock, -		    inet_ntop(AF_INET, &if_addr, buf[0], sizeof(buf[0])), -		    inet_ntop(AF_INET, &mreq.imr_multiaddr, -			      buf[1], sizeof(buf[1])), ifindex); -	  setsockopt (sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, -		      (void *)&mreq, sizeof(mreq)); -	  ret = setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, -	  		    (void *)&mreq, sizeof(mreq)); -        } -      return ret; -      break; -       -    default: -      /* Can out and give an understandable error */ -      errno = EINVAL; -      return -1; -      break; +      /* see above: handle possible problem when interface comes back up */ +      char buf[1][INET_ADDRSTRLEN]; +      zlog_info("setsockopt_ipv4_multicast attempting to drop and " +                "re-add (fd %d, mcast %s, ifindex %u)", +                sock, +                inet_ntop(AF_INET, &mreq.imr_multiaddr, +                          buf[0], sizeof(buf[0])), ifindex); +      setsockopt (sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, +                  (void *)&mreq, sizeof(mreq)); +      ret = setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, +                        (void *)&mreq, sizeof(mreq));      } +  return ret; + +#else +  #error "Unsupported multicast API"  #endif /* #if OS_TYPE */  } +/* + * Set IP_MULTICAST_IF socket option in an OS-dependent manner. + */ +int +setsockopt_ipv4_multicast_if(int sock, +			unsigned int ifindex) +{ + +#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX +  struct ip_mreqn mreqn; +  memset (&mreqn, 0, sizeof(mreqn)); + +  mreqn.imr_ifindex = ifindex; +  return setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&mreqn, sizeof(mreqn)); + +  /* Example defines for another OS, boilerplate off other code in this +     function */ +  /* #elif  defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */ +  /* Add your favourite OS here! */ +#elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) +  struct in_addr m; + +  m.s_addr = htonl(ifindex); + +  return setsockopt (sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&m, sizeof(m)); +#else +  #error "Unsupported multicast API" +#endif +} +    static int  setsockopt_ipv4_ifindex (int sock, int val)  { @@ -451,8 +476,6 @@ getsockopt_ipv4_ifindex (struct msghdr *msgh)  int  getsockopt_ifindex (int af, struct msghdr *msgh)  { -  int ifindex = 0; -      switch (af)      {        case AF_INET: @@ -465,7 +488,7 @@ getsockopt_ifindex (int af, struct msghdr *msgh)  #endif        default:          zlog_warn ("getsockopt_ifindex: unknown address family %d", af); -        return (ifindex = 0); +        return 0;      }  } diff --git a/lib/sockopt.h b/lib/sockopt.h index cb05c6fb..aced6d48 100644 --- a/lib/sockopt.h +++ b/lib/sockopt.h @@ -35,6 +35,7 @@ extern int setsockopt_ipv6_multicast_hops (int, int);  extern int setsockopt_ipv6_unicast_hops (int, int);  extern int setsockopt_ipv6_hoplimit (int, int);  extern int setsockopt_ipv6_multicast_loop (int, int); +extern int setsockopt_ipv6_tclass (int, int);  #endif /* HAVE_IPV6 */  /* @@ -82,13 +83,11 @@ extern int setsockopt_ipv6_multicast_loop (int, int);    (((af) == AF_INET) : SOPT_SIZE_CMSG_IFINDEX_IPV4() \                      ? SOPT_SIZE_CMSG_PKTINFO_IPV6()) -extern int setsockopt_multicast_ipv4(int sock, int optname,  -			             struct in_addr if_addr -					 /* required: interface to join on */, +extern int setsockopt_ipv4_multicast_if(int sock, +			             unsigned int ifindex); +extern int setsockopt_ipv4_multicast(int sock, int optname,                                       unsigned int mcast_addr, -			             unsigned int ifindex -					 /* optional: if non-zero, may be used -					 	instead of if_addr */); +			             unsigned int ifindex);  extern int setsockopt_ipv4_tos(int sock, int tos);  /* Ask for, and get, ifindex, by whatever method is supported. */ diff --git a/lib/sockunion.c b/lib/sockunion.c index a5382a72..59770529 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -297,27 +297,24 @@ sockunion_sizeof (union sockunion *su)  }  /* return sockunion structure : this function should be revised. */ -static char * -sockunion_log (union sockunion *su) +static const char * +sockunion_log (union sockunion *su, char *buf, size_t len)  { -  static char buf[SU_ADDRSTRLEN]; -    switch (su->sa.sa_family)       {      case AF_INET: -      snprintf (buf, SU_ADDRSTRLEN, "%s", inet_ntoa (su->sin.sin_addr)); -      break; +      return inet_ntop(AF_INET, &su->sin.sin_addr, buf, len); +  #ifdef HAVE_IPV6      case AF_INET6: -      snprintf (buf, SU_ADDRSTRLEN, "%s", -		inet_ntop (AF_INET6, &(su->sin6.sin6_addr), buf, SU_ADDRSTRLEN)); +      return inet_ntop(AF_INET6, &(su->sin6.sin6_addr), buf, len);        break;  #endif /* HAVE_IPV6 */ +      default: -      snprintf (buf, SU_ADDRSTRLEN, "af_unknown %d ", su->sa.sa_family); -      break; +      snprintf (buf, len, "af_unknown %d ", su->sa.sa_family); +      return buf;      } -  return (XSTRDUP (MTYPE_TMP, buf));  }  /* sockunion_connect returns @@ -379,8 +376,10 @@ sockunion_connect (int fd, union sockunion *peersu, unsigned short port,      {        if (errno != EINPROGRESS)  	{ +	  char str[SU_ADDRSTRLEN];  	  zlog_info ("can't connect to %s fd %d : %s", -		     sockunion_log (&su), fd, safe_strerror (errno)); +		     sockunion_log (&su, str, sizeof str), +		     fd, safe_strerror (errno));  	  return connect_error;  	}      } @@ -567,6 +566,30 @@ sockopt_minttl (int family, int sock, int minttl)    return -1;  } +int +sockopt_v6only (int family, int sock) +{ +  int ret, on = 1; + +#ifdef HAVE_IPV6 +#ifdef IPV6_V6ONLY +  if (family == AF_INET6) +    { +      ret = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, +			(void *) &on, sizeof (int)); +      if (ret < 0) +	{ +	  zlog (NULL, LOG_WARNING, "can't set sockopt IPV6_V6ONLY " +		    "to socket %d", sock); +	  return -1; +	} +      return 0; +    } +#endif /* IPV6_V6ONLY */ +#endif /* HAVE_IPV6 */ +  return 0; +} +  /* If same family and same prefix return 1. */  int  sockunion_same (union sockunion *su1, union sockunion *su2) diff --git a/lib/sockunion.h b/lib/sockunion.h index 0ee2d63b..4531f620 100644 --- a/lib/sockunion.h +++ b/lib/sockunion.h @@ -99,6 +99,7 @@ extern int sockunion_accept (int sock, union sockunion *);  extern int sockunion_stream_socket (union sockunion *);  extern int sockopt_reuseaddr (int);  extern int sockopt_reuseport (int); +extern int sockopt_v6only (int family, int sock);  extern int sockunion_bind (int sock, union sockunion *,                              unsigned short, union sockunion *);  extern int sockopt_ttl (int family, int sock, int ttl); diff --git a/lib/thread.c b/lib/thread.c index fd841c21..b36c43a9 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -248,7 +248,7 @@ cpu_record_hash_free (void *a)    XFREE (MTYPE_THREAD_STATS, hist);  } -static inline void  +static void   vty_out_cpu_thread_history(struct vty* vty,  			   struct cpu_thread_history *a)  { @@ -608,7 +608,7 @@ thread_master_free (struct thread_master *m)  }  /* Thread list is empty or not.  */ -static inline int +static int  thread_empty (struct thread_list *list)  {    return  list->head ? 0 : 1; @@ -972,10 +972,12 @@ static unsigned int  thread_timer_process (struct thread_list *list, struct timeval *timenow)  {    struct thread *thread; +  struct thread *next;    unsigned int ready = 0; -  for (thread = list->head; thread; thread = thread->next) +  for (thread = list->head; thread; thread = next)      { +      next = thread->next;        if (timeval_cmp (*timenow, thread->u.sands) < 0)          return ready;        thread_list_delete (list, thread); @@ -991,10 +993,12 @@ static unsigned int  thread_process (struct thread_list *list)  {    struct thread *thread; +  struct thread *next;    unsigned int ready = 0; -  for (thread = list->head; thread; thread = thread->next) +  for (thread = list->head; thread; thread = next)      { +      next = thread->next;        thread_list_delete (list, thread);        thread->type = THREAD_READY;        thread_list_add (&thread->master->ready, thread); diff --git a/lib/thread.h b/lib/thread.h index 978aa6b0..dfc51e28 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -1,5 +1,6 @@  /* Thread management routine header.   * Copyright (C) 1998 Kunihiro Ishiguro + * Portions Copyright (c) 2008 Everton da Silva Marques <everton.marques@gmail.com>   *   * This file is part of GNU Zebra.   * @@ -22,6 +23,8 @@  #ifndef _ZEBRA_THREAD_H  #define _ZEBRA_THREAD_H +#include <zebra.h> +  struct rusage_t  {  #ifdef HAVE_RUSAGE @@ -137,6 +140,12 @@ enum quagga_clkid {        thread = thread_add_timer (master, func, arg, time); \    } while (0) +#define THREAD_TIMER_MSEC_ON(master,thread,func,arg,time) \ +  do { \ +    if (! thread) \ +      thread = thread_add_timer_msec (master, func, arg, time); \ +  } while (0) +  #define THREAD_OFF(thread) \    do { \      if (thread) \ @@ -699,6 +699,7 @@ vty_end_config (struct vty *vty)      case ZEBRA_NODE:      case RIP_NODE:      case RIPNG_NODE: +    case BABEL_NODE:      case BGP_NODE:      case BGP_VPNV4_NODE:      case BGP_IPV4_NODE: @@ -1107,6 +1108,7 @@ vty_stop_input (struct vty *vty)      case ZEBRA_NODE:      case RIP_NODE:      case RIPNG_NODE: +    case BABEL_NODE:      case BGP_NODE:      case RMAP_NODE:      case OSPF_NODE: @@ -1685,7 +1687,6 @@ static int  vty_accept (struct thread *thread)  {    int vty_sock; -  struct vty *vty;    union sockunion su;    int ret;    unsigned int on; @@ -1770,7 +1771,7 @@ vty_accept (struct thread *thread)    if (bufp)      XFREE (MTYPE_TMP, bufp); -  vty = vty_create (vty_sock, &su); +  vty_create (vty_sock, &su);    return 0;  } @@ -1816,6 +1817,7 @@ vty_serv_sock_addrinfo (const char *hostname, unsigned short port)        if (sock < 0)  	continue; +      sockopt_v6only (ainfo->ai_family, sock);        sockopt_reuseaddr (sock);        sockopt_reuseport (sock); @@ -1839,7 +1841,7 @@ vty_serv_sock_addrinfo (const char *hostname, unsigned short port)    freeaddrinfo (ainfo_save);  } -#endif /* HAVE_IPV6 && ! NRL */ +#else /* HAVE_IPV6 && ! NRL */  /* Make vty server socket. */  static void @@ -1905,6 +1907,7 @@ vty_serv_sock_family (const char* addr, unsigned short port, int family)    /* Add vty server event. */    vty_event (VTY_SERV, accept_sock, NULL);  } +#endif /* HAVE_IPV6 && ! NRL */  #ifdef VTYSH  /* For sockaddr_un. */ @@ -152,8 +152,9 @@ struct vty  #define VTY_GET_LONG(NAME,V,STR) \  do { \    char *endptr = NULL; \ +  errno = 0; \    (V) = strtoul ((STR), &endptr, 10); \ -  if (*endptr != '\0' || (V) == ULONG_MAX) \ +  if (*(STR) == '-' || *endptr != '\0' || errno) \      { \        vty_out (vty, "%% Invalid %s value%s", NAME, VTY_NEWLINE); \        return CMD_WARNING; \ diff --git a/lib/workqueue.c b/lib/workqueue.c index 52b5f41c..61643bf8 100644 --- a/lib/workqueue.c +++ b/lib/workqueue.c @@ -103,7 +103,7 @@ work_queue_free (struct work_queue *wq)    return;  } -static inline int +static int  work_queue_schedule (struct work_queue *wq, unsigned int delay)  {    /* if appropriate, schedule work queue thread */ diff --git a/lib/zclient.c b/lib/zclient.c index 52a3627d..3521d99e 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -41,6 +41,8 @@ static void zclient_event (enum event, struct zclient *);  extern struct thread_master *master; +char *zclient_serv_path = NULL; +  /* This file local debug flag. */  int zclient_debug = 0; @@ -143,8 +145,10 @@ zclient_reset (struct zclient *zclient)    zclient_init (zclient, zclient->redist_default);  } +#ifdef HAVE_TCP_ZEBRA +  /* Make socket to zebra daemon. Return zebra socket. */ -int +static int  zclient_socket(void)  {    int sock; @@ -175,10 +179,12 @@ zclient_socket(void)    return sock;  } +#else +  /* For sockaddr_un. */  #include <sys/un.h> -int +static int  zclient_socket_un (const char *path)  {    int ret; @@ -208,6 +214,26 @@ zclient_socket_un (const char *path)    return sock;  } +#endif /* HAVE_TCP_ZEBRA */ + +/** + * Connect to zebra daemon. + * @param zclient a pointer to zclient structure + * @return socket fd just to make sure that connection established + * @see zclient_init + * @see zclient_new + */ +int +zclient_socket_connect (struct zclient *zclient) +{ +#ifdef HAVE_TCP_ZEBRA +  zclient->sock = zclient_socket (); +#else +  zclient->sock = zclient_socket_un (zclient_serv_path ? zclient_serv_path : ZEBRA_SERV_PATH); +#endif +  return zclient->sock; +} +  static int  zclient_failed(struct zclient *zclient)  { @@ -292,6 +318,25 @@ zebra_message_send (struct zclient *zclient, int command)    return zclient_send_message(zclient);  } +static int +zebra_hello_send (struct zclient *zclient) +{ +  struct stream *s; + +  if (zclient->redist_default) +    { +      s = zclient->obuf; +      stream_reset (s); + +      zclient_create_header (s, ZEBRA_HELLO); +      stream_putc (s, zclient->redist_default); +      stream_putw_at (s, 0, stream_get_endp (s)); +      return zclient_send_message(zclient); +    } + +  return 0; +} +  /* Make connection to zebra daemon. */  int  zclient_start (struct zclient *zclient) @@ -313,13 +358,7 @@ zclient_start (struct zclient *zclient)    if (zclient->t_connect)      return 0; -  /* Make socket. */ -#ifdef HAVE_TCP_ZEBRA -  zclient->sock = zclient_socket (); -#else -  zclient->sock = zclient_socket_un (ZEBRA_SERV_PATH); -#endif /* HAVE_TCP_ZEBRA */ -  if (zclient->sock < 0) +  if (zclient_socket_connect(zclient) < 0)      {        if (zclient_debug)  	zlog_debug ("zclient connection fail"); @@ -339,6 +378,8 @@ zclient_start (struct zclient *zclient)    /* Create read thread. */    zclient_event (ZCLIENT_READ, zclient); +  zebra_hello_send (zclient); +    /* We need router-id information. */    zebra_message_send (zclient, ZEBRA_ROUTER_ID_ADD); @@ -435,6 +476,7 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p,    stream_putc (s, api->type);    stream_putc (s, api->flags);    stream_putc (s, api->message); +  stream_putw (s, api->safi);    /* Put prefix information. */    psize = PSIZE (p->prefixlen); @@ -496,6 +538,7 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p,    stream_putc (s, api->type);    stream_putc (s, api->flags);    stream_putc (s, api->message); +  stream_putw (s, api->safi);    /* Put prefix information. */    psize = PSIZE (p->prefixlen); @@ -796,7 +839,6 @@ zebra_interface_address_read (int type, struct stream *s)  static int  zclient_read (struct thread *thread)  { -  int ret;    size_t already;    uint16_t length, command;    uint8_t marker, version; @@ -891,47 +933,47 @@ zclient_read (struct thread *thread)      {      case ZEBRA_ROUTER_ID_UPDATE:        if (zclient->router_id_update) -	ret = (*zclient->router_id_update) (command, zclient, length); +	(*zclient->router_id_update) (command, zclient, length);        break;      case ZEBRA_INTERFACE_ADD:        if (zclient->interface_add) -	ret = (*zclient->interface_add) (command, zclient, length); +	(*zclient->interface_add) (command, zclient, length);        break;      case ZEBRA_INTERFACE_DELETE:        if (zclient->interface_delete) -	ret = (*zclient->interface_delete) (command, zclient, length); +	(*zclient->interface_delete) (command, zclient, length);        break;      case ZEBRA_INTERFACE_ADDRESS_ADD:        if (zclient->interface_address_add) -	ret = (*zclient->interface_address_add) (command, zclient, length); +	(*zclient->interface_address_add) (command, zclient, length);        break;      case ZEBRA_INTERFACE_ADDRESS_DELETE:        if (zclient->interface_address_delete) -	ret = (*zclient->interface_address_delete) (command, zclient, length); +	(*zclient->interface_address_delete) (command, zclient, length);        break;      case ZEBRA_INTERFACE_UP:        if (zclient->interface_up) -	ret = (*zclient->interface_up) (command, zclient, length); +	(*zclient->interface_up) (command, zclient, length);        break;      case ZEBRA_INTERFACE_DOWN:        if (zclient->interface_down) -	ret = (*zclient->interface_down) (command, zclient, length); +	(*zclient->interface_down) (command, zclient, length);        break;      case ZEBRA_IPV4_ROUTE_ADD:        if (zclient->ipv4_route_add) -	ret = (*zclient->ipv4_route_add) (command, zclient, length); +	(*zclient->ipv4_route_add) (command, zclient, length);        break;      case ZEBRA_IPV4_ROUTE_DELETE:        if (zclient->ipv4_route_delete) -	ret = (*zclient->ipv4_route_delete) (command, zclient, length); +	(*zclient->ipv4_route_delete) (command, zclient, length);        break;      case ZEBRA_IPV6_ROUTE_ADD:        if (zclient->ipv6_route_add) -	ret = (*zclient->ipv6_route_add) (command, zclient, length); +	(*zclient->ipv6_route_add) (command, zclient, length);        break;      case ZEBRA_IPV6_ROUTE_DELETE:        if (zclient->ipv6_route_delete) -	ret = (*zclient->ipv6_route_delete) (command, zclient, length); +	(*zclient->ipv6_route_delete) (command, zclient, length);        break;      default:        break; @@ -1018,3 +1060,29 @@ zclient_event (enum event event, struct zclient *zclient)        break;      }  } + +void +zclient_serv_path_set (char *path) +{ +  struct stat sb; + +  /* reset */ +  zclient_serv_path = NULL; + +  /* test if `path' is socket. don't set it otherwise. */ +  if (stat(path, &sb) == -1) +    { +      zlog_warn ("%s: zebra socket `%s' does not exist", __func__, path); +      return; +    } + +  if ((sb.st_mode & S_IFMT) != S_IFSOCK) +    { +      zlog_warn ("%s: `%s' is not unix socket, sir", __func__, path); +      return; +    } + +  /* it seems that path is unix socket */ +  zclient_serv_path = path; +} + diff --git a/lib/zclient.h b/lib/zclient.h index 21786ab8..a7d7b548 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -22,6 +22,9 @@  #ifndef _ZEBRA_ZCLIENT_H  #define _ZEBRA_ZCLIENT_H +/* For struct zapi_ipv{4,6}. */ +#include "prefix.h" +  /* For struct interface and struct connected. */  #include "if.h" @@ -108,6 +111,8 @@ struct zapi_ipv4    u_char message; +  safi_t safi; +    u_char nexthop_num;    struct in_addr **nexthop; @@ -127,11 +132,8 @@ extern void zclient_stop (struct zclient *);  extern void zclient_reset (struct zclient *);  extern void zclient_free (struct zclient *); -/* Get TCP socket connection to zebra daemon at loopback address. */ -extern int zclient_socket (void); - -/* Get unix stream socket connection to zebra daemon at given path. */ -extern int zclient_socket_un (const char *); +extern int  zclient_socket_connect (struct zclient *); +extern void zclient_serv_path_set  (char *path);  /* Send redistribute command to zebra daemon. Do not update zclient state. */  extern int zebra_redistribute_send (int command, struct zclient *, int type); @@ -168,6 +170,8 @@ struct zapi_ipv6    u_char message; +  safi_t safi; +    u_char nexthop_num;    struct in6_addr **nexthop; diff --git a/lib/zebra.h b/lib/zebra.h index 2dc84514..ab072d6e 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -237,10 +237,6 @@ typedef int socklen_t;  #define UINT32_MAX	(4294967295U)  #endif -#ifdef HAVE_LIBUTIL_H -#include <libutil.h> -#endif /* HAVE_LIBUTIL_H */ -  #ifdef HAVE_GLIBC_BACKTRACE  #include <execinfo.h>  #endif /* HAVE_GLIBC_BACKTRACE */ @@ -421,7 +417,8 @@ struct in_pktinfo  #define ZEBRA_ROUTER_ID_ADD               20  #define ZEBRA_ROUTER_ID_DELETE            21  #define ZEBRA_ROUTER_ID_UPDATE            22 -#define ZEBRA_MESSAGE_MAX                 23 +#define ZEBRA_HELLO                       23 +#define ZEBRA_MESSAGE_MAX                 24  /* Marker value used in new Zserv, in the byte location corresponding   * the command value in the old zserv header. To allow old and new @@ -429,19 +426,8 @@ struct in_pktinfo   */  #define ZEBRA_HEADER_MARKER              255 -/* Zebra route's types. */ -#define ZEBRA_ROUTE_SYSTEM               0 -#define ZEBRA_ROUTE_KERNEL               1 -#define ZEBRA_ROUTE_CONNECT              2 -#define ZEBRA_ROUTE_STATIC               3 -#define ZEBRA_ROUTE_RIP                  4 -#define ZEBRA_ROUTE_RIPNG                5 -#define ZEBRA_ROUTE_OSPF                 6 -#define ZEBRA_ROUTE_OSPF6                7 -#define ZEBRA_ROUTE_ISIS                 8 -#define ZEBRA_ROUTE_BGP                  9 -#define ZEBRA_ROUTE_HSLS		 10 -#define ZEBRA_ROUTE_MAX                  11 +/* Zebra route's types are defined in route_types.h */ +#include "route_types.h"  /* Note: whenever a new route-type or zserv-command is added the   * corresponding {command,route}_types[] table in lib/log.c MUST be @@ -455,6 +441,10 @@ extern char zebra_route_char(unsigned int route_type);   * e.g. ZEBRA_INTERFACE_ADD -> "ZEBRA_INTERFACE_ADD" */  /* Map a protocol name to its number. e.g. ZEBRA_ROUTE_BGP->9*/  extern int proto_name2num(const char *s); +/* Map redistribute X argument to protocol number. + * unlike proto_name2num, this accepts shorthands and takes + * an AFI value to restrict input */ +extern int proto_redistnum(int afi, const char *s);  extern const char *zserv_command_string (unsigned int command); @@ -504,7 +494,7 @@ extern const char *zserv_command_string (unsigned int command);  /* Subsequent Address Family Identifier. */  #define SAFI_UNICAST              1  #define SAFI_MULTICAST            2 -#define SAFI_UNICAST_MULTICAST    3 +#define SAFI_RESERVED_3           3  #define SAFI_MPLS_VPN             4  #define SAFI_MAX                  5 | 
