mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-16 19:19:59 +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
|
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
|
||||||
|
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. */
|
/* 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);
|
||||||
|
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_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);
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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. */
|
||||||
|
@ -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",
|
||||||
|
@ -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))
|
||||||
|
@ -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));
|
||||||
|
@ -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,
|
||||||
|
@ -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))) {
|
||||||
|
@ -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);
|
||||||
|
125
ripd/ripd.c
125
ripd/ripd.c
@ -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)
|
||||||
|
13
ripd/ripd.h
13
ripd/ripd.h
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user