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