BSD 4_3 release
[unix-history] / usr / src / sys / netns / ns.c
index 31f2e63..674b15c 100644 (file)
@@ -1,9 +1,9 @@
 /*
 /*
- * Copyright (c) 1982 Regents of the University of California.
+ * Copyright (c) 1984, 1985, 1986 Regents of the University of California.
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
- *     @(#)ns.c        6.2 (Berkeley) %G%
+ *     @(#)ns.c        7.1 (Berkeley) 6/5/86
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -34,8 +34,13 @@ ns_hash(sns, hp)
 {
        register long hash = 0;
        register u_short *s =  sns->sns_addr.x_host.s_host;
 {
        register long hash = 0;
        register u_short *s =  sns->sns_addr.x_host.s_host;
+       union {
+               union ns_net    net_e;
+               long            long_e;
+       } net;
 
 
-       hp->afh_nethash = ns_netof(sns->sns_addr);
+       net.net_e = sns->sns_addr.x_net;
+       hp->afh_nethash = net.long_e;
        hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s;
        hp->afh_hosthash =  hash;
 }
        hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s;
        hp->afh_hosthash =  hash;
 }
@@ -45,12 +50,13 @@ ns_netmatch(sns1, sns2)
        struct sockaddr_ns *sns1, *sns2;
 {
 
        struct sockaddr_ns *sns1, *sns2;
 {
 
-       return (ns_netof(sns1->sns_addr) == ns_netof(sns2->sns_addr));
+       return (ns_neteq(sns1->sns_addr, sns2->sns_addr));
 }
 
 /*
  * Generic internet control operations (ioctl's).
  */
 }
 
 /*
  * Generic internet control operations (ioctl's).
  */
+/* ARGSUSED */
 ns_control(so, cmd, data, ifp)
        struct socket *so;
        int cmd;
 ns_control(so, cmd, data, ifp)
        struct socket *so;
        int cmd;
@@ -61,14 +67,12 @@ ns_control(so, cmd, data, ifp)
        register struct ns_ifaddr *ia;
        struct ifaddr *ifa;
        struct mbuf *m;
        register struct ns_ifaddr *ia;
        struct ifaddr *ifa;
        struct mbuf *m;
-       int error;
-
-       if (!suser())
-               return (u.u_error);
 
        /*
         * Find address for this interface, if it exists.
         */
 
        /*
         * Find address for this interface, if it exists.
         */
+       if (ifp == 0)
+               return (EADDRNOTAVAIL);
        for (ia = ns_ifaddr; ia; ia = ia->ia_next)
                if (ia->ia_ifp == ifp)
                        break;
        for (ia = ns_ifaddr; ia; ia = ia->ia_next)
                if (ia->ia_ifp == ifp)
                        break;
@@ -76,16 +80,36 @@ ns_control(so, cmd, data, ifp)
        switch (cmd) {
 
        case SIOCGIFADDR:
        switch (cmd) {
 
        case SIOCGIFADDR:
+               if (ia == (struct ns_ifaddr *)0)
+                       return (EADDRNOTAVAIL);
+               ifr->ifr_addr = ia->ia_addr;
+               return (0);
+
+
        case SIOCGIFBRDADDR:
        case SIOCGIFBRDADDR:
+               if (ia == (struct ns_ifaddr *)0)
+                       return (EADDRNOTAVAIL);
+               if ((ifp->if_flags & IFF_BROADCAST) == 0)
+                       return (EINVAL);
+               ifr->ifr_dstaddr = ia->ia_broadaddr;
+               return (0);
+
        case SIOCGIFDSTADDR:
                if (ia == (struct ns_ifaddr *)0)
                        return (EADDRNOTAVAIL);
        case SIOCGIFDSTADDR:
                if (ia == (struct ns_ifaddr *)0)
                        return (EADDRNOTAVAIL);
-               break;
+               if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
+                       return (EINVAL);
+               ifr->ifr_dstaddr = ia->ia_dstaddr;
+               return (0);
+       }
 
 
-       case SIOCSIFDSTADDR:
-               return (EOPNOTSUPP);
+       if (!suser())
+               return (u.u_error);
+
+       switch (cmd) {
 
        case SIOCSIFADDR:
 
        case SIOCSIFADDR:
+       case SIOCSIFDSTADDR:
                if (ia == (struct ns_ifaddr *)0) {
                        m = m_getclr(M_WAIT, MT_IFADDR);
                        if (m == (struct mbuf *)NULL)
                if (ia == (struct ns_ifaddr *)0) {
                        m = m_getclr(M_WAIT, MT_IFADDR);
                        if (m == (struct mbuf *)NULL)
@@ -106,30 +130,25 @@ ns_control(so, cmd, data, ifp)
                        ia->ia_ifp = ifp;
                        IA_SNS(ia)->sns_family = AF_NS;
                }
                        ia->ia_ifp = ifp;
                        IA_SNS(ia)->sns_family = AF_NS;
                }
-               break;
        }
 
        switch (cmd) {
 
        }
 
        switch (cmd) {
 
-       case SIOCGIFADDR:
-               ifr->ifr_addr = ia->ia_addr;
-               break;
-
-       case SIOCGIFBRDADDR:
-               if (ia == (struct ns_ifaddr *)0)
-                       return (EADDRNOTAVAIL);
-               if ((ifp->if_flags & IFF_BROADCAST) == 0)
-                       return (EINVAL);
-               ifr->ifr_dstaddr = ia->ia_broadaddr;
-               break;
-
-       case SIOCGIFDSTADDR:
-               if (ia == (struct ns_ifaddr *)0)
-                       return (EADDRNOTAVAIL);
+       case SIOCSIFDSTADDR:
                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
                        return (EINVAL);
                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
                        return (EINVAL);
-               ifr->ifr_dstaddr = ia->ia_dstaddr;
-               break;
+               if (ia->ia_flags & IFA_ROUTE) {
+                       rtinit(&ia->ia_dstaddr, &ia->ia_addr,
+                               (int)SIOCDELRT, RTF_HOST);
+                       ia->ia_flags &= ~IFA_ROUTE;
+               }
+               if (ifp->if_ioctl) {
+                       int error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia);
+                       if (error)
+                               return (error);
+               }
+               ia->ia_dstaddr = ifr->ifr_dstaddr;
+               return (0);
 
        case SIOCSIFADDR:
                return
 
        case SIOCSIFADDR:
                return
@@ -140,7 +159,6 @@ ns_control(so, cmd, data, ifp)
                        return (EOPNOTSUPP);
                return ((*ifp->if_ioctl)(ifp, cmd, data));
        }
                        return (EOPNOTSUPP);
                return ((*ifp->if_ioctl)(ifp, cmd, data));
        }
-       return (0);
 }
 
 /*
 }
 
 /*
@@ -170,22 +188,23 @@ ns_ifinit(ifp, ia, sns)
        if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) {
                ns_thishost = ns_zerohost;
                splx(s);
        if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) {
                ns_thishost = ns_zerohost;
                splx(s);
-               return(EINVAL);
+               return (0);
        }
 
        /*
         * Delete any previous route for an old address.
         */
        }
 
        /*
         * Delete any previous route for an old address.
         */
-
        bzero((caddr_t)&netaddr, sizeof (netaddr));
        netaddr.sns_family = AF_NS;
        netaddr.sns_addr.x_host = ns_broadhost;
        netaddr.sns_addr.x_net = ia->ia_net;
        if (ia->ia_flags & IFA_ROUTE) {
                if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
        bzero((caddr_t)&netaddr, sizeof (netaddr));
        netaddr.sns_family = AF_NS;
        netaddr.sns_addr.x_host = ns_broadhost;
        netaddr.sns_addr.x_net = ia->ia_net;
        if (ia->ia_flags & IFA_ROUTE) {
                if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
-                   rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, -1);
+                   rtinit((struct sockaddr *)&netaddr, &ia->ia_addr,
+                                   (int)SIOCDELRT, 0);
                } else
                } else
-                   rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, -1);
+                   rtinit(&ia->ia_dstaddr, &ia->ia_addr,
+                                   (int)SIOCDELRT, RTF_HOST);
        }
 
        /*
        }
 
        /*
@@ -197,25 +216,12 @@ ns_ifinit(ifp, ia, sns)
        if (ifp->if_flags & IFF_BROADCAST) {
                ia->ia_broadaddr = * (struct sockaddr *) &netaddr;
        }
        if (ifp->if_flags & IFF_BROADCAST) {
                ia->ia_broadaddr = * (struct sockaddr *) &netaddr;
        }
-       /*
-        * Point to point links are a little touchier --
-        * We have to have an address of our own first,
-        * and will use the supplied address as that of the other end.
-        */
-       if (ifp->if_flags & IFF_POINTOPOINT) {
-               struct sockaddr_ns *sns2 = IA_SNS(ia);
-               if (ns_hosteqnh(ns_zerohost,ns_thishost))
-                       return(EINVAL);
-               ia->ia_dstaddr = ia->ia_addr;
-               sns2->sns_addr.x_host = ns_thishost;
-               sns->sns_addr.x_host = ns_thishost;
-       }
+
        /*
         * Give the interface a chance to initialize
         * if this is its first address,
         * and to validate the address if necessary.
         */
        /*
         * Give the interface a chance to initialize
         * if this is its first address,
         * and to validate the address if necessary.
         */
-
        if (ns_hosteqnh(ns_thishost, ns_zerohost)) {
                if (ifp->if_ioctl &&
                     (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
        if (ns_hosteqnh(ns_thishost, ns_zerohost)) {
                if (ifp->if_ioctl &&
                     (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
@@ -231,39 +237,55 @@ ns_ifinit(ifp, ia, sns)
                        splx(s);
                        return (error);
                }
                        splx(s);
                        return (error);
                }
-               if(!ns_hosteqnh(ns_thishost,*h)) {
+               if (!ns_hosteqnh(ns_thishost,*h)) {
                        splx(s);
                        return (EINVAL);
                }
        } else {
                splx(s);
                        splx(s);
                        return (EINVAL);
                }
        } else {
                splx(s);
-               return(EINVAL);
+               return (EINVAL);
        }
        }
+
        /*
         * Add route for the network.
         */
        /*
         * Add route for the network.
         */
-       if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
-               rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, RTF_UP);
-       } else
-               rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr,
+       if (ifp->if_flags & IFF_POINTOPOINT)
+               rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
                        RTF_HOST|RTF_UP);
                        RTF_HOST|RTF_UP);
+       else
+               rtinit(&ia->ia_broadaddr, &ia->ia_addr, (int)SIOCADDRT,
+                       RTF_UP);
        ia->ia_flags |= IFA_ROUTE;
        ia->ia_flags |= IFA_ROUTE;
-       return(0);
+       return (0);
 }
 
 /*
  * Return address info for specified internet network.
  */
 struct ns_ifaddr *
 }
 
 /*
  * Return address info for specified internet network.
  */
 struct ns_ifaddr *
-ns_iaonnetof(net)
-       union ns_net net;
+ns_iaonnetof(dst)
+       register struct ns_addr *dst;
 {
        register struct ns_ifaddr *ia;
 {
        register struct ns_ifaddr *ia;
-
-#define        NtoL(x) (*(long *)(&(x)))
-       for (ia = ns_ifaddr; ia; ia = ia->ia_next)
-               if (NtoL(ia->ia_net) == NtoL(net))
-                       return (ia);
-       return ((struct ns_ifaddr *)0);
+       register struct ns_addr *compare;
+       register struct ifnet *ifp;
+       struct ns_ifaddr *ia_maybe = 0;
+       union ns_net net = dst->x_net;
+
+       for (ia = ns_ifaddr; ia; ia = ia->ia_next) {
+               if (ifp = ia->ia_ifp) {
+                       if (ifp->if_flags & IFF_POINTOPOINT) {
+                               compare = &satons_addr(ia->ia_dstaddr);
+                               if (ns_hosteq(*dst, *compare))
+                                       return (ia);
+                               if (ns_neteqnn(net, ia->ia_net))
+                                       ia_maybe = ia;
+                       } else {
+                               if (ns_neteqnn(net, ia->ia_net))
+                                       return (ia);
+                       }
+               }
+       }
+       return (ia_maybe);
 }
 #endif
 }
 #endif