reset directory link counts on I/O failure
[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 *
dbf0c423 5 * %sccs.include.redist.c%
240edf1f 6 *
dbf0c423 7 * @(#)ns.c 7.7 (Berkeley) %G%
8ae0e4b4 8 */
de9bc7de
KS
9
10#include "param.h"
11#include "mbuf.h"
12#include "ioctl.h"
13#include "protosw.h"
14#include "socket.h"
15#include "socketvar.h"
de9bc7de
KS
16#include "user.h"
17
18
19#include "../net/if.h"
20#include "../net/route.h"
21#include "../net/af.h"
22
23#include "ns.h"
24#include "ns_if.h"
25
26#ifdef NS
27
28struct ns_ifaddr *ns_ifaddr;
4dcdd98e
KS
29int ns_interfaces;
30extern struct sockaddr_ns ns_netmask, ns_hostmask;
de9bc7de
KS
31
32/*
33 * Generic internet control operations (ioctl's).
34 */
f97be0c9 35/* ARGSUSED */
de9bc7de
KS
36ns_control(so, cmd, data, ifp)
37 struct socket *so;
38 int cmd;
39 caddr_t data;
40 register struct ifnet *ifp;
41{
42 register struct ifreq *ifr = (struct ifreq *)data;
4dcdd98e 43 register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data;
de9bc7de
KS
44 register struct ns_ifaddr *ia;
45 struct ifaddr *ifa;
4dcdd98e 46 struct ns_ifaddr *oia;
de9bc7de 47 struct mbuf *m;
dfe62cc7 48 int error, dstIsNew, hostIsNew;
de9bc7de 49
de9bc7de
KS
50 /*
51 * Find address for this interface, if it exists.
52 */
8b659320 53 if (ifp == 0)
4353fa68 54 return (EADDRNOTAVAIL);
de9bc7de
KS
55 for (ia = ns_ifaddr; ia; ia = ia->ia_next)
56 if (ia->ia_ifp == ifp)
57 break;
58
59 switch (cmd) {
60
61 case SIOCGIFADDR:
4353fa68
KS
62 if (ia == (struct ns_ifaddr *)0)
63 return (EADDRNOTAVAIL);
4dcdd98e 64 *(struct sockaddr_ns *)&ifr->ifr_addr = ia->ia_addr;
4353fa68
KS
65 return (0);
66
67
de9bc7de 68 case SIOCGIFBRDADDR:
4353fa68
KS
69 if (ia == (struct ns_ifaddr *)0)
70 return (EADDRNOTAVAIL);
71 if ((ifp->if_flags & IFF_BROADCAST) == 0)
72 return (EINVAL);
4dcdd98e 73 *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_broadaddr;
4353fa68
KS
74 return (0);
75
de9bc7de
KS
76 case SIOCGIFDSTADDR:
77 if (ia == (struct ns_ifaddr *)0)
78 return (EADDRNOTAVAIL);
4353fa68
KS
79 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
80 return (EINVAL);
4dcdd98e 81 *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
4353fa68
KS
82 return (0);
83 }
84
dfe62cc7
KM
85 if (error = suser(u.u_cred, &u.u_acflag))
86 return (error);
4353fa68
KS
87
88 switch (cmd) {
4dcdd98e
KS
89 case SIOCAIFADDR:
90 case SIOCDIFADDR:
91 if (ifra->ifra_addr.sns_family == AF_NS)
92 for (oia = ia; ia; ia = ia->ia_next) {
93 if (ia->ia_ifp == ifp &&
94 ns_neteq(ia->ia_addr.sns_addr,
95 ifra->ifra_addr.sns_addr))
96 break;
97 }
98 if (cmd == SIOCDIFADDR && ia == 0)
99 return (EADDRNOTAVAIL);
100 /* FALLTHROUGH */
de9bc7de 101
de9bc7de 102 case SIOCSIFADDR:
8b659320 103 case SIOCSIFDSTADDR:
de9bc7de
KS
104 if (ia == (struct ns_ifaddr *)0) {
105 m = m_getclr(M_WAIT, MT_IFADDR);
106 if (m == (struct mbuf *)NULL)
107 return (ENOBUFS);
108 if (ia = ns_ifaddr) {
109 for ( ; ia->ia_next; ia = ia->ia_next)
110 ;
111 ia->ia_next = mtod(m, struct ns_ifaddr *);
112 } else
113 ns_ifaddr = mtod(m, struct ns_ifaddr *);
114 ia = mtod(m, struct ns_ifaddr *);
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 }
185 (void) m_free(dtom(oia));
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
KS
294 }
295 /*
296 * Add route for the network.
297 */
4dcdd98e
KS
298 if (scrub) {
299 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
300 ns_ifscrub(ifp, ia);
301 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
302 }
8b659320 303 if (ifp->if_flags & IFF_POINTOPOINT)
4dcdd98e
KS
304 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
305 else {
306 ia->ia_broadaddr.sns_addr.x_net = ia->ia_net;
307 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
308 }
de9bc7de 309 ia->ia_flags |= IFA_ROUTE;
8b659320 310 return (0);
de9bc7de
KS
311}
312
313/*
314 * Return address info for specified internet network.
315 */
316struct ns_ifaddr *
46aa06a9
KS
317ns_iaonnetof(dst)
318 register struct ns_addr *dst;
de9bc7de
KS
319{
320 register struct ns_ifaddr *ia;
46aa06a9 321 register struct ns_addr *compare;
8b659320
KS
322 register struct ifnet *ifp;
323 struct ns_ifaddr *ia_maybe = 0;
f1e269d4 324 union ns_net net = dst->x_net;
de9bc7de 325
46aa06a9 326 for (ia = ns_ifaddr; ia; ia = ia->ia_next) {
8b659320
KS
327 if (ifp = ia->ia_ifp) {
328 if (ifp->if_flags & IFF_POINTOPOINT) {
329 compare = &satons_addr(ia->ia_dstaddr);
330 if (ns_hosteq(*dst, *compare))
331 return (ia);
f1e269d4 332 if (ns_neteqnn(net, ia->ia_net))
8b659320
KS
333 ia_maybe = ia;
334 } else {
f1e269d4 335 if (ns_neteqnn(net, ia->ia_net))
46aa06a9
KS
336 return (ia);
337 }
338 }
339 }
340 return (ia_maybe);
de9bc7de
KS
341}
342#endif