xref: /csrg-svn/sys/netns/ns.c (revision 24226)
123204Smckusick /*
223204Smckusick  * Copyright (c) 1982 Regents of the University of California.
323204Smckusick  * All rights reserved.  The Berkeley software License Agreement
423204Smckusick  * specifies the terms and conditions for redistribution.
523204Smckusick  *
6*24226Ssklower  *	@(#)ns.c	6.4 (Berkeley) 08/09/85
723204Smckusick  */
821481Ssklower 
921481Ssklower #include "param.h"
1021481Ssklower #include "mbuf.h"
1121481Ssklower #include "ioctl.h"
1221481Ssklower #include "protosw.h"
1321481Ssklower #include "socket.h"
1421481Ssklower #include "socketvar.h"
1521481Ssklower #include "uio.h"
1621481Ssklower #include "dir.h"
1721481Ssklower #include "user.h"
1821481Ssklower 
1921481Ssklower 
2021481Ssklower #include "../net/if.h"
2121481Ssklower #include "../net/route.h"
2221481Ssklower #include "../net/af.h"
2321481Ssklower 
2421481Ssklower #include "ns.h"
2521481Ssklower #include "ns_if.h"
2621481Ssklower 
2721481Ssklower #ifdef NS
2821481Ssklower 
2921481Ssklower struct ns_ifaddr *ns_ifaddr;
3021481Ssklower 
3121481Ssklower ns_hash(sns, hp)
3221481Ssklower 	register struct sockaddr_ns *sns;
3321481Ssklower 	struct afhash *hp;
3421481Ssklower {
3521481Ssklower 	register long hash = 0;
3621481Ssklower 	register u_short *s =  sns->sns_addr.x_host.s_host;
3721481Ssklower 
3821481Ssklower 	hp->afh_nethash = ns_netof(sns->sns_addr);
3921481Ssklower 	hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s;
4021481Ssklower 	hp->afh_hosthash =  hash;
4121481Ssklower }
4221481Ssklower 
4321481Ssklower 
4421481Ssklower ns_netmatch(sns1, sns2)
4521481Ssklower 	struct sockaddr_ns *sns1, *sns2;
4621481Ssklower {
4721481Ssklower 
4821481Ssklower 	return (ns_netof(sns1->sns_addr) == ns_netof(sns2->sns_addr));
4921481Ssklower }
5021481Ssklower 
5121481Ssklower /*
5221481Ssklower  * Generic internet control operations (ioctl's).
5321481Ssklower  */
54*24226Ssklower /* ARGSUSED */
5521481Ssklower ns_control(so, cmd, data, ifp)
5621481Ssklower 	struct socket *so;
5721481Ssklower 	int cmd;
5821481Ssklower 	caddr_t data;
5921481Ssklower 	register struct ifnet *ifp;
6021481Ssklower {
6121481Ssklower 	register struct ifreq *ifr = (struct ifreq *)data;
6221481Ssklower 	register struct ns_ifaddr *ia;
6321481Ssklower 	struct ifaddr *ifa;
6421481Ssklower 	struct mbuf *m;
6521481Ssklower 
6621481Ssklower 	/*
6721481Ssklower 	 * Find address for this interface, if it exists.
6821481Ssklower 	 */
6924109Ssklower 	if (ifp==0)
7024109Ssklower 		return (EADDRNOTAVAIL);
7121481Ssklower 	for (ia = ns_ifaddr; ia; ia = ia->ia_next)
7221481Ssklower 		if (ia->ia_ifp == ifp)
7321481Ssklower 			break;
7421481Ssklower 
7521481Ssklower 	switch (cmd) {
7621481Ssklower 
7721481Ssklower 	case SIOCGIFADDR:
7824109Ssklower 		if (ia == (struct ns_ifaddr *)0)
7924109Ssklower 			return (EADDRNOTAVAIL);
8024109Ssklower 		ifr->ifr_addr = ia->ia_addr;
8124109Ssklower 		return (0);
8224109Ssklower 
8324109Ssklower 
8421481Ssklower 	case SIOCGIFBRDADDR:
8524109Ssklower 		if (ia == (struct ns_ifaddr *)0)
8624109Ssklower 			return (EADDRNOTAVAIL);
8724109Ssklower 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
8824109Ssklower 			return (EINVAL);
8924109Ssklower 		ifr->ifr_dstaddr = ia->ia_broadaddr;
9024109Ssklower 		return (0);
9124109Ssklower 
9221481Ssklower 	case SIOCGIFDSTADDR:
9321481Ssklower 		if (ia == (struct ns_ifaddr *)0)
9421481Ssklower 			return (EADDRNOTAVAIL);
9524109Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
9624109Ssklower 			return (EINVAL);
9724109Ssklower 		ifr->ifr_dstaddr = ia->ia_dstaddr;
9824109Ssklower 		return (0);
9924109Ssklower 	}
10021481Ssklower 
10124109Ssklower 	if (!suser())
10224109Ssklower 		return (u.u_error);
10324109Ssklower 
10424109Ssklower 	switch (cmd) {
10524109Ssklower 
10621481Ssklower 	case SIOCSIFDSTADDR:
10721481Ssklower 		return (EOPNOTSUPP);
10821481Ssklower 
10921481Ssklower 	case SIOCSIFADDR:
11021481Ssklower 		if (ia == (struct ns_ifaddr *)0) {
11121481Ssklower 			m = m_getclr(M_WAIT, MT_IFADDR);
11221481Ssklower 			if (m == (struct mbuf *)NULL)
11321481Ssklower 				return (ENOBUFS);
11421481Ssklower 			if (ia = ns_ifaddr) {
11521481Ssklower 				for ( ; ia->ia_next; ia = ia->ia_next)
11621481Ssklower 					;
11721481Ssklower 				ia->ia_next = mtod(m, struct ns_ifaddr *);
11821481Ssklower 			} else
11921481Ssklower 				ns_ifaddr = mtod(m, struct ns_ifaddr *);
12021481Ssklower 			ia = mtod(m, struct ns_ifaddr *);
12121481Ssklower 			if (ifa = ifp->if_addrlist) {
12221481Ssklower 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
12321481Ssklower 					;
12421481Ssklower 				ifa->ifa_next = (struct ifaddr *) ia;
12521481Ssklower 			} else
12621481Ssklower 				ifp->if_addrlist = (struct ifaddr *) ia;
12721481Ssklower 			ia->ia_ifp = ifp;
12821481Ssklower 			IA_SNS(ia)->sns_family = AF_NS;
12921481Ssklower 		}
13021481Ssklower 		return
13121481Ssklower 		    (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr));
13221481Ssklower 
13321481Ssklower 	default:
13421481Ssklower 		if (ifp->if_ioctl == 0)
13521481Ssklower 			return (EOPNOTSUPP);
13621481Ssklower 		return ((*ifp->if_ioctl)(ifp, cmd, data));
13721481Ssklower 	}
13821481Ssklower }
13921481Ssklower 
14021481Ssklower /*
14121481Ssklower  * Initialize an interface's internet address
14221481Ssklower  * and routing table entry.
14321481Ssklower  */
14421481Ssklower ns_ifinit(ifp, ia, sns)
14521481Ssklower 	register struct ifnet *ifp;
14621481Ssklower 	register struct ns_ifaddr *ia;
14721481Ssklower 	struct sockaddr_ns *sns;
14821481Ssklower {
14921481Ssklower 	struct sockaddr_ns netaddr;
15021481Ssklower 	register union ns_host *h = &(IA_SNS(ia)->sns_addr.x_host);
15121481Ssklower 	int s = splimp(), error;
15221481Ssklower 
15321481Ssklower 	/*
15421481Ssklower 	 * The convention we shall adopt for naming is that
15521481Ssklower 	 * a supplied address of zero means that "we don't care".
15621481Ssklower 	 * if there is a single interface, use the address of that
15721481Ssklower 	 * interface as our 6 byte host address.
15821481Ssklower 	 * if there are multiple interfaces, use any address already
15921481Ssklower 	 * used.
16021481Ssklower 	 *
16121481Ssklower 	 * If we have gotten into trouble and want to reset back to
16221481Ssklower 	 * virginity, we recognize a request of the broadcast address.
16321481Ssklower 	 */
16421481Ssklower 	if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) {
16521481Ssklower 		ns_thishost = ns_zerohost;
16621481Ssklower 		splx(s);
16721481Ssklower 		return(EINVAL);
16821481Ssklower 	}
16921481Ssklower 
17021481Ssklower 	/*
17121481Ssklower 	 * Delete any previous route for an old address.
17221481Ssklower 	 */
17321481Ssklower 
17421481Ssklower 	bzero((caddr_t)&netaddr, sizeof (netaddr));
17521481Ssklower 	netaddr.sns_family = AF_NS;
17621481Ssklower 	netaddr.sns_addr.x_host = ns_broadhost;
17721481Ssklower 	netaddr.sns_addr.x_net = ia->ia_net;
17821481Ssklower 	if (ia->ia_flags & IFA_ROUTE) {
17921481Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
18021481Ssklower 		    rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, -1);
18121481Ssklower 		} else
18221481Ssklower 		    rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, -1);
18321481Ssklower 	}
18421481Ssklower 
18521481Ssklower 	/*
18621481Ssklower 	 * Set up new addresses.
18721481Ssklower 	 */
18821481Ssklower 	ia->ia_addr = *(struct sockaddr *)sns;
18921481Ssklower 	ia->ia_net = sns->sns_addr.x_net;
19021481Ssklower 	netaddr.sns_addr.x_net = ia->ia_net;
19121481Ssklower 	if (ifp->if_flags & IFF_BROADCAST) {
19221481Ssklower 		ia->ia_broadaddr = * (struct sockaddr *) &netaddr;
19321481Ssklower 	}
19421481Ssklower 	/*
19521481Ssklower 	 * Point to point links are a little touchier --
19621481Ssklower 	 * We have to have an address of our own first,
19721481Ssklower 	 * and will use the supplied address as that of the other end.
19821481Ssklower 	 */
19921481Ssklower 	if (ifp->if_flags & IFF_POINTOPOINT) {
20021481Ssklower 		struct sockaddr_ns *sns2 = IA_SNS(ia);
20121481Ssklower 		if (ns_hosteqnh(ns_zerohost,ns_thishost))
20221481Ssklower 			return(EINVAL);
20321481Ssklower 		ia->ia_dstaddr = ia->ia_addr;
20421481Ssklower 		sns2->sns_addr.x_host = ns_thishost;
20521481Ssklower 		sns->sns_addr.x_host = ns_thishost;
20621481Ssklower 	}
20721481Ssklower 	/*
20821481Ssklower 	 * Give the interface a chance to initialize
20921481Ssklower 	 * if this is its first address,
21021481Ssklower 	 * and to validate the address if necessary.
21121481Ssklower 	 */
21221481Ssklower 
21321481Ssklower 	if (ns_hosteqnh(ns_thishost, ns_zerohost)) {
21421481Ssklower 		if (ifp->if_ioctl &&
21521481Ssklower 		     (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
21621481Ssklower 			splx(s);
21721481Ssklower 			return (error);
21821481Ssklower 		}
21921481Ssklower 		ns_thishost = *h;
22021481Ssklower 	} else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost)
22121481Ssklower 	    || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) {
22221481Ssklower 		*h = ns_thishost;
22321481Ssklower 		if (ifp->if_ioctl &&
22421481Ssklower 		     (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
22521481Ssklower 			splx(s);
22621481Ssklower 			return (error);
22721481Ssklower 		}
22821481Ssklower 		if(!ns_hosteqnh(ns_thishost,*h)) {
22921481Ssklower 			splx(s);
23021481Ssklower 			return (EINVAL);
23121481Ssklower 		}
23221481Ssklower 	} else {
23321481Ssklower 		splx(s);
23421481Ssklower 		return(EINVAL);
23521481Ssklower 	}
23621481Ssklower 	/*
23721481Ssklower 	 * Add route for the network.
23821481Ssklower 	 */
23921481Ssklower 	if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
24021481Ssklower 		rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, RTF_UP);
24121481Ssklower 	} else
24221481Ssklower 		rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr,
24321481Ssklower 			RTF_HOST|RTF_UP);
24421481Ssklower 	ia->ia_flags |= IFA_ROUTE;
24521481Ssklower 	return(0);
24621481Ssklower }
24721481Ssklower 
24821481Ssklower /*
24921481Ssklower  * Return address info for specified internet network.
25021481Ssklower  */
25121481Ssklower struct ns_ifaddr *
25221481Ssklower ns_iaonnetof(net)
25321481Ssklower 	union ns_net net;
25421481Ssklower {
25521481Ssklower 	register struct ns_ifaddr *ia;
25621481Ssklower 
25721481Ssklower #define	NtoL(x)	(*(long *)(&(x)))
25821481Ssklower 	for (ia = ns_ifaddr; ia; ia = ia->ia_next)
25921481Ssklower 		if (NtoL(ia->ia_net) == NtoL(net))
26021481Ssklower 			return (ia);
26121481Ssklower 	return ((struct ns_ifaddr *)0);
26221481Ssklower }
26321481Ssklower #endif
264