xref: /csrg-svn/sys/netns/ns.c (revision 68252)
123204Smckusick /*
263231Sbostic  * Copyright (c) 1984, 1985, 1986, 1987, 1993
363231Sbostic  *	The Regents of the University of California.  All rights reserved.
423204Smckusick  *
544500Sbostic  * %sccs.include.redist.c%
633371Ssklower  *
7*68252Ssklower  *	@(#)ns.c	8.5 (Berkeley) 02/09/95
823204Smckusick  */
921481Ssklower 
1056534Sbostic #include <sys/param.h>
1156534Sbostic #include <sys/mbuf.h>
1256534Sbostic #include <sys/ioctl.h>
1356534Sbostic #include <sys/protosw.h>
1456534Sbostic #include <sys/errno.h>
1556534Sbostic #include <sys/socket.h>
1656534Sbostic #include <sys/socketvar.h>
1721481Ssklower 
1856534Sbostic #include <net/if.h>
1956534Sbostic #include <net/route.h>
2021481Ssklower 
2156534Sbostic #include <netns/ns.h>
2256534Sbostic #include <netns/ns_if.h>
2321481Ssklower 
2421481Ssklower #ifdef NS
2521481Ssklower 
2621481Ssklower struct ns_ifaddr *ns_ifaddr;
2737473Ssklower int ns_interfaces;
2837473Ssklower extern struct sockaddr_ns ns_netmask, ns_hostmask;
2921481Ssklower 
3021481Ssklower /*
3121481Ssklower  * Generic internet control operations (ioctl's).
3221481Ssklower  */
3324226Ssklower /* ARGSUSED */
3421481Ssklower ns_control(so, cmd, data, ifp)
3521481Ssklower 	struct socket *so;
3668167Scgd 	u_long cmd;
3721481Ssklower 	caddr_t data;
3821481Ssklower 	register struct ifnet *ifp;
3921481Ssklower {
4021481Ssklower 	register struct ifreq *ifr = (struct ifreq *)data;
4137473Ssklower 	register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data;
4221481Ssklower 	register struct ns_ifaddr *ia;
4321481Ssklower 	struct ifaddr *ifa;
4437473Ssklower 	struct ns_ifaddr *oia;
4537546Smckusick 	int error, dstIsNew, hostIsNew;
4621481Ssklower 
4721481Ssklower 	/*
4821481Ssklower 	 * Find address for this interface, if it exists.
4921481Ssklower 	 */
5025453Ssklower 	if (ifp == 0)
5124109Ssklower 		return (EADDRNOTAVAIL);
5221481Ssklower 	for (ia = ns_ifaddr; ia; ia = ia->ia_next)
5321481Ssklower 		if (ia->ia_ifp == ifp)
5421481Ssklower 			break;
5521481Ssklower 
5621481Ssklower 	switch (cmd) {
5721481Ssklower 
5821481Ssklower 	case SIOCGIFADDR:
5924109Ssklower 		if (ia == (struct ns_ifaddr *)0)
6024109Ssklower 			return (EADDRNOTAVAIL);
6137473Ssklower 		*(struct sockaddr_ns *)&ifr->ifr_addr = ia->ia_addr;
6224109Ssklower 		return (0);
6324109Ssklower 
6424109Ssklower 
6521481Ssklower 	case SIOCGIFBRDADDR:
6624109Ssklower 		if (ia == (struct ns_ifaddr *)0)
6724109Ssklower 			return (EADDRNOTAVAIL);
6824109Ssklower 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
6924109Ssklower 			return (EINVAL);
7037473Ssklower 		*(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_broadaddr;
7124109Ssklower 		return (0);
7224109Ssklower 
7321481Ssklower 	case SIOCGIFDSTADDR:
7421481Ssklower 		if (ia == (struct ns_ifaddr *)0)
7521481Ssklower 			return (EADDRNOTAVAIL);
7624109Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
7724109Ssklower 			return (EINVAL);
7837473Ssklower 		*(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
7924109Ssklower 		return (0);
8024109Ssklower 	}
8121481Ssklower 
8250240Ssklower 	if ((so->so_state & SS_PRIV) == 0)
8350240Ssklower 		return (EPERM);
8424109Ssklower 
8524109Ssklower 	switch (cmd) {
8637473Ssklower 	case SIOCAIFADDR:
8737473Ssklower 	case SIOCDIFADDR:
8837473Ssklower 		if (ifra->ifra_addr.sns_family == AF_NS)
8937473Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
9037473Ssklower 			if (ia->ia_ifp == ifp  &&
9137473Ssklower 			    ns_neteq(ia->ia_addr.sns_addr,
9237473Ssklower 				  ifra->ifra_addr.sns_addr))
9337473Ssklower 			    break;
9437473Ssklower 		    }
9537473Ssklower 		if (cmd == SIOCDIFADDR && ia == 0)
9637473Ssklower 			return (EADDRNOTAVAIL);
9737473Ssklower 		/* FALLTHROUGH */
9824109Ssklower 
9925453Ssklower 	case SIOCSIFADDR:
10021481Ssklower 	case SIOCSIFDSTADDR:
10121481Ssklower 		if (ia == (struct ns_ifaddr *)0) {
10252029Ssklower 			oia = (struct ns_ifaddr *)
10352029Ssklower 				malloc(sizeof *ia, M_IFADDR, M_WAITOK);
10452029Ssklower 			if (oia == (struct ns_ifaddr *)NULL)
10521481Ssklower 				return (ENOBUFS);
10652630Ssklower 			bzero((caddr_t)oia, sizeof(*oia));
10721481Ssklower 			if (ia = ns_ifaddr) {
10821481Ssklower 				for ( ; ia->ia_next; ia = ia->ia_next)
10921481Ssklower 					;
11052029Ssklower 				ia->ia_next = oia;
11121481Ssklower 			} else
11252029Ssklower 				ns_ifaddr = oia;
11352029Ssklower 			ia = oia;
11421481Ssklower 			if (ifa = ifp->if_addrlist) {
11521481Ssklower 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
11621481Ssklower 					;
11721481Ssklower 				ifa->ifa_next = (struct ifaddr *) ia;
11821481Ssklower 			} else
11921481Ssklower 				ifp->if_addrlist = (struct ifaddr *) ia;
12021481Ssklower 			ia->ia_ifp = ifp;
12137473Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
12237473Ssklower 
12337473Ssklower 			ia->ia_ifa.ifa_netmask =
12437473Ssklower 				(struct sockaddr *)&ns_netmask;
12537473Ssklower 
12637473Ssklower 			ia->ia_ifa.ifa_dstaddr =
12737473Ssklower 				(struct sockaddr *)&ia->ia_dstaddr;
12837473Ssklower 			if (ifp->if_flags & IFF_BROADCAST) {
12937473Ssklower 				ia->ia_broadaddr.sns_family = AF_NS;
13037473Ssklower 				ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr);
13137473Ssklower 				ia->ia_broadaddr.sns_addr.x_host = ns_broadhost;
13237473Ssklower 			}
13337473Ssklower 			ns_interfaces++;
13421481Ssklower 		}
13525453Ssklower 	}
13625453Ssklower 
13725453Ssklower 	switch (cmd) {
13837473Ssklower 		int error;
13925453Ssklower 
14025453Ssklower 	case SIOCSIFDSTADDR:
14125453Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
14225453Ssklower 			return (EINVAL);
14325453Ssklower 		if (ia->ia_flags & IFA_ROUTE) {
14437473Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
14525453Ssklower 			ia->ia_flags &= ~IFA_ROUTE;
14625453Ssklower 		}
14725453Ssklower 		if (ifp->if_ioctl) {
148*68252Ssklower 			error = (*ifp->if_ioctl)
149*68252Ssklower 				        (ifp, SIOCSIFDSTADDR, (caddr_t)ia);
15025453Ssklower 			if (error)
15125453Ssklower 				return (error);
15225453Ssklower 		}
15337473Ssklower 		*(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr;
15425453Ssklower 		return (0);
15525453Ssklower 
15625453Ssklower 	case SIOCSIFADDR:
15737473Ssklower 		return (ns_ifinit(ifp, ia,
15837473Ssklower 				(struct sockaddr_ns *)&ifr->ifr_addr, 1));
15921481Ssklower 
16037473Ssklower 	case SIOCDIFADDR:
16137473Ssklower 		ns_ifscrub(ifp, ia);
16237473Ssklower 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
16337473Ssklower 			ifp->if_addrlist = ifa->ifa_next;
16437473Ssklower 		else {
16537473Ssklower 			while (ifa->ifa_next &&
16637473Ssklower 			       (ifa->ifa_next != (struct ifaddr *)ia))
16737473Ssklower 				    ifa = ifa->ifa_next;
16837473Ssklower 			if (ifa->ifa_next)
16937473Ssklower 			    ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
17037473Ssklower 			else
17137473Ssklower 				printf("Couldn't unlink nsifaddr from ifp\n");
17237473Ssklower 		}
17337473Ssklower 		oia = ia;
17437473Ssklower 		if (oia == (ia = ns_ifaddr)) {
17537473Ssklower 			ns_ifaddr = ia->ia_next;
17637473Ssklower 		} else {
17737473Ssklower 			while (ia->ia_next && (ia->ia_next != oia)) {
17837473Ssklower 				ia = ia->ia_next;
17937473Ssklower 			}
18037473Ssklower 			if (ia->ia_next)
18137473Ssklower 			    ia->ia_next = oia->ia_next;
18237473Ssklower 			else
18337473Ssklower 				printf("Didn't unlink nsifadr from list\n");
18437473Ssklower 		}
18552029Ssklower 		IFAFREE((&oia->ia_ifa));
18637473Ssklower 		if (0 == --ns_interfaces) {
18737473Ssklower 			/*
18837473Ssklower 			 * We reset to virginity and start all over again
18937473Ssklower 			 */
19037473Ssklower 			ns_thishost = ns_zerohost;
19137473Ssklower 		}
19237473Ssklower 		return (0);
19337473Ssklower 
19437473Ssklower 	case SIOCAIFADDR:
19537473Ssklower 		dstIsNew = 0; hostIsNew = 1;
19637473Ssklower 		if (ia->ia_addr.sns_family == AF_NS) {
19737473Ssklower 			if (ifra->ifra_addr.sns_len == 0) {
19837473Ssklower 				ifra->ifra_addr = ia->ia_addr;
19937473Ssklower 				hostIsNew = 0;
20037473Ssklower 			} else if (ns_neteq(ifra->ifra_addr.sns_addr,
20137473Ssklower 					 ia->ia_addr.sns_addr))
20237473Ssklower 				hostIsNew = 0;
20337473Ssklower 		}
20437473Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
20537473Ssklower 		    (ifra->ifra_dstaddr.sns_family == AF_NS)) {
20637473Ssklower 			if (hostIsNew == 0)
20737473Ssklower 				ns_ifscrub(ifp, ia);
20837473Ssklower 			ia->ia_dstaddr = ifra->ifra_dstaddr;
20937473Ssklower 			dstIsNew  = 1;
21037473Ssklower 		}
21137473Ssklower 		if (ifra->ifra_addr.sns_family == AF_NS &&
21237473Ssklower 					    (hostIsNew || dstIsNew))
21337473Ssklower 			error = ns_ifinit(ifp, ia, &ifra->ifra_addr, 0);
21437473Ssklower 		return (error);
21537473Ssklower 
21621481Ssklower 	default:
21721481Ssklower 		if (ifp->if_ioctl == 0)
21821481Ssklower 			return (EOPNOTSUPP);
21921481Ssklower 		return ((*ifp->if_ioctl)(ifp, cmd, data));
22021481Ssklower 	}
22121481Ssklower }
22221481Ssklower 
22321481Ssklower /*
22437473Ssklower * Delete any previous route for an old address.
22537473Ssklower */
ns_ifscrub(ifp,ia)22637473Ssklower ns_ifscrub(ifp, ia)
22737473Ssklower 	register struct ifnet *ifp;
22837473Ssklower 	register struct ns_ifaddr *ia;
22937473Ssklower {
23037473Ssklower 	if (ia->ia_flags & IFA_ROUTE) {
23137473Ssklower 		if (ifp->if_flags & IFF_POINTOPOINT) {
23237473Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
23337473Ssklower 		} else
23437473Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
23537473Ssklower 		ia->ia_flags &= ~IFA_ROUTE;
23637473Ssklower 	}
23737473Ssklower }
23837473Ssklower /*
23921481Ssklower  * Initialize an interface's internet address
24021481Ssklower  * and routing table entry.
24121481Ssklower  */
ns_ifinit(ifp,ia,sns,scrub)24237473Ssklower ns_ifinit(ifp, ia, sns, scrub)
24321481Ssklower 	register struct ifnet *ifp;
24421481Ssklower 	register struct ns_ifaddr *ia;
24537473Ssklower 	register struct sockaddr_ns *sns;
24621481Ssklower {
24737473Ssklower 	struct sockaddr_ns oldaddr;
24837473Ssklower 	register union ns_host *h = &ia->ia_addr.sns_addr.x_host;
24921481Ssklower 	int s = splimp(), error;
25021481Ssklower 
25121481Ssklower 	/*
25237473Ssklower 	 * Set up new addresses.
25337473Ssklower 	 */
25437473Ssklower 	oldaddr = ia->ia_addr;
25537473Ssklower 	ia->ia_addr = *sns;
25637473Ssklower 	/*
25721481Ssklower 	 * The convention we shall adopt for naming is that
25821481Ssklower 	 * a supplied address of zero means that "we don't care".
25921481Ssklower 	 * if there is a single interface, use the address of that
26021481Ssklower 	 * interface as our 6 byte host address.
26121481Ssklower 	 * if there are multiple interfaces, use any address already
26221481Ssklower 	 * used.
26321481Ssklower 	 *
26421481Ssklower 	 * Give the interface a chance to initialize
26521481Ssklower 	 * if this is its first address,
26621481Ssklower 	 * and to validate the address if necessary.
26721481Ssklower 	 */
26821481Ssklower 	if (ns_hosteqnh(ns_thishost, ns_zerohost)) {
26921481Ssklower 		if (ifp->if_ioctl &&
27068186Smckusick 		     (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)))
27168186Smckusick 			goto bad;
27221481Ssklower 		ns_thishost = *h;
27321481Ssklower 	} else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost)
27421481Ssklower 	    || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) {
27521481Ssklower 		*h = ns_thishost;
27621481Ssklower 		if (ifp->if_ioctl &&
27768186Smckusick 		     (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)))
27868186Smckusick 			goto bad;
27925453Ssklower 		if (!ns_hosteqnh(ns_thishost,*h)) {
28068186Smckusick 			error = EINVAL;
28168186Smckusick 			goto bad;
28221481Ssklower 		}
28321481Ssklower 	} else {
28468186Smckusick 		error = EINVAL;
28568186Smckusick 		goto bad;
28621481Ssklower 	}
28752618Ssklower 	ia->ia_ifa.ifa_metric = ifp->if_metric;
28821481Ssklower 	/*
28921481Ssklower 	 * Add route for the network.
29021481Ssklower 	 */
29137473Ssklower 	if (scrub) {
29237473Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
29337473Ssklower 		ns_ifscrub(ifp, ia);
29437473Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
29537473Ssklower 	}
29625453Ssklower 	if (ifp->if_flags & IFF_POINTOPOINT)
29737473Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
29837473Ssklower 	else {
29953397Ssklower 		ia->ia_broadaddr.sns_addr.x_net = ia->ia_addr.sns_addr.x_net;
30037473Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
30137473Ssklower 	}
30221481Ssklower 	ia->ia_flags |= IFA_ROUTE;
30368186Smckusick 	splx(s);
30425453Ssklower 	return (0);
30568186Smckusick bad:
30668186Smckusick 	ia->ia_addr = oldaddr;
30768186Smckusick 	splx(s);
30868186Smckusick 	return (error);
30921481Ssklower }
31021481Ssklower 
31121481Ssklower /*
31221481Ssklower  * Return address info for specified internet network.
31321481Ssklower  */
31421481Ssklower struct ns_ifaddr *
ns_iaonnetof(dst)31525045Ssklower ns_iaonnetof(dst)
31625045Ssklower 	register struct ns_addr *dst;
31721481Ssklower {
31821481Ssklower 	register struct ns_ifaddr *ia;
31925045Ssklower 	register struct ns_addr *compare;
32025453Ssklower 	register struct ifnet *ifp;
32125453Ssklower 	struct ns_ifaddr *ia_maybe = 0;
32226055Ssklower 	union ns_net net = dst->x_net;
32321481Ssklower 
32425045Ssklower 	for (ia = ns_ifaddr; ia; ia = ia->ia_next) {
32525453Ssklower 		if (ifp = ia->ia_ifp) {
32625453Ssklower 			if (ifp->if_flags & IFF_POINTOPOINT) {
32725453Ssklower 				compare = &satons_addr(ia->ia_dstaddr);
32825453Ssklower 				if (ns_hosteq(*dst, *compare))
32925045Ssklower 					return (ia);
33053397Ssklower 				if (ns_neteqnn(net, ia->ia_addr.sns_addr.x_net))
33125453Ssklower 					ia_maybe = ia;
33225453Ssklower 			} else {
33353397Ssklower 				if (ns_neteqnn(net, ia->ia_addr.sns_addr.x_net))
33425453Ssklower 					return (ia);
33525045Ssklower 			}
33625045Ssklower 		}
33725045Ssklower 	}
33825045Ssklower 	return (ia_maybe);
33921481Ssklower }
34021481Ssklower #endif
341