summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpaul <paul>2003-05-26 00:25:34 +0000
committerpaul <paul>2003-05-26 00:25:34 +0000
commita2642228fa2f7f4a287d05f17e09fb63953a05aa (patch)
tree13005197447156ad362f5138726f8433324055a6
parentff8c45e1d68d32731f78f9b814ccfec976165a6c (diff)
downloadquagga-a2642228fa2f7f4a287d05f17e09fb63953a05aa.tar.bz2
quagga-a2642228fa2f7f4a287d05f17e09fb63953a05aa.tar.xz
Merge HEAD to zprivs
-rw-r--r--acconfig.h14
-rwxr-xr-xconfig.sub3
-rwxr-xr-xconfigure.ac51
-rwxr-xr-xconfigure.in51
-rw-r--r--lib/command.c202
-rw-r--r--lib/if_rmap.c30
-rw-r--r--lib/memory.c27
-rw-r--r--lib/memory.h9
-rw-r--r--lib/sockunion.c13
-rw-r--r--lib/zclient.c56
-rw-r--r--lib/zebra.h7
-rw-r--r--ospf6d/Makefile.am2
-rw-r--r--ospf6d/ospf6_asbr.c24
-rw-r--r--ospf6d/ospf6_main.c6
-rw-r--r--ospf6d/ospf6_network.c8
-rw-r--r--ospf6d/ospf6_top.c3
-rw-r--r--ospfd/Makefile.am2
-rw-r--r--ospfd/ospf_main.c4
-rw-r--r--ripd/ChangeLog9
-rw-r--r--ripd/Makefile.am2
-rw-r--r--ripd/rip_interface.c237
-rw-r--r--ripd/rip_routemap.c305
-rw-r--r--ripd/rip_zebra.c42
-rw-r--r--ripd/ripd.c280
-rw-r--r--ripd/ripd.h18
-rw-r--r--ripngd/ChangeLog15
-rw-r--r--ripngd/Makefile.am4
-rw-r--r--ripngd/ripng_debug.c3
-rw-r--r--ripngd/ripng_debug.h1
-rw-r--r--ripngd/ripng_interface.c549
-rw-r--r--ripngd/ripng_main.c30
-rw-r--r--ripngd/ripng_nexthop.c216
-rw-r--r--ripngd/ripng_nexthop.h62
-rw-r--r--ripngd/ripng_offset.c417
-rw-r--r--ripngd/ripng_peer.c220
-rw-r--r--ripngd/ripng_route.c1
-rw-r--r--ripngd/ripng_route.h6
-rw-r--r--ripngd/ripng_routemap.c641
-rw-r--r--ripngd/ripng_zebra.c711
-rw-r--r--ripngd/ripngd.c1200
-rw-r--r--ripngd/ripngd.h113
-rwxr-xr-xvtysh/extract.pl6
-rw-r--r--vtysh/vtysh.c229
-rw-r--r--zebra/ChangeLog12
-rw-r--r--zebra/connected.c12
-rw-r--r--zebra/interface.h4
-rw-r--r--zebra/ioctl.c4
-rw-r--r--zebra/kernel_socket.c16
-rw-r--r--zebra/rib.h18
-rw-r--r--zebra/rt_netlink.c30
-rw-r--r--zebra/rt_socket.c17
-rw-r--r--zebra/zebra_rib.c63
-rw-r--r--zebra/zebra_vty.c392
-rw-r--r--zebra/zserv.c47
-rw-r--r--zebra/zserv.h8
55 files changed, 5040 insertions, 1412 deletions
diff --git a/acconfig.h b/acconfig.h
index de39bc82..caaf3ae6 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -32,7 +32,7 @@
#undef HAVE_IPV6
/* Define if you wish to support ipv6 router advertisment. */
-/* #undef HAVE_RTADV */
+#undef HAVE_RTADV
/* whether system has GNU regex */
#undef HAVE_GNU_REGEX
@@ -40,6 +40,9 @@
/* whether system has SNMP library */
#undef HAVE_SNMP
+/* whether systme has a ifra_lifetime field */
+#undef HAVE_IFRA_LIFETIME
+
/* whether sockaddr has a sa_len field */
#undef HAVE_SA_LEN
@@ -88,6 +91,9 @@
/* Define if you have KAME project ipv6 stack. */
#undef KAME
+/* Define if you have 6WIND MUSICA IPv6 stack. */
+#undef MUSICA
+
/* Define if you have Linux ipv6 stack. */
#undef LINUX_IPV6
@@ -139,6 +145,12 @@
/* Define if FreeBSD 3.2 */
#undef FREEBSD_32
+/* Define if FreeBSD */
+#undef FREEBSD
+
+/* Define if SIXOS */
+#undef SIXOS
+
/* Define if OpenBSD */
#undef OPEN_BSD
diff --git a/config.sub b/config.sub
index 004c7deb..8c16a0ed 100755
--- a/config.sub
+++ b/config.sub
@@ -995,7 +995,8 @@ case $os in
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
- | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* | -storm-chaos*)
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -sixos*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
diff --git a/configure.ac b/configure.ac
index fd264b7a..848ab623 100755
--- a/configure.ac
+++ b/configure.ac
@@ -81,7 +81,7 @@ AC_ARG_ENABLE(snmp,
[ --enable-snmp enable SNMP support])
AC_ARG_WITH(libpam,
[ --with-libpam use libpam for PAM support in vtysh])
-AC_ARG_ENABLE(tcpsock,
+AC_ARG_ENABLE(tcp-zebra,
[ --enable-tcp-zebra enable TCP/IP socket connection between zebra and protocol daemon])
dnl Temporary option until OSPF NSSA implementation complete
AC_ARG_ENABLE(nssa,
@@ -105,8 +105,8 @@ AC_ARG_ENABLE(zebra_group,
AC_ARG_ENABLE(vty_group,
[ --enable-vty-group=ARG set vty sockets to have specified group as owner])
-dnl AC_ARG_ENABLE(rtadv,
-dnl [ --enable-rtadv enable IPV6 router advertisment option])
+AC_ARG_ENABLE(rtadv,
+[ --enable-rtadv disable IPV6 router advertisment feature])
if test "${enable_broken_aliases}" = "yes"; then
if test "${enable_netlink}" = "yes"
@@ -135,9 +135,13 @@ if test "${enable_ospf_te}" = "yes"; then
AC_DEFINE(HAVE_OSPF_TE,,OSPF TE)
fi
-dnl if test "${enable_rtadv}" = "yes"; then
-dnl AC_DEFINE(HAVE_RTADV)
-dnl fi
+AC_MSG_CHECKING(Should Zebra's RTADV be used)
+if test "${enable_rtadv}" = "yes"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_RTADV)
+else
+ AC_MSG_RESULT(no)
+fi
if test "${enable_user}" = "yes" ; then
enable_user="zebra"
@@ -184,7 +188,7 @@ dnl -------------------
dnl Check header files.
dnl -------------------
AC_STDC_HEADERS
-AC_CHECK_HEADERS(string.h stropts.h sys/conf.h sys/ksym.h sys/time.h sys/times.h sys/select.h sys/sysctl.h sys/sockio.h sys/types.h net/if_dl.h net/if_var.h linux/version.h kvm.h netdb.h netinet/in.h net/netopt.h netinet/in_var.h netinet/in6_var.h netinet/in6.h inet/nd.h asm/types.h netinet/icmp6.h netinet6/nd6.h libutil.h)
+AC_CHECK_HEADERS(string.h stropts.h sys/conf.h sys/ksym.h sys/time.h sys/times.h sys/select.h sys/sysctl.h sys/sockio.h sys/types.h net/if_dl.h net/if_var.h linux/version.h kvm.h netdb.h netinet/in.h net/netopt.h netinet/in_var.h netinet/in6_var.h netinet6/in6_var.h netinet/in6.h inet/nd.h asm/types.h netinet/icmp6.h netinet6/nd6.h libutil.h)
dnl check some types
AC_C_CONST
@@ -496,6 +500,23 @@ if grep WIDE /usr/include/netinet6/in6.h >/dev/null 2>&1; then
fi
AC_MSG_RESULT(KAME)
fi
+dnl -------------------------
+dnl MUSICA IPv6
+dnl default host check
+dnl It is not used by Kheops
+dnl -------------------------
+if grep MUSICA /usr/include6/netinet6/in6.h >/dev/null 2>&1; then
+ zebra_cv_ipv6=yes
+ AC_DEFINE(HAVE_IPV6)
+ AC_DEFINE(MUSICA)
+ AC_DEFINE(KAME)
+ RIPNGD="ripngd"
+ OSPF6D="ospf6d"
+ if test -d /usr/local/v6/lib -a -f /usr/local/v6/lib/libinet6.a; then
+ LIB_IPV6="-L/usr/local/v6/lib -linet6"
+ fi
+ AC_MSG_RESULT(MUSICA)
+fi
dnl ---------
dnl NRL check
dnl ---------
@@ -815,13 +836,24 @@ net/if.h,
dnl ----------------------------
dnl check structure in6_aliasreq
dnl ----------------------------
-AC_MSG_CHECKING(whether struct if6_aliasreq exist)
+AC_MSG_CHECKING(whether struct in6_aliasreq exist)
AC_EGREP_HEADER(in6_aliasreq,
netinet6/in6_var.h,
[AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_IN6_ALIASREQ,,in6_aliasreq)],
AC_MSG_RESULT(no))
+dnl -----------------------------------
+dnl check ifra_lifetime of in6_aliasreq
+dnl -----------------------------------
+AC_MSG_CHECKING(whether in6_aliasreq.ifra_lifetime exist)
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet6/in6_var.h>
+],[static struct if6_aliasreq ac_i;int ac_j = sizeof (ac_i.ifra_lifetime);],
+[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IFRA_LIFETIME)],
+ AC_MSG_RESULT(no))
+
dnl ---------------------------
dnl check structure rt_addrinfo
dnl ---------------------------
@@ -965,4 +997,5 @@ source code location : ${srcdir}
compiler : ${CC}
compiler flags : ${CFLAGS}
directory for state files : ${zebra_statedir}
-" \ No newline at end of file
+linker flags : ${LDFLAGS} ${LIBS}
+"
diff --git a/configure.in b/configure.in
index fd264b7a..848ab623 100755
--- a/configure.in
+++ b/configure.in
@@ -81,7 +81,7 @@ AC_ARG_ENABLE(snmp,
[ --enable-snmp enable SNMP support])
AC_ARG_WITH(libpam,
[ --with-libpam use libpam for PAM support in vtysh])
-AC_ARG_ENABLE(tcpsock,
+AC_ARG_ENABLE(tcp-zebra,
[ --enable-tcp-zebra enable TCP/IP socket connection between zebra and protocol daemon])
dnl Temporary option until OSPF NSSA implementation complete
AC_ARG_ENABLE(nssa,
@@ -105,8 +105,8 @@ AC_ARG_ENABLE(zebra_group,
AC_ARG_ENABLE(vty_group,
[ --enable-vty-group=ARG set vty sockets to have specified group as owner])
-dnl AC_ARG_ENABLE(rtadv,
-dnl [ --enable-rtadv enable IPV6 router advertisment option])
+AC_ARG_ENABLE(rtadv,
+[ --enable-rtadv disable IPV6 router advertisment feature])
if test "${enable_broken_aliases}" = "yes"; then
if test "${enable_netlink}" = "yes"
@@ -135,9 +135,13 @@ if test "${enable_ospf_te}" = "yes"; then
AC_DEFINE(HAVE_OSPF_TE,,OSPF TE)
fi
-dnl if test "${enable_rtadv}" = "yes"; then
-dnl AC_DEFINE(HAVE_RTADV)
-dnl fi
+AC_MSG_CHECKING(Should Zebra's RTADV be used)
+if test "${enable_rtadv}" = "yes"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_RTADV)
+else
+ AC_MSG_RESULT(no)
+fi
if test "${enable_user}" = "yes" ; then
enable_user="zebra"
@@ -184,7 +188,7 @@ dnl -------------------
dnl Check header files.
dnl -------------------
AC_STDC_HEADERS
-AC_CHECK_HEADERS(string.h stropts.h sys/conf.h sys/ksym.h sys/time.h sys/times.h sys/select.h sys/sysctl.h sys/sockio.h sys/types.h net/if_dl.h net/if_var.h linux/version.h kvm.h netdb.h netinet/in.h net/netopt.h netinet/in_var.h netinet/in6_var.h netinet/in6.h inet/nd.h asm/types.h netinet/icmp6.h netinet6/nd6.h libutil.h)
+AC_CHECK_HEADERS(string.h stropts.h sys/conf.h sys/ksym.h sys/time.h sys/times.h sys/select.h sys/sysctl.h sys/sockio.h sys/types.h net/if_dl.h net/if_var.h linux/version.h kvm.h netdb.h netinet/in.h net/netopt.h netinet/in_var.h netinet/in6_var.h netinet6/in6_var.h netinet/in6.h inet/nd.h asm/types.h netinet/icmp6.h netinet6/nd6.h libutil.h)
dnl check some types
AC_C_CONST
@@ -496,6 +500,23 @@ if grep WIDE /usr/include/netinet6/in6.h >/dev/null 2>&1; then
fi
AC_MSG_RESULT(KAME)
fi
+dnl -------------------------
+dnl MUSICA IPv6
+dnl default host check
+dnl It is not used by Kheops
+dnl -------------------------
+if grep MUSICA /usr/include6/netinet6/in6.h >/dev/null 2>&1; then
+ zebra_cv_ipv6=yes
+ AC_DEFINE(HAVE_IPV6)
+ AC_DEFINE(MUSICA)
+ AC_DEFINE(KAME)
+ RIPNGD="ripngd"
+ OSPF6D="ospf6d"
+ if test -d /usr/local/v6/lib -a -f /usr/local/v6/lib/libinet6.a; then
+ LIB_IPV6="-L/usr/local/v6/lib -linet6"
+ fi
+ AC_MSG_RESULT(MUSICA)
+fi
dnl ---------
dnl NRL check
dnl ---------
@@ -815,13 +836,24 @@ net/if.h,
dnl ----------------------------
dnl check structure in6_aliasreq
dnl ----------------------------
-AC_MSG_CHECKING(whether struct if6_aliasreq exist)
+AC_MSG_CHECKING(whether struct in6_aliasreq exist)
AC_EGREP_HEADER(in6_aliasreq,
netinet6/in6_var.h,
[AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_IN6_ALIASREQ,,in6_aliasreq)],
AC_MSG_RESULT(no))
+dnl -----------------------------------
+dnl check ifra_lifetime of in6_aliasreq
+dnl -----------------------------------
+AC_MSG_CHECKING(whether in6_aliasreq.ifra_lifetime exist)
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet6/in6_var.h>
+],[static struct if6_aliasreq ac_i;int ac_j = sizeof (ac_i.ifra_lifetime);],
+[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IFRA_LIFETIME)],
+ AC_MSG_RESULT(no))
+
dnl ---------------------------
dnl check structure rt_addrinfo
dnl ---------------------------
@@ -965,4 +997,5 @@ source code location : ${srcdir}
compiler : ${CC}
compiler flags : ${CFLAGS}
directory for state files : ${zebra_statedir}
-" \ No newline at end of file
+linker flags : ${LDFLAGS} ${LIBS}
+"
diff --git a/lib/command.c b/lib/command.c
index 8cbecce1..5d429338 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -24,6 +24,7 @@ Boston, MA 02111-1307, USA. */
#include "memory.h"
#include "log.h"
#include "version.h"
+#include "thread.h"
/* Command vector which includes some level of command lists. Normally
each daemon maintains each own cmdvec. */
@@ -717,6 +718,8 @@ cmd_ipv6_match (char *str)
int state = STATE_START;
int colons = 0, nums = 0, double_colon = 0;
char *sp = NULL;
+ struct sockaddr_in6 sin6_dummy;
+ int ret;
if (str == NULL)
return partly_match;
@@ -724,6 +727,15 @@ cmd_ipv6_match (char *str)
if (strspn (str, IPV6_ADDR_STR) != strlen (str))
return no_match;
+ /* use inet_pton that has a better support,
+ * for example inet_pton can support the automatic addresses:
+ * ::1.2.3.4
+ */
+ ret = inet_pton(AF_INET6, str, &sin6_dummy.sin6_addr);
+
+ if (ret == 1)
+ return exact_match;
+
while (*str != '\0')
{
switch (state)
@@ -1411,9 +1423,21 @@ desc_unique_string (vector v, char *str)
return 0;
}
+int
+cmd_try_do_shortcut (enum node_type node, char* first_word) {
+ if ( first_word != NULL &&
+ node != AUTH_NODE &&
+ node != VIEW_NODE &&
+ node != AUTH_ENABLE_NODE &&
+ node != ENABLE_NODE &&
+ 0 == strcmp( "do", first_word ) )
+ return 1;
+ return 0;
+}
+
/* '?' describe command support. */
vector
-cmd_describe_command (vector vline, struct vty *vty, int *status)
+cmd_describe_command_real (vector vline, struct vty *vty, int *status)
{
int i;
vector cmd_vector;
@@ -1536,6 +1560,40 @@ cmd_describe_command (vector vline, struct vty *vty, int *status)
return matchvec;
}
+vector
+cmd_describe_command (vector vline, struct vty *vty, int *status)
+{
+ vector ret;
+
+ if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
+ {
+ enum node_type onode;
+ vector shifted_vline;
+ int index;
+
+ onode = vty->node;
+ vty->node = ENABLE_NODE;
+ /* We can try it on enable node, cos' the vty is authenticated */
+
+ shifted_vline = vector_init (vector_count(vline));
+ /* use memcpy? */
+ for (index = 1; index < vector_max (vline); index++)
+ {
+ vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
+ }
+
+ ret = cmd_describe_command_real (shifted_vline, vty, status);
+
+ vector_free(shifted_vline);
+ vty->node = onode;
+ return ret;
+ }
+
+
+ return cmd_describe_command_real (vline, vty, status);
+}
+
+
/* Check LCD of matched command. */
int
cmd_lcd (char **matched)
@@ -1571,7 +1629,7 @@ cmd_lcd (char **matched)
/* Command line completion support. */
char **
-cmd_complete_command (vector vline, struct vty *vty, int *status)
+cmd_complete_command_real (vector vline, struct vty *vty, int *status)
{
int i;
vector cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
@@ -1717,9 +1775,68 @@ cmd_complete_command (vector vline, struct vty *vty, int *status)
return match_str;
}
+char **
+cmd_complete_command (vector vline, struct vty *vty, int *status)
+{
+ char **ret;
+
+ if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
+ {
+ enum node_type onode;
+ vector shifted_vline;
+ int index;
+
+ onode = vty->node;
+ vty->node = ENABLE_NODE;
+ /* We can try it on enable node, cos' the vty is authenticated */
+
+ shifted_vline = vector_init (vector_count(vline));
+ /* use memcpy? */
+ for (index = 1; index < vector_max (vline); index++)
+ {
+ vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
+ }
+
+ ret = cmd_complete_command_real (shifted_vline, vty, status);
+
+ vector_free(shifted_vline);
+ vty->node = onode;
+ return ret;
+ }
+
+
+ return cmd_complete_command_real (vline, vty, status);
+}
+
+/* return parent node */
+/* MUST eventually converge on CONFIG_NODE */
+enum node_type node_parent ( enum node_type node )
+{
+ enum node_type ret;
+
+ assert (node > CONFIG_NODE);
+
+ switch (node)
+ {
+ case BGP_VPNV4_NODE:
+ case BGP_IPV4_NODE:
+ case BGP_IPV4M_NODE:
+ case BGP_IPV6_NODE:
+ ret = BGP_NODE;
+ break;
+ case KEYCHAIN_KEY_NODE:
+ ret = KEYCHAIN_NODE;
+ break;
+ default:
+ ret = CONFIG_NODE;
+ }
+
+ return ret;
+}
+
/* Execute command by argument vline vector. */
int
-cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd)
+cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cmd)
{
int i;
int index;
@@ -1842,6 +1959,60 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd)
return (*matched_element->func) (matched_element, vty, argc, argv);
}
+
+int
+cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) {
+ int ret, saved_ret, tried = 0;
+ enum node_type onode, try_node;
+
+ onode = try_node = vty->node;
+
+ if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
+ {
+ vector shifted_vline;
+ int index;
+
+ vty->node = ENABLE_NODE;
+ /* We can try it on enable node, cos' the vty is authenticated */
+
+ shifted_vline = vector_init (vector_count(vline));
+ /* use memcpy? */
+ for (index = 1; index < vector_max (vline); index++)
+ {
+ vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
+ }
+
+ ret = cmd_execute_command_real (shifted_vline, vty, cmd);
+
+ vector_free(shifted_vline);
+ vty->node = onode;
+ return ret;
+ }
+
+
+ saved_ret = ret = cmd_execute_command_real (vline, vty, cmd);
+
+ /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
+ while ( ret != CMD_SUCCESS && ret != CMD_WARNING
+ && vty->node > CONFIG_NODE )
+ {
+ try_node = node_parent(try_node);
+ vty->node = try_node;
+ ret = cmd_execute_command_real (vline, vty, cmd);
+ tried = 1;
+ if (ret == CMD_SUCCESS || ret == CMD_WARNING)
+ {
+ /* succesfull command, leave the node as is */
+ return ret;
+ }
+ }
+ /* no command succeeded, reset the vty to the original node and
+ return the error for this node */
+ if ( tried )
+ vty->node = onode;
+ return saved_ret;
+}
+
/* Execute command by argument readline. */
int
cmd_execute_command_strict (vector vline, struct vty *vty,
@@ -1981,26 +2152,12 @@ config_from_file (struct vty *vty, FILE *fp)
ret = cmd_execute_command_strict (vline, vty, NULL);
/* Try again with setting node to CONFIG_NODE */
- if (ret != CMD_SUCCESS && ret != CMD_WARNING)
- {
- if (vty->node == KEYCHAIN_KEY_NODE)
- {
- vty->node = KEYCHAIN_NODE;
-
- ret = cmd_execute_command_strict (vline, vty, NULL);
-
- if (ret != CMD_SUCCESS && ret != CMD_WARNING)
+ while (ret != CMD_SUCCESS && ret != CMD_WARNING
+ && vty->node != CONFIG_NODE)
{
- vty->node = CONFIG_NODE;
+ vty->node = node_parent(vty->node);
ret = cmd_execute_command_strict (vline, vty, NULL);
}
- }
- else
- {
- vty->node = CONFIG_NODE;
- ret = cmd_execute_command_strict (vline, vty, NULL);
- }
- }
cmd_free_strvec (vline);
@@ -2977,5 +3134,10 @@ cmd_init (int terminal)
install_element (CONFIG_NODE, &no_service_terminal_length_cmd);
}
+ if (terminal)
+ {
+ install_element(VIEW_NODE, &show_thread_cpu_cmd);
+ install_element(ENABLE_NODE, &show_thread_cpu_cmd);
+ }
srand(time(NULL));
}
diff --git a/lib/if_rmap.c b/lib/if_rmap.c
index 42271025..4cf8ad9a 100644
--- a/lib/if_rmap.c
+++ b/lib/if_rmap.c
@@ -219,7 +219,16 @@ DEFUN (if_rmap,
if_rmap = if_rmap_set (argv[2], type, argv[0]);
return CMD_SUCCESS;
-}
+}
+
+ALIAS (if_rmap,
+ if_ipv6_rmap_cmd,
+ "route-map RMAP_NAME (in|out) IFNAME",
+ "Route map set\n"
+ "Route map name\n"
+ "Route map set for input filtering\n"
+ "Route map set for output filtering\n"
+ "Route map interface name\n")
DEFUN (no_if_rmap,
no_if_rmap_cmd,
@@ -251,7 +260,17 @@ DEFUN (no_if_rmap,
return CMD_WARNING;
}
return CMD_SUCCESS;
-}
+}
+
+ALIAS (no_if_rmap,
+ no_if_ipv6_rmap_cmd,
+ "no route-map ROUTEMAP_NAME (in|out) IFNAME",
+ NO_STR
+ "Route map unset\n"
+ "Route map name\n"
+ "Route map for input filtering\n"
+ "Route map for output filtering\n"
+ "Route map interface name\n")
/* Configuration write function. */
int
@@ -300,7 +319,10 @@ if_rmap_init (int node)
{
ifrmaphash = hash_create (if_rmap_hash_make, if_rmap_hash_cmp);
if (node == RIPNG_NODE) {
- install_element (RIPNG_NODE, &if_rmap_cmd);
- install_element (RIPNG_NODE, &no_if_rmap_cmd);
+ install_element (RIPNG_NODE, &if_ipv6_rmap_cmd);
+ install_element (RIPNG_NODE, &no_if_ipv6_rmap_cmd);
+ } else if (node == RIP_NODE) {
+ install_element (RIP_NODE, &if_rmap_cmd);
+ install_element (RIP_NODE, &no_if_rmap_cmd);
}
}
diff --git a/lib/memory.c b/lib/memory.c
index bf142dcf..93833113 100644
--- a/lib/memory.c
+++ b/lib/memory.c
@@ -255,6 +255,7 @@ struct memory_list memory_list_lib[] =
{ MTYPE_ROUTE_MAP_INDEX, "Route map index " },
{ MTYPE_ROUTE_MAP_RULE, "Route map rule " },
{ MTYPE_ROUTE_MAP_RULE_STR, "Route map rule str" },
+ { MTYPE_ROUTE_MAP_COMPILED, "Route map compiled" },
{ MTYPE_DESC, "Command desc " },
{ MTYPE_BUFFER, "Buffer " },
{ MTYPE_BUFFER_DATA, "Buffer data " },
@@ -323,6 +324,17 @@ struct memory_list memory_list_rip[] =
{ -1, NULL }
};
+struct memory_list memory_list_ripng[] =
+{
+ { MTYPE_RIPNG, "RIPng structure " },
+ { MTYPE_RIPNG_ROUTE, "RIPng route info" },
+ { MTYPE_RIPNG_AGGREGATE, "RIPng aggregate " },
+ { MTYPE_RIPNG_PEER, "RIPng peer " },
+ { MTYPE_RIPNG_OFFSET_LIST, "RIPng offset lst" },
+ { MTYPE_RIPNG_RTE_DATA, "RIPng rte data " },
+ { -1, NULL }
+};
+
struct memory_list memory_list_ospf[] =
{
{ MTYPE_OSPF_TOP, "OSPF top " },
@@ -402,6 +414,8 @@ DEFUN (show_memory_all,
show_memory_vty (vty, memory_list_separator);
show_memory_vty (vty, memory_list_rip);
show_memory_vty (vty, memory_list_separator);
+ show_memory_vty (vty, memory_list_ripng);
+ show_memory_vty (vty, memory_list_separator);
show_memory_vty (vty, memory_list_ospf);
show_memory_vty (vty, memory_list_separator);
show_memory_vty (vty, memory_list_ospf6);
@@ -439,6 +453,17 @@ DEFUN (show_memory_rip,
return CMD_SUCCESS;
}
+DEFUN (show_memory_ripng,
+ show_memory_ripng_cmd,
+ "show memory ripng",
+ SHOW_STR
+ "Memory statistics\n"
+ "RIPng memory\n")
+{
+ show_memory_vty (vty, memory_list_ripng);
+ return CMD_SUCCESS;
+}
+
DEFUN (show_memory_bgp,
show_memory_bgp_cmd,
"show memory bgp",
@@ -479,6 +504,7 @@ memory_init ()
install_element (VIEW_NODE, &show_memory_all_cmd);
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_bgp_cmd);
install_element (VIEW_NODE, &show_memory_ospf_cmd);
install_element (VIEW_NODE, &show_memory_ospf6_cmd);
@@ -487,6 +513,7 @@ memory_init ()
install_element (ENABLE_NODE, &show_memory_all_cmd);
install_element (ENABLE_NODE, &show_memory_lib_cmd);
install_element (ENABLE_NODE, &show_memory_rip_cmd);
+ install_element (ENABLE_NODE, &show_memory_ripng_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/memory.h b/lib/memory.h
index 06681bd1..925f6b65 100644
--- a/lib/memory.h
+++ b/lib/memory.h
@@ -58,8 +58,6 @@ enum
MTYPE_HASH,
MTYPE_HASH_INDEX,
MTYPE_HASH_BACKET,
- MTYPE_RIPNG_ROUTE,
- MTYPE_RIPNG_AGGREGATE,
MTYPE_ROUTE_TABLE,
MTYPE_ROUTE_NODE,
MTYPE_ACCESS_LIST,
@@ -179,6 +177,13 @@ enum
MTYPE_KEYCHAIN,
MTYPE_KEY,
+ MTYPE_RIPNG,
+ MTYPE_RIPNG_ROUTE,
+ MTYPE_RIPNG_AGGREGATE,
+ MTYPE_RIPNG_PEER,
+ MTYPE_RIPNG_OFFSET_LIST,
+ MTYPE_RIPNG_RTE_DATA,
+
MTYPE_VTYSH_CONFIG,
MTYPE_VTYSH_CONFIG_LINE,
diff --git a/lib/sockunion.c b/lib/sockunion.c
index 21371624..e4b311c7 100644
--- a/lib/sockunion.c
+++ b/lib/sockunion.c
@@ -302,16 +302,16 @@ sockunion_log (union sockunion *su)
switch (su->sa.sa_family)
{
case AF_INET:
- snprintf (buf, BUFSIZ, "%s", inet_ntoa (su->sin.sin_addr));
+ snprintf (buf, SU_ADDRSTRLEN, "%s", inet_ntoa (su->sin.sin_addr));
break;
#ifdef HAVE_IPV6
case AF_INET6:
- snprintf (buf, BUFSIZ, "%s",
- inet_ntop (AF_INET6, &(su->sin6.sin6_addr), buf, BUFSIZ));
+ snprintf (buf, SU_ADDRSTRLEN, "%s",
+ inet_ntop (AF_INET6, &(su->sin6.sin6_addr), buf, SU_ADDRSTRLEN));
break;
#endif /* HAVE_IPV6 */
default:
- snprintf (buf, BUFSIZ, "af_unknown %d ", su->sa.sa_family);
+ snprintf (buf, SU_ADDRSTRLEN, "af_unknown %d ", su->sa.sa_family);
break;
}
return buf;
@@ -344,8 +344,13 @@ sockunion_connect (int fd, union sockunion *peersu, unsigned short port,
{
#ifdef HAVE_SIN6_SCOPE_ID
/* su.sin6.sin6_scope_id = ifindex; */
+#ifdef MUSICA
+ su.sin6.sin6_scope_id = ifindex;
+#endif
#endif /* HAVE_SIN6_SCOPE_ID */
+#ifndef MUSICA
SET_IN6_LINKLOCAL_IFINDEX (su.sin6.sin6_addr, ifindex);
+#endif
}
#endif /* KAME */
break;
diff --git a/lib/zclient.c b/lib/zclient.c
index 5e371546..bb7747fa 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -318,23 +318,23 @@ zapi_ipv4_add (struct zclient *zclient, struct prefix_ipv4 *p,
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
{
if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE))
- {
- stream_putc (s, 1);
- stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE);
- }
+ {
+ stream_putc (s, 1);
+ stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE);
+ }
else
- stream_putc (s, api->nexthop_num + api->ifindex_num);
-
+ stream_putc (s, api->nexthop_num + api->ifindex_num);
+
for (i = 0; i < api->nexthop_num; i++)
- {
- stream_putc (s, ZEBRA_NEXTHOP_IPV4);
- stream_put_in_addr (s, api->nexthop[i]);
- }
+ {
+ stream_putc (s, ZEBRA_NEXTHOP_IPV4);
+ stream_put_in_addr (s, api->nexthop[i]);
+ }
for (i = 0; i < api->ifindex_num; i++)
- {
- stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
- stream_putl (s, api->ifindex[i]);
- }
+ {
+ stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
+ stream_putl (s, api->ifindex[i]);
+ }
}
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE))
@@ -378,23 +378,23 @@ zapi_ipv4_delete (struct zclient *zclient, struct prefix_ipv4 *p,
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
{
if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE))
- {
- stream_putc (s, 1);
- stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE);
- }
+ {
+ stream_putc (s, 1);
+ stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE);
+ }
else
- stream_putc (s, api->nexthop_num + api->ifindex_num);
+ stream_putc (s, api->nexthop_num + api->ifindex_num);
for (i = 0; i < api->nexthop_num; i++)
- {
- stream_putc (s, ZEBRA_NEXTHOP_IPV4);
- stream_put_in_addr (s, api->nexthop[i]);
- }
+ {
+ stream_putc (s, ZEBRA_NEXTHOP_IPV4);
+ stream_put_in_addr (s, api->nexthop[i]);
+ }
for (i = 0; i < api->ifindex_num; i++)
- {
- stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
- stream_putl (s, api->ifindex[i]);
- }
+ {
+ stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
+ stream_putl (s, api->ifindex[i]);
+ }
}
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE))
@@ -564,6 +564,7 @@ zebra_interface_add_read (struct stream *s)
ifp->ifindex = stream_getl (s);
/* Read interface's value. */
+ ifp->status = stream_getc (s);
ifp->flags = stream_getl (s);
ifp->metric = stream_getl (s);
ifp->mtu = stream_getl (s);
@@ -600,6 +601,7 @@ zebra_interface_state_read (struct stream *s)
ifp->ifindex = stream_getl (s);
/* Read interface's value. */
+ ifp->status = stream_getc (s);
ifp->flags = stream_getl (s);
ifp->metric = stream_getl (s);
ifp->mtu = stream_getl (s);
diff --git a/lib/zebra.h b/lib/zebra.h
index 6a60b94b..2ac491d1 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -149,6 +149,10 @@ typedef int socklen_t;
#include <netinet/in_var.h>
#endif /* HAVE_NETINET_IN_VAR_H */
+#ifdef HAVE_NETINET6_IN6_VAR_H
+#include <netinet6/in6_var.h>
+#endif /* HAVE_NETINET6_IN6_VAR_H */
+
#ifdef HAVE_NETINET_IN6_VAR_H
#include <netinet/in6_var.h>
#endif /* HAVE_NETINET_IN6_VAR_H */
@@ -262,6 +266,7 @@ struct in_pktinfo
#define ZEBRA_FLAG_SELECTED 0x10
#define ZEBRA_FLAG_CHANGED 0x20
#define ZEBRA_FLAG_STATIC 0x40
+#define ZEBRA_FLAG_REJECT 0x80
/* Zebra nexthop flags. */
#define ZEBRA_NEXTHOP_IFINDEX 1
@@ -272,7 +277,7 @@ struct in_pktinfo
#define ZEBRA_NEXTHOP_IPV6 6
#define ZEBRA_NEXTHOP_IPV6_IFINDEX 7
#define ZEBRA_NEXTHOP_IPV6_IFNAME 8
-#define ZEBRA_NEXTHOP_BLACKHOLE 9
+#define ZEBRA_NEXTHOP_BLACKHOLE 9
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001 /* Internet address 127.0.0.1. */
diff --git a/ospf6d/Makefile.am b/ospf6d/Makefile.am
index b13942be..e42814af 100644
--- a/ospf6d/Makefile.am
+++ b/ospf6d/Makefile.am
@@ -28,7 +28,7 @@ noinst_HEADERS = \
ospf6d_SOURCES = \
ospf6_main.c $(libospf6_a_SOURCES)
-ospf6d_LDADD = ../lib/libzebra.a @LIBCAP@
+ospf6d_LDADD = -L../lib -lzebra @LIBCAP@
sysconf_DATA = ospf6d.conf.sample
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 56ed1a6c..deb708ac 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -486,6 +486,18 @@ ospf6_asbr_route_add (int type, int ifindex, struct prefix *prefix,
struct ospf6_external_route *route;
struct ospf6_external_info *info, tinfo;
+#if defined (MUSICA) || defined (LINUX)
+ /* XXX As long as the OSPFv3 redistribution is applied to all the connected
+ * routes, one needs to filter the ::/96 prefixes.
+ * However it could be a wanted case, it will be removed soon.
+ */
+ struct prefix_ipv6 *p = (prefix_ipv6 *)prefix;
+
+ if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
+ (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
+ return;
+#endif /* MUSICA or LINUX */
+
if (! ospf6_zebra_is_redistribute (type))
return;
@@ -592,6 +604,18 @@ ospf6_asbr_route_remove (int type, int ifindex, struct prefix *prefix)
struct ospf6_external_info *info;
struct ospf6_lsa *lsa;
+#if defined (MUSICA) || defined (LINUX)
+ /* XXX As long as the OSPFv3 redistribution is applied to all the connected
+ * routes, one needs to filter the ::/96 prefixes.
+ * However it could be a wanted case, it will be removed soon.
+ */
+ struct prefix_ipv6 *p = (prefix_ipv6 *)prefix;
+
+ if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
+ (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
+ return;
+#endif /* MUSICA or LINUX */
+
node = route_node_get (external_table, prefix);
route = node->info;
diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c
index 7ed0030e..e6cd6aaa 100644
--- a/ospf6d/ospf6_main.c
+++ b/ospf6d/ospf6_main.c
@@ -309,10 +309,10 @@ main (int argc, char *argv[], char *envp[])
if (! daemon_mode)
flag = ZLOG_STDOUT;
else
- flag = 0;
+ flag = ZLOG_NOLOG;
zlog_default = openzlog (progname, flag, ZLOG_OSPF6,
- LOG_CONS|LOG_NDELAY|LOG_PERROR|LOG_PID,
+ LOG_CONS|LOG_NDELAY|LOG_PID,
LOG_DAEMON);
zprivs_init (&ospf6d_privs);
signal_init ();
@@ -342,9 +342,11 @@ main (int argc, char *argv[], char *envp[])
/* Make ospf vty socket. */
vty_serv_sock (vty_addr, vty_port, OSPF6_VTYSH_PATH);
+#ifdef DEBUG
/* Print start message */
zlog_notice ("OSPF6d (Zebra-%s ospf6d-%s) starts",
ZEBRA_VERSION, OSPF6_DAEMON_VERSION);
+#endif
/* Start finite state machine, here we go! */
while (thread_fetch (master, &thread))
diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c
index 9b98f808..ece34135 100644
--- a/ospf6d/ospf6_network.c
+++ b/ospf6d/ospf6_network.c
@@ -264,10 +264,8 @@ ospf6_leave_allspfrouters (u_int ifindex)
&mreq6, sizeof (mreq6)) < 0)
zlog_warn ("Network: Leave AllSPFRouters on ifindex %d Failed: %s",
ifindex, strerror (errno));
-#if 0
else
zlog_info ("Network: Leave AllSPFRouters on ifindex %d", ifindex);
-#endif
}
void
@@ -284,10 +282,8 @@ ospf6_join_alldrouters (u_int ifindex)
&mreq6, sizeof (mreq6)) < 0)
zlog_warn ("Network: Join AllDRouters on ifindex %d Failed: %s",
ifindex, strerror (errno));
-#if 0
else
zlog_info ("Network: Join AllDRouters on ifindex %d", ifindex);
-#endif
}
void
@@ -303,10 +299,8 @@ ospf6_leave_alldrouters (u_int ifindex)
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
&mreq6, sizeof (mreq6)) < 0)
zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex);
-#if 0
else
zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex);
-#endif
}
/* setsockopt ReUseAddr to on */
@@ -349,7 +343,7 @@ void
ospf6_set_checksum ()
{
int offset = 12;
-#ifndef DISABLE_IPV6_CHECKSUM
+#if !defined(DISABLE_IPV6_CHECKSUM)
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM,
&offset, sizeof (offset)) < 0)
zlog_warn ("Network: set IPV6_CHECKSUM failed: %s", strerror (errno));
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index a8a058f2..f9cc3299 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -286,6 +286,9 @@ ospf6_create (unsigned long process_id)
void
ospf6_delete (struct ospf6 *ospf6)
{
+ if (!ospf6)
+ return;
+
ospf6_route_remove_all (ospf6->route_table);
ospf6_free (ospf6);
}
diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am
index dd0a0922..81f212c4 100644
--- a/ospfd/Makefile.am
+++ b/ospfd/Makefile.am
@@ -28,7 +28,7 @@ noinst_HEADERS = \
ospfd_SOURCES = \
ospf_main.c $(libospf_a_SOURCES)
-ospfd_LDADD = ../lib/libzebra.a @LIBCAP@
+ospfd_LDADD = -L../lib -lzebra @LIBCAP@
sysconf_DATA = ospfd.conf.sample
diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c
index 12415453..489d0278 100644
--- a/ospfd/ospf_main.c
+++ b/ospfd/ospf_main.c
@@ -208,7 +208,7 @@ main (int argc, char **argv)
progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
/* Invoked by a priviledged user? -- endo. */
- if (getuid () != 0)
+ if (geteuid () != 0)
{
errno = EPERM;
perror (progname);
@@ -319,8 +319,10 @@ main (int argc, char **argv)
/* Create VTY socket */
vty_serv_sock (vty_addr, vty_port, OSPF_VTYSH_PATH);
+#ifdef DEBUG
/* Print banner. */
zlog (NULL, LOG_INFO, "OSPFd (%s) starts", ZEBRA_VERSION);
+#endif
/* Fetch next active thread. */
while (thread_fetch (master, &thread))
diff --git a/ripd/ChangeLog b/ripd/ChangeLog
index 42fced50..c80338dd 100644
--- a/ripd/ChangeLog
+++ b/ripd/ChangeLog
@@ -1,3 +1,12 @@
+2003-05-25 Vincent Jardin <vjardin@wanadoo.fr>
+
+ * 6Wind patch merge.
+
+2003-04-19 Hasso Tepper <hasso@estpak.ee>
+
+ * rip_routemap.c: sync daemon's route-map commands to have same
+ syntax
+
2002-07-07 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* zebra-0.93 released.
diff --git a/ripd/Makefile.am b/ripd/Makefile.am
index 138c3a51..2c187e84 100644
--- a/ripd/Makefile.am
+++ b/ripd/Makefile.am
@@ -17,7 +17,7 @@ noinst_HEADERS = \
ripd_SOURCES = \
rip_main.c $(librip_a_SOURCES)
-ripd_LDADD = ../lib/libzebra.a @LIBCAP@
+ripd_LDADD = -L../lib -lzebra @LIBCAP@
sysconf_DATA = ripd.conf.sample
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index d7856341..c3889295 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -44,6 +44,10 @@
void rip_enable_apply (struct interface *);
void rip_passive_interface_apply (struct interface *);
int rip_if_down(struct interface *ifp);
+int rip_enable_if_lookup (char *ifname);
+int rip_enable_network_lookup2 (struct connected *connected);
+void rip_enable_apply_all ();
+
struct message ri_version_msg[] =
{
@@ -125,7 +129,7 @@ rip_interface_new ()
Relay or SMDS is enabled, the default value for split-horizon is
off. But currently Zebra does detect Frame Relay or SMDS
interface. So all interface is set to split horizon. */
- ri->split_horizon_default = 1;
+ ri->split_horizon_default = RIP_SPLIT_HORIZON;
ri->split_horizon = ri->split_horizon_default;
return ri;
@@ -235,10 +239,8 @@ rip_request_interface_send (struct interface *ifp, u_char version)
to.sin_port = htons (RIP_PORT_DEFAULT);
to.sin_addr = p->prefix;
-#if 0
if (IS_RIP_DEBUG_EVENT)
zlog_info ("SEND request to %s", inet_ntoa (to.sin_addr));
-#endif /* 0 */
rip_request_send (&to, ifp, version);
}
@@ -475,6 +477,9 @@ rip_interface_add (int command, struct zclient *zclient, zebra_size_t length)
/* rip_request_neighbor_all (); */
+ /* Check interface routemap. */
+ rip_if_rmap_update_interface (ifp);
+
return 0;
}
@@ -563,8 +568,8 @@ rip_interface_reset ()
ri->key_chain = NULL;
}
- ri->split_horizon = 0;
- ri->split_horizon_default = 0;
+ ri->split_horizon = RIP_NO_SPLIT_HORIZON;
+ ri->split_horizon_default = RIP_NO_SPLIT_HORIZON;
ri->list[RIP_FILTER_IN] = NULL;
ri->list[RIP_FILTER_OUT] = NULL;
@@ -653,6 +658,34 @@ rip_if_down_all ()
}
}
+static void
+rip_apply_address_add (struct connected *ifc) {
+ struct prefix_ipv4 address;
+ struct prefix *p;
+
+ if (!rip)
+ return;
+
+ if (! if_is_up(ifc->ifp))
+ return;
+
+ p = ifc->address;
+
+ memset (&address, 0, sizeof (address));
+ address.family = p->family;
+ address.prefix = p->u.prefix4;
+ address.prefixlen = p->prefixlen;
+ apply_mask_ipv4(&address);
+
+ /* Check if this interface is RIP enabled or not
+ or Check if this address's prefix is RIP enabled */
+ if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) ||
+ (rip_enable_network_lookup2(ifc) >= 0))
+ rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
+ &address, ifc->ifp->ifindex, NULL);
+
+}
+
int
rip_interface_address_add (int command, struct zclient *zclient,
zebra_size_t length)
@@ -672,9 +705,9 @@ rip_interface_address_add (int command, struct zclient *zclient,
if (IS_RIP_DEBUG_ZEBRA)
zlog_info ("connected address %s/%d is added",
inet_ntoa (p->u.prefix4), p->prefixlen);
-
- /* Check is this interface is RIP enabled or not.*/
- rip_enable_apply (ifc->ifp);
+
+ /* Check if this prefix needs to be redistributed */
+ rip_apply_address_add(ifc);
#ifdef HAVE_SNMP
rip_ifaddr_add (ifc->ifp, ifc);
@@ -684,6 +717,29 @@ rip_interface_address_add (int command, struct zclient *zclient,
return 0;
}
+static void
+rip_apply_address_del (struct connected *ifc) {
+ struct prefix_ipv4 address;
+ struct prefix *p;
+
+ if (!rip)
+ return;
+
+ if (! if_is_up(ifc->ifp))
+ return;
+
+ p = ifc->address;
+
+ memset (&address, 0, sizeof (address));
+ address.family = p->family;
+ address.prefix = p->u.prefix4;
+ address.prefixlen = p->prefixlen;
+ apply_mask_ipv4(&address);
+
+ rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
+ &address, ifc->ifp->ifindex);
+}
+
int
rip_interface_address_delete (int command, struct zclient *zclient,
zebra_size_t length)
@@ -707,8 +763,9 @@ rip_interface_address_delete (int command, struct zclient *zclient,
rip_ifaddr_delete (ifc->ifp, ifc);
#endif /* HAVE_SNMP */
- /* Check if this interface is RIP enabled or not.*/
- rip_enable_apply (ifc->ifp);
+ /* Chech wether this prefix needs to be removed */
+ rip_apply_address_del(ifc);
+
}
connected_free (ifc);
@@ -719,8 +776,10 @@ rip_interface_address_delete (int command, struct zclient *zclient,
}
/* Check interface is enabled by network statement. */
+/* Check wether the interface has at least a connected prefix that
+ * is within the ripng_enable_network table. */
int
-rip_enable_network_lookup (struct interface *ifp)
+rip_enable_network_lookup_if (struct interface *ifp)
{
struct listnode *nn;
struct connected *connected;
@@ -752,6 +811,34 @@ rip_enable_network_lookup (struct interface *ifp)
return -1;
}
+/* Check wether connected is within the ripng_enable_network table. */
+int
+rip_enable_network_lookup2 (struct connected *connected)
+{
+ struct prefix_ipv4 address;
+ struct prefix *p;
+
+ p = connected->address;
+
+ if (p->family == AF_INET) {
+ struct route_node *node;
+
+ address.family = p->family;
+ address.prefix = p->u.prefix4;
+ address.prefixlen = IPV4_MAX_BITLEN;
+
+ /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within rip_enable_network */
+ node = route_node_match (rip_enable_network,
+ (struct prefix *)&address);
+
+ if (node) {
+ route_unlock_node (node);
+ return 1;
+ }
+ }
+
+ return -1;
+}
/* Add RIP enable network. */
int
rip_enable_network_add (struct prefix *p)
@@ -768,6 +855,9 @@ rip_enable_network_add (struct prefix *p)
else
node->info = "enabled";
+ /* XXX: One should find a better solution than a generic one */
+ rip_enable_apply_all();
+
return 1;
}
@@ -788,6 +878,9 @@ rip_enable_network_delete (struct prefix *p)
/* Unlock lookup lock. */
route_unlock_node (node);
+ /* XXX: One should find a better solution than a generic one */
+ rip_enable_apply_all ();
+
return 1;
}
return -1;
@@ -819,6 +912,8 @@ rip_enable_if_add (char *ifname)
vector_set (rip_enable_interface, strdup (ifname));
+ rip_enable_apply_all(); /* TODOVJ */
+
return 1;
}
@@ -837,6 +932,8 @@ rip_enable_if_delete (char *ifname)
free (str);
vector_unset (rip_enable_interface, index);
+ rip_enable_apply_all(); /* TODOVJ */
+
return 1;
}
@@ -892,10 +989,13 @@ rip_connect_set (struct interface *ifp, int set)
address.prefixlen = p->prefixlen;
apply_mask_ipv4 (&address);
- if (set)
- rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
- &address, connected->ifp->ifindex, NULL);
- else
+ if (set) {
+ /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
+ if ((rip_enable_if_lookup(connected->ifp->name) >= 0) ||
+ (rip_enable_network_lookup2(connected) >= 0))
+ rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
+ &address, connected->ifp->ifindex, NULL);
+ } else
{
rip_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
&address, connected->ifp->ifindex);
@@ -914,16 +1014,13 @@ rip_enable_apply (struct interface *ifp)
struct rip_interface *ri = NULL;
/* Check interface. */
- if (if_is_loopback (ifp))
- return;
-
if (! if_is_operative (ifp))
return;
ri = ifp->info;
/* Check network configuration. */
- ret = rip_enable_network_lookup (ifp);
+ ret = rip_enable_network_lookup_if (ifp);
/* If the interface is matched. */
if (ret > 0)
@@ -948,7 +1045,6 @@ rip_enable_apply (struct interface *ifp)
/* Update running status of the interface. */
if (ri->enable_network || ri->enable_interface)
{
- if (! ri->running)
{
if (IS_RIP_DEBUG_EVENT)
zlog_info ("turn on %s", ifp->name);
@@ -964,13 +1060,11 @@ rip_enable_apply (struct interface *ifp)
{
if (ri->running)
{
- if (IS_RIP_DEBUG_EVENT)
- zlog_info ("turn off %s", ifp->name);
-
- /* Might as well clean up the route table as well */
+ /* Might as well clean up the route table as well
+ * rip_if_down sets to 0 ri->running, and displays "turn off %s"
+ **/
rip_if_down(ifp);
- ri->running = 0;
rip_connect_set (ifp, 0);
}
}
@@ -1190,8 +1284,6 @@ DEFUN (rip_network,
return CMD_WARNING;
}
- rip_enable_apply_all ();
-
return CMD_SUCCESS;
}
@@ -1221,8 +1313,6 @@ DEFUN (no_rip_network,
return CMD_WARNING;
}
- rip_enable_apply_all ();
-
return CMD_SUCCESS;
}
@@ -1670,10 +1760,15 @@ ALIAS (no_ip_rip_authentication_key_chain,
"Authentication key-chain\n"
"name of key-chain\n")
-DEFUN (rip_split_horizon,
- rip_split_horizon_cmd,
- "ip split-horizon",
+/* CHANGED: ip rip split-horizon
+ Cisco and Zebra's command is
+ ip split-horizon
+ */
+DEFUN (ip_rip_split_horizon,
+ ip_rip_split_horizon_cmd,
+ "ip rip split-horizon",
IP_STR
+ "Routing Information Protocol\n"
"Perform split horizon\n")
{
struct interface *ifp;
@@ -1682,15 +1777,38 @@ DEFUN (rip_split_horizon,
ifp = vty->index;
ri = ifp->info;
- ri->split_horizon = 1;
+ ri->split_horizon = RIP_SPLIT_HORIZON;
return CMD_SUCCESS;
}
-DEFUN (no_rip_split_horizon,
- no_rip_split_horizon_cmd,
- "no ip split-horizon",
+DEFUN (ip_rip_split_horizon_poisoned_reverse,
+ ip_rip_split_horizon_poisoned_reverse_cmd,
+ "ip rip split-horizon poisoned-reverse",
+ IP_STR
+ "Routing Information Protocol\n"
+ "Perform split horizon\n"
+ "With poisoned-reverse\n")
+{
+ struct interface *ifp;
+ struct rip_interface *ri;
+
+ ifp = vty->index;
+ ri = ifp->info;
+
+ ri->split_horizon = RIP_SPLIT_HORIZON_POISONED_REVERSE;
+ return CMD_SUCCESS;
+}
+
+/* CHANGED: no ip rip split-horizon
+ Cisco and Zebra's command is
+ no ip split-horizon
+ */
+DEFUN (no_ip_rip_split_horizon,
+ no_ip_rip_split_horizon_cmd,
+ "no ip rip split-horizon",
NO_STR
IP_STR
+ "Routing Information Protocol\n"
"Perform split horizon\n")
{
struct interface *ifp;
@@ -1699,10 +1817,19 @@ DEFUN (no_rip_split_horizon,
ifp = vty->index;
ri = ifp->info;
- ri->split_horizon = 0;
+ ri->split_horizon = RIP_NO_SPLIT_HORIZON;
return CMD_SUCCESS;
}
+ALIAS (no_ip_rip_split_horizon,
+ no_ip_rip_split_horizon_poisoned_reverse_cmd,
+ "no ip rip split-horizon poisoned-reverse",
+ NO_STR
+ IP_STR
+ "Routing Information Protocol\n"
+ "Perform split horizon\n"
+ "With poisoned-reverse\n")
+
DEFUN (rip_passive_interface,
rip_passive_interface_cmd,
"passive-interface IFNAME",
@@ -1736,6 +1863,18 @@ rip_interface_config_write (struct vty *vty)
ifp = getdata (node);
ri = ifp->info;
+ /* Do not display the interface if there is no
+ * configuration about it.
+ **/
+ if ((!ifp->desc) &&
+ (ri->split_horizon == ri->split_horizon_default) &&
+ (ri->ri_send == RI_RIP_UNSPEC) &&
+ (ri->ri_receive == RI_RIP_UNSPEC) &&
+ (ri->auth_type != RIP_AUTH_MD5) &&
+ (!ri->auth_str) &&
+ (!ri->key_chain) )
+ continue;
+
vty_out (vty, "interface %s%s", ifp->name,
VTY_NEWLINE);
@@ -1746,10 +1885,19 @@ rip_interface_config_write (struct vty *vty)
/* Split horizon. */
if (ri->split_horizon != ri->split_horizon_default)
{
- if (ri->split_horizon)
- vty_out (vty, " ip split-horizon%s", VTY_NEWLINE);
- else
- vty_out (vty, " no ip split-horizon%s", VTY_NEWLINE);
+ switch (ri->split_horizon) {
+ case RIP_SPLIT_HORIZON:
+ vty_out (vty, " ip rip split-horizon%s", VTY_NEWLINE);
+ break;
+ case RIP_SPLIT_HORIZON_POISONED_REVERSE:
+ vty_out (vty, " ip rip split-horizon poisoned-reverse%s",
+ VTY_NEWLINE);
+ break;
+ case RIP_NO_SPLIT_HORIZON:
+ default:
+ vty_out (vty, " no ip rip split-horizon%s", VTY_NEWLINE);
+ break;
+ }
}
/* RIP version setting. */
@@ -1846,6 +1994,7 @@ int
rip_interface_delete_hook (struct interface *ifp)
{
XFREE (MTYPE_RIP_INTERFACE, ifp->info);
+ ifp->info = NULL;
return 0;
}
@@ -1906,6 +2055,8 @@ rip_if_init ()
install_element (INTERFACE_NODE, &no_ip_rip_authentication_string_cmd);
install_element (INTERFACE_NODE, &no_ip_rip_authentication_string2_cmd);
- install_element (INTERFACE_NODE, &rip_split_horizon_cmd);
- install_element (INTERFACE_NODE, &no_rip_split_horizon_cmd);
+ install_element (INTERFACE_NODE, &ip_rip_split_horizon_cmd);
+ install_element (INTERFACE_NODE, &ip_rip_split_horizon_poisoned_reverse_cmd);
+ install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_cmd);
+ install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_poisoned_reverse_cmd);
}
diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c
index 791de412..bab29f32 100644
--- a/ripd/rip_routemap.c
+++ b/ripd/rip_routemap.c
@@ -31,6 +31,18 @@
#include "plist.h"
#include "ripd/ripd.h"
+
+struct rip_metric_modifier
+{
+ enum
+ {
+ metric_increment,
+ metric_decrement,
+ metric_absolute
+ } type;
+
+ u_char metric;
+};
/* Add rip route map rule. */
int
@@ -439,6 +451,57 @@ struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
route_match_ip_address_prefix_list_compile,
route_match_ip_address_prefix_list_free
};
+
+/* `match tag TAG' */
+/* Match function return 1 if match is success else return zero. */
+route_map_result_t
+route_match_tag (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ u_short *tag;
+ struct rip_info *rinfo;
+
+ if (type == RMAP_RIP)
+ {
+ tag = rule;
+ rinfo = object;
+
+ /* The information stored by rinfo is host ordered. */
+ if (rinfo->tag == *tag)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
+ }
+ return RMAP_NOMATCH;
+}
+
+/* Route map `match tag' match statement. `arg' is TAG value */
+void *
+route_match_tag_compile (char *arg)
+{
+ u_short *tag;
+
+ tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
+ *tag = atoi (arg);
+
+ return tag;
+}
+
+/* Free route map's compiled `match tag' value. */
+void
+route_match_tag_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for tag matching. */
+struct route_map_rule_cmd route_match_tag_cmd =
+{
+ "tag",
+ route_match_tag,
+ route_match_tag_compile,
+ route_match_tag_free
+};
/* `set metric METRIC' */
@@ -447,17 +510,26 @@ route_map_result_t
route_set_metric (void *rule, struct prefix *prefix,
route_map_object_t type, void *object)
{
- u_int32_t *metric;
- struct rip_info *rinfo;
-
if (type == RMAP_RIP)
{
- /* Fetch routemap's rule information. */
- metric = rule;
+ struct rip_metric_modifier *mod;
+ struct rip_info *rinfo;
+
+ mod = rule;
rinfo = object;
-
- /* Set metric out value. */
- rinfo->metric_out = *metric;
+
+ if (mod->type == metric_increment)
+ rinfo->metric_out += mod->metric;
+ else if (mod->type == metric_decrement)
+ rinfo->metric_out -= mod->metric;
+ else if (mod->type == metric_absolute)
+ rinfo->metric_out = mod->metric;
+
+ if (rinfo->metric_out < 1)
+ rinfo->metric_out = 1;
+ if (rinfo->metric_out > RIP_METRIC_INFINITY)
+ rinfo->metric_out = RIP_METRIC_INFINITY;
+
rinfo->metric_set = 1;
}
return RMAP_OKAY;
@@ -467,22 +539,51 @@ route_set_metric (void *rule, struct prefix *prefix,
void *
route_set_metric_compile (char *arg)
{
- u_int32_t *metric;
+ int len;
+ char *pnt;
+ int type;
+ long metric;
+ char *endptr = NULL;
+ struct rip_metric_modifier *mod;
- metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
- *metric = atoi (arg);
+ len = strlen (arg);
+ pnt = arg;
- return metric;
+ if (len == 0)
+ return NULL;
-#if 0
- /* To make it consistent to other daemon, metric check is commented
- out.*/
- if (*metric >= 0 && *metric <= 16)
- return metric;
+ /* Examine first character. */
+ if (arg[0] == '+')
+ {
+ type = metric_increment;
+ pnt++;
+ }
+ else if (arg[0] == '-')
+ {
+ type = metric_decrement;
+ pnt++;
+ }
+ else
+ type = metric_absolute;
- XFREE (MTYPE_ROUTE_MAP_COMPILED, metric);
- return NULL;
-#endif /* 0 */
+ /* Check beginning with digit string. */
+ if (*pnt < '0' || *pnt > '9')
+ return NULL;
+
+ /* Convert string to integer. */
+ metric = strtol (pnt, &endptr, 10);
+
+ if (metric == LONG_MAX || *endptr != '\0')
+ return NULL;
+ if (metric < 0 || metric > RIP_METRIC_INFINITY)
+ return NULL;
+
+ mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
+ sizeof (struct rip_metric_modifier));
+ mod->type = type;
+ mod->metric = metric;
+
+ return mod;
}
/* Free route map's compiled `set metric' value. */
@@ -560,6 +661,58 @@ struct route_map_rule_cmd route_set_ip_nexthop_cmd =
route_set_ip_nexthop_compile,
route_set_ip_nexthop_free
};
+
+/* `set tag TAG' */
+
+/* Set tag to object. ojbect must be pointer to struct attr. */
+route_map_result_t
+route_set_tag (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ u_short *tag;
+ struct rip_info *rinfo;
+
+ if(type == RMAP_RIP)
+ {
+ /* Fetch routemap's rule information. */
+ tag = rule;
+ rinfo = object;
+
+ /* Set next hop value. */
+ rinfo->tag_out = *tag;
+ }
+
+ return RMAP_OKAY;
+}
+
+/* Route map `tag' compile function. Given string is converted
+ to u_short. */
+void *
+route_set_tag_compile (char *arg)
+{
+ u_short *tag;
+
+ tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
+ *tag = atoi (arg);
+
+ return tag;
+}
+
+/* Free route map's compiled `ip nexthop' value. */
+void
+route_set_tag_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for tag set. */
+struct route_map_rule_cmd route_set_tag_cmd =
+{
+ "tag",
+ route_set_tag,
+ route_set_tag_compile,
+ route_set_tag_free
+};
#define MATCH_STR "Match values from routing table\n"
#define SET_STR "Set values in destination routing protocol\n"
@@ -628,11 +781,13 @@ ALIAS (no_match_interface,
DEFUN (match_ip_next_hop,
match_ip_next_hop_cmd,
- "match ip next-hop WORD",
+ "match ip next-hop (<1-199>|<1300-2699>|WORD)",
MATCH_STR
IP_STR
"Match next-hop address of route\n"
- "IP access-list name\n")
+ "IP access-list number\n"
+ "IP access-list number (expanded range)\n"
+ "IP Access-list name\n")
{
return rip_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
}
@@ -653,12 +808,14 @@ DEFUN (no_match_ip_next_hop,
ALIAS (no_match_ip_next_hop,
no_match_ip_next_hop_val_cmd,
- "no match ip next-hop WORD",
+ "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
NO_STR
MATCH_STR
IP_STR
"Match next-hop address of route\n"
- "IP access-list name\n")
+ "IP access-list number\n"
+ "IP access-list number (expanded range)\n"
+ "IP Access-list name\n")
DEFUN (match_ip_next_hop_prefix_list,
match_ip_next_hop_prefix_list_cmd,
@@ -697,13 +854,16 @@ ALIAS (no_match_ip_next_hop_prefix_list,
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
-DEFUN (match_ip_address,
+DEFUN (match_ip_address,
match_ip_address_cmd,
- "match ip address WORD",
+ "match ip address (<1-199>|<1300-2699>|WORD)",
MATCH_STR
IP_STR
"Match address of route\n"
- "IP access-list name\n")
+ "IP access-list number\n"
+ "IP access-list number (expanded range)\n"
+ "IP Access-list name\n")
+
{
return rip_route_match_add (vty, vty->index, "ip address", argv[0]);
}
@@ -722,14 +882,16 @@ DEFUN (no_match_ip_address,
return rip_route_match_delete (vty, vty->index, "ip address", argv[0]);
}
-ALIAS (no_match_ip_address,
+ALIAS (no_match_ip_address,
no_match_ip_address_val_cmd,
- "no match ip address WORD",
+ "no match ip address (<1-199>|<1300-2699>|WORD)",
NO_STR
MATCH_STR
IP_STR
"Match address of route\n"
- "IP access-list name\n")
+ "IP access-list number\n"
+ "IP access-list number (expanded range)\n"
+ "IP Access-list name\n")
DEFUN (match_ip_address_prefix_list,
match_ip_address_prefix_list_cmd,
@@ -768,6 +930,37 @@ ALIAS (no_match_ip_address_prefix_list,
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
+DEFUN (match_tag,
+ match_tag_cmd,
+ "match tag <0-65535>",
+ MATCH_STR
+ "Match tag of route\n"
+ "Metric value\n")
+{
+ return rip_route_match_add (vty, vty->index, "tag", argv[0]);
+}
+
+DEFUN (no_match_tag,
+ no_match_tag_cmd,
+ "no match tag",
+ NO_STR
+ MATCH_STR
+ "Match tag of route\n")
+{
+ if (argc == 0)
+ return rip_route_match_delete (vty, vty->index, "tag", NULL);
+
+ return rip_route_match_delete (vty, vty->index, "tag", argv[0]);
+}
+
+ALIAS (no_match_tag,
+ no_match_tag_val_cmd,
+ "no match tag <0-65535>",
+ NO_STR
+ MATCH_STR
+ "Match tag of route\n"
+ "Metric value\n")
+
/* set functions */
DEFUN (set_metric,
@@ -780,6 +973,13 @@ DEFUN (set_metric,
return rip_route_set_add (vty, vty->index, "metric", argv[0]);
}
+ALIAS (set_metric,
+ set_metric_addsub_cmd,
+ "set metric <+/-metric>",
+ SET_STR
+ "Metric value for destination routing protocol\n"
+ "Add or subtract BGP metric\n")
+
DEFUN (no_set_metric,
no_set_metric_cmd,
"no set metric",
@@ -795,11 +995,12 @@ DEFUN (no_set_metric,
ALIAS (no_set_metric,
no_set_metric_val_cmd,
- "no set metric <0-4294967295>",
+ "no set metric (<0-4294967295>|<+/-metric>)",
NO_STR
SET_STR
"Metric value for destination routing protocol\n"
- "Metric value\n")
+ "Metric value\n"
+ "Add or subtract metric\n")
DEFUN (set_ip_nexthop,
set_ip_nexthop_cmd,
@@ -845,6 +1046,37 @@ ALIAS (no_set_ip_nexthop,
"Next hop address\n"
"IP address of next hop\n")
+DEFUN (set_tag,
+ set_tag_cmd,
+ "set tag <0-65535>",
+ SET_STR
+ "Tag value for routing protocol\n"
+ "Tag value\n")
+{
+ return rip_route_set_add (vty, vty->index, "tag", argv[0]);
+}
+
+DEFUN (no_set_tag,
+ no_set_tag_cmd,
+ "no set tag",
+ NO_STR
+ SET_STR
+ "Tag value for routing protocol\n")
+{
+ if (argc == 0)
+ return rip_route_set_delete (vty, vty->index, "tag", NULL);
+
+ return rip_route_set_delete (vty, vty->index, "tag", argv[0]);
+}
+
+ALIAS (no_set_tag,
+ no_set_tag_val_cmd,
+ "no set tag <0-65535>",
+ NO_STR
+ SET_STR
+ "Tag value for routing protocol\n"
+ "Tag value\n")
+
void
rip_route_map_reset ()
{
@@ -866,9 +1098,11 @@ rip_route_map_init ()
route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
route_map_install_match (&route_match_ip_address_cmd);
route_map_install_match (&route_match_ip_address_prefix_list_cmd);
+ route_map_install_match (&route_match_tag_cmd);
route_map_install_set (&route_set_metric_cmd);
route_map_install_set (&route_set_ip_nexthop_cmd);
+ route_map_install_set (&route_set_tag_cmd);
install_element (RMAP_NODE, &match_metric_cmd);
install_element (RMAP_NODE, &no_match_metric_cmd);
@@ -888,11 +1122,18 @@ rip_route_map_init ()
install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
+ install_element (RMAP_NODE, &match_tag_cmd);
+ install_element (RMAP_NODE, &no_match_tag_cmd);
+ install_element (RMAP_NODE, &no_match_tag_val_cmd);
install_element (RMAP_NODE, &set_metric_cmd);
+ install_element (RMAP_NODE, &set_metric_addsub_cmd);
install_element (RMAP_NODE, &no_set_metric_cmd);
install_element (RMAP_NODE, &no_set_metric_val_cmd);
install_element (RMAP_NODE, &set_ip_nexthop_cmd);
install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd);
+ install_element (RMAP_NODE, &set_tag_cmd);
+ install_element (RMAP_NODE, &no_set_tag_cmd);
+ install_element (RMAP_NODE, &no_set_tag_val_cmd);
}
diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c
index b6caf3b0..67d7b8bf 100644
--- a/ripd/rip_zebra.c
+++ b/ripd/rip_zebra.c
@@ -502,6 +502,43 @@ DEFUN (no_rip_redistribute_type_metric,
return CMD_WARNING;
}
+DEFUN (rip_redistribute_type_metric_routemap,
+ rip_redistribute_type_metric_routemap_cmd,
+ "redistribute (kernel|connected|static|ospf|bgp) metric <0-16> route-map WORD",
+ "Redistribute information from another routing protocol\n"
+ "Kernel routes\n"
+ "Connected\n"
+ "Static routes\n"
+ "Open Shortest Path First (OSPF)\n"
+ "Border Gateway Protocol (BGP)\n"
+ "Metric\n"
+ "Metric value\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ int i;
+ int metric;
+
+ metric = atoi (argv[1]);
+
+ for (i = 0; redist_type[i].str; i++) {
+ if (strncmp(redist_type[i].str, argv[0],
+ redist_type[i].str_min_len) == 0)
+ {
+ rip_redistribute_metric_set (redist_type[i].type, metric);
+ rip_routemap_set (redist_type[i].type, argv[2]);
+ zclient_redistribute_set (zclient, redist_type[i].type);
+ return CMD_SUCCESS;
+ }
+ }
+
+ vty_out(vty, "Invalid type %s%s", argv[0],
+ VTY_NEWLINE);
+
+ return CMD_WARNING;
+}
+
+
DEFUN (no_rip_redistribute_type_metric_routemap,
no_rip_redistribute_type_metric_routemap_cmd,
"no redistribute (kernel|connected|static|ospf|bgp) metric <0-16> route-map WORD",
@@ -559,7 +596,7 @@ DEFUN (rip_default_information_originate,
rip->default_information = 1;
- rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
+ rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0, NULL);
}
return CMD_SUCCESS;
@@ -581,7 +618,7 @@ DEFUN (no_rip_default_information_originate,
rip->default_information = 0;
- rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
+ rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0);
}
return CMD_SUCCESS;
@@ -682,6 +719,7 @@ rip_zclient_init ()
install_element (RIP_NODE, &rip_redistribute_type_cmd);
install_element (RIP_NODE, &rip_redistribute_type_routemap_cmd);
install_element (RIP_NODE, &rip_redistribute_type_metric_cmd);
+ install_element (RIP_NODE, &rip_redistribute_type_metric_routemap_cmd);
install_element (RIP_NODE, &no_rip_redistribute_type_cmd);
install_element (RIP_NODE, &no_rip_redistribute_type_routemap_cmd);
install_element (RIP_NODE, &no_rip_redistribute_type_metric_cmd);
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 42974a72..a58406b4 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -32,6 +32,7 @@
#include "filter.h"
#include "sockunion.h"
#include "routemap.h"
+#include "if_rmap.h"
#include "plist.h"
#include "distribute.h"
#include "md5-gnu.h"
@@ -407,6 +408,40 @@ rip_rte_process (struct rte *rte, struct sockaddr_in *from,
if (ret < 0)
return;
+ /* Modify entry according to the interface routemap. */
+ if (ri->routemap[RIP_FILTER_IN])
+ {
+ int ret;
+ struct rip_info newinfo;
+
+ memset (&newinfo, 0, sizeof (newinfo));
+ newinfo.type = ZEBRA_ROUTE_RIP;
+ newinfo.sub_type = RIP_ROUTE_RTE;
+ newinfo.nexthop= rte->nexthop;
+ newinfo.from = from->sin_addr;
+ newinfo.ifindex= ifp->ifindex;
+ newinfo.metric = rte->metric;
+ newinfo.metric_out = rte->metric; /* XXX */
+ newinfo.tag = ntohs(rte->tag); /* XXX */
+
+ /* The object should be of the type of rip_info */
+ ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
+ (struct prefix *)&p, RMAP_RIP, &newinfo);
+
+ if (ret == RMAP_DENYMATCH)
+ {
+ if (IS_RIP_DEBUG_PACKET)
+ zlog_info ("RIP %s/%d is filtered by route-map in",
+ inet_ntoa (p.prefix), p.prefixlen);
+ return;
+ }
+
+ /* Get back the object */
+ rte->nexthop = newinfo.nexthop_out;
+ rte->tag = htons(newinfo.tag_out); /* XXX */
+ rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
+ }
+
/* Once the entry has been validated, update the metric by
adding the cost of the network on wich the message
arrived. If the result is greater than infinity, use infinity
@@ -428,11 +463,11 @@ rip_rte_process (struct rte *rte, struct sockaddr_in *from,
else
nexthop = &rte->nexthop;
- /* Check nexthop address. */
+ /* Check if nexthop address is myself, then do nothing. */
if (rip_nexthop_check (nexthop) < 0)
{
if (IS_RIP_DEBUG_PACKET)
- zlog_info ("Nexthop address %s is invalid", inet_ntoa (*nexthop));
+ zlog_info ("Nexthop address %s is myself", inet_ntoa (*nexthop));
return;
}
@@ -451,7 +486,8 @@ rip_rte_process (struct rte *rte, struct sockaddr_in *from,
/* Local static route. */
if (rinfo->type == ZEBRA_ROUTE_RIP
- && rinfo->sub_type == RIP_ROUTE_STATIC
+ && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
+ (rinfo->sub_type == RIP_ROUTE_DEFAULT))
&& rinfo->metric != RIP_METRIC_INFINITY)
return;
}
@@ -517,7 +553,8 @@ rip_rte_process (struct rte *rte, struct sockaddr_in *from,
to the address of the router from which the datagram came.
If this datagram is from the same router as the existing
route, reinitialize the timeout. */
- same = IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr);
+ same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
+ && (rinfo->ifindex == ifp->ifindex));
if (same)
rip_timeout_update (rinfo);
@@ -525,9 +562,10 @@ rip_rte_process (struct rte *rte, struct sockaddr_in *from,
/* Next, compare the metrics. If the datagram is from the same
router as the existing route, and the new metric is different
than the old one; or, if the new metric is lower than the old
- one; do the following actions: */
+ one, or if the tag has been changed; do the following actions: */
if ((same && rinfo->metric != rte->metric) ||
- rte->metric < rinfo->metric)
+ (rte->metric < rinfo->metric) ||
+ (same && (rinfo->metric == rte->metric) && ntohs(rte->tag) != rinfo->tag))
{
/* - Adopt the route from the datagram. That is, put the
new metric in, and adjust the next hop address (if
@@ -1278,9 +1316,11 @@ rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
/* Manually configured RIP route check. */
if (rinfo->type == ZEBRA_ROUTE_RIP
- && rinfo->sub_type == RIP_ROUTE_STATIC)
+ && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
+ (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
{
- if (type != ZEBRA_ROUTE_RIP || sub_type != RIP_ROUTE_STATIC)
+ if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
+ (sub_type != RIP_ROUTE_DEFAULT)))
{
route_unlock_node (rp);
return;
@@ -1315,6 +1355,18 @@ rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
rinfo->flags |= RIP_RTF_CHANGED;
+ if (IS_RIP_DEBUG_EVENT) {
+ if (!nexthop)
+ zlog_info ("Redistribute new prefix %s/%d on the interface %s",
+ inet_ntoa(p->prefix), p->prefixlen,
+ ifindex2ifname(ifindex));
+ else
+ zlog_info ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
+ inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
+ ifindex2ifname(ifindex));
+ }
+
+
rip_event (RIP_TRIGGERED_UPDATE, 0);
}
@@ -1348,6 +1400,11 @@ rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,
RIP_TIMER_OFF (rinfo->t_timeout);
rinfo->flags |= RIP_RTF_CHANGED;
+ if (IS_RIP_DEBUG_EVENT)
+ zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
+ inet_ntoa(p->prefix), p->prefixlen,
+ ifindex2ifname(ifindex));
+
rip_event (RIP_TRIGGERED_UPDATE, 0);
}
}
@@ -1365,7 +1422,14 @@ rip_request_process (struct rip_packet *packet, int size,
struct rip_info *rinfo;
struct rip_interface *ri;
+ /* Does not reponse to the requests on the loopback interfaces */
+ if (if_is_loopback (ifp))
+ return;
+
+ /* Check RIPng process is enabled on this interface. */
ri = ifp->info;
+ if (! ri->running)
+ return;
/* When passive interface is specified, suppress responses */
if (ri->passive)
@@ -1914,7 +1978,7 @@ rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
masklen2ip (p->prefixlen, &mask);
stream_putw (s, AF_INET);
- stream_putw (s, rinfo->tag);
+ stream_putw (s, rinfo->tag_out);
stream_put_ipv4 (s, p->prefix.s_addr);
stream_put_ipv4 (s, mask.s_addr);
stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
@@ -2061,7 +2125,7 @@ rip_output_process (struct interface *ifp, struct prefix *ifaddr,
/* Split horizon. */
/* if (split_horizon == rip_split_horizon) */
- if (ri->split_horizon)
+ if (ri->split_horizon == RIP_SPLIT_HORIZON)
{
/* We perform split horizon for RIP and connected route. */
if ((rinfo->type == ZEBRA_ROUTE_RIP ||
@@ -2074,23 +2138,36 @@ rip_output_process (struct interface *ifp, struct prefix *ifaddr,
rinfo->metric_set = 0;
rinfo->nexthop_out.s_addr = 0;
rinfo->metric_out = rinfo->metric;
+ rinfo->tag_out = rinfo->tag;
rinfo->ifindex_out = ifp->ifindex;
- /* In order to avoid some local loops, if the RIP route has a
- nexthop via this interface, keep the nexthop, otherwise set
- it to 0. The nexthop should not be propagated beyond the
- local broadcast/multicast area in order to avoid an IGP
- multi-level recursive look-up. For RIP and connected
- route, we don't set next hop value automatically. For
- settting next hop to those routes, please use
- route-map. */
-
- if (rinfo->type != ZEBRA_ROUTE_RIP
- && rinfo->type != ZEBRA_ROUTE_CONNECT
- && rinfo->ifindex == ifp->ifindex)
+ /* In order to avoid some local loops,
+ * if the RIP route has a nexthop via this interface, keep the nexthop,
+ * otherwise set it to 0. The nexthop should not be propagated
+ * beyond the local broadcast/multicast area in order
+ * to avoid an IGP multi-level recursive look-up.
+ * see (4.4)
+ */
+ if (rinfo->ifindex == ifp->ifindex)
rinfo->nexthop_out = rinfo->nexthop;
+
+ /* Interface route-map */
+ if (ri->routemap[RIP_FILTER_OUT])
+ {
+ ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
+ (struct prefix *) p, RMAP_RIP,
+ rinfo);
+
+ if (ret == RMAP_DENYMATCH)
+ {
+ if (IS_RIP_DEBUG_PACKET)
+ zlog_info ("RIP %s/%d is filtered by route-map out",
+ inet_ntoa (p->prefix), p->prefixlen);
+ continue;
+ }
+ }
- /* Apply route map - continue, if deny */
+ /* Apply redistribute route map - continue, if deny */
if (rip->route_map[rinfo->type].name
&& rinfo->sub_type != RIP_ROUTE_INTERFACE)
{
@@ -2132,7 +2209,17 @@ rip_output_process (struct interface *ifp, struct prefix *ifaddr,
if (rinfo->metric_out > RIP_METRIC_INFINITY)
rinfo->metric_out = RIP_METRIC_INFINITY;
-
+
+ /* Perform split-horizon with poisoned reverse
+ * for RIP and connected routes.
+ **/
+ if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
+ if ((rinfo->type == ZEBRA_ROUTE_RIP ||
+ rinfo->type == ZEBRA_ROUTE_CONNECT) &&
+ rinfo->ifindex == ifp->ifindex)
+ rinfo->metric_out = RIP_METRIC_INFINITY;
+ }
+
/* Write RTE to the stream. */
num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifp);
if (num == rtemax)
@@ -2426,6 +2513,14 @@ rip_redistribute_withdraw (int type)
RIP_TIMER_OFF (rinfo->t_timeout);
rinfo->flags |= RIP_RTF_CHANGED;
+ if (IS_RIP_DEBUG_EVENT) {
+ struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
+
+ zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
+ inet_ntoa(p->prefix), p->prefixlen,
+ ifindex2ifname(rinfo->ifindex));
+ }
+
rip_event (RIP_TRIGGERED_UPDATE, 0);
}
}
@@ -2782,6 +2877,17 @@ DEFUN (no_rip_timers,
return CMD_SUCCESS;
}
+
+ALIAS (no_rip_timers,
+ no_rip_timers_val_cmd,
+ "no timers basic <0-65535> <0-65535> <0-65535>",
+ NO_STR
+ "Adjust routing timers\n"
+ "Basic routing protocol update timers\n"
+ "Routing table update timer value in second. Default is 30.\n"
+ "Routing information timeout timer. Default is 180.\n"
+ "Garbage collection timer. Default is 120.\n")
+
struct route_table *rip_distance_table;
@@ -3116,11 +3222,12 @@ DEFUN (show_ip_rip,
if (! rip)
return CMD_SUCCESS;
- vty_out (vty, "Codes: R - RIP, C - connected, O - OSPF, B - BGP%s"
- " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
+ vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
+ "Sub-codes:%s"
+ " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
" (i) - interface%s%s"
- " Network Next Hop Metric From Time%s",
- VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+ " Network Next Hop Metric From Tag Time%s",
+ VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
for (np = route_top (rip->table); np; np = route_next (np))
if ((rinfo = np->info) != NULL)
@@ -3133,7 +3240,7 @@ DEFUN (show_ip_rip,
rip_route_type_print (rinfo->sub_type),
inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
- len = 24 - len;
+ len = 21 - len;
if (len > 0)
vty_out (vty, "%*s", len, " ");
@@ -3149,15 +3256,20 @@ DEFUN (show_ip_rip,
(rinfo->sub_type == RIP_ROUTE_RTE))
{
vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
+ vty_out (vty, "%3d ", rinfo->tag);
rip_vty_out_uptime (vty, rinfo);
}
else if (rinfo->metric == RIP_METRIC_INFINITY)
{
vty_out (vty, "self ");
+ vty_out (vty, "%3d ", rinfo->tag);
rip_vty_out_uptime (vty, rinfo);
}
else
- vty_out (vty, "self");
+ {
+ vty_out (vty, "self ");
+ vty_out (vty, "%3d", rinfo->tag);
+ }
vty_out (vty, "%s", VTY_NEWLINE);
}
@@ -3175,11 +3287,13 @@ rip_next_thread_timer (struct thread *thread)
return thread->u.sands.tv_sec - timer_now.tv_sec;
}
-DEFUN (show_ip_protocols_rip,
- show_ip_protocols_rip_cmd,
- "show ip protocols",
+/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
+DEFUN (show_ip_rip_status,
+ show_ip_rip_status_cmd,
+ "show ip rip status",
SHOW_STR
IP_STR
+ "Show RIP routes\n"
"IP routing protocol process parameters and statistics\n")
{
listnode node;
@@ -3314,6 +3428,9 @@ config_write_rip (struct vty *vty)
/* Distribute configuration. */
write += config_write_distribute (vty);
+ /* Interface routemap configuration */
+ write += config_write_if_rmap (vty);
+
/* Distance configuration. */
if (rip->distance)
vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
@@ -3545,6 +3662,83 @@ rip_reset ()
rip_zclient_reset ();
}
+void
+rip_if_rmap_update (struct if_rmap *if_rmap)
+{
+ struct interface *ifp;
+ struct rip_interface *ri;
+ struct route_map *rmap;
+
+ ifp = if_lookup_by_name (if_rmap->ifname);
+ if (ifp == NULL)
+ return;
+
+ ri = ifp->info;
+
+ if (if_rmap->routemap[IF_RMAP_IN])
+ {
+ rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
+ if (rmap)
+ ri->routemap[IF_RMAP_IN] = rmap;
+ else
+ ri->routemap[IF_RMAP_IN] = NULL;
+ }
+ else
+ ri->routemap[RIP_FILTER_IN] = NULL;
+
+ if (if_rmap->routemap[IF_RMAP_OUT])
+ {
+ rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
+ if (rmap)
+ ri->routemap[IF_RMAP_OUT] = rmap;
+ else
+ ri->routemap[IF_RMAP_OUT] = NULL;
+ }
+ else
+ ri->routemap[RIP_FILTER_OUT] = NULL;
+}
+
+void
+rip_if_rmap_update_interface (struct interface *ifp)
+{
+ struct if_rmap *if_rmap;
+
+ if_rmap = if_rmap_lookup (ifp->name);
+ if (if_rmap)
+ rip_if_rmap_update (if_rmap);
+}
+
+void
+rip_routemap_update_redistribute (void)
+{
+ int i;
+
+ if (rip)
+ {
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ {
+ if (rip->route_map[i].name)
+ rip->route_map[i].map =
+ route_map_lookup_by_name (rip->route_map[i].name);
+ }
+ }
+}
+
+void
+rip_routemap_update ()
+{
+ struct interface *ifp;
+ listnode node;
+
+ for (node = listhead (iflist); node; nextnode (node))
+ {
+ ifp = getdata (node);
+ rip_if_rmap_update_interface (ifp);
+ }
+
+ rip_routemap_update_redistribute ();
+}
+
/* Allocate new rip structure and set default value. */
void
rip_init ()
@@ -3557,9 +3751,9 @@ rip_init ()
/* Install rip commands. */
install_element (VIEW_NODE, &show_ip_rip_cmd);
- install_element (VIEW_NODE, &show_ip_protocols_rip_cmd);
+ install_element (VIEW_NODE, &show_ip_rip_status_cmd);
install_element (ENABLE_NODE, &show_ip_rip_cmd);
- install_element (ENABLE_NODE, &show_ip_protocols_rip_cmd);
+ install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
install_element (CONFIG_NODE, &router_rip_cmd);
install_element (CONFIG_NODE, &no_router_rip_cmd);
@@ -3572,6 +3766,7 @@ rip_init ()
install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
install_element (RIP_NODE, &rip_timers_cmd);
install_element (RIP_NODE, &no_rip_timers_cmd);
+ install_element (RIP_NODE, &no_rip_timers_val_cmd);
install_element (RIP_NODE, &rip_route_cmd);
install_element (RIP_NODE, &no_rip_route_cmd);
install_element (RIP_NODE, &rip_distance_cmd);
@@ -3584,10 +3779,6 @@ rip_init ()
/* Debug related init. */
rip_debug_init ();
- /* Filter related init. */
- rip_route_map_init ();
- rip_offset_init ();
-
/* SNMP init. */
#ifdef HAVE_SNMP
rip_snmp_init ();
@@ -3608,6 +3799,17 @@ rip_init ()
distribute_list_add_hook (rip_distribute_update);
distribute_list_delete_hook (rip_distribute_update);
+ /* Route-map */
+ rip_route_map_init ();
+ rip_offset_init ();
+
+ route_map_add_hook (rip_routemap_update);
+ route_map_delete_hook (rip_routemap_update);
+
+ if_rmap_init (RIP_NODE);
+ if_rmap_hook_add (rip_if_rmap_update);
+ if_rmap_hook_delete (rip_if_rmap_update);
+
/* Distance control. */
rip_distance_table = route_table_init ();
}
diff --git a/ripd/ripd.h b/ripd/ripd.h
index 2545db04..260ea469 100644
--- a/ripd/ripd.h
+++ b/ripd/ripd.h
@@ -64,7 +64,6 @@
/* RIP port number. */
#define RIP_PORT_DEFAULT 520
#define RIP_VTY_PORT 2602
-#define RIP_VTYSH_PATH "/tmp/.ripd"
/* Default configuration file name. */
#define RIPD_DEFAULT_CONFIG "ripd.conf"
@@ -200,6 +199,7 @@ struct rip_info
struct in_addr nexthop_out;
u_char metric_set;
u_int32_t metric_out;
+ u_short tag_out;
unsigned int ifindex_out;
struct route_node *rp;
@@ -212,6 +212,12 @@ struct rip_info
#endif /* NEW_RIP_TABLE */
};
+typedef enum {
+ RIP_NO_SPLIT_HORIZON = 0,
+ RIP_SPLIT_HORIZON,
+ RIP_SPLIT_HORIZON_POISONED_REVERSE
+} split_horizon_policy_t;
+
/* RIP specific interface configuration. */
struct rip_interface
{
@@ -240,8 +246,8 @@ struct rip_interface
char *key_chain;
/* Split horizon flag. */
- int split_horizon;
- int split_horizon_default;
+ split_horizon_policy_t split_horizon;
+ split_horizon_policy_t split_horizon_default;
/* For filter type slot. */
#define RIP_FILTER_IN 0
@@ -254,6 +260,9 @@ struct rip_interface
/* Prefix-list. */
struct prefix_list *prefix[RIP_FILTER_MAX];
+ /* Route-map. */
+ struct route_map *routemap[RIP_FILTER_MAX];
+
/* Wake up thread. */
struct thread *t_wakeup;
@@ -359,8 +368,6 @@ void rip_zclient_init ();
void rip_zclient_start ();
void rip_zclient_reset ();
void rip_offset_init ();
-int if_check_address (struct in_addr addr);
-int if_valid_neighbor (struct in_addr addr);
int rip_request_send (struct sockaddr_in *, struct interface *, u_char);
int rip_neighbor_lookup (struct sockaddr_in *);
@@ -372,6 +379,7 @@ void rip_zebra_ipv4_add (struct prefix_ipv4 *, struct in_addr *, u_int32_t, u_ch
void rip_zebra_ipv4_delete (struct prefix_ipv4 *, struct in_addr *, u_int32_t);
void rip_interface_multicast_set (int, struct interface *);
void rip_distribute_update_interface (struct interface *);
+void rip_if_rmap_update_interface (struct interface *);
int config_write_rip_network (struct vty *, int);
int config_write_rip_offset_list (struct vty *);
diff --git a/ripngd/ChangeLog b/ripngd/ChangeLog
index 07e3d761..fa135103 100644
--- a/ripngd/ChangeLog
+++ b/ripngd/ChangeLog
@@ -1,3 +1,18 @@
+2003-05-25 Hasso Tepper <hasso@estpak.ee>
+
+ * Revert ripng_ifrmap stuff because ripd uses it now as well.
+ * Merge ripngd part of 6Wind patch from Vincent Jardin
+ <vjardin@wanadoo.fr>.
+
+2003-04-23 Hasso Tepper <hasso@estpak.ee>
+
+ * {ripng_ifrmap,ripngd}.c: fix "router xxx" node commands in vtysh
+
+2003-04-19 Hasso Tepper <hasso@estpak.ee>
+
+ * rip_routemap.c: sync daemon's route-map commands to have same
+ syntax
+
2002-07-07 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* zebra-0.93 released.
diff --git a/ripngd/Makefile.am b/ripngd/Makefile.am
index fffc1e8a..7d7f1049 100644
--- a/ripngd/Makefile.am
+++ b/ripngd/Makefile.am
@@ -9,7 +9,7 @@ sbin_PROGRAMS = ripngd
libripng_a_SOURCES = \
ripng_interface.c ripngd.c ripng_zebra.c ripng_route.c ripng_debug.c \
- ripng_routemap.c
+ ripng_routemap.c ripng_offset.c ripng_peer.c ripng_nexthop.c
noinst_HEADERS = \
ripng_debug.h ripng_route.h ripngd.h
@@ -17,7 +17,7 @@ noinst_HEADERS = \
ripngd_SOURCES = \
ripng_main.c $(libripng_a_SOURCES)
-ripngd_LDADD = ../lib/libzebra.a @LIBCAP@
+ripngd_LDADD = -L../lib -lzebra @LIBCAP@
sysconf_DATA = ripngd.conf.sample
diff --git a/ripngd/ripng_debug.c b/ripngd/ripng_debug.c
index 51314bc2..2cff3d01 100644
--- a/ripngd/ripng_debug.c
+++ b/ripngd/ripng_debug.c
@@ -207,7 +207,8 @@ DEFUN (no_debug_ripng_zebra,
struct cmd_node debug_node =
{
DEBUG_NODE,
- "" /* Debug node has no interface. */
+ "", /* Debug node has no interface. */
+ 1 /* VTYSH */
};
int
diff --git a/ripngd/ripng_debug.h b/ripngd/ripng_debug.h
index 6713a151..617a07de 100644
--- a/ripngd/ripng_debug.h
+++ b/ripngd/ripng_debug.h
@@ -48,5 +48,6 @@ extern unsigned long ripng_debug_packet;
extern unsigned long ripng_debug_zebra;
void ripng_debug_init ();
+void ripng_debug_reset ();
#endif /* _ZEBRA_RIPNG_DEBUG_H */
diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c
index c177381a..b4299eb0 100644
--- a/ripngd/ripng_interface.c
+++ b/ripngd/ripng_interface.c
@@ -49,6 +49,9 @@
/* Static utility function. */
static void ripng_enable_apply (struct interface *);
static void ripng_passive_interface_apply (struct interface *);
+int ripng_enable_if_lookup (char *ifname);
+int ripng_enable_network_lookup2 (struct connected *connected);
+void ripng_enable_apply_all ();
/* Join to the all rip routers multicast group. */
int
@@ -57,19 +60,23 @@ ripng_multicast_join (struct interface *ifp)
int ret;
struct ipv6_mreq mreq;
- memset (&mreq, 0, sizeof (mreq));
- inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
- mreq.ipv6mr_interface = ifp->ifindex;
+ if (if_is_up (ifp) && if_is_multicast (ifp)) {
+ memset (&mreq, 0, sizeof (mreq));
+ inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
+ mreq.ipv6mr_interface = ifp->ifindex;
- ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
- (char *) &mreq, sizeof (mreq));
- if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", strerror (errno));
+ ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ (char *) &mreq, sizeof (mreq));
+ if (ret < 0)
+ zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", strerror (errno));
- if (IS_RIPNG_DEBUG_EVENT)
- zlog_info ("RIPng %s join to all-rip-routers multicast group", ifp->name);
+ if (IS_RIPNG_DEBUG_EVENT)
+ zlog_info ("RIPng %s join to all-rip-routers multicast group", ifp->name);
- return ret;
+ if (ret < 0)
+ return -1;
+ }
+ return 0;
}
/* Leave from the all rip routers multicast group. */
@@ -79,20 +86,46 @@ ripng_multicast_leave (struct interface *ifp)
int ret;
struct ipv6_mreq mreq;
- memset (&mreq, 0, sizeof (mreq));
- inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
- mreq.ipv6mr_interface = ifp->ifindex;
+ if (if_is_up (ifp) && if_is_multicast (ifp)) {
+ memset (&mreq, 0, sizeof (mreq));
+ inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
+ mreq.ipv6mr_interface = ifp->ifindex;
- ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
- (char *) &mreq, sizeof (mreq));
- if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s\n", strerror (errno));
+ ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
+ (char *) &mreq, sizeof (mreq));
+ if (ret < 0)
+ zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s\n", strerror (errno));
+
+ if (IS_RIPNG_DEBUG_EVENT)
+ zlog_info ("RIPng %s leave from all-rip-routers multicast group",
+ ifp->name);
+
+ if (ret < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* How many link local IPv6 address could be used on the interface ? */
+int
+ripng_if_ipv6_lladdress_check (struct interface *ifp)
+{
+ struct listnode *nn;
+ struct connected *connected;
+ int count = 0;
+
+ for (nn = listhead (ifp->connected); nn; nextnode (nn))
+ if ((connected = getdata (nn)) != NULL) {
+ struct prefix *p;
+ p = connected->address;
- if (IS_RIPNG_DEBUG_EVENT)
- zlog_info ("RIPng %s leave from all-rip-routers multicast group",
- ifp->name);
+ if ((p->family == AF_INET6) &&
+ IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6))
+ count++;
+ }
- return ret;
+ return count;
}
/* Check max mtu size. */
@@ -120,7 +153,7 @@ ripng_if_down (struct interface *ifp)
struct ripng_info *rinfo;
struct ripng_interface *ri;
- if (ripng->table)
+ if (ripng)
{
for (rp = route_top (ripng->table); rp; rp = route_next (rp))
if ((rinfo = rp->info) != NULL)
@@ -134,18 +167,17 @@ ripng_if_down (struct interface *ifp)
&rinfo->nexthop,
rinfo->ifindex);
- RIPNG_TIMER_OFF (rinfo->t_timeout);
- RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
-
- rp->info = NULL;
- route_unlock_node (rp);
-
- ripng_info_free (rinfo);
+ ripng_redistribute_delete (rinfo->type, rinfo->sub_type,
+ (struct prefix_ipv6 *)&rp->p,
+ rinfo->ifindex);
}
else
{
- /* All redistributed routes got through this interface. */
- if (rinfo->ifindex == ifp->ifindex)
+ /* All redistributed routes got through this interface,
+ * but the static and system ones are kept. */
+ if ((rinfo->ifindex == ifp->ifindex) &&
+ (rinfo->type != ZEBRA_ROUTE_STATIC) &&
+ (rinfo->type != ZEBRA_ROUTE_SYSTEM))
ripng_redistribute_delete (rinfo->type, rinfo->sub_type,
(struct prefix_ipv6 *) &rp->p,
rinfo->ifindex);
@@ -155,7 +187,7 @@ ripng_if_down (struct interface *ifp)
ri = ifp->info;
- if (ripng && ri->running)
+ if (ri->running)
{
if (IS_RIPNG_DEBUG_EVENT)
zlog_info ("turn off %s", ifp->name);
@@ -251,16 +283,121 @@ int
ripng_interface_delete (int command, struct zclient *zclient,
zebra_size_t length)
{
+ struct interface *ifp;
+ struct stream *s;
+
+ s = zclient->ibuf;
+ /* zebra_interface_state_read() updates interface structure in iflist */
+ ifp = zebra_interface_state_read(s);
+
+ if (ifp == NULL)
+ return 0;
+
+ if (if_is_up (ifp)) {
+ ripng_if_down(ifp);
+ }
+
+ zlog_info("interface delete %s index %d flags %ld metric %d mtu %d",
+ ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+
+ /* To support pseudo interface do not free interface structure. */
+ /* if_delete(ifp); */
+
return 0;
}
+void
+ripng_interface_clean ()
+{
+ listnode node;
+ struct interface *ifp;
+ struct ripng_interface *ri;
+
+ for (node = listhead (iflist); node; nextnode (node))
+ {
+ ifp = getdata (node);
+ ri = ifp->info;
+
+ ri->enable_network = 0;
+ ri->enable_interface = 0;
+ ri->running = 0;
+
+ if (ri->t_wakeup)
+ {
+ thread_cancel (ri->t_wakeup);
+ ri->t_wakeup = NULL;
+ }
+ }
+}
+
+void
+ripng_interface_reset () {
+ listnode node;
+ struct interface *ifp;
+ struct ripng_interface *ri;
+
+ for (node = listhead (iflist); node; nextnode (node))
+ {
+ ifp = getdata (node);
+ ri = ifp->info;
+
+ ri->enable_network = 0;
+ ri->enable_interface = 0;
+ ri->running = 0;
+
+ ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
+ ri->split_horizon_default = RIPNG_NO_SPLIT_HORIZON;
+
+ ri->list[RIPNG_FILTER_IN] = NULL;
+ ri->list[RIPNG_FILTER_OUT] = NULL;
+
+ ri->prefix[RIPNG_FILTER_IN] = NULL;
+ ri->prefix[RIPNG_FILTER_OUT] = NULL;
+
+ if (ri->t_wakeup)
+ {
+ thread_cancel (ri->t_wakeup);
+ ri->t_wakeup = NULL;
+ }
+
+ ri->passive = 0;
+ }
+}
+
+static void
+ripng_apply_address_add (struct connected *ifc) {
+ struct prefix_ipv6 address;
+ struct prefix *p;
+
+ if (!ripng)
+ return;
+
+ if (! if_is_up(ifc->ifp))
+ return;
+
+ p = ifc->address;
+
+ memset (&address, 0, sizeof (address));
+ address.family = p->family;
+ address.prefix = p->u.prefix6;
+ address.prefixlen = p->prefixlen;
+ apply_mask_ipv6(&address);
+
+ /* Check if this interface is RIP enabled or not
+ or Check if this address's prefix is RIP enabled */
+ if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0) ||
+ (ripng_enable_network_lookup2(ifc) >= 0))
+ ripng_redistribute_add(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
+ &address, ifc->ifp->ifindex, NULL);
+
+}
+
int
ripng_interface_address_add (int command, struct zclient *zclient,
zebra_size_t length)
{
struct connected *c;
struct prefix *p;
- char buf[INET6_ADDRSTRLEN];
c = zebra_interface_address_add_read (zclient->ibuf);
@@ -273,16 +410,56 @@ ripng_interface_address_add (int command, struct zclient *zclient,
{
if (IS_RIPNG_DEBUG_ZEBRA)
zlog_info ("RIPng connected address %s/%d add",
- inet_ntop (AF_INET6, &p->u.prefix6, buf, INET6_ADDRSTRLEN),
+ inet6_ntop(&p->u.prefix6),
p->prefixlen);
- /* Check is this interface is RIP enabled or not.*/
- ripng_enable_apply (c->ifp);
+ /* Check is this prefix needs to be redistributed. */
+ ripng_apply_address_add(c);
+
+ /* Let's try once again whether the interface could be activated */
+ if (c->ifp) {
+ struct ripng_interface *ri = c->ifp->info;
+
+ if (!ri->running) {
+ /* Check if this interface is RIP enabled or not.*/
+ ripng_enable_apply (c->ifp);
+
+ /* Apply distribute list to the interface. */
+ ripng_distribute_update_interface (c->ifp);
+
+ /* Check interface routemap. */
+ ripng_if_rmap_update_interface (c->ifp);
+ }
+ }
+
}
return 0;
}
+static void
+ripng_apply_address_del (struct connected *ifc) {
+ struct prefix_ipv6 address;
+ struct prefix *p;
+
+ if (!ripng)
+ return;
+
+ if (! if_is_up(ifc->ifp))
+ return;
+
+ p = ifc->address;
+
+ memset (&address, 0, sizeof (address));
+ address.family = p->family;
+ address.prefix = p->u.prefix6;
+ address.prefixlen = p->prefixlen;
+ apply_mask_ipv6(&address);
+
+ ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
+ &address, ifc->ifp->ifindex);
+}
+
int
ripng_interface_address_delete (int command, struct zclient *zclient,
zebra_size_t length)
@@ -305,8 +482,8 @@ ripng_interface_address_delete (int command, struct zclient *zclient,
INET6_ADDRSTRLEN),
p->prefixlen);
- /* Check is this interface is RIP enabled or not.*/
- ripng_enable_apply (ifc->ifp);
+ /* Check wether this prefix needs to be removed. */
+ ripng_apply_address_del(ifc);
}
connected_free (ifc);
}
@@ -321,11 +498,14 @@ vector ripng_enable_if;
struct route_table *ripng_enable_network;
/* Lookup RIPng enable network. */
+/* Check wether the interface has at least a connected prefix that
+ * is within the ripng_enable_network table. */
int
-ripng_enable_network_lookup (struct interface *ifp)
+ripng_enable_network_lookup_if (struct interface *ifp)
{
listnode listnode;
struct connected *connected;
+ struct prefix_ipv6 address;
for (listnode = listhead (ifp->connected); listnode; nextnode (listnode))
if ((connected = getdata (listnode)) != NULL)
@@ -337,7 +517,12 @@ ripng_enable_network_lookup (struct interface *ifp)
if (p->family == AF_INET6)
{
- node = route_node_match (ripng_enable_network, p);
+ address.family = AF_INET6;
+ address.prefix = p->u.prefix6;
+ address.prefixlen = IPV6_MAX_BITLEN;
+
+ node = route_node_match (ripng_enable_network,
+ (struct prefix *)&address);
if (node)
{
route_unlock_node (node);
@@ -348,6 +533,35 @@ ripng_enable_network_lookup (struct interface *ifp)
return -1;
}
+/* Check wether connected is within the ripng_enable_network table. */
+int
+ripng_enable_network_lookup2 (struct connected *connected)
+{
+ struct prefix_ipv6 address;
+ struct prefix *p;
+
+ p = connected->address;
+
+ if (p->family == AF_INET6) {
+ struct route_node *node;
+
+ address.family = p->family;
+ address.prefix = p->u.prefix6;
+ address.prefixlen = IPV6_MAX_BITLEN;
+
+ /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within ripng_enable_network */
+ node = route_node_match (ripng_enable_network,
+ (struct prefix *)&address);
+
+ if (node) {
+ route_unlock_node (node);
+ return 1;
+ }
+ }
+
+ return -1;
+}
+
/* Add RIPng enable network. */
int
ripng_enable_network_add (struct prefix *p)
@@ -364,6 +578,9 @@ ripng_enable_network_add (struct prefix *p)
else
node->info = "enabled";
+ /* XXX: One should find a better solution than a generic one */
+ ripng_enable_apply_all();
+
return 1;
}
@@ -415,6 +632,8 @@ ripng_enable_if_add (char *ifname)
vector_set (ripng_enable_if, strdup (ifname));
+ ripng_enable_apply_all();
+
return 1;
}
@@ -433,6 +652,8 @@ ripng_enable_if_delete (char *ifname)
free (str);
vector_unset (ripng_enable_if, index);
+ ripng_enable_apply_all();
+
return 1;
}
@@ -450,7 +671,13 @@ ripng_interface_wakeup (struct thread *t)
ri->t_wakeup = NULL;
/* Join to multicast group. */
- ripng_multicast_join (ifp);
+ if (ripng_multicast_join (ifp) < 0) {
+ zlog_err ("multicast join failed, interface %s not running", ifp->name);
+ return 0;
+ }
+
+ /* Set running flag. */
+ ri->running = 1;
/* Send RIP request to the interface. */
ripng_request (ifp);
@@ -458,6 +685,44 @@ ripng_interface_wakeup (struct thread *t)
return 0;
}
+int ripng_redistribute_check (int);
+
+void
+ripng_connect_set (struct interface *ifp, int set)
+{
+ struct listnode *nn;
+ struct connected *connected;
+ struct prefix_ipv6 address;
+
+ for (nn = listhead (ifp->connected); nn; nextnode (nn))
+ if ((connected = getdata (nn)) != NULL) {
+ struct prefix *p;
+ p = connected->address;
+
+ if (p->family != AF_INET6)
+ continue;
+
+ address.family = AF_INET6;
+ address.prefix = p->u.prefix6;
+ address.prefixlen = p->prefixlen;
+ apply_mask_ipv6 (&address);
+
+ if (set) {
+ /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
+ if ((ripng_enable_if_lookup(connected->ifp->name) >= 0) ||
+ (ripng_enable_network_lookup2(connected) >= 0))
+ ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
+ &address, connected->ifp->ifindex, NULL);
+ } else {
+ ripng_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
+ &address, connected->ifp->ifindex);
+ if (ripng_redistribute_check (ZEBRA_ROUTE_CONNECT))
+ ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_REDISTRIBUTE,
+ &address, connected->ifp->ifindex, NULL);
+ }
+ }
+}
+
/* Check RIPng is enabed on this interface. */
void
ripng_enable_apply (struct interface *ifp)
@@ -466,16 +731,13 @@ ripng_enable_apply (struct interface *ifp)
struct ripng_interface *ri = NULL;
/* Check interface. */
- if (if_is_loopback (ifp))
- return;
-
if (! if_is_up (ifp))
return;
ri = ifp->info;
- /* Check network configuration. */
- ret = ripng_enable_network_lookup (ifp);
+ /* Is this interface a candidate for RIPng ? */
+ ret = ripng_enable_network_lookup_if (ifp);
/* If the interface is matched. */
if (ret > 0)
@@ -490,10 +752,18 @@ ripng_enable_apply (struct interface *ifp)
else
ri->enable_interface = 0;
+ /* any candidate interface MUST have a link-local IPv6 address */
+ if ((! ripng_if_ipv6_lladdress_check (ifp)) &&
+ (ri->enable_network || ri->enable_interface)) {
+ ri->enable_network = 0;
+ ri->enable_interface = 0;
+ zlog_warn("Interface %s does not have any link-local address",
+ ifp->name);
+ }
+
/* Update running status of the interface. */
if (ri->enable_network || ri->enable_interface)
{
- if (! ri->running)
{
if (IS_RIPNG_DEBUG_EVENT)
zlog_info ("RIPng turn on %s", ifp->name);
@@ -502,34 +772,26 @@ ripng_enable_apply (struct interface *ifp)
if (! ri->t_wakeup)
ri->t_wakeup = thread_add_timer (master, ripng_interface_wakeup,
ifp, 1);
-#if 0
- /* Join to multicast group. */
- ripng_multicast_join (ifp);
- /* Send RIP request to the interface. */
- ripng_request (ifp);
-#endif /* 0 */
-
- ri->running = 1;
+ ripng_connect_set (ifp, 1);
}
}
else
{
if (ri->running)
{
- if (IS_RIPNG_DEBUG_EVENT)
- zlog_info ("RIPng turn off %s", ifp->name);
-
- /* Leave from multicast group. */
- ripng_multicast_leave (ifp);
+ /* Might as well clean up the route table as well
+ * ripng_if_down sets to 0 ri->running, and displays "turn off %s"
+ **/
+ ripng_if_down(ifp);
- ri->running = 0;
+ ripng_connect_set (ifp, 0);
}
}
}
/* Set distribute list to all interfaces. */
-static void
+void
ripng_enable_apply_all ()
{
struct interface *ifp;
@@ -542,6 +804,29 @@ ripng_enable_apply_all ()
}
}
+/* Clear all network and neighbor configuration */
+void
+ripng_clean_network ()
+{
+ int i;
+ char *str;
+ struct route_node *rn;
+
+ /* ripng_enable_network */
+ for (rn = route_top (ripng_enable_network); rn; rn = route_next (rn))
+ if (rn->info) {
+ rn->info = NULL;
+ route_unlock_node(rn);
+ }
+
+ /* ripng_enable_if */
+ for (i = 0; i < vector_max (ripng_enable_if); i++)
+ if ((str = vector_slot (ripng_enable_if, i)) != NULL) {
+ free (str);
+ vector_slot (ripng_enable_if, i) = NULL;
+ }
+}
+
/* Vector to store passive-interface name. */
vector Vripng_passive_interface;
@@ -638,10 +923,9 @@ ripng_passive_interface_clean (void)
/* Write RIPng enable network and interface to the vty. */
int
-ripng_network_write (struct vty *vty)
+ripng_network_write (struct vty *vty, int config_mode)
{
int i;
- char *str;
char *ifname;
struct route_node *node;
char buf[BUFSIZ];
@@ -651,7 +935,8 @@ ripng_network_write (struct vty *vty)
if (node->info)
{
struct prefix *p = &node->p;
- vty_out (vty, " network %s/%d%s",
+ vty_out (vty, "%s%s/%d%s",
+ config_mode ? " network " : " ",
inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
p->prefixlen,
VTY_NEWLINE);
@@ -660,14 +945,17 @@ ripng_network_write (struct vty *vty)
/* Write enable interface. */
for (i = 0; i < vector_max (ripng_enable_if); i++)
- if ((str = vector_slot (ripng_enable_if, i)) != NULL)
- vty_out (vty, " network %s%s", str,
+ if ((ifname = vector_slot (ripng_enable_if, i)) != NULL)
+ vty_out (vty, "%s%s%s",
+ config_mode ? " network " : " ",
+ ifname,
VTY_NEWLINE);
/* Write passive interface. */
- for (i = 0; i < vector_max (Vripng_passive_interface); i++)
- if ((ifname = vector_slot (Vripng_passive_interface, i)) != NULL)
- vty_out (vty, " passive-interface %s%s", ifname, VTY_NEWLINE);
+ if (config_mode)
+ for (i = 0; i < vector_max (Vripng_passive_interface); i++)
+ if ((ifname = vector_slot (Vripng_passive_interface, i)) != NULL)
+ vty_out (vty, " passive-interface %s%s", ifname, VTY_NEWLINE);
return 0;
}
@@ -697,8 +985,6 @@ DEFUN (ripng_network,
return CMD_WARNING;
}
- ripng_enable_apply_all ();
-
return CMD_SUCCESS;
}
@@ -728,11 +1014,71 @@ DEFUN (no_ripng_network,
return CMD_WARNING;
}
- ripng_enable_apply_all ();
+ return CMD_SUCCESS;
+}
+
+DEFUN (ipv6_ripng_split_horizon,
+ ipv6_ripng_split_horizon_cmd,
+ "ipv6 ripng split-horizon",
+ IPV6_STR
+ "Routing Information Protocol\n"
+ "Perform split horizon\n")
+{
+ struct interface *ifp;
+ struct ripng_interface *ri;
+
+ ifp = vty->index;
+ ri = ifp->info;
+
+ ri->split_horizon = RIPNG_SPLIT_HORIZON;
+ return CMD_SUCCESS;
+}
+
+DEFUN (ipv6_ripng_split_horizon_poisoned_reverse,
+ ipv6_ripng_split_horizon_poisoned_reverse_cmd,
+ "ipv6 ripng split-horizon poisoned-reverse",
+ IPV6_STR
+ "Routing Information Protocol\n"
+ "Perform split horizon\n"
+ "With poisoned-reverse\n")
+{
+ struct interface *ifp;
+ struct ripng_interface *ri;
+
+ ifp = vty->index;
+ ri = ifp->info;
+
+ ri->split_horizon = RIPNG_SPLIT_HORIZON_POISONED_REVERSE;
+ return CMD_SUCCESS;
+}
+DEFUN (no_ipv6_ripng_split_horizon,
+ no_ipv6_ripng_split_horizon_cmd,
+ "no ipv6 ripng split-horizon",
+ NO_STR
+ IPV6_STR
+ "Routing Information Protocol\n"
+ "Perform split horizon\n")
+{
+ struct interface *ifp;
+ struct ripng_interface *ri;
+
+ ifp = vty->index;
+ ri = ifp->info;
+
+ ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
return CMD_SUCCESS;
}
+ALIAS (no_ipv6_ripng_split_horizon,
+ no_ipv6_ripng_split_horizon_poisoned_reverse_cmd,
+ "no ipv6 ripng split-horizon poisoned-reverse",
+ NO_STR
+ IPV6_STR
+ "Routing Information Protocol\n"
+ "Perform split horizon\n"
+ "With poisoned-reverse\n")
+
DEFUN (ripng_passive_interface,
ripng_passive_interface_cmd,
"passive-interface IFNAME",
@@ -757,6 +1103,14 @@ ri_new ()
{
struct ripng_interface *ri;
ri = XCALLOC (MTYPE_IF, sizeof (struct ripng_interface));
+
+ /* Set default split-horizon behavior. If the interface is Frame
+ Relay or SMDS is enabled, the default value for split-horizon is
+ off. But currently Zebra does detect Frame Relay or SMDS
+ interface. So all interface is set to split horizon. */
+ ri->split_horizon_default = RIPNG_SPLIT_HORIZON;
+ ri->split_horizon = ri->split_horizon_default;
+
return ri;
}
@@ -767,6 +1121,15 @@ ripng_if_new_hook (struct interface *ifp)
return 0;
}
+/* Called when interface structure deleted. */
+int
+ripng_if_delete_hook (struct interface *ifp)
+{
+ XFREE (MTYPE_IF, ifp->info);
+ ifp->info = NULL;
+ return 0;
+}
+
/* Configuration write function for ripngd. */
int
interface_config_write (struct vty *vty)
@@ -781,12 +1144,37 @@ interface_config_write (struct vty *vty)
ifp = getdata (node);
ri = ifp->info;
+ /* Do not display the interface if there is no
+ * configuration about it.
+ **/
+ if ((!ifp->desc) &&
+ (ri->split_horizon == ri->split_horizon_default))
+ continue;
+
vty_out (vty, "interface %s%s", ifp->name,
VTY_NEWLINE);
if (ifp->desc)
vty_out (vty, " description %s%s", ifp->desc,
VTY_NEWLINE);
+ /* Split horizon. */
+ if (ri->split_horizon != ri->split_horizon_default)
+ {
+ switch (ri->split_horizon) {
+ case RIPNG_SPLIT_HORIZON:
+ vty_out (vty, " ipv6 ripng split-horizon%s", VTY_NEWLINE);
+ break;
+ case RIPNG_SPLIT_HORIZON_POISONED_REVERSE:
+ vty_out (vty, " ipv6 ripng split-horizon poisoned-reverse%s",
+ VTY_NEWLINE);
+ break;
+ case RIPNG_NO_SPLIT_HORIZON:
+ default:
+ vty_out (vty, " no ipv6 ripng split-horizon%s", VTY_NEWLINE);
+ break;
+ }
+ }
+
vty_out (vty, "!%s", VTY_NEWLINE);
write++;
@@ -799,6 +1187,7 @@ struct cmd_node interface_node =
{
INTERFACE_NODE,
"%s(config-if)# ",
+ 1 /* VTYSH */
};
/* Initialization of interface. */
@@ -808,6 +1197,7 @@ ripng_if_init ()
/* Interface initialize. */
iflist = list_new ();
if_add_hook (IF_NEW_HOOK, ripng_if_new_hook);
+ if_add_hook (IF_DELETE_HOOK, ripng_if_delete_hook);
/* RIPng enable network init. */
ripng_enable_network = route_table_init ();
@@ -820,11 +1210,11 @@ ripng_if_init ()
/* Install interface node. */
install_node (&interface_node, interface_config_write);
-
+
+ /* Install commands. */
install_element (CONFIG_NODE, &interface_cmd);
- install_element (INTERFACE_NODE, &config_end_cmd);
- install_element (INTERFACE_NODE, &config_exit_cmd);
- install_element (INTERFACE_NODE, &config_help_cmd);
+ install_element (CONFIG_NODE, &no_interface_cmd);
+ install_default (INTERFACE_NODE);
install_element (INTERFACE_NODE, &interface_desc_cmd);
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
@@ -832,4 +1222,9 @@ ripng_if_init ()
install_element (RIPNG_NODE, &no_ripng_network_cmd);
install_element (RIPNG_NODE, &ripng_passive_interface_cmd);
install_element (RIPNG_NODE, &no_ripng_passive_interface_cmd);
+
+ install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
+ install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_poisoned_reverse_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_poisoned_reverse_cmd);
}
diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c
index 0d5fe78c..87d16a52 100644
--- a/ripngd/ripng_main.c
+++ b/ripngd/ripng_main.c
@@ -27,6 +27,7 @@
#include "vector.h"
#include "vty.h"
#include "command.h"
+#include "memory.h"
#include "thread.h"
#include "log.h"
#include "prefix.h"
@@ -38,6 +39,7 @@
/* Configuration filename and directory. */
char config_current[] = RIPNG_DEFAULT_CONFIG;
char config_default[] = SYSCONFDIR RIPNG_DEFAULT_CONFIG;
+char *config_file = NULL;
/* RIPngd options. */
struct option longopts[] =
@@ -81,6 +83,12 @@ struct zebra_privs_t ripngd_privs =
/* Route retain mode flag. */
int retain_mode = 0;
+/* RIPng VTY bind address. */
+char *vty_addr = NULL;
+
+/* RIPng VTY connection port. */
+int vty_port = RIPNG_VTY_PORT;
+
/* Master of threads. */
struct thread_master *master;
@@ -117,17 +125,27 @@ Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
void
sighup (int sig)
{
- zlog (NULL, LOG_INFO, "SIGHUP received");
+ zlog_info ("SIGHUP received");
+ ripng_clean ();
+ ripng_reset ();
+ zlog_info ("Terminating on signal");
+
+ /* Reload config file. */
+ vty_read_config (config_file, config_current, config_default);
+ /* Create VTY's socket */
+ vty_serv_sock (vty_addr, vty_port, RIPNG_VTYSH_PATH);
+
+ /* Try to return to normal operation. */
}
/* SIGINT handler. */
void
sigint (int sig)
{
- zlog (NULL, LOG_INFO, "Terminating on signal");
+ zlog_info ("Terminating on signal");
if (! retain_mode)
- ripng_terminate ();
+ ripng_clean ();
exit (0);
}
@@ -178,10 +196,8 @@ int
main (int argc, char **argv)
{
char *p;
- char *vty_addr = NULL;
int vty_port = RIPNG_VTY_PORT;
int daemon_mode = 0;
- char *config_file = NULL;
char *progname;
struct thread thread;
@@ -259,10 +275,14 @@ main (int argc, char **argv)
signal_init ();
cmd_init (1);
vty_init ();
+ memory_init ();
/* RIPngd inits. */
ripng_init ();
zebra_init ();
+ ripng_peer_init ();
+
+ /* Sort all installed commands. */
sort_node ();
/* Get configuration file. */
diff --git a/ripngd/ripng_nexthop.c b/ripngd/ripng_nexthop.c
new file mode 100644
index 00000000..2c5d45cd
--- /dev/null
+++ b/ripngd/ripng_nexthop.c
@@ -0,0 +1,216 @@
+/* RIPngd Zebra
+ * Copyright (C) 2002 6WIND <vincent.jardin@6wind.com>
+ *
+ * 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.
+ */
+
+/* This file is required in order to support properly the RIPng nexthop
+ * feature.
+ */
+
+#include <zebra.h>
+
+/* For struct udphdr. */
+#include <netinet/udp.h>
+
+#include "linklist.h"
+#include "stream.h"
+#include "log.h"
+#include "memory.h"
+#include "vty.h"
+#include "if.h"
+#include "prefix.h"
+
+#include "ripngd/ripngd.h"
+#include "ripngd/ripng_debug.h"
+#include "ripngd/ripng_nexthop.h"
+
+#define DEBUG 1
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+struct ripng_rte_data {
+ struct prefix_ipv6 *p;
+ struct ripng_info *rinfo;
+ struct ripng_aggregate *aggregate;
+};
+
+void _ripng_rte_del(struct ripng_rte_data *A);
+int _ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B);
+
+#define METRIC_OUT(a) \
+ (a->rinfo ? a->rinfo->metric_out : a->aggregate->metric_out)
+#define NEXTHOP_OUT(a) \
+ (a->rinfo ? a->rinfo->nexthop_out : a->aggregate->nexthop_out)
+#define TAG_OUT(a) \
+ (a->rinfo ? a->rinfo->tag_out : a->aggregate->tag_out)
+
+struct list *
+ripng_rte_new(void) {
+ struct list *rte;
+
+ rte = list_new();
+ rte->cmp = (int (*)(void *, void *)) _ripng_rte_cmp;
+ rte->del = (void (*)(void *)) _ripng_rte_del;
+
+ return rte;
+}
+
+void
+ripng_rte_free(struct list *ripng_rte_list) {
+ list_delete(ripng_rte_list);
+}
+
+/* Delete RTE */
+void
+_ripng_rte_del(struct ripng_rte_data *A) {
+ XFREE(MTYPE_RIPNG_RTE_DATA, A);
+}
+
+/* Compare RTE:
+ * return + if A > B
+ * 0 if A = B
+ * - if A < B
+ */
+int
+_ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B) {
+ return addr6_cmp(&NEXTHOP_OUT(A), &NEXTHOP_OUT(B));
+}
+
+/* Add routing table entry */
+void
+ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p,
+ struct ripng_info *rinfo, struct ripng_aggregate *aggregate) {
+
+ struct ripng_rte_data *data;
+
+ /* At least one should not be null */
+ assert(!rinfo || !aggregate);
+
+ data = XMALLOC(MTYPE_RIPNG_RTE_DATA, sizeof(*data));
+ data->p = p;
+ data->rinfo = rinfo;
+ data->aggregate = aggregate;
+
+ listnode_add_sort(ripng_rte_list, data);
+}
+
+/* Send the RTE with the nexthop support
+ */
+void
+ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp,
+ struct sockaddr_in6 *to) {
+
+ struct ripng_rte_data *data;
+ struct listnode * nn;
+
+ struct in6_addr last_nexthop;
+ struct in6_addr myself_nexthop;
+
+ struct stream *s;
+ int num;
+ int mtu;
+ int rtemax;
+ int ret;
+
+ /* Most of the time, there is no nexthop */
+ memset(&last_nexthop, 0, sizeof(last_nexthop));
+
+ /* Use myself_nexthop if the nexthop is not a link-local address, because
+ * we remain a right path without beeing the optimal one.
+ */
+ memset(&myself_nexthop, 0, sizeof(myself_nexthop));
+
+ /* Output stream get from ripng structre. XXX this should be
+ interface structure. */
+ s = ripng->obuf;
+
+ /* Reset stream and RTE counter. */
+ stream_reset (s);
+ num = 0;
+
+ mtu = ifp->mtu;
+ if (mtu < 0)
+ mtu = IFMINMTU;
+
+ rtemax = (min (mtu, RIPNG_MAX_PACKET_SIZE) -
+ IPV6_HDRLEN -
+ sizeof (struct udphdr) -
+ sizeof (struct ripng_packet) +
+ sizeof (struct rte)) / sizeof (struct rte);
+
+ LIST_LOOP(ripng_rte_list, data, nn) {
+
+ /* (2.1) Next hop support */
+ if (!IPV6_ADDR_SAME(&last_nexthop, &NEXTHOP_OUT(data))) {
+
+ /* A nexthop entry should be at least followed by 1 RTE */
+ if (num == (rtemax-1)) {
+ ret = ripng_send_packet (STREAM_DATA (s), stream_get_endp (s),
+ to, ifp);
+
+ if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
+ ripng_packet_dump((struct ripng_packet *)STREAM_DATA (s),
+ stream_get_endp(s), "SEND");
+ num = 0;
+ stream_reset (s);
+ }
+
+ /* Add the nexthop (2.1) */
+
+ /* If the received next hop address is not a link-local address,
+ * it should be treated as 0:0:0:0:0:0:0:0.
+ */
+ if (!IN6_IS_ADDR_LINKLOCAL(&NEXTHOP_OUT(data)))
+ last_nexthop = myself_nexthop;
+ else
+ last_nexthop = NEXTHOP_OUT(data);
+
+ num = ripng_write_rte(num, s, NULL, &last_nexthop, 0, RIPNG_METRIC_NEXTHOP);
+ } else {
+ /* Rewrite the nexthop for each new packet */
+ if ((num == 0) && !IPV6_ADDR_SAME(&last_nexthop, &myself_nexthop))
+ num = ripng_write_rte(num, s, NULL, &last_nexthop, 0, RIPNG_METRIC_NEXTHOP);
+ }
+ num = ripng_write_rte(num, s, data->p, NULL,
+ TAG_OUT(data), METRIC_OUT(data));
+
+ if (num == rtemax) {
+ ret = ripng_send_packet (STREAM_DATA (s), stream_get_endp (s),
+ to, ifp);
+
+ if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
+ ripng_packet_dump((struct ripng_packet *)STREAM_DATA (s),
+ stream_get_endp(s), "SEND");
+ num = 0;
+ stream_reset (s);
+ }
+ }
+
+ /* If unwritten RTE exist, flush it. */
+ if (num != 0) {
+ ret = ripng_send_packet (STREAM_DATA (s), stream_get_endp (s),
+ to, ifp);
+
+ if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
+ ripng_packet_dump ((struct ripng_packet *)STREAM_DATA (s),
+ stream_get_endp (s), "SEND");
+ num = 0;
+ stream_reset (s);
+ }
+}
diff --git a/ripngd/ripng_nexthop.h b/ripngd/ripng_nexthop.h
new file mode 100644
index 00000000..5c778f5e
--- /dev/null
+++ b/ripngd/ripng_nexthop.h
@@ -0,0 +1,62 @@
+/* RIPng nexthop support
+ * Copyright (C) 6WIND Vincent Jardin <vincent.jardin@6wind.com>
+ *
+ * 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.
+ */
+
+#ifndef _ZEBRA_RIPNG_RIPNG_NEXTHOP_H
+#define _ZEBRA_RIPNG_RIPNG_NEXTHOP_H
+
+#include <zebra.h>
+#include "linklist.h"
+#include "ripngd/ripng_route.h"
+#include "ripngd/ripngd.h"
+
+struct list * ripng_rte_new(void);
+void ripng_rte_free(struct list *ripng_rte_list);
+void ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p,
+ struct ripng_info *rinfo, struct ripng_aggregate *aggregate);
+void ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp,
+ struct sockaddr_in6 *to);
+
+/***
+ * 1 if A > B
+ * 0 if A = B
+ * -1 if A < B
+ **/
+static inline int
+addr6_cmp(struct in6_addr *A, struct in6_addr *B) {
+#define a(i) A->s6_addr32[i]
+#define b(i) B->s6_addr32[i]
+
+ if (a(3) > b(3))
+ return 1;
+ else if ((a(3) == b(3)) && (a(2) > b(2)))
+ return 1;
+ else if ((a(3) == b(3)) && (a(2) == b(2)) && (a(1) > b(1)))
+ return 1;
+ else if ((a(3) == b(3)) && (a(2) == b(2)) && (a(1) == b(1)) && (a(0) > b(0)))
+ return 1;
+
+ if ((a(3) == b(3)) && (a(2) == b(2)) && (a(1) == b(1)) && (a(0) == b(0)))
+ return 0;
+
+ return -1;
+}
+
+#endif /* _ZEBRA_RIPNG_RIPNG_NEXTHOP_H */
diff --git a/ripngd/ripng_offset.c b/ripngd/ripng_offset.c
new file mode 100644
index 00000000..ab3c4601
--- /dev/null
+++ b/ripngd/ripng_offset.c
@@ -0,0 +1,417 @@
+/* RIPng offset-list
+ * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
+ *
+ * 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.
+ */
+
+ /* RIPng support by Vincent Jardin <vincent.jardin@6wind.com>
+ * Copyright (C) 2002 6WIND
+ */
+
+#include <zebra.h>
+
+#include "if.h"
+#include "prefix.h"
+#include "filter.h"
+#include "command.h"
+#include "linklist.h"
+#include "memory.h"
+
+#define RIPNG_OFFSET_LIST_IN 0
+#define RIPNG_OFFSET_LIST_OUT 1
+#define RIPNG_OFFSET_LIST_MAX 2
+
+struct ripng_offset_list
+{
+ char *ifname;
+
+ struct
+ {
+ char *alist_name;
+ /* struct access_list *alist; */
+ int metric;
+ } direct[RIPNG_OFFSET_LIST_MAX];
+};
+
+static struct list *ripng_offset_list_master;
+
+int
+strcmp_safe (char *s1, char *s2)
+{
+ if (s1 == NULL && s2 == NULL)
+ return 0;
+ if (s1 == NULL)
+ return -1;
+ if (s2 == NULL)
+ return 1;
+ return strcmp (s1, s2);
+}
+
+struct ripng_offset_list *
+ripng_offset_list_new ()
+{
+ struct ripng_offset_list *new;
+
+ new = XCALLOC (MTYPE_RIPNG_OFFSET_LIST, sizeof (struct ripng_offset_list));
+ return new;
+}
+
+void
+ripng_offset_list_free (struct ripng_offset_list *offset)
+{
+ XFREE (MTYPE_RIPNG_OFFSET_LIST, offset);
+}
+
+struct ripng_offset_list *
+ripng_offset_list_lookup (char *ifname)
+{
+ struct ripng_offset_list *offset;
+ struct listnode *nn;
+
+ LIST_LOOP (ripng_offset_list_master, offset, nn)
+ {
+ if (strcmp_safe (offset->ifname, ifname) == 0)
+ return offset;
+ }
+ return NULL;
+}
+
+struct ripng_offset_list *
+ripng_offset_list_get (char *ifname)
+{
+ struct ripng_offset_list *offset;
+
+ offset = ripng_offset_list_lookup (ifname);
+ if (offset)
+ return offset;
+
+ offset = ripng_offset_list_new ();
+ if (ifname)
+ offset->ifname = strdup (ifname);
+ listnode_add_sort (ripng_offset_list_master, offset);
+
+ return offset;
+}
+
+int
+ripng_offset_list_set (struct vty *vty, char *alist, char *direct_str,
+ char *metric_str, char *ifname)
+{
+ int direct;
+ int metric;
+ struct ripng_offset_list *offset;
+
+ /* Check direction. */
+ if (strncmp (direct_str, "i", 1) == 0)
+ direct = RIPNG_OFFSET_LIST_IN;
+ else if (strncmp (direct_str, "o", 1) == 0)
+ direct = RIPNG_OFFSET_LIST_OUT;
+ else
+ {
+ vty_out (vty, "Invalid direction: %s%s", direct_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ /* Check metric. */
+ metric = atoi (metric_str);
+ if (metric < 0 || metric > 16)
+ {
+ vty_out (vty, "Invalid metric: %s%s", metric_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ /* Get offset-list structure with interface name. */
+ offset = ripng_offset_list_get (ifname);
+
+ if (offset->direct[direct].alist_name)
+ free (offset->direct[direct].alist_name);
+ offset->direct[direct].alist_name = strdup (alist);
+ offset->direct[direct].metric = metric;
+
+ return CMD_SUCCESS;
+}
+
+int
+ripng_offset_list_unset (struct vty *vty, char *alist, char *direct_str,
+ char *metric_str, char *ifname)
+{
+ int direct;
+ int metric;
+ struct ripng_offset_list *offset;
+
+ /* Check direction. */
+ if (strncmp (direct_str, "i", 1) == 0)
+ direct = RIPNG_OFFSET_LIST_IN;
+ else if (strncmp (direct_str, "o", 1) == 0)
+ direct = RIPNG_OFFSET_LIST_OUT;
+ else
+ {
+ vty_out (vty, "Invalid direction: %s%s", direct_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ /* Check metric. */
+ metric = atoi (metric_str);
+ if (metric < 0 || metric > 16)
+ {
+ vty_out (vty, "Invalid metric: %s%s", metric_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ /* Get offset-list structure with interface name. */
+ offset = ripng_offset_list_lookup (ifname);
+
+ if (offset)
+ {
+ if (offset->direct[direct].alist_name)
+ free (offset->direct[direct].alist_name);
+ offset->direct[direct].alist_name = NULL;
+
+ if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL &&
+ offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL)
+ {
+ listnode_delete (ripng_offset_list_master, offset);
+ if (offset->ifname)
+ free (offset->ifname);
+ ripng_offset_list_free (offset);
+ }
+ }
+ else
+ {
+ vty_out (vty, "Can't find offset-list%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ return CMD_SUCCESS;
+}
+
+#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name)
+#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].metric)
+
+#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
+#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric)
+
+/* If metric is modifed return 1. */
+int
+ripng_offset_list_apply_in (struct prefix_ipv6 *p, struct interface *ifp,
+ u_char *metric)
+{
+ struct ripng_offset_list *offset;
+ struct access_list *alist;
+
+ /* Look up offset-list with interface name. */
+ offset = ripng_offset_list_lookup (ifp->name);
+ if (offset && OFFSET_LIST_IN_NAME (offset))
+ {
+ alist = access_list_lookup (AFI_IP6, OFFSET_LIST_IN_NAME (offset));
+
+ if (alist
+ && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
+ {
+ *metric += OFFSET_LIST_IN_METRIC (offset);
+ return 1;
+ }
+ return 0;
+ }
+ /* Look up offset-list without interface name. */
+ offset = ripng_offset_list_lookup (NULL);
+ if (offset && OFFSET_LIST_IN_NAME (offset))
+ {
+ alist = access_list_lookup (AFI_IP6, OFFSET_LIST_IN_NAME (offset));
+
+ if (alist
+ && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
+ {
+ *metric += OFFSET_LIST_IN_METRIC (offset);
+ return 1;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+/* If metric is modifed return 1. */
+int
+ripng_offset_list_apply_out (struct prefix_ipv6 *p, struct interface *ifp,
+ u_char *metric)
+{
+ struct ripng_offset_list *offset;
+ struct access_list *alist;
+
+ /* Look up offset-list with interface name. */
+ offset = ripng_offset_list_lookup (ifp->name);
+ if (offset && OFFSET_LIST_OUT_NAME (offset))
+ {
+ alist = access_list_lookup (AFI_IP6, OFFSET_LIST_OUT_NAME (offset));
+
+ if (alist
+ && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
+ {
+ *metric += OFFSET_LIST_OUT_METRIC (offset);
+ return 1;
+ }
+ return 0;
+ }
+
+ /* Look up offset-list without interface name. */
+ offset = ripng_offset_list_lookup (NULL);
+ if (offset && OFFSET_LIST_OUT_NAME (offset))
+ {
+ alist = access_list_lookup (AFI_IP6, OFFSET_LIST_OUT_NAME (offset));
+
+ if (alist
+ && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
+ {
+ *metric += OFFSET_LIST_OUT_METRIC (offset);
+ return 1;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+DEFUN (ripng_offset_list,
+ ripng_offset_list_cmd,
+ "offset-list WORD (in|out) <0-16>",
+ "Modify RIPng metric\n"
+ "Access-list name\n"
+ "For incoming updates\n"
+ "For outgoing updates\n"
+ "Metric value\n")
+{
+ return ripng_offset_list_set (vty, argv[0], argv[1], argv[2], NULL);
+}
+
+DEFUN (ripng_offset_list_ifname,
+ ripng_offset_list_ifname_cmd,
+ "offset-list WORD (in|out) <0-16> IFNAME",
+ "Modify RIPng metric\n"
+ "Access-list name\n"
+ "For incoming updates\n"
+ "For outgoing updates\n"
+ "Metric value\n"
+ "Interface to match\n")
+{
+ return ripng_offset_list_set (vty, argv[0], argv[1], argv[2], argv[3]);
+}
+
+DEFUN (no_ripng_offset_list,
+ no_ripng_offset_list_cmd,
+ "no offset-list WORD (in|out) <0-16>",
+ NO_STR
+ "Modify RIPng metric\n"
+ "Access-list name\n"
+ "For incoming updates\n"
+ "For outgoing updates\n"
+ "Metric value\n")
+{
+ return ripng_offset_list_unset (vty, argv[0], argv[1], argv[2], NULL);
+}
+
+DEFUN (no_ripng_offset_list_ifname,
+ no_ripng_offset_list_ifname_cmd,
+ "no offset-list WORD (in|out) <0-16> IFNAME",
+ NO_STR
+ "Modify RIPng metric\n"
+ "Access-list name\n"
+ "For incoming updates\n"
+ "For outgoing updates\n"
+ "Metric value\n"
+ "Interface to match\n")
+{
+ return ripng_offset_list_unset (vty, argv[0], argv[1], argv[2], argv[3]);
+}
+
+int
+offset_list_cmp (struct ripng_offset_list *o1, struct ripng_offset_list *o2)
+{
+ return strcmp_safe (o1->ifname, o2->ifname);
+}
+
+void
+offset_list_del (struct ripng_offset_list *offset)
+{
+ if (OFFSET_LIST_IN_NAME (offset))
+ free (OFFSET_LIST_IN_NAME (offset));
+ if (OFFSET_LIST_OUT_NAME (offset))
+ free (OFFSET_LIST_OUT_NAME (offset));
+ if (offset->ifname)
+ free (offset->ifname);
+ ripng_offset_list_free (offset);
+}
+
+void
+ripng_offset_init ()
+{
+ ripng_offset_list_master = list_new ();
+ ripng_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp;
+ ripng_offset_list_master->del = (void (*)(void *)) offset_list_del;
+
+ install_element (RIPNG_NODE, &ripng_offset_list_cmd);
+ install_element (RIPNG_NODE, &ripng_offset_list_ifname_cmd);
+ install_element (RIPNG_NODE, &no_ripng_offset_list_cmd);
+ install_element (RIPNG_NODE, &no_ripng_offset_list_ifname_cmd);
+}
+
+void
+ripng_offset_clean ()
+{
+ list_delete (ripng_offset_list_master);
+
+ ripng_offset_list_master = list_new ();
+ ripng_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp;
+ ripng_offset_list_master->del = (void (*)(void *)) offset_list_del;
+}
+
+int
+config_write_ripng_offset_list (struct vty *vty)
+{
+ struct listnode *nn;
+ struct ripng_offset_list *offset;
+
+ LIST_LOOP (ripng_offset_list_master, offset, nn)
+ {
+ if (! offset->ifname)
+ {
+ if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name)
+ vty_out (vty, " offset-list %s in %d%s",
+ offset->direct[RIPNG_OFFSET_LIST_IN].alist_name,
+ offset->direct[RIPNG_OFFSET_LIST_IN].metric,
+ VTY_NEWLINE);
+ if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
+ vty_out (vty, " offset-list %s out %d%s",
+ offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name,
+ offset->direct[RIPNG_OFFSET_LIST_OUT].metric,
+ VTY_NEWLINE);
+ }
+ else
+ {
+ if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name)
+ vty_out (vty, " offset-list %s in %d %s%s",
+ offset->direct[RIPNG_OFFSET_LIST_IN].alist_name,
+ offset->direct[RIPNG_OFFSET_LIST_IN].metric,
+ offset->ifname, VTY_NEWLINE);
+ if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
+ vty_out (vty, " offset-list %s out %d %s%s",
+ offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name,
+ offset->direct[RIPNG_OFFSET_LIST_OUT].metric,
+ offset->ifname, VTY_NEWLINE);
+ }
+ }
+
+ return 0;
+}
diff --git a/ripngd/ripng_peer.c b/ripngd/ripng_peer.c
new file mode 100644
index 00000000..b9af930c
--- /dev/null
+++ b/ripngd/ripng_peer.c
@@ -0,0 +1,220 @@
+/* RIPng peer support
+ * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
+ *
+ * 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.
+ */
+
+/* RIPng support added by Vincent Jardin <vincent.jardin@6wind.com>
+ * Copyright (C) 2002 6WIND
+ */
+
+#include <zebra.h>
+
+#include "if.h"
+#include "prefix.h"
+#include "command.h"
+#include "linklist.h"
+#include "thread.h"
+#include "memory.h"
+
+#include "ripngd/ripngd.h"
+#include "ripngd/ripng_nexthop.h"
+
+
+/* Linked list of RIPng peer. */
+struct list *peer_list;
+
+struct ripng_peer *
+ripng_peer_new ()
+{
+ struct ripng_peer *new;
+
+ new = XMALLOC (MTYPE_RIPNG_PEER, sizeof (struct ripng_peer));
+ memset (new, 0, sizeof (struct ripng_peer));
+ return new;
+}
+
+void
+ripng_peer_free (struct ripng_peer *peer)
+{
+ XFREE (MTYPE_RIPNG_PEER, peer);
+}
+
+struct ripng_peer *
+ripng_peer_lookup (struct in6_addr *addr)
+{
+ struct ripng_peer *peer;
+ struct listnode *nn;
+
+ LIST_LOOP (peer_list, peer, nn)
+ {
+ if (IPV6_ADDR_SAME (&peer->addr, addr))
+ return peer;
+ }
+ return NULL;
+}
+
+struct ripng_peer *
+ripng_peer_lookup_next (struct in6_addr *addr)
+{
+ struct ripng_peer *peer;
+ struct listnode *nn;
+
+ LIST_LOOP (peer_list, peer, nn)
+ {
+ if (addr6_cmp(&peer->addr, addr) > 0)
+ return peer;
+ }
+ return NULL;
+}
+
+/* RIPng peer is timeout.
+ * Garbage collector.
+ **/
+int
+ripng_peer_timeout (struct thread *t)
+{
+ struct ripng_peer *peer;
+
+ peer = THREAD_ARG (t);
+ listnode_delete (peer_list, peer);
+ ripng_peer_free (peer);
+
+ return 0;
+}
+
+/* Get RIPng peer. At the same time update timeout thread. */
+struct ripng_peer *
+ripng_peer_get (struct in6_addr *addr)
+{
+ struct ripng_peer *peer;
+
+ peer = ripng_peer_lookup (addr);
+
+ if (peer)
+ {
+ if (peer->t_timeout)
+ thread_cancel (peer->t_timeout);
+ }
+ else
+ {
+ peer = ripng_peer_new ();
+ peer->addr = *addr; /* XXX */
+ listnode_add_sort (peer_list, peer);
+ }
+
+ /* Update timeout thread. */
+ peer->t_timeout = thread_add_timer (master, ripng_peer_timeout, peer,
+ RIPNG_PEER_TIMER_DEFAULT);
+
+ /* Last update time set. */
+ time (&peer->uptime);
+
+ return peer;
+}
+
+void
+ripng_peer_update (struct sockaddr_in6 *from, u_char version)
+{
+ struct ripng_peer *peer;
+ peer = ripng_peer_get (&from->sin6_addr);
+ peer->version = version;
+}
+
+void
+ripng_peer_bad_route (struct sockaddr_in6 *from)
+{
+ struct ripng_peer *peer;
+ peer = ripng_peer_get (&from->sin6_addr);
+ peer->recv_badroutes++;
+}
+
+void
+ripng_peer_bad_packet (struct sockaddr_in6 *from)
+{
+ struct ripng_peer *peer;
+ peer = ripng_peer_get (&from->sin6_addr);
+ peer->recv_badpackets++;
+}
+
+/* Display peer uptime. */
+char *
+ripng_peer_uptime (struct ripng_peer *peer, char *buf, size_t len)
+{
+ time_t uptime;
+ struct tm *tm;
+
+ /* If there is no connection has been done before print `never'. */
+ if (peer->uptime == 0)
+ {
+ snprintf (buf, len, "never ");
+ return buf;
+ }
+
+ /* Get current time. */
+ uptime = time (NULL);
+ uptime -= peer->uptime;
+ tm = gmtime (&uptime);
+
+ /* Making formatted timer strings. */
+#define ONE_DAY_SECOND 60*60*24
+#define ONE_WEEK_SECOND 60*60*24*7
+
+ if (uptime < ONE_DAY_SECOND)
+ snprintf (buf, len, "%02d:%02d:%02d",
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ else if (uptime < ONE_WEEK_SECOND)
+ snprintf (buf, len, "%dd%02dh%02dm",
+ tm->tm_yday, tm->tm_hour, tm->tm_min);
+ else
+ snprintf (buf, len, "%02dw%dd%02dh",
+ tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
+ return buf;
+}
+
+void
+ripng_peer_display (struct vty *vty)
+{
+ struct ripng_peer *peer;
+ struct listnode *nn;
+#define RIPNG_UPTIME_LEN 25
+ char timebuf[RIPNG_UPTIME_LEN];
+
+ LIST_LOOP (peer_list, peer, nn)
+ {
+ vty_out (vty, " %s %s%14s %10d %10d %10d %s%s", inet6_ntop (&peer->addr),
+ VTY_NEWLINE, " ",
+ peer->recv_badpackets, peer->recv_badroutes,
+ ZEBRA_RIPNG_DISTANCE_DEFAULT,
+ ripng_peer_uptime (peer, timebuf, RIPNG_UPTIME_LEN),
+ VTY_NEWLINE);
+ }
+}
+
+int
+ripng_peer_list_cmp (struct ripng_peer *p1, struct ripng_peer *p2)
+{
+ return addr6_cmp(&p1->addr, &p2->addr) > 0;
+}
+
+void
+ripng_peer_init ()
+{
+ peer_list = list_new ();
+ peer_list->cmp = (int (*)(void *, void *)) ripng_peer_list_cmp;
+}
diff --git a/ripngd/ripng_route.c b/ripngd/ripng_route.c
index 27475f05..9c3c4f99 100644
--- a/ripngd/ripng_route.c
+++ b/ripngd/ripng_route.c
@@ -26,6 +26,7 @@
#include "table.h"
#include "memory.h"
#include "if.h"
+#include "vty.h"
#include "ripngd/ripngd.h"
#include "ripngd/ripng_route.h"
diff --git a/ripngd/ripng_route.h b/ripngd/ripng_route.h
index 283d8268..db53f148 100644
--- a/ripngd/ripng_route.h
+++ b/ripngd/ripng_route.h
@@ -36,6 +36,12 @@ struct ripng_aggregate
/* Tag field of RIPng packet.*/
u_short tag;
+
+ /* Route-map futures - this variables can be changed. */
+ struct in6_addr nexthop_out;
+ u_char metric_set;
+ u_char metric_out;
+ u_short tag_out;
};
void
diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c
index f237e6b6..0bd7e448 100644
--- a/ripngd/ripng_routemap.c
+++ b/ripngd/ripng_routemap.c
@@ -26,11 +26,175 @@
#include "prefix.h"
#include "routemap.h"
#include "command.h"
+#include "sockunion.h"
#include "ripngd/ripngd.h"
-#if 0
+struct rip_metric_modifier
+{
+ enum
+ {
+ metric_increment,
+ metric_decrement,
+ metric_absolute
+ } type;
+
+ u_char metric;
+};
+
+
+int
+ripng_route_match_add (struct vty *vty, struct route_map_index *index,
+ char *command, char *arg)
+{
+ int ret;
+
+ ret = route_map_add_match (index, command, arg);
+ if (ret)
+ {
+ switch (ret)
+ {
+ case RMAP_RULE_MISSING:
+ vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ break;
+ case RMAP_COMPILE_ERROR:
+ vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ break;
+ }
+ }
+ return CMD_SUCCESS;
+}
+
+int
+ripng_route_match_delete (struct vty *vty, struct route_map_index *index,
+ char *command, char *arg)
+{
+ int ret;
+
+ ret = route_map_delete_match (index, command, arg);
+ if (ret)
+ {
+ switch (ret)
+ {
+ case RMAP_RULE_MISSING:
+ vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ break;
+ case RMAP_COMPILE_ERROR:
+ vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ break;
+ }
+ }
+ return CMD_SUCCESS;
+}
+
+int
+ripng_route_set_add (struct vty *vty, struct route_map_index *index,
+ char *command, char *arg)
+{
+ int ret;
+
+ ret = route_map_add_set (index, command, arg);
+ if (ret)
+ {
+ switch (ret)
+ {
+ case RMAP_RULE_MISSING:
+ vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ break;
+ case RMAP_COMPILE_ERROR:
+ vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ break;
+ }
+ }
+ return CMD_SUCCESS;
+}
+
+int
+ripng_route_set_delete (struct vty *vty, struct route_map_index *index,
+ char *command, char *arg)
+{
+ int ret;
+
+ ret = route_map_delete_set (index, command, arg);
+ if (ret)
+ {
+ switch (ret)
+ {
+ case RMAP_RULE_MISSING:
+ vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ break;
+ case RMAP_COMPILE_ERROR:
+ vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ break;
+ }
+ }
+ return CMD_SUCCESS;
+}
+
+/* `match metric METRIC' */
+/* Match function return 1 if match is success else return zero. */
+route_map_result_t
+route_match_metric (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ u_int32_t *metric;
+ struct ripng_info *rinfo;
+
+ if (type == RMAP_RIPNG)
+ {
+ metric = rule;
+ rinfo = object;
+
+ if (rinfo->metric == *metric)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
+ }
+ return RMAP_NOMATCH;
+}
+
+/* Route map `match metric' match statement. `arg' is METRIC value */
+void *
+route_match_metric_compile (char *arg)
+{
+ u_int32_t *metric;
+
+ metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
+ *metric = atoi (arg);
+
+ if(*metric > 0)
+ return metric;
+
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, metric);
+ return NULL;
+}
+
+/* Free route map's compiled `match metric' value. */
+void
+route_match_metric_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for metric matching. */
+struct route_map_rule_cmd route_match_metric_cmd =
+{
+ "metric",
+ route_match_metric,
+ route_match_metric_compile,
+ route_match_metric_free
+};
+
/* `match interface IFNAME' */
+/* Match function return 1 if match is success else return zero. */
route_map_result_t
route_match_interface (void *rule, struct prefix *prefix,
route_map_object_t type, void *object)
@@ -39,24 +203,25 @@ route_match_interface (void *rule, struct prefix *prefix,
struct interface *ifp;
char *ifname;
- if (type == ROUTE_MAP_RIPNG)
+ if (type == RMAP_RIPNG)
{
ifname = rule;
ifp = if_lookup_by_name(ifname);
if (!ifp)
- return RM_NOMATCH;
+ return RMAP_NOMATCH;
rinfo = object;
if (rinfo->ifindex == ifp->ifindex)
- return RM_MATCH;
+ return RMAP_MATCH;
else
- return RM_NOMATCH;
+ return RMAP_NOMATCH;
}
- return RM_NOMATCH;
+ return RMAP_NOMATCH;
}
+/* Route map `match interface' match statement. `arg' is IFNAME value */
void *
route_match_interface_compile (char *arg)
{
@@ -76,20 +241,61 @@ struct route_map_rule_cmd route_match_interface_cmd =
route_match_interface_compile,
route_match_interface_free
};
-#endif /* 0 */
-
-struct rip_metric_modifier
+
+/* `match tag TAG' */
+/* Match function return 1 if match is success else return zero. */
+route_map_result_t
+route_match_tag (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
{
- enum
- {
- metric_increment,
- metric_decrement,
- metric_absolute
- } type;
+ u_short *tag;
+ struct ripng_info *rinfo;
- u_char metric;
+ if (type == RMAP_RIPNG)
+ {
+ tag = rule;
+ rinfo = object;
+
+ /* The information stored by rinfo is host ordered. */
+ if (rinfo->tag == *tag)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
+ }
+ return RMAP_NOMATCH;
+}
+
+/* Route map `match tag' match statement. `arg' is TAG value */
+void *
+route_match_tag_compile (char *arg)
+{
+ u_short *tag;
+
+ tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
+ *tag = atoi (arg);
+
+ return tag;
+}
+
+/* Free route map's compiled `match tag' value. */
+void
+route_match_tag_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for tag matching. */
+struct route_map_rule_cmd route_match_tag_cmd =
+{
+ "tag",
+ route_match_tag,
+ route_match_tag_compile,
+ route_match_tag_free
};
+
+/* `set metric METRIC' */
+/* Set metric to attribute. */
route_map_result_t
route_set_metric (void *rule, struct prefix *prefix,
route_map_object_t type, void *object)
@@ -103,22 +309,23 @@ route_set_metric (void *rule, struct prefix *prefix,
rinfo = object;
if (mod->type == metric_increment)
- rinfo->metric += mod->metric;
+ rinfo->metric_out += mod->metric;
else if (mod->type == metric_decrement)
- rinfo->metric -= mod->metric;
+ rinfo->metric_out-= mod->metric;
else if (mod->type == metric_absolute)
- rinfo->metric = mod->metric;
+ rinfo->metric_out = mod->metric;
- if (rinfo->metric < 1)
- rinfo->metric = 1;
- if (rinfo->metric > RIPNG_METRIC_INFINITY)
- rinfo->metric = RIPNG_METRIC_INFINITY;
+ if (rinfo->metric_out < 1)
+ rinfo->metric_out = 1;
+ if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
+ rinfo->metric_out = RIPNG_METRIC_INFINITY;
rinfo->metric_set = 1;
}
return RMAP_OKAY;
}
+/* set metric compilation. */
void *
route_set_metric_compile (char *arg)
{
@@ -158,7 +365,9 @@ route_set_metric_compile (char *arg)
if (metric == LONG_MAX || *endptr != '\0')
return NULL;
- if (metric < 0 || metric > RIPNG_METRIC_INFINITY)
+ /* Commented out by Hasso Tepper, to avoid problems in vtysh. */
+ /* if (metric < 0 || metric > RIPNG_METRIC_INFINITY) */
+ if (metric < 0)
return NULL;
mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
@@ -169,6 +378,7 @@ route_set_metric_compile (char *arg)
return mod;
}
+/* Free route map's compiled `set metric' value. */
void
route_set_metric_free (void *rule)
{
@@ -182,109 +392,158 @@ struct route_map_rule_cmd route_set_metric_cmd =
route_set_metric_compile,
route_set_metric_free,
};
-
-int
-ripng_route_match_add (struct vty *vty, struct route_map_index *index,
- char *command, char *arg)
+
+/* `set ipv6 next-hop local IP_ADDRESS' */
+
+/* Set nexthop to object. ojbect must be pointer to struct attr. */
+route_map_result_t
+route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
{
- int ret;
+ struct in6_addr *address;
+ struct ripng_info *rinfo;
- ret = route_map_add_match (index, command, arg);
- if (ret)
+ if(type == RMAP_RIPNG)
{
- switch (ret)
- {
- case RMAP_RULE_MISSING:
- vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
- return CMD_WARNING;
- break;
- case RMAP_COMPILE_ERROR:
- vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
- return CMD_WARNING;
- break;
- }
+ /* Fetch routemap's rule information. */
+ address = rule;
+ rinfo = object;
+
+ /* Set next hop value. */
+ rinfo->nexthop_out = *address;
}
- return CMD_SUCCESS;
+
+ return RMAP_OKAY;
}
-int
-ripng_route_match_delete (struct vty *vty, struct route_map_index *index,
- char *command, char *arg)
+/* Route map `ipv6 nexthop local' compile function. Given string is converted
+ to struct in6_addr structure. */
+void *
+route_set_ipv6_nexthop_local_compile (char *arg)
{
int ret;
+ struct in6_addr *address;
- ret = route_map_delete_match (index, command, arg);
- if (ret)
+ address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
+
+ ret = inet_pton (AF_INET6, arg, address);
+
+ if (ret == 0)
{
- switch (ret)
- {
- case RMAP_RULE_MISSING:
- vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
- return CMD_WARNING;
- break;
- case RMAP_COMPILE_ERROR:
- vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
- return CMD_WARNING;
- break;
- }
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+ return NULL;
}
- return CMD_SUCCESS;
+
+ return address;
}
-int
-ripng_route_set_add (struct vty *vty, struct route_map_index *index,
- char *command, char *arg)
+/* Free route map's compiled `ipv6 nexthop local' value. */
+void
+route_set_ipv6_nexthop_local_free (void *rule)
{
- int ret;
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
- ret = route_map_add_set (index, command, arg);
- if (ret)
+/* Route map commands for ipv6 nexthop local set. */
+struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd =
+{
+ "ipv6 next-hop local",
+ route_set_ipv6_nexthop_local,
+ route_set_ipv6_nexthop_local_compile,
+ route_set_ipv6_nexthop_local_free
+};
+
+/* `set tag TAG' */
+
+/* Set tag to object. ojbect must be pointer to struct attr. */
+route_map_result_t
+route_set_tag (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ u_short *tag;
+ struct ripng_info *rinfo;
+
+ if(type == RMAP_RIPNG)
{
- switch (ret)
- {
- case RMAP_RULE_MISSING:
- vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
- return CMD_WARNING;
- break;
- case RMAP_COMPILE_ERROR:
- vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
- return CMD_WARNING;
- break;
- }
+ /* Fetch routemap's rule information. */
+ tag = rule;
+ rinfo = object;
+
+ /* Set next hop value. */
+ rinfo->tag_out = *tag;
}
- return CMD_SUCCESS;
+
+ return RMAP_OKAY;
}
-int
-ripng_route_set_delete (struct vty *vty, struct route_map_index *index,
- char *command, char *arg)
+/* Route map `tag' compile function. Given string is converted
+ to u_short. */
+void *
+route_set_tag_compile (char *arg)
{
- int ret;
+ u_short *tag;
- ret = route_map_delete_set (index, command, arg);
- if (ret)
- {
- switch (ret)
- {
- case RMAP_RULE_MISSING:
- vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
- return CMD_WARNING;
- break;
- case RMAP_COMPILE_ERROR:
- vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
- return CMD_WARNING;
- break;
- }
- }
- return CMD_SUCCESS;
+ tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
+ *tag = atoi (arg);
+
+ return tag;
+}
+
+/* Free route map's compiled `ip nexthop' value. */
+void
+route_set_tag_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
}
+
+/* Route map commands for tag set. */
+struct route_map_rule_cmd route_set_tag_cmd =
+{
+ "tag",
+ route_set_tag,
+ route_set_tag_compile,
+ route_set_tag_free
+};
-#if 0
+#define MATCH_STR "Match values from routing table\n"
+#define SET_STR "Set values in destination routing protocol\n"
+
+DEFUN (match_metric,
+ match_metric_cmd,
+ "match metric <0-4294967295>",
+ MATCH_STR
+ "Match metric of route\n"
+ "Metric value\n")
+{
+ return ripng_route_match_add (vty, vty->index, "metric", argv[0]);
+}
+
+DEFUN (no_match_metric,
+ no_match_metric_cmd,
+ "no match metric",
+ NO_STR
+ MATCH_STR
+ "Match metric of route\n")
+{
+ if (argc == 0)
+ return ripng_route_match_delete (vty, vty->index, "metric", NULL);
+
+ return ripng_route_match_delete (vty, vty->index, "metric", argv[0]);
+}
+
+ALIAS (no_match_metric,
+ no_match_metric_val_cmd,
+ "no match metric <0-4294967295>",
+ NO_STR
+ MATCH_STR
+ "Match metric of route\n"
+ "Metric value\n")
+
DEFUN (match_interface,
match_interface_cmd,
"match interface WORD",
- "Match value\n"
- "Interface\n"
+ MATCH_STR
+ "Match first hop interface of route\n"
"Interface name\n")
{
return ripng_route_match_add (vty, vty->index, "interface", argv[0]);
@@ -292,51 +551,205 @@ DEFUN (match_interface,
DEFUN (no_match_interface,
no_match_interface_cmd,
+ "no match interface",
+ NO_STR
+ MATCH_STR
+ "Match first hop interface of route\n")
+{
+ if (argc == 0)
+ return ripng_route_match_delete (vty, vty->index, "interface", NULL);
+
+ return ripng_route_match_delete (vty, vty->index, "interface", argv[0]);
+}
+
+ALIAS (no_match_interface,
+ no_match_interface_val_cmd,
"no match interface WORD",
NO_STR
- "Match value\n"
- "Interface\n"
+ MATCH_STR
+ "Match first hop interface of route\n"
"Interface name\n")
+
+DEFUN (match_tag,
+ match_tag_cmd,
+ "match tag <0-65535>",
+ MATCH_STR
+ "Match tag of route\n"
+ "Metric value\n")
{
- return ripng_route_match_delete (vty, vty->index, "interface", argv[0]);
+ return ripng_route_match_add (vty, vty->index, "tag", argv[0]);
}
-#endif /* 0 */
+
+DEFUN (no_match_tag,
+ no_match_tag_cmd,
+ "no match tag",
+ NO_STR
+ MATCH_STR
+ "Match tag of route\n")
+{
+ if (argc == 0)
+ return ripng_route_match_delete (vty, vty->index, "tag", NULL);
+
+ return ripng_route_match_delete (vty, vty->index, "tag", argv[0]);
+}
+
+ALIAS (no_match_tag,
+ no_match_tag_val_cmd,
+ "no match tag <0-65535>",
+ NO_STR
+ MATCH_STR
+ "Match tag of route\n"
+ "Metric value\n")
+
+/* set functions */
DEFUN (set_metric,
set_metric_cmd,
"set metric <0-4294967295>",
"Set value\n"
- "Metric\n"
- "METRIC value\n")
+ "Metric value for destination routing protocol\n"
+ "Metric value\n")
{
return ripng_route_set_add (vty, vty->index, "metric", argv[0]);
}
DEFUN (no_set_metric,
no_set_metric_cmd,
- "no set metric <0-4294967295>",
+ "no set metric",
NO_STR
- "Set value\n"
- "Metric\n"
- "METRIC value\n")
+ SET_STR
+ "Metric value for destination routing protocol\n")
{
+ if (argc == 0)
+ return ripng_route_set_delete (vty, vty->index, "metric", NULL);
+
return ripng_route_set_delete (vty, vty->index, "metric", argv[0]);
}
+ALIAS (no_set_metric,
+ no_set_metric_val_cmd,
+ "no set metric <0-4294967295>",
+ NO_STR
+ SET_STR
+ "Metric value for destination routing protocol\n"
+ "Metric value\n")
+
+DEFUN (set_ipv6_nexthop_local,
+ set_ipv6_nexthop_local_cmd,
+ "set ipv6 next-hop local X:X::X:X",
+ SET_STR
+ IPV6_STR
+ "IPv6 next-hop address\n"
+ "IPv6 local address\n"
+ "IPv6 address of next hop\n")
+{
+ union sockunion su;
+ int ret;
+
+ ret = str2sockunion (argv[0], &su);
+ if (ret < 0)
+ {
+ vty_out (vty, "%% Malformed next-hop local address%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return ripng_route_set_add (vty, vty->index, "ipv6 next-hop local", argv[0]);
+}
+
+DEFUN (no_set_ipv6_nexthop_local,
+ no_set_ipv6_nexthop_local_cmd,
+ "no set ipv6 next-hop local",
+ NO_STR
+ SET_STR
+ IPV6_STR
+ "IPv6 next-hop address\n"
+ "IPv6 local address\n")
+{
+ if (argc == 0)
+ return ripng_route_set_delete (vty, vty->index, "ipv6 next-hop local", NULL);
+
+ return ripng_route_set_delete (vty, vty->index, "ipv6 next-hop local", argv[0]);
+}
+
+ALIAS (no_set_ipv6_nexthop_local,
+ no_set_ipv6_nexthop_local_val_cmd,
+ "no set ipv6 next-hop local X:X::X:X",
+ NO_STR
+ SET_STR
+ IPV6_STR
+ "IPv6 next-hop address\n"
+ "IPv6 local address\n"
+ "IPv6 address of next hop\n")
+
+DEFUN (set_tag,
+ set_tag_cmd,
+ "set tag <0-65535>",
+ SET_STR
+ "Tag value for routing protocol\n"
+ "Tag value\n")
+{
+ return ripng_route_set_add (vty, vty->index, "tag", argv[0]);
+}
+
+DEFUN (no_set_tag,
+ no_set_tag_cmd,
+ "no set tag",
+ NO_STR
+ SET_STR
+ "Tag value for routing protocol\n")
+{
+ if (argc == 0)
+ return ripng_route_set_delete (vty, vty->index, "tag", NULL);
+
+ return ripng_route_set_delete (vty, vty->index, "tag", argv[0]);
+}
+
+ALIAS (no_set_tag,
+ no_set_tag_val_cmd,
+ "no set tag <0-65535>",
+ NO_STR
+ SET_STR
+ "Tag value for routing protocol\n"
+ "Tag value\n")
+
+void
+ripng_route_map_reset ()
+{
+ /* XXX ??? */
+ ;
+}
+
void
ripng_route_map_init ()
{
route_map_init ();
route_map_init_vty ();
- /* route_map_install_match (&route_match_interface_cmd); */
+ route_map_install_match (&route_match_metric_cmd);
+ route_map_install_match (&route_match_interface_cmd);
+ route_map_install_match (&route_match_tag_cmd);
+
route_map_install_set (&route_set_metric_cmd);
+ route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
+ route_map_install_set (&route_set_tag_cmd);
- /*
+ install_element (RMAP_NODE, &match_metric_cmd);
+ install_element (RMAP_NODE, &no_match_metric_cmd);
+ install_element (RMAP_NODE, &no_match_metric_val_cmd);
install_element (RMAP_NODE, &match_interface_cmd);
install_element (RMAP_NODE, &no_match_interface_cmd);
- */
+ install_element (RMAP_NODE, &no_match_interface_val_cmd);
+ install_element (RMAP_NODE, &match_tag_cmd);
+ install_element (RMAP_NODE, &no_match_tag_cmd);
+ install_element (RMAP_NODE, &no_match_tag_val_cmd);
install_element (RMAP_NODE, &set_metric_cmd);
install_element (RMAP_NODE, &no_set_metric_cmd);
+ install_element (RMAP_NODE, &no_set_metric_val_cmd);
+ install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
+ install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
+ install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);
+ install_element (RMAP_NODE, &set_tag_cmd);
+ install_element (RMAP_NODE, &no_set_tag_cmd);
+ install_element (RMAP_NODE, &no_set_tag_val_cmd);
}
diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c
index 4d8a48d3..1af5e240 100644
--- a/ripngd/ripng_zebra.c
+++ b/ripngd/ripng_zebra.c
@@ -133,13 +133,19 @@ ripng_zebra_read_ipv6 (int command, struct zclient *zclient,
api.metric = 0;
if (command == ZEBRA_IPV6_ROUTE_ADD)
- ripng_redistribute_add (api.type, 0, &p, ifindex);
+ ripng_redistribute_add (api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, ifindex, &nexthop);
else
- ripng_redistribute_delete (api.type, 0, &p, ifindex);
+ ripng_redistribute_delete (api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, ifindex);
return 0;
}
+void
+ripng_zclient_reset ()
+{
+ zclient_reset (zclient);
+}
+
int
ripng_redistribute_unset (int type)
{
@@ -156,6 +162,12 @@ ripng_redistribute_unset (int type)
return CMD_SUCCESS;
}
+int
+ripng_redistribute_check (int type)
+{
+ return (zclient->redist[type]);
+}
+
void
ripng_redistribute_metric_set (int type, int metric)
{
@@ -163,11 +175,12 @@ ripng_redistribute_metric_set (int type, int metric)
ripng->route_map[type].metric = metric;
}
-void
+int
ripng_redistribute_metric_unset (int type)
{
ripng->route_map[type].metric_config = 0;
ripng->route_map[type].metric = 0;
+ return 0;
}
void
@@ -189,8 +202,42 @@ ripng_redistribute_routemap_unset (int type)
ripng->route_map[type].name = NULL;
ripng->route_map[type].map = NULL;
}
-
+/* Redistribution types */
+static struct {
+ int type;
+ int str_min_len;
+ char *str;
+} redist_type[] = {
+ {ZEBRA_ROUTE_KERNEL, 1, "kernel"},
+ {ZEBRA_ROUTE_CONNECT, 1, "connected"},
+ {ZEBRA_ROUTE_STATIC, 1, "static"},
+ {ZEBRA_ROUTE_OSPF6, 1, "ospf6"},
+ {ZEBRA_ROUTE_BGP, 1, "bgp"},
+ {0, 0, NULL}
+};
+
+void
+ripng_redistribute_clean ()
+{
+ int i;
+
+ for (i = 0; redist_type[i].str; i++)
+ {
+ if (zclient->redist[redist_type[i].type])
+ {
+ if (zclient->sock > 0)
+ zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE,
+ zclient->sock, redist_type[i].type);
+
+ zclient->redist[redist_type[i].type] = 0;
+
+ /* Remove the routes from RIPng table. */
+ ripng_redistribute_withdraw (redist_type[i].type);
+ }
+ }
+}
+
DEFUN (router_zebra,
router_zebra_cmd,
"router zebra",
@@ -236,513 +283,205 @@ DEFUN (no_ripng_redistribute_ripng,
return CMD_SUCCESS;
}
-DEFUN (ripng_redistribute_static,
- ripng_redistribute_static_cmd,
- "redistribute static",
- "Redistribute information from another routing protocol\n"
- "Static routes\n")
-{
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_STATIC);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ripng_redistribute_static,
- no_ripng_redistribute_static_cmd,
- "no redistribute static",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "Static routes\n")
-{
- ripng_redistribute_metric_unset (ZEBRA_ROUTE_STATIC);
- ripng_redistribute_routemap_unset (ZEBRA_ROUTE_STATIC);
- return ripng_redistribute_unset (ZEBRA_ROUTE_STATIC);
-}
-
-DEFUN (ripng_redistribute_kernel,
- ripng_redistribute_kernel_cmd,
- "redistribute kernel",
- "Redistribute information from another routing protocol\n"
- "Kernel routes\n")
-{
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_KERNEL);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ripng_redistribute_kernel,
- no_ripng_redistribute_kernel_cmd,
- "no redistribute kernel",
- NO_STR
+DEFUN (ripng_redistribute_type,
+ ripng_redistribute_type_cmd,
+ "redistribute (kernel|connected|static|ospf6|bgp)",
"Redistribute information from another routing protocol\n"
- "Kernel routes\n")
+ "Kernel routes\n"
+ "Connected\n"
+ "Static routes\n"
+ "Open Shortest Path First (OSPFv3)\n"
+ "Border Gateway Protocol (BGP)\n")
{
- ripng_redistribute_metric_unset (ZEBRA_ROUTE_KERNEL);
- ripng_redistribute_routemap_unset (ZEBRA_ROUTE_KERNEL);
- return ripng_redistribute_unset (ZEBRA_ROUTE_KERNEL);
-}
+ int i;
-DEFUN (ripng_redistribute_connected,
- ripng_redistribute_connected_cmd,
- "redistribute connected",
- "Redistribute information from another routing protocol\n"
- "Connected\n")
-{
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_CONNECT);
- return CMD_SUCCESS;
-}
+ for(i = 0; redist_type[i].str; i++)
+ {
+ if (strncmp (redist_type[i].str, argv[0],
+ redist_type[i].str_min_len) == 0)
+ {
+ zclient_redistribute_set (zclient, redist_type[i].type);
+ return CMD_SUCCESS;
+ }
+ }
-DEFUN (no_ripng_redistribute_connected,
- no_ripng_redistribute_connected_cmd,
- "no redistribute connected",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "Connected\n")
-{
- ripng_redistribute_metric_unset (ZEBRA_ROUTE_CONNECT);
- ripng_redistribute_routemap_unset (ZEBRA_ROUTE_CONNECT);
- return ripng_redistribute_unset (ZEBRA_ROUTE_CONNECT);
-}
+ vty_out(vty, "Invalid type %s%s", argv[0],
+ VTY_NEWLINE);
-DEFUN (ripng_redistribute_bgp,
- ripng_redistribute_bgp_cmd,
- "redistribute bgp",
- "Redistribute information from another routing protocol\n"
- "Border Gateway Protocol (BGP)\n")
-{
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_BGP);
- return CMD_SUCCESS;
+ return CMD_WARNING;
}
-DEFUN (no_ripng_redistribute_bgp,
- no_ripng_redistribute_bgp_cmd,
- "no redistribute bgp",
+DEFUN (no_ripng_redistribute_type,
+ no_ripng_redistribute_type_cmd,
+ "no redistribute (kernel|connected|static|ospf6|bgp)",
NO_STR
"Redistribute information from another routing protocol\n"
+ "Kernel routes\n"
+ "Connected\n"
+ "Static routes\n"
+ "Open Shortest Path First (OSPFv3)\n"
"Border Gateway Protocol (BGP)\n")
{
- ripng_redistribute_metric_unset (ZEBRA_ROUTE_BGP);
- ripng_redistribute_routemap_unset (ZEBRA_ROUTE_BGP);
- return ripng_redistribute_unset (ZEBRA_ROUTE_BGP);
-}
+ int i;
-DEFUN (ripng_redistribute_ospf6,
- ripng_redistribute_ospf6_cmd,
- "redistribute ospf6",
- "Redistribute information from another routing protocol\n"
- "IPv6 Open Shortest Path First (OSPFv3)\n")
-{
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_OSPF6);
- return CMD_SUCCESS;
-}
+ for (i = 0; redist_type[i].str; i++)
+ {
+ if (strncmp(redist_type[i].str, argv[0],
+ redist_type[i].str_min_len) == 0)
+ {
+ ripng_redistribute_metric_unset (redist_type[i].type);
+ ripng_redistribute_routemap_unset (redist_type[i].type);
+ return ripng_redistribute_unset (redist_type[i].type);
+ }
+ }
-DEFUN (no_ripng_redistribute_ospf6,
- no_ripng_redistribute_ospf6_cmd,
- "no redistribute ospf6",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "IPv6 Open Shortest Path First (OSPFv3)\n")
-{
- ripng_redistribute_metric_unset (ZEBRA_ROUTE_OSPF6);
- ripng_redistribute_routemap_unset (ZEBRA_ROUTE_OSPF6);
- return ripng_redistribute_unset (ZEBRA_ROUTE_OSPF6);
-}
+ vty_out(vty, "Invalid type %s%s", argv[0],
+ VTY_NEWLINE);
-DEFUN (ripng_redistribute_kernel_metric,
- ripng_redistribute_kernel_metric_cmd,
- "redistribute kernel metric <0-16>",
- "Redistribute information from another routing protocol\n"
- "Kernel routes\n"
- "Metric\n"
- "Metric value\n")
-{
- ripng_redistribute_metric_set (ZEBRA_ROUTE_KERNEL, atoi (argv[0]));
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_KERNEL);
- return CMD_SUCCESS;
+ return CMD_WARNING;
}
-ALIAS (no_ripng_redistribute_kernel,
- no_ripng_redistribute_kernel_metric_cmd,
- "no redistribute kernel metric",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "Kernel routes\n"
- "Metric\n")
-ALIAS (no_ripng_redistribute_kernel,
- no_ripng_redistribute_kernel_metric_val_cmd,
- "no redistribute kernel metric <0-16>",
- NO_STR
+DEFUN (ripng_redistribute_type_metric,
+ ripng_redistribute_type_metric_cmd,
+ "redistribute (kernel|connected|static|ospf6|bgp) metric <0-16>",
"Redistribute information from another routing protocol\n"
"Kernel routes\n"
- "Metric\n"
- "Metric value\n")
-
-DEFUN (ripng_redistribute_connected_metric,
- ripng_redistribute_connected_metric_cmd,
- "redistribute connected metric <0-16>",
- "Redistribute information from another routing protocol\n"
"Connected\n"
- "Metric\n"
- "Metric value\n")
-{
- ripng_redistribute_metric_set (ZEBRA_ROUTE_CONNECT, atoi (argv[0]));
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_CONNECT);
- return CMD_SUCCESS;
-}
-
-ALIAS (no_ripng_redistribute_connected,
- no_ripng_redistribute_connected_metric_cmd,
- "no redistribute connected metric",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "Connected\n"
- "Metric\n")
-
-ALIAS (no_ripng_redistribute_connected,
- no_ripng_redistribute_connected_metric_val_cmd,
- "no redistribute connected metric <0-16>",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "Connected\n"
- "Metric\n"
- "Metric value\n")
-
-DEFUN (ripng_redistribute_static_metric,
- ripng_redistribute_static_metric_cmd,
- "redistribute static metric <0-16>",
- "Redistribute information from another routing protocol\n"
"Static routes\n"
+ "Open Shortest Path First (OSPFv3)\n"
+ "Border Gateway Protocol (BGP)\n"
"Metric\n"
"Metric value\n")
{
- ripng_redistribute_metric_set (ZEBRA_ROUTE_STATIC, atoi (argv[0]));
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_STATIC);
- return CMD_SUCCESS;
-}
-
-ALIAS (no_ripng_redistribute_static,
- no_ripng_redistribute_static_metric_cmd,
- "no redistribute static metric",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "Static routes\n"
- "Metric\n")
+ int i;
+ int metric;
-ALIAS (no_ripng_redistribute_static,
- no_ripng_redistribute_static_metric_val_cmd,
- "no redistribute static metric <0-16>",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "Static routes\n"
- "Metric\n"
- "Metric value\n")
+ metric = atoi (argv[1]);
-DEFUN (ripng_redistribute_ospf6_metric,
- ripng_redistribute_ospf6_metric_cmd,
- "redistribute ospf6 metric <0-16>",
- "Redistribute information from another routing protocol\n"
- "IPv6 Open Shortest Path First (OSPFv3)\n"
- "Metric\n"
- "Metric value\n")
-{
- ripng_redistribute_metric_set (ZEBRA_ROUTE_OSPF6, atoi (argv[0]));
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_OSPF6);
- return CMD_SUCCESS;
-}
+ for (i = 0; redist_type[i].str; i++) {
+ if (strncmp(redist_type[i].str, argv[0],
+ redist_type[i].str_min_len) == 0)
+ {
+ ripng_redistribute_metric_set (redist_type[i].type, metric);
+ zclient_redistribute_set (zclient, redist_type[i].type);
+ return CMD_SUCCESS;
+ }
+ }
-ALIAS (no_ripng_redistribute_ospf6,
- no_ripng_redistribute_ospf6_metric_cmd,
- "no redistribute ospf6 metric",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "IPv6 Open Shortest Path First (OSPFv3)\n"
- "Metric\n")
+ vty_out(vty, "Invalid type %s%s", argv[0],
+ VTY_NEWLINE);
-ALIAS (no_ripng_redistribute_ospf6,
- no_ripng_redistribute_ospf6_metric_val_cmd,
- "no redistribute ospf6 metric <0-16>",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "IPv6 Open Shortest Path First (OSPFv3)\n"
- "Metric\n"
- "Metric value\n")
-
-DEFUN (ripng_redistribute_bgp_metric,
- ripng_redistribute_bgp_metric_cmd,
- "redistribute bgp metric <0-16>",
- "Redistribute information from another routing protocol\n"
- "Border Gateway Protocol (BGP)\n"
- "Metric\n"
- "Metric value\n")
-{
- ripng_redistribute_metric_set (ZEBRA_ROUTE_BGP, atoi (argv[0]));
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_BGP);
- return CMD_SUCCESS;
+ return CMD_WARNING;
}
-ALIAS (no_ripng_redistribute_bgp,
- no_ripng_redistribute_bgp_metric_cmd,
- "no redistribute bgp metric",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "Border Gateway Protocol (BGP)\n"
- "Metric\n")
-
-ALIAS (no_ripng_redistribute_bgp,
- no_ripng_redistribute_bgp_metric_val_cmd,
- "no redistribute bgp metric <0-16>",
+ALIAS (no_ripng_redistribute_type,
+ no_ripng_redistribute_type_metric_cmd,
+ "no redistribute (kernel|connected|static|ospf6|bgp) metric <0-16>",
NO_STR
"Redistribute information from another routing protocol\n"
+ "Kernel routes\n"
+ "Connected\n"
+ "Static routes\n"
+ "Open Shortest Path First (OSPFv3)\n"
"Border Gateway Protocol (BGP)\n"
"Metric\n"
"Metric value\n")
-DEFUN (ripng_redistribute_kernel_routemap,
- ripng_redistribute_kernel_routemap_cmd,
- "redistribute kernel route-map WORD",
- "Redistribute information from another routing protocol\n"
- "Kernel routes\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-{
- ripng_redistribute_routemap_set (ZEBRA_ROUTE_KERNEL, argv[0]);
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_KERNEL);
- return CMD_SUCCESS;
-}
-
-ALIAS (no_ripng_redistribute_kernel,
- no_ripng_redistribute_kernel_routemap_cmd,
- "no redistribute kernel route-map WORD",
- NO_STR
+DEFUN (ripng_redistribute_type_routemap,
+ ripng_redistribute_type_routemap_cmd,
+ "redistribute (kernel|connected|static|ospf6|bgp) route-map WORD",
"Redistribute information from another routing protocol\n"
"Kernel routes\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-
-DEFUN (ripng_redistribute_connected_routemap,
- ripng_redistribute_connected_routemap_cmd,
- "redistribute connected route-map WORD",
- "Redistribute information from another routing protocol\n"
"Connected\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-{
- ripng_redistribute_routemap_set (ZEBRA_ROUTE_CONNECT, argv[0]);
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_CONNECT);
- return CMD_SUCCESS;
-}
-
-ALIAS (no_ripng_redistribute_connected,
- no_ripng_redistribute_connected_routemap_cmd,
- "no redistribute connected route-map WORD",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "Connected\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-
-DEFUN (ripng_redistribute_static_routemap,
- ripng_redistribute_static_routemap_cmd,
- "redistribute static route-map WORD",
- "Redistribute information from another routing protocol\n"
- "Static routes\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-{
- ripng_redistribute_routemap_set (ZEBRA_ROUTE_STATIC, argv[0]);
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_STATIC);
- return CMD_SUCCESS;
-}
-
-ALIAS (no_ripng_redistribute_static,
- no_ripng_redistribute_static_routemap_cmd,
- "no redistribute static route-map WORD",
- NO_STR
- "Redistribute information from another routing protocol\n"
"Static routes\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-
-DEFUN (ripng_redistribute_ospf6_routemap,
- ripng_redistribute_ospf6_routemap_cmd,
- "redistribute ospf6 route-map WORD",
- "Redistribute information from another routing protocol\n"
- "IPv6 Open Shortest Path First (OSPFv3)\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-{
- ripng_redistribute_routemap_set (ZEBRA_ROUTE_OSPF6, argv[0]);
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_OSPF6);
- return CMD_SUCCESS;
-}
-
-ALIAS (no_ripng_redistribute_ospf6,
- no_ripng_redistribute_ospf6_routemap_cmd,
- "no redistribute ospf6 route-map WORD",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "IPv6 Open Shortest Path First (OSPFv3)\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-
-DEFUN (ripng_redistribute_bgp_routemap,
- ripng_redistribute_bgp_routemap_cmd,
- "redistribute bgp route-map WORD",
- "Redistribute information from another routing protocol\n"
+ "Open Shortest Path First (OSPFv3)\n"
"Border Gateway Protocol (BGP)\n"
"Route map reference\n"
"Pointer to route-map entries\n")
{
- ripng_redistribute_routemap_set (ZEBRA_ROUTE_BGP, argv[0]);
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_BGP);
- return CMD_SUCCESS;
-}
+ int i;
-ALIAS (no_ripng_redistribute_bgp,
- no_ripng_redistribute_bgp_routemap_cmd,
- "no redistribute bgp route-map WORD",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "Border Gateway Protocol (BGP)\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
+ for (i = 0; redist_type[i].str; i++) {
+ if (strncmp(redist_type[i].str, argv[0],
+ redist_type[i].str_min_len) == 0)
+ {
+ ripng_redistribute_routemap_set (redist_type[i].type, argv[1]);
+ zclient_redistribute_set (zclient, redist_type[i].type);
+ return CMD_SUCCESS;
+ }
+ }
-DEFUN (ripng_redistribute_kernel_metric_routemap,
- ripng_redistribute_kernel_metric_routemap_cmd,
- "redistribute kernel metric <0-16> route-map WORD",
- "Redistribute information from another routing protocol\n"
- "Kernel routes\n"
- "Metric\n"
- "Metric value\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-{
- ripng_redistribute_metric_set (ZEBRA_ROUTE_KERNEL, atoi (argv[0]));
- ripng_redistribute_routemap_set (ZEBRA_ROUTE_KERNEL, argv[1]);
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_KERNEL);
- return CMD_SUCCESS;
+ vty_out(vty, "Invalid type %s%s", argv[0],
+ VTY_NEWLINE);
+
+ return CMD_WARNING;
}
-ALIAS (no_ripng_redistribute_kernel,
- no_ripng_redistribute_kernel_metric_routemap_cmd,
- "no redistribute kernel metric <0-16> route-map WORD",
+ALIAS (no_ripng_redistribute_type,
+ no_ripng_redistribute_type_routemap_cmd,
+ "no redistribute (kernel|connected|static|ospf6|bgp) route-map WORD",
NO_STR
"Redistribute information from another routing protocol\n"
"Kernel routes\n"
- "Metric\n"
- "Metric value\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-
-DEFUN (ripng_redistribute_connected_metric_routemap,
- ripng_redistribute_connected_metric_routemap_cmd,
- "redistribute connected metric <0-16> route-map WORD",
- "Redistribute information from another routing protocol\n"
"Connected\n"
- "Metric\n"
- "Metric value\n"
+ "Static routes\n"
+ "Open Shortest Path First (OSPFv3)\n"
+ "Border Gateway Protocol (BGP)\n"
"Route map reference\n"
"Pointer to route-map entries\n")
-{
- ripng_redistribute_metric_set (ZEBRA_ROUTE_CONNECT, atoi (argv[0]));
- ripng_redistribute_routemap_set (ZEBRA_ROUTE_CONNECT, argv[1]);
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_CONNECT);
- return CMD_SUCCESS;
-}
-ALIAS (no_ripng_redistribute_connected,
- no_ripng_redistribute_connected_metric_routemap_cmd,
- "no redistribute connected metric <0-16> route-map WORD",
- NO_STR
+DEFUN (ripng_redistribute_type_metric_routemap,
+ ripng_redistribute_type_metric_routemap_cmd,
+ "redistribute (kernel|connected|static|ospf6|bgp) metric <0-16> route-map WORD",
"Redistribute information from another routing protocol\n"
+ "Kernel routes\n"
"Connected\n"
- "Metric\n"
- "Metric value\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-
-DEFUN (ripng_redistribute_static_metric_routemap,
- ripng_redistribute_static_metric_routemap_cmd,
- "redistribute static metric <0-16> route-map WORD",
- "Redistribute information from another routing protocol\n"
"Static routes\n"
+ "Open Shortest Path First (OSPFv3)\n"
+ "Border Gateway Protocol (BGP)\n"
"Metric\n"
"Metric value\n"
"Route map reference\n"
"Pointer to route-map entries\n")
{
- ripng_redistribute_metric_set (ZEBRA_ROUTE_STATIC, atoi (argv[0]));
- ripng_redistribute_routemap_set (ZEBRA_ROUTE_STATIC, argv[1]);
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_STATIC);
- return CMD_SUCCESS;
-}
+ int i;
+ int metric;
-ALIAS (no_ripng_redistribute_static,
- no_ripng_redistribute_static_metric_routemap_cmd,
- "no redistribute static metric <0-16> route-map WORD",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "Static routes\n"
- "Metric\n"
- "Metric value\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
+ metric = atoi (argv[1]);
-DEFUN (ripng_redistribute_ospf6_metric_routemap,
- ripng_redistribute_ospf6_metric_routemap_cmd,
- "redistribute ospf6 metric <0-16> route-map WORD",
- "Redistribute information from another routing protocol\n"
- "IPv6 Open Shortest Path First (OSPFv3)\n"
- "Metric\n"
- "Metric value\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-{
- ripng_redistribute_metric_set (ZEBRA_ROUTE_OSPF6, atoi (argv[0]));
- ripng_redistribute_routemap_set (ZEBRA_ROUTE_OSPF6, argv[1]);
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_OSPF6);
- return CMD_SUCCESS;
-}
+ for (i = 0; redist_type[i].str; i++) {
+ if (strncmp(redist_type[i].str, argv[0],
+ redist_type[i].str_min_len) == 0)
+ {
+ ripng_redistribute_metric_set (redist_type[i].type, metric);
+ ripng_redistribute_routemap_set (redist_type[i].type, argv[2]);
+ zclient_redistribute_set (zclient, redist_type[i].type);
+ return CMD_SUCCESS;
+ }
+ }
-ALIAS (no_ripng_redistribute_ospf6,
- no_ripng_redistribute_ospf6_metric_routemap_cmd,
- "no redistribute ospf6 metric <0-16> route-map WORD",
- NO_STR
- "Redistribute information from another routing protocol\n"
- "IPv6 Open Shortest Path First (OSPFv3)\n"
- "Metric\n"
- "Metric value\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
+ vty_out(vty, "Invalid type %s%s", argv[0],
+ VTY_NEWLINE);
-DEFUN (ripng_redistribute_bgp_metric_routemap,
- ripng_redistribute_bgp_metric_routemap_cmd,
- "redistribute bgp metric <0-16> route-map WORD",
- "Redistribute information from another routing protocol\n"
- "Border Gateway Protocol (BGP)\n"
- "Metric\n"
- "Metric value\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-{
- ripng_redistribute_metric_set (ZEBRA_ROUTE_BGP, atoi (argv[0]));
- ripng_redistribute_routemap_set (ZEBRA_ROUTE_BGP, argv[1]);
- zclient_redistribute_set (zclient, ZEBRA_ROUTE_BGP);
- return CMD_SUCCESS;
+ return CMD_WARNING;
}
-ALIAS (no_ripng_redistribute_bgp,
- no_ripng_redistribute_bgp_metric_routemap_cmd,
- "no redistribute bgp metric <0-16> route-map WORD",
+ALIAS (no_ripng_redistribute_type,
+ no_ripng_redistribute_type_metric_routemap_cmd,
+ "no redistribute (kernel|connected|static|ospf6|bgp) metric <0-16> route-map WORD",
NO_STR
"Redistribute information from another routing protocol\n"
+ "Kernel routes\n"
+ "Connected\n"
+ "Static routes\n"
+ "Open Shortest Path First (OSPFv3)\n"
"Border Gateway Protocol (BGP)\n"
- "Metric\n"
- "Metric value\n"
"Route map reference\n"
"Pointer to route-map entries\n")
void
-ripng_redistribute_write (struct vty *vty)
+ripng_redistribute_write (struct vty *vty, int config_mode)
{
int i;
char *str[] = { "system", "kernel", "connected", "static", "rip",
@@ -751,24 +490,29 @@ ripng_redistribute_write (struct vty *vty)
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
if (i != zclient->redist_default && zclient->redist[i])
{
- if (ripng->route_map[i].metric_config)
- {
- if (ripng->route_map[i].name)
- vty_out (vty, " redistribute %s metric %d route-map %s%s",
- str[i], ripng->route_map[i].metric,
- ripng->route_map[i].name, VTY_NEWLINE);
- else
- vty_out (vty, " redistribute %s metric %d%s",
- str[i], ripng->route_map[i].metric, VTY_NEWLINE);
- }
- else
- {
- if (ripng->route_map[i].name)
- vty_out (vty, " redistribute %s route-map %s%s",
- str[i], ripng->route_map[i].name, VTY_NEWLINE);
- else
- vty_out (vty, " redistribute %s%s", str[i], VTY_NEWLINE);
- }
+ if (config_mode)
+ {
+ if (ripng->route_map[i].metric_config)
+ {
+ if (ripng->route_map[i].name)
+ vty_out (vty, " redistribute %s metric %d route-map %s%s",
+ str[i], ripng->route_map[i].metric,
+ ripng->route_map[i].name, VTY_NEWLINE);
+ else
+ vty_out (vty, " redistribute %s metric %d%s",
+ str[i], ripng->route_map[i].metric, VTY_NEWLINE);
+ }
+ else
+ {
+ if (ripng->route_map[i].name)
+ vty_out (vty, " redistribute %s route-map %s%s",
+ str[i], ripng->route_map[i].name, VTY_NEWLINE);
+ else
+ vty_out (vty, " redistribute %s%s", str[i], VTY_NEWLINE);
+ }
+ }
+ else
+ vty_out (vty, " %s", str[i]);
}
}
@@ -823,55 +567,14 @@ zebra_init ()
install_default (ZEBRA_NODE);
install_element (ZEBRA_NODE, &ripng_redistribute_ripng_cmd);
install_element (ZEBRA_NODE, &no_ripng_redistribute_ripng_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_static_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_static_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_kernel_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_kernel_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_connected_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_connected_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_bgp_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_bgp_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_ospf6_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_ospf6_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_kernel_metric_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_kernel_metric_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_kernel_metric_val_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_connected_metric_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_connected_metric_cmd);
- install_element (RIPNG_NODE,
- &no_ripng_redistribute_connected_metric_val_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_static_metric_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_static_metric_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_static_metric_val_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_ospf6_metric_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_ospf6_metric_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_ospf6_metric_val_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_bgp_metric_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_bgp_metric_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_bgp_metric_val_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_kernel_routemap_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_kernel_routemap_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_connected_routemap_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_connected_routemap_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_static_routemap_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_static_routemap_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_ospf6_routemap_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_ospf6_routemap_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_bgp_routemap_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_bgp_routemap_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_kernel_metric_routemap_cmd);
- install_element (RIPNG_NODE,
- &no_ripng_redistribute_kernel_metric_routemap_cmd);
- install_element (RIPNG_NODE,
- &ripng_redistribute_connected_metric_routemap_cmd);
- install_element (RIPNG_NODE,
- &no_ripng_redistribute_connected_metric_routemap_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_static_metric_routemap_cmd);
- install_element (RIPNG_NODE,
- &no_ripng_redistribute_static_metric_routemap_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_ospf6_metric_routemap_cmd);
- install_element (RIPNG_NODE,
- &no_ripng_redistribute_ospf6_metric_routemap_cmd);
- install_element (RIPNG_NODE, &ripng_redistribute_bgp_metric_routemap_cmd);
- install_element (RIPNG_NODE, &no_ripng_redistribute_bgp_metric_routemap_cmd);
+
+ /* Install command elements to ripng node */
+ install_element (RIPNG_NODE, &ripng_redistribute_type_cmd);
+ install_element (RIPNG_NODE, &ripng_redistribute_type_routemap_cmd);
+ install_element (RIPNG_NODE, &ripng_redistribute_type_metric_cmd);
+ install_element (RIPNG_NODE, &ripng_redistribute_type_metric_routemap_cmd);
+ install_element (RIPNG_NODE, &no_ripng_redistribute_type_cmd);
+ install_element (RIPNG_NODE, &no_ripng_redistribute_type_routemap_cmd);
+ install_element (RIPNG_NODE, &no_ripng_redistribute_type_metric_cmd);
+ install_element (RIPNG_NODE, &no_ripng_redistribute_type_metric_routemap_cmd);
}
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index 0f12785d..df5f31cf 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -21,9 +21,6 @@
#include <zebra.h>
-/* For struct udphdr. */
-#include <netinet/udp.h>
-
#include "prefix.h"
#include "filter.h"
#include "log.h"
@@ -43,8 +40,7 @@
#include "ripngd/ripngd.h"
#include "ripngd/ripng_route.h"
#include "ripngd/ripng_debug.h"
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
+#include "ripngd/ripng_nexthop.h"
/* RIPng structure which includes many parameters related to RIPng
protocol. If ripng couldn't active or ripng doesn't configured,
@@ -55,15 +51,13 @@ enum
{
ripng_all_route,
ripng_changed_route,
- ripng_split_horizon,
- ripng_no_split_horizon
};
extern struct zebra_privs_t ripngd_privs;
/* Prototypes. */
void
-ripng_output_process (struct interface *, struct sockaddr_in6 *, int, int);
+ripng_output_process (struct interface *, struct sockaddr_in6 *, int);
int
ripng_triggered_update (struct thread *);
@@ -90,6 +84,12 @@ inet6_ntop (struct in6_addr *p)
return buf;
}
+int
+ripng_route_rte (struct ripng_info *rinfo)
+{
+ return (rinfo->type == ZEBRA_ROUTE_RIPNG && rinfo->sub_type == RIPNG_ROUTE_RTE);
+}
+
/* Allocate new ripng information. */
struct ripng_info *
ripng_info_new ()
@@ -185,12 +185,12 @@ ripng_send_packet (caddr_t buf, int bufsize, struct sockaddr_in6 *to,
struct in6_pktinfo *pkt;
struct sockaddr_in6 addr;
-#ifdef DEBUG
- if (to)
- zlog_info ("DEBUG RIPng: send to %s", inet6_ntop (&to->sin6_addr));
- zlog_info ("DEBUG RIPng: send if %s", ifp->name);
- zlog_info ("DEBUG RIPng: send packet size %d", bufsize);
-#endif /* DEBUG */
+ if (IS_RIPNG_DEBUG_SEND) {
+ if (to)
+ zlog_info ("send to %s", inet6_ntop (&to->sin6_addr));
+ zlog_info (" send interface %s", ifp->name);
+ zlog_info (" send packet size %d", bufsize);
+ }
memset (&addr, 0, sizeof (struct sockaddr_in6));
addr.sin6_family = AF_INET6;
@@ -232,8 +232,13 @@ ripng_send_packet (caddr_t buf, int bufsize, struct sockaddr_in6 *to,
ret = sendmsg (ripng->sock, &msg, 0);
- if (ret < 0)
- zlog_warn ("RIPng send fail on %s: %s", ifp->name, strerror (errno));
+ if (ret < 0) {
+ if (to)
+ zlog_err ("RIPng send fail on %s to %s: %s", ifp->name,
+ inet6_ntop (&to->sin6_addr), strerror (errno));
+ else
+ zlog_err ("RIPng send fail on %s: %s", ifp->name, strerror (errno));
+ }
return ret;
}
@@ -430,14 +435,6 @@ ripng_garbage_collect (struct thread *t)
/* Get route_node pointer. */
rp = rinfo->rp;
- /* Delete this route from the kernel. */
- ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p,
- &rinfo->nexthop, rinfo->ifindex);
- rinfo->flags &= ~RIPNG_RTF_FIB;
-
- /* Aggregate count decrement. */
- ripng_aggregate_decrement (rp, rinfo);
-
/* Unlock route_node. */
rp->info = NULL;
route_unlock_node (rp);
@@ -465,9 +462,16 @@ ripng_timeout (struct thread *t)
RIPNG_TIMER_ON (rinfo->t_garbage_collect, ripng_garbage_collect,
ripng->garbage_time);
+ /* Delete this route from the kernel. */
+ ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop,
+ rinfo->ifindex);
/* - The metric for the route is set to 16 (infinity). This causes
the route to be removed from service. */
rinfo->metric = RIPNG_METRIC_INFINITY;
+ rinfo->flags &= ~RIPNG_RTF_FIB;
+
+ /* Aggregate count decrement. */
+ ripng_aggregate_decrement (rp, rinfo);
/* - The route change flag is to indicate that this entry has been
changed. */
@@ -489,12 +493,154 @@ ripng_timeout_update (struct ripng_info *rinfo)
}
}
+int
+ripng_incoming_filter (struct prefix_ipv6 *p, struct ripng_interface *ri)
+{
+ struct distribute *dist;
+ struct access_list *alist;
+ struct prefix_list *plist;
+
+ /* Input distribute-list filtering. */
+ if (ri->list[RIPNG_FILTER_IN])
+ {
+ if (access_list_apply (ri->list[RIPNG_FILTER_IN],
+ (struct prefix *) p) == FILTER_DENY)
+ {
+ if (IS_RIPNG_DEBUG_PACKET)
+ zlog_info ("%s/%d filtered by distribute in",
+ inet6_ntop (&p->prefix), p->prefixlen);
+ return -1;
+ }
+ }
+ if (ri->prefix[RIPNG_FILTER_IN])
+ {
+ if (prefix_list_apply (ri->prefix[RIPNG_FILTER_IN],
+ (struct prefix *) p) == PREFIX_DENY)
+ {
+ if (IS_RIPNG_DEBUG_PACKET)
+ zlog_info ("%s/%d filtered by prefix-list in",
+ inet6_ntop (&p->prefix), p->prefixlen);
+ return -1;
+ }
+ }
+
+ /* All interface filter check. */
+ dist = distribute_lookup (NULL);
+ if (dist)
+ {
+ if (dist->list[DISTRIBUTE_IN])
+ {
+ alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
+
+ if (alist)
+ {
+ if (access_list_apply (alist,
+ (struct prefix *) p) == FILTER_DENY)
+ {
+ if (IS_RIPNG_DEBUG_PACKET)
+ zlog_info ("%s/%d filtered by distribute in",
+ inet6_ntop (&p->prefix), p->prefixlen);
+ return -1;
+ }
+ }
+ }
+ if (dist->prefix[DISTRIBUTE_IN])
+ {
+ plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
+
+ if (plist)
+ {
+ if (prefix_list_apply (plist,
+ (struct prefix *) p) == PREFIX_DENY)
+ {
+ if (IS_RIPNG_DEBUG_PACKET)
+ zlog_info ("%s/%d filtered by prefix-list in",
+ inet6_ntop (&p->prefix), p->prefixlen);
+ return -1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int
+ripng_outgoing_filter (struct prefix_ipv6 *p, struct ripng_interface *ri)
+{
+ struct distribute *dist;
+ struct access_list *alist;
+ struct prefix_list *plist;
+
+ if (ri->list[RIPNG_FILTER_OUT])
+ {
+ if (access_list_apply (ri->list[RIPNG_FILTER_OUT],
+ (struct prefix *) p) == FILTER_DENY)
+ {
+ if (IS_RIPNG_DEBUG_PACKET)
+ zlog_info ("%s/%d is filtered by distribute out",
+ inet6_ntop (&p->prefix), p->prefixlen);
+ return -1;
+ }
+ }
+ if (ri->prefix[RIPNG_FILTER_OUT])
+ {
+ if (prefix_list_apply (ri->prefix[RIPNG_FILTER_OUT],
+ (struct prefix *) p) == PREFIX_DENY)
+ {
+ if (IS_RIPNG_DEBUG_PACKET)
+ zlog_info ("%s/%d is filtered by prefix-list out",
+ inet6_ntop (&p->prefix), p->prefixlen);
+ return -1;
+ }
+ }
+
+ /* All interface filter check. */
+ dist = distribute_lookup (NULL);
+ if (dist)
+ {
+ if (dist->list[DISTRIBUTE_OUT])
+ {
+ alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
+
+ if (alist)
+ {
+ if (access_list_apply (alist,
+ (struct prefix *) p) == FILTER_DENY)
+ {
+ if (IS_RIPNG_DEBUG_PACKET)
+ zlog_info ("%s/%d filtered by distribute out",
+ inet6_ntop (&p->prefix), p->prefixlen);
+ return -1;
+ }
+ }
+ }
+ if (dist->prefix[DISTRIBUTE_OUT])
+ {
+ plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
+
+ if (plist)
+ {
+ if (prefix_list_apply (plist,
+ (struct prefix *) p) == PREFIX_DENY)
+ {
+ if (IS_RIPNG_DEBUG_PACKET)
+ zlog_info ("%s/%d filtered by prefix-list out",
+ inet6_ntop (&p->prefix), p->prefixlen);
+ return -1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
/* Process RIPng route according to RFC2080. */
void
ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
struct ripng_nexthop *ripng_nexthop,
struct interface *ifp)
{
+ int ret;
struct prefix_ipv6 p;
struct route_node *rp;
struct ripng_info *rinfo;
@@ -518,26 +664,9 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
/* Apply input filters. */
ri = ifp->info;
- if (ri->list[RIPNG_FILTER_IN])
- {
- if (access_list_apply (ri->list[RIPNG_FILTER_IN], &p) == FILTER_DENY)
- {
- if (IS_RIPNG_DEBUG_PACKET)
- zlog_info ("RIPng %s/%d is filtered by distribute in",
- inet6_ntop (&p.prefix), p.prefixlen);
- return;
- }
- }
- if (ri->prefix[RIPNG_FILTER_IN])
- {
- if (prefix_list_apply (ri->prefix[RIPNG_FILTER_IN], &p) == PREFIX_DENY)
- {
- if (IS_RIPNG_DEBUG_PACKET)
- zlog_info ("RIPng %s/%d is filtered by prefix-list in",
- inet6_ntop (&p.prefix), p.prefixlen);
- return;
- }
- }
+ ret = ripng_incoming_filter (&p, ri);
+ if (ret < 0)
+ return;
/* Modify entry. */
if (ri->routemap[RIPNG_FILTER_IN])
@@ -546,7 +675,17 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
struct ripng_info newinfo;
memset (&newinfo, 0, sizeof (struct ripng_info));
+ newinfo.type = ZEBRA_ROUTE_RIPNG;
+ newinfo.sub_type = RIPNG_ROUTE_RTE;
+ if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
+ newinfo.nexthop = ripng_nexthop->address;
+ else
+ newinfo.nexthop = from->sin6_addr;
+ newinfo.from = from->sin6_addr;
+ newinfo.ifindex = ifp->ifindex;
newinfo.metric = rte->metric;
+ newinfo.metric_out = rte->metric; /* XXX */
+ newinfo.tag = ntohs(rte->tag); /* XXX */
ret = route_map_apply (ri->routemap[RIPNG_FILTER_IN],
(struct prefix *)&p, RMAP_RIPNG, &newinfo);
@@ -559,9 +698,45 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
return;
}
- rte->metric = newinfo.metric;
+ /* Get back the object */
+ if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) {
+ if (! IPV6_ADDR_SAME(&newinfo.nexthop, &ripng_nexthop->address) ) {
+ /* the nexthop get changed by the routemap */
+ if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop))
+ ripng_nexthop->address = newinfo.nexthop;
+ else
+ ripng_nexthop->address = in6addr_any;
+ }
+ } else {
+ if (! IPV6_ADDR_SAME(&newinfo.nexthop, &from->sin6_addr) ) {
+ /* the nexthop get changed by the routemap */
+ if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) {
+ ripng_nexthop->flag = RIPNG_NEXTHOP_ADDRESS;
+ ripng_nexthop->address = newinfo.nexthop;
+ }
+ }
+ }
+ rte->tag = htons(newinfo.tag_out); /* XXX */
+ rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
}
+ /* Once the entry has been validated, update the metric by
+ * adding the cost of the network on wich the message
+ * arrived. If the result is greater than infinity, use infinity
+ * (RFC2453 Sec. 3.9.2)
+ **/
+
+ /* Zebra ripngd can handle offset-list in. */
+ ret = ripng_offset_list_apply_in (&p, ifp, &rte->metric);
+
+ /* If offset-list does not modify the metric use interface's
+ * one. */
+ if (! ret)
+ rte->metric += ifp->metric;
+
+ if (rte->metric > RIPNG_METRIC_INFINITY)
+ rte->metric = RIPNG_METRIC_INFINITY;
+
/* Set nexthop pointer. */
if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
nexthop = &ripng_nexthop->address;
@@ -571,6 +746,23 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
/* Lookup RIPng routing table. */
rp = route_node_get (ripng->table, (struct prefix *) &p);
+ /* Sanity check */
+ rinfo = rp->info;
+ if (rinfo)
+ {
+ /* Redistributed route check. */
+ if (rinfo->type != ZEBRA_ROUTE_RIPNG
+ && rinfo->metric != RIPNG_METRIC_INFINITY)
+ return;
+
+ /* Local static route. */
+ if (rinfo->type == ZEBRA_ROUTE_RIPNG
+ && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) ||
+ (rinfo->sub_type == RIPNG_ROUTE_DEFAULT))
+ && rinfo->metric != RIPNG_METRIC_INFINITY)
+ return;
+ }
+
if (rp->info == NULL)
{
/* Now, check to see whether there is already an explicit route
@@ -648,17 +840,45 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
oldmetric = rinfo->metric;
rinfo->metric = rte->metric;
rinfo->tag = ntohs (rte->tag);
+ IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr);
+ rinfo->ifindex = ifp->ifindex;
- if (! IN6_ARE_ADDR_EQUAL (&rinfo->nexthop, nexthop))
+ /* Should a new route to this network be established
+ while the garbage-collection timer is running, the
+ new route will replace the one that is about to be
+ deleted. In this case the garbage-collection timer
+ must be cleared. */
+
+ if (oldmetric == RIPNG_METRIC_INFINITY &&
+ rinfo->metric < RIPNG_METRIC_INFINITY)
+ {
+ rinfo->type = ZEBRA_ROUTE_RIPNG;
+ rinfo->sub_type = RIPNG_ROUTE_RTE;
+
+ RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
+
+ if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop))
+ IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
+
+ ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex);
+ rinfo->flags |= RIPNG_RTF_FIB;
+
+ /* The aggregation counter needs to be updated because
+ the prefixes, which are into the gc, have been
+ removed from the aggregator (see ripng_timout). */
+ ripng_aggregate_increment (rp, rinfo);
+ }
+
+ /* Update nexthop and/or metric value. */
+ if (oldmetric != RIPNG_METRIC_INFINITY)
{
ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex);
ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex);
rinfo->flags |= RIPNG_RTF_FIB;
- IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
+ if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop))
+ IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
}
- IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr);
- rinfo->ifindex = ifp->ifindex;
/* - Set the route change flag and signal the output process
to trigger an update. */
@@ -685,6 +905,12 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
/* - The metric for the route is set to 16
(infinity). This causes the route to be removed
from service.*/
+ ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex);
+ rinfo->flags &= ~RIPNG_RTF_FIB;
+
+ /* Aggregate count decrement. */
+ ripng_aggregate_decrement (rp, rinfo);
+
/* - The route change flag is to indicate that this
entry has been changed. */
/* - The output process is signalled to trigger a
@@ -696,13 +922,6 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
{
/* otherwise, re-initialize the timeout. */
ripng_timeout_update (rinfo);
-
- /* Should a new route to this network be established
- while the garbage-collection timer is running, the
- new route will replace the one that is about to be
- deleted. In this case the garbage-collection timer
- must be cleared. */
- RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
}
}
/* Unlock tempolary lock of the route. */
@@ -713,7 +932,7 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
/* Add redistributed route to RIPng table. */
void
ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p,
- unsigned int ifindex)
+ unsigned int ifindex, struct in6_addr *nexthop)
{
struct route_node *rp;
struct ripng_info *rinfo;
@@ -723,30 +942,89 @@ ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p,
return;
if (IN6_IS_ADDR_LOOPBACK (&p->prefix))
return;
+#if defined (MUSICA) || defined (LINUX)
+ /* XXX As long as the RIPng redistribution is applied to all the connected
+ * routes, one needs to filter the ::/96 prefixes.
+ * However it could be a wanted case, it will be removed soon.
+ */
+ if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
+ (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
+ return;
+#endif /* MUSICA or LINUX */
rp = route_node_get (ripng->table, (struct prefix *) p);
rinfo = rp->info;
if (rinfo)
{
+ if (rinfo->type == ZEBRA_ROUTE_CONNECT
+ && rinfo->sub_type == RIPNG_ROUTE_INTERFACE
+ && rinfo->metric != RIPNG_METRIC_INFINITY) {
+ route_unlock_node (rp);
+ return;
+ }
+
+ /* Manually configured RIPng route check.
+ * They have the precedence on all the other entries.
+ **/
+ if (rinfo->type == ZEBRA_ROUTE_RIPNG
+ && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) ||
+ (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) ) {
+ if (type != ZEBRA_ROUTE_RIPNG || ((sub_type != RIPNG_ROUTE_STATIC) &&
+ (sub_type != RIPNG_ROUTE_DEFAULT))) {
+ route_unlock_node (rp);
+ return;
+ }
+ }
+
RIPNG_TIMER_OFF (rinfo->t_timeout);
RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
+
+ /* Tells the other daemons about the deletion of
+ * this RIPng route
+ **/
+ if (ripng_route_rte (rinfo))
+ ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop,
+ rinfo->metric);
+
+ rp->info = NULL;
+ ripng_info_free (rinfo);
+
route_unlock_node (rp);
+
}
- else
- {
- rinfo = ripng_info_new ();
- ripng_aggregate_increment (rp, rinfo);
- }
+
+ rinfo = ripng_info_new ();
rinfo->type = type;
rinfo->sub_type = sub_type;
rinfo->ifindex = ifindex;
rinfo->metric = 1;
- rinfo->flags |= RIPNG_RTF_FIB;
-
rinfo->rp = rp;
+
+ if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop))
+ rinfo->nexthop = *nexthop;
+
+ rinfo->flags |= RIPNG_RTF_FIB;
rp->info = rinfo;
+
+ /* Aggregate check. */
+ ripng_aggregate_increment (rp, rinfo);
+
+ rinfo->flags |= RIPNG_RTF_CHANGED;
+
+ if (IS_RIPNG_DEBUG_EVENT) {
+ if (!nexthop)
+ zlog_info ("Redistribute new prefix %s/%d on the interface %s",
+ inet6_ntop(&p->prefix), p->prefixlen,
+ ifindex2ifname(ifindex));
+ else
+ zlog_info ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
+ inet6_ntop(&p->prefix), p->prefixlen, inet6_ntop(nexthop),
+ ifindex2ifname(ifindex));
+ }
+
+ ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
}
/* Delete redistributed route to RIPng table. */
@@ -761,6 +1039,15 @@ ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p,
return;
if (IN6_IS_ADDR_LOOPBACK (&p->prefix))
return;
+#if defined (MUSICA) || defined (LINUX)
+ /* XXX As long as the RIPng redistribution is applied to all the connected
+ * routes, one needs to filter the ::/96 prefixes.
+ * However it could be a wanted case, it will be removed soon.
+ */
+ if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
+ (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
+ return;
+#endif /* MUSICA or LINUX */
rp = route_node_lookup (ripng->table, (struct prefix *) p);
@@ -773,18 +1060,24 @@ ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p,
&& rinfo->sub_type == sub_type
&& rinfo->ifindex == ifindex)
{
- rp->info = NULL;
-
+ /* Perform poisoned reverse. */
+ rinfo->metric = RIPNG_METRIC_INFINITY;
+ RIPNG_TIMER_ON (rinfo->t_garbage_collect,
+ ripng_garbage_collect, ripng->garbage_time);
RIPNG_TIMER_OFF (rinfo->t_timeout);
- RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
+
+ /* Aggregate count decrement. */
+ ripng_aggregate_decrement (rp, rinfo);
+
+ rinfo->flags |= RIPNG_RTF_CHANGED;
- ripng_info_free (rinfo);
+ if (IS_RIPNG_DEBUG_EVENT)
+ zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
+ inet6_ntop(&p->prefix), p->prefixlen,
+ ifindex2ifname(ifindex));
- route_unlock_node (rp);
+ ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
}
-
- /* For unlock route_node_lookup (). */
- route_unlock_node (rp);
}
}
@@ -795,19 +1088,35 @@ ripng_redistribute_withdraw (int type)
struct route_node *rp;
struct ripng_info *rinfo;
+ if (!ripng)
+ return;
+
for (rp = route_top (ripng->table); rp; rp = route_next (rp))
if ((rinfo = rp->info) != NULL)
{
- if (rinfo->type == type)
+ if ((rinfo->type == type)
+ && (rinfo->sub_type != RIPNG_ROUTE_INTERFACE))
{
- rp->info = NULL;
-
+ /* Perform poisoned reverse. */
+ rinfo->metric = RIPNG_METRIC_INFINITY;
+ RIPNG_TIMER_ON (rinfo->t_garbage_collect,
+ ripng_garbage_collect, ripng->garbage_time);
RIPNG_TIMER_OFF (rinfo->t_timeout);
- RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
- ripng_info_free (rinfo);
+ /* Aggregate count decrement. */
+ ripng_aggregate_decrement (rp, rinfo);
+
+ rinfo->flags |= RIPNG_RTF_CHANGED;
+
+ if (IS_RIPNG_DEBUG_EVENT) {
+ struct prefix_ipv6 *p = (struct prefix_ipv6 *) &rp->p;
- route_unlock_node (rp);
+ zlog_info ("Poisone %s/%d on the interface %s [withdraw]",
+ inet6_ntop(&p->prefix), p->prefixlen,
+ ifindex2ifname(rinfo->ifindex));
+ }
+
+ ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
}
}
}
@@ -828,6 +1137,7 @@ ripng_response_process (struct ripng_packet *packet, int size,
{
zlog_warn ("RIPng packet comes from non RIPng port %d from %s",
ntohs (from->sin6_port), inet6_ntop (&from->sin6_addr));
+ ripng_peer_bad_packet (from);
return;
}
@@ -838,6 +1148,7 @@ ripng_response_process (struct ripng_packet *packet, int size,
{
zlog_warn ("RIPng packet comes from non link local address %s",
inet6_ntop (&from->sin6_addr));
+ ripng_peer_bad_packet (from);
return;
}
@@ -850,6 +1161,7 @@ ripng_response_process (struct ripng_packet *packet, int size,
{
zlog_warn ("RIPng packet comes from my own link local address %s",
inet6_ntop (&from->sin6_addr));
+ ripng_peer_bad_packet (from);
return;
}
@@ -861,9 +1173,13 @@ ripng_response_process (struct ripng_packet *packet, int size,
{
zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",
hoplimit, inet6_ntop (&from->sin6_addr));
+ ripng_peer_bad_packet (from);
return;
}
+ /* Update RIPng peer. */
+ ripng_peer_update (from, packet->version);
+
/* Reset nexthop. */
memset (&nexthop, 0, sizeof (struct ripng_nexthop));
nexthop.flag = RIPNG_NEXTHOP_UNSPEC;
@@ -891,18 +1207,21 @@ ripng_response_process (struct ripng_packet *packet, int size,
{
zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",
inet6_ntop (&rte->addr), rte->prefixlen, rte->metric);
+ ripng_peer_bad_route (from);
continue;
}
if (IN6_IS_ADDR_LINKLOCAL (&rte->addr))
{
zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",
inet6_ntop (&rte->addr), rte->prefixlen, rte->metric);
+ ripng_peer_bad_route (from);
continue;
}
if (IN6_IS_ADDR_LOOPBACK (&rte->addr))
{
zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",
inet6_ntop (&rte->addr), rte->prefixlen, rte->metric);
+ ripng_peer_bad_route (from);
continue;
}
@@ -913,6 +1232,7 @@ ripng_response_process (struct ripng_packet *packet, int size,
zlog_warn ("Invalid prefix length %s/%d from %s%%%s",
inet6_ntop (&rte->addr), rte->prefixlen,
inet6_ntop (&from->sin6_addr), ifp->name);
+ ripng_peer_bad_route (from);
continue;
}
@@ -921,13 +1241,13 @@ ripng_response_process (struct ripng_packet *packet, int size,
{
zlog_warn ("Invalid metric %d from %s%%%s", rte->metric,
inet6_ntop (&from->sin6_addr), ifp->name);
+ ripng_peer_bad_route (from);
continue;
}
- /* Metric calculation. */
- rte->metric += ifp->metric;
- if (rte->metric > RIPNG_METRIC_INFINITY)
- rte->metric = RIPNG_METRIC_INFINITY;
+ /* Vincent: XXX Should we compute the direclty reachable nexthop
+ * for our RIPng network ?
+ **/
/* Routing table updates. */
ripng_route_process (rte, from, &nexthop, ifp);
@@ -946,6 +1266,10 @@ ripng_request_process (struct ripng_packet *packet,int size,
struct ripng_info *rinfo;
struct ripng_interface *ri;
+ /* Does not reponse to the requests on the loopback interfaces */
+ if (if_is_loopback (ifp))
+ return;
+
/* Check RIPng process is enabled on this interface. */
ri = ifp->info;
if (! ri->running)
@@ -955,6 +1279,9 @@ ripng_request_process (struct ripng_packet *packet,int size,
if (ri->passive)
return;
+ /* RIPng peer update. */
+ ripng_peer_update (from, packet->version);
+
lim = ((caddr_t) packet) + size;
rte = packet->rte;
@@ -975,7 +1302,7 @@ ripng_request_process (struct ripng_packet *packet,int size,
rte->metric == RIPNG_METRIC_INFINITY)
{
/* All route with split horizon */
- ripng_output_process (ifp, from, ripng_all_route, ripng_split_horizon);
+ ripng_output_process (ifp, from, ripng_all_route);
}
else
{
@@ -1054,6 +1381,7 @@ ripng_read (struct thread *thread)
{
zlog_warn ("RIPng invalid packet size %d from %s", len,
inet6_ntop (&from.sin6_addr));
+ ripng_peer_bad_packet (&from);
return 0;
}
@@ -1082,6 +1410,7 @@ ripng_read (struct thread *thread)
{
zlog_warn ("RIPng packet version %d doesn't fit to my version %d",
packet->version, ripng->version);
+ ripng_peer_bad_packet (&from);
return 0;
}
@@ -1096,6 +1425,7 @@ ripng_read (struct thread *thread)
break;
default:
zlog_warn ("Invalid RIPng command %d", packet->command);
+ ripng_peer_bad_packet (&from);
break;
}
return 0;
@@ -1158,7 +1488,7 @@ ripng_update (struct thread *t)
}
#endif /* RIPNG_ADVANCED */
- ripng_output_process (ifp, NULL, ripng_all_route, ripng_split_horizon);
+ ripng_output_process (ifp, NULL, ripng_all_route);
}
/* Triggered updates may be suppressed if a regular update is due by
@@ -1231,8 +1561,7 @@ ripng_triggered_update (struct thread *t)
if (ri->passive)
continue;
- ripng_output_process (ifp, NULL, ripng_changed_route,
- ripng_split_horizon);
+ ripng_output_process (ifp, NULL, ripng_changed_route);
}
/* Once all of the triggered updates have been generated, the route
@@ -1255,7 +1584,7 @@ ripng_triggered_update (struct thread *t)
the routing table entry in the stream. */
int
ripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p,
- u_int16_t tag, u_char metric)
+ struct in6_addr *nexthop, u_int16_t tag, u_char metric)
{
/* RIPng packet header. */
if (num == 0)
@@ -1266,9 +1595,15 @@ ripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p,
}
/* Write routing table entry. */
- stream_write (s, (caddr_t) &p->prefix, sizeof (struct in6_addr));
+ if (!nexthop)
+ stream_write (s, (caddr_t) &p->prefix, sizeof (struct in6_addr));
+ else
+ stream_write (s, (caddr_t) nexthop, sizeof (struct in6_addr));
stream_putw (s, tag);
- stream_putc (s, p->prefixlen);
+ if (p)
+ stream_putc (s, p->prefixlen);
+ else
+ stream_putc (s, 0);
stream_putc (s, metric);
return ++num;
@@ -1277,56 +1612,53 @@ ripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p,
/* Send RESPONSE message to specified destination. */
void
ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to,
- int route_type, int split_horizon)
+ int route_type)
{
int ret;
- struct stream *s;
struct route_node *rp;
struct ripng_info *rinfo;
struct ripng_interface *ri;
struct ripng_aggregate *aggregate;
struct prefix_ipv6 *p;
- int num;
- int mtu;
- int rtemax;
- u_char metric;
- u_char metric_set;
-
- if (IS_RIPNG_DEBUG_EVENT)
- zlog_info ("RIPng update routes on interface %s", ifp->name);
-
- /* Output stream get from ripng structre. XXX this should be
- interface structure. */
- s = ripng->obuf;
-
- /* Reset stream and RTE counter. */
- stream_reset (s);
- num = 0;
-
- mtu = ifp->mtu;
- if (mtu < 0)
- mtu = IFMINMTU;
+ struct list * ripng_rte_list;
- rtemax = (min (mtu, RIPNG_MAX_PACKET_SIZE) -
- IPV6_HDRLEN -
- sizeof (struct udphdr) -
- sizeof (struct ripng_packet) +
- sizeof (struct rte)) / sizeof (struct rte);
+ if (IS_RIPNG_DEBUG_EVENT) {
+ if (to)
+ zlog_info ("RIPng update routes to neighbor %s",
+ inet6_ntop(&to->sin6_addr));
+ else
+ zlog_info ("RIPng update routes on interface %s", ifp->name);
+ }
-#ifdef DEBUG
- zlog_info ("DEBUG RIPng: ifmtu is %d", ifp->mtu);
- zlog_info ("DEBUG RIPng: rtemax is %d", rtemax);
-#endif /* DEBUG */
-
/* Get RIPng interface. */
ri = ifp->info;
-
+
+ ripng_rte_list = ripng_rte_new();
+
for (rp = route_top (ripng->table); rp; rp = route_next (rp))
{
if ((rinfo = rp->info) != NULL && rinfo->suppress == 0)
{
+ /* If no route-map are applied, the RTE will be these following
+ * informations.
+ */
p = (struct prefix_ipv6 *) &rp->p;
- metric = rinfo->metric;
+ rinfo->metric_out = rinfo->metric;
+ rinfo->tag_out = rinfo->tag;
+ memset(&rinfo->nexthop_out, 0, sizeof(rinfo->nexthop_out));
+ /* In order to avoid some local loops,
+ * if the RIPng route has a nexthop via this interface, keep the nexthop,
+ * otherwise set it to 0. The nexthop should not be propagated
+ * beyond the local broadcast/multicast area in order
+ * to avoid an IGP multi-level recursive look-up.
+ */
+ if (rinfo->ifindex == ifp->ifindex)
+ rinfo->nexthop_out = rinfo->nexthop;
+
+ /* Apply output filters. */
+ ret = ripng_outgoing_filter (p, ri);
+ if (ret < 0)
+ continue;
/* Changed route only output. */
if (route_type == ripng_changed_route &&
@@ -1334,164 +1666,130 @@ ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to,
continue;
/* Split horizon. */
- if (split_horizon == ripng_split_horizon &&
- rinfo->ifindex == ifp->ifindex)
- continue;
-
- /* Apply output filters.*/
- if (ri->list[RIPNG_FILTER_OUT])
- {
- if (access_list_apply (ri->list[RIPNG_FILTER_OUT],
- (struct prefix *) p) == FILTER_DENY)
- {
- if (IS_RIPNG_DEBUG_PACKET)
- zlog_info ("RIPng %s/%d is filtered by distribute out",
- inet6_ntop (&p->prefix), p->prefixlen);
- continue;
- }
- }
- if (ri->prefix[RIPNG_FILTER_OUT])
- {
- if (prefix_list_apply (ri->prefix[RIPNG_FILTER_OUT],
- (struct prefix *) p) == PREFIX_DENY)
- {
- if (IS_RIPNG_DEBUG_PACKET)
- zlog_info ("RIPng %s/%d is filtered by prefix-list out",
- inet6_ntop (&p->prefix), p->prefixlen);
- continue;
- }
- }
+ if (ri->split_horizon == RIPNG_SPLIT_HORIZON)
+ {
+ /* We perform split horizon for RIPng routes. */
+ if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
+ rinfo->ifindex == ifp->ifindex)
+ continue;
+ }
/* Preparation for route-map. */
- metric_set = 0;
+ rinfo->metric_set = 0;
+ /* nexthop_out,
+ * metric_out
+ * and tag_out are already initialized.
+ */
- /* Route-map */
+ /* Interface route-map */
if (ri->routemap[RIPNG_FILTER_OUT])
{
int ret;
- struct ripng_info newinfo;
-
- memset (&newinfo, 0, sizeof (struct ripng_info));
- newinfo.metric = metric;
ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT],
(struct prefix *) p, RMAP_RIPNG,
- &newinfo);
+ rinfo);
if (ret == RMAP_DENYMATCH)
{
if (IS_RIPNG_DEBUG_PACKET)
zlog_info ("RIPng %s/%d is filtered by route-map out",
inet6_ntop (&p->prefix), p->prefixlen);
- return;
+ continue;
}
- metric = newinfo.metric;
- metric_set = newinfo.metric_set;
}
- /* When the interface route-map does not set metric */
- if (! metric_set)
+ /* Redistribute route-map. */
+ if (ripng->route_map[rinfo->type].name)
{
- /* and the redistribute route-map is set. */
- if (ripng->route_map[rinfo->type].name)
+ int ret;
+
+ ret = route_map_apply (ripng->route_map[rinfo->type].map,
+ (struct prefix *) p, RMAP_RIPNG,
+ &rinfo);
+
+ if (ret == RMAP_DENYMATCH)
{
- int ret;
- struct ripng_info newinfo;
-
- memset (&newinfo, 0, sizeof (struct ripng_info));
- newinfo.metric = metric;
-
- ret = route_map_apply (ripng->route_map[rinfo->type].map,
- (struct prefix *) p, RMAP_RIPNG,
- &newinfo);
-
- if (ret == RMAP_DENYMATCH)
- {
- if (IS_RIPNG_DEBUG_PACKET)
- zlog_info ("RIPng %s/%d is filtered by route-map",
- inet6_ntop (&p->prefix), p->prefixlen);
- continue;
- }
-
- metric = newinfo.metric;
- metric_set = newinfo.metric_set;
+ if (IS_RIPNG_DEBUG_PACKET)
+ zlog_info ("RIPng %s/%d is filtered by route-map",
+ inet6_ntop (&p->prefix), p->prefixlen);
+ continue;
}
+ }
- /* When the redistribute route-map does not set metric. */
- if (! metric_set)
+ /* When the route-map does not set metric. */
+ if (! rinfo->metric_set)
+ {
+ /* If the redistribute metric is set. */
+ if (ripng->route_map[rinfo->type].metric_config
+ && rinfo->metric != RIPNG_METRIC_INFINITY)
+ {
+ rinfo->metric_out = ripng->route_map[rinfo->type].metric;
+ }
+ else
{
- /* If the redistribute metric is set. */
- if (ripng->route_map[rinfo->type].metric_config
+ /* If the route is not connected or localy generated
+ one, use default-metric value */
+ if (rinfo->type != ZEBRA_ROUTE_RIPNG
+ && rinfo->type != ZEBRA_ROUTE_CONNECT
&& rinfo->metric != RIPNG_METRIC_INFINITY)
- {
- metric = ripng->route_map[rinfo->type].metric;
- }
- else
- {
- /* If the route is not connected or localy generated
- one, use default-metric value */
- if (rinfo->type != ZEBRA_ROUTE_RIPNG
- && rinfo->type != ZEBRA_ROUTE_CONNECT
- && rinfo->metric != RIPNG_METRIC_INFINITY)
- metric = ripng->default_metric;
- }
+ rinfo->metric_out = ripng->default_metric;
}
}
- /* Write RTE to the stream. */
- num = ripng_write_rte (num, s, p, rinfo->tag, metric);
- if (num == rtemax)
- {
- ret = ripng_send_packet (STREAM_DATA (s), stream_get_endp (s),
- to, ifp);
-
- if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
- ripng_packet_dump ((struct ripng_packet *)STREAM_DATA (s),
- stream_get_endp(s), "SEND");
- num = 0;
- stream_reset (s);
- }
+ /* Apply offset-list */
+ if (rinfo->metric_out != RIPNG_METRIC_INFINITY)
+ ripng_offset_list_apply_out (p, ifp, &rinfo->metric_out);
+
+ if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
+ rinfo->metric_out = RIPNG_METRIC_INFINITY;
+
+ /* Perform split-horizon with poisoned reverse
+ * for RIPng routes.
+ **/
+ if (ri->split_horizon == RIPNG_SPLIT_HORIZON_POISONED_REVERSE) {
+ if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
+ rinfo->ifindex == ifp->ifindex)
+ rinfo->metric_out = RIPNG_METRIC_INFINITY;
+ }
+
+ /* Add RTE to the list */
+ ripng_rte_add(ripng_rte_list, p, rinfo, NULL);
}
+
+ /* Process the aggregated RTE entry */
if ((aggregate = rp->aggregate) != NULL &&
aggregate->count > 0 &&
aggregate->suppress == 0)
{
+ /* If no route-map are applied, the RTE will be these following
+ * informations.
+ */
p = (struct prefix_ipv6 *) &rp->p;
- metric = aggregate->metric;
+ aggregate->metric_set = 0;
+ aggregate->metric_out = aggregate->metric;
+ aggregate->tag_out = aggregate->tag;
+ memset(&aggregate->nexthop_out, 0, sizeof(aggregate->nexthop_out));
/* Apply output filters.*/
- if (ri->list[RIPNG_FILTER_OUT])
- {
- if (access_list_apply (ri->list[RIPNG_FILTER_OUT],
- (struct prefix *) p) == FILTER_DENY)
- {
- if (IS_RIPNG_DEBUG_PACKET)
- zlog_info ("RIPng %s/%d is filtered by distribute out",
- inet6_ntop (&p->prefix), p->prefixlen);
- continue;
- }
- }
- if (ri->prefix[RIPNG_FILTER_OUT])
- {
- if (prefix_list_apply (ri->prefix[RIPNG_FILTER_OUT],
- (struct prefix *) p) == PREFIX_DENY)
- {
- if (IS_RIPNG_DEBUG_PACKET)
- zlog_info ("RIPng %s/%d is filtered by prefix-list out",
- inet6_ntop (&p->prefix), p->prefixlen);
- continue;
- }
- }
+ ret = ripng_outgoing_filter (p, ri);
+ if (ret < 0)
+ continue;
- /* Route-map */
+ /* Interface route-map */
if (ri->routemap[RIPNG_FILTER_OUT])
{
int ret;
struct ripng_info newinfo;
+ /* let's cast the aggregate structure to ripng_info */
memset (&newinfo, 0, sizeof (struct ripng_info));
- newinfo.metric = metric;
+ /* the nexthop is :: */
+ newinfo.metric = aggregate->metric;
+ newinfo.metric_out = aggregate->metric_out;
+ newinfo.tag = aggregate->tag;
+ newinfo.tag_out = aggregate->tag_out;
ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT],
(struct prefix *) p, RMAP_RIPNG,
@@ -1502,45 +1800,40 @@ ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to,
if (IS_RIPNG_DEBUG_PACKET)
zlog_info ("RIPng %s/%d is filtered by route-map out",
inet6_ntop (&p->prefix), p->prefixlen);
- return;
+ continue;
}
- metric = newinfo.metric;
+ aggregate->metric_out = newinfo.metric_out;
+ aggregate->tag_out = newinfo.tag_out;
+ if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop_out))
+ aggregate->nexthop_out = newinfo.nexthop_out;
}
+ /* There is no redistribute routemap for the aggregated RTE */
+
/* Changed route only output. */
+ /* XXX, vincent, in order to increase time convergence,
+ * it should be announced if a child has changed.
+ */
if (route_type == ripng_changed_route)
continue;
- /* Write RTE to the stream. */
- num = ripng_write_rte (num, s, p, aggregate->tag, metric);
- if (num == rtemax)
- {
- ret = ripng_send_packet (STREAM_DATA (s), stream_get_endp (s),
- to, ifp);
-
- if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
- ripng_packet_dump ((struct ripng_packet *)STREAM_DATA (s),
- stream_get_endp(s), "SEND");
- num = 0;
- stream_reset (s);
- }
+ /* Apply offset-list */
+ if (aggregate->metric_out != RIPNG_METRIC_INFINITY)
+ ripng_offset_list_apply_out (p, ifp, &aggregate->metric_out);
+
+ if (aggregate->metric_out > RIPNG_METRIC_INFINITY)
+ aggregate->metric_out = RIPNG_METRIC_INFINITY;
+
+ /* Add RTE to the list */
+ ripng_rte_add(ripng_rte_list, p, NULL, aggregate);
}
}
-
- /* If unwritten RTE exist, flush it. */
- if (num != 0)
- {
- ret = ripng_send_packet (STREAM_DATA (s), stream_get_endp (s),
- to, ifp);
- if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
- ripng_packet_dump ((struct ripng_packet *)STREAM_DATA (s),
- stream_get_endp (s), "SEND");
- num = 0;
- stream_reset (s);
- }
+ /* Flush the list */
+ ripng_rte_send(ripng_rte_list, ifp, to);
+ ripng_rte_free(ripng_rte_list);
}
/* Create new RIPng instance and set it to global variable. */
@@ -1551,7 +1844,7 @@ ripng_create ()
assert (ripng == NULL);
/* Allocaste RIPng instance. */
- ripng = XMALLOC (0, sizeof (struct ripng));
+ ripng = XMALLOC (MTYPE_RIPNG, sizeof (struct ripng));
memset (ripng, 0, sizeof (struct ripng));
/* Default version and timer values. */
@@ -1582,13 +1875,21 @@ ripng_create ()
return 0;
}
-/* Sned RIPng request to the interface. */
+/* Send RIPng request to the interface. */
int
ripng_request (struct interface *ifp)
{
struct rte *rte;
struct ripng_packet ripng_packet;
+ /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */
+ if (if_is_loopback(ifp))
+ return 0;
+
+ /* If interface is down, don't send RIP packet. */
+ if (! if_is_up (ifp))
+ return 0;
+
if (IS_RIPNG_DEBUG_EVENT)
zlog_info ("RIPng send request to %s", ifp->name);
@@ -1602,22 +1903,6 @@ ripng_request (struct interface *ifp)
NULL, ifp);
}
-/* Clean up installed RIPng routes. */
-void
-ripng_terminate ()
-{
- struct route_node *rp;
- struct ripng_info *rinfo;
-
- for (rp = route_top (ripng->table); rp; rp = route_next (rp))
- if ((rinfo = rp->info) != NULL)
- {
- if (rinfo->type == ZEBRA_ROUTE_RIPNG &&
- rinfo->sub_type == RIPNG_ROUTE_RTE)
- ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p,
- &rinfo->nexthop, rinfo->ifindex);
- }
-}
int
ripng_update_jitter (int time)
@@ -1628,7 +1913,6 @@ ripng_update_jitter (int time)
void
ripng_event (enum ripng_event event, int sock)
{
- int ripng_request_all (struct thread *);
int jitter = 0;
switch (event)
@@ -1682,14 +1966,6 @@ struct
{ ZEBRA_ROUTE_BGP, "B", "bgp", 70},
};
-/* For messages. */
-struct message ripng_route_info[] =
-{
- { RIPNG_ROUTE_RTE, " "},
- { RIPNG_ROUTE_STATIC, "S"},
- { RIPNG_ROUTE_AGGREGATE, "a"}
-};
-
/* Print out routes update time. */
static void
ripng_vty_out_uptime (struct vty *vty, struct ripng_info *rinfo)
@@ -1719,6 +1995,40 @@ ripng_vty_out_uptime (struct vty *vty, struct ripng_info *rinfo)
}
}
+char *
+ripng_route_subtype_print (struct ripng_info *rinfo)
+{
+ static char str[3];
+ memset(str, 0, 3);
+
+ if (rinfo->suppress)
+ strcat(str, "S");
+
+ switch (rinfo->sub_type)
+ {
+ case RIPNG_ROUTE_RTE:
+ strcat(str, "n");
+ break;
+ case RIPNG_ROUTE_STATIC:
+ strcat(str, "s");
+ break;
+ case RIPNG_ROUTE_DEFAULT:
+ strcat(str, "d");
+ break;
+ case RIPNG_ROUTE_REDISTRIBUTE:
+ strcat(str, "r");
+ break;
+ case RIPNG_ROUTE_INTERFACE:
+ strcat(str, "i");
+ break;
+ default:
+ strcat(str, "?");
+ break;
+ }
+
+ return str;
+}
+
DEFUN (show_ipv6_ripng,
show_ipv6_ripng_cmd,
"show ipv6 ripng",
@@ -1732,10 +2042,16 @@ DEFUN (show_ipv6_ripng,
struct prefix_ipv6 *p;
int len;
+ if (! ripng)
+ return CMD_SUCCESS;
+
/* Header of display. */
- vty_out (vty, "%sCodes: R - RIPng%s%s"
- " Network "
- "Next Hop If Met Tag Time%s", VTY_NEWLINE,
+ vty_out (vty, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s"
+ "Sub-codes:%s"
+ " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
+ " (i) - interface, (a/S) - aggregated/Suppressed%s%s"
+ " Network Next Hop Via Metric Tag Time%s",
+ VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
for (rp = route_top (ripng->table); rp; rp = route_next (rp))
@@ -1745,20 +2061,18 @@ DEFUN (show_ipv6_ripng,
p = (struct prefix_ipv6 *) &rp->p;
#ifdef DEBUG
- len = vty_out (vty, "Ra %d/%d %s/%d ",
+ len = vty_out (vty, "R(a) %d/%d %s/%d ",
aggregate->count, aggregate->suppress,
inet6_ntop (&p->prefix), p->prefixlen);
#else
- len = vty_out (vty, "Ra %s/%d ",
+ len = vty_out (vty, "R(a) %s/%d ",
inet6_ntop (&p->prefix), p->prefixlen);
#endif /* DEBUG */
+ vty_out (vty, "%s", VTY_NEWLINE);
+ vty_out (vty, "%*s", 18, " ");
- len = 37 - len;
- if (len > 0)
- vty_out (vty, "%*s", len, " ");
-
- vty_out (vty, "%*s", 26, " ");
- vty_out (vty, "%4d %3d%s", aggregate->metric,
+ vty_out (vty, "%*s", 28, " ");
+ vty_out (vty, "self %2d %3d%s", aggregate->metric,
aggregate->tag,
VTY_NEWLINE);
}
@@ -1768,32 +2082,54 @@ DEFUN (show_ipv6_ripng,
p = (struct prefix_ipv6 *) &rp->p;
#ifdef DEBUG
- len = vty_out (vty, "%s%s 0/%d %s/%d ",
+ len = vty_out (vty, "%s(%s) 0/%d %s/%d ",
route_info[rinfo->type].str,
- rinfo->suppress ? "s" : " ",
+ ripng_route_subtype_print(rinfo),
rinfo->suppress,
inet6_ntop (&p->prefix), p->prefixlen);
#else
- len = vty_out (vty, "%s%s %s/%d ",
+ len = vty_out (vty, "%s(%s) %s/%d ",
route_info[rinfo->type].str,
- rinfo->suppress ? "s" : " ",
+ ripng_route_subtype_print(rinfo),
inet6_ntop (&p->prefix), p->prefixlen);
#endif /* DEBUG */
- len = 37 - len;
+ vty_out (vty, "%s", VTY_NEWLINE);
+ vty_out (vty, "%*s", 18, " ");
+ len = vty_out (vty, "%s", inet6_ntop (&rinfo->nexthop));
+
+ len = 28 - len;
if (len > 0)
- vty_out (vty, "%*s", len, " ");
+ len = vty_out (vty, "%*s", len, " ");
- len = vty_out (vty, "%s", inet6_ntop (&rinfo->nexthop));
+ /* from */
+ if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
+ (rinfo->sub_type == RIPNG_ROUTE_RTE))
+ {
+ len = vty_out (vty, "%s", ifindex2ifname(rinfo->ifindex));
+ } else if (rinfo->metric == RIPNG_METRIC_INFINITY)
+ {
+ len = vty_out (vty, "kill");
+ } else
+ len = vty_out (vty, "self");
- len = 26 - len;
+ len = 9 - len;
if (len > 0)
vty_out (vty, "%*s", len, " ");
- vty_out (vty, "%2d %2d %3d ",
- rinfo->ifindex, rinfo->metric, rinfo->tag);
+ vty_out (vty, " %2d %3d ",
+ rinfo->metric, rinfo->tag);
- if (rinfo->sub_type == RIPNG_ROUTE_RTE)
+ /* time */
+ if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
+ (rinfo->sub_type == RIPNG_ROUTE_RTE))
+ {
+ /* RTE from remote RIP routers */
ripng_vty_out_uptime (vty, rinfo);
+ } else if (rinfo->metric == RIPNG_METRIC_INFINITY)
+ {
+ /* poisonous reversed routes (gc) */
+ ripng_vty_out_uptime (vty, rinfo);
+ }
vty_out (vty, "%s", VTY_NEWLINE);
}
@@ -1802,6 +2138,88 @@ DEFUN (show_ipv6_ripng,
return CMD_SUCCESS;
}
+/* Return next event time. */
+static int
+ripng_next_thread_timer (struct thread *thread)
+{
+ struct timeval timer_now;
+
+ gettimeofday (&timer_now, NULL);
+
+ return thread->u.sands.tv_sec - timer_now.tv_sec;
+}
+
+DEFUN (show_ipv6_ripng_status,
+ show_ipv6_ripng_status_cmd,
+ "show ipv6 ripng status",
+ SHOW_STR
+ IP_STR
+ "Show RIPng routes\n"
+ "IPv6 routing protocol process parameters and statistics\n")
+{
+ listnode node;
+ int ripng_network_write (struct vty *, int);
+ void ripng_redistribute_write (struct vty *, int);
+
+ if (! ripng)
+ return CMD_SUCCESS;
+
+ vty_out (vty, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE);
+ vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
+ ripng->update_time);
+ vty_out (vty, " next due in %d seconds%s",
+ ripng_next_thread_timer (ripng->t_update),
+ VTY_NEWLINE);
+ vty_out (vty, " Timeout after %ld seconds,", ripng->timeout_time);
+ vty_out (vty, " garbage collect after %ld seconds%s", ripng->garbage_time,
+ VTY_NEWLINE);
+
+ /* Filtering status show. */
+ config_show_distribute (vty);
+
+ /* Default metric information. */
+ vty_out (vty, " Default redistribution metric is %d%s",
+ ripng->default_metric, VTY_NEWLINE);
+
+ /* Redistribute information. */
+ vty_out (vty, " Redistributing:");
+ ripng_redistribute_write (vty, 0);
+ vty_out (vty, "%s", VTY_NEWLINE);
+
+ vty_out (vty, " Default version control: send version %d,", ripng->version);
+ vty_out (vty, " receive version %d %s", ripng->version,
+ VTY_NEWLINE);
+
+ vty_out (vty, " Interface Send Recv%s", VTY_NEWLINE);
+
+ for (node = listhead (iflist); node; node = nextnode (node))
+ {
+ struct ripng_interface *ri;
+ struct interface *ifp;
+
+ ifp = getdata (node);
+ ri = ifp->info;
+
+ if (ri->enable_network || ri->enable_interface)
+ {
+
+ vty_out (vty, " %-17s%-3d %-3d%s", ifp->name,
+ ripng->version,
+ ripng->version,
+ VTY_NEWLINE);
+ }
+ }
+
+ vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
+ ripng_network_write (vty, 0);
+
+ vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
+ vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
+ ripng_peer_display (vty);
+
+ return CMD_SUCCESS;
+}
+
DEFUN (router_ripng,
router_ripng_cmd,
"router ripng",
@@ -1827,6 +2245,18 @@ DEFUN (router_ripng,
return CMD_SUCCESS;
}
+DEFUN (no_router_ripng,
+ no_router_ripng_cmd,
+ "no router ripng",
+ NO_STR
+ "Enable a routing process\n"
+ "Make RIPng instance command\n")
+{
+ if(ripng)
+ ripng_clean();
+ return CMD_SUCCESS;
+}
+
DEFUN (ripng_route,
ripng_route_cmd,
"route IPV6ADDR",
@@ -1854,7 +2284,7 @@ DEFUN (ripng_route,
}
rp->info = (void *)1;
- ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0);
+ ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, NULL);
return CMD_SUCCESS;
}
@@ -2160,6 +2590,15 @@ DEFUN (no_ripng_timers,
return CMD_SUCCESS;
}
+ALIAS (no_ripng_timers,
+ no_ripng_timers_val_cmd,
+ "no timers basic <0-65535> <0-65535> <0-65535>",
+ NO_STR
+ "RIPng timers setup\n"
+ "Basic timer\n"
+ "Routing table update timer value in second. Default is 30.\n"
+ "Routing information timeout timer. Default is 180.\n"
+ "Garbage collection timer. Default is 120.\n")
DEFUN (show_ipv6_protocols, show_ipv6_protocols_cmd,
"show ipv6 protocols",
@@ -2196,10 +2635,12 @@ DEFUN (ripng_default_information_originate,
{
struct prefix_ipv6 p;
- ripng->default_information = 1;
+ if (! ripng ->default_information) {
+ ripng->default_information = 1;
- str2prefix_ipv6 ("::/0", &p);
- ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0);
+ str2prefix_ipv6 ("::/0", &p);
+ ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0, NULL);
+ }
return CMD_SUCCESS;
}
@@ -2213,10 +2654,12 @@ DEFUN (no_ripng_default_information_originate,
{
struct prefix_ipv6 p;
- ripng->default_information = 0;
+ if (ripng->default_information) {
+ ripng->default_information = 0;
- str2prefix_ipv6 ("::/0", &p);
- ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0);
+ str2prefix_ipv6 ("::/0", &p);
+ ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0);
+ }
return CMD_SUCCESS;
}
@@ -2225,8 +2668,8 @@ DEFUN (no_ripng_default_information_originate,
int
ripng_config_write (struct vty *vty)
{
- int ripng_network_write (struct vty *);
- void ripng_redistribute_write (struct vty *);
+ int ripng_network_write (struct vty *, int);
+ void ripng_redistribute_write (struct vty *, int);
int write = 0;
struct route_node *rp;
@@ -2239,14 +2682,17 @@ ripng_config_write (struct vty *vty)
if (ripng->default_information)
vty_out (vty, " default-information originate%s", VTY_NEWLINE);
- ripng_network_write (vty);
+ ripng_network_write (vty, 1);
/* RIPng default metric configuration */
if (ripng->default_metric != RIPNG_DEFAULT_METRIC_DEFAULT)
vty_out (vty, " default-metric %d%s",
ripng->default_metric, VTY_NEWLINE);
- ripng_redistribute_write (vty);
+ ripng_redistribute_write (vty, 1);
+
+ /* RIP offset-list configuration. */
+ config_write_ripng_offset_list (vty);
/* RIPng aggregate routes. */
for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp))
@@ -2365,6 +2811,7 @@ ripng_distribute_update (struct distribute *dist)
else
ri->prefix[RIPNG_FILTER_OUT] = NULL;
}
+
void
ripng_distribute_update_interface (struct interface *ifp)
{
@@ -2388,6 +2835,103 @@ ripng_distribute_update_all ()
ripng_distribute_update_interface (ifp);
}
}
+
+/* delete all the added ripng routes. */
+void
+ripng_clean()
+{
+ int i;
+ struct route_node *rp;
+ struct ripng_info *rinfo;
+
+ if (ripng) {
+ /* Clear RIPng routes */
+ for (rp = route_top (ripng->table); rp; rp = route_next (rp)) {
+ if ((rinfo = rp->info) != NULL) {
+ if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
+ (rinfo->sub_type == RIPNG_ROUTE_RTE))
+ ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p,
+ &rinfo->nexthop, rinfo->metric);
+
+ RIPNG_TIMER_OFF (rinfo->t_timeout);
+ RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
+
+ rp->info = NULL;
+ route_unlock_node (rp);
+
+ ripng_info_free(rinfo);
+ }
+ }
+
+ /* Cancel the RIPng timers */
+ RIPNG_TIMER_OFF (ripng->t_update);
+ RIPNG_TIMER_OFF (ripng->t_triggered_update);
+ RIPNG_TIMER_OFF (ripng->t_triggered_interval);
+
+ /* Cancel the read thread */
+ if (ripng->t_read) {
+ thread_cancel (ripng->t_read);
+ ripng->t_read = NULL;
+ }
+
+ /* Close the RIPng socket */
+ if (ripng->sock >= 0) {
+ close(ripng->sock);
+ ripng->sock = -1;
+ }
+
+ /* Static RIPng route configuration. */
+ for (rp = route_top (ripng->route); rp; rp = route_next (rp))
+ if (rp->info) {
+ rp->info = NULL;
+ route_unlock_node (rp);
+ }
+
+ /* RIPng aggregated prefixes */
+ for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp))
+ if (rp->info) {
+ rp->info = NULL;
+ route_unlock_node (rp);
+ }
+
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ if (ripng->route_map[i].name)
+ free (ripng->route_map[i].name);
+
+ XFREE (MTYPE_ROUTE_TABLE, ripng->table);
+ XFREE (MTYPE_ROUTE_TABLE, ripng->route);
+ XFREE (MTYPE_ROUTE_TABLE, ripng->aggregate);
+
+ XFREE (MTYPE_RIPNG, ripng);
+ ripng = NULL;
+ } /* if (ripng) */
+
+ ripng_clean_network();
+ ripng_passive_interface_clean ();
+ ripng_offset_clean ();
+ ripng_interface_clean ();
+ ripng_redistribute_clean ();
+}
+
+/* Reset all values to the default settings. */
+void
+ripng_reset ()
+{
+ /* Call ripd related reset functions. */
+ ripng_debug_reset ();
+ ripng_route_map_reset ();
+
+ /* Call library reset functions. */
+ vty_reset ();
+ access_list_reset ();
+ prefix_list_reset ();
+
+ distribute_list_reset ();
+
+ ripng_interface_reset ();
+
+ ripng_zclient_reset ();
+}
void
ripng_if_rmap_update (struct if_rmap *if_rmap)
@@ -2478,10 +3022,13 @@ ripng_init ()
/* Install ripng commands. */
install_element (VIEW_NODE, &show_ipv6_ripng_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ripng_status_cmd);
install_element (ENABLE_NODE, &show_ipv6_ripng_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ripng_status_cmd);
install_element (CONFIG_NODE, &router_ripng_cmd);
+ install_element (CONFIG_NODE, &no_router_ripng_cmd);
install_default (RIPNG_NODE);
install_element (RIPNG_NODE, &ripng_route_cmd);
@@ -2495,6 +3042,7 @@ ripng_init ()
install_element (RIPNG_NODE, &ripng_timers_cmd);
install_element (RIPNG_NODE, &no_ripng_timers_cmd);
+ install_element (RIPNG_NODE, &no_ripng_timers_val_cmd);
#if 0
install_element (RIPNG_NODE, &ripng_update_timer_cmd);
install_element (RIPNG_NODE, &no_ripng_update_timer_cmd);
@@ -2527,6 +3075,8 @@ ripng_init ()
/* Route-map for interface. */
ripng_route_map_init ();
+ ripng_offset_init ();
+
route_map_add_hook (ripng_routemap_update);
route_map_delete_hook (ripng_routemap_update);
diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h
index 2509bdd5..609e6925 100644
--- a/ripngd/ripngd.h
+++ b/ripngd/ripngd.h
@@ -27,7 +27,6 @@
#define RIPNG_V1 1
#define RIPNG_PORT_DEFAULT 521
#define RIPNG_VTY_PORT 2603
-#define RIPNG_VTYSH_PATH "/tmp/.ripngd"
#define RIPNG_MAX_PACKET_SIZE 1500
#define RIPNG_PRIORITY_DEFAULT 0
@@ -45,13 +44,19 @@
#define RIPNG_TIMEOUT_TIMER_DEFAULT 180
#define RIPNG_GARBAGE_TIMER_DEFAULT 120
+/* RIPng peer timeout value. */
+#define RIPNG_PEER_TIMER_DEFAULT 180
+
/* Default config file name. */
#define RIPNG_DEFAULT_CONFIG "ripngd.conf"
/* RIPng route types. */
#define RIPNG_ROUTE_RTE 0
#define RIPNG_ROUTE_STATIC 1
-#define RIPNG_ROUTE_AGGREGATE 2
+#define RIPNG_ROUTE_DEFAULT 2
+#define RIPNG_ROUTE_REDISTRIBUTE 3
+#define RIPNG_ROUTE_INTERFACE 4
+#define RIPNG_ROUTE_AGGREGATE 5
/* Interface send/receive configuration. */
#define RIPNG_SEND_UNSPEC 0
@@ -59,12 +64,6 @@
#define RIPNG_RECEIVE_UNSPEC 0
#define RIPNG_RECEIVE_OFF 1
-/* Split horizon definitions. */
-#define RIPNG_SPLIT_HORIZON_UNSPEC 0
-#define RIPNG_SPLIT_HORIZON_NONE 1
-#define RIPNG_SPLIT_HORIZON 2
-#define RIPNG_SPLIT_HORIZON_POISONED 3
-
/* RIP default route's accept/announce methods. */
#define RIPNG_DEFAULT_ADVERTISE_UNSPEC 0
#define RIPNG_DEFAULT_ADVERTISE_NONE 1
@@ -140,10 +139,12 @@ struct ripng
/* Routing table entry. */
struct rte
{
- struct in6_addr addr;
- u_short tag;
- u_char prefixlen;
- u_char metric;
+ struct in6_addr addr; /* RIPng destination prefix */
+ u_short tag; /* RIPng tag */
+ u_char prefixlen; /* Length of the RIPng prefix */
+ u_char metric; /* Metric of the RIPng route */
+ /* The nexthop is stored by the structure
+ * ripng_nexthop within ripngd.c */
};
/* RIPNG send packet. */
@@ -190,11 +191,16 @@ struct ripng_info
struct thread *t_garbage_collect;
/* Route-map features - this variables can be changed. */
+ struct in6_addr nexthop_out;
u_char metric_set;
+ u_char metric_out;
+ u_short tag_out;
struct route_node *rp;
};
+#ifdef notyet
+#if 0
/* RIPng tag structure. */
struct ripng_tag
{
@@ -219,6 +225,14 @@ struct ripng_tag
/* Poison reverse. */
u_char poison_reverse;
};
+#endif /* 0 */
+#endif /* not yet */
+
+typedef enum {
+ RIPNG_NO_SPLIT_HORIZON = 0,
+ RIPNG_SPLIT_HORIZON,
+ RIPNG_SPLIT_HORIZON_POISONED_REVERSE
+} split_horizon_policy_t;
/* RIPng specific interface configuration. */
struct ripng_interface
@@ -230,6 +244,10 @@ struct ripng_interface
/* RIPng is running on this interface. */
int running;
+ /* Split horizon flag. */
+ split_horizon_policy_t split_horizon;
+ split_horizon_policy_t split_horizon_default;
+
/* For filter type slot. */
#define RIPNG_FILTER_IN 0
#define RIPNG_FILTER_OUT 1
@@ -244,8 +262,12 @@ struct ripng_interface
/* Route-map. */
struct route_map *routemap[RIPNG_FILTER_MAX];
+#ifdef notyet
+#if 0
/* RIPng tag configuration. */
struct ripng_tag *rtag;
+#endif /* 0 */
+#endif /* notyet */
/* Default information originate. */
u_char default_originate;
@@ -260,6 +282,29 @@ struct ripng_interface
int passive;
};
+/* RIPng peer information. */
+struct ripng_peer
+{
+ /* Peer address. */
+ struct in6_addr addr;
+
+ /* Peer RIPng tag value. */
+ int domain;
+
+ /* Last update time. */
+ time_t uptime;
+
+ /* Peer RIP version. */
+ u_char version;
+
+ /* Statistics. */
+ int recv_badpackets;
+ int recv_badroutes;
+
+ /* Timeout thread. */
+ struct thread *t_timeout;
+};
+
/* All RIPng events. */
enum ripng_event
{
@@ -296,15 +341,42 @@ extern struct thread_master *master;
/* Prototypes. */
void ripng_init ();
+void ripng_reset ();
+void ripng_clean ();
+void ripng_clean_network ();
+void ripng_interface_clean ();
+void ripng_interface_reset ();
+void ripng_passive_interface_clean ();
void ripng_if_init ();
+void ripng_route_map_init ();
+void ripng_route_map_reset ();
void ripng_terminate ();
-void ripng_zclient_start ();
+ /* zclient_init() is done by ripng_zebra.c:zebra_init() */
void zebra_init ();
+void ripng_zclient_start ();
+void ripng_zclient_reset ();
+void ripng_offset_init ();
+
+int config_write_ripng_offset_list (struct vty *);
+
+void ripng_peer_init ();
+void ripng_peer_update (struct sockaddr_in6 *, u_char);
+void ripng_peer_bad_route (struct sockaddr_in6 *);
+void ripng_peer_bad_packet (struct sockaddr_in6 *);
+void ripng_peer_display (struct vty *);
+struct ripng_peer *ripng_peer_lookup (struct in6_addr *);
+struct ripng_peer *ripng_peer_lookup_next (struct in6_addr *);
+
+int ripng_offset_list_apply_in (struct prefix_ipv6 *, struct interface *, u_char *);
+int ripng_offset_list_apply_out (struct prefix_ipv6 *, struct interface *, u_char *);
+void ripng_offset_clean ();
+
struct ripng_info * ripng_info_new ();
void ripng_info_free (struct ripng_info *rinfo);
void ripng_event (enum ripng_event, int);
int ripng_request (struct interface *ifp);
-void ripng_redistribute_add (int, int, struct prefix_ipv6 *, unsigned int);
+void ripng_redistribute_add (int, int, struct prefix_ipv6 *, unsigned int,
+ struct in6_addr *);
void ripng_redistribute_delete (int, int, struct prefix_ipv6 *, unsigned int);
void ripng_redistribute_withdraw (int type);
@@ -313,6 +385,17 @@ void ripng_if_rmap_update_interface (struct interface *);
void ripng_zebra_ipv6_add (struct prefix_ipv6 *p, struct in6_addr *nexthop, unsigned int ifindex);
void ripng_zebra_ipv6_delete (struct prefix_ipv6 *p, struct in6_addr *nexthop, unsigned int ifindex);
-void ripng_route_map_init ();
+
+void ripng_redistribute_clean ();
+
+const char *inet6_ntop (struct in6_addr *p);
+
+int ripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p,
+ struct in6_addr *nexthop, u_int16_t tag, u_char metric);
+int ripng_send_packet (caddr_t buf, int bufsize, struct sockaddr_in6 *to,
+ struct interface *ifp);
+
+void ripng_packet_dump (struct ripng_packet *packet, int size, char *sndrcv);
+
#endif /* _ZEBRA_RIPNG_RIPNGD_H */
diff --git a/vtysh/extract.pl b/vtysh/extract.pl
index ca88cf7b..9a65f145 100755
--- a/vtysh/extract.pl
+++ b/vtysh/extract.pl
@@ -109,7 +109,11 @@ foreach (@ARGV) {
}
}
if ($file =~ /if_rmap.c/) {
- $protocol = "VTYSH_RIPNGD";
+ if ($defun_array[1] =~ m/ipv6/) {
+ $protocol = "VTYSH_RIPNGD";
+ } else {
+ $protocol = "VTYSH_RIPD";
+ }
}
} else {
($protocol) = ($file =~ /\/([a-z0-9]+)/);
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index eca9a0a1..6000f817 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -217,7 +217,7 @@ vtysh_client_config (struct vtysh_client *vclient, char *line)
/* Allow enough room for buffer to read more than a few pages from socket
*/
- bufsz = 5 * sysconf(_SC_PAGESIZE) + 1;
+ bufsz = 5 * getpagesize() + 1;
buf = XMALLOC(MTYPE_TMP, bufsz);
memset(buf, 0, bufsz);
pbuf = buf;
@@ -350,6 +350,8 @@ vtysh_pager_init ()
{
vtysh_pager_name = getenv ("VTYSH_PAGER");
if (! vtysh_pager_name)
+ vtysh_pager_name = getenv ("PAGER");
+ if (! vtysh_pager_name)
vtysh_pager_name = "more";
}
@@ -361,6 +363,7 @@ vtysh_execute_func (char *line, int pager)
vector vline;
struct cmd_element *cmd;
FILE *fp = NULL;
+ int closepager=0;
/* Split readline string up into the vector */
vline = cmd_make_strvec (line);
@@ -376,27 +379,29 @@ vtysh_execute_func (char *line, int pager)
{
case CMD_WARNING:
if (vty->type == VTY_FILE)
- printf ("Warning...\n");
+ fprintf (stdout,"Warning...\n");
break;
case CMD_ERR_AMBIGUOUS:
- printf ("%% Ambiguous command.\n");
+ fprintf (stdout,"%% Ambiguous command.\n");
break;
case CMD_ERR_NO_MATCH:
- printf ("%% Unknown command.\n");
+ fprintf (stdout,"%% Unknown command.\n");
break;
case CMD_ERR_INCOMPLETE:
- printf ("%% Command incomplete.\n");
+ fprintf (stdout,"%% Command incomplete.\n");
break;
case CMD_SUCCESS_DAEMON:
{
if (pager && vtysh_pager_name)
{
- fp = popen ("more", "w");
+ fp = popen (vtysh_pager_name, "w");
if (fp == NULL)
{
- perror ("popen");
- exit (1);
+ perror ("popen failed for pager");
+ fp = stdout;
}
+ else
+ closepager=1;
}
else
fp = stdout;
@@ -425,12 +430,11 @@ vtysh_execute_func (char *line, int pager)
if (vline == NULL)
{
- if (pager && vtysh_pager_name && fp)
+ if (pager && vtysh_pager_name && fp && closepager)
{
if (pclose (fp) == -1)
{
- perror ("pclose");
- exit (1);
+ perror ("pclose failed for pager");
}
fp = NULL;
}
@@ -478,12 +482,11 @@ vtysh_execute_func (char *line, int pager)
(*cmd->func) (cmd, vty, 0, NULL);
}
}
- if (pager && vtysh_pager_name && fp)
+ if (pager && vtysh_pager_name && fp && closepager)
{
if (pclose (fp) == -1)
{
- perror ("pclose");
- exit (1);
+ perror ("pclose failed for pager");
}
fp = NULL;
}
@@ -558,16 +561,16 @@ vtysh_config_from_file (struct vty *vty, FILE *fp)
{
case CMD_WARNING:
if (vty->type == VTY_FILE)
- printf ("Warning...\n");
+ fprintf (stdout,"Warning...\n");
break;
case CMD_ERR_AMBIGUOUS:
- printf ("%% Ambiguous command.\n");
+ fprintf (stdout,"%% Ambiguous command.\n");
break;
case CMD_ERR_NO_MATCH:
- printf ("%% Unknown command: %s", vty->buf);
+ fprintf (stdout,"%% Unknown command: %s", vty->buf);
break;
case CMD_ERR_INCOMPLETE:
- printf ("%% Command incomplete.\n");
+ fprintf (stdout,"%% Command incomplete.\n");
break;
case CMD_SUCCESS_DAEMON:
{
@@ -628,20 +631,20 @@ vtysh_rl_describe ()
describe = cmd_describe_command (vline, vty, &ret);
- printf ("\n");
+ fprintf (stdout,"\n");
/* Ambiguous and no match error. */
switch (ret)
{
case CMD_ERR_AMBIGUOUS:
cmd_free_strvec (vline);
- printf ("%% Ambiguous command.\n");
+ fprintf (stdout,"%% Ambiguous command.\n");
rl_on_new_line ();
return 0;
break;
case CMD_ERR_NO_MATCH:
cmd_free_strvec (vline);
- printf ("%% There is no matched command.\n");
+ fprintf (stdout,"%% There is no matched command.\n");
rl_on_new_line ();
return 0;
break;
@@ -672,10 +675,10 @@ vtysh_rl_describe ()
continue;
if (! desc->str)
- printf (" %-s\n",
+ fprintf (stdout," %-s\n",
desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd);
else
- printf (" %-*s %s\n",
+ fprintf (stdout," %-*s %s\n",
width,
desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
desc->str);
@@ -695,7 +698,7 @@ vtysh_rl_describe ()
int complete_status;
char *
-command_generator (char *text, int state)
+command_generator (const char *text, int state)
{
vector vline;
static char **matched = NULL;
@@ -730,7 +733,7 @@ new_completion (char *text, int start, int end)
{
char **matches;
- matches = completion_matches (text, command_generator);
+ matches = rl_completion_matches (text, command_generator);
if (matches)
{
@@ -1151,7 +1154,7 @@ ALIAS (vtysh_exit_ospf6d,
"quit",
"Exit current mode and down to previous mode\n")
-DEFUNSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_OSPF6D,
+DEFUNSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D,
vtysh_interface,
vtysh_interface_cmd,
"interface IFNAME",
@@ -1162,22 +1165,26 @@ DEFUNSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_OSPF6D,
return CMD_SUCCESS;
}
-DEFSH (VTYSH_RIPD|VTYSH_BGPD,
- set_ip_nexthop_cmd,
- "set ip next-hop A.B.C.D",
- SET_STR
- IP_STR
- "Next hop address\n"
- "IP address of next hop\n")
-
-DEFSH (VTYSH_RMAP,
- set_metric_cmd,
- "set metric <0-4294967295>",
- SET_STR
- "Metric value for destination routing protocol\n"
- "Metric value\n")
+DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D,
+ vtysh_no_interface_cmd,
+ "no interface IFNAME",
+ NO_STR
+ "Delete a pseudo interface's configuration\n"
+ "Interface's name\n")
+
+DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD,
+ interface_desc_cmd,
+ "description .LINE",
+ "Interface specific description\n"
+ "Characters describing this interface\n")
+
+DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD,
+ no_interface_desc_cmd,
+ "no description",
+ NO_STR
+ "Interface specific description\n")
-DEFUNSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_OSPF6D,
+DEFUNSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D,
vtysh_exit_interface,
vtysh_exit_interface_cmd,
"exit",
@@ -1203,7 +1210,7 @@ DEFUN (vtysh_write_terminal,
if (vtysh_pager_name)
{
- fp = popen ("more", "w");
+ fp = popen (vtysh_pager_name, "w");
if (fp == NULL)
{
perror ("popen");
@@ -1242,11 +1249,42 @@ DEFUN (vtysh_write_terminal,
return CMD_SUCCESS;
}
-DEFUN (vtysh_write_memory,
- vtysh_write_memory_cmd,
- "write memory",
- "Write running configuration to memory, network, or terminal\n"
- "Write configuration to the file (same as write file)\n")
+struct vtysh_writeconfig_t {
+ int daemon;
+ int integrated;
+} vtysh_wc = {-1,0};
+
+DEFUN (vtysh_write_config,
+ vtysh_write_config_cmd,
+ "write-config (daemon|integrated)",
+ "Specify config files to write to\n"
+ "Write per daemon file\n"
+ "Write integrated file\n"
+)
+{
+ if (!strncmp(argv[0],"d",1)) {
+ vtysh_wc.daemon = 1;
+ } else if (!strncmp(argv[0],"i",1)) {
+ vtysh_wc.integrated = 1;
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_vtysh_write_config,
+ no_vtysh_write_config_cmd,
+ "no write-config (daemon|integrated)",
+ "Negate per daemon and/or integrated config files\n"
+)
+{
+ if (!strncmp(argv[0],"d",1)) {
+ vtysh_wc.daemon = 0;
+ } else if (!strncmp(argv[0],"i",1)) {
+ vtysh_wc.integrated = 0;
+ }
+ return CMD_SUCCESS;
+}
+
+int write_config_integrated(void)
{
int ret;
mode_t old_umask;
@@ -1263,22 +1301,20 @@ DEFUN (vtysh_write_memory,
strcat (integrate_sav, CONF_BACKUP_EXT);
- printf ("Building Configuration...\n");
+ fprintf (stdout,"Building Configuration...\n");
/* Move current configuration file to backup config file */
unlink (integrate_sav);
rename (integrate_default, integrate_sav);
-
+ free (integrate_sav);
+
fp = fopen (integrate_default, "w");
if (fp == NULL)
{
- printf ("%% Can't open configuration file %s.\n", integrate_default);
+ fprintf (stdout,"%% Can't open configuration file %s.\n", integrate_default);
umask (old_umask);
return CMD_SUCCESS;
}
- else
- printf ("[OK]\n");
-
vtysh_config_write (fp);
@@ -1293,10 +1329,46 @@ DEFUN (vtysh_write_memory,
fclose (fp);
+ fprintf(stdout,"Integrated configuration saved to %s\n",integrate_default);
+
+ fprintf (stdout,"[OK]\n");
+
umask (old_umask);
return CMD_SUCCESS;
}
+DEFUN (vtysh_write_memory,
+ vtysh_write_memory_cmd,
+ "write memory",
+ "Write running configuration to memory, network, or terminal\n"
+ "Write configuration to the file (same as write file)\n")
+{
+ int ret = CMD_SUCCESS;
+ char line[] = "write memory\n";
+
+ /* if integrated Zebra.conf explicitely set */
+ if (vtysh_wc.integrated == 1) {
+ ret = write_config_integrated();
+ }
+
+ if (!vtysh_wc.daemon) {
+ return ret;
+ }
+
+ fprintf (stdout,"Building Configuration...\n");
+
+ ret = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_ZEBRA], line, stdout);
+ ret = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIP], line, stdout);
+ ret = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIPNG], line, stdout);
+ ret = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF], line, stdout);
+ ret = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF6], line, stdout);
+ ret = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_BGP], line, stdout);
+
+ fprintf (stdout,"[OK]\n");
+
+ return ret;
+}
+
ALIAS (vtysh_write_memory,
vtysh_copy_runningconfig_startupconfig_cmd,
"copy running-config startup-config",
@@ -1310,6 +1382,11 @@ ALIAS (vtysh_write_memory,
"Write running configuration to memory, network, or terminal\n"
"Write configuration to the file (same as write memory)\n")
+ALIAS (vtysh_write_memory,
+ vtysh_write_cmd,
+ "write",
+ "Write running configuration to memory, network, or terminal\n")
+
ALIAS (vtysh_write_terminal,
vtysh_show_running_config_cmd,
"show running-config",
@@ -1404,6 +1481,16 @@ DEFUN (vtysh_telnet_port,
return CMD_SUCCESS;
}
+DEFUN (vtysh_ssh,
+ vtysh_ssh_cmd,
+ "ssh WORD",
+ "Open an ssh connection\n"
+ "[user@]host\n")
+{
+ execute_command ("ssh", 1, argv[0], NULL);
+ return CMD_SUCCESS;
+}
+
DEFUN (vtysh_start_shell,
vtysh_start_shell_cmd,
"start-shell",
@@ -1543,14 +1630,6 @@ vtysh_connect (struct vtysh_client *vclient, char *path)
exit (1);
}
- if (euid != s_stat.st_uid
- || !(s_stat.st_mode & S_IWUSR)
- || !(s_stat.st_mode & S_IRUSR))
- {
- fprintf (stderr, "vtysh_connect(%s): No permission to access socket\n",
- path);
- exit (1);
- }
}
sock = socket (AF_UNIX, SOCK_STREAM, 0);
@@ -1589,20 +1668,20 @@ void
vtysh_connect_all()
{
/* Clear each daemons client structure. */
- vtysh_connect (&vtysh_client[VTYSH_INDEX_ZEBRA], ZEBRA_PATH);
- vtysh_connect (&vtysh_client[VTYSH_INDEX_RIP], RIP_PATH);
- vtysh_connect (&vtysh_client[VTYSH_INDEX_RIPNG], RIPNG_PATH);
- vtysh_connect (&vtysh_client[VTYSH_INDEX_OSPF], OSPF_PATH);
- vtysh_connect (&vtysh_client[VTYSH_INDEX_OSPF6], OSPF6_PATH);
- vtysh_connect (&vtysh_client[VTYSH_INDEX_BGP], BGP_PATH);
+ vtysh_connect (&vtysh_client[VTYSH_INDEX_ZEBRA], ZEBRA_VTYSH_PATH);
+ vtysh_connect (&vtysh_client[VTYSH_INDEX_RIP], RIP_VTYSH_PATH);
+ vtysh_connect (&vtysh_client[VTYSH_INDEX_RIPNG], RIPNG_VTYSH_PATH);
+ vtysh_connect (&vtysh_client[VTYSH_INDEX_OSPF], OSPF_VTYSH_PATH);
+ vtysh_connect (&vtysh_client[VTYSH_INDEX_OSPF6], OSPF6_VTYSH_PATH);
+ vtysh_connect (&vtysh_client[VTYSH_INDEX_BGP], BGP_VTYSH_PATH);
}
/* To disable readline's filename completion */
-int
-vtysh_completion_entry_function (int ignore, int invoking_key)
+char *
+vtysh_completion_entry_function (const char *ignore, int invoking_key)
{
- return 0;
+ return NULL;
}
void
@@ -1739,6 +1818,8 @@ vtysh_init_vty ()
install_element (KEYCHAIN_KEY_NODE, &vtysh_end_all_cmd);
install_element (RMAP_NODE, &vtysh_end_all_cmd);
+ install_element (INTERFACE_NODE, &interface_desc_cmd);
+ install_element (INTERFACE_NODE, &no_interface_desc_cmd);
install_element (INTERFACE_NODE, &vtysh_end_all_cmd);
install_element (INTERFACE_NODE, &vtysh_exit_interface_cmd);
install_element (INTERFACE_NODE, &vtysh_quit_interface_cmd);
@@ -1769,9 +1850,11 @@ vtysh_init_vty ()
install_element (KEYCHAIN_NODE, &key_chain_cmd);
install_element (KEYCHAIN_KEY_NODE, &key_chain_cmd);
install_element (CONFIG_NODE, &vtysh_interface_cmd);
+ install_element (CONFIG_NODE, &vtysh_no_interface_cmd);
install_element (ENABLE_NODE, &vtysh_show_running_config_cmd);
install_element (ENABLE_NODE, &vtysh_copy_runningconfig_startupconfig_cmd);
install_element (ENABLE_NODE, &vtysh_write_file_cmd);
+ install_element (ENABLE_NODE, &vtysh_write_cmd);
/* write terminal command */
install_element (ENABLE_NODE, &vtysh_write_terminal_cmd);
@@ -1811,6 +1894,7 @@ vtysh_init_vty ()
install_element (VIEW_NODE, &vtysh_traceroute_cmd);
install_element (VIEW_NODE, &vtysh_telnet_cmd);
install_element (VIEW_NODE, &vtysh_telnet_port_cmd);
+ install_element (VIEW_NODE, &vtysh_ssh_cmd);
install_element (ENABLE_NODE, &vtysh_ping_cmd);
install_element (ENABLE_NODE, &vtysh_traceroute_cmd);
install_element (ENABLE_NODE, &vtysh_telnet_cmd);
@@ -1819,9 +1903,6 @@ vtysh_init_vty ()
install_element (ENABLE_NODE, &vtysh_start_bash_cmd);
install_element (ENABLE_NODE, &vtysh_start_zsh_cmd);
- install_element (RMAP_NODE, &set_metric_cmd);
- install_element (RMAP_NODE, &set_ip_nexthop_cmd);
-
install_element (CONFIG_NODE, &vtysh_log_stdout_cmd);
install_element (CONFIG_NODE, &no_vtysh_log_stdout_cmd);
install_element (CONFIG_NODE, &vtysh_log_file_cmd);
@@ -1832,4 +1913,6 @@ vtysh_init_vty ()
install_element (CONFIG_NODE, &no_vtysh_log_trap_cmd);
install_element (CONFIG_NODE, &vtysh_log_record_priority_cmd);
install_element (CONFIG_NODE, &no_vtysh_log_record_priority_cmd);
+ install_element (CONFIG_NODE, &vtysh_write_config_cmd);
+ install_element (CONFIG_NODE, &no_vtysh_write_config_cmd);
}
diff --git a/zebra/ChangeLog b/zebra/ChangeLog
index 1f392197..7f3d724c 100644
--- a/zebra/ChangeLog
+++ b/zebra/ChangeLog
@@ -1,3 +1,15 @@
+2003-05-25 Jim Crumpler <Jim.Crumpler@edion.com>
+
+ * zserv.c: Add "ip forwarding" command.
+
+2003-05-16 Gilad Arnold <gilad.arnold@terayon.com>
+
+ * zebra_rib.c: Fix memory leaks for ifname nexthops
+
+2003-04-19 Israel Keys <ikeys@agile.tv>
+
+ * rt_netlink.c: BLOCK on netlink while initialising
+
2003-02-06 Francois Deppierraz <francois@ctrlaltdel.ch>
* rt_netlink.c (netlink_route_multipath): Set RTM_F_EQUALIZE when
diff --git a/zebra/connected.c b/zebra/connected.c
index cb43074b..280e423e 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -69,7 +69,7 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
p.prefixlen = addr->prefixlen;
/* Point-to-point check. */
- if (if_is_pointopoint (ifp))
+ if (ifc_pointopoint (ifc) && dest)
p.prefix = dest->prefix;
else
p.prefix = addr->prefix;
@@ -162,7 +162,8 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
p.family = AF_INET;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp))
+ /* Point-to-point check. */
+ if (dest && ifc_pointopoint (ifc))
p.prefix = dest->prefix;
else
p.prefix = addr->prefix;
@@ -249,7 +250,7 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
p.family = AF_INET6;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp) && dest)
+ if (ifc_pointopoint (ifc) && dest)
{
if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
p.prefix = addr->prefix;
@@ -262,8 +263,11 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
/* Apply mask to the network. */
apply_mask_ipv6 (&p);
+#if ! defined (MUSICA) && ! defined (LINUX)
+ /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
return;
+#endif
rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
@@ -339,7 +343,7 @@ connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
p.family = AF_INET6;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp) && dest)
+ if (ifc_pointopoint (ifc) && dest)
{
if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
p.prefix = addr->prefix;
diff --git a/zebra/interface.h b/zebra/interface.h
index dbfa8221..3ab624f2 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -31,7 +31,9 @@
/* Router advertisement feature. */
#if (defined(LINUX_IPV6) && (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1)) || defined(KAME)
-#define RTADV
+ #ifdef HAVE_RTADV
+ #define RTADV
+ #endif
#endif
#ifdef RTADV
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index 4c341e8b..f8e7f22b 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -489,8 +489,10 @@ if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc)
#endif
memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6));
+#ifdef HAVE_IFRA_LIFETIME
addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
+#endif
ret = if_ioctl_ipv6 (SIOCAIFADDR_IN6, (caddr_t) &addreq);
if (ret < 0)
@@ -528,8 +530,10 @@ if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc)
#endif
memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6));
+#ifdef HAVE_IFRA_LIFETIME
addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
+#endif
ret = if_ioctl_ipv6 (SIOCDIFADDR_IN6, (caddr_t) &addreq);
if (ret < 0)
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index b5431d3e..17893a87 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -477,6 +477,12 @@ rtm_read (struct rt_msghdr *rtm)
if (flags & RTF_STATIC)
SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC);
+ /* This is a reject or blackhole route */
+ if (flags & RTF_REJECT)
+ SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT);
+ if (flags & RTF_BLACKHOLE)
+ SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE);
+
if (dest.sa.sa_family == AF_INET)
{
struct prefix_ipv4 p;
@@ -620,6 +626,9 @@ rtm_write (int message,
/* Additional flags. */
if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
msg.rtm.rtm_flags |= RTF_BLACKHOLE;
+ if (zebra_flags & ZEBRA_FLAG_REJECT)
+ msg.rtm.rtm_flags |= RTF_REJECT;
+
#ifdef HAVE_SIN_LEN
#define SOCKADDRSET(X,R) \
@@ -754,9 +763,8 @@ kernel_read (struct thread *thread)
thread_add_read (master, kernel_read, NULL, sock);
-#ifdef DEBUG
- rtmsg_debug (&buf.r.rtm);
-#endif /* DEBUG */
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ rtmsg_debug (&buf.r.rtm);
rtm = &buf.r.rtm;
@@ -779,6 +787,8 @@ kernel_read (struct thread *thread)
break;
#endif /* RTM_IFANNOUNCE */
default:
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_info("Unprocessed RTM_type: %d", rtm->rtm_type);
break;
}
return 0;
diff --git a/zebra/rib.h b/zebra/rib.h
index f5012610..5b0dcfe9 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -84,6 +84,13 @@ struct static_ipv4
struct in_addr ipv4;
char *ifname;
} gate;
+
+ /* bit flags */
+ u_char flags;
+/*
+ see ZEBRA_FLAG_REJECT
+ ZEBRA_FLAG_BLACKHOLE
+ */
};
#ifdef HAVE_IPV6
@@ -106,6 +113,13 @@ struct static_ipv6
/* Nexthop value. */
struct in6_addr ipv6;
char *ifname;
+
+ /* bit flags */
+ u_char flags;
+/*
+ see ZEBRA_FLAG_REJECT
+ ZEBRA_FLAG_BLACKHOLE
+ */
};
#endif /* HAVE_IPV6 */
@@ -217,7 +231,7 @@ void rib_init ();
int
static_add_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname,
- u_char distance, u_int32_t vrf_id);
+ u_char flags, u_char distance, u_int32_t vrf_id);
int
static_delete_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname,
@@ -240,7 +254,7 @@ extern struct route_table *rib_table_ipv6;
int
static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
- char *ifname, u_char distance, u_int32_t vrf_id);
+ char *ifname, u_char flags, u_char distance, u_int32_t vrf_id);
int
static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index f4f51034..f1784a77 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1193,7 +1193,8 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate,
req.r.rtm_table = table;
req.r.rtm_dst_len = length;
- if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
+ if ((zebra_flags & ZEBRA_FLAG_BLACKHOLE)
+ || (zebra_flags & ZEBRA_FLAG_REJECT))
discard = 1;
else
discard = 0;
@@ -1203,10 +1204,16 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate,
req.r.rtm_protocol = RTPROT_ZEBRA;
req.r.rtm_scope = RT_SCOPE_UNIVERSE;
- if (discard)
- req.r.rtm_type = RTN_BLACKHOLE;
+ if (discard)
+ {
+ if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
+ req.r.rtm_type = RTN_BLACKHOLE;
+ else if (zebra_flags & ZEBRA_FLAG_REJECT)
+ req.r.rtm_type = RTN_UNREACHABLE;
+ else assert(RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
+ }
else
- req.r.rtm_type = RTN_UNICAST;
+ req.r.rtm_type = RTN_UNICAST;
}
if (dest)
@@ -1266,7 +1273,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
req.r.rtm_flags |= RTM_F_EQUALIZE;
#endif /* RTM_F_EQUALIZE */
- if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
+ if ((rib->flags & ZEBRA_FLAG_BLACKHOLE)
+ || (rib->flags & ZEBRA_FLAG_REJECT))
discard = 1;
else
discard = 0;
@@ -1276,10 +1284,16 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
req.r.rtm_protocol = RTPROT_ZEBRA;
req.r.rtm_scope = RT_SCOPE_UNIVERSE;
- if (discard)
- req.r.rtm_type = RTN_BLACKHOLE;
+ if (discard)
+ {
+ if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
+ req.r.rtm_type = RTN_BLACKHOLE;
+ else if (rib->flags & ZEBRA_FLAG_REJECT)
+ req.r.rtm_type = RTN_UNREACHABLE;
+ else assert(RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
+ }
else
- req.r.rtm_type = RTN_UNICAST;
+ req.r.rtm_type = RTN_UNICAST;
}
addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index 363363f7..d603c60d 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -132,15 +132,14 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib, int family)
|| nexthop->type == NEXTHOP_TYPE_IFNAME
|| nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
ifindex = nexthop->ifindex;
- if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
- {
- struct in_addr loopback;
-
- loopback.s_addr = htonl (INADDR_LOOPBACK);
- sin_gate.sin_addr = loopback;
- gate = 1;
- }
- }
+ if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
+ {
+ struct in_addr loopback;
+ loopback.s_addr = htonl (INADDR_LOOPBACK);
+ sin_gate.sin_addr = loopback;
+ gate = 1;
+ }
+ }
if (cmd == RTM_ADD)
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index ec07e2e3..4098db26 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -187,8 +187,8 @@ nexthop_delete (struct rib *rib, struct nexthop *nexthop)
void
nexthop_free (struct nexthop *nexthop)
{
- if (nexthop->type == NEXTHOP_TYPE_IFNAME && nexthop->ifname)
- free (nexthop->ifname);
+ if (nexthop->ifname)
+ XFREE (0, nexthop->ifname);
XFREE (MTYPE_NEXTHOP, nexthop);
}
@@ -215,7 +215,7 @@ nexthop_ifname_add (struct rib *rib, char *ifname)
nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
memset (nexthop, 0, sizeof (struct nexthop));
nexthop->type = NEXTHOP_TYPE_IFNAME;
- nexthop->ifname = strdup (ifname);
+ nexthop->ifname = XSTRDUP (0, ifname);
nexthop_add (rib, nexthop);
@@ -305,7 +305,6 @@ nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
}
#endif /* HAVE_IPV6 */
-
struct nexthop *
nexthop_blackhole_add (struct rib *rib)
{
@@ -855,11 +854,13 @@ rib_process (struct route_node *rn, struct rib *del)
struct rib *next;
struct rib *fib = NULL;
struct rib *select = NULL;
+ int installed = 0;
+ struct nexthop *nexthop = NULL;
for (rib = rn->info; rib; rib = next)
{
next = rib->next;
-
+
/* Currently installed rib. */
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
fib = rib;
@@ -898,6 +899,22 @@ rib_process (struct route_node *rn, struct rib *del)
rib_install_kernel (rn, select);
redistribute_add (&rn->p, select);
}
+ else if (! RIB_SYSTEM_ROUTE (select))
+ {
+ /* Housekeeping code to deal with
+ race conditions in kernel with linux
+ netlink reporting interface up before IPv4 or IPv6 protocol
+ is ready to add routes.
+ This makes sure the routes are IN the kernel.
+ */
+
+ for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
+ {
+ if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+ installed = 1;
+ }
+ if (! installed) rib_install_kernel (rn, select);
+ }
return;
}
@@ -1271,9 +1288,9 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
case STATIC_IPV4_IFNAME:
nexthop_ifname_add (rib, si->gate.ifname);
break;
- case STATIC_IPV4_BLACKHOLE:
- nexthop_blackhole_add (rib);
- break;
+ case STATIC_IPV4_BLACKHOLE:
+ nexthop_blackhole_add (rib);
+ break;
}
rib_process (rn, NULL);
}
@@ -1296,11 +1313,14 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
case STATIC_IPV4_IFNAME:
nexthop_ifname_add (rib, si->gate.ifname);
break;
- case STATIC_IPV4_BLACKHOLE:
- nexthop_blackhole_add (rib);
- break;
+ case STATIC_IPV4_BLACKHOLE:
+ nexthop_blackhole_add (rib);
+ break;
}
+ /* Save the flags of this static routes (reject, blackhole) */
+ rib->flags = si->flags;
+
/* Link this rib to the tree. */
rib_addnode (rn, rib);
@@ -1390,7 +1410,7 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
/* Add static route into static route configuration. */
int
static_add_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname,
- u_char distance, u_int32_t vrf_id)
+ u_char flags, u_char distance, u_int32_t vrf_id)
{
u_char type = 0;
struct route_node *rn;
@@ -1443,6 +1463,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname,
si->type = type;
si->distance = distance;
+ si->flags = flags;
if (gate)
si->gate.ipv4 = *gate;
@@ -1536,6 +1557,8 @@ static_delete_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname,
si->next->prev = si->prev;
/* Free static route configuration. */
+ if (ifname)
+ XFREE (0, si->gate.ifname);
XFREE (MTYPE_STATIC_IPV4, si);
return 1;
@@ -1547,8 +1570,14 @@ int
rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
struct in6_addr *gate, unsigned int ifindex, int table)
{
- if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix))
+ if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
+#if defined (MUSICA) || defined (LINUX)
+ /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
+ if (p->prefixlen == 96)
+ return 0;
+#endif /* MUSICA */
return 1;
+ }
if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
&& p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
{
@@ -1849,6 +1878,9 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
break;
}
+ /* Save the flags of this static routes (reject, blackhole) */
+ rib->flags = si->flags;
+
/* Link this rib to the tree. */
rib_addnode (rn, rib);
@@ -1938,7 +1970,7 @@ static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
/* Add static route into static route configuration. */
int
static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
- char *ifname, u_char distance, u_int32_t vrf_id)
+ char *ifname, u_char flags, u_char distance, u_int32_t vrf_id)
{
struct route_node *rn;
struct static_ipv6 *si;
@@ -1973,6 +2005,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
si->type = type;
si->distance = distance;
+ si->flags = flags;
switch (type)
{
@@ -2060,6 +2093,8 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
si->next->prev = si->prev;
/* Free static route configuration. */
+ if (ifname)
+ XFREE (0, si->ifname);
XFREE (MTYPE_STATIC_IPV6, si);
return 1;
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index f6e7f51d..c8168c90 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -89,7 +89,7 @@ route_type_char (u_char type)
int
zebra_static_ipv4 (struct vty *vty, int add_cmd,
char *dest_str, char *mask_str, char *gate_str,
- char *distance_str)
+ char *flag_str, char *distance_str)
{
int ret;
u_char distance;
@@ -97,6 +97,7 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd,
struct in_addr gate;
struct in_addr mask;
char *ifname;
+ u_char flag = 0;
ret = str2prefix (dest_str, &p);
if (ret <= 0)
@@ -110,10 +111,10 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd,
{
ret = inet_aton (mask_str, &mask);
if (ret == 0)
- {
- vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
+ {
+ vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
p.prefixlen = ip_masklen (mask);
}
@@ -129,13 +130,35 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd,
/* Null0 static route. */
if (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)
{
+ if (flag_str)
+ {
+ vty_out (vty, "%% can not have flag %s with Null0%s", flag_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
if (add_cmd)
- static_add_ipv4 (&p, NULL, NULL, distance, 0);
+ static_add_ipv4 (&p, NULL, NULL, 0, distance, 0);
else
- static_delete_ipv4 (&p, NULL, NULL, distance, 0);
+ static_delete_ipv4 (&p, NULL, NULL, distance, 0);
return CMD_SUCCESS;
}
+ /* Route flags */
+ if (flag_str) {
+ switch(flag_str[0]) {
+ case 'r':
+ case 'R': /* XXX */
+ SET_FLAG (flag, ZEBRA_FLAG_REJECT);
+ break;
+ case 'b':
+ case 'B': /* XXX */
+ SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE);
+ break;
+ default:
+ vty_out (vty, "%% Malformed flag %s %s", flag_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
/* When gateway is A.B.C.D format, gate is treated as nexthop
address other case gate is treated as interface name. */
ret = inet_aton (gate_str, &gate);
@@ -145,7 +168,7 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd,
ifname = gate_str;
if (add_cmd)
- static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, distance, 0);
+ static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, distance, 0);
else
static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, distance, 0);
@@ -163,7 +186,21 @@ DEFUN (ip_route,
"IP gateway interface name\n"
"Null interface\n")
{
- return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL);
+ return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL);
+}
+
+DEFUN (ip_route_flags,
+ ip_route_flags_cmd,
+ "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole)",
+ IP_STR
+ "Establish static routes\n"
+ "IP destination prefix (e.g. 10.0.0.0/8)\n"
+ "IP gateway address\n"
+ "IP gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n")
+{
+ return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL);
}
/* Mask as A.B.C.D format. */
@@ -178,7 +215,22 @@ DEFUN (ip_route_mask,
"IP gateway interface name\n"
"Null interface\n")
{
- return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL);
+ return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL);
+}
+
+DEFUN (ip_route_mask_flags,
+ ip_route_mask_flags_cmd,
+ "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole)",
+ IP_STR
+ "Establish static routes\n"
+ "IP destination prefix\n"
+ "IP destination prefix mask\n"
+ "IP gateway address\n"
+ "IP gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n")
+{
+ return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL);
}
/* Distance option value. */
@@ -193,7 +245,22 @@ DEFUN (ip_route_distance,
"Null interface\n"
"Distance value for this route\n")
{
- return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2]);
+ return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2]);
+}
+
+DEFUN (ip_route_flags_distance,
+ ip_route_flags_distance_cmd,
+ "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>",
+ IP_STR
+ "Establish static routes\n"
+ "IP destination prefix (e.g. 10.0.0.0/8)\n"
+ "IP gateway address\n"
+ "IP gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n"
+ "Distance value for this route\n")
+{
+ return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3]);
}
DEFUN (ip_route_mask_distance,
@@ -208,7 +275,23 @@ DEFUN (ip_route_mask_distance,
"Null interface\n"
"Distance value for this route\n")
{
- return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3]);
+ return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3]);
+}
+
+DEFUN (ip_route_mask_flags_distance,
+ ip_route_mask_flags_distance_cmd,
+ "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>",
+ IP_STR
+ "Establish static routes\n"
+ "IP destination prefix\n"
+ "IP destination prefix mask\n"
+ "IP gateway address\n"
+ "IP gateway interface name\n"
+ "Distance value for this route\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n")
+{
+ return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4]);
}
DEFUN (no_ip_route,
@@ -222,9 +305,21 @@ DEFUN (no_ip_route,
"IP gateway interface name\n"
"Null interface\n")
{
- return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL);
+ return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL);
}
+ALIAS (no_ip_route,
+ no_ip_route_flags_cmd,
+ "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole)",
+ NO_STR
+ IP_STR
+ "Establish static routes\n"
+ "IP destination prefix (e.g. 10.0.0.0/8)\n"
+ "IP gateway address\n"
+ "IP gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n")
+
DEFUN (no_ip_route_mask,
no_ip_route_mask_cmd,
"no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0)",
@@ -237,9 +332,22 @@ DEFUN (no_ip_route_mask,
"IP gateway interface name\n"
"Null interface\n")
{
- return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL);
+ return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL);
}
+ALIAS (no_ip_route_mask,
+ no_ip_route_mask_flags_cmd,
+ "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole)",
+ NO_STR
+ IP_STR
+ "Establish static routes\n"
+ "IP destination prefix\n"
+ "IP destination prefix mask\n"
+ "IP gateway address\n"
+ "IP gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n")
+
DEFUN (no_ip_route_distance,
no_ip_route_distance_cmd,
"no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>",
@@ -252,7 +360,23 @@ DEFUN (no_ip_route_distance,
"Null interface\n"
"Distance value for this route\n")
{
- return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2]);
+ return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2]);
+}
+
+DEFUN (no_ip_route_flags_distance,
+ no_ip_route_flags_distance_cmd,
+ "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>",
+ NO_STR
+ IP_STR
+ "Establish static routes\n"
+ "IP destination prefix (e.g. 10.0.0.0/8)\n"
+ "IP gateway address\n"
+ "IP gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n"
+ "Distance value for this route\n")
+{
+ return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3]);
}
DEFUN (no_ip_route_mask_distance,
@@ -268,7 +392,24 @@ DEFUN (no_ip_route_mask_distance,
"Null interface\n"
"Distance value for this route\n")
{
- return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3]);
+ return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3]);
+}
+
+DEFUN (no_ip_route_mask_flags_distance,
+ no_ip_route_mask_flags_distance_cmd,
+ "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>",
+ NO_STR
+ IP_STR
+ "Establish static routes\n"
+ "IP destination prefix\n"
+ "IP destination prefix mask\n"
+ "IP gateway address\n"
+ "IP gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n"
+ "Distance value for this route\n")
+{
+ return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4]);
}
/* New RIB. Detailed information for IPv4 route. */
@@ -289,6 +430,10 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
vty_out (vty, ", best");
if (rib->refcnt)
vty_out (vty, ", refcnt %ld", rib->refcnt);
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
+ vty_out (vty, ", blackhole");
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
+ vty_out (vty, ", reject");
vty_out (vty, "%s", VTY_NEWLINE);
#define ONE_DAY_SECOND 60*60*24
@@ -339,9 +484,9 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
case NEXTHOP_TYPE_IFNAME:
vty_out (vty, " directly connected, %s", nexthop->ifname);
break;
- case NEXTHOP_TYPE_BLACKHOLE:
- vty_out (vty, " directly connected, via Null0");
- break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ vty_out (vty, " directly connected, via Null0");
+ break;
default:
break;
}
@@ -422,8 +567,9 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
case NEXTHOP_TYPE_IFNAME:
vty_out (vty, " is directly connected, %s", nexthop->ifname);
break;
- case NEXTHOP_TYPE_BLACKHOLE:
- vty_out (vty, " is directly connected, Null0");
+ case NEXTHOP_TYPE_BLACKHOLE:
+ vty_out (vty, " is directly connected, Null0");
+ break;
default:
break;
}
@@ -450,6 +596,11 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
}
}
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
+ vty_out (vty, ", bh");
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
+ vty_out (vty, ", rej");
+
if (rib->type == ZEBRA_ROUTE_RIP
|| rib->type == ZEBRA_ROUTE_OSPF
|| rib->type == ZEBRA_ROUTE_BGP)
@@ -808,11 +959,17 @@ static_config_ipv4 (struct vty *vty)
case STATIC_IPV4_IFNAME:
vty_out (vty, " %s", si->gate.ifname);
break;
- case STATIC_IPV4_BLACKHOLE:
- vty_out (vty, " Null0");
- break;
+ case STATIC_IPV4_BLACKHOLE:
+ vty_out (vty, " Null0");
+ break;
}
+ if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT))
+ vty_out (vty, " %s", "reject");
+
+ if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE))
+ vty_out (vty, " %s", "blackhole");
+
if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
vty_out (vty, " %d", si->distance);
vty_out (vty, "%s", VTY_NEWLINE);
@@ -826,7 +983,7 @@ static_config_ipv4 (struct vty *vty)
/* General fucntion for IPv6 static route. */
int
static_ipv6_func (struct vty *vty, int add_cmd, char *dest_str,
- char *gate_str, char *ifname, char *distance_str)
+ char *gate_str, char *ifname, char *flag_str, char *distance_str)
{
int ret;
u_char distance;
@@ -835,6 +992,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, char *dest_str,
struct in6_addr gate_addr;
u_char type = 0;
int table = 0;
+ u_char flag = 0;
ret = str2prefix (dest_str, &p);
if (ret <= 0)
@@ -846,6 +1004,23 @@ static_ipv6_func (struct vty *vty, int add_cmd, char *dest_str,
/* Apply mask for given prefix. */
apply_mask (&p);
+ /* Route flags */
+ if (flag_str) {
+ switch(flag_str[0]) {
+ case 'r':
+ case 'R': /* XXX */
+ SET_FLAG (flag, ZEBRA_FLAG_REJECT);
+ break;
+ case 'b':
+ case 'B': /* XXX */
+ SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE);
+ break;
+ default:
+ vty_out (vty, "%% Malformed flag %s %s", flag_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
/* Administrative distance. */
if (distance_str)
distance = atoi (distance_str);
@@ -883,7 +1058,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, char *dest_str,
}
if (add_cmd)
- static_add_ipv6 (&p, type, gate, ifname, distance, table);
+ static_add_ipv6 (&p, type, gate, ifname, flag, distance, table);
else
static_delete_ipv6 (&p, type, gate, ifname, distance, table);
@@ -899,7 +1074,21 @@ DEFUN (ipv6_route,
"IPv6 gateway address\n"
"IPv6 gateway interface name\n")
{
- return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL);
+ return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL);
+}
+
+DEFUN (ipv6_route_flags,
+ ipv6_route_flags_cmd,
+ "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)",
+ IP_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n")
+{
+ return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL);
}
DEFUN (ipv6_route_ifname,
@@ -911,7 +1100,21 @@ DEFUN (ipv6_route_ifname,
"IPv6 gateway address\n"
"IPv6 gateway interface name\n")
{
- return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL);
+ return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL);
+}
+
+DEFUN (ipv6_route_ifname_flags,
+ ipv6_route_ifname_flags_cmd,
+ "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)",
+ IP_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n")
+{
+ return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL);
}
DEFUN (ipv6_route_pref,
@@ -924,7 +1127,22 @@ DEFUN (ipv6_route_pref,
"IPv6 gateway interface name\n"
"Distance value for this prefix\n")
{
- return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2]);
+ return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2]);
+}
+
+DEFUN (ipv6_route_flags_pref,
+ ipv6_route_flags_pref_cmd,
+ "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>",
+ IP_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n"
+ "Distance value for this prefix\n")
+{
+ return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3]);
}
DEFUN (ipv6_route_ifname_pref,
@@ -937,7 +1155,22 @@ DEFUN (ipv6_route_ifname_pref,
"IPv6 gateway interface name\n"
"Distance value for this prefix\n")
{
- return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3]);
+ return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3]);
+}
+
+DEFUN (ipv6_route_ifname_flags_pref,
+ ipv6_route_ifname_flags_pref_cmd,
+ "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>",
+ IP_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n"
+ "Distance value for this prefix\n")
+{
+ return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4]);
}
DEFUN (no_ipv6_route,
@@ -950,9 +1183,21 @@ DEFUN (no_ipv6_route,
"IPv6 gateway address\n"
"IPv6 gateway interface name\n")
{
- return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL);
+ return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL);
}
+ALIAS (no_ipv6_route,
+ no_ipv6_route_flags_cmd,
+ "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)",
+ NO_STR
+ IP_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n")
+
DEFUN (no_ipv6_route_ifname,
no_ipv6_route_ifname_cmd,
"no ipv6 route X:X::X:X/M X:X::X:X INTERFACE",
@@ -963,9 +1208,21 @@ DEFUN (no_ipv6_route_ifname,
"IPv6 gateway address\n"
"IPv6 gateway interface name\n")
{
- return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL);
+ return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL);
}
+ALIAS (no_ipv6_route_ifname,
+ no_ipv6_route_ifname_flags_cmd,
+ "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)",
+ NO_STR
+ IP_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n")
+
DEFUN (no_ipv6_route_pref,
no_ipv6_route_pref_cmd,
"no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>",
@@ -977,7 +1234,24 @@ DEFUN (no_ipv6_route_pref,
"IPv6 gateway interface name\n"
"Distance value for this prefix\n")
{
- return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2]);
+ return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2]);
+}
+
+DEFUN (no_ipv6_route_flags_pref,
+ no_ipv6_route_flags_pref_cmd,
+ "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>",
+ NO_STR
+ IP_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n"
+ "Distance value for this prefix\n")
+{
+ /* We do not care about argv[2] */
+ return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3]);
}
DEFUN (no_ipv6_route_ifname_pref,
@@ -991,10 +1265,26 @@ DEFUN (no_ipv6_route_ifname_pref,
"IPv6 gateway interface name\n"
"Distance value for this prefix\n")
{
- return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3]);
+ return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3]);
}
-/* New RIB. Detailed information for IPv4 route. */
+DEFUN (no_ipv6_route_ifname_flags_pref,
+ no_ipv6_route_ifname_flags_pref_cmd,
+ "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>",
+ NO_STR
+ IP_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n"
+ "Distance value for this prefix\n")
+{
+ return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4]);
+}
+
+/* New RIB. Detailed information for IPv6 route. */
void
vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)
{
@@ -1014,6 +1304,10 @@ vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)
vty_out (vty, ", best");
if (rib->refcnt)
vty_out (vty, ", refcnt %ld", rib->refcnt);
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
+ vty_out (vty, ", blackhole");
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
+ vty_out (vty, ", reject");
vty_out (vty, "%s", VTY_NEWLINE);
#define ONE_DAY_SECOND 60*60*24
@@ -1191,6 +1485,11 @@ vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
}
}
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
+ vty_out (vty, ", bh");
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
+ vty_out (vty, ", rej");
+
if (rib->type == ZEBRA_ROUTE_RIPNG
|| rib->type == ZEBRA_ROUTE_OSPF6
|| rib->type == ZEBRA_ROUTE_BGP)
@@ -1465,6 +1764,12 @@ static_config_ipv6 (struct vty *vty)
break;
}
+ if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT))
+ vty_out (vty, " %s", "reject");
+
+ if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE))
+ vty_out (vty, " %s", "blackhole");
+
if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
vty_out (vty, " %d", si->distance);
vty_out (vty, "%s", VTY_NEWLINE);
@@ -1499,13 +1804,20 @@ zebra_vty_route_init ()
install_node (&ip_node, zebra_ip_config);
install_element (CONFIG_NODE, &ip_route_cmd);
+ install_element (CONFIG_NODE, &ip_route_flags_cmd);
install_element (CONFIG_NODE, &ip_route_mask_cmd);
+ install_element (CONFIG_NODE, &ip_route_mask_flags_cmd);
install_element (CONFIG_NODE, &no_ip_route_cmd);
+ install_element (CONFIG_NODE, &no_ip_route_flags_cmd);
install_element (CONFIG_NODE, &no_ip_route_mask_cmd);
+ install_element (CONFIG_NODE, &no_ip_route_mask_flags_cmd);
install_element (CONFIG_NODE, &ip_route_distance_cmd);
+ install_element (CONFIG_NODE, &ip_route_flags_distance_cmd);
install_element (CONFIG_NODE, &ip_route_mask_distance_cmd);
+ install_element (CONFIG_NODE, &ip_route_mask_flags_distance_cmd);
install_element (CONFIG_NODE, &no_ip_route_distance_cmd);
- install_element (CONFIG_NODE, &no_ip_route_mask_distance_cmd);
+ install_element (CONFIG_NODE, &no_ip_route_flags_distance_cmd);
+ install_element (CONFIG_NODE, &no_ip_route_mask_flags_distance_cmd);
install_element (VIEW_NODE, &show_ip_route_cmd);
install_element (VIEW_NODE, &show_ip_route_addr_cmd);
@@ -1527,13 +1839,21 @@ zebra_vty_route_init ()
#ifdef HAVE_IPV6
install_element (CONFIG_NODE, &ipv6_route_cmd);
+ install_element (CONFIG_NODE, &ipv6_route_flags_cmd);
install_element (CONFIG_NODE, &ipv6_route_ifname_cmd);
+ install_element (CONFIG_NODE, &ipv6_route_ifname_flags_cmd);
install_element (CONFIG_NODE, &no_ipv6_route_cmd);
+ install_element (CONFIG_NODE, &no_ipv6_route_flags_cmd);
install_element (CONFIG_NODE, &no_ipv6_route_ifname_cmd);
+ install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_cmd);
install_element (CONFIG_NODE, &ipv6_route_pref_cmd);
+ install_element (CONFIG_NODE, &ipv6_route_flags_pref_cmd);
install_element (CONFIG_NODE, &ipv6_route_ifname_pref_cmd);
+ install_element (CONFIG_NODE, &ipv6_route_ifname_flags_pref_cmd);
install_element (CONFIG_NODE, &no_ipv6_route_pref_cmd);
+ install_element (CONFIG_NODE, &no_ipv6_route_flags_pref_cmd);
install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_cmd);
+ install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_pref_cmd);
install_element (VIEW_NODE, &show_ipv6_route_cmd);
install_element (VIEW_NODE, &show_ipv6_route_protocol_cmd);
install_element (VIEW_NODE, &show_ipv6_route_addr_cmd);
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 0508f905..975574af 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -451,6 +451,7 @@ zsend_ipv4_add_multipath (struct zserv *client, struct prefix *p,
{
stream_putc (s, 1);
+ /* XXX: Waht's about NEXTHOP_TYPE_IPV4_IFNAME ? */
if (nexthop->type == NEXTHOP_TYPE_IPV4
|| nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
stream_put_in_addr (s, &nexthop->gate.ipv4);
@@ -532,6 +533,8 @@ zsend_ipv4_delete_multipath (struct zserv *client, struct prefix *p,
return 0;
}
+#if 0
+#warning oldies
int
zsend_ipv4_add (struct zserv *client, int type, int flags,
struct prefix_ipv4 *p, struct in_addr *nexthop,
@@ -613,8 +616,11 @@ zsend_ipv4_delete (struct zserv *client, int type, int flags,
return 0;
}
+#endif /* oldies */
#ifdef HAVE_IPV6
+#if 0
+#warning oldies
int
zsend_ipv6_add (struct zserv *client, int type, int flags,
struct prefix_ipv6 *p, struct in6_addr *nexthop,
@@ -655,6 +661,7 @@ zsend_ipv6_add (struct zserv *client, int type, int flags,
return 0;
}
+#endif /* oldies */
int
zsend_ipv6_add_multipath (struct zserv *client, struct prefix *p,
@@ -690,7 +697,9 @@ zsend_ipv6_add_multipath (struct zserv *client, struct prefix *p,
{
stream_putc (s, 1);
- if (nexthop->type == NEXTHOP_TYPE_IPV6)
+ if (nexthop->type == NEXTHOP_TYPE_IPV6
+ || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
+ || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
stream_write (s, (u_char *) &nexthop->gate.ipv6, 16);
else
stream_write (s, (u_char *) &empty, 16);
@@ -714,6 +723,8 @@ zsend_ipv6_add_multipath (struct zserv *client, struct prefix *p,
return 0;
}
+#if 0
+#warning oldies
int
zsend_ipv6_delete (struct zserv *client, int type, int flags,
struct prefix_ipv6 *p, struct in6_addr *nexthop,
@@ -754,6 +765,7 @@ zsend_ipv6_delete (struct zserv *client, int type, int flags,
return 0;
}
+#endif /* oldies */
int
zsend_ipv6_delete_multipath (struct zserv *client, struct prefix *p,
@@ -1089,9 +1101,9 @@ zread_ipv4_add (struct zserv *client, u_short length)
case ZEBRA_NEXTHOP_IPV6:
stream_forward (s, IPV6_MAX_BYTELEN);
break;
- case ZEBRA_NEXTHOP_BLACKHOLE:
- nexthop_blackhole_add (rib);
- break;
+ case ZEBRA_NEXTHOP_BLACKHOLE:
+ nexthop_blackhole_add (rib);
+ break;
}
}
}
@@ -1757,6 +1769,32 @@ DEFUN (config_table,
return CMD_SUCCESS;
}
+DEFUN (ip_forwarding,
+ ip_forwarding_cmd,
+ "ip forwarding",
+ IP_STR
+ "Turn on IP forwarding")
+{
+ int ret;
+
+ ret = ipforward ();
+
+ if (ret != 0)
+ {
+ vty_out (vty, "IP forwarding is already on%s", VTY_NEWLINE);
+ return CMD_ERR_NOTHING_TODO;
+ }
+
+ ret = ipforward_on ();
+ if (ret == 0)
+ {
+ vty_out (vty, "Can't turn on IP forwarding%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN (no_ip_forwarding,
no_ip_forwarding_cmd,
"no ip forwarding",
@@ -1941,6 +1979,7 @@ zebra_init ()
install_element (VIEW_NODE, &show_ip_forwarding_cmd);
install_element (ENABLE_NODE, &show_ip_forwarding_cmd);
+ install_element (CONFIG_NODE, &ip_forwarding_cmd);
install_element (CONFIG_NODE, &no_ip_forwarding_cmd);
install_element (ENABLE_NODE, &show_zebra_client_cmd);
diff --git a/zebra/zserv.h b/zebra/zserv.h
index c7622808..ec3c9f4b 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -25,8 +25,6 @@
/* Default port information. */
#define ZEBRA_PORT 2600
#define ZEBRA_VTY_PORT 2601
-#define ZEBRA_VTYSH_PATH "/tmp/.zebra"
-#define ZEBRA_SERV_PATH "/tmp/.zserv"
/* Default configuration filename. */
#define DEFAULT_CONFIG_FILE "zebra.conf"
@@ -91,6 +89,8 @@ zsend_interface_up (struct zserv *, struct interface *);
int
zsend_interface_down (struct zserv *, struct interface *);
+#if 0
+#warning oldies
int
zsend_ipv4_add (struct zserv *client, int type, int flags,
struct prefix_ipv4 *p, struct in_addr *nexthop,
@@ -100,6 +100,7 @@ int
zsend_ipv4_delete (struct zserv *client, int type, int flags,
struct prefix_ipv4 *p, struct in_addr *nexthop,
unsigned int ifindex);
+#endif
int
zsend_ipv4_add_multipath (struct zserv *, struct prefix *, struct rib *);
@@ -108,6 +109,8 @@ int
zsend_ipv4_delete_multipath (struct zserv *, struct prefix *, struct rib *);
#ifdef HAVE_IPV6
+#if 0
+#warning oldies
int
zsend_ipv6_add (struct zserv *client, int type, int flags,
struct prefix_ipv6 *p, struct in6_addr *nexthop,
@@ -117,6 +120,7 @@ int
zsend_ipv6_delete (struct zserv *client, int type, int flags,
struct prefix_ipv6 *p, struct in6_addr *nexthop,
unsigned int ifindex);
+#endif
int
zsend_ipv6_add_multipath (struct zserv *, struct prefix *, struct rib *);