|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983, 1988 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that this notice is preserved and that due credit is given ! 7: * to the University of California at Berkeley. The name of the University ! 8: * may not be used to endorse or promote products derived from this ! 9: * software without specific prior written permission. This software ! 10: * is provided ``as is'' without express or implied warranty. ! 11: */ ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)input.c 5.17 (Berkeley) 6/6/88"; ! 15: #endif /* not lint */ ! 16: ! 17: /* ! 18: * Routing Table Management Daemon ! 19: */ ! 20: #include "defs.h" ! 21: #include <sys/syslog.h> ! 22: ! 23: /* ! 24: * Process a newly received packet. ! 25: */ ! 26: rip_input(from, size) ! 27: struct sockaddr *from; ! 28: int size; ! 29: { ! 30: register struct rt_entry *rt; ! 31: register struct netinfo *n; ! 32: register struct interface *ifp; ! 33: struct interface *if_ifwithdstaddr(); ! 34: int newsize; ! 35: register struct afswitch *afp; ! 36: static struct sockaddr badfrom, badfrom2; ! 37: ! 38: ifp = 0; ! 39: TRACE_INPUT(ifp, from, size); ! 40: if (from->sa_family >= af_max || ! 41: (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0) { ! 42: syslog(LOG_INFO, ! 43: "\"from\" address in unsupported address family (%d), cmd %d\n", ! 44: from->sa_family, msg->rip_cmd); ! 45: return; ! 46: } ! 47: switch (msg->rip_cmd) { ! 48: ! 49: case RIPCMD_REQUEST: ! 50: newsize = 0; ! 51: size -= 4 * sizeof (char); ! 52: n = msg->rip_nets; ! 53: while (size > 0) { ! 54: if (size < sizeof (struct netinfo)) ! 55: break; ! 56: size -= sizeof (struct netinfo); ! 57: ! 58: if (msg->rip_vers > 0) { ! 59: n->rip_dst.sa_family = ! 60: ntohs(n->rip_dst.sa_family); ! 61: n->rip_metric = ntohl(n->rip_metric); ! 62: } ! 63: /* ! 64: * A single entry with sa_family == AF_UNSPEC and ! 65: * metric ``infinity'' means ``all routes''. ! 66: * We respond to routers only if we are acting ! 67: * as a supplier, or to anyone other than a router ! 68: * (eg, query). ! 69: */ ! 70: if (n->rip_dst.sa_family == AF_UNSPEC && ! 71: n->rip_metric == HOPCNT_INFINITY && size == 0) { ! 72: if (supplier || (*afp->af_portmatch)(from) == 0) ! 73: supply(from, 0, 0); ! 74: return; ! 75: } ! 76: if (n->rip_dst.sa_family < af_max && ! 77: afswitch[n->rip_dst.sa_family].af_hash) ! 78: rt = rtlookup(&n->rip_dst); ! 79: else ! 80: rt = 0; ! 81: n->rip_metric = rt == 0 ? HOPCNT_INFINITY : ! 82: min(rt->rt_metric + 1, HOPCNT_INFINITY); ! 83: if (msg->rip_vers > 0) { ! 84: n->rip_dst.sa_family = ! 85: htons(n->rip_dst.sa_family); ! 86: n->rip_metric = htonl(n->rip_metric); ! 87: } ! 88: n++, newsize += sizeof (struct netinfo); ! 89: } ! 90: if (newsize > 0) { ! 91: msg->rip_cmd = RIPCMD_RESPONSE; ! 92: newsize += sizeof (int); ! 93: (*afp->af_output)(s, 0, from, newsize); ! 94: } ! 95: return; ! 96: ! 97: case RIPCMD_TRACEON: ! 98: case RIPCMD_TRACEOFF: ! 99: /* verify message came from a privileged port */ ! 100: if ((*afp->af_portcheck)(from) == 0) ! 101: return; ! 102: if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags & ! 103: (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 || ! 104: ifp->int_flags & IFF_PASSIVE) { ! 105: syslog(LOG_ERR, "trace command from unknown router, %s", ! 106: (*afswitch[from->sa_family].af_format)(from)); ! 107: return; ! 108: } ! 109: packet[size] = '\0'; ! 110: if (msg->rip_cmd == RIPCMD_TRACEON) ! 111: traceon(msg->rip_tracefile); ! 112: else ! 113: traceoff(); ! 114: return; ! 115: ! 116: case RIPCMD_RESPONSE: ! 117: /* verify message came from a router */ ! 118: if ((*afp->af_portmatch)(from) == 0) ! 119: return; ! 120: (*afp->af_canon)(from); ! 121: /* are we talking to ourselves? */ ! 122: ifp = if_ifwithaddr(from); ! 123: if (ifp) { ! 124: if (ifp->int_flags & IFF_PASSIVE) { ! 125: syslog(LOG_ERR, ! 126: "bogus input (from passive interface, %s)", ! 127: (*afswitch[from->sa_family].af_format)(from)); ! 128: return; ! 129: } ! 130: rt = rtfind(from); ! 131: if (rt == 0 || ((rt->rt_state & RTS_INTERFACE) == 0) && ! 132: rt->rt_metric >= ifp->int_metric) ! 133: addrouteforif(ifp); ! 134: else ! 135: rt->rt_timer = 0; ! 136: return; ! 137: } ! 138: /* ! 139: * Update timer for interface on which the packet arrived. ! 140: * If from other end of a point-to-point link that isn't ! 141: * in the routing tables, (re-)add the route. ! 142: */ ! 143: if ((rt = rtfind(from)) && ! 144: (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE))) ! 145: rt->rt_timer = 0; ! 146: else if ((ifp = if_ifwithdstaddr(from)) && ! 147: (rt == 0 || rt->rt_metric >= ifp->int_metric)) ! 148: addrouteforif(ifp); ! 149: /* ! 150: * "Authenticate" router from which message originated. ! 151: * We accept routing packets from routers directly connected ! 152: * via broadcast or point-to-point networks, ! 153: * and from those listed in /etc/gateways. ! 154: */ ! 155: if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags & ! 156: (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 || ! 157: ifp->int_flags & IFF_PASSIVE) { ! 158: if (bcmp((char *)from, (char *)&badfrom, ! 159: sizeof(badfrom)) != 0) { ! 160: syslog(LOG_ERR, ! 161: "packet from unknown router, %s", ! 162: (*afswitch[from->sa_family].af_format)(from)); ! 163: badfrom = *from; ! 164: } ! 165: return; ! 166: } ! 167: size -= 4 * sizeof (char); ! 168: n = msg->rip_nets; ! 169: for (; size > 0; size -= sizeof (struct netinfo), n++) { ! 170: if (size < sizeof (struct netinfo)) ! 171: break; ! 172: if (msg->rip_vers > 0) { ! 173: n->rip_dst.sa_family = ! 174: ntohs(n->rip_dst.sa_family); ! 175: n->rip_metric = ntohl(n->rip_metric); ! 176: } ! 177: if (n->rip_dst.sa_family >= af_max || ! 178: (afp = &afswitch[n->rip_dst.sa_family])->af_hash == ! 179: (int (*)())0) { ! 180: syslog(LOG_INFO, ! 181: "route in unsupported address family (%d), from %s (af %d)\n", ! 182: n->rip_dst.sa_family, ! 183: (*afswitch[from->sa_family].af_format)(from), ! 184: from->sa_family); ! 185: continue; ! 186: } ! 187: if (((*afp->af_checkhost)(&n->rip_dst)) == 0) { ! 188: syslog(LOG_DEBUG, ! 189: "bad host in route from %s (af %d)\n", ! 190: (*afswitch[from->sa_family].af_format)(from), ! 191: from->sa_family); ! 192: continue; ! 193: } ! 194: if (n->rip_metric == 0 || ! 195: (unsigned) n->rip_metric > HOPCNT_INFINITY) { ! 196: if (bcmp((char *)from, (char *)&badfrom2, ! 197: sizeof(badfrom2)) != 0) { ! 198: syslog(LOG_ERR, ! 199: "bad metric (%d) from %s\n", ! 200: n->rip_metric, ! 201: (*afswitch[from->sa_family].af_format)(from)); ! 202: badfrom2 = *from; ! 203: } ! 204: continue; ! 205: } ! 206: /* ! 207: * Adjust metric according to incoming interface. ! 208: */ ! 209: if ((unsigned) n->rip_metric < HOPCNT_INFINITY) ! 210: n->rip_metric += ifp->int_metric; ! 211: if ((unsigned) n->rip_metric > HOPCNT_INFINITY) ! 212: n->rip_metric = HOPCNT_INFINITY; ! 213: rt = rtlookup(&n->rip_dst); ! 214: if (rt == 0 || ! 215: (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) == ! 216: (RTS_INTERNAL|RTS_INTERFACE)) { ! 217: /* ! 218: * If we're hearing a logical network route ! 219: * back from a peer to which we sent it, ! 220: * ignore it. ! 221: */ ! 222: if (rt && rt->rt_state & RTS_SUBNET && ! 223: (*afp->af_sendroute)(rt, from)) ! 224: continue; ! 225: if ((unsigned)n->rip_metric < HOPCNT_INFINITY) { ! 226: /* ! 227: * Look for an equivalent route that ! 228: * includes this one before adding ! 229: * this route. ! 230: */ ! 231: rt = rtfind(&n->rip_dst); ! 232: if (rt && equal(from, &rt->rt_router)) ! 233: continue; ! 234: rtadd(&n->rip_dst, from, n->rip_metric, 0); ! 235: } ! 236: continue; ! 237: } ! 238: ! 239: /* ! 240: * Update if from gateway and different, ! 241: * shorter, or equivalent but old route ! 242: * is getting stale. ! 243: */ ! 244: if (equal(from, &rt->rt_router)) { ! 245: if (n->rip_metric != rt->rt_metric) { ! 246: rtchange(rt, from, n->rip_metric); ! 247: rt->rt_timer = 0; ! 248: if (rt->rt_metric >= HOPCNT_INFINITY) ! 249: rt->rt_timer = ! 250: GARBAGE_TIME - EXPIRE_TIME; ! 251: } else if (rt->rt_metric < HOPCNT_INFINITY) ! 252: rt->rt_timer = 0; ! 253: } else if ((unsigned) n->rip_metric < rt->rt_metric || ! 254: (rt->rt_metric == n->rip_metric && ! 255: rt->rt_timer > (EXPIRE_TIME/2) && ! 256: (unsigned) n->rip_metric < HOPCNT_INFINITY)) { ! 257: rtchange(rt, from, n->rip_metric); ! 258: rt->rt_timer = 0; ! 259: } ! 260: } ! 261: return; ! 262: } ! 263: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.