1 /*
2 * Copyright (c) 1984, 1985, 1986, 1987, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)ns.c 8.5 (Berkeley) 02/09/95
8 */
9
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>
17
18 #include <net/if.h>
19 #include <net/route.h>
20
21 #include <netns/ns.h>
22 #include <netns/ns_if.h>
23
24 #ifdef NS
25
26 struct ns_ifaddr *ns_ifaddr;
27 int ns_interfaces;
28 extern struct sockaddr_ns ns_netmask, ns_hostmask;
29
30 /*
31 * Generic internet control operations (ioctl's).
32 */
33 /* ARGSUSED */
34 ns_control(so, cmd, data, ifp)
35 struct socket *so;
36 u_long cmd;
37 caddr_t data;
38 register struct ifnet *ifp;
39 {
40 register struct ifreq *ifr = (struct ifreq *)data;
41 register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data;
42 register struct ns_ifaddr *ia;
43 struct ifaddr *ifa;
44 struct ns_ifaddr *oia;
45 int error, dstIsNew, hostIsNew;
46
47 /*
48 * Find address for this interface, if it exists.
49 */
50 if (ifp == 0)
51 return (EADDRNOTAVAIL);
52 for (ia = ns_ifaddr; ia; ia = ia->ia_next)
53 if (ia->ia_ifp == ifp)
54 break;
55
56 switch (cmd) {
57
58 case SIOCGIFADDR:
59 if (ia == (struct ns_ifaddr *)0)
60 return (EADDRNOTAVAIL);
61 *(struct sockaddr_ns *)&ifr->ifr_addr = ia->ia_addr;
62 return (0);
63
64
65 case SIOCGIFBRDADDR:
66 if (ia == (struct ns_ifaddr *)0)
67 return (EADDRNOTAVAIL);
68 if ((ifp->if_flags & IFF_BROADCAST) == 0)
69 return (EINVAL);
70 *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_broadaddr;
71 return (0);
72
73 case SIOCGIFDSTADDR:
74 if (ia == (struct ns_ifaddr *)0)
75 return (EADDRNOTAVAIL);
76 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
77 return (EINVAL);
78 *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
79 return (0);
80 }
81
82 if ((so->so_state & SS_PRIV) == 0)
83 return (EPERM);
84
85 switch (cmd) {
86 case SIOCAIFADDR:
87 case SIOCDIFADDR:
88 if (ifra->ifra_addr.sns_family == AF_NS)
89 for (oia = ia; ia; ia = ia->ia_next) {
90 if (ia->ia_ifp == ifp &&
91 ns_neteq(ia->ia_addr.sns_addr,
92 ifra->ifra_addr.sns_addr))
93 break;
94 }
95 if (cmd == SIOCDIFADDR && ia == 0)
96 return (EADDRNOTAVAIL);
97 /* FALLTHROUGH */
98
99 case SIOCSIFADDR:
100 case SIOCSIFDSTADDR:
101 if (ia == (struct ns_ifaddr *)0) {
102 oia = (struct ns_ifaddr *)
103 malloc(sizeof *ia, M_IFADDR, M_WAITOK);
104 if (oia == (struct ns_ifaddr *)NULL)
105 return (ENOBUFS);
106 bzero((caddr_t)oia, sizeof(*oia));
107 if (ia = ns_ifaddr) {
108 for ( ; ia->ia_next; ia = ia->ia_next)
109 ;
110 ia->ia_next = oia;
111 } else
112 ns_ifaddr = oia;
113 ia = oia;
114 if (ifa = ifp->if_addrlist) {
115 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
116 ;
117 ifa->ifa_next = (struct ifaddr *) ia;
118 } else
119 ifp->if_addrlist = (struct ifaddr *) ia;
120 ia->ia_ifp = ifp;
121 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
122
123 ia->ia_ifa.ifa_netmask =
124 (struct sockaddr *)&ns_netmask;
125
126 ia->ia_ifa.ifa_dstaddr =
127 (struct sockaddr *)&ia->ia_dstaddr;
128 if (ifp->if_flags & IFF_BROADCAST) {
129 ia->ia_broadaddr.sns_family = AF_NS;
130 ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr);
131 ia->ia_broadaddr.sns_addr.x_host = ns_broadhost;
132 }
133 ns_interfaces++;
134 }
135 }
136
137 switch (cmd) {
138 int error;
139
140 case SIOCSIFDSTADDR:
141 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
142 return (EINVAL);
143 if (ia->ia_flags & IFA_ROUTE) {
144 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
145 ia->ia_flags &= ~IFA_ROUTE;
146 }
147 if (ifp->if_ioctl) {
148 error = (*ifp->if_ioctl)
149 (ifp, SIOCSIFDSTADDR, (caddr_t)ia);
150 if (error)
151 return (error);
152 }
153 *(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr;
154 return (0);
155
156 case SIOCSIFADDR:
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 IFAFREE((&oia->ia_ifa));
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);
215
216 default:
217 if (ifp->if_ioctl == 0)
218 return (EOPNOTSUPP);
219 return ((*ifp->if_ioctl)(ifp, cmd, data));
220 }
221 }
222
223 /*
224 * Delete any previous route for an old address.
225 */
ns_ifscrub(ifp,ia)226 ns_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 }
238 /*
239 * Initialize an interface's internet address
240 * and routing table entry.
241 */
ns_ifinit(ifp,ia,sns,scrub)242 ns_ifinit(ifp, ia, sns, scrub)
243 register struct ifnet *ifp;
244 register struct ns_ifaddr *ia;
245 register struct sockaddr_ns *sns;
246 {
247 struct sockaddr_ns oldaddr;
248 register union ns_host *h = &ia->ia_addr.sns_addr.x_host;
249 int s = splimp(), error;
250
251 /*
252 * Set up new addresses.
253 */
254 oldaddr = ia->ia_addr;
255 ia->ia_addr = *sns;
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 *
264 * Give the interface a chance to initialize
265 * if this is its first address,
266 * and to validate the address if necessary.
267 */
268 if (ns_hosteqnh(ns_thishost, ns_zerohost)) {
269 if (ifp->if_ioctl &&
270 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)))
271 goto bad;
272 ns_thishost = *h;
273 } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost)
274 || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) {
275 *h = ns_thishost;
276 if (ifp->if_ioctl &&
277 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)))
278 goto bad;
279 if (!ns_hosteqnh(ns_thishost,*h)) {
280 error = EINVAL;
281 goto bad;
282 }
283 } else {
284 error = EINVAL;
285 goto bad;
286 }
287 ia->ia_ifa.ifa_metric = ifp->if_metric;
288 /*
289 * Add route for the network.
290 */
291 if (scrub) {
292 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
293 ns_ifscrub(ifp, ia);
294 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
295 }
296 if (ifp->if_flags & IFF_POINTOPOINT)
297 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
298 else {
299 ia->ia_broadaddr.sns_addr.x_net = ia->ia_addr.sns_addr.x_net;
300 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
301 }
302 ia->ia_flags |= IFA_ROUTE;
303 splx(s);
304 return (0);
305 bad:
306 ia->ia_addr = oldaddr;
307 splx(s);
308 return (error);
309 }
310
311 /*
312 * Return address info for specified internet network.
313 */
314 struct ns_ifaddr *
ns_iaonnetof(dst)315 ns_iaonnetof(dst)
316 register struct ns_addr *dst;
317 {
318 register struct ns_ifaddr *ia;
319 register struct ns_addr *compare;
320 register struct ifnet *ifp;
321 struct ns_ifaddr *ia_maybe = 0;
322 union ns_net net = dst->x_net;
323
324 for (ia = ns_ifaddr; ia; ia = ia->ia_next) {
325 if (ifp = ia->ia_ifp) {
326 if (ifp->if_flags & IFF_POINTOPOINT) {
327 compare = &satons_addr(ia->ia_dstaddr);
328 if (ns_hosteq(*dst, *compare))
329 return (ia);
330 if (ns_neteqnn(net, ia->ia_addr.sns_addr.x_net))
331 ia_maybe = ia;
332 } else {
333 if (ns_neteqnn(net, ia->ia_addr.sns_addr.x_net))
334 return (ia);
335 }
336 }
337 }
338 return (ia_maybe);
339 }
340 #endif
341