Merge branch '-rip' into stable/2.0

This fixes up a lot of RIP/RIPng compliance tests that were still
flagged up.

Tested-by: Martin Winter <mwinter@opensourcerouting.org>
This commit is contained in:
David Lamparter 2016-12-05 16:25:58 +01:00
commit a93baa31d3
16 changed files with 228 additions and 162 deletions

View File

@ -421,15 +421,7 @@ sock_set_ipv4_mcast(struct iface *iface)
int int
sock_set_ipv4_mcast_loop(int fd) sock_set_ipv4_mcast_loop(int fd)
{ {
uint8_t loop = 0; return (setsockopt_ipv4_multicast_loop(fd, 0));
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
(char *)&loop, sizeof(loop)) < 0) {
log_warn("%s: error setting IP_MULTICAST_LOOP", __func__);
return (-1);
}
return (0);
} }
int int

View File

@ -390,7 +390,7 @@ if_lookup_exact_address (void *src, int family)
} }
/* Lookup interface by IPv4 address. */ /* Lookup interface by IPv4 address. */
struct interface * struct connected *
if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id) if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id)
{ {
struct listnode *node; struct listnode *node;
@ -399,7 +399,7 @@ if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id)
struct listnode *cnode; struct listnode *cnode;
struct interface *ifp; struct interface *ifp;
struct connected *c; struct connected *c;
struct interface *match; struct connected *match;
if (family == AF_INET) if (family == AF_INET)
{ {
@ -425,14 +425,14 @@ if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id)
(c->address->prefixlen > bestlen)) (c->address->prefixlen > bestlen))
{ {
bestlen = c->address->prefixlen; bestlen = c->address->prefixlen;
match = ifp; match = c;
} }
} }
} }
return match; return match;
} }
struct interface * struct connected *
if_lookup_address (void *matchaddr, int family) if_lookup_address (void *matchaddr, int family)
{ {
return if_lookup_address_vrf (matchaddr, family, VRF_DEFAULT); return if_lookup_address_vrf (matchaddr, family, VRF_DEFAULT);

View File

@ -389,7 +389,7 @@ extern int if_cmp_name_func (char *, char *);
extern struct interface *if_create (const char *name, int namelen); extern struct interface *if_create (const char *name, int namelen);
extern struct interface *if_lookup_by_index (ifindex_t); extern struct interface *if_lookup_by_index (ifindex_t);
extern struct interface *if_lookup_exact_address (void *matchaddr, int family); extern struct interface *if_lookup_exact_address (void *matchaddr, int family);
extern struct interface *if_lookup_address (void *matchaddr, int family); extern struct connected *if_lookup_address (void *matchaddr, int family);
extern struct interface *if_lookup_prefix (struct prefix *prefix); extern struct interface *if_lookup_prefix (struct prefix *prefix);
extern void if_update_vrf (struct interface *, const char *name, int namelen, extern void if_update_vrf (struct interface *, const char *name, int namelen,
@ -399,7 +399,7 @@ extern struct interface *if_create_vrf (const char *name, int namelen,
extern struct interface *if_lookup_by_index_vrf (ifindex_t, vrf_id_t vrf_id); extern struct interface *if_lookup_by_index_vrf (ifindex_t, vrf_id_t vrf_id);
extern struct interface *if_lookup_exact_address_vrf (void *matchaddr, int family, extern struct interface *if_lookup_exact_address_vrf (void *matchaddr, int family,
vrf_id_t vrf_id); vrf_id_t vrf_id);
extern struct interface *if_lookup_address_vrf (void *matchaddr, int family, extern struct connected *if_lookup_address_vrf (void *matchaddr, int family,
vrf_id_t vrf_id); vrf_id_t vrf_id);
extern struct interface *if_lookup_prefix_vrf (struct prefix *prefix, extern struct interface *if_lookup_prefix_vrf (struct prefix *prefix,
vrf_id_t vrf_id); vrf_id_t vrf_id);

View File

@ -385,6 +385,19 @@ setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr,
#endif #endif
} }
int
setsockopt_ipv4_multicast_loop (int sock, u_char val)
{
int ret;
ret = setsockopt (sock, IPPROTO_IP, IP_MULTICAST_LOOP, (void *) &val,
sizeof (val));
if (ret < 0)
zlog_warn ("can't setsockopt IP_MULTICAST_LOOP");
return ret;
}
static int static int
setsockopt_ipv4_ifindex (int sock, ifindex_t val) setsockopt_ipv4_ifindex (int sock, ifindex_t val)
{ {

View File

@ -89,6 +89,8 @@ extern int setsockopt_ipv4_multicast(int sock, int optname,
struct in_addr if_addr, struct in_addr if_addr,
unsigned int mcast_addr, unsigned int mcast_addr,
ifindex_t ifindex); ifindex_t ifindex);
extern int setsockopt_ipv4_multicast_loop (int sock, u_char val);
extern int setsockopt_ipv4_tos(int sock, int tos); extern int setsockopt_ipv4_tos(int sock, int tos);
/* Ask for, and get, ifindex, by whatever method is supported. */ /* Ask for, and get, ifindex, by whatever method is supported. */

View File

@ -133,17 +133,15 @@ ospf_if_ipmulticast (struct ospf *top, struct prefix *p, ifindex_t ifindex)
u_char val; u_char val;
int ret, len; int ret, len;
val = 0;
len = sizeof (val);
/* Prevent receiving self-origined multicast packets. */ /* Prevent receiving self-origined multicast packets. */
ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *)&val, len); ret = setsockopt_ipv4_multicast_loop (top->fd, 0);
if (ret < 0) if (ret < 0)
zlog_warn ("can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s", zlog_warn ("can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s",
top->fd, safe_strerror(errno)); top->fd, safe_strerror(errno));
/* Explicitly set multicast ttl to 1 -- endo. */ /* Explicitly set multicast ttl to 1 -- endo. */
val = 1; val = 1;
len = sizeof (val);
ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len); ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len);
if (ret < 0) if (ret < 0)
zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s", zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s",

View File

@ -2772,6 +2772,7 @@ ospf_read (struct thread *thread)
struct ospf_header *ospfh; struct ospf_header *ospfh;
u_int16_t length; u_int16_t length;
struct interface *ifp; struct interface *ifp;
struct connected *c;
/* first of all get interface pointer. */ /* first of all get interface pointer. */
ospf = THREAD_ARG (thread); ospf = THREAD_ARG (thread);
@ -2790,13 +2791,16 @@ ospf_read (struct thread *thread)
/* Note that sockopt_iphdrincl_swab_systoh was called in ospf_recv_packet. */ /* Note that sockopt_iphdrincl_swab_systoh was called in ospf_recv_packet. */
if (ifp == NULL) if (ifp == NULL)
{
/* Handle cases where the platform does not support retrieving the ifindex, /* Handle cases where the platform does not support retrieving the ifindex,
and also platforms (such as Solaris 8) that claim to support ifindex and also platforms (such as Solaris 8) that claim to support ifindex
retrieval but do not. */ retrieval but do not. */
ifp = if_lookup_address ((void *)&iph->ip_src, AF_INET); c = if_lookup_address ((void *)&iph->ip_src, AF_INET);
if (c)
ifp = c->ifp;
if (ifp == NULL) if (ifp == NULL)
return 0; return 0;
}
/* IP Header dump. */ /* IP Header dump. */
if (IS_DEBUG_OSPF_PACKET(0, RECV)) if (IS_DEBUG_OSPF_PACKET(0, RECV))

View File

@ -35,6 +35,7 @@
#include "privs.h" #include "privs.h"
#include "if.h" #include "if.h"
#include "vrf.h" #include "vrf.h"
#include "sockopt.h"
#include "pimd.h" #include "pimd.h"
#include "pim_mroute.h" #include "pim_mroute.h"
@ -68,7 +69,7 @@ int pim_socket_raw(int protocol)
return fd; return fd;
} }
int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop) int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char loop)
{ {
int fd; int fd;
@ -173,8 +174,7 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop)
} }
} }
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, if (setsockopt_ipv4_multicast_loop (fd, loop)) {
(void *) &loop, sizeof(loop))) {
zlog_warn("Could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s", zlog_warn("Could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s",
loop ? "enable" : "disable", loop ? "enable" : "disable",
fd, errno, safe_strerror(errno)); fd, errno, safe_strerror(errno));

View File

@ -39,7 +39,7 @@
#define PIM_SOCK_ERR_BIND (-11) /* Can't bind to interface */ #define PIM_SOCK_ERR_BIND (-11) /* Can't bind to interface */
int pim_socket_raw(int protocol); int pim_socket_raw(int protocol);
int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop); int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char loop);
int pim_socket_join(int fd, struct in_addr group, int pim_socket_join(int fd, struct in_addr group,
struct in_addr ifaddr, ifindex_t ifindex); struct in_addr ifaddr, ifindex_t ifindex);
int pim_socket_join_source(int fd, ifindex_t ifindex, int pim_socket_join_source(int fd, ifindex_t ifindex,

View File

@ -25,6 +25,7 @@
#include "if.h" #include "if.h"
#include "log.h" #include "log.h"
#include "memory.h" #include "memory.h"
#include "sockopt.h"
#include "pim_ssmpingd.h" #include "pim_ssmpingd.h"
#include "pim_time.h" #include "pim_time.h"
@ -150,18 +151,13 @@ static int ssmpingd_socket(struct in_addr addr, int port, int mttl)
return -1; return -1;
} }
{ if (setsockopt_ipv4_multicast_loop (fd, 0)) {
int loop = 0; zlog_warn("%s: could not disable Multicast Loopback Option on socket fd=%d: errno=%d: %s",
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
(void *) &loop, sizeof(loop))) {
zlog_warn("%s: could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s",
__PRETTY_FUNCTION__, __PRETTY_FUNCTION__,
loop ? "enable" : "disable",
fd, errno, safe_strerror(errno)); fd, errno, safe_strerror(errno));
close(fd); close(fd);
return PIM_SOCK_ERR_LOOP; return PIM_SOCK_ERR_LOOP;
} }
}
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
(void *) &addr, sizeof(addr))) { (void *) &addr, sizeof(addr))) {

View File

@ -55,6 +55,7 @@ const struct message ri_version_msg[] =
{RI_RIP_VERSION_1, "1"}, {RI_RIP_VERSION_1, "1"},
{RI_RIP_VERSION_2, "2"}, {RI_RIP_VERSION_2, "2"},
{RI_RIP_VERSION_1_AND_2, "1 2"}, {RI_RIP_VERSION_1_AND_2, "1 2"},
{RI_RIP_VERSION_NONE, "none"},
}; };
extern struct zebra_privs_t ripd_privs; extern struct zebra_privs_t ripd_privs;
@ -537,6 +538,8 @@ rip_interface_reset (struct rip_interface *ri)
ri->ri_send = RI_RIP_UNSPEC; ri->ri_send = RI_RIP_UNSPEC;
ri->ri_receive = RI_RIP_UNSPEC; ri->ri_receive = RI_RIP_UNSPEC;
ri->v2_broadcast = 0;
if (ri->auth_str) if (ri->auth_str)
{ {
free (ri->auth_str); free (ri->auth_str);
@ -1316,13 +1319,14 @@ DEFUN (no_rip_neighbor,
DEFUN (ip_rip_receive_version, DEFUN (ip_rip_receive_version,
ip_rip_receive_version_cmd, ip_rip_receive_version_cmd,
"ip rip receive version (1|2)", "ip rip receive version (1|2|none)",
IP_STR IP_STR
"Routing Information Protocol\n" "Routing Information Protocol\n"
"Advertisement reception\n" "Advertisement reception\n"
"Version control\n" "Version control\n"
"RIP version 1\n" "RIP version 1\n"
"RIP version 2\n") "RIP version 2\n"
"None\n")
{ {
struct interface *ifp; struct interface *ifp;
struct rip_interface *ri; struct rip_interface *ri;
@ -1330,17 +1334,21 @@ DEFUN (ip_rip_receive_version,
ifp = (struct interface *)vty->index; ifp = (struct interface *)vty->index;
ri = ifp->info; ri = ifp->info;
/* Version 1. */ switch (*argv[0])
if (atoi (argv[0]) == 1)
{ {
case '1':
ri->ri_receive = RI_RIP_VERSION_1; ri->ri_receive = RI_RIP_VERSION_1;
return CMD_SUCCESS; return CMD_SUCCESS;
} case '2':
if (atoi (argv[0]) == 2)
{
ri->ri_receive = RI_RIP_VERSION_2; ri->ri_receive = RI_RIP_VERSION_2;
return CMD_SUCCESS; return CMD_SUCCESS;
case 'n':
ri->ri_receive = RI_RIP_VERSION_NONE;
return CMD_SUCCESS;
default:
break;
} }
return CMD_WARNING; return CMD_WARNING;
} }
@ -1518,6 +1526,41 @@ ALIAS (no_ip_rip_send_version,
"Version 1\n" "Version 1\n"
"Version 2\n") "Version 2\n")
DEFUN (ip_rip_v2_broadcast,
ip_rip_v2_broadcast_cmd,
"ip rip v2-broadcast",
IP_STR
"Routing Information Protocol\n"
"Send ip broadcast v2 update\n")
{
struct interface *ifp;
struct rip_interface *ri;
ifp = (struct interface *)vty->index;
ri = ifp->info;
ri->v2_broadcast = 1;
return CMD_SUCCESS;
}
DEFUN (no_ip_rip_v2_broadcast,
no_ip_rip_v2_broadcast_cmd,
"no ip rip v2-broadcast",
NO_STR
IP_STR
"Routing Information Protocol\n"
"Send ip broadcast v2 update\n")
{
struct interface *ifp;
struct rip_interface *ri;
ifp = (struct interface *)vty->index;
ri = ifp->info;
ri->v2_broadcast = 0;
return CMD_SUCCESS;
}
DEFUN (ip_rip_authentication_mode, DEFUN (ip_rip_authentication_mode,
ip_rip_authentication_mode_cmd, ip_rip_authentication_mode_cmd,
"ip rip authentication mode (md5|text)", "ip rip authentication mode (md5|text)",
@ -1918,6 +1961,7 @@ rip_interface_config_write (struct vty *vty)
(ri->ri_send == RI_RIP_UNSPEC) && (ri->ri_send == RI_RIP_UNSPEC) &&
(ri->ri_receive == RI_RIP_UNSPEC) && (ri->ri_receive == RI_RIP_UNSPEC) &&
(ri->auth_type != RIP_AUTH_MD5) && (ri->auth_type != RIP_AUTH_MD5) &&
(!ri->v2_broadcast) &&
(ri->md5_auth_len != RIP_AUTH_MD5_SIZE) && (ri->md5_auth_len != RIP_AUTH_MD5_SIZE) &&
(!ri->auth_str) && (!ri->auth_str) &&
(!ri->key_chain) ) (!ri->key_chain) )
@ -1959,6 +2003,9 @@ rip_interface_config_write (struct vty *vty)
lookup (ri_version_msg, ri->ri_receive), lookup (ri_version_msg, ri->ri_receive),
VTY_NEWLINE); VTY_NEWLINE);
if (ri->v2_broadcast)
vty_out (vty, " ip rip v2-broadcast%s", VTY_NEWLINE);
/* RIP authentication. */ /* RIP authentication. */
if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
vty_out (vty, " ip rip authentication mode text%s", VTY_NEWLINE); vty_out (vty, " ip rip authentication mode text%s", VTY_NEWLINE);
@ -2099,6 +2146,9 @@ rip_if_init (void)
install_element (INTERFACE_NODE, &no_ip_rip_receive_version_cmd); install_element (INTERFACE_NODE, &no_ip_rip_receive_version_cmd);
install_element (INTERFACE_NODE, &no_ip_rip_receive_version_num_cmd); install_element (INTERFACE_NODE, &no_ip_rip_receive_version_num_cmd);
install_element (INTERFACE_NODE, &ip_rip_v2_broadcast_cmd);
install_element (INTERFACE_NODE, &no_ip_rip_v2_broadcast_cmd);
install_element (INTERFACE_NODE, &ip_rip_authentication_mode_cmd); install_element (INTERFACE_NODE, &ip_rip_authentication_mode_cmd);
install_element (INTERFACE_NODE, &ip_rip_authentication_mode_authlen_cmd); install_element (INTERFACE_NODE, &ip_rip_authentication_mode_authlen_cmd);
install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_cmd); install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_cmd);

View File

@ -812,7 +812,15 @@ rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
struct interface *ifp) struct interface *ifp)
{ {
struct rip_interface *ri; struct rip_interface *ri;
char *auth_str; char *auth_str = (char *) &rte->prefix;
int i;
/* reject passwords with zeros in the middle of the string */
for (i = strlen (auth_str); i < 16; i++)
{
if (auth_str[i] != '\0')
return 0;
}
if (IS_RIP_DEBUG_EVENT) if (IS_RIP_DEBUG_EVENT)
zlog_debug ("RIPv2 simple password authentication from %s", zlog_debug ("RIPv2 simple password authentication from %s",
@ -827,8 +835,6 @@ rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
/* Simple password authentication. */ /* Simple password authentication. */
if (ri->auth_str) if (ri->auth_str)
{ {
auth_str = (char *) &rte->prefix;
if (strncmp (auth_str, ri->auth_str, 16) == 0) if (strncmp (auth_str, ri->auth_str, 16) == 0)
return 1; return 1;
} }
@ -841,7 +847,7 @@ rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
if (keychain == NULL) if (keychain == NULL)
return 0; return 0;
key = key_match_for_accept (keychain, (char *) &rte->prefix); key = key_match_for_accept (keychain, auth_str);
if (key) if (key)
return 1; return 1;
} }
@ -1333,30 +1339,23 @@ rip_response_process (struct rip_packet *packet, int size,
/* Make socket for RIP protocol. */ /* Make socket for RIP protocol. */
static int static int
rip_create_socket (struct sockaddr_in *from) rip_create_socket (void)
{ {
int ret; int ret;
int sock; int sock;
struct sockaddr_in addr; struct sockaddr_in addr;
memset (&addr, 0, sizeof (struct sockaddr_in)); memset (&addr, 0, sizeof (struct sockaddr_in));
if (!from)
{
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY; addr.sin_addr.s_addr = INADDR_ANY;
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
addr.sin_len = sizeof (struct sockaddr_in); addr.sin_len = sizeof (struct sockaddr_in);
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
} else {
memcpy(&addr, from, sizeof(addr));
}
/* sending port must always be the RIP port */ /* sending port must always be the RIP port */
addr.sin_port = htons (RIP_PORT_DEFAULT); addr.sin_port = htons (RIP_PORT_DEFAULT);
/* Make datagram socket. */ /* Make datagram socket. */
sock = socket (AF_INET, SOCK_DGRAM, 0); sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0) if (sock < 0)
{ {
zlog_err("Cannot create UDP socket: %s", safe_strerror(errno)); zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
@ -1366,6 +1365,7 @@ rip_create_socket (struct sockaddr_in *from)
sockopt_broadcast (sock); sockopt_broadcast (sock);
sockopt_reuseaddr (sock); sockopt_reuseaddr (sock);
sockopt_reuseport (sock); sockopt_reuseport (sock);
setsockopt_ipv4_multicast_loop (sock, 0);
#ifdef RIP_RECVMSG #ifdef RIP_RECVMSG
setsockopt_pktinfo (sock); setsockopt_pktinfo (sock);
#endif /* RIP_RECVMSG */ #endif /* RIP_RECVMSG */
@ -1406,7 +1406,7 @@ static int
rip_send_packet (u_char * buf, int size, struct sockaddr_in *to, rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
struct connected *ifc) struct connected *ifc)
{ {
int ret, send_sock; int ret;
struct sockaddr_in sin; struct sockaddr_in sin;
assert (ifc != NULL); assert (ifc != NULL);
@ -1462,38 +1462,16 @@ rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
{ {
sin.sin_port = to->sin_port; sin.sin_port = to->sin_port;
sin.sin_addr = to->sin_addr; sin.sin_addr = to->sin_addr;
send_sock = rip->sock;
} }
else else
{ {
struct sockaddr_in from;
sin.sin_port = htons (RIP_PORT_DEFAULT); sin.sin_port = htons (RIP_PORT_DEFAULT);
sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP); sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
/* multicast send should bind to local interface address */ rip_interface_multicast_set (rip->sock, ifc);
memset (&from, 0, sizeof (from));
from.sin_family = AF_INET;
from.sin_port = htons (RIP_PORT_DEFAULT);
from.sin_addr = ifc->address->u.prefix4;
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
from.sin_len = sizeof (struct sockaddr_in);
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
/*
* we have to open a new socket for each packet because this
* is the most portable way to bind to a different source
* ipv4 address for each packet.
*/
if ( (send_sock = rip_create_socket (&from)) < 0)
{
zlog_warn("rip_send_packet could not create socket.");
return -1;
}
rip_interface_multicast_set (send_sock, ifc);
} }
ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin, ret = sendto (rip->sock, buf, size, 0, (struct sockaddr *)&sin,
sizeof (struct sockaddr_in)); sizeof (struct sockaddr_in));
if (IS_RIP_DEBUG_EVENT) if (IS_RIP_DEBUG_EVENT)
@ -1503,9 +1481,6 @@ rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
if (ret < 0) if (ret < 0)
zlog_warn ("can't send packet : %s", safe_strerror (errno)); zlog_warn ("can't send packet : %s", safe_strerror (errno));
if (!to)
close(send_sock);
return ret; return ret;
} }
@ -1681,6 +1656,9 @@ rip_request_process (struct rip_packet *packet, int size,
} }
else else
{ {
if (ntohs (rte->family) != AF_INET)
return;
/* Examine the list of RTEs in the Request one by one. For each /* Examine the list of RTEs in the Request one by one. For each
entry, look up the destination in the router's routing entry, look up the destination in the router's routing
database and, if there is a route, put that route's metric in database and, if there is a route, put that route's metric in
@ -1803,7 +1781,7 @@ rip_read (struct thread *t)
int len; int len;
int vrecv; int vrecv;
socklen_t fromlen; socklen_t fromlen;
struct interface *ifp; struct interface *ifp = NULL;
struct connected *ifc; struct connected *ifc;
struct rip_interface *ri; struct rip_interface *ri;
struct prefix p; struct prefix p;
@ -1836,7 +1814,9 @@ rip_read (struct thread *t)
} }
/* Which interface is this packet comes from. */ /* Which interface is this packet comes from. */
ifp = if_lookup_address ((void *)&from.sin_addr, AF_INET); ifc = if_lookup_address ((void *)&from.sin_addr, AF_INET);
if (ifc)
ifp = ifc->ifp;
/* RIP packet received */ /* RIP packet received */
if (IS_RIP_DEBUG_EVENT) if (IS_RIP_DEBUG_EVENT)
@ -1928,15 +1908,9 @@ rip_read (struct thread *t)
/* RIP Version check. RFC2453, 4.6 and 5.1 */ /* RIP Version check. RFC2453, 4.6 and 5.1 */
vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ? vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
rip->version_recv : ri->ri_receive); rip->version_recv : ri->ri_receive);
if ((packet->version == RIPv1) && !(vrecv & RIPv1)) if (vrecv == RI_RIP_VERSION_NONE ||
{ ((packet->version == RIPv1) && !(vrecv & RIPv1)) ||
if (IS_RIP_DEBUG_PACKET) ((packet->version == RIPv2) && !(vrecv & RIPv2)))
zlog_debug (" packet's v%d doesn't fit to if version spec",
packet->version);
rip_peer_bad_packet (&from);
return -1;
}
if ((packet->version == RIPv2) && !(vrecv & RIPv2))
{ {
if (IS_RIP_DEBUG_PACKET) if (IS_RIP_DEBUG_PACKET)
zlog_debug (" packet's v%d doesn't fit to if version spec", zlog_debug (" packet's v%d doesn't fit to if version spec",
@ -2434,20 +2408,22 @@ rip_output_process (struct connected *ifc, struct sockaddr_in *to,
static void static void
rip_update_interface (struct connected *ifc, u_char version, int route_type) rip_update_interface (struct connected *ifc, u_char version, int route_type)
{ {
struct interface *ifp = ifc->ifp;
struct rip_interface *ri = ifp->info;
struct sockaddr_in to; struct sockaddr_in to;
/* When RIP version is 2 and multicast enable interface. */ /* When RIP version is 2 and multicast enable interface. */
if (version == RIPv2 && if_is_multicast (ifc->ifp)) if (version == RIPv2 && !ri->v2_broadcast && if_is_multicast (ifp))
{ {
if (IS_RIP_DEBUG_EVENT) if (IS_RIP_DEBUG_EVENT)
zlog_debug ("multicast announce on %s ", ifc->ifp->name); zlog_debug ("multicast announce on %s ", ifp->name);
rip_output_process (ifc, NULL, route_type, version); rip_output_process (ifc, NULL, route_type, version);
return; return;
} }
/* If we can't send multicast packet, send it with unicast. */ /* If we can't send multicast packet, send it with unicast. */
if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp)) if (if_is_broadcast (ifp) || if_is_pointopoint (ifp))
{ {
if (ifc->address->family == AF_INET) if (ifc->address->family == AF_INET)
{ {
@ -2469,7 +2445,7 @@ rip_update_interface (struct connected *ifc, u_char version, int route_type)
if (IS_RIP_DEBUG_EVENT) if (IS_RIP_DEBUG_EVENT)
zlog_debug("%s announce to %s on %s", zlog_debug("%s announce to %s on %s",
CONNECTED_PEER(ifc) ? "unicast" : "broadcast", CONNECTED_PEER(ifc) ? "unicast" : "broadcast",
inet_ntoa (to.sin_addr), ifc->ifp->name); inet_ntoa (to.sin_addr), ifp->name);
rip_output_process (ifc, &to, route_type, version); rip_output_process (ifc, &to, route_type, version);
} }
@ -2539,21 +2515,14 @@ rip_update_process (int route_type)
{ {
p = &rp->p; p = &rp->p;
ifp = if_lookup_prefix (p); connected = if_lookup_address (&p->u.prefix4, AF_INET);
if (! ifp) if (! connected)
{ {
zlog_warn ("Neighbor %s doesnt have connected interface!", zlog_warn ("Neighbor %s doesnt have connected interface!",
inet_ntoa (p->u.prefix4)); inet_ntoa (p->u.prefix4));
continue; continue;
} }
if ( (connected = connected_lookup_prefix (ifp, p)) == NULL)
{
zlog_warn ("Neighbor %s doesnt have connected network",
inet_ntoa (p->u.prefix4));
continue;
}
/* Set destination address and port */ /* Set destination address and port */
memset (&to, 0, sizeof (struct sockaddr_in)); memset (&to, 0, sizeof (struct sockaddr_in));
to.sin_addr = p->u.prefix4; to.sin_addr = p->u.prefix4;
@ -2579,11 +2548,7 @@ rip_update (struct thread *t)
/* Triggered updates may be suppressed if a regular update is due by /* Triggered updates may be suppressed if a regular update is due by
the time the triggered update would be sent. */ the time the triggered update would be sent. */
if (rip->t_triggered_interval) RIP_TIMER_OFF (rip->t_triggered_interval);
{
thread_cancel (rip->t_triggered_interval);
rip->t_triggered_interval = NULL;
}
rip->trigger = 0; rip->trigger = 0;
/* Register myself. */ /* Register myself. */
@ -2637,11 +2602,7 @@ rip_triggered_update (struct thread *t)
rip->t_triggered_update = NULL; rip->t_triggered_update = NULL;
/* Cancel interval timer. */ /* Cancel interval timer. */
if (rip->t_triggered_interval) RIP_TIMER_OFF (rip->t_triggered_interval);
{
thread_cancel (rip->t_triggered_interval);
rip->t_triggered_interval = NULL;
}
rip->trigger = 0; rip->trigger = 0;
/* Logging triggered update. */ /* Logging triggered update. */
@ -2729,7 +2690,7 @@ rip_create (void)
rip->obuf = stream_new (1500); rip->obuf = stream_new (1500);
/* Make socket. */ /* Make socket. */
rip->sock = rip_create_socket (NULL); rip->sock = rip_create_socket ();
if (rip->sock < 0) if (rip->sock < 0)
return rip->sock; return rip->sock;
@ -2819,11 +2780,7 @@ rip_event (enum rip_event event, int sock)
rip->t_read = thread_add_read (master, rip_read, NULL, sock); rip->t_read = thread_add_read (master, rip_read, NULL, sock);
break; break;
case RIP_UPDATE_EVENT: case RIP_UPDATE_EVENT:
if (rip->t_update) RIP_TIMER_OFF (rip->t_update);
{
thread_cancel (rip->t_update);
rip->t_update = NULL;
}
jitter = rip_update_jitter (rip->update_time); jitter = rip_update_jitter (rip->update_time);
rip->t_update = rip->t_update =
thread_add_timer (master, rip_update, NULL, thread_add_timer (master, rip_update, NULL,
@ -3918,11 +3875,7 @@ rip_clean (void)
RIP_TIMER_OFF (rip->t_triggered_interval); RIP_TIMER_OFF (rip->t_triggered_interval);
/* Cancel read thread. */ /* Cancel read thread. */
if (rip->t_read) THREAD_READ_OFF (rip->t_read);
{
thread_cancel (rip->t_read);
rip->t_read = NULL;
}
/* Close RIP socket. */ /* Close RIP socket. */
if (rip->sock >= 0) if (rip->sock >= 0)

View File

@ -258,6 +258,9 @@ struct rip_interface
int ri_send; int ri_send;
int ri_receive; int ri_receive;
/* RIPv2 broadcast mode */
int v2_broadcast;
/* RIPv2 authentication type. */ /* RIPv2 authentication type. */
int auth_type; int auth_type;
@ -347,6 +350,7 @@ struct rip_md5_data
#define RI_RIP_VERSION_1 1 #define RI_RIP_VERSION_1 1
#define RI_RIP_VERSION_2 2 #define RI_RIP_VERSION_2 2
#define RI_RIP_VERSION_1_AND_2 3 #define RI_RIP_VERSION_1_AND_2 3
#define RI_RIP_VERSION_NONE 4
/* N.B. stuff will break if /* N.B. stuff will break if
(RIPv1 != RI_RIP_VERSION_1) || (RIPv2 != RI_RIP_VERSION_2) */ (RIPv1 != RI_RIP_VERSION_1) || (RIPv2 != RI_RIP_VERSION_2) */
@ -369,14 +373,7 @@ enum rip_event
} while (0) } while (0)
/* Macro for timer turn off. */ /* Macro for timer turn off. */
#define RIP_TIMER_OFF(X) \ #define RIP_TIMER_OFF(X) THREAD_TIMER_OFF(X)
do { \
if (X) \
{ \
thread_cancel (X); \
(X) = NULL; \
} \
} while (0)
/* Prototypes. */ /* Prototypes. */
extern void rip_init (void); extern void rip_init (void);

View File

@ -65,7 +65,7 @@ ripng_multicast_join (struct interface *ifp)
struct ipv6_mreq mreq; struct ipv6_mreq mreq;
int save_errno; int save_errno;
if (if_is_up (ifp) && if_is_multicast (ifp)) { if (if_is_multicast (ifp)) {
memset (&mreq, 0, sizeof (mreq)); memset (&mreq, 0, sizeof (mreq));
inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr); inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
mreq.ipv6mr_interface = ifp->ifindex; mreq.ipv6mr_interface = ifp->ifindex;
@ -116,7 +116,7 @@ ripng_multicast_leave (struct interface *ifp)
int ret; int ret;
struct ipv6_mreq mreq; struct ipv6_mreq mreq;
if (if_is_up (ifp) && if_is_multicast (ifp)) { if (if_is_multicast (ifp)) {
memset (&mreq, 0, sizeof (mreq)); memset (&mreq, 0, sizeof (mreq));
inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr); inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
mreq.ipv6mr_interface = ifp->ifindex; mreq.ipv6mr_interface = ifp->ifindex;

View File

@ -829,8 +829,10 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
* with the new one in below. */ * with the new one in below. */
break; break;
/* Metrics are same. Keep "rinfo" null and the new route /* Metrics are same. Unless ECMP is disabled, keep "rinfo" null and
* is added in the ECMP list in below. */ * the new route is added in the ECMP list in below. */
if (! ripng->ecmp)
break;
} }
} }
@ -874,11 +876,24 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr) same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr)
&& (rinfo->ifindex == ifp->ifindex)); && (rinfo->ifindex == ifp->ifindex));
/*
* RFC 2080 - Section 2.4.2:
* "If the new metric is the same as the old one, examine the timeout
* for the existing route. If it is at least halfway to the expiration
* point, switch to the new route. This heuristic is optional, but
* highly recommended".
*/
if (!ripng->ecmp && !same &&
rinfo->metric == rte->metric && rinfo->t_timeout &&
(thread_timer_remain_second (rinfo->t_timeout) < (ripng->timeout_time / 2)))
{
ripng_ecmp_replace (&newinfo);
}
/* Next, compare the metrics. If the datagram is from the same /* Next, compare the metrics. If the datagram is from the same
router as the existing route, and the new metric is different 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 than the old one; or, if the new metric is lower than the old
one; do the following actions: */ one; do the following actions: */
if ((same && rinfo->metric != rte->metric) || else if ((same && rinfo->metric != rte->metric) ||
rte->metric < rinfo->metric) rte->metric < rinfo->metric)
{ {
if (listcount (list) == 1) if (listcount (list) == 1)
@ -2155,6 +2170,54 @@ DEFUN (show_ipv6_ripng_status,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (clear_ipv6_rip,
clear_ipv6_rip_cmd,
"clear ipv6 ripng",
CLEAR_STR
IPV6_STR
"Clear IPv6 RIP database")
{
struct route_node *rp;
struct ripng_info *rinfo;
struct list *list;
struct listnode *listnode;
/* Clear received RIPng routes */
for (rp = route_top (ripng->table); rp; rp = route_next (rp))
{
list = rp->info;
if (list == NULL)
continue;
for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
{
if (! ripng_route_rte (rinfo))
continue;
if (CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB))
ripng_zebra_ipv6_delete (rp);
break;
}
if (rinfo)
{
RIPNG_TIMER_OFF (rinfo->t_timeout);
RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
listnode_delete (list, rinfo);
ripng_info_free (rinfo);
}
if (list_isempty (list))
{
list_free (list);
rp->info = NULL;
route_unlock_node (rp);
}
}
return CMD_SUCCESS;
}
DEFUN (router_ripng, DEFUN (router_ripng,
router_ripng_cmd, router_ripng_cmd,
"router ripng", "router ripng",
@ -3032,6 +3095,8 @@ ripng_init ()
install_element (VIEW_NODE, &show_ipv6_ripng_cmd); install_element (VIEW_NODE, &show_ipv6_ripng_cmd);
install_element (VIEW_NODE, &show_ipv6_ripng_status_cmd); install_element (VIEW_NODE, &show_ipv6_ripng_status_cmd);
install_element (ENABLE_NODE, &clear_ipv6_rip_cmd);
install_element (CONFIG_NODE, &router_ripng_cmd); install_element (CONFIG_NODE, &router_ripng_cmd);
install_element (CONFIG_NODE, &no_router_ripng_cmd); install_element (CONFIG_NODE, &no_router_ripng_cmd);

View File

@ -282,7 +282,7 @@ send_packet(struct interface *ifp,
char buf[256]; char buf[256];
struct in_pktinfo *pktinfo; struct in_pktinfo *pktinfo;
u_long src; u_long src;
int on; u_char on;
if (!(ifp->flags & IFF_UP)) if (!(ifp->flags & IFF_UP))
return; return;
@ -323,12 +323,8 @@ send_packet(struct interface *ifp,
zlog_warn("sendto %s", safe_strerror (errno)); zlog_warn("sendto %s", safe_strerror (errno));
} }
if(dst != INADDR_BROADCAST) { if(dst != INADDR_BROADCAST)
on = 0; setsockopt_ipv4_multicast_loop (irdp_sock, 0);
if( setsockopt(irdp_sock,IPPROTO_IP, IP_MULTICAST_LOOP,
(char *)&on,sizeof(on)) < 0)
zlog_warn("sendto %s", safe_strerror (errno));
}
memset(&sockdst,0,sizeof(sockdst)); memset(&sockdst,0,sizeof(sockdst));
sockdst.sin_family=AF_INET; sockdst.sin_family=AF_INET;