mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 06:50:17 +00:00
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:
commit
a93baa31d3
@ -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
|
||||
|
8
lib/if.c
8
lib/if.c
@ -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);
|
||||
|
4
lib/if.h
4
lib/if.h
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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. */
|
||||
|
@ -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",
|
||||
|
@ -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))
|
||||
|
@ -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));
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
135
ripd/ripd.c
135
ripd/ripd.c
@ -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)
|
||||
|
13
ripd/ripd.h
13
ripd/ripd.h
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user