changes for var. length sockaddrs, routing lookup changes,
[unix-history] / usr / src / sys / netns / ns.c
CommitLineData
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 *
4dcdd98e 17 * @(#)ns.c 7.4 (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
40struct ns_ifaddr *ns_ifaddr;
4dcdd98e
KS
41int ns_interfaces;
42extern struct sockaddr_ns ns_netmask, ns_hostmask;
de9bc7de
KS
43
44/*
45 * Generic internet control operations (ioctl's).
46 */
f97be0c9 47/* ARGSUSED */
de9bc7de
KS
48ns_control(so, cmd, data, ifp)
49 struct socket *so;
50 int cmd;
51 caddr_t data;
52 register struct ifnet *ifp;
53{
54 register struct ifreq *ifr = (struct ifreq *)data;
4dcdd98e 55 register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data;
de9bc7de
KS
56 register struct ns_ifaddr *ia;
57 struct ifaddr *ifa;
4dcdd98e 58 struct ns_ifaddr *oia;
de9bc7de 59 struct mbuf *m;
4dcdd98e 60 int dstIsNew, hostIsNew;
de9bc7de 61
de9bc7de
KS
62 /*
63 * Find address for this interface, if it exists.
64 */
8b659320 65 if (ifp == 0)
4353fa68 66 return (EADDRNOTAVAIL);
de9bc7de
KS
67 for (ia = ns_ifaddr; ia; ia = ia->ia_next)
68 if (ia->ia_ifp == ifp)
69 break;
70
71 switch (cmd) {
72
73 case SIOCGIFADDR:
4353fa68
KS
74 if (ia == (struct ns_ifaddr *)0)
75 return (EADDRNOTAVAIL);
4dcdd98e 76 *(struct sockaddr_ns *)&ifr->ifr_addr = ia->ia_addr;
4353fa68
KS
77 return (0);
78
79
de9bc7de 80 case SIOCGIFBRDADDR:
4353fa68
KS
81 if (ia == (struct ns_ifaddr *)0)
82 return (EADDRNOTAVAIL);
83 if ((ifp->if_flags & IFF_BROADCAST) == 0)
84 return (EINVAL);
4dcdd98e 85 *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_broadaddr;
4353fa68
KS
86 return (0);
87
de9bc7de
KS
88 case SIOCGIFDSTADDR:
89 if (ia == (struct ns_ifaddr *)0)
90 return (EADDRNOTAVAIL);
4353fa68
KS
91 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
92 return (EINVAL);
4dcdd98e 93 *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
4353fa68
KS
94 return (0);
95 }
96
97 if (!suser())
98 return (u.u_error);
99
100 switch (cmd) {
4dcdd98e
KS
101 case SIOCAIFADDR:
102 case SIOCDIFADDR:
103 if (ifra->ifra_addr.sns_family == AF_NS)
104 for (oia = ia; ia; ia = ia->ia_next) {
105 if (ia->ia_ifp == ifp &&
106 ns_neteq(ia->ia_addr.sns_addr,
107 ifra->ifra_addr.sns_addr))
108 break;
109 }
110 if (cmd == SIOCDIFADDR && ia == 0)
111 return (EADDRNOTAVAIL);
112 /* FALLTHROUGH */
de9bc7de 113
de9bc7de 114 case SIOCSIFADDR:
8b659320 115 case SIOCSIFDSTADDR:
de9bc7de
KS
116 if (ia == (struct ns_ifaddr *)0) {
117 m = m_getclr(M_WAIT, MT_IFADDR);
118 if (m == (struct mbuf *)NULL)
119 return (ENOBUFS);
120 if (ia = ns_ifaddr) {
121 for ( ; ia->ia_next; ia = ia->ia_next)
122 ;
123 ia->ia_next = mtod(m, struct ns_ifaddr *);
124 } else
125 ns_ifaddr = mtod(m, struct ns_ifaddr *);
126 ia = mtod(m, struct ns_ifaddr *);
127 if (ifa = ifp->if_addrlist) {
128 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
129 ;
130 ifa->ifa_next = (struct ifaddr *) ia;
131 } else
132 ifp->if_addrlist = (struct ifaddr *) ia;
133 ia->ia_ifp = ifp;
4dcdd98e
KS
134 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
135
136 ia->ia_ifa.ifa_netmask =
137 (struct sockaddr *)&ns_netmask;
138
139 ia->ia_ifa.ifa_dstaddr =
140 (struct sockaddr *)&ia->ia_dstaddr;
141 if (ifp->if_flags & IFF_BROADCAST) {
142 ia->ia_broadaddr.sns_family = AF_NS;
143 ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr);
144 ia->ia_broadaddr.sns_addr.x_host = ns_broadhost;
145 }
146 ns_interfaces++;
de9bc7de 147 }
8b659320
KS
148 }
149
150 switch (cmd) {
4dcdd98e 151 int error;
8b659320
KS
152
153 case SIOCSIFDSTADDR:
154 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
155 return (EINVAL);
156 if (ia->ia_flags & IFA_ROUTE) {
4dcdd98e 157 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
8b659320
KS
158 ia->ia_flags &= ~IFA_ROUTE;
159 }
160 if (ifp->if_ioctl) {
4dcdd98e 161 error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia);
8b659320
KS
162 if (error)
163 return (error);
164 }
4dcdd98e 165 *(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr;
8b659320
KS
166 return (0);
167
168 case SIOCSIFADDR:
4dcdd98e
KS
169 return (ns_ifinit(ifp, ia,
170 (struct sockaddr_ns *)&ifr->ifr_addr, 1));
171
172 case SIOCDIFADDR:
173 ns_ifscrub(ifp, ia);
174 if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
175 ifp->if_addrlist = ifa->ifa_next;
176 else {
177 while (ifa->ifa_next &&
178 (ifa->ifa_next != (struct ifaddr *)ia))
179 ifa = ifa->ifa_next;
180 if (ifa->ifa_next)
181 ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
182 else
183 printf("Couldn't unlink nsifaddr from ifp\n");
184 }
185 oia = ia;
186 if (oia == (ia = ns_ifaddr)) {
187 ns_ifaddr = ia->ia_next;
188 } else {
189 while (ia->ia_next && (ia->ia_next != oia)) {
190 ia = ia->ia_next;
191 }
192 if (ia->ia_next)
193 ia->ia_next = oia->ia_next;
194 else
195 printf("Didn't unlink nsifadr from list\n");
196 }
197 (void) m_free(dtom(oia));
198 if (0 == --ns_interfaces) {
199 /*
200 * We reset to virginity and start all over again
201 */
202 ns_thishost = ns_zerohost;
203 }
204 return (0);
205
206 case SIOCAIFADDR:
207 dstIsNew = 0; hostIsNew = 1;
208 if (ia->ia_addr.sns_family == AF_NS) {
209 if (ifra->ifra_addr.sns_len == 0) {
210 ifra->ifra_addr = ia->ia_addr;
211 hostIsNew = 0;
212 } else if (ns_neteq(ifra->ifra_addr.sns_addr,
213 ia->ia_addr.sns_addr))
214 hostIsNew = 0;
215 }
216 if ((ifp->if_flags & IFF_POINTOPOINT) &&
217 (ifra->ifra_dstaddr.sns_family == AF_NS)) {
218 if (hostIsNew == 0)
219 ns_ifscrub(ifp, ia);
220 ia->ia_dstaddr = ifra->ifra_dstaddr;
221 dstIsNew = 1;
222 }
223 if (ifra->ifra_addr.sns_family == AF_NS &&
224 (hostIsNew || dstIsNew))
225 error = ns_ifinit(ifp, ia, &ifra->ifra_addr, 0);
226 return (error);
de9bc7de
KS
227
228 default:
229 if (ifp->if_ioctl == 0)
230 return (EOPNOTSUPP);
231 return ((*ifp->if_ioctl)(ifp, cmd, data));
232 }
de9bc7de
KS
233}
234
4dcdd98e
KS
235/*
236* Delete any previous route for an old address.
237*/
238ns_ifscrub(ifp, ia)
239 register struct ifnet *ifp;
240 register struct ns_ifaddr *ia;
241{
242 if (ia->ia_flags & IFA_ROUTE) {
243 if (ifp->if_flags & IFF_POINTOPOINT) {
244 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
245 } else
246 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
247 ia->ia_flags &= ~IFA_ROUTE;
248 }
249}
de9bc7de
KS
250/*
251 * Initialize an interface's internet address
252 * and routing table entry.
253 */
4dcdd98e 254ns_ifinit(ifp, ia, sns, scrub)
de9bc7de
KS
255 register struct ifnet *ifp;
256 register struct ns_ifaddr *ia;
4dcdd98e 257 register struct sockaddr_ns *sns;
de9bc7de 258{
4dcdd98e
KS
259 struct sockaddr_ns oldaddr;
260 register union ns_host *h = &ia->ia_addr.sns_addr.x_host;
de9bc7de
KS
261 int s = splimp(), error;
262
4dcdd98e
KS
263 /*
264 * Set up new addresses.
265 */
266 oldaddr = ia->ia_addr;
267 ia->ia_addr = *sns;
de9bc7de
KS
268 /*
269 * The convention we shall adopt for naming is that
270 * a supplied address of zero means that "we don't care".
271 * if there is a single interface, use the address of that
272 * interface as our 6 byte host address.
273 * if there are multiple interfaces, use any address already
274 * used.
275 *
de9bc7de
KS
276 * Give the interface a chance to initialize
277 * if this is its first address,
278 * and to validate the address if necessary.
279 */
de9bc7de
KS
280 if (ns_hosteqnh(ns_thishost, ns_zerohost)) {
281 if (ifp->if_ioctl &&
282 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
4dcdd98e 283 ia->ia_addr = oldaddr;
de9bc7de
KS
284 splx(s);
285 return (error);
286 }
287 ns_thishost = *h;
288 } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost)
289 || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) {
290 *h = ns_thishost;
291 if (ifp->if_ioctl &&
292 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
4dcdd98e 293 ia->ia_addr = oldaddr;
de9bc7de
KS
294 splx(s);
295 return (error);
296 }
8b659320 297 if (!ns_hosteqnh(ns_thishost,*h)) {
4dcdd98e 298 ia->ia_addr = oldaddr;
de9bc7de
KS
299 splx(s);
300 return (EINVAL);
301 }
302 } else {
4dcdd98e 303 ia->ia_addr = oldaddr;
de9bc7de 304 splx(s);
8b659320 305 return (EINVAL);
de9bc7de
KS
306 }
307 /*
308 * Add route for the network.
309 */
4dcdd98e
KS
310 if (scrub) {
311 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
312 ns_ifscrub(ifp, ia);
313 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
314 }
8b659320 315 if (ifp->if_flags & IFF_POINTOPOINT)
4dcdd98e
KS
316 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
317 else {
318 ia->ia_broadaddr.sns_addr.x_net = ia->ia_net;
319 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
320 }
de9bc7de 321 ia->ia_flags |= IFA_ROUTE;
8b659320 322 return (0);
de9bc7de
KS
323}
324
325/*
326 * Return address info for specified internet network.
327 */
328struct ns_ifaddr *
46aa06a9
KS
329ns_iaonnetof(dst)
330 register struct ns_addr *dst;
de9bc7de
KS
331{
332 register struct ns_ifaddr *ia;
46aa06a9 333 register struct ns_addr *compare;
8b659320
KS
334 register struct ifnet *ifp;
335 struct ns_ifaddr *ia_maybe = 0;
f1e269d4 336 union ns_net net = dst->x_net;
de9bc7de 337
46aa06a9 338 for (ia = ns_ifaddr; ia; ia = ia->ia_next) {
8b659320
KS
339 if (ifp = ia->ia_ifp) {
340 if (ifp->if_flags & IFF_POINTOPOINT) {
341 compare = &satons_addr(ia->ia_dstaddr);
342 if (ns_hosteq(*dst, *compare))
343 return (ia);
f1e269d4 344 if (ns_neteqnn(net, ia->ia_net))
8b659320
KS
345 ia_maybe = ia;
346 } else {
f1e269d4 347 if (ns_neteqnn(net, ia->ia_net))
46aa06a9
KS
348 return (ia);
349 }
350 }
351 }
352 return (ia_maybe);
de9bc7de
KS
353}
354#endif