can't reset it if not set up
[unix-history] / usr / src / sys / netinet / in.c
index e026b07..5085f9e 100644 (file)
@@ -1,9 +1,9 @@
 /*
 /*
- * Copyright (c) 1982 Regents of the University of California.
+ * Copyright (c) 1982, 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.
  *
- *     @(#)in.c        6.12 (Berkeley) %G%
+ *     @(#)in.c        7.2 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -101,6 +101,7 @@ in_netof(in)
 /*
  * Return the host portion of an internet address.
  */
 /*
  * Return the host portion of an internet address.
  */
+u_long
 in_lnaof(in)
        struct in_addr in;
 {
 in_lnaof(in)
        struct in_addr in;
 {
@@ -129,9 +130,15 @@ in_lnaof(in)
        return (host);
 }
 
        return (host);
 }
 
+#ifndef SUBNETSARELOCAL
+#define        SUBNETSARELOCAL 1
+#endif
+int subnetsarelocal = SUBNETSARELOCAL;
 /*
  * Return 1 if an internet address is for a ``local'' host
 /*
  * Return 1 if an internet address is for a ``local'' host
- * (one to which we have a connection through a local logical net).
+ * (one to which we have a connection).  If subnetsarelocal
+ * is true, this includes other subnets of the local net.
+ * Otherwise, it includes only the directly-connected (sub)nets.
  */
 in_localaddr(in)
        struct in_addr in;
  */
 in_localaddr(in)
        struct in_addr in;
@@ -148,7 +155,7 @@ in_localaddr(in)
                net = i & IN_CLASSC_NET;
 
        for (ia = in_ifaddr; ia; ia = ia->ia_next)
                net = i & IN_CLASSC_NET;
 
        for (ia = in_ifaddr; ia; ia = ia->ia_next)
-               if (net == ia->ia_net)
+               if (net == (subnetsarelocal ? ia->ia_net : ia->ia_subnet))
                        return (1);
        return (0);
 }
                        return (1);
        return (0);
 }
@@ -186,6 +193,7 @@ in_control(so, cmd, data, ifp)
 
        case SIOCSIFADDR:
        case SIOCSIFNETMASK:
 
        case SIOCSIFADDR:
        case SIOCSIFNETMASK:
+       case SIOCSIFDSTADDR:
                if (!suser())
                        return (u.u_error);
 
                if (!suser())
                        return (u.u_error);
 
@@ -216,7 +224,6 @@ in_control(so, cmd, data, ifp)
                break;
 
        case SIOCSIFBRDADDR:
                break;
 
        case SIOCSIFBRDADDR:
-       case SIOCSIFDSTADDR:
                if (!suser())
                        return (u.u_error);
                /* FALLTHROUGH */
                if (!suser())
                        return (u.u_error);
                /* FALLTHROUGH */
@@ -252,12 +259,25 @@ in_control(so, cmd, data, ifp)
                break;
 
        case SIOCSIFDSTADDR:
                break;
 
        case SIOCSIFDSTADDR:
+           {
+               struct sockaddr oldaddr;
+
                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
                        return (EINVAL);
                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
                        return (EINVAL);
+               oldaddr = ia->ia_dstaddr;
+               ia->ia_dstaddr = ifr->ifr_dstaddr;
                if (ifp->if_ioctl &&
                if (ifp->if_ioctl &&
-                   (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia)))
+                   (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) {
+                       ia->ia_dstaddr = oldaddr;
                        return (error);
                        return (error);
-               ia->ia_dstaddr = ifr->ifr_dstaddr;
+               }
+               if (ia->ia_flags & IFA_ROUTE) {
+                       rtinit(&oldaddr, &ia->ia_addr, (int)SIOCDELRT,
+                           RTF_HOST);
+                       rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
+                           RTF_HOST|RTF_UP);
+               }
+           }
                break;
 
        case SIOCSIFBRDADDR:
                break;
 
        case SIOCSIFBRDADDR:
@@ -297,10 +317,11 @@ in_ifinit(ifp, ia, sin)
        struct sockaddr_in *sin;
 {
        register u_long i = ntohl(sin->sin_addr.s_addr);
        struct sockaddr_in *sin;
 {
        register u_long i = ntohl(sin->sin_addr.s_addr);
-       struct sockaddr_in tmpaddr;
+       struct sockaddr oldaddr;
+       struct sockaddr_in netaddr;
        int s = splimp(), error;
 
        int s = splimp(), error;
 
-       tmpaddr = *(struct sockaddr_in *)&ia->ia_addr;
+       oldaddr = ia->ia_addr;
        ia->ia_addr = *(struct sockaddr *)sin;
 
        /*
        ia->ia_addr = *(struct sockaddr *)sin;
 
        /*
@@ -310,23 +331,27 @@ in_ifinit(ifp, ia, sin)
         */
        if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
                splx(s);
         */
        if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
                splx(s);
-               ia->ia_addr = *(struct sockaddr *)&tmpaddr;
+               ia->ia_addr = oldaddr;
                return (error);
        }
 
                return (error);
        }
 
-       bzero((caddr_t)&tmpaddr, sizeof (tmpaddr));
-       tmpaddr.sin_family = AF_INET;
        /*
         * Delete any previous route for an old address.
         */
        /*
         * Delete any previous route for an old address.
         */
+       bzero((caddr_t)&netaddr, sizeof (netaddr));
+       netaddr.sin_family = AF_INET;
        if (ia->ia_flags & IFA_ROUTE) {
        if (ia->ia_flags & IFA_ROUTE) {
-               if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
-                   tmpaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
-                   rtinit((struct sockaddr *)&tmpaddr, &ia->ia_addr, 
+               if (ifp->if_flags & IFF_LOOPBACK)
+                       rtinit(&oldaddr, &oldaddr, (int)SIOCDELRT, RTF_HOST);
+               else if (ifp->if_flags & IFF_POINTOPOINT)
+                       rtinit(&ia->ia_dstaddr, &oldaddr, (int)SIOCDELRT,
+                           RTF_HOST);
+               else {
+                       netaddr.sin_addr = in_makeaddr(ia->ia_subnet,
+                           INADDR_ANY);
+                       rtinit((struct sockaddr *)&netaddr, &oldaddr, 
                            (int)SIOCDELRT, 0);
                            (int)SIOCDELRT, 0);
-               } else
-                   rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr,
-                           (int)SIOCDELRT, RTF_HOST);
+               }
                ia->ia_flags &= ~IFA_ROUTE;
        }
        if (IN_CLASSA(i))
                ia->ia_flags &= ~IFA_ROUTE;
        }
        if (IN_CLASSA(i))
@@ -353,13 +378,17 @@ in_ifinit(ifp, ia, sin)
        /*
         * Add route for the network.
         */
        /*
         * Add route for the network.
         */
-       if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
-               tmpaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
-               rtinit((struct sockaddr *)&tmpaddr, &ia->ia_addr,
-                       (int)SIOCADDRT, RTF_UP);
-       } else
-               rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr,
-                       (int)SIOCADDRT, RTF_HOST|RTF_UP);
+       if (ifp->if_flags & IFF_LOOPBACK)
+               rtinit(&ia->ia_addr, &ia->ia_addr, (int)SIOCADDRT,
+                   RTF_HOST|RTF_UP);
+       else if (ifp->if_flags & IFF_POINTOPOINT)
+               rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
+                   RTF_HOST|RTF_UP);
+       else {
+               netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
+               rtinit((struct sockaddr *)&netaddr, &ia->ia_addr,
+                   (int)SIOCADDRT, RTF_UP);
+       }
        ia->ia_flags |= IFA_ROUTE;
        return (0);
 }
        ia->ia_flags |= IFA_ROUTE;
        return (0);
 }