home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / netiso / iso_snpac.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-29  |  20.5 KB  |  734 lines

  1. /*-
  2.  * Copyright (c) 1991 The 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.  *    @(#)iso_snpac.c    7.14 (Berkeley) 6/27/91
  34.  */
  35.  
  36. /***********************************************************
  37.         Copyright IBM Corporation 1987
  38.  
  39.                       All Rights Reserved
  40.  
  41. Permission to use, copy, modify, and distribute this software and its 
  42. documentation for any purpose and without fee is hereby granted, 
  43. provided that the above copyright notice appear in all copies and that
  44. both that copyright notice and this permission notice appear in 
  45. supporting documentation, and that the name of IBM not be
  46. used in advertising or publicity pertaining to distribution of the
  47. software without specific, written prior permission.  
  48.  
  49. IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  50. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  51. IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  52. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  53. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  54. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  55. SOFTWARE.
  56.  
  57. ******************************************************************/
  58.  
  59. /*
  60.  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
  61.  */
  62. /* $Header: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $ */
  63. /* $Source: /usr/argo/sys/netiso/RCS/iso_snpac.c,v $ */
  64.  
  65. #ifdef ISO
  66.  
  67. #include "types.h"
  68. #include "param.h"
  69. #include "systm.h"
  70. #include "mbuf.h"
  71. #include "domain.h"
  72. #include "protosw.h"
  73. #include "socket.h"
  74. #include "socketvar.h"
  75. #include "errno.h"
  76. #include "ioctl.h"
  77. #include "syslog.h"
  78.  
  79. #include "../net/if.h"
  80. #include "../net/if_dl.h"
  81. #include "../net/route.h"
  82.  
  83. #include "iso.h"
  84. #include "iso_var.h"
  85. #include "iso_snpac.h"
  86. #include "clnp.h"
  87. #include "clnp_stat.h"
  88. #include "esis.h"
  89. #include "argo_debug.h"
  90.  
  91. int                 iso_systype = SNPA_ES;    /* default to be an ES */
  92. extern short    esis_holding_time, esis_config_time, esis_esconfig_time;
  93. extern struct    timeval time;
  94. extern int esis_config(), hz;
  95. static void snpac_fixdstandmask();
  96.  
  97. struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO};
  98. extern u_long iso_hashchar();
  99. static struct sockaddr_iso
  100.     dst    = {sizeof(dst), AF_ISO},
  101.     gte    = {sizeof(dst), AF_ISO},
  102.     src    = {sizeof(dst), AF_ISO},
  103.     msk    = {sizeof(dst), AF_ISO},
  104.     zmk = {1};
  105. #define zsi blank_siso
  106. #define zero_isoa    zsi.siso_addr
  107. #define zap_isoaddr(a, b) {Bzero(&a.siso_addr, sizeof(*r)); r = b; \
  108.        Bcopy(r, &a.siso_addr, 1 + (r)->isoa_len);}
  109. #define S(x) ((struct sockaddr *)&(x))
  110.  
  111. static struct sockaddr_dl blank_dl = {sizeof(blank_dl), AF_LINK};
  112. static struct sockaddr_dl gte_dl;
  113. #define zap_linkaddr(a, b, c, i) \
  114.     (*a = blank_dl, bcopy(b, a->sdl_data, a->sdl_alen = c), a->sdl_index = i)
  115.  
  116. /*
  117.  *    We only keep track of a single IS at a time.
  118.  */
  119. struct rtentry    *known_is;
  120.  
  121. /*
  122.  *    Addresses taken from NBS agreements, December 1987.
  123.  *
  124.  *    These addresses assume on-the-wire transmission of least significant
  125.  *    bit first. This is the method used by 802.3. When these
  126.  *    addresses are passed to the token ring driver, (802.5), they
  127.  *    must be bit-swaped because 802.5 transmission order is MSb first.
  128.  *
  129.  *    Furthermore, according to IBM Austin, these addresses are not
  130.  *    true token ring multicast addresses. More work is necessary
  131.  *    to get multicast to work right on token ring.
  132.  *
  133.  *    Currently, the token ring driver does not handle multicast, so
  134.  *    these addresses are converted into the broadcast address in
  135.  *    lan_output() That means that if these multicast addresses change
  136.  *    the token ring driver must be altered.
  137.  */
  138. char all_es_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 };
  139. char all_is_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 };
  140. char all_l1is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14};
  141. char all_l2is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x15};
  142.  
  143. union sockunion {
  144.     struct sockaddr_iso siso;
  145.     struct sockaddr_dl    sdl;
  146.     struct sockaddr        sa;
  147. };
  148.  
  149. /*
  150.  * FUNCTION:        llc_rtrequest
  151.  *
  152.  * PURPOSE:            Manage routing table entries specific to LLC for ISO.
  153.  *
  154.  * NOTES:            This does a lot of obscure magic;
  155.  */
  156. llc_rtrequest(req, rt, sa)
  157. int req;
  158. register struct rtentry *rt;
  159. struct sockaddr *sa;
  160. {
  161.     register union sockunion *gate = (union sockunion *)rt->rt_gateway;
  162.     register struct llinfo_llc *lc = (struct llinfo_llc *)rt->rt_llinfo, *lc2;
  163.     struct rtentry *rt2;
  164.     struct ifnet *ifp = rt->rt_ifp;
  165.     int addrlen = ifp->if_addrlen;
  166.     static struct rtentry *recursing = 0;
  167. #define LLC_SIZE 3 /* XXXXXX do this right later */
  168.  
  169.     IFDEBUG (D_SNPA)
  170.         printf("llc_rtrequest(%d, %x, %x)\n", req, rt, sa);
  171.     ENDDEBUG
  172.     if (rt->rt_flags & RTF_GATEWAY) {
  173.         if (recursing) {
  174.             log(LOG_DEBUG, "llc_rtrequest: gateway route points to same type %x %x\n",
  175.                 recursing, rt);
  176.         } else switch (req) {
  177.         case RTM_RESOLVE:
  178.         case RTM_ADD:
  179.             recursing = rt;
  180.             rt->rt_llinfo = (caddr_t)rtalloc1(&gate->sa, 1);
  181.             recursing = 0;
  182.             if (rt->rt_rmx.rmx_mtu == 0) {
  183.                 rt->rt_rmx.rmx_mtu =
  184.                     ((rt2 = (struct rtentry *)rt->rt_llinfo) &&
  185.                         (rt2->rt_rmx.rmx_mtu)) ?
  186.                     rt2->rt_rmx.rmx_mtu :
  187.                     rt->rt_ifp->if_mtu - LLC_SIZE;
  188.             }
  189.             return;
  190.  
  191.         case RTM_DELETE:
  192.             if (lc)
  193.                 RTFREE((struct rtentry *)lc);
  194.             rt->rt_llinfo = 0;
  195.         }
  196.     } else switch (req) {
  197.     case RTM_ADD:
  198.         /*
  199.          * Case 1: This route may come from a route to iface with mask
  200.          * or from a default route.
  201.          */
  202.         if (rt->rt_flags & RTF_CLONING) {
  203.             register struct ifaddr *ifa;
  204.             register struct sockaddr *sa;
  205.             for (ifa = ifp->if_addrlist; ifa; ifa->ifa_next)
  206.                 if ((sa = ifa->ifa_addr)->sa_family == AF_LINK) {
  207.                     if (sa->sa_len > gate->sa.sa_len)
  208.                         log(LOG_DEBUG, "llc_rtrequest: cloning address too small\n");
  209.                     else {
  210.                         Bcopy(sa, gate, gate->sa.sa_len);
  211.                         gate->sdl.sdl_alen = 0;
  212.                     }
  213.                     break;
  214.                 }
  215.             if (ifa == 0)
  216.                 log(LOG_DEBUG, "llc_rtrequest: can't find LL ifaddr for iface\n");
  217.             break;
  218.         }
  219.         /* FALLTHROUGH */
  220.     case RTM_RESOLVE:
  221.         /*
  222.          * Case 2:  This route may come from cloning, or a manual route
  223.          * add with a LL address.
  224.          */
  225.         if (gate->sdl.sdl_family != AF_LINK) {
  226.             log(LOG_DEBUG, "llc_rtrequest: got non-link non-gateway route\n");
  227.             break;
  228.         }
  229.         if (lc != 0)
  230.             return; /* happens on a route change */
  231.         R_Malloc(lc, struct llinfo_llc *, sizeof (*lc));
  232.         rt->rt_llinfo = (caddr_t)lc;
  233.         if (lc == 0) {
  234.             log(LOG_DEBUG, "llc_rtrequest: malloc failed\n");
  235.             break;
  236.         }
  237.         Bzero(lc, sizeof(*lc));
  238.         lc->lc_rt = rt;
  239.         rt->rt_flags |= RTF_LLINFO;
  240.         insque(lc, &llinfo_llc);
  241.         if (gate->sdl.sdl_alen == sizeof(struct esis_req) + addrlen) {
  242.             gate->sdl.sdl_alen -= sizeof(struct esis_req);
  243.             bcopy(addrlen + LLADDR(&gate->sdl),
  244.                   (caddr_t)&lc->lc_er, sizeof(lc->lc_er));
  245.         } else if (gate->sdl.sdl_alen == addrlen)
  246.             lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM);
  247.         break;
  248.     case RTM_DELETE:
  249.         if (lc == 0 || (rt->rt_flags & RTF_CLONING))
  250.             return;
  251.         remque(lc);
  252.         Free(lc);
  253.         rt->rt_llinfo = 0;
  254.         rt->rt_flags &= ~RTF_LLINFO;
  255.         break;
  256.     }
  257.     if (rt->rt_rmx.rmx_mtu == 0) {
  258.             rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu - LLC_SIZE;
  259.     }
  260. }
  261. /*
  262.  * FUNCTION:        iso_snparesolve
  263.  *
  264.  * PURPOSE:            Resolve an iso address into snpa address
  265.  *
  266.  * RETURNS:            0 if addr is resolved
  267.  *                    errno if addr is unknown
  268.  *
  269.  * SIDE EFFECTS:    
  270.  *
  271.  * NOTES:            Now that we have folded the snpa cache into the routing
  272.  *                    table, we know there is no snpa address known for this
  273.  *                    destination.  If we know of a default IS, then the address
  274.  *                    of the IS is returned.  If no IS is known, then return the
  275.  *                    multi-cast address for "all ES" for this interface.
  276.  *
  277.  *                    NB: the last case described above constitutes the
  278.  *                    query configuration function 9542, sec 6.5
  279.  *                    A mechanism is needed to prevent this function from
  280.  *                    being invoked if the system is an IS.
  281.  */
  282. iso_snparesolve(ifp, dest, snpa, snpa_len)
  283. struct    ifnet *ifp;            /* outgoing interface */
  284. struct    sockaddr_iso *dest;    /* destination */
  285. caddr_t    snpa;                /* RESULT: snpa to be used */
  286. int        *snpa_len;            /* RESULT: length of snpa */
  287. {
  288.     struct    llinfo_llc *sc;    /* ptr to snpa table entry */
  289.     caddr_t    found_snpa;
  290.     int     addrlen;
  291.  
  292.     /*
  293.      *    This hack allows us to send esis packets that have the destination snpa
  294.      *    addresss embedded in the destination nsap address 
  295.      */
  296.     if (dest->siso_data[0] == AFI_SNA) {
  297.         /*
  298.          *    This is a subnetwork address. Return it immediately
  299.          */
  300.         IFDEBUG(D_SNPA)
  301.             printf("iso_snparesolve: return SN address\n");
  302.         ENDDEBUG
  303.         addrlen = dest->siso_nlen - 1;    /* subtract size of AFI */
  304.         found_snpa = (caddr_t) dest->siso_data + 1;
  305.     /* 
  306.      * If we are an IS, we can't do much with the packet;
  307.      *    Check if we know about an IS.
  308.      */
  309.     } else if (iso_systype != SNPA_IS && known_is != 0 &&
  310.                 (sc = (struct llinfo_llc *)known_is->rt_llinfo) &&
  311.                  (sc->lc_flags & SNPA_VALID)) {
  312.         register struct sockaddr_dl *sdl =
  313.             (struct sockaddr_dl *)(known_is->rt_gateway);
  314.         found_snpa = LLADDR(sdl);
  315.         addrlen = sdl->sdl_alen;
  316.     } else if (ifp->if_flags & IFF_BROADCAST) {
  317.         /* 
  318.          *    no IS, no match. Return "all es" multicast address for this
  319.          *    interface, as per Query Configuration Function (9542 sec 6.5)
  320.          *
  321.          *    Note: there is a potential problem here. If the destination
  322.          *    is on the subnet and it does not respond with a ESH, but
  323.          *    does send back a TP CC, a connection could be established
  324.          *    where we always transmit the CLNP packet to "all es"
  325.          */
  326.         addrlen = ifp->if_addrlen;
  327.         found_snpa = (caddr_t)all_es_snpa;
  328.     } else
  329.         return (ENETUNREACH);
  330.     bcopy(found_snpa, snpa, *snpa_len = addrlen);
  331.     return (0);
  332. }
  333.  
  334.  
  335. /*
  336.  * FUNCTION:        snpac_free
  337.  *
  338.  * PURPOSE:            free an entry in the iso address map table
  339.  *
  340.  * RETURNS:            nothing
  341.  *
  342.  * SIDE EFFECTS:    
  343.  *
  344.  * NOTES:            If there is a route entry associated with cache
  345.  *                    entry, then delete that as well
  346.  */
  347. snpac_free(lc)
  348. register struct llinfo_llc *lc;        /* entry to free */
  349. {
  350.     register struct rtentry *rt = lc->lc_rt;
  351.     register struct iso_addr *r;
  352.  
  353.     if (known_is == rt)
  354.         known_is = 0;
  355.     if (rt && (rt->rt_flags & RTF_UP) &&
  356.         (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) {
  357.             RTFREE(rt);
  358.             rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
  359.                         rt->rt_flags, (struct rtentry **)0);
  360.         RTFREE(rt);
  361.     }
  362. }
  363.  
  364. /*
  365.  * FUNCTION:        snpac_add
  366.  *
  367.  * PURPOSE:            Add an entry to the snpa cache
  368.  *
  369.  * RETURNS:            
  370.  *
  371.  * SIDE EFFECTS:    
  372.  *
  373.  * NOTES:            If entry already exists, then update holding time.
  374.  */
  375. snpac_add(ifp, nsap, snpa, type, ht, nsellength)
  376. struct ifnet        *ifp;        /* interface info is related to */
  377. struct iso_addr        *nsap;        /* nsap to add */
  378. caddr_t                snpa;        /* translation */
  379. char                type;        /* SNPA_IS or SNPA_ES */
  380. u_short                ht;            /* holding time (in seconds) */
  381. int                    nsellength;    /* nsaps may differ only in trailing bytes */
  382. {
  383.     register struct    llinfo_llc *lc;
  384.     register struct rtentry *rt;
  385.     struct    rtentry *mrt = 0;
  386.     register struct    iso_addr *r; /* for zap_isoaddr macro */
  387.     int        snpalen = min(ifp->if_addrlen, MAX_SNPALEN);
  388.     int        new_entry = 0, index = ifp->if_index;
  389.  
  390.     IFDEBUG(D_SNPA)
  391.         printf("snpac_add(%x, %x, %x, %x, %x, %x)\n",
  392.             ifp, nsap, snpa, type, ht, nsellength);
  393.     ENDDEBUG
  394.     zap_isoaddr(dst, nsap);
  395.     rt = rtalloc1(S(dst), 0);
  396.     IFDEBUG(D_SNPA)
  397.         printf("snpac_add: rtalloc1 returns %x\n", rt);
  398.     ENDDEBUG
  399.     if (rt == 0) {
  400.         struct sockaddr *netmask;
  401.         int flags;
  402.         add:
  403.         if (nsellength) {
  404.             netmask = S(msk); flags = RTF_UP;
  405.             snpac_fixdstandmask(nsellength);
  406.         } else {
  407.             netmask = 0; flags = RTF_UP | RTF_HOST;
  408.         }
  409.         new_entry = 1;
  410.         zap_linkaddr((>e_dl), snpa, snpalen, index);
  411.         if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) ||
  412.             mrt == 0)
  413.             return (0);
  414.         rt = mrt;
  415.         rt->rt_refcnt--;
  416.     } else {
  417.         register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway;
  418.         rt->rt_refcnt--;
  419.         if ((rt->rt_flags & RTF_LLINFO) == 0)
  420.             goto add;
  421.         if (nsellength && (rt->rt_flags & RTF_HOST)) {
  422.             if (rt->rt_refcnt == 0) {
  423.                 rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0,
  424.                     (struct sockaddr *)0, 0, (struct rtentry *)0);
  425.                 rt = 0;
  426.                 goto add;
  427.             } else {
  428.                 static struct iso_addr nsap2; register char *cp;
  429.                 nsap2 = *nsap;
  430.                 cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength;
  431.                 while (cp < (char *)(1 + &nsap2))
  432.                     *cp++ = 0;
  433.                 (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength);
  434.             }
  435.         }
  436.         if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) {
  437.             int old_sdl_len = sdl->sdl_len;
  438.             if (old_sdl_len < sizeof(*sdl)) {
  439.                 log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n");
  440.                 return (0);
  441.             }
  442.             zap_linkaddr(sdl, snpa, snpalen, index);
  443.             sdl->sdl_len = old_sdl_len;
  444.             new_entry = 1;
  445.         }
  446.     }
  447.     if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0)
  448.         panic("snpac_rtrequest");
  449.     rt->rt_rmx.rmx_expire = ht + time.tv_sec;
  450.     lc->lc_flags = SNPA_VALID | type;
  451.     if (type & SNPA_IS)
  452.         snpac_logdefis(rt);
  453.     return (new_entry);
  454. }
  455.  
  456. static void
  457. snpac_fixdstandmask(nsellength)
  458. {
  459.     register char *cp = msk.siso_data, *cplim;
  460.  
  461.     cplim = cp + (dst.siso_nlen -= nsellength);
  462.     msk.siso_len = cplim - (char *)&msk;
  463.     msk.siso_nlen = 0;
  464.     while (cp < cplim)
  465.         *cp++ = -1;
  466.     while (cp < (char *)msk.siso_pad)
  467.         *cp++ = 0;
  468.     for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; )
  469.         *cp++ = 0;
  470. }
  471.  
  472. /*
  473.  * FUNCTION:        snpac_ioctl
  474.  *
  475.  * PURPOSE:            Set/Get the system type and esis parameters
  476.  *
  477.  * RETURNS:            0 on success, or unix error code
  478.  *
  479.  * SIDE EFFECTS:    
  480.  *
  481.  * NOTES:            
  482.  */
  483. snpac_ioctl (so, cmd, data)
  484. struct socket *so;
  485. int        cmd;    /* ioctl to process */
  486. caddr_t    data;    /* data for the cmd */
  487. {
  488.     register struct systype_req *rq = (struct systype_req *)data;
  489.  
  490.     IFDEBUG(D_IOCTL)
  491.         if (cmd == SIOCSSTYPE)
  492.             printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n",
  493.                 rq->sr_type, rq->sr_holdt, rq->sr_configt);
  494.         else
  495.             printf("snpac_ioctl: cmd get\n");
  496.     ENDDEBUG
  497.  
  498.     if (cmd == SIOCSSTYPE) {
  499.         if ((so->so_state & SS_PRIV) == 0)
  500.             return (EPERM);
  501.         if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS))
  502.             return(EINVAL);
  503.         if (rq->sr_type & SNPA_ES) {
  504.             iso_systype = SNPA_ES;
  505.         } else if (rq->sr_type & SNPA_IS) {
  506.             iso_systype = SNPA_IS;
  507.         } else {
  508.             return(EINVAL);
  509.         }
  510.         esis_holding_time = rq->sr_holdt;
  511.         esis_config_time = rq->sr_configt;
  512.         if (esis_esconfig_time != rq->sr_esconfigt) {
  513.             untimeout(esis_config, (caddr_t)0);
  514.             esis_esconfig_time = rq->sr_esconfigt;
  515.             esis_config();
  516.         }
  517.     } else if (cmd == SIOCGSTYPE) {
  518.         rq->sr_type = iso_systype;
  519.         rq->sr_holdt = esis_holding_time;
  520.         rq->sr_configt = esis_config_time;
  521.         rq->sr_esconfigt = esis_esconfig_time;
  522.     } else {
  523.         return (EINVAL);
  524.     }
  525.     return (0);
  526. }
  527.  
  528. /*
  529.  * FUNCTION:        snpac_logdefis
  530.  *
  531.  * PURPOSE:            Mark the IS passed as the default IS
  532.  *
  533.  * RETURNS:            nothing
  534.  *
  535.  * SIDE EFFECTS:    
  536.  *
  537.  * NOTES:            
  538.  */
  539. snpac_logdefis(sc)
  540. register struct rtentry *sc;
  541. {
  542.     register struct iso_addr *r;
  543.     register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway;
  544.     register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0);
  545.  
  546.     zap_linkaddr((>e_dl), LLADDR(sdl), sdl->sdl_alen, sdl->sdl_index);
  547.     if (known_is == 0)
  548.         known_is = sc;
  549.     if (known_is != sc) {
  550.         rtfree(known_is);
  551.         known_is = sc;
  552.     }
  553.     if (rt == 0) {
  554.         rtrequest(RTM_ADD, S(zsi), S(gte_dl), S(zmk),
  555.                         RTF_DYNAMIC|RTF_GATEWAY|RTF_CLONING, 0);
  556.         return;
  557.     }
  558.     rt->rt_refcnt--;
  559.     if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) {
  560.         *((struct sockaddr_dl *)rt->rt_gateway) = gte_dl;
  561.     }
  562. }
  563.  
  564. /*
  565.  * FUNCTION:        snpac_age
  566.  *
  567.  * PURPOSE:            Time out snpac entries
  568.  *
  569.  * RETURNS:            
  570.  *
  571.  * SIDE EFFECTS:    
  572.  *
  573.  * NOTES:            When encountering an entry for the first time, snpac_age
  574.  *                    may delete up to SNPAC_AGE too many seconds. Ie.
  575.  *                    if the entry is added a moment before snpac_age is
  576.  *                    called, the entry will immediately have SNPAC_AGE
  577.  *                    seconds taken off the holding time, even though
  578.  *                    it has only been held a brief moment.
  579.  *
  580.  *                    The proper way to do this is set an expiry timeval
  581.  *                    equal to current time + holding time. Then snpac_age
  582.  *                    would time out entries where expiry date is older
  583.  *                    than the current time.
  584.  */
  585. snpac_age()
  586. {
  587.     register struct    llinfo_llc *lc, *nlc;
  588.     register struct    rtentry *rt;
  589.  
  590.     timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz);
  591.  
  592.     for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = nlc) {
  593.         nlc = lc->lc_next;
  594.         if (((lc->lc_flags & SNPA_PERM) == 0) && (lc->lc_flags & SNPA_VALID)) {
  595.             rt = lc->lc_rt;
  596.             if (rt->rt_rmx.rmx_expire && rt->rt_rmx.rmx_expire < time.tv_sec)
  597.                 snpac_free(lc);
  598.             else
  599.                 continue;
  600.         }
  601.     }
  602. }
  603.  
  604. /*
  605.  * FUNCTION:        snpac_ownmulti
  606.  *
  607.  * PURPOSE:            Determine if the snpa address is a multicast address
  608.  *                    of the same type as the system.
  609.  *
  610.  * RETURNS:            true or false
  611.  *
  612.  * SIDE EFFECTS:    
  613.  *
  614.  * NOTES:            Used by interface drivers when not in eavesdrop mode 
  615.  *                    as interm kludge until
  616.  *                    real multicast addresses can be configured
  617.  */
  618. snpac_ownmulti(snpa, len)
  619. caddr_t    snpa;
  620. u_int    len;
  621. {
  622.     return (((iso_systype & SNPA_ES) &&
  623.              (!bcmp(snpa, (caddr_t)all_es_snpa, len))) ||
  624.             ((iso_systype & SNPA_IS) &&
  625.              (!bcmp(snpa, (caddr_t)all_is_snpa, len))));
  626. }
  627.  
  628. /*
  629.  * FUNCTION:        snpac_flushifp
  630.  *
  631.  * PURPOSE:            Flush entries associated with specific ifp
  632.  *
  633.  * RETURNS:            nothing
  634.  *
  635.  * SIDE EFFECTS:    
  636.  *
  637.  * NOTES:            
  638.  */
  639. snpac_flushifp(ifp)
  640. struct ifnet    *ifp;
  641. {
  642.     register struct llinfo_llc    *lc;
  643.  
  644.     for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) {
  645.         if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID))
  646.             snpac_free(lc);
  647.     }
  648. }
  649.  
  650. /*
  651.  * FUNCTION:        snpac_rtrequest
  652.  *
  653.  * PURPOSE:            Make a routing request
  654.  *
  655.  * RETURNS:            nothing
  656.  *
  657.  * SIDE EFFECTS:    
  658.  *
  659.  * NOTES:            In the future, this should make a request of a user
  660.  *                    level routing daemon.
  661.  */
  662. snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt)
  663. int                req;
  664. struct iso_addr    *host;
  665. struct iso_addr    *gateway;
  666. struct iso_addr    *netmask;
  667. short            flags;
  668. struct rtentry    **ret_nrt;
  669. {
  670.     register struct iso_addr *r;
  671.  
  672.     IFDEBUG(D_SNPA)
  673.         printf("snpac_rtrequest: ");
  674.         if (req == RTM_ADD)
  675.             printf("add");
  676.         else if (req == RTM_DELETE)
  677.             printf("delete");
  678.         else 
  679.             printf("unknown command");
  680.         printf(" dst: %s\n", clnp_iso_addrp(host));
  681.         printf("\tgateway: %s\n", clnp_iso_addrp(gateway));
  682.     ENDDEBUG
  683.  
  684.  
  685.     zap_isoaddr(dst, host);
  686.     zap_isoaddr(gte, gateway);
  687.     if (netmask) {
  688.         zap_isoaddr(msk, netmask);
  689.         msk.siso_nlen = 0;
  690.         msk.siso_len = msk.siso_pad - (u_char *)&msk;
  691.     }
  692.  
  693.     rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0),
  694.         flags, ret_nrt);
  695. }
  696.  
  697. /*
  698.  * FUNCTION:        snpac_addrt
  699.  *
  700.  * PURPOSE:            Associate a routing entry with an snpac entry
  701.  *
  702.  * RETURNS:            nothing
  703.  *
  704.  * SIDE EFFECTS:    
  705.  *
  706.  * NOTES:            If a cache entry exists for gateway, then
  707.  *                    make a routing entry (host, gateway) and associate
  708.  *                    with gateway.
  709.  *
  710.  *                    If a route already exists and is different, first delete
  711.  *                    it.
  712.  *
  713.  *                    This could be made more efficient by checking 
  714.  *                    the existing route before adding a new one.
  715.  */
  716. snpac_addrt(ifp, host, gateway, netmask)
  717. struct ifnet *ifp;
  718. struct iso_addr    *host, *gateway, *netmask;
  719. {
  720.     register struct iso_addr *r;
  721.  
  722.     zap_isoaddr(dst, host);
  723.     zap_isoaddr(gte, gateway);
  724.     if (netmask) {
  725.         zap_isoaddr(msk, netmask);
  726.         msk.siso_nlen = 0;
  727.         msk.siso_len = msk.siso_pad - (u_char *)&msk;
  728.         rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0);
  729.     } else
  730.         rtredirect(S(dst), S(gte), (struct sockaddr *)0,
  731.                             RTF_DONE | RTF_HOST, S(gte), 0);
  732. }
  733. #endif    ISO
  734.