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