mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 09:30:30 +00:00
2003-10-15 sowmini.varadhan@sun.com
* ripd/ripd.c: (rip_send_packet) use rip->sock for mcast sends, instead of creating one socket per send. send source addr to rip_update_interface. (rip_update_process) should send an update on every connected network for each interface. (rip_request_send) should send a request on every connected network for each interface. * ripd/ripd.h: update prototype for rip_interface_multicast_set * ripd/rip_interface.c: (rip_interface_multicast_set) reorganized so that it can be called repeatedly for aliased interfaces (on multiple networks).
This commit is contained in:
parent
bf547fed75
commit
cc1131ab01
@ -137,28 +137,25 @@ rip_interface_new ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rip_interface_multicast_set (int sock, struct interface *ifp)
|
rip_interface_multicast_set (int sock, struct connected *connected,
|
||||||
|
int if_pointopoint)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
listnode node;
|
|
||||||
struct servent *sp;
|
struct servent *sp;
|
||||||
struct sockaddr_in from;
|
struct sockaddr_in from;
|
||||||
|
|
||||||
for (node = listhead (ifp->connected); node; nextnode (node))
|
|
||||||
{
|
|
||||||
struct prefix_ipv4 *p;
|
|
||||||
struct connected *connected;
|
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
|
struct prefix_ipv4 *p;
|
||||||
|
|
||||||
connected = getdata (node);
|
if (if_pointopoint)
|
||||||
|
p = (struct prefix_ipv4 *) connected->destination;
|
||||||
|
else
|
||||||
p = (struct prefix_ipv4 *) connected->address;
|
p = (struct prefix_ipv4 *) connected->address;
|
||||||
|
|
||||||
if (p->family == AF_INET)
|
|
||||||
{
|
|
||||||
addr = p->prefix;
|
addr = p->prefix;
|
||||||
|
|
||||||
|
|
||||||
if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF,
|
if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF,
|
||||||
addr, 0, ifp->ifindex) < 0)
|
addr, 0, 0) < 0)
|
||||||
{
|
{
|
||||||
zlog_warn ("Can't setsockopt IP_MULTICAST_IF to fd %d", sock);
|
zlog_warn ("Can't setsockopt IP_MULTICAST_IF to fd %d", sock);
|
||||||
return;
|
return;
|
||||||
@ -176,6 +173,7 @@ rip_interface_multicast_set (int sock, struct interface *ifp)
|
|||||||
|
|
||||||
/* Address shoud be any address. */
|
/* Address shoud be any address. */
|
||||||
from.sin_family = AF_INET;
|
from.sin_family = AF_INET;
|
||||||
|
addr = ((struct prefix_ipv4 *) connected->address)->prefix;
|
||||||
from.sin_addr = addr;
|
from.sin_addr = addr;
|
||||||
#ifdef HAVE_SIN_LEN
|
#ifdef HAVE_SIN_LEN
|
||||||
from.sin_len = sizeof (struct sockaddr_in);
|
from.sin_len = sizeof (struct sockaddr_in);
|
||||||
@ -184,12 +182,11 @@ rip_interface_multicast_set (int sock, struct interface *ifp)
|
|||||||
if (ripd_privs.change (ZPRIVS_RAISE))
|
if (ripd_privs.change (ZPRIVS_RAISE))
|
||||||
zlog_err ("rip_interface_multicast_set: could not raise privs");
|
zlog_err ("rip_interface_multicast_set: could not raise privs");
|
||||||
|
|
||||||
ret = bind (sock, (struct sockaddr *) & from,
|
bind (sock, NULL, 0); /* unbind any previous association */
|
||||||
sizeof (struct sockaddr_in));
|
ret = bind (sock, (struct sockaddr *) & from, sizeof (struct sockaddr_in));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
zlog_warn ("Can't bind socket: %s", strerror (errno));
|
zlog_warn ("Can't bind socket: %s", strerror (errno));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ripd_privs.change (ZPRIVS_LOWER))
|
if (ripd_privs.change (ZPRIVS_LOWER))
|
||||||
@ -198,8 +195,6 @@ rip_interface_multicast_set (int sock, struct interface *ifp)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send RIP request packet to specified interface. */
|
/* Send RIP request packet to specified interface. */
|
||||||
void
|
void
|
||||||
|
95
ripd/ripd.c
95
ripd/ripd.c
@ -60,7 +60,8 @@ long rip_global_queries = 0;
|
|||||||
void rip_event (enum rip_event, int);
|
void rip_event (enum rip_event, int);
|
||||||
|
|
||||||
void rip_output_process (struct interface *, struct prefix *,
|
void rip_output_process (struct interface *, struct prefix *,
|
||||||
struct sockaddr_in *, int, u_char);
|
struct sockaddr_in *, int, u_char,
|
||||||
|
struct prefix_ipv4 *);
|
||||||
|
|
||||||
/* RIP output routes type. */
|
/* RIP output routes type. */
|
||||||
enum
|
enum
|
||||||
@ -1238,7 +1239,6 @@ rip_send_packet (caddr_t buf, int size, struct sockaddr_in *to,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
int sock;
|
|
||||||
|
|
||||||
/* Make destination address. */
|
/* Make destination address. */
|
||||||
memset (&sin, 0, sizeof (struct sockaddr_in));
|
memset (&sin, 0, sizeof (struct sockaddr_in));
|
||||||
@ -1250,39 +1250,29 @@ rip_send_packet (caddr_t buf, int size, struct sockaddr_in *to,
|
|||||||
/* When destination is specified, use it's port and address. */
|
/* When destination is specified, use it's port and address. */
|
||||||
if (to)
|
if (to)
|
||||||
{
|
{
|
||||||
sock = rip->sock;
|
|
||||||
|
|
||||||
sin.sin_port = to->sin_port;
|
sin.sin_port = to->sin_port;
|
||||||
sin.sin_addr = to->sin_addr;
|
sin.sin_addr = to->sin_addr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sock = socket (AF_INET, SOCK_DGRAM, 0);
|
|
||||||
|
|
||||||
sockopt_broadcast (sock);
|
|
||||||
sockopt_reuseaddr (sock);
|
|
||||||
sockopt_reuseport (sock);
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
/* Set multicast interface. */
|
/* caller has set multicast interface */
|
||||||
rip_interface_multicast_set (sock, ifp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sendto (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)
|
||||||
zlog_info ("SEND to socket %d port %d addr %s",
|
zlog_info ("SEND to %s.%d", inet_ntoa(sin.sin_addr),
|
||||||
sock, ntohs (sin.sin_port), inet_ntoa(sin.sin_addr));
|
ntohs (sin.sin_port));
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
zlog_warn ("can't send packet : %s", strerror (errno));
|
zlog_warn ("can't send packet : %s", strerror (errno));
|
||||||
|
|
||||||
if (! to)
|
|
||||||
close (sock);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1454,8 +1444,19 @@ rip_request_process (struct rip_packet *packet, int size,
|
|||||||
ntohs (rte->family) == 0 &&
|
ntohs (rte->family) == 0 &&
|
||||||
ntohl (rte->metric) == RIP_METRIC_INFINITY)
|
ntohl (rte->metric) == RIP_METRIC_INFINITY)
|
||||||
{
|
{
|
||||||
|
struct prefix_ipv4 saddr;
|
||||||
|
|
||||||
|
/* saddr will be used for determining which routes to split-horizon.
|
||||||
|
Since the source address we'll pick will be on the same subnet as the
|
||||||
|
destination, for the purpose of split-horizoning, we'll
|
||||||
|
pretend that "from" is our source address. */
|
||||||
|
saddr.family = AF_INET;
|
||||||
|
saddr.prefixlen = IPV4_MAX_BITLEN;
|
||||||
|
saddr.prefix = from->sin_addr;
|
||||||
|
|
||||||
/* All route with split horizon */
|
/* All route with split horizon */
|
||||||
rip_output_process (ifp, NULL, from, rip_all_route, packet->version);
|
rip_output_process (ifp, NULL, from, rip_all_route, packet->version,
|
||||||
|
&saddr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1979,7 +1980,8 @@ rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
|
|||||||
/* Send update to the ifp or spcified neighbor. */
|
/* Send update to the ifp or spcified neighbor. */
|
||||||
void
|
void
|
||||||
rip_output_process (struct interface *ifp, struct prefix *ifaddr,
|
rip_output_process (struct interface *ifp, struct prefix *ifaddr,
|
||||||
struct sockaddr_in *to, int route_type, u_char version)
|
struct sockaddr_in *to, int route_type, u_char version,
|
||||||
|
struct prefix_ipv4 *saddr)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
@ -2118,7 +2120,7 @@ rip_output_process (struct interface *ifp, struct prefix *ifaddr,
|
|||||||
/* We perform split horizon for RIP and connected route. */
|
/* We perform split horizon for RIP and connected route. */
|
||||||
if ((rinfo->type == ZEBRA_ROUTE_RIP ||
|
if ((rinfo->type == ZEBRA_ROUTE_RIP ||
|
||||||
rinfo->type == ZEBRA_ROUTE_CONNECT) &&
|
rinfo->type == ZEBRA_ROUTE_CONNECT) &&
|
||||||
rinfo->ifindex == ifp->ifindex)
|
prefix_match((struct prefix *)p, (struct prefix *)saddr))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2247,7 +2249,8 @@ rip_output_process (struct interface *ifp, struct prefix *ifaddr,
|
|||||||
|
|
||||||
/* Send RIP packet to the interface. */
|
/* Send RIP packet to the interface. */
|
||||||
void
|
void
|
||||||
rip_update_interface (struct interface *ifp, u_char version, int route_type)
|
rip_update_interface (struct interface *ifp, u_char version, int route_type,
|
||||||
|
struct prefix_ipv4 *saddr)
|
||||||
{
|
{
|
||||||
struct prefix_ipv4 *p;
|
struct prefix_ipv4 *p;
|
||||||
struct connected *connected;
|
struct connected *connected;
|
||||||
@ -2260,7 +2263,8 @@ rip_update_interface (struct interface *ifp, u_char version, int route_type)
|
|||||||
if (IS_RIP_DEBUG_EVENT)
|
if (IS_RIP_DEBUG_EVENT)
|
||||||
zlog_info ("multicast announce on %s ", ifp->name);
|
zlog_info ("multicast announce on %s ", ifp->name);
|
||||||
|
|
||||||
rip_output_process (ifp, NULL, NULL, route_type, rip->version_send);
|
rip_output_process (ifp, NULL, NULL, route_type, rip->version_send,
|
||||||
|
saddr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2288,7 +2292,7 @@ rip_update_interface (struct interface *ifp, u_char version, int route_type)
|
|||||||
inet_ntoa (to.sin_addr), ifp->name);
|
inet_ntoa (to.sin_addr), ifp->name);
|
||||||
|
|
||||||
rip_output_process (ifp, connected->address, &to, route_type,
|
rip_output_process (ifp, connected->address, &to, route_type,
|
||||||
rip->version_send);
|
rip->version_send, saddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2298,7 +2302,8 @@ rip_update_interface (struct interface *ifp, u_char version, int route_type)
|
|||||||
void
|
void
|
||||||
rip_update_process (int route_type)
|
rip_update_process (int route_type)
|
||||||
{
|
{
|
||||||
listnode node;
|
listnode node, ifnode;
|
||||||
|
struct connected *connected;
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
struct rip_interface *ri;
|
struct rip_interface *ri;
|
||||||
struct route_node *rp;
|
struct route_node *rp;
|
||||||
@ -2336,15 +2341,29 @@ rip_update_process (int route_type)
|
|||||||
ifp->ifindex);
|
ifp->ifindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* send update on each connected network */
|
||||||
|
|
||||||
|
LIST_LOOP(ifp->connected, connected, ifnode)
|
||||||
|
{
|
||||||
|
struct prefix_ipv4 *ifaddr;
|
||||||
|
|
||||||
|
|
||||||
/* If there is no version configuration in the interface,
|
/* If there is no version configuration in the interface,
|
||||||
use rip's version setting. */
|
use rip's version setting. */
|
||||||
{
|
|
||||||
int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
|
int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
|
||||||
rip->version_send : ri->ri_send);
|
rip->version_send : ri->ri_send);
|
||||||
|
|
||||||
|
ifaddr = (struct prefix_ipv4 *) connected->address;
|
||||||
|
|
||||||
|
if (ifaddr->family != AF_INET)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rip_interface_multicast_set(rip->sock, connected,
|
||||||
|
if_is_pointopoint(ifp));
|
||||||
if (vsend & RIPv1)
|
if (vsend & RIPv1)
|
||||||
rip_update_interface (ifp, RIPv1, route_type);
|
rip_update_interface (ifp, RIPv1, route_type, ifaddr);
|
||||||
if (vsend & RIPv2)
|
if (vsend & RIPv2)
|
||||||
rip_update_interface (ifp, RIPv2, route_type);
|
rip_update_interface (ifp, RIPv2, route_type, ifaddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2369,7 +2388,7 @@ rip_update_process (int route_type)
|
|||||||
to.sin_port = htons (RIP_PORT_DEFAULT);
|
to.sin_port = htons (RIP_PORT_DEFAULT);
|
||||||
|
|
||||||
/* RIP version is rip's configuration. */
|
/* RIP version is rip's configuration. */
|
||||||
rip_output_process (ifp, NULL, &to, route_type, rip->version_send);
|
rip_output_process (ifp, NULL, &to, route_type, rip->version_send, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2549,6 +2568,8 @@ rip_request_send (struct sockaddr_in *to, struct interface *ifp,
|
|||||||
{
|
{
|
||||||
struct rte *rte;
|
struct rte *rte;
|
||||||
struct rip_packet rip_packet;
|
struct rip_packet rip_packet;
|
||||||
|
listnode node;
|
||||||
|
struct connected *connected;
|
||||||
|
|
||||||
memset (&rip_packet, 0, sizeof (rip_packet));
|
memset (&rip_packet, 0, sizeof (rip_packet));
|
||||||
|
|
||||||
@ -2557,7 +2578,23 @@ rip_request_send (struct sockaddr_in *to, struct interface *ifp,
|
|||||||
rte = rip_packet.rte;
|
rte = rip_packet.rte;
|
||||||
rte->metric = htonl (RIP_METRIC_INFINITY);
|
rte->metric = htonl (RIP_METRIC_INFINITY);
|
||||||
|
|
||||||
return rip_send_packet ((caddr_t) &rip_packet, sizeof (rip_packet), to, ifp);
|
/* send request on each connected network */
|
||||||
|
LIST_LOOP(ifp->connected, connected, node)
|
||||||
|
{
|
||||||
|
struct prefix_ipv4 *p;
|
||||||
|
|
||||||
|
p = (struct prefix_ipv4 *) connected->address;
|
||||||
|
|
||||||
|
if (p->family != AF_INET)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rip_interface_multicast_set(rip->sock, connected,
|
||||||
|
if_is_pointopoint(ifp));
|
||||||
|
if (rip_send_packet ((caddr_t) &rip_packet, sizeof (rip_packet),
|
||||||
|
to, ifp) != sizeof (rip_packet))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return sizeof (rip_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -385,7 +385,7 @@ void rip_redistribute_delete (int, int, struct prefix_ipv4 *, unsigned int);
|
|||||||
void rip_redistribute_withdraw (int);
|
void rip_redistribute_withdraw (int);
|
||||||
void rip_zebra_ipv4_add (struct prefix_ipv4 *, struct in_addr *, u_int32_t, u_char);
|
void rip_zebra_ipv4_add (struct prefix_ipv4 *, struct in_addr *, u_int32_t, u_char);
|
||||||
void rip_zebra_ipv4_delete (struct prefix_ipv4 *, struct in_addr *, u_int32_t);
|
void rip_zebra_ipv4_delete (struct prefix_ipv4 *, struct in_addr *, u_int32_t);
|
||||||
void rip_interface_multicast_set (int, struct interface *);
|
void rip_interface_multicast_set (int, struct connected *, int);
|
||||||
void rip_distribute_update_interface (struct interface *);
|
void rip_distribute_update_interface (struct interface *);
|
||||||
void rip_if_rmap_update_interface (struct interface *);
|
void rip_if_rmap_update_interface (struct interface *);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user