|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)input.c 5.6 (Berkeley) 6/3/86"; ! 9: #endif not lint ! 10: ! 11: /* ! 12: * Routing Table Management Daemon ! 13: */ ! 14: #include "defs.h" ! 15: #include <sys/syslog.h> ! 16: ! 17: /* ! 18: * Process a newly received packet. ! 19: */ ! 20: rip_input(from, size) ! 21: struct sockaddr *from; ! 22: int size; ! 23: { ! 24: register struct rt_entry *rt; ! 25: register struct netinfo *n; ! 26: register struct interface *ifp; ! 27: struct interface *if_ifwithdstaddr(); ! 28: int newsize; ! 29: register struct afswitch *afp; ! 30: ! 31: ifp = 0; ! 32: TRACE_INPUT(ifp, from, size); ! 33: if (from->sa_family >= af_max || ! 34: (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0) { ! 35: syslog(LOG_INFO, ! 36: "\"from\" address in unsupported address family (%d), cmd %d\n", ! 37: from->sa_family, msg->rip_cmd); ! 38: return; ! 39: } ! 40: switch (msg->rip_cmd) { ! 41: ! 42: case RIPCMD_REQUEST: ! 43: newsize = 0; ! 44: size -= 4 * sizeof (char); ! 45: n = msg->rip_nets; ! 46: while (size > 0) { ! 47: if (size < sizeof (struct netinfo)) ! 48: break; ! 49: size -= sizeof (struct netinfo); ! 50: ! 51: if (msg->rip_vers > 0) { ! 52: n->rip_dst.sa_family = ! 53: ntohs(n->rip_dst.sa_family); ! 54: n->rip_metric = ntohl(n->rip_metric); ! 55: } ! 56: /* ! 57: * A single entry with sa_family == AF_UNSPEC and ! 58: * metric ``infinity'' means ``all routes''. ! 59: * We respond to routers only if we are acting ! 60: * as a supplier, or to anyone other than a router ! 61: * (eg, query). ! 62: */ ! 63: if (n->rip_dst.sa_family == AF_UNSPEC && ! 64: n->rip_metric == HOPCNT_INFINITY && size == 0) { ! 65: if (supplier || (*afp->af_portmatch)(from) == 0) ! 66: supply(from, 0, 0); ! 67: return; ! 68: } ! 69: if (n->rip_dst.sa_family < af_max && ! 70: afswitch[n->rip_dst.sa_family].af_hash) ! 71: rt = rtlookup(&n->rip_dst); ! 72: else ! 73: rt = 0; ! 74: n->rip_metric = rt == 0 ? HOPCNT_INFINITY : ! 75: min(rt->rt_metric+1, HOPCNT_INFINITY); ! 76: if (msg->rip_vers > 0) { ! 77: n->rip_dst.sa_family = ! 78: htons(n->rip_dst.sa_family); ! 79: n->rip_metric = htonl(n->rip_metric); ! 80: } ! 81: n++, newsize += sizeof (struct netinfo); ! 82: } ! 83: if (newsize > 0) { ! 84: msg->rip_cmd = RIPCMD_RESPONSE; ! 85: newsize += sizeof (int); ! 86: (*afp->af_output)(s, 0, from, newsize); ! 87: } ! 88: return; ! 89: ! 90: case RIPCMD_TRACEON: ! 91: case RIPCMD_TRACEOFF: ! 92: /* verify message came from a privileged port */ ! 93: if ((*afp->af_portcheck)(from) == 0) ! 94: return; ! 95: if (if_iflookup(from) == 0) { ! 96: syslog(LOG_ERR, "trace command from unknown router, %s", ! 97: (*afswitch[from->sa_family].af_format)(from)); ! 98: return; ! 99: } ! 100: packet[size] = '\0'; ! 101: if (msg->rip_cmd == RIPCMD_TRACEON) ! 102: traceon(msg->rip_tracefile); ! 103: else ! 104: traceoff(); ! 105: return; ! 106: ! 107: case RIPCMD_RESPONSE: ! 108: /* verify message came from a router */ ! 109: if ((*afp->af_portmatch)(from) == 0) ! 110: return; ! 111: (*afp->af_canon)(from); ! 112: /* are we talking to ourselves? */ ! 113: ifp = if_ifwithaddr(from); ! 114: if (ifp) { ! 115: rt = rtfind(from); ! 116: if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0) ! 117: addrouteforif(ifp); ! 118: else ! 119: rt->rt_timer = 0; ! 120: return; ! 121: } ! 122: /* ! 123: * Update timer for interface on which the packet arrived. ! 124: * If from other end of a point-to-point link that isn't ! 125: * in the routing tables, (re-)add the route. ! 126: */ ! 127: if ((rt = rtfind(from)) && ! 128: (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE))) ! 129: rt->rt_timer = 0; ! 130: else if (ifp = if_ifwithdstaddr(from)) ! 131: addrouteforif(ifp); ! 132: else if (if_iflookup(from) == 0) { ! 133: syslog(LOG_ERR, "packet from unknown router, %s", ! 134: (*afswitch[from->sa_family].af_format)(from)); ! 135: return; ! 136: } ! 137: size -= 4 * sizeof (char); ! 138: n = msg->rip_nets; ! 139: for (; size > 0; size -= sizeof (struct netinfo), n++) { ! 140: if (size < sizeof (struct netinfo)) ! 141: break; ! 142: if (msg->rip_vers > 0) { ! 143: n->rip_dst.sa_family = ! 144: ntohs(n->rip_dst.sa_family); ! 145: n->rip_metric = ntohl(n->rip_metric); ! 146: } ! 147: if ((unsigned) n->rip_metric > HOPCNT_INFINITY) ! 148: continue; ! 149: if (n->rip_dst.sa_family >= af_max || ! 150: (afp = &afswitch[n->rip_dst.sa_family])->af_hash == ! 151: (int (*)())0) { ! 152: syslog(LOG_INFO, ! 153: "route in unsupported address family (%d), from %s (af %d)\n", ! 154: n->rip_dst.sa_family, ! 155: (*afswitch[from->sa_family].af_format)(from), ! 156: from->sa_family); ! 157: continue; ! 158: } ! 159: if (((*afp->af_checkhost)(&n->rip_dst)) == 0) { ! 160: syslog(LOG_DEBUG, ! 161: "bad host in route from %s (af %d)\n", ! 162: (*afswitch[from->sa_family].af_format)(from), ! 163: from->sa_family); ! 164: continue; ! 165: } ! 166: rt = rtlookup(&n->rip_dst); ! 167: if (rt == 0 || ! 168: (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) == ! 169: (RTS_INTERNAL|RTS_INTERFACE)) { ! 170: rt = rtfind(&n->rip_dst); ! 171: if (rt && equal(from, &rt->rt_router) && ! 172: rt->rt_metric == n->rip_metric) ! 173: continue; ! 174: if (n->rip_metric < HOPCNT_INFINITY) ! 175: rtadd(&n->rip_dst, from, n->rip_metric, 0); ! 176: continue; ! 177: } ! 178: ! 179: /* ! 180: * Update if from gateway and different, ! 181: * shorter, or getting stale and equivalent. ! 182: */ ! 183: if (equal(from, &rt->rt_router)) { ! 184: if (n->rip_metric == HOPCNT_INFINITY) { ! 185: rtdelete(rt); ! 186: continue; ! 187: } ! 188: if (n->rip_metric != rt->rt_metric) ! 189: rtchange(rt, from, n->rip_metric); ! 190: rt->rt_timer = 0; ! 191: } else if ((unsigned) (n->rip_metric) < rt->rt_metric || ! 192: (rt->rt_timer > (EXPIRE_TIME/2) && ! 193: rt->rt_metric == n->rip_metric)) { ! 194: rtchange(rt, from, n->rip_metric); ! 195: rt->rt_timer = 0; ! 196: } ! 197: } ! 198: return; ! 199: } ! 200: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.