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