Commit | Line | Data |
---|---|---|
8ae0e4b4 | 1 | /* |
240edf1f KS |
2 | * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. |
3 | * All rights reserved. | |
8ae0e4b4 | 4 | * |
240edf1f | 5 | * Redistribution and use in source and binary forms are permitted |
616d42db KB |
6 | * provided that the above copyright notice and this paragraph are |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
240edf1f | 16 | * |
616d42db | 17 | * @(#)ns.c 7.3 (Berkeley) %G% |
8ae0e4b4 | 18 | */ |
de9bc7de KS |
19 | |
20 | #include "param.h" | |
21 | #include "mbuf.h" | |
22 | #include "ioctl.h" | |
23 | #include "protosw.h" | |
24 | #include "socket.h" | |
25 | #include "socketvar.h" | |
26 | #include "uio.h" | |
27 | #include "dir.h" | |
28 | #include "user.h" | |
29 | ||
30 | ||
31 | #include "../net/if.h" | |
32 | #include "../net/route.h" | |
33 | #include "../net/af.h" | |
34 | ||
35 | #include "ns.h" | |
36 | #include "ns_if.h" | |
37 | ||
38 | #ifdef NS | |
39 | ||
40 | struct ns_ifaddr *ns_ifaddr; | |
41 | ||
42 | ns_hash(sns, hp) | |
43 | register struct sockaddr_ns *sns; | |
44 | struct afhash *hp; | |
45 | { | |
46 | register long hash = 0; | |
47 | register u_short *s = sns->sns_addr.x_host.s_host; | |
f1e269d4 KS |
48 | union { |
49 | union ns_net net_e; | |
50 | long long_e; | |
51 | } net; | |
de9bc7de | 52 | |
f1e269d4 KS |
53 | net.net_e = sns->sns_addr.x_net; |
54 | hp->afh_nethash = net.long_e; | |
de9bc7de KS |
55 | hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s; |
56 | hp->afh_hosthash = hash; | |
57 | } | |
58 | ||
59 | ||
60 | ns_netmatch(sns1, sns2) | |
61 | struct sockaddr_ns *sns1, *sns2; | |
62 | { | |
63 | ||
f1e269d4 | 64 | return (ns_neteq(sns1->sns_addr, sns2->sns_addr)); |
de9bc7de KS |
65 | } |
66 | ||
67 | /* | |
68 | * Generic internet control operations (ioctl's). | |
69 | */ | |
f97be0c9 | 70 | /* ARGSUSED */ |
de9bc7de KS |
71 | ns_control(so, cmd, data, ifp) |
72 | struct socket *so; | |
73 | int cmd; | |
74 | caddr_t data; | |
75 | register struct ifnet *ifp; | |
76 | { | |
77 | register struct ifreq *ifr = (struct ifreq *)data; | |
78 | register struct ns_ifaddr *ia; | |
79 | struct ifaddr *ifa; | |
80 | struct mbuf *m; | |
de9bc7de | 81 | |
de9bc7de KS |
82 | /* |
83 | * Find address for this interface, if it exists. | |
84 | */ | |
8b659320 | 85 | if (ifp == 0) |
4353fa68 | 86 | return (EADDRNOTAVAIL); |
de9bc7de KS |
87 | for (ia = ns_ifaddr; ia; ia = ia->ia_next) |
88 | if (ia->ia_ifp == ifp) | |
89 | break; | |
90 | ||
91 | switch (cmd) { | |
92 | ||
93 | case SIOCGIFADDR: | |
4353fa68 KS |
94 | if (ia == (struct ns_ifaddr *)0) |
95 | return (EADDRNOTAVAIL); | |
96 | ifr->ifr_addr = ia->ia_addr; | |
97 | return (0); | |
98 | ||
99 | ||
de9bc7de | 100 | case SIOCGIFBRDADDR: |
4353fa68 KS |
101 | if (ia == (struct ns_ifaddr *)0) |
102 | return (EADDRNOTAVAIL); | |
103 | if ((ifp->if_flags & IFF_BROADCAST) == 0) | |
104 | return (EINVAL); | |
105 | ifr->ifr_dstaddr = ia->ia_broadaddr; | |
106 | return (0); | |
107 | ||
de9bc7de KS |
108 | case SIOCGIFDSTADDR: |
109 | if (ia == (struct ns_ifaddr *)0) | |
110 | return (EADDRNOTAVAIL); | |
4353fa68 KS |
111 | if ((ifp->if_flags & IFF_POINTOPOINT) == 0) |
112 | return (EINVAL); | |
113 | ifr->ifr_dstaddr = ia->ia_dstaddr; | |
114 | return (0); | |
115 | } | |
116 | ||
117 | if (!suser()) | |
118 | return (u.u_error); | |
119 | ||
120 | switch (cmd) { | |
de9bc7de | 121 | |
de9bc7de | 122 | case SIOCSIFADDR: |
8b659320 | 123 | case SIOCSIFDSTADDR: |
de9bc7de KS |
124 | if (ia == (struct ns_ifaddr *)0) { |
125 | m = m_getclr(M_WAIT, MT_IFADDR); | |
126 | if (m == (struct mbuf *)NULL) | |
127 | return (ENOBUFS); | |
128 | if (ia = ns_ifaddr) { | |
129 | for ( ; ia->ia_next; ia = ia->ia_next) | |
130 | ; | |
131 | ia->ia_next = mtod(m, struct ns_ifaddr *); | |
132 | } else | |
133 | ns_ifaddr = mtod(m, struct ns_ifaddr *); | |
134 | ia = mtod(m, struct ns_ifaddr *); | |
135 | if (ifa = ifp->if_addrlist) { | |
136 | for ( ; ifa->ifa_next; ifa = ifa->ifa_next) | |
137 | ; | |
138 | ifa->ifa_next = (struct ifaddr *) ia; | |
139 | } else | |
140 | ifp->if_addrlist = (struct ifaddr *) ia; | |
141 | ia->ia_ifp = ifp; | |
142 | IA_SNS(ia)->sns_family = AF_NS; | |
143 | } | |
8b659320 KS |
144 | } |
145 | ||
146 | switch (cmd) { | |
147 | ||
148 | case SIOCSIFDSTADDR: | |
149 | if ((ifp->if_flags & IFF_POINTOPOINT) == 0) | |
150 | return (EINVAL); | |
151 | if (ia->ia_flags & IFA_ROUTE) { | |
152 | rtinit(&ia->ia_dstaddr, &ia->ia_addr, | |
153 | (int)SIOCDELRT, RTF_HOST); | |
154 | ia->ia_flags &= ~IFA_ROUTE; | |
155 | } | |
156 | if (ifp->if_ioctl) { | |
157 | int error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia); | |
158 | if (error) | |
159 | return (error); | |
160 | } | |
161 | ia->ia_dstaddr = ifr->ifr_dstaddr; | |
162 | return (0); | |
163 | ||
164 | case SIOCSIFADDR: | |
de9bc7de KS |
165 | return |
166 | (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr)); | |
167 | ||
168 | default: | |
169 | if (ifp->if_ioctl == 0) | |
170 | return (EOPNOTSUPP); | |
171 | return ((*ifp->if_ioctl)(ifp, cmd, data)); | |
172 | } | |
de9bc7de KS |
173 | } |
174 | ||
175 | /* | |
176 | * Initialize an interface's internet address | |
177 | * and routing table entry. | |
178 | */ | |
179 | ns_ifinit(ifp, ia, sns) | |
180 | register struct ifnet *ifp; | |
181 | register struct ns_ifaddr *ia; | |
182 | struct sockaddr_ns *sns; | |
183 | { | |
184 | struct sockaddr_ns netaddr; | |
185 | register union ns_host *h = &(IA_SNS(ia)->sns_addr.x_host); | |
186 | int s = splimp(), error; | |
187 | ||
188 | /* | |
189 | * The convention we shall adopt for naming is that | |
190 | * a supplied address of zero means that "we don't care". | |
191 | * if there is a single interface, use the address of that | |
192 | * interface as our 6 byte host address. | |
193 | * if there are multiple interfaces, use any address already | |
194 | * used. | |
195 | * | |
196 | * If we have gotten into trouble and want to reset back to | |
197 | * virginity, we recognize a request of the broadcast address. | |
198 | */ | |
199 | if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) { | |
200 | ns_thishost = ns_zerohost; | |
201 | splx(s); | |
8b659320 | 202 | return (0); |
de9bc7de KS |
203 | } |
204 | ||
205 | /* | |
206 | * Delete any previous route for an old address. | |
207 | */ | |
de9bc7de KS |
208 | bzero((caddr_t)&netaddr, sizeof (netaddr)); |
209 | netaddr.sns_family = AF_NS; | |
210 | netaddr.sns_addr.x_host = ns_broadhost; | |
211 | netaddr.sns_addr.x_net = ia->ia_net; | |
212 | if (ia->ia_flags & IFA_ROUTE) { | |
213 | if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { | |
8b659320 KS |
214 | rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, |
215 | (int)SIOCDELRT, 0); | |
de9bc7de | 216 | } else |
8b659320 KS |
217 | rtinit(&ia->ia_dstaddr, &ia->ia_addr, |
218 | (int)SIOCDELRT, RTF_HOST); | |
de9bc7de KS |
219 | } |
220 | ||
221 | /* | |
222 | * Set up new addresses. | |
223 | */ | |
224 | ia->ia_addr = *(struct sockaddr *)sns; | |
225 | ia->ia_net = sns->sns_addr.x_net; | |
226 | netaddr.sns_addr.x_net = ia->ia_net; | |
227 | if (ifp->if_flags & IFF_BROADCAST) { | |
228 | ia->ia_broadaddr = * (struct sockaddr *) &netaddr; | |
229 | } | |
8b659320 | 230 | |
de9bc7de KS |
231 | /* |
232 | * Give the interface a chance to initialize | |
233 | * if this is its first address, | |
234 | * and to validate the address if necessary. | |
235 | */ | |
de9bc7de KS |
236 | if (ns_hosteqnh(ns_thishost, ns_zerohost)) { |
237 | if (ifp->if_ioctl && | |
238 | (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { | |
239 | splx(s); | |
240 | return (error); | |
241 | } | |
242 | ns_thishost = *h; | |
243 | } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost) | |
244 | || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) { | |
245 | *h = ns_thishost; | |
246 | if (ifp->if_ioctl && | |
247 | (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { | |
248 | splx(s); | |
249 | return (error); | |
250 | } | |
8b659320 | 251 | if (!ns_hosteqnh(ns_thishost,*h)) { |
de9bc7de KS |
252 | splx(s); |
253 | return (EINVAL); | |
254 | } | |
255 | } else { | |
256 | splx(s); | |
8b659320 | 257 | return (EINVAL); |
de9bc7de | 258 | } |
8b659320 | 259 | |
de9bc7de KS |
260 | /* |
261 | * Add route for the network. | |
262 | */ | |
8b659320 KS |
263 | if (ifp->if_flags & IFF_POINTOPOINT) |
264 | rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT, | |
de9bc7de | 265 | RTF_HOST|RTF_UP); |
8b659320 KS |
266 | else |
267 | rtinit(&ia->ia_broadaddr, &ia->ia_addr, (int)SIOCADDRT, | |
268 | RTF_UP); | |
de9bc7de | 269 | ia->ia_flags |= IFA_ROUTE; |
8b659320 | 270 | return (0); |
de9bc7de KS |
271 | } |
272 | ||
273 | /* | |
274 | * Return address info for specified internet network. | |
275 | */ | |
276 | struct ns_ifaddr * | |
46aa06a9 KS |
277 | ns_iaonnetof(dst) |
278 | register struct ns_addr *dst; | |
de9bc7de KS |
279 | { |
280 | register struct ns_ifaddr *ia; | |
46aa06a9 | 281 | register struct ns_addr *compare; |
8b659320 KS |
282 | register struct ifnet *ifp; |
283 | struct ns_ifaddr *ia_maybe = 0; | |
f1e269d4 | 284 | union ns_net net = dst->x_net; |
de9bc7de | 285 | |
46aa06a9 | 286 | for (ia = ns_ifaddr; ia; ia = ia->ia_next) { |
8b659320 KS |
287 | if (ifp = ia->ia_ifp) { |
288 | if (ifp->if_flags & IFF_POINTOPOINT) { | |
289 | compare = &satons_addr(ia->ia_dstaddr); | |
290 | if (ns_hosteq(*dst, *compare)) | |
291 | return (ia); | |
f1e269d4 | 292 | if (ns_neteqnn(net, ia->ia_net)) |
8b659320 KS |
293 | ia_maybe = ia; |
294 | } else { | |
f1e269d4 | 295 | if (ns_neteqnn(net, ia->ia_net)) |
46aa06a9 KS |
296 | return (ia); |
297 | } | |
298 | } | |
299 | } | |
300 | return (ia_maybe); | |
de9bc7de KS |
301 | } |
302 | #endif |