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