2 * Copyright (c) 1984, 1985, 1986, 1987, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
33 * @(#)ns.c 8.2 (Berkeley) 11/15/93
34 * $FreeBSD: src/sys/netns/ns.c,v 1.9 1999/08/28 00:49:47 peter Exp $
35 * $DragonFly: src/sys/netproto/ns/ns.c,v 1.16 2008/01/06 16:55:52 swildner Exp $
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
42 #include <sys/sockio.h>
43 #include <sys/protosw.h>
44 #include <sys/errno.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/thread2.h>
50 #include <net/route.h>
59 struct ns_ifaddr
*ns_ifaddr
;
62 extern struct sockaddr_ns ns_netmask
, ns_hostmask
;
65 * Generic internet control operations (ioctl's).
69 ns_control(struct socket
*so
, u_long cmd
, caddr_t data
, struct ifnet
*ifp
,
72 struct ifreq
*ifr
= (struct ifreq
*)data
;
73 struct ns_aliasreq
*ifra
= (struct ns_aliasreq
*)data
;
75 struct ifaddr
*ifa
= NULL
; /* XXX used ininitialized ?*/
76 struct ns_ifaddr
*oia
;
77 int dstIsNew
, hostIsNew
;
78 int error
= 0; /* initalize because of scoping */
81 * Find address for this interface, if it exists.
84 return (EADDRNOTAVAIL
);
85 for (ia
= ns_ifaddr
; ia
; ia
= ia
->ia_next
)
86 if (ia
->ia_ifp
== ifp
)
92 if (ia
== (struct ns_ifaddr
*)0)
93 return (EADDRNOTAVAIL
);
94 *(struct sockaddr_ns
*)&ifr
->ifr_addr
= ia
->ia_addr
;
99 if (ia
== (struct ns_ifaddr
*)0)
100 return (EADDRNOTAVAIL
);
101 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
103 *(struct sockaddr_ns
*)&ifr
->ifr_dstaddr
= ia
->ia_broadaddr
;
107 if (ia
== (struct ns_ifaddr
*)0)
108 return (EADDRNOTAVAIL
);
109 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
111 *(struct sockaddr_ns
*)&ifr
->ifr_dstaddr
= ia
->ia_dstaddr
;
115 #ifdef NS_PRIV_SOCKETS
116 if ((so
->so_state
& SS_PRIV
) == 0)
123 if (ifra
->ifra_addr
.sns_family
== AF_NS
)
124 for (oia
= ia
; ia
; ia
= ia
->ia_next
) {
125 if (ia
->ia_ifp
== ifp
&&
126 ns_neteq(ia
->ia_addr
.sns_addr
,
127 ifra
->ifra_addr
.sns_addr
))
130 if (cmd
== SIOCDIFADDR
&& ia
== 0)
131 return (EADDRNOTAVAIL
);
136 if (ia
== (struct ns_ifaddr
*)0) {
137 oia
= (struct ns_ifaddr
*)
138 kmalloc(sizeof *ia
, M_IFADDR
, M_WAITOK
| M_ZERO
);
139 if ((ia
= ns_ifaddr
) != NULL
) {
140 for ( ; ia
->ia_next
; ia
= ia
->ia_next
)
147 TAILQ_INSERT_TAIL(&ifp
->if_addrhead
, ifa
, ifa_link
);
149 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
151 ia
->ia_ifa
.ifa_netmask
=
152 (struct sockaddr
*)&ns_netmask
;
154 ia
->ia_ifa
.ifa_dstaddr
=
155 (struct sockaddr
*)&ia
->ia_dstaddr
;
156 if (ifp
->if_flags
& IFF_BROADCAST
) {
157 ia
->ia_broadaddr
.sns_family
= AF_NS
;
158 ia
->ia_broadaddr
.sns_len
= sizeof(ia
->ia_addr
);
159 ia
->ia_broadaddr
.sns_addr
.x_host
= ns_broadhost
;
167 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
169 if (ia
->ia_flags
& IFA_ROUTE
) {
170 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
171 ia
->ia_flags
&= ~IFA_ROUTE
;
174 lwkt_serialize_enter(ifp
->if_serializer
);
175 error
= ifp
->if_ioctl(ifp
, SIOCSIFDSTADDR
,
177 (struct ucred
*)NULL
);
178 lwkt_serialize_exit(ifp
->if_serializer
);
182 *(struct sockaddr
*)&ia
->ia_dstaddr
= ifr
->ifr_dstaddr
;
186 return (ns_ifinit(ifp
, (struct ns_ifaddr
*)ia
,
187 (struct sockaddr_ns
*)&ifr
->ifr_addr
, 1));
190 ns_ifscrub(ifp
, (struct ns_ifaddr
*)ia
);
191 /* XXX not on list */
193 TAILQ_REMOVE(&ifp
->if_addrhead
, (struct ifaddr
*)ia
, ifa_link
);
194 if (oia
== (ia
= ns_ifaddr
)) {
195 ns_ifaddr
= ia
->ia_next
;
197 while (ia
->ia_next
&& (ia
->ia_next
!= oia
)) {
201 ia
->ia_next
= oia
->ia_next
;
203 kprintf("Didn't unlink nsifadr from list\n");
205 IFAFREE((&oia
->ia_ifa
));
206 if (0 == --ns_interfaces
) {
208 * We reset to virginity and start all over again
210 ns_thishost
= ns_zerohost
;
215 dstIsNew
= 0; hostIsNew
= 1;
216 if (ia
->ia_addr
.sns_family
== AF_NS
) {
217 if (ifra
->ifra_addr
.sns_len
== 0) {
218 ifra
->ifra_addr
= ia
->ia_addr
;
220 } else if (ns_neteq(ifra
->ifra_addr
.sns_addr
,
221 ia
->ia_addr
.sns_addr
))
224 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
225 (ifra
->ifra_dstaddr
.sns_family
== AF_NS
)) {
227 ns_ifscrub(ifp
, (struct ns_ifaddr
*)ia
);
228 ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
231 if (ifra
->ifra_addr
.sns_family
== AF_NS
&&
232 (hostIsNew
|| dstIsNew
))
233 error
= ns_ifinit(ifp
, (struct ns_ifaddr
*)ia
,
234 &ifra
->ifra_addr
, 0);
238 if (ifp
->if_ioctl
== 0)
240 lwkt_serialize_enter(ifp
->if_serializer
);
241 error
= ifp
->if_ioctl(ifp
, cmd
, data
, (struct ucred
*)NULL
);
242 lwkt_serialize_exit(ifp
->if_serializer
);
248 * Delete any previous route for an old address.
251 ns_ifscrub(struct ifnet
*ifp
, struct ns_ifaddr
*ia
)
253 if (ia
->ia_flags
& IFA_ROUTE
) {
254 if (ifp
->if_flags
& IFF_POINTOPOINT
) {
255 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
257 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, 0);
258 ia
->ia_flags
&= ~IFA_ROUTE
;
262 * Initialize an interface's internet address
263 * and routing table entry.
266 ns_ifinit(struct ifnet
*ifp
, struct ns_ifaddr
*ia
, struct sockaddr_ns
*sns
, int scrub
)
268 struct sockaddr_ns oldaddr
;
269 union ns_host
*h
= &ia
->ia_addr
.sns_addr
.x_host
;
275 * Set up new addresses.
277 oldaddr
= ia
->ia_addr
;
280 * The convention we shall adopt for naming is that
281 * a supplied address of zero means that "we don't care".
282 * if there is a single interface, use the address of that
283 * interface as our 6 byte host address.
284 * if there are multiple interfaces, use any address already
287 * Give the interface a chance to initialize
288 * if this is its first address,
289 * and to validate the address if necessary.
291 if (ns_hosteqnh(ns_thishost
, ns_zerohost
)) {
292 lwkt_serialize_enter(ifp
->if_serializer
);
294 (error
= ifp
->if_ioctl(ifp
, SIOCSIFADDR
,
296 (struct ucred
*)NULL
))) {
297 ia
->ia_addr
= oldaddr
;
298 lwkt_serialize_exit(ifp
->if_serializer
);
302 lwkt_serialize_exit(ifp
->if_serializer
);
304 } else if (ns_hosteqnh(sns
->sns_addr
.x_host
, ns_zerohost
)
305 || ns_hosteqnh(sns
->sns_addr
.x_host
, ns_thishost
)) {
307 lwkt_serialize_enter(ifp
->if_serializer
);
309 (error
= ifp
->if_ioctl(ifp
, SIOCSIFADDR
,
311 (struct ucred
*)NULL
))) {
312 ia
->ia_addr
= oldaddr
;
313 lwkt_serialize_exit(ifp
->if_serializer
);
317 lwkt_serialize_exit(ifp
->if_serializer
);
318 if (!ns_hosteqnh(ns_thishost
,*h
)) {
319 ia
->ia_addr
= oldaddr
;
324 ia
->ia_addr
= oldaddr
;
328 ia
->ia_ifa
.ifa_metric
= ifp
->if_metric
;
330 * Add route for the network.
333 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&oldaddr
;
335 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
337 if (ifp
->if_flags
& IFF_POINTOPOINT
)
338 rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_HOST
|RTF_UP
);
340 ia
->ia_broadaddr
.sns_addr
.x_net
= ia
->ia_addr
.sns_addr
.x_net
;
341 rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_UP
);
343 ia
->ia_flags
|= IFA_ROUTE
;
348 * Return address info for specified internet network.
351 ns_iaonnetof(struct ns_addr
*dst
)
353 struct ns_ifaddr
*ia
;
354 struct ns_addr
*compare
;
356 struct ns_ifaddr
*ia_maybe
= 0;
357 union ns_net net
= dst
->x_net
;
359 for (ia
= ns_ifaddr
; ia
; ia
= ia
->ia_next
) {
360 if ((ifp
= ia
->ia_ifp
) != NULL
) {
361 if (ifp
->if_flags
& IFF_POINTOPOINT
) {
362 compare
= &satons_addr(ia
->ia_dstaddr
);
363 if (ns_hosteq(*dst
, *compare
))
365 if (ns_neteqnn(net
, ia
->ia_addr
.sns_addr
.x_net
))
368 if (ns_neteqnn(net
, ia
->ia_addr
.sns_addr
.x_net
))