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 | * | |
6ecf3d85 | 8 | * %sccs.include.redist.c% |
e69f81e0 KS |
9 | */ |
10 | ||
786d36ce | 11 | #ifndef lint |
6ecf3d85 | 12 | static char sccsid[] = "@(#)input.c 5.9 (Berkeley) %G%"; |
3565c602 | 13 | #endif /* not lint */ |
786d36ce KS |
14 | |
15 | /* | |
16 | * XNS Routing Table Management Daemon | |
17 | */ | |
18 | #include "defs.h" | |
19 | ||
20 | struct sockaddr * | |
21 | xns_nettosa(net) | |
84f93e8f | 22 | union ns_net net; |
786d36ce | 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; | |
0b7e1339 | 29 | sxn.sns_len = sizeof (sxn); |
84f93e8f | 30 | sxn.sns_addr.x_net = net; |
48681466 | 31 | sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr; |
786d36ce KS |
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 | ||
48681466 | 50 | ifp = 0; |
786d36ce KS |
51 | TRACE_INPUT(ifp, from, size); |
52 | if (from->sa_family >= AF_MAX) | |
53 | return; | |
54 | afp = &afswitch[from->sa_family]; | |
55 | ||
786d36ce KS |
56 | size -= sizeof (u_short) /* command */; |
57 | n = msg->rip_nets; | |
58 | ||
59 | switch (ntohs(msg->rip_cmd)) { | |
60 | ||
61 | case RIPCMD_REQUEST: | |
786d36ce KS |
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 | */ | |
84f93e8f | 72 | if (ns_neteqnn(n->rip_dst, ns_anynet) && |
48681466 KS |
73 | ntohs(n->rip_metric) == HOPCNT_INFINITY && |
74 | size == 0) { | |
75 | ifp = if_ifwithnet(from); | |
76 | supply(from, 0, ifp); | |
786d36ce KS |
77 | return; |
78 | } | |
79 | /* | |
80 | * request for specific nets | |
81 | */ | |
82 | rt = rtlookup(xns_nettosa(n->rip_dst)); | |
610b111d | 83 | if (ftrace) { |
e69f81e0 | 84 | fprintf(ftrace, |
84f93e8f KS |
85 | "specific request for %s", |
86 | xns_nettoa(n->rip_dst)); | |
e69f81e0 | 87 | fprintf(ftrace, |
84f93e8f | 88 | " yields route %x\n", |
e69f81e0 KS |
89 | rt); |
90 | } | |
786d36ce KS |
91 | n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY : |
92 | min(rt->rt_metric+1, HOPCNT_INFINITY)); | |
84f93e8f KS |
93 | n++; |
94 | newsize += sizeof (struct netinfo); | |
786d36ce KS |
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 */ | |
e69f81e0 | 100 | (*afp->af_output)(0, from, newsize); |
84f93e8f KS |
101 | ifp = if_ifwithnet(from); |
102 | TRACE_OUTPUT(ifp, from, newsize); | |
610b111d | 103 | if (ftrace) { |
e69f81e0 | 104 | fprintf(ftrace, |
84f93e8f KS |
105 | "request arrived on interface %s\n", |
106 | ifp->int_name); | |
e69f81e0 | 107 | } |
786d36ce KS |
108 | } |
109 | return; | |
110 | ||
111 | case RIPCMD_RESPONSE: | |
112 | /* verify message came from a router */ | |
113 | if ((*afp->af_portmatch)(from) == 0) | |
114 | return; | |
48681466 KS |
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 | } | |
e69f81e0 KS |
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)) { | |
610b111d | 130 | if(ftrace) fprintf(ftrace, "Got route\n"); |
786d36ce | 131 | rt->rt_timer = 0; |
e69f81e0 | 132 | } else if (ifp = if_ifwithdstaddr(from)) { |
610b111d | 133 | if(ftrace) fprintf(ftrace, "Got partner\n"); |
e69f81e0 KS |
134 | addrouteforif(ifp); |
135 | } | |
786d36ce | 136 | for (; size > 0; size -= sizeof (struct netinfo), n++) { |
e69f81e0 | 137 | struct sockaddr *sa; |
786d36ce KS |
138 | if (size < sizeof (struct netinfo)) |
139 | break; | |
3efa4c38 | 140 | if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY) |
786d36ce | 141 | continue; |
e69f81e0 | 142 | rt = rtfind(sa = xns_nettosa(n->rip_dst)); |
786d36ce | 143 | if (rt == 0) { |
e69f81e0 | 144 | rtadd(sa, from, ntohs(n->rip_metric), 0); |
786d36ce KS |
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 | } |