diff options
Diffstat (limited to 'ripd/ripd.c')
| -rw-r--r-- | ripd/ripd.c | 135 |
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) |
