The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netiso/iso_snpac.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: ae163124b688775cd930e652aeae47c0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.