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.17 2008/03/07 11:34:21 sephe 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 ns_ifaddr
*oia
;
76 int dstIsNew
, hostIsNew
;
77 int error
= 0; /* initalize because of scoping */
80 * Find address for this interface, if it exists.
83 return (EADDRNOTAVAIL
);
84 for (ia
= ns_ifaddr
; ia
; ia
= ia
->ia_next
)
85 if (ia
->ia_ifp
== ifp
)
91 if (ia
== (struct ns_ifaddr
*)0)
92 return (EADDRNOTAVAIL
);
93 *(struct sockaddr_ns
*)&ifr
->ifr_addr
= ia
->ia_addr
;
98 if (ia
== (struct ns_ifaddr
*)0)
99 return (EADDRNOTAVAIL
);
100 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
102 *(struct sockaddr_ns
*)&ifr
->ifr_dstaddr
= ia
->ia_broadaddr
;
106 if (ia
== (struct ns_ifaddr
*)0)
107 return (EADDRNOTAVAIL
);
108 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
110 *(struct sockaddr_ns
*)&ifr
->ifr_dstaddr
= ia
->ia_dstaddr
;
114 #ifdef NS_PRIV_SOCKETS
115 if ((so
->so_state
& SS_PRIV
) == 0)
122 if (ifra
->ifra_addr
.sns_family
== AF_NS
)
123 for (oia
= ia
; ia
; ia
= ia
->ia_next
) {
124 if (ia
->ia_ifp
== ifp
&&
125 ns_neteq(ia
->ia_addr
.sns_addr
,
126 ifra
->ifra_addr
.sns_addr
))
129 if (cmd
== SIOCDIFADDR
&& ia
== 0)
130 return (EADDRNOTAVAIL
);
135 if (ia
== (struct ns_ifaddr
*)0) {
136 oia
= ifa_create(sizeof(*ia
), M_WAITOK
);
137 if ((ia
= ns_ifaddr
) != NULL
) {
138 for ( ; ia
->ia_next
; ia
= ia
->ia_next
)
145 ifa_iflink(&ia
->ia_ifa
, ifp
, 1);
147 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
149 ia
->ia_ifa
.ifa_netmask
=
150 (struct sockaddr
*)&ns_netmask
;
152 ia
->ia_ifa
.ifa_dstaddr
=
153 (struct sockaddr
*)&ia
->ia_dstaddr
;
154 if (ifp
->if_flags
& IFF_BROADCAST
) {
155 ia
->ia_broadaddr
.sns_family
= AF_NS
;
156 ia
->ia_broadaddr
.sns_len
= sizeof(ia
->ia_addr
);
157 ia
->ia_broadaddr
.sns_addr
.x_host
= ns_broadhost
;
165 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
167 if (ia
->ia_flags
& IFA_ROUTE
) {
168 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
169 ia
->ia_flags
&= ~IFA_ROUTE
;
172 lwkt_serialize_enter(ifp
->if_serializer
);
173 error
= ifp
->if_ioctl(ifp
, SIOCSIFDSTADDR
,
175 (struct ucred
*)NULL
);
176 lwkt_serialize_exit(ifp
->if_serializer
);
180 *(struct sockaddr
*)&ia
->ia_dstaddr
= ifr
->ifr_dstaddr
;
184 return (ns_ifinit(ifp
, (struct ns_ifaddr
*)ia
,
185 (struct sockaddr_ns
*)&ifr
->ifr_addr
, 1));
188 ns_ifscrub(ifp
, (struct ns_ifaddr
*)ia
);
189 /* XXX not on list */
191 ifa_ifunlink(&ia
->ia_ifa
, ifp
);
192 if (oia
== (ia
= ns_ifaddr
)) {
193 ns_ifaddr
= ia
->ia_next
;
195 while (ia
->ia_next
&& (ia
->ia_next
!= oia
)) {
199 ia
->ia_next
= oia
->ia_next
;
201 kprintf("Didn't unlink nsifadr from list\n");
203 ifa_destroy(&oia
->ia_ifa
);
204 if (0 == --ns_interfaces
) {
206 * We reset to virginity and start all over again
208 ns_thishost
= ns_zerohost
;
213 dstIsNew
= 0; hostIsNew
= 1;
214 if (ia
->ia_addr
.sns_family
== AF_NS
) {
215 if (ifra
->ifra_addr
.sns_len
== 0) {
216 ifra
->ifra_addr
= ia
->ia_addr
;
218 } else if (ns_neteq(ifra
->ifra_addr
.sns_addr
,
219 ia
->ia_addr
.sns_addr
))
222 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
223 (ifra
->ifra_dstaddr
.sns_family
== AF_NS
)) {
225 ns_ifscrub(ifp
, (struct ns_ifaddr
*)ia
);
226 ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
229 if (ifra
->ifra_addr
.sns_family
== AF_NS
&&
230 (hostIsNew
|| dstIsNew
))
231 error
= ns_ifinit(ifp
, (struct ns_ifaddr
*)ia
,
232 &ifra
->ifra_addr
, 0);
236 if (ifp
->if_ioctl
== 0)
238 lwkt_serialize_enter(ifp
->if_serializer
);
239 error
= ifp
->if_ioctl(ifp
, cmd
, data
, (struct ucred
*)NULL
);
240 lwkt_serialize_exit(ifp
->if_serializer
);
246 * Delete any previous route for an old address.
249 ns_ifscrub(struct ifnet
*ifp
, struct ns_ifaddr
*ia
)
251 if (ia
->ia_flags
& IFA_ROUTE
) {
252 if (ifp
->if_flags
& IFF_POINTOPOINT
) {
253 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
255 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, 0);
256 ia
->ia_flags
&= ~IFA_ROUTE
;
260 * Initialize an interface's internet address
261 * and routing table entry.
264 ns_ifinit(struct ifnet
*ifp
, struct ns_ifaddr
*ia
, struct sockaddr_ns
*sns
, int scrub
)
266 struct sockaddr_ns oldaddr
;
267 union ns_host
*h
= &ia
->ia_addr
.sns_addr
.x_host
;
273 * Set up new addresses.
275 oldaddr
= ia
->ia_addr
;
278 * The convention we shall adopt for naming is that
279 * a supplied address of zero means that "we don't care".
280 * if there is a single interface, use the address of that
281 * interface as our 6 byte host address.
282 * if there are multiple interfaces, use any address already
285 * Give the interface a chance to initialize
286 * if this is its first address,
287 * and to validate the address if necessary.
289 if (ns_hosteqnh(ns_thishost
, ns_zerohost
)) {
290 lwkt_serialize_enter(ifp
->if_serializer
);
292 (error
= ifp
->if_ioctl(ifp
, SIOCSIFADDR
,
294 (struct ucred
*)NULL
))) {
295 ia
->ia_addr
= oldaddr
;
296 lwkt_serialize_exit(ifp
->if_serializer
);
300 lwkt_serialize_exit(ifp
->if_serializer
);
302 } else if (ns_hosteqnh(sns
->sns_addr
.x_host
, ns_zerohost
)
303 || ns_hosteqnh(sns
->sns_addr
.x_host
, ns_thishost
)) {
305 lwkt_serialize_enter(ifp
->if_serializer
);
307 (error
= ifp
->if_ioctl(ifp
, SIOCSIFADDR
,
309 (struct ucred
*)NULL
))) {
310 ia
->ia_addr
= oldaddr
;
311 lwkt_serialize_exit(ifp
->if_serializer
);
315 lwkt_serialize_exit(ifp
->if_serializer
);
316 if (!ns_hosteqnh(ns_thishost
,*h
)) {
317 ia
->ia_addr
= oldaddr
;
322 ia
->ia_addr
= oldaddr
;
326 ia
->ia_ifa
.ifa_metric
= ifp
->if_metric
;
328 * Add route for the network.
331 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&oldaddr
;
333 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
335 if (ifp
->if_flags
& IFF_POINTOPOINT
)
336 rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_HOST
|RTF_UP
);
338 ia
->ia_broadaddr
.sns_addr
.x_net
= ia
->ia_addr
.sns_addr
.x_net
;
339 rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_UP
);
341 ia
->ia_flags
|= IFA_ROUTE
;
346 * Return address info for specified internet network.
349 ns_iaonnetof(struct ns_addr
*dst
)
351 struct ns_ifaddr
*ia
;
352 struct ns_addr
*compare
;
354 struct ns_ifaddr
*ia_maybe
= 0;
355 union ns_net net
= dst
->x_net
;
357 for (ia
= ns_ifaddr
; ia
; ia
= ia
->ia_next
) {
358 if ((ifp
= ia
->ia_ifp
) != NULL
) {
359 if (ifp
->if_flags
& IFF_POINTOPOINT
) {
360 compare
= &satons_addr(ia
->ia_dstaddr
);
361 if (ns_hosteq(*dst
, *compare
))
363 if (ns_neteqnn(net
, ia
->ia_addr
.sns_addr
.x_net
))
366 if (ns_neteqnn(net
, ia
->ia_addr
.sns_addr
.x_net
))