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 |