summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAvneesh Sachdev <avneesh@opensourcerouting.org>2012-04-11 23:51:08 -0700
committerAvneesh Sachdev <avneesh@opensourcerouting.org>2012-04-11 23:51:08 -0700
commit14d2bbaa3f4aa53152472694c29f336808e47313 (patch)
treee39bdddef4ea53207dd8fb61e1fd6b54d8c7721d /lib
parent51d4ef832c1e58150325630e25c442866e5a6cf5 (diff)
parente96b312150d8e376c1ef463793d1929eca3618d5 (diff)
Merge quagga mainline into the google ISIS code.
The steps were: $ git checkout google-is-is $ git merge quagga $ git checkout google-is-is -- isisd # Resolve conflicts in the following: lib/md5.h zebra/rt_netlink.c zebra/zebra_rib.c zebra/zserv.c Note that the content in the isisd directory is left unchanged in the merge. As a result, changes made to isisd as part of the following commits on the quagga mainline are dropped. # 8ced4e82 is the merge base, e96b3121 is the current quagga master $ git log --oneline --reverse 8ced4e82..e96b3121 -- isisd 5574999 isisd: fix crash on "no router isis" (BZ#536) 8998075 isisd: raise hello rate for DIS (BZ#539) 306ca83 isisd: include hash.h, not hash.c b82cdeb delete CVS keywords 2f65867 isisd: indent longopts array b511468 quagga: option "-z" ("--socket <path>") added 05e54ee build: delete .cvsignore files b4e45f6 fix zebra protocol after MP-BGP changes 7fd6cd8 isisd: fix circuit state machine 907fd95 isisd: send proper LSP after DIS election d034aa0 isisd: fix wrong next-hops from SPF c25eaff isisd: unexpected kernel routing table (BZ#544) e6b03b7 isisd: implement MD5 circuit authentication
Diffstat (limited to 'lib')
-rw-r--r--lib/.cvsignore14
-rw-r--r--lib/Makefile.am6
-rw-r--r--lib/command.c4
-rw-r--r--lib/command.h1
-rw-r--r--lib/distribute.c69
-rw-r--r--lib/distribute.h3
-rw-r--r--lib/filter.c12
-rw-r--r--lib/if.c16
-rw-r--r--lib/if_rmap.c3
-rw-r--r--lib/log.c86
-rw-r--r--lib/log.h9
-rw-r--r--lib/memory.c14
-rw-r--r--lib/memtypes.c9
-rw-r--r--lib/prefix.c314
-rw-r--r--lib/prefix.h27
-rw-r--r--lib/route_types.awk187
-rwxr-xr-xlib/route_types.pl199
-rw-r--r--lib/route_types.txt12
-rw-r--r--lib/routemap.h1
-rw-r--r--lib/smux.c7
-rw-r--r--lib/sockopt.c207
-rw-r--r--lib/sockopt.h11
-rw-r--r--lib/sockunion.c47
-rw-r--r--lib/sockunion.h1
-rw-r--r--lib/thread.c12
-rw-r--r--lib/thread.h9
-rw-r--r--lib/vty.c9
-rw-r--r--lib/vty.h3
-rw-r--r--lib/workqueue.c2
-rw-r--r--lib/zclient.c110
-rw-r--r--lib/zclient.h14
-rw-r--r--lib/zebra.h28
32 files changed, 880 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;
}
diff --git a/lib/if.c b/lib/if.c
index e9ef50b7..e26aa046 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -431,19 +431,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;
}
diff --git a/lib/log.c b/lib/log.c
index df6e13db..cbc935b6 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -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;
+}
diff --git a/lib/log.h b/lib/log.h
index 2dd1d313..27f21b31 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -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[];
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 69beb1c9..2ded1d6c 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"
@@ -176,6 +174,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,
diff --git a/lib/smux.c b/lib/smux.c
index 1941cf8c..b7cd18d1 100644
--- a/lib/smux.c
+++ b/lib/smux.c
@@ -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) \
diff --git a/lib/vty.c b/lib/vty.c
index bd1dbac0..9a4efe64 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -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. */
diff --git a/lib/vty.h b/lib/vty.h
index 7df04b5f..639d7417 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -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 85aa737e..61c6f730 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);
@@ -778,7 +821,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;
@@ -873,47 +915,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;
@@ -1000,3 +1042,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