summaryrefslogtreecommitdiff
path: root/ripd/ripd.c
diff options
context:
space:
mode:
Diffstat (limited to 'ripd/ripd.c')
-rw-r--r--ripd/ripd.c135
1 files changed, 44 insertions, 91 deletions
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 24ba74c73f..9de3ca7c3d 100644
--- a/ripd/ripd.c
+++ b/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,
@@ -3919,11 +3876,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)