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-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: iso_snpac.c,v 1.51 2008/10/24 21:50:08 dyoung 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.51 2008/10/24 21:50:08 dyoung 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 && (ifp->if_ioctl == NULL ||
  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 && (ifp->if_ioctl == NULL ||
  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                 if (l == NULL || kauth_authorize_generic(l->l_cred,
  553                     KAUTH_GENERIC_ISSUSER, NULL))
  554                         return (EPERM);
  555                 if ((rq->sr_type & (SNPA_ES | SNPA_IS)) == (SNPA_ES | SNPA_IS))
  556                         return (EINVAL);
  557                 if (rq->sr_type & SNPA_ES) {
  558                         iso_systype = SNPA_ES;
  559                 } else if (rq->sr_type & SNPA_IS) {
  560                         iso_systype = SNPA_IS;
  561                 } else {
  562                         return (EINVAL);
  563                 }
  564                 esis_holding_time = rq->sr_holdt;
  565                 esis_config_time = rq->sr_configt;
  566                 if (esis_esconfig_time != rq->sr_esconfigt) {
  567                         callout_stop(&esis_config_ch);
  568                         esis_esconfig_time = rq->sr_esconfigt;
  569                         esis_config(NULL);
  570                 }
  571         } else if (cmd == SIOCGSTYPE) {
  572                 rq->sr_type = iso_systype;
  573                 rq->sr_holdt = esis_holding_time;
  574                 rq->sr_configt = esis_config_time;
  575                 rq->sr_esconfigt = esis_esconfig_time;
  576         } else {
  577                 return (EINVAL);
  578         }
  579         return (0);
  580 }
  581 
  582 /*
  583  * FUNCTION:            snpac_logdefis
  584  *
  585  * PURPOSE:                     Mark the IS passed as the default IS
  586  *
  587  * RETURNS:                     nothing
  588  *
  589  * SIDE EFFECTS:
  590  *
  591  * NOTES:
  592  */
  593 void
  594 snpac_logdefis(struct rtentry *sc)
  595 {
  596         struct rtentry *rt;
  597 
  598         if (known_is == sc || !(sc->rt_flags & RTF_HOST))
  599                 return;
  600         if (known_is) {
  601                 RTFREE(known_is);
  602         }
  603         known_is = sc;
  604         sc->rt_refcnt++;
  605         rt = rtalloc1((struct sockaddr *) & zsi, 0);
  606         if (rt == 0) {
  607                 rtrequest(RTM_ADD, sisotosa(&zsi), rt_getkey(sc),
  608                     sisotosa(&zmk), RTF_DYNAMIC | RTF_GATEWAY, NULL);
  609         } else {
  610                 if ((rt->rt_flags & RTF_DYNAMIC) &&
  611                     (rt->rt_flags & RTF_GATEWAY) && rt_mask(rt)->sa_len == 0)
  612                         rt_setgate(rt, rt_getkey(sc));
  613         }
  614 }
  615 
  616 /*
  617  * FUNCTION:            snpac_age
  618  *
  619  * PURPOSE:             Time out snpac entries
  620  *
  621  * RETURNS:
  622  *
  623  * SIDE EFFECTS:
  624  *
  625  * NOTES:               When encountering an entry for the first time, snpac_age
  626  *                      may delete up to SNPAC_AGE too many seconds. Ie.
  627  *                      if the entry is added a moment before snpac_age is
  628  *                      called, the entry will immediately have SNPAC_AGE
  629  *                      seconds taken off the holding time, even though
  630  *                      it has only been held a brief moment.
  631  *
  632  *                      The proper way to do this is set an expiry timeval
  633  *                      equal to current time + holding time. Then snpac_age
  634  *                      would time out entries where expiry date is older
  635  *                      than the current time.
  636  */
  637 /*ARGSUSED*/
  638 void
  639 snpac_age(void *v)
  640 {
  641         struct llinfo_llc *lc, *nlc;
  642         struct rtentry *rt;
  643 
  644         callout_reset(&snpac_age_ch, SNPAC_AGE * hz, snpac_age, NULL);
  645 
  646         for (lc = llinfo_llc.lh_first; lc != 0; lc = nlc) {
  647                 nlc = lc->lc_list.le_next;
  648                 if (lc->lc_flags & SNPA_VALID) {
  649                         rt = lc->lc_rt;
  650                         if (rt->rt_rmx.rmx_expire &&
  651                             rt->rt_rmx.rmx_expire < time_second)
  652                                 snpac_free(lc);
  653                 }
  654         }
  655 }
  656 
  657 /*
  658  * FUNCTION:            snpac_ownmulti
  659  *
  660  * PURPOSE:             Determine if the snpa address is a multicast address
  661  *                      of the same type as the system.
  662  *
  663  * RETURNS:             true or false
  664  *
  665  * SIDE EFFECTS:
  666  *
  667  * NOTES:               Used by interface drivers when not in eavesdrop mode
  668  *                      as interm kludge until
  669  *                      real multicast addresses can be configured
  670  */
  671 int
  672 snpac_ownmulti(void *snpa, u_int len)
  673 {
  674         return (((iso_systype & SNPA_ES) &&
  675                  (!memcmp(snpa, all_es_snpa, len))) ||
  676                 ((iso_systype & SNPA_IS) &&
  677                  (!memcmp(snpa, all_is_snpa, len))));
  678 }
  679 
  680 /*
  681  * FUNCTION:            snpac_flushifp
  682  *
  683  * PURPOSE:             Flush entries associated with specific ifp
  684  *
  685  * RETURNS:             nothing
  686  *
  687  * SIDE EFFECTS:
  688  *
  689  * NOTES:
  690  */
  691 void
  692 snpac_flushifp(struct ifnet *ifp)
  693 {
  694         struct llinfo_llc *lc;
  695 
  696         for (lc = llinfo_llc.lh_first; lc != 0; lc = lc->lc_list.le_next) {
  697                 if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID))
  698                         snpac_free(lc);
  699         }
  700 }
  701 
  702 /*
  703  * FUNCTION:            snpac_rtrequest
  704  *
  705  * PURPOSE:             Make a routing request
  706  *
  707  * RETURNS:             nothing
  708  *
  709  * SIDE EFFECTS:
  710  *
  711  * NOTES:               In the future, this should make a request of a user
  712  *                      level routing daemon.
  713  */
  714 void
  715 snpac_rtrequest(int req, struct iso_addr *host, struct iso_addr *gateway,
  716         struct iso_addr *netmask, int flags, struct rtentry **ret_nrt)
  717 {
  718         struct iso_addr *r;
  719 
  720 #ifdef ARGO_DEBUG
  721         if (argo_debug[D_SNPA]) {
  722                 printf("snpac_rtrequest: ");
  723                 if (req == RTM_ADD)
  724                         printf("add");
  725                 else if (req == RTM_DELETE)
  726                         printf("delete");
  727                 else
  728                         printf("unknown command");
  729                 printf(" dst: %s\n", clnp_iso_addrp(host));
  730                 printf("\tgateway: %s\n", clnp_iso_addrp(gateway));
  731         }
  732 #endif
  733 
  734 
  735         zap_isoaddr(dst, host);
  736         zap_isoaddr(gte, gateway);
  737         if (netmask) {
  738                 zap_isoaddr(msk, netmask);
  739                 msk.siso_nlen = 0;
  740                 msk.siso_len = msk.siso_pad - (u_char *) & msk;
  741         }
  742         rtrequest(req, sisotosa(&dst), sisotosa(&gte),
  743         (netmask ? sisotosa(&msk) : (struct sockaddr *) 0), flags, ret_nrt);
  744 }
  745 
  746 /*
  747  * FUNCTION:            snpac_addrt
  748  *
  749  * PURPOSE:             Associate a routing entry with an snpac entry
  750  *
  751  * RETURNS:             nothing
  752  *
  753  * SIDE EFFECTS:
  754  *
  755  * NOTES:               If a cache entry exists for gateway, then
  756  *                      make a routing entry (host, gateway) and associate
  757  *                      with gateway.
  758  *
  759  *                      If a route already exists and is different, first delete
  760  *                      it.
  761  *
  762  *                      This could be made more efficient by checking
  763  *                      the existing route before adding a new one.
  764  */
  765 void
  766 snpac_addrt(struct ifnet *ifp, struct iso_addr *host,
  767     struct iso_addr *gateway, struct iso_addr *netmask)
  768 {
  769         struct iso_addr *r;
  770 
  771         zap_isoaddr(dst, host);
  772         zap_isoaddr(gte, gateway);
  773         if (netmask) {
  774                 zap_isoaddr(msk, netmask);
  775                 msk.siso_nlen = 0;
  776                 msk.siso_len = msk.siso_pad - (u_char *) & msk;
  777                 rtredirect(sisotosa(&dst), sisotosa(&gte), sisotosa(&msk),
  778                            RTF_DONE, sisotosa(&gte), 0);
  779         } else
  780                 rtredirect(sisotosa(&dst), sisotosa(&gte), (struct sockaddr *) 0,
  781                            RTF_DONE | RTF_HOST, sisotosa(&gte), 0);
  782 }
  783 #endif                          /* ISO */

Cache object: 1211620ae9005a448579fe1a41034a3f


[ 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.