121995Sdist /* 261540Sbostic * Copyright (c) 1983, 1988, 1993 361540Sbostic * The Regents of the University of California. All rights reserved. 433489Sbostic * 542712Sbostic * %sccs.include.redist.c% 621995Sdist */ 721995Sdist 89016Ssam #ifndef lint 9*69037Sbostic static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 04/28/95"; 1033489Sbostic #endif /* not lint */ 119016Ssam 129016Ssam /* 139016Ssam * Routing Table Management Daemon 149016Ssam */ 1510245Ssam #include "defs.h" 1626340Skarels #include <sys/syslog.h> 179016Ssam 189016Ssam /* 199016Ssam * Process a newly received packet. 209016Ssam */ 2136846Skarels rip_input(from, rip, size) 229016Ssam struct sockaddr *from; 2336846Skarels register struct rip *rip; 249016Ssam int size; 259016Ssam { 2621836Skarels register struct rt_entry *rt; 2721836Skarels register struct netinfo *n; 2821836Skarels register struct interface *ifp; 2921836Skarels struct interface *if_ifwithdstaddr(); 3036831Skarels int count, changes = 0; 3121836Skarels register struct afswitch *afp; 3234661Skarels static struct sockaddr badfrom, badfrom2; 339016Ssam 349016Ssam ifp = 0; 3536846Skarels TRACE_INPUT(ifp, from, (char *)rip, size); 3626340Skarels if (from->sa_family >= af_max || 3726340Skarels (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0) { 3826340Skarels syslog(LOG_INFO, 3926340Skarels "\"from\" address in unsupported address family (%d), cmd %d\n", 4036846Skarels from->sa_family, rip->rip_cmd); 419016Ssam return; 4226340Skarels } 4336846Skarels if (rip->rip_vers == 0) { 4436831Skarels syslog(LOG_ERR, 4536831Skarels "RIP version 0 packet received from %s! (cmd %d)", 4636846Skarels (*afswitch[from->sa_family].af_format)(from), rip->rip_cmd); 4736831Skarels return; 4836831Skarels } 4936846Skarels switch (rip->rip_cmd) { 509016Ssam 519016Ssam case RIPCMD_REQUEST: 5236846Skarels n = rip->rip_nets; 5336846Skarels count = size - ((char *)n - (char *)rip); 5436831Skarels if (count < sizeof (struct netinfo)) 5536831Skarels return; 5636831Skarels for (; count > 0; n++) { 5736831Skarels if (count < sizeof (struct netinfo)) 589016Ssam break; 5936831Skarels count -= sizeof (struct netinfo); 609016Ssam 6136831Skarels #if BSD < 198810 6238684Ssklower if (sizeof(n->rip_dst.sa_family) > 1) /* XXX */ 6338684Ssklower n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); 6438684Ssklower #else 6538684Ssklower #define osa(x) ((struct osockaddr *)(&(x))) 6638684Ssklower n->rip_dst.sa_family = 6738684Ssklower ntohs(osa(n->rip_dst)->sa_family); 6838684Ssklower n->rip_dst.sa_len = sizeof(n->rip_dst); 6936831Skarels #endif 7036831Skarels n->rip_metric = ntohl(n->rip_metric); 719016Ssam /* 729016Ssam * A single entry with sa_family == AF_UNSPEC and 739016Ssam * metric ``infinity'' means ``all routes''. 7426340Skarels * We respond to routers only if we are acting 7526340Skarels * as a supplier, or to anyone other than a router 7626340Skarels * (eg, query). 779016Ssam */ 789016Ssam if (n->rip_dst.sa_family == AF_UNSPEC && 7936831Skarels n->rip_metric == HOPCNT_INFINITY && count == 0) { 8026810Skarels if (supplier || (*afp->af_portmatch)(from) == 0) 8136831Skarels supply(from, 0, 0, 0); 829016Ssam return; 839016Ssam } 8426810Skarels if (n->rip_dst.sa_family < af_max && 8526810Skarels afswitch[n->rip_dst.sa_family].af_hash) 8626810Skarels rt = rtlookup(&n->rip_dst); 8726810Skarels else 8826810Skarels rt = 0; 8938684Ssklower #define min(a, b) (a < b ? a : b) 909016Ssam n->rip_metric = rt == 0 ? HOPCNT_INFINITY : 9131495Skarels min(rt->rt_metric + 1, HOPCNT_INFINITY); 9236831Skarels #if BSD < 198810 9336831Skarels if (sizeof(n->rip_dst.sa_family) > 1) /* XXX */ 9436831Skarels n->rip_dst.sa_family = htons(n->rip_dst.sa_family); 9538684Ssklower #else 9638684Ssklower osa(n->rip_dst)->sa_family = 9738684Ssklower htons(n->rip_dst.sa_family); 9836831Skarels #endif 9936831Skarels n->rip_metric = htonl(n->rip_metric); 1009016Ssam } 10136846Skarels rip->rip_cmd = RIPCMD_RESPONSE; 10269003Sbostic memmove(packet, rip, size); 10336831Skarels (*afp->af_output)(s, 0, from, size); 1049016Ssam return; 1059016Ssam 1069016Ssam case RIPCMD_TRACEON: 1079016Ssam case RIPCMD_TRACEOFF: 10816314Skarels /* verify message came from a privileged port */ 1099016Ssam if ((*afp->af_portcheck)(from) == 0) 1109016Ssam return; 11129945Skarels if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags & 11233020Skarels (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 || 11333020Skarels ifp->int_flags & IFF_PASSIVE) { 11428906Skarels syslog(LOG_ERR, "trace command from unknown router, %s", 11529931Skarels (*afswitch[from->sa_family].af_format)(from)); 11628906Skarels return; 11728906Skarels } 11836846Skarels ((char *)rip)[size] = '\0'; 11936846Skarels if (rip->rip_cmd == RIPCMD_TRACEON) 12036846Skarels traceon(rip->rip_tracefile); 1219016Ssam else 1229016Ssam traceoff(); 1239016Ssam return; 1249016Ssam 1259016Ssam case RIPCMD_RESPONSE: 1269016Ssam /* verify message came from a router */ 1279016Ssam if ((*afp->af_portmatch)(from) == 0) 1289016Ssam return; 1299016Ssam (*afp->af_canon)(from); 1309016Ssam /* are we talking to ourselves? */ 1319016Ssam ifp = if_ifwithaddr(from); 1329016Ssam if (ifp) { 13334572Skarels if (ifp->int_flags & IFF_PASSIVE) { 13434572Skarels syslog(LOG_ERR, 13534572Skarels "bogus input (from passive interface, %s)", 13634572Skarels (*afswitch[from->sa_family].af_format)(from)); 13734572Skarels return; 13834572Skarels } 1399016Ssam rt = rtfind(from); 14031220Skarels if (rt == 0 || ((rt->rt_state & RTS_INTERFACE) == 0) && 14131220Skarels rt->rt_metric >= ifp->int_metric) 1429016Ssam addrouteforif(ifp); 1439016Ssam else 1449016Ssam rt->rt_timer = 0; 1459016Ssam return; 1469016Ssam } 14717573Skarels /* 14817573Skarels * Update timer for interface on which the packet arrived. 14917573Skarels * If from other end of a point-to-point link that isn't 15017573Skarels * in the routing tables, (re-)add the route. 15117573Skarels */ 15228906Skarels if ((rt = rtfind(from)) && 15328906Skarels (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE))) 15416314Skarels rt->rt_timer = 0; 15531220Skarels else if ((ifp = if_ifwithdstaddr(from)) && 15631220Skarels (rt == 0 || rt->rt_metric >= ifp->int_metric)) 15717573Skarels addrouteforif(ifp); 15829945Skarels /* 15929945Skarels * "Authenticate" router from which message originated. 16029945Skarels * We accept routing packets from routers directly connected 16129945Skarels * via broadcast or point-to-point networks, 16229945Skarels * and from those listed in /etc/gateways. 16329945Skarels */ 16429945Skarels if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags & 16533020Skarels (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 || 16633020Skarels ifp->int_flags & IFF_PASSIVE) { 167*69037Sbostic if (memcmp(from, &badfrom, sizeof(badfrom)) != 0) { 16829931Skarels syslog(LOG_ERR, 16929931Skarels "packet from unknown router, %s", 17029931Skarels (*afswitch[from->sa_family].af_format)(from)); 17129931Skarels badfrom = *from; 17229931Skarels } 17328906Skarels return; 17428906Skarels } 1759016Ssam size -= 4 * sizeof (char); 17636846Skarels n = rip->rip_nets; 1779016Ssam for (; size > 0; size -= sizeof (struct netinfo), n++) { 1789016Ssam if (size < sizeof (struct netinfo)) 1799016Ssam break; 18036831Skarels #if BSD < 198810 18136831Skarels if (sizeof(n->rip_dst.sa_family) > 1) /* XXX */ 18212726Ssam n->rip_dst.sa_family = 18312726Ssam ntohs(n->rip_dst.sa_family); 18438684Ssklower #else 18538684Ssklower n->rip_dst.sa_family = 18638684Ssklower ntohs(osa(n->rip_dst)->sa_family); 18738684Ssklower n->rip_dst.sa_len = sizeof(n->rip_dst); 18836831Skarels #endif 18936831Skarels n->rip_metric = ntohl(n->rip_metric); 19026340Skarels if (n->rip_dst.sa_family >= af_max || 19126340Skarels (afp = &afswitch[n->rip_dst.sa_family])->af_hash == 19226340Skarels (int (*)())0) { 19326340Skarels syslog(LOG_INFO, 19426340Skarels "route in unsupported address family (%d), from %s (af %d)\n", 19526340Skarels n->rip_dst.sa_family, 19626340Skarels (*afswitch[from->sa_family].af_format)(from), 19726340Skarels from->sa_family); 19816753Skarels continue; 19926340Skarels } 20026340Skarels if (((*afp->af_checkhost)(&n->rip_dst)) == 0) { 20126340Skarels syslog(LOG_DEBUG, 20226340Skarels "bad host in route from %s (af %d)\n", 20326340Skarels (*afswitch[from->sa_family].af_format)(from), 20426340Skarels from->sa_family); 20516128Skarels continue; 20626340Skarels } 20734661Skarels if (n->rip_metric == 0 || 20834661Skarels (unsigned) n->rip_metric > HOPCNT_INFINITY) { 209*69037Sbostic if (memcmp(from, &badfrom2, 21034661Skarels sizeof(badfrom2)) != 0) { 21134661Skarels syslog(LOG_ERR, 21234661Skarels "bad metric (%d) from %s\n", 21334661Skarels n->rip_metric, 21434661Skarels (*afswitch[from->sa_family].af_format)(from)); 21534661Skarels badfrom2 = *from; 21634661Skarels } 21734661Skarels continue; 21834661Skarels } 21931220Skarels /* 22031220Skarels * Adjust metric according to incoming interface. 22131220Skarels */ 22231495Skarels if ((unsigned) n->rip_metric < HOPCNT_INFINITY) 22331220Skarels n->rip_metric += ifp->int_metric; 22431495Skarels if ((unsigned) n->rip_metric > HOPCNT_INFINITY) 22531495Skarels n->rip_metric = HOPCNT_INFINITY; 2269016Ssam rt = rtlookup(&n->rip_dst); 22728994Skarels if (rt == 0 || 22828994Skarels (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) == 22928994Skarels (RTS_INTERNAL|RTS_INTERFACE)) { 23031220Skarels /* 23131220Skarels * If we're hearing a logical network route 23231220Skarels * back from a peer to which we sent it, 23331220Skarels * ignore it. 23431220Skarels */ 23531220Skarels if (rt && rt->rt_state & RTS_SUBNET && 23631220Skarels (*afp->af_sendroute)(rt, from)) 23731220Skarels continue; 23834572Skarels if ((unsigned)n->rip_metric < HOPCNT_INFINITY) { 23934572Skarels /* 24034572Skarels * Look for an equivalent route that 24134572Skarels * includes this one before adding 24234572Skarels * this route. 24334572Skarels */ 24434572Skarels rt = rtfind(&n->rip_dst); 24534572Skarels if (rt && equal(from, &rt->rt_router)) 24634572Skarels continue; 24721836Skarels rtadd(&n->rip_dst, from, n->rip_metric, 0); 24836831Skarels changes++; 24934572Skarels } 2509016Ssam continue; 2519016Ssam } 2529016Ssam 2539016Ssam /* 25416323Skarels * Update if from gateway and different, 25534572Skarels * shorter, or equivalent but old route 25634572Skarels * is getting stale. 2579016Ssam */ 25818112Skarels if (equal(from, &rt->rt_router)) { 25930745Skarels if (n->rip_metric != rt->rt_metric) { 26018112Skarels rtchange(rt, from, n->rip_metric); 26136831Skarels changes++; 26234572Skarels rt->rt_timer = 0; 26331220Skarels if (rt->rt_metric >= HOPCNT_INFINITY) 26430745Skarels rt->rt_timer = 26530745Skarels GARBAGE_TIME - EXPIRE_TIME; 26630745Skarels } else if (rt->rt_metric < HOPCNT_INFINITY) 26729940Skarels rt->rt_timer = 0; 26831495Skarels } else if ((unsigned) n->rip_metric < rt->rt_metric || 26934572Skarels (rt->rt_metric == n->rip_metric && 27034572Skarels rt->rt_timer > (EXPIRE_TIME/2) && 27131495Skarels (unsigned) n->rip_metric < HOPCNT_INFINITY)) { 2729016Ssam rtchange(rt, from, n->rip_metric); 27336831Skarels changes++; 2749016Ssam rt->rt_timer = 0; 2759016Ssam } 2769016Ssam } 27736831Skarels break; 2789016Ssam } 27936831Skarels 28036831Skarels /* 28136831Skarels * If changes have occurred, and if we have not sent a broadcast 28236831Skarels * recently, send a dynamic update. This update is sent only 28336831Skarels * on interfaces other than the one on which we received notice 28436831Skarels * of the change. If we are within MIN_WAITTIME of a full update, 28536831Skarels * don't bother sending; if we just sent a dynamic update 28636831Skarels * and set a timer (nextbcast), delay until that time. 28736831Skarels * If we just sent a full update, delay the dynamic update. 28836831Skarels * Set a timer for a randomized value to suppress additional 28936831Skarels * dynamic updates until it expires; if we delayed sending 29036831Skarels * the current changes, set needupdate. 29136831Skarels */ 29236831Skarels if (changes && supplier && 29336831Skarels now.tv_sec - lastfullupdate.tv_sec < SUPPLY_INTERVAL-MAX_WAITTIME) { 29436831Skarels u_long delay; 29536831Skarels extern long random(); 29636831Skarels 29736831Skarels if (now.tv_sec - lastbcast.tv_sec >= MIN_WAITTIME && 29836831Skarels timercmp(&nextbcast, &now, <)) { 29936831Skarels if (traceactions) 30036831Skarels fprintf(ftrace, "send dynamic update\n"); 30136831Skarels toall(supply, RTS_CHANGED, ifp); 30236831Skarels lastbcast = now; 30336831Skarels needupdate = 0; 30436831Skarels nextbcast.tv_sec = 0; 30536831Skarels } else { 30636831Skarels needupdate++; 30736831Skarels if (traceactions) 30836831Skarels fprintf(ftrace, "delay dynamic update\n"); 30936831Skarels } 31036831Skarels #define RANDOMDELAY() (MIN_WAITTIME * 1000000 + \ 31136831Skarels (u_long)random() % ((MAX_WAITTIME - MIN_WAITTIME) * 1000000)) 31236831Skarels 31336831Skarels if (nextbcast.tv_sec == 0) { 31436831Skarels delay = RANDOMDELAY(); 31536831Skarels if (traceactions) 31636831Skarels fprintf(ftrace, 31736831Skarels "inhibit dynamic update for %d usec\n", 31836831Skarels delay); 31936831Skarels nextbcast.tv_sec = delay / 1000000; 32036831Skarels nextbcast.tv_usec = delay % 1000000; 32136831Skarels timevaladd(&nextbcast, &now); 32236831Skarels /* 32336831Skarels * If the next possibly dynamic update 32436831Skarels * is within MIN_WAITTIME of the next full update, 32536831Skarels * force the delay past the full update, 32636831Skarels * or we might send a dynamic update just before 32736831Skarels * the full update. 32836831Skarels */ 32936831Skarels if (nextbcast.tv_sec > lastfullupdate.tv_sec + 33036831Skarels SUPPLY_INTERVAL - MIN_WAITTIME) 33136831Skarels nextbcast.tv_sec = lastfullupdate.tv_sec + 33236831Skarels SUPPLY_INTERVAL + 1; 33336831Skarels } 33436831Skarels } 3359016Ssam } 336