|
|
1.1 root 1: /*
2: * Copyright (c) 1985 The Regents of the University of California.
3: * 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: * Redistribution and use in source and binary forms are permitted
9: * provided that: (1) source distributions retain this entire copyright
10: * notice and comment, and (2) distributions including binaries display
11: * the following acknowledgement: ``This product includes software
12: * developed by the University of California, Berkeley and its contributors''
13: * in the documentation or other materials provided with the distribution
14: * and in all advertising materials mentioning features or use of this
15: * software. Neither the name of the University nor the names of its
16: * contributors may be used to endorse or promote products derived
17: * from this software without specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #ifndef lint
24: static char sccsid[] = "@(#)input.c 5.9 (Berkeley) 6/1/90";
25: #endif /* not lint */
26:
27: /*
28: * XNS Routing Table Management Daemon
29: */
30: #include "defs.h"
31:
32: struct sockaddr *
33: xns_nettosa(net)
34: union ns_net net;
35: {
36: static struct sockaddr_ns sxn;
37: extern char ether_broadcast_addr[6];
38:
39: bzero(&sxn, sizeof (struct sockaddr_ns));
40: sxn.sns_family = AF_NS;
41: sxn.sns_len = sizeof (sxn);
42: sxn.sns_addr.x_net = net;
43: sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr;
44: return( (struct sockaddr *)&sxn);
45:
46: }
47:
48: /*
49: * Process a newly received packet.
50: */
51: rip_input(from, size)
52: struct sockaddr *from;
53: int size;
54: {
55: struct rt_entry *rt;
56: struct netinfo *n;
57: struct interface *ifp;
58: int newsize;
59: struct afswitch *afp;
60:
61:
62: ifp = 0;
63: TRACE_INPUT(ifp, from, size);
64: if (from->sa_family >= AF_MAX)
65: return;
66: afp = &afswitch[from->sa_family];
67:
68: size -= sizeof (u_short) /* command */;
69: n = msg->rip_nets;
70:
71: switch (ntohs(msg->rip_cmd)) {
72:
73: case RIPCMD_REQUEST:
74: newsize = 0;
75: while (size > 0) {
76: if (size < sizeof (struct netinfo))
77: break;
78: size -= sizeof (struct netinfo);
79:
80: /*
81: * A single entry with rip_dst == DSTNETS_ALL and
82: * metric ``infinity'' means ``all routes''.
83: */
84: if (ns_neteqnn(n->rip_dst, ns_anynet) &&
85: ntohs(n->rip_metric) == HOPCNT_INFINITY &&
86: size == 0) {
87: ifp = if_ifwithnet(from);
88: supply(from, 0, ifp);
89: return;
90: }
91: /*
92: * request for specific nets
93: */
94: rt = rtlookup(xns_nettosa(n->rip_dst));
95: if (ftrace) {
96: fprintf(ftrace,
97: "specific request for %s",
98: xns_nettoa(n->rip_dst));
99: fprintf(ftrace,
100: " yields route %x\n",
101: rt);
102: }
103: n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY :
104: min(rt->rt_metric+1, HOPCNT_INFINITY));
105: n++;
106: newsize += sizeof (struct netinfo);
107: }
108: if (newsize > 0) {
109: msg->rip_cmd = htons(RIPCMD_RESPONSE);
110: newsize += sizeof (u_short);
111: /* should check for if with dstaddr(from) first */
112: (*afp->af_output)(0, from, newsize);
113: ifp = if_ifwithnet(from);
114: TRACE_OUTPUT(ifp, from, newsize);
115: if (ftrace) {
116: fprintf(ftrace,
117: "request arrived on interface %s\n",
118: ifp->int_name);
119: }
120: }
121: return;
122:
123: case RIPCMD_RESPONSE:
124: /* verify message came from a router */
125: if ((*afp->af_portmatch)(from) == 0)
126: return;
127: (*afp->af_canon)(from);
128: /* are we talking to ourselves? */
129: if (ifp = if_ifwithaddr(from)) {
130: rt = rtfind(from);
131: if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
132: addrouteforif(ifp);
133: else
134: rt->rt_timer = 0;
135: return;
136: }
137: /* Update timer for interface on which the packet arrived.
138: * If from other end of a point-to-point link that isn't
139: * in the routing tables, (re-)add the route.
140: */
141: if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) {
142: if(ftrace) fprintf(ftrace, "Got route\n");
143: rt->rt_timer = 0;
144: } else if (ifp = if_ifwithdstaddr(from)) {
145: if(ftrace) fprintf(ftrace, "Got partner\n");
146: addrouteforif(ifp);
147: }
148: for (; size > 0; size -= sizeof (struct netinfo), n++) {
149: struct sockaddr *sa;
150: if (size < sizeof (struct netinfo))
151: break;
152: if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY)
153: continue;
154: rt = rtfind(sa = xns_nettosa(n->rip_dst));
155: if (rt == 0) {
156: rtadd(sa, from, ntohs(n->rip_metric), 0);
157: continue;
158: }
159:
160: /*
161: * Update if from gateway and different,
162: * from anywhere and shorter, or getting stale and equivalent.
163: */
164: if ((equal(from, &rt->rt_router) &&
165: ntohs(n->rip_metric) != rt->rt_metric ) ||
166: (unsigned) ntohs(n->rip_metric) < rt->rt_metric ||
167: (rt->rt_timer > (EXPIRE_TIME/2) &&
168: rt->rt_metric == ntohs(n->rip_metric))) {
169: rtchange(rt, from, ntohs(n->rip_metric));
170: rt->rt_timer = 0;
171: }
172: }
173: return;
174: }
175: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.