Make changes to allow for split nets on pt to pt interfaces.
[unix-history] / usr / src / sbin / XNSrouted / input.c
CommitLineData
e69f81e0
KS
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
786d36ce 11#ifndef lint
3efa4c38 12static char sccsid[] = "@(#)input.c 5.5 (Berkeley) %G%";
e69f81e0 13#endif not lint
786d36ce
KS
14
15/*
16 * XNS Routing Table Management Daemon
17 */
18#include "defs.h"
19
20struct sockaddr *
21xns_nettosa(net)
22u_short *net;
23{
48681466
KS
24 static struct sockaddr_ns sxn;
25 extern char ether_broadcast_addr[6];
786d36ce 26
48681466
KS
27 bzero(&sxn, sizeof (struct sockaddr_ns));
28 sxn.sns_family = AF_NS;
29 xnnet(sxn.sns_addr.x_net) = xnnet(net[0]);
30 sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr;
786d36ce
KS
31 return( (struct sockaddr *)&sxn);
32
33}
34
35/*
36 * Process a newly received packet.
37 */
38rip_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
48681466 49 ifp = 0;
786d36ce
KS
50 TRACE_INPUT(ifp, from, size);
51 if (from->sa_family >= AF_MAX)
52 return;
53 afp = &afswitch[from->sa_family];
54
786d36ce
KS
55 size -= sizeof (u_short) /* command */;
56 n = msg->rip_nets;
57
58 switch (ntohs(msg->rip_cmd)) {
59
60 case RIPCMD_REQUEST:
786d36ce
KS
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 */
48681466
KS
71 if (ntohl(xnnet(n->rip_dst[0])) == DSTNETS_ALL &&
72 ntohs(n->rip_metric) == HOPCNT_INFINITY &&
73 size == 0) {
74 ifp = if_ifwithnet(from);
75 supply(from, 0, ifp);
786d36ce
KS
76 return;
77 }
78 /*
79 * request for specific nets
80 */
81 rt = rtlookup(xns_nettosa(n->rip_dst));
610b111d 82 if (ftrace) {
e69f81e0
KS
83 fprintf(ftrace,
84 "specific request for %d",
85 ntohl(xnnet(n->rip_dst[0])));
86 fprintf(ftrace,
87 "yields route %x",
88 rt);
89 }
786d36ce
KS
90 n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY :
91 min(rt->rt_metric+1, HOPCNT_INFINITY));
92 n++, newsize += sizeof (struct netinfo);
93 }
94 if (newsize > 0) {
95 msg->rip_cmd = htons(RIPCMD_RESPONSE);
96 newsize += sizeof (u_short);
97 /* should check for if with dstaddr(from) first */
e69f81e0 98 (*afp->af_output)(0, from, newsize);
610b111d
KS
99 (ifp = if_ifwithnet(from));
100 if (ftrace) {
e69f81e0
KS
101 fprintf(ftrace,
102 ", request arriving on interface %x\n",
103 ifp);
104 }
786d36ce
KS
105 }
106 return;
107
108 case RIPCMD_RESPONSE:
109 /* verify message came from a router */
110 if ((*afp->af_portmatch)(from) == 0)
111 return;
48681466
KS
112 (*afp->af_canon)(from);
113 /* are we talking to ourselves? */
114 if (ifp = if_ifwithaddr(from)) {
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 }
e69f81e0
KS
122 /* Update timer for interface on which the packet arrived.
123 * If from other end of a point-to-point link that isn't
124 * in the routing tables, (re-)add the route.
125 */
126 if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) {
610b111d 127 if(ftrace) fprintf(ftrace, "Got route\n");
786d36ce 128 rt->rt_timer = 0;
e69f81e0 129 } else if (ifp = if_ifwithdstaddr(from)) {
610b111d 130 if(ftrace) fprintf(ftrace, "Got partner\n");
e69f81e0
KS
131 addrouteforif(ifp);
132 }
786d36ce 133 for (; size > 0; size -= sizeof (struct netinfo), n++) {
e69f81e0 134 struct sockaddr *sa;
786d36ce
KS
135 if (size < sizeof (struct netinfo))
136 break;
3efa4c38 137 if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY)
786d36ce 138 continue;
e69f81e0 139 rt = rtfind(sa = xns_nettosa(n->rip_dst));
786d36ce 140 if (rt == 0) {
e69f81e0 141 rtadd(sa, from, ntohs(n->rip_metric), 0);
786d36ce
KS
142 continue;
143 }
144
145 /*
146 * Update if from gateway and different,
147 * from anywhere and shorter, or getting stale and equivalent.
148 */
149 if ((equal(from, &rt->rt_router) &&
150 ntohs(n->rip_metric) != rt->rt_metric ) ||
151 (unsigned) ntohs(n->rip_metric) < rt->rt_metric ||
152 (rt->rt_timer > (EXPIRE_TIME/2) &&
153 rt->rt_metric == ntohs(n->rip_metric))) {
154 rtchange(rt, from, ntohs(n->rip_metric));
155 rt->rt_timer = 0;
156 }
157 }
158 return;
159 }
160}