xref: /csrg-svn/sys/netns/ns.c (revision 37473)
123204Smckusick /*
233371Ssklower  * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
333371Ssklower  * All rights reserved.
423204Smckusick  *
533371Ssklower  * Redistribution and use in source and binary forms are permitted
634856Sbostic  * provided that the above copyright notice and this paragraph are
734856Sbostic  * duplicated in all such forms and that any documentation,
834856Sbostic  * advertising materials, and other materials related to such
934856Sbostic  * distribution and use acknowledge that the software was developed
1034856Sbostic  * by the University of California, Berkeley.  The name of the
1134856Sbostic  * University may not be used to endorse or promote products derived
1234856Sbostic  * from this software without specific prior written permission.
1334856Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434856Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534856Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1633371Ssklower  *
17*37473Ssklower  *	@(#)ns.c	7.4 (Berkeley) 04/22/89
1823204Smckusick  */
1921481Ssklower 
2021481Ssklower #include "param.h"
2121481Ssklower #include "mbuf.h"
2221481Ssklower #include "ioctl.h"
2321481Ssklower #include "protosw.h"
2421481Ssklower #include "socket.h"
2521481Ssklower #include "socketvar.h"
2621481Ssklower #include "uio.h"
2721481Ssklower #include "dir.h"
2821481Ssklower #include "user.h"
2921481Ssklower 
3021481Ssklower 
3121481Ssklower #include "../net/if.h"
3221481Ssklower #include "../net/route.h"
3321481Ssklower #include "../net/af.h"
3421481Ssklower 
3521481Ssklower #include "ns.h"
3621481Ssklower #include "ns_if.h"
3721481Ssklower 
3821481Ssklower #ifdef NS
3921481Ssklower 
4021481Ssklower struct ns_ifaddr *ns_ifaddr;
41*37473Ssklower int ns_interfaces;
42*37473Ssklower extern struct sockaddr_ns ns_netmask, ns_hostmask;
4321481Ssklower 
4421481Ssklower /*
4521481Ssklower  * Generic internet control operations (ioctl's).
4621481Ssklower  */
4724226Ssklower /* ARGSUSED */
4821481Ssklower ns_control(so, cmd, data, ifp)
4921481Ssklower 	struct socket *so;
5021481Ssklower 	int cmd;
5121481Ssklower 	caddr_t data;
5221481Ssklower 	register struct ifnet *ifp;
5321481Ssklower {
5421481Ssklower 	register struct ifreq *ifr = (struct ifreq *)data;
55*37473Ssklower 	register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data;
5621481Ssklower 	register struct ns_ifaddr *ia;
5721481Ssklower 	struct ifaddr *ifa;
58*37473Ssklower 	struct ns_ifaddr *oia;
5921481Ssklower 	struct mbuf *m;
60*37473Ssklower 	int dstIsNew, hostIsNew;
6121481Ssklower 
6221481Ssklower 	/*
6321481Ssklower 	 * Find address for this interface, if it exists.
6421481Ssklower 	 */
6525453Ssklower 	if (ifp == 0)
6624109Ssklower 		return (EADDRNOTAVAIL);
6721481Ssklower 	for (ia = ns_ifaddr; ia; ia = ia->ia_next)
6821481Ssklower 		if (ia->ia_ifp == ifp)
6921481Ssklower 			break;
7021481Ssklower 
7121481Ssklower 	switch (cmd) {
7221481Ssklower 
7321481Ssklower 	case SIOCGIFADDR:
7424109Ssklower 		if (ia == (struct ns_ifaddr *)0)
7524109Ssklower 			return (EADDRNOTAVAIL);
76*37473Ssklower 		*(struct sockaddr_ns *)&ifr->ifr_addr = ia->ia_addr;
7724109Ssklower 		return (0);
7824109Ssklower 
7924109Ssklower 
8021481Ssklower 	case SIOCGIFBRDADDR:
8124109Ssklower 		if (ia == (struct ns_ifaddr *)0)
8224109Ssklower 			return (EADDRNOTAVAIL);
8324109Ssklower 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
8424109Ssklower 			return (EINVAL);
85*37473Ssklower 		*(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_broadaddr;
8624109Ssklower 		return (0);
8724109Ssklower 
8821481Ssklower 	case SIOCGIFDSTADDR:
8921481Ssklower 		if (ia == (struct ns_ifaddr *)0)
9021481Ssklower 			return (EADDRNOTAVAIL);
9124109Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
9224109Ssklower 			return (EINVAL);
93*37473Ssklower 		*(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
9424109Ssklower 		return (0);
9524109Ssklower 	}
9621481Ssklower 
9724109Ssklower 	if (!suser())
9824109Ssklower 		return (u.u_error);
9924109Ssklower 
10024109Ssklower 	switch (cmd) {
101*37473Ssklower 	case SIOCAIFADDR:
102*37473Ssklower 	case SIOCDIFADDR:
103*37473Ssklower 		if (ifra->ifra_addr.sns_family == AF_NS)
104*37473Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
105*37473Ssklower 			if (ia->ia_ifp == ifp  &&
106*37473Ssklower 			    ns_neteq(ia->ia_addr.sns_addr,
107*37473Ssklower 				  ifra->ifra_addr.sns_addr))
108*37473Ssklower 			    break;
109*37473Ssklower 		    }
110*37473Ssklower 		if (cmd == SIOCDIFADDR && ia == 0)
111*37473Ssklower 			return (EADDRNOTAVAIL);
112*37473Ssklower 		/* FALLTHROUGH */
11324109Ssklower 
11425453Ssklower 	case SIOCSIFADDR:
11521481Ssklower 	case SIOCSIFDSTADDR:
11621481Ssklower 		if (ia == (struct ns_ifaddr *)0) {
11721481Ssklower 			m = m_getclr(M_WAIT, MT_IFADDR);
11821481Ssklower 			if (m == (struct mbuf *)NULL)
11921481Ssklower 				return (ENOBUFS);
12021481Ssklower 			if (ia = ns_ifaddr) {
12121481Ssklower 				for ( ; ia->ia_next; ia = ia->ia_next)
12221481Ssklower 					;
12321481Ssklower 				ia->ia_next = mtod(m, struct ns_ifaddr *);
12421481Ssklower 			} else
12521481Ssklower 				ns_ifaddr = mtod(m, struct ns_ifaddr *);
12621481Ssklower 			ia = mtod(m, struct ns_ifaddr *);
12721481Ssklower 			if (ifa = ifp->if_addrlist) {
12821481Ssklower 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
12921481Ssklower 					;
13021481Ssklower 				ifa->ifa_next = (struct ifaddr *) ia;
13121481Ssklower 			} else
13221481Ssklower 				ifp->if_addrlist = (struct ifaddr *) ia;
13321481Ssklower 			ia->ia_ifp = ifp;
134*37473Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
135*37473Ssklower 
136*37473Ssklower 			ia->ia_ifa.ifa_netmask =
137*37473Ssklower 				(struct sockaddr *)&ns_netmask;
138*37473Ssklower 
139*37473Ssklower 			ia->ia_ifa.ifa_dstaddr =
140*37473Ssklower 				(struct sockaddr *)&ia->ia_dstaddr;
141*37473Ssklower 			if (ifp->if_flags & IFF_BROADCAST) {
142*37473Ssklower 				ia->ia_broadaddr.sns_family = AF_NS;
143*37473Ssklower 				ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr);
144*37473Ssklower 				ia->ia_broadaddr.sns_addr.x_host = ns_broadhost;
145*37473Ssklower 			}
146*37473Ssklower 			ns_interfaces++;
14721481Ssklower 		}
14825453Ssklower 	}
14925453Ssklower 
15025453Ssklower 	switch (cmd) {
151*37473Ssklower 		int error;
15225453Ssklower 
15325453Ssklower 	case SIOCSIFDSTADDR:
15425453Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
15525453Ssklower 			return (EINVAL);
15625453Ssklower 		if (ia->ia_flags & IFA_ROUTE) {
157*37473Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
15825453Ssklower 			ia->ia_flags &= ~IFA_ROUTE;
15925453Ssklower 		}
16025453Ssklower 		if (ifp->if_ioctl) {
161*37473Ssklower 			error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia);
16225453Ssklower 			if (error)
16325453Ssklower 				return (error);
16425453Ssklower 		}
165*37473Ssklower 		*(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr;
16625453Ssklower 		return (0);
16725453Ssklower 
16825453Ssklower 	case SIOCSIFADDR:
169*37473Ssklower 		return (ns_ifinit(ifp, ia,
170*37473Ssklower 				(struct sockaddr_ns *)&ifr->ifr_addr, 1));
17121481Ssklower 
172*37473Ssklower 	case SIOCDIFADDR:
173*37473Ssklower 		ns_ifscrub(ifp, ia);
174*37473Ssklower 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
175*37473Ssklower 			ifp->if_addrlist = ifa->ifa_next;
176*37473Ssklower 		else {
177*37473Ssklower 			while (ifa->ifa_next &&
178*37473Ssklower 			       (ifa->ifa_next != (struct ifaddr *)ia))
179*37473Ssklower 				    ifa = ifa->ifa_next;
180*37473Ssklower 			if (ifa->ifa_next)
181*37473Ssklower 			    ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
182*37473Ssklower 			else
183*37473Ssklower 				printf("Couldn't unlink nsifaddr from ifp\n");
184*37473Ssklower 		}
185*37473Ssklower 		oia = ia;
186*37473Ssklower 		if (oia == (ia = ns_ifaddr)) {
187*37473Ssklower 			ns_ifaddr = ia->ia_next;
188*37473Ssklower 		} else {
189*37473Ssklower 			while (ia->ia_next && (ia->ia_next != oia)) {
190*37473Ssklower 				ia = ia->ia_next;
191*37473Ssklower 			}
192*37473Ssklower 			if (ia->ia_next)
193*37473Ssklower 			    ia->ia_next = oia->ia_next;
194*37473Ssklower 			else
195*37473Ssklower 				printf("Didn't unlink nsifadr from list\n");
196*37473Ssklower 		}
197*37473Ssklower 		(void) m_free(dtom(oia));
198*37473Ssklower 		if (0 == --ns_interfaces) {
199*37473Ssklower 			/*
200*37473Ssklower 			 * We reset to virginity and start all over again
201*37473Ssklower 			 */
202*37473Ssklower 			ns_thishost = ns_zerohost;
203*37473Ssklower 		}
204*37473Ssklower 		return (0);
205*37473Ssklower 
206*37473Ssklower 	case SIOCAIFADDR:
207*37473Ssklower 		dstIsNew = 0; hostIsNew = 1;
208*37473Ssklower 		if (ia->ia_addr.sns_family == AF_NS) {
209*37473Ssklower 			if (ifra->ifra_addr.sns_len == 0) {
210*37473Ssklower 				ifra->ifra_addr = ia->ia_addr;
211*37473Ssklower 				hostIsNew = 0;
212*37473Ssklower 			} else if (ns_neteq(ifra->ifra_addr.sns_addr,
213*37473Ssklower 					 ia->ia_addr.sns_addr))
214*37473Ssklower 				hostIsNew = 0;
215*37473Ssklower 		}
216*37473Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
217*37473Ssklower 		    (ifra->ifra_dstaddr.sns_family == AF_NS)) {
218*37473Ssklower 			if (hostIsNew == 0)
219*37473Ssklower 				ns_ifscrub(ifp, ia);
220*37473Ssklower 			ia->ia_dstaddr = ifra->ifra_dstaddr;
221*37473Ssklower 			dstIsNew  = 1;
222*37473Ssklower 		}
223*37473Ssklower 		if (ifra->ifra_addr.sns_family == AF_NS &&
224*37473Ssklower 					    (hostIsNew || dstIsNew))
225*37473Ssklower 			error = ns_ifinit(ifp, ia, &ifra->ifra_addr, 0);
226*37473Ssklower 		return (error);
227*37473Ssklower 
22821481Ssklower 	default:
22921481Ssklower 		if (ifp->if_ioctl == 0)
23021481Ssklower 			return (EOPNOTSUPP);
23121481Ssklower 		return ((*ifp->if_ioctl)(ifp, cmd, data));
23221481Ssklower 	}
23321481Ssklower }
23421481Ssklower 
23521481Ssklower /*
236*37473Ssklower * Delete any previous route for an old address.
237*37473Ssklower */
238*37473Ssklower ns_ifscrub(ifp, ia)
239*37473Ssklower 	register struct ifnet *ifp;
240*37473Ssklower 	register struct ns_ifaddr *ia;
241*37473Ssklower {
242*37473Ssklower 	if (ia->ia_flags & IFA_ROUTE) {
243*37473Ssklower 		if (ifp->if_flags & IFF_POINTOPOINT) {
244*37473Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
245*37473Ssklower 		} else
246*37473Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
247*37473Ssklower 		ia->ia_flags &= ~IFA_ROUTE;
248*37473Ssklower 	}
249*37473Ssklower }
250*37473Ssklower /*
25121481Ssklower  * Initialize an interface's internet address
25221481Ssklower  * and routing table entry.
25321481Ssklower  */
254*37473Ssklower ns_ifinit(ifp, ia, sns, scrub)
25521481Ssklower 	register struct ifnet *ifp;
25621481Ssklower 	register struct ns_ifaddr *ia;
257*37473Ssklower 	register struct sockaddr_ns *sns;
25821481Ssklower {
259*37473Ssklower 	struct sockaddr_ns oldaddr;
260*37473Ssklower 	register union ns_host *h = &ia->ia_addr.sns_addr.x_host;
26121481Ssklower 	int s = splimp(), error;
26221481Ssklower 
26321481Ssklower 	/*
264*37473Ssklower 	 * Set up new addresses.
265*37473Ssklower 	 */
266*37473Ssklower 	oldaddr = ia->ia_addr;
267*37473Ssklower 	ia->ia_addr = *sns;
268*37473Ssklower 	/*
26921481Ssklower 	 * The convention we shall adopt for naming is that
27021481Ssklower 	 * a supplied address of zero means that "we don't care".
27121481Ssklower 	 * if there is a single interface, use the address of that
27221481Ssklower 	 * interface as our 6 byte host address.
27321481Ssklower 	 * if there are multiple interfaces, use any address already
27421481Ssklower 	 * used.
27521481Ssklower 	 *
27621481Ssklower 	 * Give the interface a chance to initialize
27721481Ssklower 	 * if this is its first address,
27821481Ssklower 	 * and to validate the address if necessary.
27921481Ssklower 	 */
28021481Ssklower 	if (ns_hosteqnh(ns_thishost, ns_zerohost)) {
28121481Ssklower 		if (ifp->if_ioctl &&
28221481Ssklower 		     (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
283*37473Ssklower 			ia->ia_addr = oldaddr;
28421481Ssklower 			splx(s);
28521481Ssklower 			return (error);
28621481Ssklower 		}
28721481Ssklower 		ns_thishost = *h;
28821481Ssklower 	} else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost)
28921481Ssklower 	    || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) {
29021481Ssklower 		*h = ns_thishost;
29121481Ssklower 		if (ifp->if_ioctl &&
29221481Ssklower 		     (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
293*37473Ssklower 			ia->ia_addr = oldaddr;
29421481Ssklower 			splx(s);
29521481Ssklower 			return (error);
29621481Ssklower 		}
29725453Ssklower 		if (!ns_hosteqnh(ns_thishost,*h)) {
298*37473Ssklower 			ia->ia_addr = oldaddr;
29921481Ssklower 			splx(s);
30021481Ssklower 			return (EINVAL);
30121481Ssklower 		}
30221481Ssklower 	} else {
303*37473Ssklower 		ia->ia_addr = oldaddr;
30421481Ssklower 		splx(s);
30525453Ssklower 		return (EINVAL);
30621481Ssklower 	}
30721481Ssklower 	/*
30821481Ssklower 	 * Add route for the network.
30921481Ssklower 	 */
310*37473Ssklower 	if (scrub) {
311*37473Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
312*37473Ssklower 		ns_ifscrub(ifp, ia);
313*37473Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
314*37473Ssklower 	}
31525453Ssklower 	if (ifp->if_flags & IFF_POINTOPOINT)
316*37473Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
317*37473Ssklower 	else {
318*37473Ssklower 		ia->ia_broadaddr.sns_addr.x_net = ia->ia_net;
319*37473Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
320*37473Ssklower 	}
32121481Ssklower 	ia->ia_flags |= IFA_ROUTE;
32225453Ssklower 	return (0);
32321481Ssklower }
32421481Ssklower 
32521481Ssklower /*
32621481Ssklower  * Return address info for specified internet network.
32721481Ssklower  */
32821481Ssklower struct ns_ifaddr *
32925045Ssklower ns_iaonnetof(dst)
33025045Ssklower 	register struct ns_addr *dst;
33121481Ssklower {
33221481Ssklower 	register struct ns_ifaddr *ia;
33325045Ssklower 	register struct ns_addr *compare;
33425453Ssklower 	register struct ifnet *ifp;
33525453Ssklower 	struct ns_ifaddr *ia_maybe = 0;
33626055Ssklower 	union ns_net net = dst->x_net;
33721481Ssklower 
33825045Ssklower 	for (ia = ns_ifaddr; ia; ia = ia->ia_next) {
33925453Ssklower 		if (ifp = ia->ia_ifp) {
34025453Ssklower 			if (ifp->if_flags & IFF_POINTOPOINT) {
34125453Ssklower 				compare = &satons_addr(ia->ia_dstaddr);
34225453Ssklower 				if (ns_hosteq(*dst, *compare))
34325045Ssklower 					return (ia);
34426055Ssklower 				if (ns_neteqnn(net, ia->ia_net))
34525453Ssklower 					ia_maybe = ia;
34625453Ssklower 			} else {
34726055Ssklower 				if (ns_neteqnn(net, ia->ia_net))
34825453Ssklower 					return (ia);
34925045Ssklower 			}
35025045Ssklower 		}
35125045Ssklower 	}
35225045Ssklower 	return (ia_maybe);
35321481Ssklower }
35421481Ssklower #endif
355