home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / netns / ns.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-27  |  9.7 KB  |  369 lines

  1. /*
  2.  * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)ns.c    7.8 (Berkeley) 6/27/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "mbuf.h"
  38. #include "ioctl.h"
  39. #include "protosw.h"
  40. #include "errno.h"
  41. #include "socket.h"
  42. #include "socketvar.h"
  43.  
  44.  
  45. #include "../net/if.h"
  46. #include "../net/route.h"
  47. #include "../net/af.h"
  48.  
  49. #include "ns.h"
  50. #include "ns_if.h"
  51.  
  52. #ifdef NS
  53.  
  54. struct ns_ifaddr *ns_ifaddr;
  55. int ns_interfaces;
  56. extern struct sockaddr_ns ns_netmask, ns_hostmask;
  57.  
  58. /*
  59.  * Generic internet control operations (ioctl's).
  60.  */
  61. /* ARGSUSED */
  62. ns_control(so, cmd, data, ifp)
  63.     struct socket *so;
  64.     int cmd;
  65.     caddr_t data;
  66.     register struct ifnet *ifp;
  67. {
  68.     register struct ifreq *ifr = (struct ifreq *)data;
  69.     register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data;
  70.     register struct ns_ifaddr *ia;
  71.     struct ifaddr *ifa;
  72.     struct ns_ifaddr *oia;
  73.     struct mbuf *m;
  74.     int error, dstIsNew, hostIsNew;
  75.  
  76.     /*
  77.      * Find address for this interface, if it exists.
  78.      */
  79.     if (ifp == 0)
  80.         return (EADDRNOTAVAIL);
  81.     for (ia = ns_ifaddr; ia; ia = ia->ia_next)
  82.         if (ia->ia_ifp == ifp)
  83.             break;
  84.  
  85.     switch (cmd) {
  86.  
  87.     case SIOCGIFADDR:
  88.         if (ia == (struct ns_ifaddr *)0)
  89.             return (EADDRNOTAVAIL);
  90.         *(struct sockaddr_ns *)&ifr->ifr_addr = ia->ia_addr;
  91.         return (0);
  92.  
  93.  
  94.     case SIOCGIFBRDADDR:
  95.         if (ia == (struct ns_ifaddr *)0)
  96.             return (EADDRNOTAVAIL);
  97.         if ((ifp->if_flags & IFF_BROADCAST) == 0)
  98.             return (EINVAL);
  99.         *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_broadaddr;
  100.         return (0);
  101.  
  102.     case SIOCGIFDSTADDR:
  103.         if (ia == (struct ns_ifaddr *)0)
  104.             return (EADDRNOTAVAIL);
  105.         if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  106.             return (EINVAL);
  107.         *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
  108.         return (0);
  109.     }
  110.  
  111.     if ((so->so_state & SS_PRIV) == 0)
  112.         return (EPERM);
  113.  
  114.     switch (cmd) {
  115.     case SIOCAIFADDR:
  116.     case SIOCDIFADDR:
  117.         if (ifra->ifra_addr.sns_family == AF_NS)
  118.             for (oia = ia; ia; ia = ia->ia_next) {
  119.             if (ia->ia_ifp == ifp  &&
  120.                 ns_neteq(ia->ia_addr.sns_addr,
  121.                   ifra->ifra_addr.sns_addr))
  122.                 break;
  123.             }
  124.         if (cmd == SIOCDIFADDR && ia == 0)
  125.             return (EADDRNOTAVAIL);
  126.         /* FALLTHROUGH */
  127.  
  128.     case SIOCSIFADDR:
  129.     case SIOCSIFDSTADDR:
  130.         if (ia == (struct ns_ifaddr *)0) {
  131.             m = m_getclr(M_WAIT, MT_IFADDR);
  132.             if (m == (struct mbuf *)NULL)
  133.                 return (ENOBUFS);
  134.             if (ia = ns_ifaddr) {
  135.                 for ( ; ia->ia_next; ia = ia->ia_next)
  136.                     ;
  137.                 ia->ia_next = mtod(m, struct ns_ifaddr *);
  138.             } else
  139.                 ns_ifaddr = mtod(m, struct ns_ifaddr *);
  140.             ia = mtod(m, struct ns_ifaddr *);
  141.             if (ifa = ifp->if_addrlist) {
  142.                 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
  143.                     ;
  144.                 ifa->ifa_next = (struct ifaddr *) ia;
  145.             } else
  146.                 ifp->if_addrlist = (struct ifaddr *) ia;
  147.             ia->ia_ifp = ifp;
  148.             ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
  149.  
  150.             ia->ia_ifa.ifa_netmask =
  151.                 (struct sockaddr *)&ns_netmask;
  152.  
  153.             ia->ia_ifa.ifa_dstaddr =
  154.                 (struct sockaddr *)&ia->ia_dstaddr;
  155.             if (ifp->if_flags & IFF_BROADCAST) {
  156.                 ia->ia_broadaddr.sns_family = AF_NS;
  157.                 ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr);
  158.                 ia->ia_broadaddr.sns_addr.x_host = ns_broadhost;
  159.             }
  160.             ns_interfaces++;
  161.         }
  162.     }
  163.  
  164.     switch (cmd) {
  165.         int error;
  166.  
  167.     case SIOCSIFDSTADDR:
  168.         if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  169.             return (EINVAL);
  170.         if (ia->ia_flags & IFA_ROUTE) {
  171.             rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  172.             ia->ia_flags &= ~IFA_ROUTE;
  173.         }
  174.         if (ifp->if_ioctl) {
  175.             error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia);
  176.             if (error)
  177.                 return (error);
  178.         }
  179.         *(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr;
  180.         return (0);
  181.  
  182.     case SIOCSIFADDR:
  183.         return (ns_ifinit(ifp, ia,
  184.                 (struct sockaddr_ns *)&ifr->ifr_addr, 1));
  185.  
  186.     case SIOCDIFADDR:
  187.         ns_ifscrub(ifp, ia);
  188.         if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
  189.             ifp->if_addrlist = ifa->ifa_next;
  190.         else {
  191.             while (ifa->ifa_next &&
  192.                    (ifa->ifa_next != (struct ifaddr *)ia))
  193.                     ifa = ifa->ifa_next;
  194.             if (ifa->ifa_next)
  195.                 ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
  196.             else
  197.                 printf("Couldn't unlink nsifaddr from ifp\n");
  198.         }
  199.         oia = ia;
  200.         if (oia == (ia = ns_ifaddr)) {
  201.             ns_ifaddr = ia->ia_next;
  202.         } else {
  203.             while (ia->ia_next && (ia->ia_next != oia)) {
  204.                 ia = ia->ia_next;
  205.             }
  206.             if (ia->ia_next)
  207.                 ia->ia_next = oia->ia_next;
  208.             else
  209.                 printf("Didn't unlink nsifadr from list\n");
  210.         }
  211.         (void) m_free(dtom(oia));
  212.         if (0 == --ns_interfaces) {
  213.             /*
  214.              * We reset to virginity and start all over again
  215.              */
  216.             ns_thishost = ns_zerohost;
  217.         }
  218.         return (0);
  219.     
  220.     case SIOCAIFADDR:
  221.         dstIsNew = 0; hostIsNew = 1;
  222.         if (ia->ia_addr.sns_family == AF_NS) {
  223.             if (ifra->ifra_addr.sns_len == 0) {
  224.                 ifra->ifra_addr = ia->ia_addr;
  225.                 hostIsNew = 0;
  226.             } else if (ns_neteq(ifra->ifra_addr.sns_addr,
  227.                      ia->ia_addr.sns_addr))
  228.                 hostIsNew = 0;
  229.         }
  230.         if ((ifp->if_flags & IFF_POINTOPOINT) &&
  231.             (ifra->ifra_dstaddr.sns_family == AF_NS)) {
  232.             if (hostIsNew == 0)
  233.                 ns_ifscrub(ifp, ia);
  234.             ia->ia_dstaddr = ifra->ifra_dstaddr;
  235.             dstIsNew  = 1;
  236.         }
  237.         if (ifra->ifra_addr.sns_family == AF_NS &&
  238.                         (hostIsNew || dstIsNew))
  239.             error = ns_ifinit(ifp, ia, &ifra->ifra_addr, 0);
  240.         return (error);
  241.  
  242.     default:
  243.         if (ifp->if_ioctl == 0)
  244.             return (EOPNOTSUPP);
  245.         return ((*ifp->if_ioctl)(ifp, cmd, data));
  246.     }
  247. }
  248.  
  249. /*
  250. * Delete any previous route for an old address.
  251. */
  252. ns_ifscrub(ifp, ia)
  253.     register struct ifnet *ifp;
  254.     register struct ns_ifaddr *ia; 
  255. {
  256.     if (ia->ia_flags & IFA_ROUTE) {
  257.         if (ifp->if_flags & IFF_POINTOPOINT) {
  258.             rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  259.         } else
  260.             rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
  261.         ia->ia_flags &= ~IFA_ROUTE;
  262.     }
  263. }
  264. /*
  265.  * Initialize an interface's internet address
  266.  * and routing table entry.
  267.  */
  268. ns_ifinit(ifp, ia, sns, scrub)
  269.     register struct ifnet *ifp;
  270.     register struct ns_ifaddr *ia;
  271.     register struct sockaddr_ns *sns;
  272. {
  273.     struct sockaddr_ns oldaddr;
  274.     register union ns_host *h = &ia->ia_addr.sns_addr.x_host;
  275.     int s = splimp(), error;
  276.  
  277.     /*
  278.      * Set up new addresses.
  279.      */
  280.     oldaddr = ia->ia_addr;
  281.     ia->ia_addr = *sns;
  282.     /*
  283.      * The convention we shall adopt for naming is that
  284.      * a supplied address of zero means that "we don't care".
  285.      * if there is a single interface, use the address of that
  286.      * interface as our 6 byte host address.
  287.      * if there are multiple interfaces, use any address already
  288.      * used.
  289.      *
  290.      * Give the interface a chance to initialize
  291.      * if this is its first address,
  292.      * and to validate the address if necessary.
  293.      */
  294.     if (ns_hosteqnh(ns_thishost, ns_zerohost)) {
  295.         if (ifp->if_ioctl &&
  296.              (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
  297.             ia->ia_addr = oldaddr;
  298.             splx(s);
  299.             return (error);
  300.         }
  301.         ns_thishost = *h;
  302.     } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost)
  303.         || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) {
  304.         *h = ns_thishost;
  305.         if (ifp->if_ioctl &&
  306.              (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
  307.             ia->ia_addr = oldaddr;
  308.             splx(s);
  309.             return (error);
  310.         }
  311.         if (!ns_hosteqnh(ns_thishost,*h)) {
  312.             ia->ia_addr = oldaddr;
  313.             splx(s);
  314.             return (EINVAL);
  315.         }
  316.     } else {
  317.         ia->ia_addr = oldaddr;
  318.         splx(s);
  319.         return (EINVAL);
  320.     }
  321.     /*
  322.      * Add route for the network.
  323.      */
  324.     if (scrub) {
  325.         ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
  326.         ns_ifscrub(ifp, ia);
  327.         ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
  328.     }
  329.     if (ifp->if_flags & IFF_POINTOPOINT)
  330.         rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
  331.     else {
  332.         ia->ia_broadaddr.sns_addr.x_net = ia->ia_net;
  333.         rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
  334.     }
  335.     ia->ia_flags |= IFA_ROUTE;
  336.     return (0);
  337. }
  338.  
  339. /*
  340.  * Return address info for specified internet network.
  341.  */
  342. struct ns_ifaddr *
  343. ns_iaonnetof(dst)
  344.     register struct ns_addr *dst;
  345. {
  346.     register struct ns_ifaddr *ia;
  347.     register struct ns_addr *compare;
  348.     register struct ifnet *ifp;
  349.     struct ns_ifaddr *ia_maybe = 0;
  350.     union ns_net net = dst->x_net;
  351.  
  352.     for (ia = ns_ifaddr; ia; ia = ia->ia_next) {
  353.         if (ifp = ia->ia_ifp) {
  354.             if (ifp->if_flags & IFF_POINTOPOINT) {
  355.                 compare = &satons_addr(ia->ia_dstaddr);
  356.                 if (ns_hosteq(*dst, *compare))
  357.                     return (ia);
  358.                 if (ns_neteqnn(net, ia->ia_net))
  359.                     ia_maybe = ia;
  360.             } else {
  361.                 if (ns_neteqnn(net, ia->ia_net))
  362.                     return (ia);
  363.             }
  364.         }
  365.     }
  366.     return (ia_maybe);
  367. }
  368. #endif
  369.