Commit | Line | Data |
---|---|---|
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 | 12 | static 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 | ||
20 | struct sockaddr * | |
21 | xns_nettosa(net) | |
22 | u_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 | */ | |
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 | ||
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 | } |