|
|
1.1 root 1: /*
2: * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)ns.c 7.8 (Berkeley) 6/27/91
34: */
35:
36: #include "param.h"
37: #include "mbuf.h"
38: #include "ioctl.h"
39: #include "protosw.h"
40: #include "errno.h"
41: #include "socket.h"
42: #include "socketvar.h"
43:
44:
45: #include "../net/if.h"
46: #include "../net/route.h"
47: #include "../net/af.h"
48:
49: #include "ns.h"
50: #include "ns_if.h"
51:
52: #ifdef NS
53:
54: struct ns_ifaddr *ns_ifaddr;
55: int ns_interfaces;
56: extern struct sockaddr_ns ns_netmask, ns_hostmask;
57:
58: /*
59: * Generic internet control operations (ioctl's).
60: */
61: /* ARGSUSED */
62: ns_control(so, cmd, data, ifp)
63: struct socket *so;
64: int cmd;
65: caddr_t data;
66: register struct ifnet *ifp;
67: {
68: register struct ifreq *ifr = (struct ifreq *)data;
69: register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data;
70: register struct ns_ifaddr *ia;
71: struct ifaddr *ifa;
72: struct ns_ifaddr *oia;
73: struct mbuf *m;
74: int error, dstIsNew, hostIsNew;
75:
76: /*
77: * Find address for this interface, if it exists.
78: */
79: if (ifp == 0)
80: return (EADDRNOTAVAIL);
81: for (ia = ns_ifaddr; ia; ia = ia->ia_next)
82: if (ia->ia_ifp == ifp)
83: break;
84:
85: switch (cmd) {
86:
87: case SIOCGIFADDR:
88: if (ia == (struct ns_ifaddr *)0)
89: return (EADDRNOTAVAIL);
90: *(struct sockaddr_ns *)&ifr->ifr_addr = ia->ia_addr;
91: return (0);
92:
93:
94: case SIOCGIFBRDADDR:
95: if (ia == (struct ns_ifaddr *)0)
96: return (EADDRNOTAVAIL);
97: if ((ifp->if_flags & IFF_BROADCAST) == 0)
98: return (EINVAL);
99: *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_broadaddr;
100: return (0);
101:
102: case SIOCGIFDSTADDR:
103: if (ia == (struct ns_ifaddr *)0)
104: return (EADDRNOTAVAIL);
105: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
106: return (EINVAL);
107: *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
108: return (0);
109: }
110:
111: if ((so->so_state & SS_PRIV) == 0)
112: return (EPERM);
113:
114: switch (cmd) {
115: case SIOCAIFADDR:
116: case SIOCDIFADDR:
117: if (ifra->ifra_addr.sns_family == AF_NS)
118: for (oia = ia; ia; ia = ia->ia_next) {
119: if (ia->ia_ifp == ifp &&
120: ns_neteq(ia->ia_addr.sns_addr,
121: ifra->ifra_addr.sns_addr))
122: break;
123: }
124: if (cmd == SIOCDIFADDR && ia == 0)
125: return (EADDRNOTAVAIL);
126: /* FALLTHROUGH */
127:
128: case SIOCSIFADDR:
129: case SIOCSIFDSTADDR:
130: if (ia == (struct ns_ifaddr *)0) {
131: m = m_getclr(M_WAIT, MT_IFADDR);
132: if (m == (struct mbuf *)NULL)
133: return (ENOBUFS);
134: if (ia = ns_ifaddr) {
135: for ( ; ia->ia_next; ia = ia->ia_next)
136: ;
137: ia->ia_next = mtod(m, struct ns_ifaddr *);
138: } else
139: ns_ifaddr = mtod(m, struct ns_ifaddr *);
140: ia = mtod(m, struct ns_ifaddr *);
141: if (ifa = ifp->if_addrlist) {
142: for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
143: ;
144: ifa->ifa_next = (struct ifaddr *) ia;
145: } else
146: ifp->if_addrlist = (struct ifaddr *) ia;
147: ia->ia_ifp = ifp;
148: ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
149:
150: ia->ia_ifa.ifa_netmask =
151: (struct sockaddr *)&ns_netmask;
152:
153: ia->ia_ifa.ifa_dstaddr =
154: (struct sockaddr *)&ia->ia_dstaddr;
155: if (ifp->if_flags & IFF_BROADCAST) {
156: ia->ia_broadaddr.sns_family = AF_NS;
157: ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr);
158: ia->ia_broadaddr.sns_addr.x_host = ns_broadhost;
159: }
160: ns_interfaces++;
161: }
162: }
163:
164: switch (cmd) {
165: int error;
166:
167: case SIOCSIFDSTADDR:
168: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
169: return (EINVAL);
170: if (ia->ia_flags & IFA_ROUTE) {
171: rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
172: ia->ia_flags &= ~IFA_ROUTE;
173: }
174: if (ifp->if_ioctl) {
175: error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia);
176: if (error)
177: return (error);
178: }
179: *(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr;
180: return (0);
181:
182: case SIOCSIFADDR:
183: return (ns_ifinit(ifp, ia,
184: (struct sockaddr_ns *)&ifr->ifr_addr, 1));
185:
186: case SIOCDIFADDR:
187: ns_ifscrub(ifp, ia);
188: if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
189: ifp->if_addrlist = ifa->ifa_next;
190: else {
191: while (ifa->ifa_next &&
192: (ifa->ifa_next != (struct ifaddr *)ia))
193: ifa = ifa->ifa_next;
194: if (ifa->ifa_next)
195: ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
196: else
197: printf("Couldn't unlink nsifaddr from ifp\n");
198: }
199: oia = ia;
200: if (oia == (ia = ns_ifaddr)) {
201: ns_ifaddr = ia->ia_next;
202: } else {
203: while (ia->ia_next && (ia->ia_next != oia)) {
204: ia = ia->ia_next;
205: }
206: if (ia->ia_next)
207: ia->ia_next = oia->ia_next;
208: else
209: printf("Didn't unlink nsifadr from list\n");
210: }
211: (void) m_free(dtom(oia));
212: if (0 == --ns_interfaces) {
213: /*
214: * We reset to virginity and start all over again
215: */
216: ns_thishost = ns_zerohost;
217: }
218: return (0);
219:
220: case SIOCAIFADDR:
221: dstIsNew = 0; hostIsNew = 1;
222: if (ia->ia_addr.sns_family == AF_NS) {
223: if (ifra->ifra_addr.sns_len == 0) {
224: ifra->ifra_addr = ia->ia_addr;
225: hostIsNew = 0;
226: } else if (ns_neteq(ifra->ifra_addr.sns_addr,
227: ia->ia_addr.sns_addr))
228: hostIsNew = 0;
229: }
230: if ((ifp->if_flags & IFF_POINTOPOINT) &&
231: (ifra->ifra_dstaddr.sns_family == AF_NS)) {
232: if (hostIsNew == 0)
233: ns_ifscrub(ifp, ia);
234: ia->ia_dstaddr = ifra->ifra_dstaddr;
235: dstIsNew = 1;
236: }
237: if (ifra->ifra_addr.sns_family == AF_NS &&
238: (hostIsNew || dstIsNew))
239: error = ns_ifinit(ifp, ia, &ifra->ifra_addr, 0);
240: return (error);
241:
242: default:
243: if (ifp->if_ioctl == 0)
244: return (EOPNOTSUPP);
245: return ((*ifp->if_ioctl)(ifp, cmd, data));
246: }
247: }
248:
249: /*
250: * Delete any previous route for an old address.
251: */
252: ns_ifscrub(ifp, ia)
253: register struct ifnet *ifp;
254: register struct ns_ifaddr *ia;
255: {
256: if (ia->ia_flags & IFA_ROUTE) {
257: if (ifp->if_flags & IFF_POINTOPOINT) {
258: rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
259: } else
260: rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
261: ia->ia_flags &= ~IFA_ROUTE;
262: }
263: }
264: /*
265: * Initialize an interface's internet address
266: * and routing table entry.
267: */
268: ns_ifinit(ifp, ia, sns, scrub)
269: register struct ifnet *ifp;
270: register struct ns_ifaddr *ia;
271: register struct sockaddr_ns *sns;
272: {
273: struct sockaddr_ns oldaddr;
274: register union ns_host *h = &ia->ia_addr.sns_addr.x_host;
275: int s = splimp(), error;
276:
277: /*
278: * Set up new addresses.
279: */
280: oldaddr = ia->ia_addr;
281: ia->ia_addr = *sns;
282: /*
283: * The convention we shall adopt for naming is that
284: * a supplied address of zero means that "we don't care".
285: * if there is a single interface, use the address of that
286: * interface as our 6 byte host address.
287: * if there are multiple interfaces, use any address already
288: * used.
289: *
290: * Give the interface a chance to initialize
291: * if this is its first address,
292: * and to validate the address if necessary.
293: */
294: if (ns_hosteqnh(ns_thishost, ns_zerohost)) {
295: if (ifp->if_ioctl &&
296: (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
297: ia->ia_addr = oldaddr;
298: splx(s);
299: return (error);
300: }
301: ns_thishost = *h;
302: } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost)
303: || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) {
304: *h = ns_thishost;
305: if (ifp->if_ioctl &&
306: (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
307: ia->ia_addr = oldaddr;
308: splx(s);
309: return (error);
310: }
311: if (!ns_hosteqnh(ns_thishost,*h)) {
312: ia->ia_addr = oldaddr;
313: splx(s);
314: return (EINVAL);
315: }
316: } else {
317: ia->ia_addr = oldaddr;
318: splx(s);
319: return (EINVAL);
320: }
321: /*
322: * Add route for the network.
323: */
324: if (scrub) {
325: ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
326: ns_ifscrub(ifp, ia);
327: ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
328: }
329: if (ifp->if_flags & IFF_POINTOPOINT)
330: rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
331: else {
332: ia->ia_broadaddr.sns_addr.x_net = ia->ia_net;
333: rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
334: }
335: ia->ia_flags |= IFA_ROUTE;
336: return (0);
337: }
338:
339: /*
340: * Return address info for specified internet network.
341: */
342: struct ns_ifaddr *
343: ns_iaonnetof(dst)
344: register struct ns_addr *dst;
345: {
346: register struct ns_ifaddr *ia;
347: register struct ns_addr *compare;
348: register struct ifnet *ifp;
349: struct ns_ifaddr *ia_maybe = 0;
350: union ns_net net = dst->x_net;
351:
352: for (ia = ns_ifaddr; ia; ia = ia->ia_next) {
353: if (ifp = ia->ia_ifp) {
354: if (ifp->if_flags & IFF_POINTOPOINT) {
355: compare = &satons_addr(ia->ia_dstaddr);
356: if (ns_hosteq(*dst, *compare))
357: return (ia);
358: if (ns_neteqnn(net, ia->ia_net))
359: ia_maybe = ia;
360: } else {
361: if (ns_neteqnn(net, ia->ia_net))
362: return (ia);
363: }
364: }
365: }
366: return (ia_maybe);
367: }
368: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.