1 /* 2 * Copyright (c) 1985, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This file includes significant work done at Cornell University by 6 * Bill Nesheim. That work included by permission. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 06/05/93"; 13 #endif /* not lint */ 14 15 /* 16 * XNS Routing Table Management Daemon 17 */ 18 #include "defs.h" 19 20 struct sockaddr * 21 xns_nettosa(net) 22 union ns_net net; 23 { 24 static struct sockaddr_ns sxn; 25 extern char ether_broadcast_addr[6]; 26 27 bzero(&sxn, sizeof (struct sockaddr_ns)); 28 sxn.sns_family = AF_NS; 29 sxn.sns_len = sizeof (sxn); 30 sxn.sns_addr.x_net = net; 31 sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr; 32 return( (struct sockaddr *)&sxn); 33 34 } 35 36 /* 37 * Process a newly received packet. 38 */ 39 rip_input(from, size) 40 struct sockaddr *from; 41 int size; 42 { 43 struct rt_entry *rt; 44 struct netinfo *n; 45 struct interface *ifp; 46 int newsize; 47 struct afswitch *afp; 48 49 50 ifp = 0; 51 TRACE_INPUT(ifp, from, size); 52 if (from->sa_family >= AF_MAX) 53 return; 54 afp = &afswitch[from->sa_family]; 55 56 size -= sizeof (u_short) /* command */; 57 n = msg->rip_nets; 58 59 switch (ntohs(msg->rip_cmd)) { 60 61 case RIPCMD_REQUEST: 62 newsize = 0; 63 while (size > 0) { 64 if (size < sizeof (struct netinfo)) 65 break; 66 size -= sizeof (struct netinfo); 67 68 /* 69 * A single entry with rip_dst == DSTNETS_ALL and 70 * metric ``infinity'' means ``all routes''. 71 */ 72 if (ns_neteqnn(n->rip_dst, ns_anynet) && 73 ntohs(n->rip_metric) == HOPCNT_INFINITY && 74 size == 0) { 75 ifp = if_ifwithnet(from); 76 supply(from, 0, ifp); 77 return; 78 } 79 /* 80 * request for specific nets 81 */ 82 rt = rtlookup(xns_nettosa(n->rip_dst)); 83 if (ftrace) { 84 fprintf(ftrace, 85 "specific request for %s", 86 xns_nettoa(n->rip_dst)); 87 fprintf(ftrace, 88 " yields route %x\n", 89 rt); 90 } 91 n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY : 92 min(rt->rt_metric+1, HOPCNT_INFINITY)); 93 n++; 94 newsize += sizeof (struct netinfo); 95 } 96 if (newsize > 0) { 97 msg->rip_cmd = htons(RIPCMD_RESPONSE); 98 newsize += sizeof (u_short); 99 /* should check for if with dstaddr(from) first */ 100 (*afp->af_output)(0, from, newsize); 101 ifp = if_ifwithnet(from); 102 TRACE_OUTPUT(ifp, from, newsize); 103 if (ftrace) { 104 fprintf(ftrace, 105 "request arrived on interface %s\n", 106 ifp->int_name); 107 } 108 } 109 return; 110 111 case RIPCMD_RESPONSE: 112 /* verify message came from a router */ 113 if ((*afp->af_portmatch)(from) == 0) 114 return; 115 (*afp->af_canon)(from); 116 /* are we talking to ourselves? */ 117 if (ifp = if_ifwithaddr(from)) { 118 rt = rtfind(from); 119 if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0) 120 addrouteforif(ifp); 121 else 122 rt->rt_timer = 0; 123 return; 124 } 125 /* Update timer for interface on which the packet arrived. 126 * If from other end of a point-to-point link that isn't 127 * in the routing tables, (re-)add the route. 128 */ 129 if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) { 130 if(ftrace) fprintf(ftrace, "Got route\n"); 131 rt->rt_timer = 0; 132 } else if (ifp = if_ifwithdstaddr(from)) { 133 if(ftrace) fprintf(ftrace, "Got partner\n"); 134 addrouteforif(ifp); 135 } 136 for (; size > 0; size -= sizeof (struct netinfo), n++) { 137 struct sockaddr *sa; 138 if (size < sizeof (struct netinfo)) 139 break; 140 if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY) 141 continue; 142 rt = rtfind(sa = xns_nettosa(n->rip_dst)); 143 if (rt == 0) { 144 rtadd(sa, from, ntohs(n->rip_metric), 0); 145 continue; 146 } 147 148 /* 149 * Update if from gateway and different, 150 * from anywhere and shorter, or getting stale and equivalent. 151 */ 152 if ((equal(from, &rt->rt_router) && 153 ntohs(n->rip_metric) != rt->rt_metric ) || 154 (unsigned) ntohs(n->rip_metric) < rt->rt_metric || 155 (rt->rt_timer > (EXPIRE_TIME/2) && 156 rt->rt_metric == ntohs(n->rip_metric))) { 157 rtchange(rt, from, ntohs(n->rip_metric)); 158 rt->rt_timer = 0; 159 } 160 } 161 return; 162 } 163 } 164