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