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
sock_set_ipv4_mcast_loop(int fd)
{
uint8_t loop = 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);
return (setsockopt_ipv4_multicast_loop(fd, 0));
}
int

View File

@ -390,7 +390,7 @@ if_lookup_exact_address (void *src, int family)
}
/* Lookup interface by IPv4 address. */
struct interface *
struct connected *
if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id)
{
struct listnode *node;
@ -399,7 +399,7 @@ if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id)
struct listnode *cnode;
struct interface *ifp;
struct connected *c;
struct interface *match;
struct connected *match;
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))
{
bestlen = c->address->prefixlen;
match = ifp;
match = c;
}
}
}
return match;
}
struct interface *
struct connected *
if_lookup_address (void *matchaddr, int family)
{
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_lookup_by_index (ifindex_t);
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 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_exact_address_vrf (void *matchaddr, int family,
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);
extern struct interface *if_lookup_prefix_vrf (struct prefix *prefix,
vrf_id_t vrf_id);

View File

@ -384,7 +384,20 @@ setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr,
#error "Unsupported multicast API"
#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
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,
unsigned int mcast_addr,
ifindex_t ifindex);
extern int setsockopt_ipv4_multicast_loop (int sock, u_char val);
extern int setsockopt_ipv4_tos(int sock, int tos);
/* Ask for, and get, ifindex, by whatever method is supported. */

View File

@ -132,18 +132,16 @@ ospf_if_ipmulticast (struct ospf *top, struct prefix *p, ifindex_t ifindex)
{
u_char val;
int ret, len;
val = 0;
len = sizeof (val);
/* 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)
zlog_warn ("can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s",
top->fd, safe_strerror(errno));
/* Explicitly set multicast ttl to 1 -- endo. */
val = 1;
len = sizeof (val);
ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len);
if (ret < 0)
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;
u_int16_t length;
struct interface *ifp;
struct connected *c;
/* first of all get interface pointer. */
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. */
if (ifp == NULL)
/* Handle cases where the platform does not support retrieving the ifindex,
and also platforms (such as Solaris 8) that claim to support ifindex
retrieval but do not. */
ifp = if_lookup_address ((void *)&iph->ip_src, AF_INET);
if (ifp == NULL)
return 0;
{
/* Handle cases where the platform does not support retrieving the ifindex,
and also platforms (such as Solaris 8) that claim to support ifindex
retrieval but do not. */
c = if_lookup_address ((void *)&iph->ip_src, AF_INET);
if (c)
ifp = c->ifp;
if (ifp == NULL)
return 0;
}
/* IP Header dump. */
if (IS_DEBUG_OSPF_PACKET(0, RECV))

View File

@ -35,6 +35,7 @@
#include "privs.h"
#include "if.h"
#include "vrf.h"
#include "sockopt.h"
#include "pimd.h"
#include "pim_mroute.h"
@ -68,7 +69,7 @@ int pim_socket_raw(int protocol)
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;
@ -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,
(void *) &loop, sizeof(loop))) {
if (setsockopt_ipv4_multicast_loop (fd, loop)) {
zlog_warn("Could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s",
loop ? "enable" : "disable",
fd, errno, safe_strerror(errno));

View File

@ -39,7 +39,7 @@
#define PIM_SOCK_ERR_BIND (-11) /* Can't bind to interface */
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,
struct in_addr ifaddr, ifindex_t ifindex);
int pim_socket_join_source(int fd, ifindex_t ifindex,

View File

@ -25,6 +25,7 @@
#include "if.h"
#include "log.h"
#include "memory.h"
#include "sockopt.h"
#include "pim_ssmpingd.h"
#include "pim_time.h"
@ -150,17 +151,12 @@ static int ssmpingd_socket(struct in_addr addr, int port, int mttl)
return -1;
}
{
int loop = 0;
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__,
loop ? "enable" : "disable",
fd, errno, safe_strerror(errno));
close(fd);
return PIM_SOCK_ERR_LOOP;
}
if (setsockopt_ipv4_multicast_loop (fd, 0)) {
zlog_warn("%s: could not disable Multicast Loopback Option on socket fd=%d: errno=%d: %s",
__PRETTY_FUNCTION__,
fd, errno, safe_strerror(errno));
close(fd);
return PIM_SOCK_ERR_LOOP;
}
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,

View File

@ -55,6 +55,7 @@ const struct message ri_version_msg[] =
{RI_RIP_VERSION_1, "1"},
{RI_RIP_VERSION_2, "2"},
{RI_RIP_VERSION_1_AND_2, "1 2"},
{RI_RIP_VERSION_NONE, "none"},
};
extern struct zebra_privs_t ripd_privs;
@ -536,7 +537,9 @@ rip_interface_reset (struct rip_interface *ri)
ri->ri_send = RI_RIP_UNSPEC;
ri->ri_receive = RI_RIP_UNSPEC;
ri->v2_broadcast = 0;
if (ri->auth_str)
{
free (ri->auth_str);
@ -1316,13 +1319,14 @@ DEFUN (no_rip_neighbor,
DEFUN (ip_rip_receive_version,
ip_rip_receive_version_cmd,
"ip rip receive version (1|2)",
"ip rip receive version (1|2|none)",
IP_STR
"Routing Information Protocol\n"
"Advertisement reception\n"
"Version control\n"
"RIP version 1\n"
"RIP version 2\n")
"RIP version 2\n"
"None\n")
{
struct interface *ifp;
struct rip_interface *ri;
@ -1330,17 +1334,21 @@ DEFUN (ip_rip_receive_version,
ifp = (struct interface *)vty->index;
ri = ifp->info;
/* Version 1. */
if (atoi (argv[0]) == 1)
switch (*argv[0])
{
case '1':
ri->ri_receive = RI_RIP_VERSION_1;
return CMD_SUCCESS;
}
if (atoi (argv[0]) == 2)
{
case '2':
ri->ri_receive = RI_RIP_VERSION_2;
return CMD_SUCCESS;
case 'n':
ri->ri_receive = RI_RIP_VERSION_NONE;
return CMD_SUCCESS;
default:
break;
}
return CMD_WARNING;
}
@ -1518,6 +1526,41 @@ ALIAS (no_ip_rip_send_version,
"Version 1\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,
ip_rip_authentication_mode_cmd,
"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_receive == RI_RIP_UNSPEC) &&
(ri->auth_type != RIP_AUTH_MD5) &&
(!ri->v2_broadcast) &&
(ri->md5_auth_len != RIP_AUTH_MD5_SIZE) &&
(!ri->auth_str) &&
(!ri->key_chain) )
@ -1959,6 +2003,9 @@ rip_interface_config_write (struct vty *vty)
lookup (ri_version_msg, ri->ri_receive),
VTY_NEWLINE);
if (ri->v2_broadcast)
vty_out (vty, " ip rip v2-broadcast%s", VTY_NEWLINE);
/* RIP authentication. */
if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
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_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_authlen_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 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)
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. */
if (ri->auth_str)
{
auth_str = (char *) &rte->prefix;
if (strncmp (auth_str, ri->auth_str, 16) == 0)
return 1;
}
@ -841,7 +847,7 @@ rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
if (keychain == NULL)
return 0;
key = key_match_for_accept (keychain, (char *) &rte->prefix);
key = key_match_for_accept (keychain, auth_str);
if (key)
return 1;
}
@ -1333,30 +1339,23 @@ rip_response_process (struct rip_packet *packet, int size,
/* Make socket for RIP protocol. */
static int
rip_create_socket (struct sockaddr_in *from)
rip_create_socket (void)
{
int ret;
int sock;
struct sockaddr_in addr;
memset (&addr, 0, sizeof (struct sockaddr_in));
if (!from)
{
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
#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 */
} else {
memcpy(&addr, from, sizeof(addr));
}
/* sending port must always be the RIP port */
addr.sin_port = htons (RIP_PORT_DEFAULT);
/* Make datagram socket. */
sock = socket (AF_INET, SOCK_DGRAM, 0);
sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0)
{
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_reuseaddr (sock);
sockopt_reuseport (sock);
setsockopt_ipv4_multicast_loop (sock, 0);
#ifdef RIP_RECVMSG
setsockopt_pktinfo (sock);
#endif /* RIP_RECVMSG */
@ -1406,7 +1406,7 @@ static int
rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
struct connected *ifc)
{
int ret, send_sock;
int ret;
struct sockaddr_in sin;
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_addr = to->sin_addr;
send_sock = rip->sock;
}
else
{
struct sockaddr_in from;
sin.sin_port = htons (RIP_PORT_DEFAULT);
sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
/* multicast send should bind to local interface address */
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);
rip_interface_multicast_set (rip->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));
if (IS_RIP_DEBUG_EVENT)
@ -1503,9 +1481,6 @@ rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
if (ret < 0)
zlog_warn ("can't send packet : %s", safe_strerror (errno));
if (!to)
close(send_sock);
return ret;
}
@ -1681,6 +1656,9 @@ rip_request_process (struct rip_packet *packet, int size,
}
else
{
if (ntohs (rte->family) != AF_INET)
return;
/* Examine the list of RTEs in the Request one by one. For each
entry, look up the destination in the router's routing
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 vrecv;
socklen_t fromlen;
struct interface *ifp;
struct interface *ifp = NULL;
struct connected *ifc;
struct rip_interface *ri;
struct prefix p;
@ -1836,8 +1814,10 @@ rip_read (struct thread *t)
}
/* 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 */
if (IS_RIP_DEBUG_EVENT)
zlog_debug ("RECV packet from %s port %d on %s",
@ -1928,15 +1908,9 @@ rip_read (struct thread *t)
/* RIP Version check. RFC2453, 4.6 and 5.1 */
vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
rip->version_recv : ri->ri_receive);
if ((packet->version == RIPv1) && !(vrecv & RIPv1))
{
if (IS_RIP_DEBUG_PACKET)
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 (vrecv == RI_RIP_VERSION_NONE ||
((packet->version == RIPv1) && !(vrecv & RIPv1)) ||
((packet->version == RIPv2) && !(vrecv & RIPv2)))
{
if (IS_RIP_DEBUG_PACKET)
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
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;
/* 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)
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);
return;
}
/* 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)
{
@ -2469,7 +2445,7 @@ rip_update_interface (struct connected *ifc, u_char version, int route_type)
if (IS_RIP_DEBUG_EVENT)
zlog_debug("%s announce to %s on %s",
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);
}
@ -2539,21 +2515,14 @@ rip_update_process (int route_type)
{
p = &rp->p;
ifp = if_lookup_prefix (p);
if (! ifp)
connected = if_lookup_address (&p->u.prefix4, AF_INET);
if (! connected)
{
zlog_warn ("Neighbor %s doesnt have connected interface!",
inet_ntoa (p->u.prefix4));
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 */
memset (&to, 0, sizeof (struct sockaddr_in));
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
the time the triggered update would be sent. */
if (rip->t_triggered_interval)
{
thread_cancel (rip->t_triggered_interval);
rip->t_triggered_interval = NULL;
}
RIP_TIMER_OFF (rip->t_triggered_interval);
rip->trigger = 0;
/* Register myself. */
@ -2637,11 +2602,7 @@ rip_triggered_update (struct thread *t)
rip->t_triggered_update = NULL;
/* Cancel interval timer. */
if (rip->t_triggered_interval)
{
thread_cancel (rip->t_triggered_interval);
rip->t_triggered_interval = NULL;
}
RIP_TIMER_OFF (rip->t_triggered_interval);
rip->trigger = 0;
/* Logging triggered update. */
@ -2729,7 +2690,7 @@ rip_create (void)
rip->obuf = stream_new (1500);
/* Make socket. */
rip->sock = rip_create_socket (NULL);
rip->sock = rip_create_socket ();
if (rip->sock < 0)
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);
break;
case RIP_UPDATE_EVENT:
if (rip->t_update)
{
thread_cancel (rip->t_update);
rip->t_update = NULL;
}
RIP_TIMER_OFF (rip->t_update);
jitter = rip_update_jitter (rip->update_time);
rip->t_update =
thread_add_timer (master, rip_update, NULL,
@ -3918,11 +3875,7 @@ rip_clean (void)
RIP_TIMER_OFF (rip->t_triggered_interval);
/* Cancel read thread. */
if (rip->t_read)
{
thread_cancel (rip->t_read);
rip->t_read = NULL;
}
THREAD_READ_OFF (rip->t_read);
/* Close RIP socket. */
if (rip->sock >= 0)

View File

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

View File

@ -65,7 +65,7 @@ ripng_multicast_join (struct interface *ifp)
struct ipv6_mreq mreq;
int save_errno;
if (if_is_up (ifp) && if_is_multicast (ifp)) {
if (if_is_multicast (ifp)) {
memset (&mreq, 0, sizeof (mreq));
inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
mreq.ipv6mr_interface = ifp->ifindex;
@ -116,7 +116,7 @@ ripng_multicast_leave (struct interface *ifp)
int ret;
struct ipv6_mreq mreq;
if (if_is_up (ifp) && if_is_multicast (ifp)) {
if (if_is_multicast (ifp)) {
memset (&mreq, 0, sizeof (mreq));
inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
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. */
break;
/* Metrics are same. Keep "rinfo" null and the new route
* is added in the ECMP list in below. */
/* Metrics are same. Unless ECMP is disabled, keep "rinfo" null and
* 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)
&& (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
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: */
if ((same && rinfo->metric != rte->metric) ||
else if ((same && rinfo->metric != rte->metric) ||
rte->metric < rinfo->metric)
{
if (listcount (list) == 1)
@ -2155,6 +2170,54 @@ DEFUN (show_ipv6_ripng_status,
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,
router_ripng_cmd,
"router ripng",
@ -3032,6 +3095,8 @@ ripng_init ()
install_element (VIEW_NODE, &show_ipv6_ripng_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, &no_router_ripng_cmd);

View File

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