xref: /csrg-svn/sys/netns/ns.c (revision 52029)
123204Smckusick /*
233371Ssklower  * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
333371Ssklower  * All rights reserved.
423204Smckusick  *
544500Sbostic  * %sccs.include.redist.c%
633371Ssklower  *
7*52029Ssklower  *	@(#)ns.c	7.9 (Berkeley) 12/19/91
823204Smckusick  */
921481Ssklower 
1021481Ssklower #include "param.h"
1121481Ssklower #include "mbuf.h"
1221481Ssklower #include "ioctl.h"
1321481Ssklower #include "protosw.h"
1450240Ssklower #include "errno.h"
1521481Ssklower #include "socket.h"
1621481Ssklower #include "socketvar.h"
1721481Ssklower 
1821481Ssklower 
1921481Ssklower #include "../net/if.h"
2021481Ssklower #include "../net/route.h"
2121481Ssklower #include "../net/af.h"
2221481Ssklower 
2321481Ssklower #include "ns.h"
2421481Ssklower #include "ns_if.h"
2521481Ssklower 
2621481Ssklower #ifdef NS
2721481Ssklower 
2821481Ssklower struct ns_ifaddr *ns_ifaddr;
2937473Ssklower int ns_interfaces;
3037473Ssklower extern struct sockaddr_ns ns_netmask, ns_hostmask;
3121481Ssklower 
3221481Ssklower /*
3321481Ssklower  * Generic internet control operations (ioctl's).
3421481Ssklower  */
3524226Ssklower /* ARGSUSED */
3621481Ssklower ns_control(so, cmd, data, ifp)
3721481Ssklower 	struct socket *so;
3821481Ssklower 	int cmd;
3921481Ssklower 	caddr_t data;
4021481Ssklower 	register struct ifnet *ifp;
4121481Ssklower {
4221481Ssklower 	register struct ifreq *ifr = (struct ifreq *)data;
4337473Ssklower 	register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data;
4421481Ssklower 	register struct ns_ifaddr *ia;
4521481Ssklower 	struct ifaddr *ifa;
4637473Ssklower 	struct ns_ifaddr *oia;
4737546Smckusick 	int error, dstIsNew, hostIsNew;
4821481Ssklower 
4921481Ssklower 	/*
5021481Ssklower 	 * Find address for this interface, if it exists.
5121481Ssklower 	 */
5225453Ssklower 	if (ifp == 0)
5324109Ssklower 		return (EADDRNOTAVAIL);
5421481Ssklower 	for (ia = ns_ifaddr; ia; ia = ia->ia_next)
5521481Ssklower 		if (ia->ia_ifp == ifp)
5621481Ssklower 			break;
5721481Ssklower 
5821481Ssklower 	switch (cmd) {
5921481Ssklower 
6021481Ssklower 	case SIOCGIFADDR:
6124109Ssklower 		if (ia == (struct ns_ifaddr *)0)
6224109Ssklower 			return (EADDRNOTAVAIL);
6337473Ssklower 		*(struct sockaddr_ns *)&ifr->ifr_addr = ia->ia_addr;
6424109Ssklower 		return (0);
6524109Ssklower 
6624109Ssklower 
6721481Ssklower 	case SIOCGIFBRDADDR:
6824109Ssklower 		if (ia == (struct ns_ifaddr *)0)
6924109Ssklower 			return (EADDRNOTAVAIL);
7024109Ssklower 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
7124109Ssklower 			return (EINVAL);
7237473Ssklower 		*(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_broadaddr;
7324109Ssklower 		return (0);
7424109Ssklower 
7521481Ssklower 	case SIOCGIFDSTADDR:
7621481Ssklower 		if (ia == (struct ns_ifaddr *)0)
7721481Ssklower 			return (EADDRNOTAVAIL);
7824109Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
7924109Ssklower 			return (EINVAL);
8037473Ssklower 		*(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
8124109Ssklower 		return (0);
8224109Ssklower 	}
8321481Ssklower 
8450240Ssklower 	if ((so->so_state & SS_PRIV) == 0)
8550240Ssklower 		return (EPERM);
8624109Ssklower 
8724109Ssklower 	switch (cmd) {
8837473Ssklower 	case SIOCAIFADDR:
8937473Ssklower 	case SIOCDIFADDR:
9037473Ssklower 		if (ifra->ifra_addr.sns_family == AF_NS)
9137473Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
9237473Ssklower 			if (ia->ia_ifp == ifp  &&
9337473Ssklower 			    ns_neteq(ia->ia_addr.sns_addr,
9437473Ssklower 				  ifra->ifra_addr.sns_addr))
9537473Ssklower 			    break;
9637473Ssklower 		    }
9737473Ssklower 		if (cmd == SIOCDIFADDR && ia == 0)
9837473Ssklower 			return (EADDRNOTAVAIL);
9937473Ssklower 		/* FALLTHROUGH */
10024109Ssklower 
10125453Ssklower 	case SIOCSIFADDR:
10221481Ssklower 	case SIOCSIFDSTADDR:
10321481Ssklower 		if (ia == (struct ns_ifaddr *)0) {
104*52029Ssklower 			oia = (struct ns_ifaddr *)
105*52029Ssklower 				malloc(sizeof *ia, M_IFADDR, M_WAITOK);
106*52029Ssklower 			if (oia == (struct ns_ifaddr *)NULL)
10721481Ssklower 				return (ENOBUFS);
10821481Ssklower 			if (ia = ns_ifaddr) {
10921481Ssklower 				for ( ; ia->ia_next; ia = ia->ia_next)
11021481Ssklower 					;
111*52029Ssklower 				ia->ia_next = oia;
11221481Ssklower 			} else
113*52029Ssklower 				ns_ifaddr = oia;
114*52029Ssklower 			ia = oia;
11521481Ssklower 			if (ifa = ifp->if_addrlist) {
11621481Ssklower 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
11721481Ssklower 					;
11821481Ssklower 				ifa->ifa_next = (struct ifaddr *) ia;
11921481Ssklower 			} else
12021481Ssklower 				ifp->if_addrlist = (struct ifaddr *) ia;
12121481Ssklower 			ia->ia_ifp = ifp;
12237473Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
12337473Ssklower 
12437473Ssklower 			ia->ia_ifa.ifa_netmask =
12537473Ssklower 				(struct sockaddr *)&ns_netmask;
12637473Ssklower 
12737473Ssklower 			ia->ia_ifa.ifa_dstaddr =
12837473Ssklower 				(struct sockaddr *)&ia->ia_dstaddr;
12937473Ssklower 			if (ifp->if_flags & IFF_BROADCAST) {
13037473Ssklower 				ia->ia_broadaddr.sns_family = AF_NS;
13137473Ssklower 				ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr);
13237473Ssklower 				ia->ia_broadaddr.sns_addr.x_host = ns_broadhost;
13337473Ssklower 			}
13437473Ssklower 			ns_interfaces++;
13521481Ssklower 		}
13625453Ssklower 	}
13725453Ssklower 
13825453Ssklower 	switch (cmd) {
13937473Ssklower 		int error;
14025453Ssklower 
14125453Ssklower 	case SIOCSIFDSTADDR:
14225453Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
14325453Ssklower 			return (EINVAL);
14425453Ssklower 		if (ia->ia_flags & IFA_ROUTE) {
14537473Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
14625453Ssklower 			ia->ia_flags &= ~IFA_ROUTE;
14725453Ssklower 		}
14825453Ssklower 		if (ifp->if_ioctl) {
14937473Ssklower 			error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, 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 		}
185*52029Ssklower 		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 */
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  */
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 &&
27021481Ssklower 		     (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
27137473Ssklower 			ia->ia_addr = oldaddr;
27221481Ssklower 			splx(s);
27321481Ssklower 			return (error);
27421481Ssklower 		}
27521481Ssklower 		ns_thishost = *h;
27621481Ssklower 	} else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost)
27721481Ssklower 	    || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) {
27821481Ssklower 		*h = ns_thishost;
27921481Ssklower 		if (ifp->if_ioctl &&
28021481Ssklower 		     (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
28137473Ssklower 			ia->ia_addr = oldaddr;
28221481Ssklower 			splx(s);
28321481Ssklower 			return (error);
28421481Ssklower 		}
28525453Ssklower 		if (!ns_hosteqnh(ns_thishost,*h)) {
28637473Ssklower 			ia->ia_addr = oldaddr;
28721481Ssklower 			splx(s);
28821481Ssklower 			return (EINVAL);
28921481Ssklower 		}
29021481Ssklower 	} else {
29137473Ssklower 		ia->ia_addr = oldaddr;
29221481Ssklower 		splx(s);
29325453Ssklower 		return (EINVAL);
29421481Ssklower 	}
29521481Ssklower 	/*
29621481Ssklower 	 * Add route for the network.
29721481Ssklower 	 */
29837473Ssklower 	if (scrub) {
29937473Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
30037473Ssklower 		ns_ifscrub(ifp, ia);
30137473Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
30237473Ssklower 	}
30325453Ssklower 	if (ifp->if_flags & IFF_POINTOPOINT)
30437473Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
30537473Ssklower 	else {
30637473Ssklower 		ia->ia_broadaddr.sns_addr.x_net = ia->ia_net;
30737473Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
30837473Ssklower 	}
30921481Ssklower 	ia->ia_flags |= IFA_ROUTE;
31025453Ssklower 	return (0);
31121481Ssklower }
31221481Ssklower 
31321481Ssklower /*
31421481Ssklower  * Return address info for specified internet network.
31521481Ssklower  */
31621481Ssklower struct ns_ifaddr *
31725045Ssklower ns_iaonnetof(dst)
31825045Ssklower 	register struct ns_addr *dst;
31921481Ssklower {
32021481Ssklower 	register struct ns_ifaddr *ia;
32125045Ssklower 	register struct ns_addr *compare;
32225453Ssklower 	register struct ifnet *ifp;
32325453Ssklower 	struct ns_ifaddr *ia_maybe = 0;
32426055Ssklower 	union ns_net net = dst->x_net;
32521481Ssklower 
32625045Ssklower 	for (ia = ns_ifaddr; ia; ia = ia->ia_next) {
32725453Ssklower 		if (ifp = ia->ia_ifp) {
32825453Ssklower 			if (ifp->if_flags & IFF_POINTOPOINT) {
32925453Ssklower 				compare = &satons_addr(ia->ia_dstaddr);
33025453Ssklower 				if (ns_hosteq(*dst, *compare))
33125045Ssklower 					return (ia);
33226055Ssklower 				if (ns_neteqnn(net, ia->ia_net))
33325453Ssklower 					ia_maybe = ia;
33425453Ssklower 			} else {
33526055Ssklower 				if (ns_neteqnn(net, ia->ia_net))
33625453Ssklower 					return (ia);
33725045Ssklower 			}
33825045Ssklower 		}
33925045Ssklower 	}
34025045Ssklower 	return (ia_maybe);
34121481Ssklower }
34221481Ssklower #endif
343