xref: /csrg-svn/sys/netns/ns.c (revision 37546)
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*37546Smckusick  *	@(#)ns.c	7.5 (Berkeley) 04/26/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;
4137473Ssklower int ns_interfaces;
4237473Ssklower 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;
5537473Ssklower 	register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data;
5621481Ssklower 	register struct ns_ifaddr *ia;
5721481Ssklower 	struct ifaddr *ifa;
5837473Ssklower 	struct ns_ifaddr *oia;
5921481Ssklower 	struct mbuf *m;
60*37546Smckusick 	int error, 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);
7637473Ssklower 		*(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);
8537473Ssklower 		*(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);
9337473Ssklower 		*(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
9424109Ssklower 		return (0);
9524109Ssklower 	}
9621481Ssklower 
97*37546Smckusick 	if (error = suser(u.u_cred, &u.u_acflag))
98*37546Smckusick 		return (error);
9924109Ssklower 
10024109Ssklower 	switch (cmd) {
10137473Ssklower 	case SIOCAIFADDR:
10237473Ssklower 	case SIOCDIFADDR:
10337473Ssklower 		if (ifra->ifra_addr.sns_family == AF_NS)
10437473Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
10537473Ssklower 			if (ia->ia_ifp == ifp  &&
10637473Ssklower 			    ns_neteq(ia->ia_addr.sns_addr,
10737473Ssklower 				  ifra->ifra_addr.sns_addr))
10837473Ssklower 			    break;
10937473Ssklower 		    }
11037473Ssklower 		if (cmd == SIOCDIFADDR && ia == 0)
11137473Ssklower 			return (EADDRNOTAVAIL);
11237473Ssklower 		/* 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;
13437473Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
13537473Ssklower 
13637473Ssklower 			ia->ia_ifa.ifa_netmask =
13737473Ssklower 				(struct sockaddr *)&ns_netmask;
13837473Ssklower 
13937473Ssklower 			ia->ia_ifa.ifa_dstaddr =
14037473Ssklower 				(struct sockaddr *)&ia->ia_dstaddr;
14137473Ssklower 			if (ifp->if_flags & IFF_BROADCAST) {
14237473Ssklower 				ia->ia_broadaddr.sns_family = AF_NS;
14337473Ssklower 				ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr);
14437473Ssklower 				ia->ia_broadaddr.sns_addr.x_host = ns_broadhost;
14537473Ssklower 			}
14637473Ssklower 			ns_interfaces++;
14721481Ssklower 		}
14825453Ssklower 	}
14925453Ssklower 
15025453Ssklower 	switch (cmd) {
15137473Ssklower 		int error;
15225453Ssklower 
15325453Ssklower 	case SIOCSIFDSTADDR:
15425453Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
15525453Ssklower 			return (EINVAL);
15625453Ssklower 		if (ia->ia_flags & IFA_ROUTE) {
15737473Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
15825453Ssklower 			ia->ia_flags &= ~IFA_ROUTE;
15925453Ssklower 		}
16025453Ssklower 		if (ifp->if_ioctl) {
16137473Ssklower 			error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia);
16225453Ssklower 			if (error)
16325453Ssklower 				return (error);
16425453Ssklower 		}
16537473Ssklower 		*(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr;
16625453Ssklower 		return (0);
16725453Ssklower 
16825453Ssklower 	case SIOCSIFADDR:
16937473Ssklower 		return (ns_ifinit(ifp, ia,
17037473Ssklower 				(struct sockaddr_ns *)&ifr->ifr_addr, 1));
17121481Ssklower 
17237473Ssklower 	case SIOCDIFADDR:
17337473Ssklower 		ns_ifscrub(ifp, ia);
17437473Ssklower 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
17537473Ssklower 			ifp->if_addrlist = ifa->ifa_next;
17637473Ssklower 		else {
17737473Ssklower 			while (ifa->ifa_next &&
17837473Ssklower 			       (ifa->ifa_next != (struct ifaddr *)ia))
17937473Ssklower 				    ifa = ifa->ifa_next;
18037473Ssklower 			if (ifa->ifa_next)
18137473Ssklower 			    ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
18237473Ssklower 			else
18337473Ssklower 				printf("Couldn't unlink nsifaddr from ifp\n");
18437473Ssklower 		}
18537473Ssklower 		oia = ia;
18637473Ssklower 		if (oia == (ia = ns_ifaddr)) {
18737473Ssklower 			ns_ifaddr = ia->ia_next;
18837473Ssklower 		} else {
18937473Ssklower 			while (ia->ia_next && (ia->ia_next != oia)) {
19037473Ssklower 				ia = ia->ia_next;
19137473Ssklower 			}
19237473Ssklower 			if (ia->ia_next)
19337473Ssklower 			    ia->ia_next = oia->ia_next;
19437473Ssklower 			else
19537473Ssklower 				printf("Didn't unlink nsifadr from list\n");
19637473Ssklower 		}
19737473Ssklower 		(void) m_free(dtom(oia));
19837473Ssklower 		if (0 == --ns_interfaces) {
19937473Ssklower 			/*
20037473Ssklower 			 * We reset to virginity and start all over again
20137473Ssklower 			 */
20237473Ssklower 			ns_thishost = ns_zerohost;
20337473Ssklower 		}
20437473Ssklower 		return (0);
20537473Ssklower 
20637473Ssklower 	case SIOCAIFADDR:
20737473Ssklower 		dstIsNew = 0; hostIsNew = 1;
20837473Ssklower 		if (ia->ia_addr.sns_family == AF_NS) {
20937473Ssklower 			if (ifra->ifra_addr.sns_len == 0) {
21037473Ssklower 				ifra->ifra_addr = ia->ia_addr;
21137473Ssklower 				hostIsNew = 0;
21237473Ssklower 			} else if (ns_neteq(ifra->ifra_addr.sns_addr,
21337473Ssklower 					 ia->ia_addr.sns_addr))
21437473Ssklower 				hostIsNew = 0;
21537473Ssklower 		}
21637473Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
21737473Ssklower 		    (ifra->ifra_dstaddr.sns_family == AF_NS)) {
21837473Ssklower 			if (hostIsNew == 0)
21937473Ssklower 				ns_ifscrub(ifp, ia);
22037473Ssklower 			ia->ia_dstaddr = ifra->ifra_dstaddr;
22137473Ssklower 			dstIsNew  = 1;
22237473Ssklower 		}
22337473Ssklower 		if (ifra->ifra_addr.sns_family == AF_NS &&
22437473Ssklower 					    (hostIsNew || dstIsNew))
22537473Ssklower 			error = ns_ifinit(ifp, ia, &ifra->ifra_addr, 0);
22637473Ssklower 		return (error);
22737473Ssklower 
22821481Ssklower 	default:
22921481Ssklower 		if (ifp->if_ioctl == 0)
23021481Ssklower 			return (EOPNOTSUPP);
23121481Ssklower 		return ((*ifp->if_ioctl)(ifp, cmd, data));
23221481Ssklower 	}
23321481Ssklower }
23421481Ssklower 
23521481Ssklower /*
23637473Ssklower * Delete any previous route for an old address.
23737473Ssklower */
23837473Ssklower ns_ifscrub(ifp, ia)
23937473Ssklower 	register struct ifnet *ifp;
24037473Ssklower 	register struct ns_ifaddr *ia;
24137473Ssklower {
24237473Ssklower 	if (ia->ia_flags & IFA_ROUTE) {
24337473Ssklower 		if (ifp->if_flags & IFF_POINTOPOINT) {
24437473Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
24537473Ssklower 		} else
24637473Ssklower 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
24737473Ssklower 		ia->ia_flags &= ~IFA_ROUTE;
24837473Ssklower 	}
24937473Ssklower }
25037473Ssklower /*
25121481Ssklower  * Initialize an interface's internet address
25221481Ssklower  * and routing table entry.
25321481Ssklower  */
25437473Ssklower ns_ifinit(ifp, ia, sns, scrub)
25521481Ssklower 	register struct ifnet *ifp;
25621481Ssklower 	register struct ns_ifaddr *ia;
25737473Ssklower 	register struct sockaddr_ns *sns;
25821481Ssklower {
25937473Ssklower 	struct sockaddr_ns oldaddr;
26037473Ssklower 	register union ns_host *h = &ia->ia_addr.sns_addr.x_host;
26121481Ssklower 	int s = splimp(), error;
26221481Ssklower 
26321481Ssklower 	/*
26437473Ssklower 	 * Set up new addresses.
26537473Ssklower 	 */
26637473Ssklower 	oldaddr = ia->ia_addr;
26737473Ssklower 	ia->ia_addr = *sns;
26837473Ssklower 	/*
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))) {
28337473Ssklower 			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))) {
29337473Ssklower 			ia->ia_addr = oldaddr;
29421481Ssklower 			splx(s);
29521481Ssklower 			return (error);
29621481Ssklower 		}
29725453Ssklower 		if (!ns_hosteqnh(ns_thishost,*h)) {
29837473Ssklower 			ia->ia_addr = oldaddr;
29921481Ssklower 			splx(s);
30021481Ssklower 			return (EINVAL);
30121481Ssklower 		}
30221481Ssklower 	} else {
30337473Ssklower 		ia->ia_addr = oldaddr;
30421481Ssklower 		splx(s);
30525453Ssklower 		return (EINVAL);
30621481Ssklower 	}
30721481Ssklower 	/*
30821481Ssklower 	 * Add route for the network.
30921481Ssklower 	 */
31037473Ssklower 	if (scrub) {
31137473Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
31237473Ssklower 		ns_ifscrub(ifp, ia);
31337473Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
31437473Ssklower 	}
31525453Ssklower 	if (ifp->if_flags & IFF_POINTOPOINT)
31637473Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
31737473Ssklower 	else {
31837473Ssklower 		ia->ia_broadaddr.sns_addr.x_net = ia->ia_net;
31937473Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
32037473Ssklower 	}
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