home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / os / bsdss4.tz / bsdss4 / bsdss / server / netinet / in.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-22  |  16.2 KB  |  636 lines

  1. /* 
  2.  * Mach Operating System
  3.  * Copyright (c) 1992 Carnegie Mellon University
  4.  * All Rights Reserved.
  5.  * 
  6.  * Permission to use, copy, modify and distribute this software and its
  7.  * documentation is hereby granted, provided that both the copyright
  8.  * notice and this permission notice appear in all copies of the
  9.  * software, derivative works or modified versions, and any portions
  10.  * thereof, and that both notices appear in supporting documentation.
  11.  * 
  12.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15.  * 
  16.  * Carnegie Mellon requests users of this software to return to
  17.  * 
  18.  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  19.  *  School of Computer Science
  20.  *  Carnegie Mellon University
  21.  *  Pittsburgh PA 15213-3890
  22.  * 
  23.  * any improvements or extensions that they make and grant Carnegie Mellon 
  24.  * the rights to redistribute these changes.
  25.  */
  26. /*
  27.  * HISTORY
  28.  * $Log:    in.c,v $
  29.  * Revision 2.1  92/04/21  17:14:21  rwd
  30.  * BSDSS
  31.  * 
  32.  *
  33.  */
  34.  
  35. /*
  36.  * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
  37.  * All rights reserved.
  38.  *
  39.  * Redistribution and use in source and binary forms, with or without
  40.  * modification, are permitted provided that the following conditions
  41.  * are met:
  42.  * 1. Redistributions of source code must retain the above copyright
  43.  *    notice, this list of conditions and the following disclaimer.
  44.  * 2. Redistributions in binary form must reproduce the above copyright
  45.  *    notice, this list of conditions and the following disclaimer in the
  46.  *    documentation and/or other materials provided with the distribution.
  47.  * 3. All advertising materials mentioning features or use of this software
  48.  *    must display the following acknowledgement:
  49.  *    This product includes software developed by the University of
  50.  *    California, Berkeley and its contributors.
  51.  * 4. Neither the name of the University nor the names of its contributors
  52.  *    may be used to endorse or promote products derived from this software
  53.  *    without specific prior written permission.
  54.  *
  55.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  56.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  57.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  58.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  59.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  60.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  61.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  62.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  63.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  64.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  65.  * SUCH DAMAGE.
  66.  *
  67.  *    @(#)in.c    7.17 (Berkeley) 4/20/91
  68.  */
  69.  
  70. #include <inet.h>
  71.  
  72. #include <sys/param.h>
  73. #include <sys/ioctl.h>
  74. #include <sys/mbuf.h>
  75. #include <sys/socket.h>
  76. #include <sys/socketvar.h>
  77. #include <sys/synch.h>
  78.  
  79. #include <netinet/in_systm.h>
  80. #include <net/if.h>
  81. #include <net/route.h>
  82. #include <net/af.h>
  83. #include <netinet/in.h>
  84. #include <netinet/in_var.h>
  85.  
  86. #if INET
  87. /*
  88.  * Formulate an Internet address from network + host.
  89.  */
  90. struct in_addr
  91. in_makeaddr(net, host)
  92.     u_long net, host;
  93. {
  94.     register struct in_ifaddr *ia;
  95.     register u_long mask;
  96.     u_long addr;
  97.  
  98.     if (IN_CLASSA(net))
  99.         mask = IN_CLASSA_HOST;
  100.     else if (IN_CLASSB(net))
  101.         mask = IN_CLASSB_HOST;
  102.     else
  103.         mask = IN_CLASSC_HOST;
  104.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  105.         if ((ia->ia_netmask & net) == ia->ia_net) {
  106.             mask = ~ia->ia_subnetmask;
  107.             break;
  108.         }
  109.     addr = htonl(net | (host & mask));
  110.     return (*(struct in_addr *)&addr);
  111. }
  112.  
  113. /*
  114.  * Return the network number from an internet address.
  115.  */
  116. u_long
  117. in_netof(in)
  118.     struct in_addr in;
  119. {
  120.     register u_long i = ntohl(in.s_addr);
  121.     register u_long net;
  122.     register struct in_ifaddr *ia;
  123.  
  124.     if (IN_CLASSA(i))
  125.         net = i & IN_CLASSA_NET;
  126.     else if (IN_CLASSB(i))
  127.         net = i & IN_CLASSB_NET;
  128.     else if (IN_CLASSC(i))
  129.         net = i & IN_CLASSC_NET;
  130.     else
  131.         return (0);
  132.  
  133.     /*
  134.      * Check whether network is a subnet;
  135.      * if so, return subnet number.
  136.      */
  137.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  138.         if (net == ia->ia_net)
  139.             return (i & ia->ia_subnetmask);
  140.     return (net);
  141. }
  142.  
  143. /*
  144.  * Compute and save network mask as sockaddr from an internet address.
  145.  */
  146. in_sockmaskof(in, sockmask)
  147.     struct in_addr in;
  148.     register struct sockaddr_in *sockmask;
  149. {
  150.     register u_long net;
  151.     register u_long mask;
  152.     {
  153.     register u_long i = ntohl(in.s_addr);
  154.  
  155.     if (i == 0)
  156.         net = 0, mask = 0;
  157.     else if (IN_CLASSA(i))
  158.         net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET;
  159.     else if (IN_CLASSB(i))
  160.         net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET;
  161.     else if (IN_CLASSC(i))
  162.         net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET;
  163.     else
  164.         net = i, mask = -1;
  165.     }
  166.     {
  167.     register struct in_ifaddr *ia;
  168.     /*
  169.      * Check whether network is a subnet;
  170.      * if so, return subnet number.
  171.      */
  172.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  173.         if (net == ia->ia_net)
  174.             mask =  ia->ia_subnetmask;
  175.     }
  176.     {
  177.     register char *cpbase = (char *)&(sockmask->sin_addr);
  178.     register char *cp = (char *)(1 + &(sockmask->sin_addr));
  179.  
  180.     sockmask->sin_addr.s_addr = htonl(mask);
  181.     sockmask->sin_len = 0;
  182.     while (--cp >= cpbase)
  183.         if (*cp) {
  184.             sockmask->sin_len = 1 + cp - (caddr_t)sockmask;
  185.             break;
  186.         }
  187.     }
  188. }
  189.  
  190. /*
  191.  * Return the host portion of an internet address.
  192.  */
  193. u_long
  194. in_lnaof(in)
  195.     struct in_addr in;
  196. {
  197.     register u_long i = ntohl(in.s_addr);
  198.     register u_long net, host;
  199.     register struct in_ifaddr *ia;
  200.  
  201.     if (IN_CLASSA(i)) {
  202.         net = i & IN_CLASSA_NET;
  203.         host = i & IN_CLASSA_HOST;
  204.     } else if (IN_CLASSB(i)) {
  205.         net = i & IN_CLASSB_NET;
  206.         host = i & IN_CLASSB_HOST;
  207.     } else if (IN_CLASSC(i)) {
  208.         net = i & IN_CLASSC_NET;
  209.         host = i & IN_CLASSC_HOST;
  210.     } else
  211.         return (i);
  212.  
  213.     /*
  214.      * Check whether network is a subnet;
  215.      * if so, use the modified interpretation of `host'.
  216.      */
  217.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  218.         if (net == ia->ia_net)
  219.             return (host &~ ia->ia_subnetmask);
  220.     return (host);
  221. }
  222.  
  223. #ifndef SUBNETSARELOCAL
  224. #define    SUBNETSARELOCAL    1
  225. #endif
  226. int subnetsarelocal = SUBNETSARELOCAL;
  227. /*
  228.  * Return 1 if an internet address is for a ``local'' host
  229.  * (one to which we have a connection).  If subnetsarelocal
  230.  * is true, this includes other subnets of the local net.
  231.  * Otherwise, it includes only the directly-connected (sub)nets.
  232.  */
  233. in_localaddr(in)
  234.     struct in_addr in;
  235. {
  236.     register u_long i = ntohl(in.s_addr);
  237.     register struct in_ifaddr *ia;
  238.  
  239.     if (subnetsarelocal) {
  240.         for (ia = in_ifaddr; ia; ia = ia->ia_next)
  241.             if ((i & ia->ia_netmask) == ia->ia_net)
  242.                 return (1);
  243.     } else {
  244.         for (ia = in_ifaddr; ia; ia = ia->ia_next)
  245.             if ((i & ia->ia_subnetmask) == ia->ia_subnet)
  246.                 return (1);
  247.     }
  248.     return (0);
  249. }
  250.  
  251. /*
  252.  * Determine whether an IP address is in a reserved set of addresses
  253.  * that may not be forwarded, or whether datagrams to that destination
  254.  * may be forwarded.
  255.  */
  256. in_canforward(in)
  257.     struct in_addr in;
  258. {
  259.     register u_long i = ntohl(in.s_addr);
  260.     register u_long net;
  261.  
  262.     if (IN_EXPERIMENTAL(i))
  263.         return (0);
  264.     if (IN_CLASSA(i)) {
  265.         net = i & IN_CLASSA_NET;
  266.         if (net == 0 || net == IN_LOOPBACKNET)
  267.             return (0);
  268.     }
  269.     return (1);
  270. }
  271.  
  272. int    in_interfaces;        /* number of external internet interfaces */
  273. extern    struct ifnet loif;
  274.  
  275. /*
  276.  * Generic internet control operations (ioctl's).
  277.  * Ifp is 0 if not an interface-specific ioctl.
  278.  */
  279. /* ARGSUSED */
  280. in_control(so, cmd, data, ifp)
  281.     struct socket *so;
  282.     int cmd;
  283.     caddr_t data;
  284.     register struct ifnet *ifp;
  285. {
  286.     register struct ifreq *ifr = (struct ifreq *)data;
  287.     register struct in_ifaddr *ia = 0;
  288.     register struct ifaddr *ifa;
  289.     struct in_ifaddr *oia;
  290.     struct in_aliasreq *ifra = (struct in_aliasreq *)data;
  291.     struct mbuf *m;
  292.     struct sockaddr_in oldaddr;
  293.     int error, hostIsNew, maskIsNew;
  294.     u_long i;
  295.  
  296.     /*
  297.      * Find address for this interface, if it exists.
  298.      */
  299.     if (ifp)
  300.         for (ia = in_ifaddr; ia; ia = ia->ia_next)
  301.             if (ia->ia_ifp == ifp)
  302.                 break;
  303.  
  304.     switch (cmd) {
  305.  
  306.     case SIOCAIFADDR:
  307.     case SIOCDIFADDR:
  308.         if (ifra->ifra_addr.sin_family == AF_INET)
  309.             for (oia = ia; ia; ia = ia->ia_next) {
  310.             if (ia->ia_ifp == ifp  &&
  311.                 ia->ia_addr.sin_addr.s_addr ==
  312.                 ifra->ifra_addr.sin_addr.s_addr)
  313.                 break;
  314.         }
  315.         if (cmd == SIOCDIFADDR && ia == 0)
  316.             return (EADDRNOTAVAIL);
  317.         /* FALLTHROUGH */
  318.     case SIOCSIFADDR:
  319.     case SIOCSIFNETMASK:
  320.     case SIOCSIFDSTADDR:
  321.         if ((so->so_state & SS_PRIV) == 0)
  322.             return (EPERM);
  323.  
  324.         if (ifp == 0)
  325.             panic("in_control");
  326.         if (ia == (struct in_ifaddr *)0) {
  327.             m = m_getclr(M_WAIT, MT_IFADDR);
  328.             if (m == (struct mbuf *)NULL)
  329.                 return (ENOBUFS);
  330.             if (ia = in_ifaddr) {
  331.                 for ( ; ia->ia_next; ia = ia->ia_next)
  332.                     ;
  333.                 ia->ia_next = mtod(m, struct in_ifaddr *);
  334.             } else
  335.                 in_ifaddr = mtod(m, struct in_ifaddr *);
  336.             ia = mtod(m, struct in_ifaddr *);
  337.             if (ifa = ifp->if_addrlist) {
  338.                 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
  339.                     ;
  340.                 ifa->ifa_next = (struct ifaddr *) ia;
  341.             } else
  342.                 ifp->if_addrlist = (struct ifaddr *) ia;
  343.             ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
  344.             ia->ia_ifa.ifa_dstaddr
  345.                     = (struct sockaddr *)&ia->ia_dstaddr;
  346.             ia->ia_ifa.ifa_netmask
  347.                     = (struct sockaddr *)&ia->ia_sockmask;
  348.             ia->ia_sockmask.sin_len = 8;
  349.             if (ifp->if_flags & IFF_BROADCAST) {
  350.                 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
  351.                 ia->ia_broadaddr.sin_family = AF_INET;
  352.             }
  353.             ia->ia_ifp = ifp;
  354.             if (ifp != &loif)
  355.                 in_interfaces++;
  356.         }
  357.         break;
  358.  
  359.     case SIOCSIFBRDADDR:
  360.         if ((so->so_state & SS_PRIV) == 0)
  361.             return (EPERM);
  362.         /* FALLTHROUGH */
  363.  
  364.     case SIOCGIFADDR:
  365.     case SIOCGIFNETMASK:
  366.     case SIOCGIFDSTADDR:
  367.     case SIOCGIFBRDADDR:
  368.         if (ia == (struct in_ifaddr *)0)
  369.             return (EADDRNOTAVAIL);
  370.         break;
  371.  
  372.     default:
  373.         return (EOPNOTSUPP);
  374.         break;
  375.     }
  376.     switch (cmd) {
  377.  
  378.     case SIOCGIFADDR:
  379.         *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
  380.         break;
  381.  
  382.     case SIOCGIFBRDADDR:
  383.         if ((ifp->if_flags & IFF_BROADCAST) == 0)
  384.             return (EINVAL);
  385.         *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
  386.         break;
  387.  
  388.     case SIOCGIFDSTADDR:
  389.         if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  390.             return (EINVAL);
  391.         *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
  392.         break;
  393.  
  394.     case SIOCGIFNETMASK:
  395.         *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
  396.         break;
  397.  
  398.     case SIOCSIFDSTADDR:
  399.         if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  400.             return (EINVAL);
  401.         oldaddr = ia->ia_dstaddr;
  402.         ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
  403.         if (ifp->if_ioctl &&
  404.             (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) {
  405.             ia->ia_dstaddr = oldaddr;
  406.             return (error);
  407.         }
  408.         if (ia->ia_flags & IFA_ROUTE) {
  409.             ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
  410.             rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  411.             ia->ia_ifa.ifa_dstaddr =
  412.                     (struct sockaddr *)&ia->ia_dstaddr;
  413.             rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
  414.         }
  415.         break;
  416.  
  417.     case SIOCSIFBRDADDR:
  418.         if ((ifp->if_flags & IFF_BROADCAST) == 0)
  419.             return (EINVAL);
  420.         ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
  421.         break;
  422.  
  423.     case SIOCSIFADDR:
  424.         return (in_ifinit(ifp, ia,
  425.             (struct sockaddr_in *) &ifr->ifr_addr, 1));
  426.  
  427.     case SIOCSIFNETMASK:
  428.         i = ifra->ifra_addr.sin_addr.s_addr;
  429.         ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
  430.         break;
  431.  
  432.     case SIOCAIFADDR:
  433.         maskIsNew = 0;
  434.         hostIsNew = 1;
  435.         error = 0;
  436.         if (ia->ia_addr.sin_family == AF_INET) {
  437.             if (ifra->ifra_addr.sin_len == 0) {
  438.                 ifra->ifra_addr = ia->ia_addr;
  439.                 hostIsNew = 0;
  440.             } else if (ifra->ifra_addr.sin_addr.s_addr ==
  441.                            ia->ia_addr.sin_addr.s_addr)
  442.                 hostIsNew = 0;
  443.         }
  444.         if (ifra->ifra_mask.sin_len) {
  445.             in_ifscrub(ifp, ia);
  446.             ia->ia_sockmask = ifra->ifra_mask;
  447.             ia->ia_subnetmask =
  448.                  ntohl(ia->ia_sockmask.sin_addr.s_addr);
  449.             maskIsNew = 1;
  450.         }
  451.         if ((ifp->if_flags & IFF_POINTOPOINT) &&
  452.             (ifra->ifra_dstaddr.sin_family == AF_INET)) {
  453.             in_ifscrub(ifp, ia);
  454.             ia->ia_dstaddr = ifra->ifra_dstaddr;
  455.             maskIsNew  = 1; /* We lie; but the effect's the same */
  456.         }
  457.         if (ifra->ifra_addr.sin_family == AF_INET &&
  458.             (hostIsNew || maskIsNew))
  459.             error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
  460.         if ((ifp->if_flags & IFF_BROADCAST) &&
  461.             (ifra->ifra_broadaddr.sin_family == AF_INET))
  462.             ia->ia_broadaddr = ifra->ifra_broadaddr;
  463.         return (error);
  464.  
  465.     case SIOCDIFADDR:
  466.         in_ifscrub(ifp, ia);
  467.         if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
  468.             ifp->if_addrlist = ifa->ifa_next;
  469.         else {
  470.             while (ifa->ifa_next &&
  471.                    (ifa->ifa_next != (struct ifaddr *)ia))
  472.                     ifa = ifa->ifa_next;
  473.             if (ifa->ifa_next)
  474.                 ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
  475.             else
  476.                 printf("Couldn't unlink inifaddr from ifp\n");
  477.         }
  478.         oia = ia;
  479.         if (oia == (ia = in_ifaddr))
  480.             in_ifaddr = ia->ia_next;
  481.         else {
  482.             while (ia->ia_next && (ia->ia_next != oia))
  483.                 ia = ia->ia_next;
  484.             if (ia->ia_next)
  485.                 ia->ia_next = oia->ia_next;
  486.             else
  487.                 printf("Didn't unlink inifadr from list\n");
  488.         }
  489.         (void) m_free(dtom(oia));
  490.         break;
  491.  
  492.     default:
  493.         if (ifp == 0 || ifp->if_ioctl == 0)
  494.             return (EOPNOTSUPP);
  495.         return ((*ifp->if_ioctl)(ifp, cmd, data));
  496.     }
  497.     return (0);
  498. }
  499.  
  500. /*
  501.  * Delete any existing route for an interface.
  502.  */
  503. in_ifscrub(ifp, ia)
  504.     register struct ifnet *ifp;
  505.     register struct in_ifaddr *ia;
  506. {
  507.  
  508.     if ((ia->ia_flags & IFA_ROUTE) == 0)
  509.         return;
  510.     if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
  511.         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  512.     else
  513.         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
  514.     ia->ia_flags &= ~IFA_ROUTE;
  515. }
  516.  
  517. /*
  518.  * Initialize an interface's internet address
  519.  * and routing table entry.
  520.  */
  521. in_ifinit(ifp, ia, sin, scrub)
  522.     register struct ifnet *ifp;
  523.     register struct in_ifaddr *ia;
  524.     struct sockaddr_in *sin;
  525. {
  526.     register u_long i = ntohl(sin->sin_addr.s_addr);
  527.     struct sockaddr_in oldaddr;
  528.     int s = splimp(), error, flags = RTF_UP;
  529.  
  530.     oldaddr = ia->ia_addr;
  531.     ia->ia_addr = *sin;
  532.     /*
  533.      * Give the interface a chance to initialize
  534.      * if this is its first address,
  535.      * and to validate the address if necessary.
  536.      */
  537.     if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
  538.         splx(s);
  539.         ia->ia_addr = oldaddr;
  540.         return (error);
  541.     }
  542.     splx(s);
  543.     if (scrub) {
  544.         ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
  545.         in_ifscrub(ifp, ia);
  546.         ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
  547.     }
  548.     if (IN_CLASSA(i))
  549.         ia->ia_netmask = IN_CLASSA_NET;
  550.     else if (IN_CLASSB(i))
  551.         ia->ia_netmask = IN_CLASSB_NET;
  552.     else
  553.         ia->ia_netmask = IN_CLASSC_NET;
  554.     ia->ia_net = i & ia->ia_netmask;
  555.     /*
  556.      * The subnet mask includes at least the standard network part,
  557.      * but may already have been set to a larger value.
  558.      */
  559.     ia->ia_subnetmask |= ia->ia_netmask;
  560.     ia->ia_subnet = i & ia->ia_subnetmask;
  561.     ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
  562.     {
  563.         register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr));
  564.         register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr);
  565.         while (--cp >= cpbase)
  566.             if (*cp) {
  567.                 ia->ia_sockmask.sin_len =
  568.                     1 + cp - (char *) &(ia->ia_sockmask);
  569.                 break;
  570.             }
  571.     }
  572.     /*
  573.      * Add route for the network.
  574.      */
  575.     if (ifp->if_flags & IFF_BROADCAST) {
  576.         ia->ia_broadaddr.sin_addr = 
  577.             in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
  578.         ia->ia_netbroadcast.s_addr =
  579.             htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
  580.     } else if (ifp->if_flags & IFF_LOOPBACK) {
  581.         ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
  582.         flags |= RTF_HOST;
  583.     } else if (ifp->if_flags & IFF_POINTOPOINT) {
  584.         if (ia->ia_dstaddr.sin_family != AF_INET)
  585.             return (0);
  586.         flags |= RTF_HOST;
  587.     }
  588.     if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
  589.         ia->ia_flags |= IFA_ROUTE;
  590.     return (error);
  591. }
  592.  
  593. /*
  594.  * Return address info for specified internet network.
  595.  */
  596. struct in_ifaddr *
  597. in_iaonnetof(net)
  598.     u_long net;
  599. {
  600.     register struct in_ifaddr *ia;
  601.  
  602.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  603.         if (ia->ia_subnet == net)
  604.             return (ia);
  605.     return ((struct in_ifaddr *)0);
  606. }
  607.  
  608. /*
  609.  * Return 1 if the address might be a local broadcast address.
  610.  */
  611. in_broadcast(in)
  612.     struct in_addr in;
  613. {
  614.     register struct in_ifaddr *ia;
  615.     u_long t;
  616.  
  617.     /*
  618.      * Look through the list of addresses for a match
  619.      * with a broadcast address.
  620.      */
  621.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  622.         if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
  623.         if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr)
  624.              return (1);
  625.         /*
  626.          * Check for old-style (host 0) broadcast.
  627.          */
  628.         if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net)
  629.             return (1);
  630.     }
  631.     if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY)
  632.         return (1);
  633.     return (0);
  634. }
  635. #endif
  636.