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.40 2006/11/16 01:33:51 christos 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.40 2006/11/16 01:33:51 christos 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) {Bzero(&a.siso_addr, sizeof(*r)); r = b; \
  133            Bcopy(r, &a.siso_addr, 1 + (r)->isoa_len);}
  134 #define S(x) ((struct sockaddr *)&(x))
  135 
  136 static struct sockaddr_dl blank_dl = {
  137         .sdl_len = sizeof(blank_dl),
  138         .sdl_family = AF_LINK,
  139 };
  140 static struct sockaddr_dl gte_dl;
  141 #define zap_linkaddr(a, b, c, i) \
  142         (*a = blank_dl, memcpy(a->sdl_data, b, a->sdl_alen = c), a->sdl_index = i)
  143 
  144 static void snpac_fixdstandmask (int);
  145 
  146 /*
  147  *      We only keep track of a single IS at a time.
  148  */
  149 struct rtentry *known_is;
  150 
  151 /*
  152  *      Addresses taken from NBS agreements, December 1987.
  153  *
  154  *      These addresses assume on-the-wire transmission of least significant
  155  *      bit first. This is the method used by 802.3. When these
  156  *      addresses are passed to the token ring driver, (802.5), they
  157  *      must be bit-swapped because 802.5 transmission order is MSb first.
  158  *
  159  *      Furthermore, according to IBM Austin, these addresses are not
  160  *      true token ring multicast addresses. More work is necessary
  161  *      to get multicast to work right on token ring.
  162  *
  163  *      Currently, the token ring driver does not handle multicast, so
  164  *      these addresses are converted into the broadcast address in
  165  *      lan_output() That means that if these multicast addresses change
  166  *      the token ring driver must be altered.
  167  */
  168 const char all_es_snpa[] = {0x09, 0x00, 0x2b, 0x00, 0x00, 0x04};
  169 const char all_is_snpa[] = {0x09, 0x00, 0x2b, 0x00, 0x00, 0x05};
  170 const char all_l1is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14};
  171 const char all_l2is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x15};
  172 
  173 union sockunion {
  174         struct sockaddr_iso siso;
  175         struct sockaddr_dl sdl;
  176         struct sockaddr sa;
  177 };
  178 
  179 /*
  180  * FUNCTION:            llc_rtrequest
  181  *
  182  * PURPOSE:             Manage routing table entries specific to LLC for ISO.
  183  *
  184  * NOTES:               This does a lot of obscure magic;
  185  */
  186 void
  187 llc_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
  188 {
  189         union sockunion *gate = (union sockunion *) rt->rt_gateway;
  190         struct llinfo_llc *lc = (struct llinfo_llc *) rt->rt_llinfo;
  191         struct ifnet   *ifp = rt->rt_ifp;
  192         int             addrlen = ifp->if_addrlen;
  193 #define LLC_SIZE 3              /* XXXXXX do this right later */
  194 
  195 #ifdef ARGO_DEBUG
  196         if (argo_debug[D_SNPA]) {
  197                 printf("llc_rtrequest(%d, %p, %p)\n", req, rt, info);
  198         }
  199 #endif
  200         if (rt->rt_flags & RTF_GATEWAY)
  201                 return;
  202         else
  203                 switch (req) {
  204                 case RTM_ADD:
  205                         /*
  206                          * Case 1: This route may come from a route to iface with mask
  207                          * or from a default route.
  208                          */
  209                         if (rt->rt_flags & RTF_CLONING) {
  210                                 iso_setmcasts(ifp, req);
  211                                 rt_setgate(rt, rt_key(rt),
  212                                            (struct sockaddr *) & blank_dl);
  213                                 return;
  214                         }
  215                         if (lc != 0)
  216                                 return; /* happens on a route change */
  217                         /* FALLTHROUGH */
  218                 case RTM_RESOLVE:
  219                         /*
  220                          * Case 2:  This route may come from cloning, or a manual route
  221                          * add with a LL address.
  222                          */
  223                         if (gate->sdl.sdl_family != AF_LINK) {
  224                                 log(LOG_DEBUG, "llc_rtrequest: got non-link non-gateway route\n");
  225                                 break;
  226                         }
  227                         R_Malloc(lc, struct llinfo_llc *, sizeof(*lc));
  228                         rt->rt_llinfo = (caddr_t) lc;
  229                         if (lc == 0) {
  230                                 log(LOG_DEBUG, "llc_rtrequest: malloc failed\n");
  231                                 break;
  232                         }
  233                         Bzero(lc, sizeof(*lc));
  234                         lc->lc_rt = rt;
  235                         rt->rt_flags |= RTF_LLINFO;
  236                         LIST_INSERT_HEAD(&llinfo_llc, lc, lc_list);
  237                         if (gate->sdl.sdl_alen == sizeof(struct esis_req)
  238                             + addrlen) {
  239                                 gate->sdl.sdl_alen -= sizeof(struct esis_req);
  240                                 (void)memcpy(&lc->lc_er,
  241                                     (const char *)CLLADDR(&gate->sdl) +
  242                                     addrlen, sizeof(lc->lc_er));
  243                         } else if (gate->sdl.sdl_alen == addrlen)
  244                                 lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM);
  245                         break;
  246                 case RTM_DELETE:
  247                         if (rt->rt_flags & RTF_CLONING)
  248                                 iso_setmcasts(ifp, req);
  249                         if (lc == 0)
  250                                 return;
  251                         LIST_REMOVE(lc, lc_list);
  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 /*
  263  * FUNCTION:            iso_setmcasts
  264  *
  265  * PURPOSE:             Enable/Disable ESIS/ISIS multicast reception on
  266  *                      interfaces.
  267  *
  268  * NOTES:               This also does a lot of obscure magic;
  269  */
  270 void
  271 iso_setmcasts(struct ifnet *ifp, int req)
  272 {
  273         static const char * const addrlist[] =
  274         {all_es_snpa, all_is_snpa, all_l1is_snpa, all_l2is_snpa, 0};
  275         struct ifreq ifr;
  276         const char *const *cpp;
  277 
  278         (void)memset(&ifr, 0, sizeof(ifr));
  279         for (cpp = addrlist; *cpp; cpp++) {
  280                 (void)memcpy(ifr.ifr_addr.sa_data, *cpp, 6);
  281                 if (req == RTM_ADD && (ifp->if_ioctl == 0 ||
  282                     (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr) != 0))
  283                         printf("iso_setmcasts: %s unable to add mcast\n",
  284                             ifp->if_xname);
  285                 else if (req == RTM_DELETE && (ifp->if_ioctl == 0 ||
  286                     (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr) != 0))
  287                         printf("iso_setmcasts: %s unable to delete mcast\n",
  288                             ifp->if_xname);
  289         }
  290 }
  291 
  292 /*
  293  * FUNCTION:            iso_snparesolve
  294  *
  295  * PURPOSE:             Resolve an iso address into snpa address
  296  *
  297  * RETURNS:             0 if addr is resolved
  298  *                      errno if addr is unknown
  299  *
  300  * SIDE EFFECTS:
  301  *
  302  * NOTES:               Now that we have folded the snpa cache into the routing
  303  *                      table, we know there is no snpa address known for this
  304  *                      destination.  If we know of a default IS, then the
  305  *                      address of the IS is returned.  If no IS is known,
  306  *                      then return the multi-cast address for "all ES" for
  307  *                      this interface.
  308  *
  309  *                      NB: the last case described above constitutes the
  310  *                      query configuration function 9542, sec 6.5
  311  *                      A mechanism is needed to prevent this function from
  312  *                      being invoked if the system is an IS.
  313  */
  314 int
  315 iso_snparesolve(
  316         struct ifnet   *ifp,            /* outgoing interface */
  317         struct sockaddr_iso *dest,      /* destination */
  318         caddr_t         snpa,           /* RESULT: snpa to be used */
  319         int            *snpa_len)       /* RESULT: length of snpa */
  320 {
  321         struct llinfo_llc *sc;  /* ptr to snpa table entry */
  322         const char *found_snpa;
  323         int             addrlen;
  324 
  325         /*
  326          * This hack allows us to send esis packets that have the destination
  327          * snpa addresss embedded in the destination nsap address
  328          */
  329         if (dest->siso_data[0] == AFI_SNA) {
  330                 /*
  331                  *      This is a subnetwork address. Return it immediately
  332                  */
  333 #ifdef ARGO_DEBUG
  334                 if (argo_debug[D_SNPA]) {
  335                         printf("iso_snparesolve: return SN address\n");
  336                 }
  337 #endif
  338                 addrlen = dest->siso_nlen - 1;  /* subtract size of AFI */
  339                 found_snpa = (const char *)dest->siso_data + 1;
  340                 /*
  341                  * If we are an IS, we can't do much with the packet; Check
  342                  * if we know about an IS.
  343                  */
  344         } else if (iso_systype != SNPA_IS && known_is != 0 &&
  345                    (sc = (struct llinfo_llc *) known_is->rt_llinfo) &&
  346                    (sc->lc_flags & SNPA_VALID)) {
  347                 struct sockaddr_dl *sdl =
  348                 (struct sockaddr_dl *) (known_is->rt_gateway);
  349                 found_snpa = LLADDR(sdl);
  350                 addrlen = sdl->sdl_alen;
  351         } else if (ifp->if_flags & IFF_BROADCAST) {
  352                 /*
  353                  * no IS, no match. Return "all es" multicast address for
  354                  * this interface, as per Query Configuration Function (9542
  355                  * sec 6.5)
  356                  *
  357                  * Note: there is a potential problem here. If the destination
  358                  * is on the subnet and it does not respond with a ESH, but
  359                  * does send back a TP CC, a connection could be established
  360                  * where we always transmit the CLNP packet to "all es"
  361                  */
  362                 addrlen = ifp->if_addrlen;
  363                 found_snpa = (const char *) all_es_snpa;
  364         } else
  365                 return (ENETUNREACH);
  366         memcpy(snpa, found_snpa, *snpa_len = addrlen);
  367         return (0);
  368 }
  369 
  370 
  371 /*
  372  * FUNCTION:            snpac_free
  373  *
  374  * PURPOSE:             free an entry in the iso address map table
  375  *
  376  * RETURNS:             nothing
  377  *
  378  * SIDE EFFECTS:
  379  *
  380  * NOTES:               If there is a route entry associated with cache
  381  *                      entry, then delete that as well
  382  */
  383 void
  384 snpac_free(
  385         struct llinfo_llc *lc)  /* entry to free */
  386 {
  387         struct rtentry *rt = lc->lc_rt;
  388 
  389         if (known_is == rt)
  390                 known_is = 0;
  391         if (rt && (rt->rt_flags & RTF_UP) &&
  392             (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) {
  393                 RTFREE(rt);
  394                 rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
  395                           rt->rt_flags, (struct rtentry **) 0);
  396                 RTFREE(rt);
  397         }
  398 }
  399 
  400 /*
  401  * FUNCTION:            snpac_add
  402  *
  403  * PURPOSE:             Add an entry to the snpa cache
  404  *
  405  * RETURNS:
  406  *
  407  * SIDE EFFECTS:
  408  *
  409  * NOTES:               If entry already exists, then update holding time.
  410  */
  411 int
  412 snpac_add(
  413         struct ifnet   *ifp,            /* interface info is related to */
  414         struct iso_addr *nsap,          /* nsap to add */
  415         caddr_t         snpa,           /* translation */
  416         int             type,           /* SNPA_IS or SNPA_ES */
  417         u_short         ht,             /* holding time (in seconds) */
  418         int             nsellength)     /* nsaps may differ only in trailing
  419                                          * bytes */
  420 {
  421         struct llinfo_llc *lc;
  422         struct rtentry *rt;
  423         struct rtentry *mrt = 0;
  424         struct iso_addr *r;     /* for zap_isoaddr macro */
  425         int             snpalen = min(ifp->if_addrlen, MAX_SNPALEN);
  426         int             new_entry = 0, index = ifp->if_index, iftype = ifp->if_type;
  427 
  428 #ifdef ARGO_DEBUG
  429         if (argo_debug[D_SNPA]) {
  430                 printf("snpac_add(%p, %p, %p, %x, %x, %x)\n",
  431                     ifp, nsap, snpa, type, ht, nsellength);
  432         }
  433 #endif
  434         zap_isoaddr(dst, nsap);
  435         rt = rtalloc1(sisotosa(&dst), 0);
  436 #ifdef ARGO_DEBUG
  437         if (argo_debug[D_SNPA]) {
  438                 printf("snpac_add: rtalloc1 returns %p\n", rt);
  439         }
  440 #endif
  441         if (rt == 0) {
  442                 struct sockaddr *netmask;
  443                 int             flags;
  444 add:
  445                 if (nsellength) {
  446                         netmask = sisotosa(&msk);
  447                         flags = RTF_UP;
  448                         snpac_fixdstandmask(nsellength);
  449                 } else {
  450                         netmask = 0;
  451                         flags = RTF_UP | RTF_HOST;
  452                 }
  453                 new_entry = 1;
  454                 zap_linkaddr((&gte_dl), snpa, snpalen, index);
  455                 gte_dl.sdl_type = iftype;
  456                 if (rtrequest(RTM_ADD, sisotosa(&dst), S(gte_dl), netmask,
  457                               flags, &mrt) || mrt == 0)
  458                         return (0);
  459                 rt = mrt;
  460                 rt->rt_refcnt--;
  461         } else {
  462                 struct sockaddr_dl *sdl = (struct sockaddr_dl *) rt->rt_gateway;
  463                 rt->rt_refcnt--;
  464                 if ((rt->rt_flags & RTF_LLINFO) == 0)
  465                         goto add;
  466                 if (nsellength && (rt->rt_flags & RTF_HOST)) {
  467                         if (rt->rt_refcnt == 0) {
  468                                 rtrequest(RTM_DELETE, sisotosa(&dst),
  469                                 (struct sockaddr *) 0, (struct sockaddr *) 0,
  470                                           0, (struct rtentry **) 0);
  471                                 rt = 0;
  472                                 goto add;
  473                         } else {
  474                                 static struct iso_addr nsap2;
  475                                 char  *cp;
  476                                 nsap2 = *nsap;
  477                                 cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength;
  478                                 while (cp < (char *) (1 + &nsap2))
  479                                         *cp++ = 0;
  480                                 (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength);
  481                         }
  482                 }
  483                 if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) {
  484                         int             old_sdl_len = sdl->sdl_len;
  485                         if (old_sdl_len < sizeof(*sdl)) {
  486                                 log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n");
  487                                 return (0);
  488                         }
  489                         zap_linkaddr(sdl, snpa, snpalen, index);
  490                         sdl->sdl_len = old_sdl_len;
  491                         sdl->sdl_type = iftype;
  492                         new_entry = 1;
  493                 }
  494         }
  495         if ((lc = (struct llinfo_llc *) rt->rt_llinfo) == 0)
  496                 panic("snpac_rtrequest");
  497         rt->rt_rmx.rmx_expire = ht + time_second;
  498         lc->lc_flags = SNPA_VALID | type;
  499         if ((type & SNPA_IS) && !(iso_systype & SNPA_IS))
  500                 snpac_logdefis(rt);
  501         return (new_entry);
  502 }
  503 
  504 static void
  505 snpac_fixdstandmask(int nsellength)
  506 {
  507         char  *cp = msk.siso_data, *cplim;
  508 
  509         cplim = cp + (dst.siso_nlen -= nsellength);
  510         msk.siso_len = cplim - (char *) &msk;
  511         msk.siso_nlen = 0;
  512         while (cp < cplim)
  513                 *cp++ = -1;
  514         while (cp < (char *) msk.siso_pad)
  515                 *cp++ = 0;
  516         for (cp = dst.siso_data + dst.siso_nlen; cp < (char *) dst.siso_pad;)
  517                 *cp++ = 0;
  518 }
  519 
  520 /*
  521  * FUNCTION:            snpac_ioctl
  522  *
  523  * PURPOSE:                     Set/Get the system type and esis parameters
  524  *
  525  * RETURNS:                     0 on success, or unix error code
  526  *
  527  * SIDE EFFECTS:
  528  *
  529  * NOTES:
  530  */
  531 int
  532 snpac_ioctl(
  533         struct socket *so,
  534         u_long cmd,             /* ioctl to process */
  535         caddr_t data,           /* data for the cmd */
  536         struct lwp *l)
  537 {
  538         struct systype_req *rq = (struct systype_req *) data;
  539 
  540 #ifdef ARGO_DEBUG
  541         if (argo_debug[D_IOCTL]) {
  542                 if (cmd == SIOCSSTYPE)
  543                         printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n",
  544                             rq->sr_type, rq->sr_holdt, rq->sr_configt);
  545                 else
  546                         printf("snpac_ioctl: cmd get\n");
  547         }
  548 #endif
  549 
  550         if (cmd == SIOCSSTYPE) {
  551                 if (l == NULL || kauth_authorize_generic(l->l_cred,
  552                     KAUTH_GENERIC_ISSUSER, &l->l_acflag))
  553                         return (EPERM);
  554                 if ((rq->sr_type & (SNPA_ES | SNPA_IS)) == (SNPA_ES | SNPA_IS))
  555                         return (EINVAL);
  556                 if (rq->sr_type & SNPA_ES) {
  557                         iso_systype = SNPA_ES;
  558                 } else if (rq->sr_type & SNPA_IS) {
  559                         iso_systype = SNPA_IS;
  560                 } else {
  561                         return (EINVAL);
  562                 }
  563                 esis_holding_time = rq->sr_holdt;
  564                 esis_config_time = rq->sr_configt;
  565                 if (esis_esconfig_time != rq->sr_esconfigt) {
  566                         callout_stop(&esis_config_ch);
  567                         esis_esconfig_time = rq->sr_esconfigt;
  568                         esis_config(NULL);
  569                 }
  570         } else if (cmd == SIOCGSTYPE) {
  571                 rq->sr_type = iso_systype;
  572                 rq->sr_holdt = esis_holding_time;
  573                 rq->sr_configt = esis_config_time;
  574                 rq->sr_esconfigt = esis_esconfig_time;
  575         } else {
  576                 return (EINVAL);
  577         }
  578         return (0);
  579 }
  580 
  581 /*
  582  * FUNCTION:            snpac_logdefis
  583  *
  584  * PURPOSE:                     Mark the IS passed as the default IS
  585  *
  586  * RETURNS:                     nothing
  587  *
  588  * SIDE EFFECTS:
  589  *
  590  * NOTES:
  591  */
  592 void
  593 snpac_logdefis(struct rtentry *sc)
  594 {
  595         struct rtentry *rt;
  596 
  597         if (known_is == sc || !(sc->rt_flags & RTF_HOST))
  598                 return;
  599         if (known_is) {
  600                 RTFREE(known_is);
  601         }
  602         known_is = sc;
  603         sc->rt_refcnt++;
  604         rt = rtalloc1((struct sockaddr *) & zsi, 0);
  605         if (rt == 0)
  606                 rtrequest(RTM_ADD, sisotosa(&zsi), rt_key(sc), sisotosa(&zmk),
  607                           RTF_DYNAMIC | RTF_GATEWAY, 0);
  608         else {
  609                 if ((rt->rt_flags & RTF_DYNAMIC) &&
  610                     (rt->rt_flags & RTF_GATEWAY) && rt_mask(rt)->sa_len == 0)
  611                         rt_setgate(rt, rt_key(rt), rt_key(sc));
  612         }
  613 }
  614 
  615 /*
  616  * FUNCTION:            snpac_age
  617  *
  618  * PURPOSE:             Time out snpac entries
  619  *
  620  * RETURNS:
  621  *
  622  * SIDE EFFECTS:
  623  *
  624  * NOTES:               When encountering an entry for the first time, snpac_age
  625  *                      may delete up to SNPAC_AGE too many seconds. Ie.
  626  *                      if the entry is added a moment before snpac_age is
  627  *                      called, the entry will immediately have SNPAC_AGE
  628  *                      seconds taken off the holding time, even though
  629  *                      it has only been held a brief moment.
  630  *
  631  *                      The proper way to do this is set an expiry timeval
  632  *                      equal to current time + holding time. Then snpac_age
  633  *                      would time out entries where expiry date is older
  634  *                      than the current time.
  635  */
  636 /*ARGSUSED*/
  637 void
  638 snpac_age(void *v)
  639 {
  640         struct llinfo_llc *lc, *nlc;
  641         struct rtentry *rt;
  642 
  643         callout_reset(&snpac_age_ch, SNPAC_AGE * hz, snpac_age, NULL);
  644 
  645         for (lc = llinfo_llc.lh_first; lc != 0; lc = nlc) {
  646                 nlc = lc->lc_list.le_next;
  647                 if (lc->lc_flags & SNPA_VALID) {
  648                         rt = lc->lc_rt;
  649                         if (rt->rt_rmx.rmx_expire &&
  650                             rt->rt_rmx.rmx_expire < time_second)
  651                                 snpac_free(lc);
  652                 }
  653         }
  654 }
  655 
  656 /*
  657  * FUNCTION:            snpac_ownmulti
  658  *
  659  * PURPOSE:             Determine if the snpa address is a multicast address
  660  *                      of the same type as the system.
  661  *
  662  * RETURNS:             true or false
  663  *
  664  * SIDE EFFECTS:
  665  *
  666  * NOTES:               Used by interface drivers when not in eavesdrop mode
  667  *                      as interm kludge until
  668  *                      real multicast addresses can be configured
  669  */
  670 int
  671 snpac_ownmulti(caddr_t snpa, u_int len)
  672 {
  673         return (((iso_systype & SNPA_ES) &&
  674                  (!memcmp(snpa, all_es_snpa, len))) ||
  675                 ((iso_systype & SNPA_IS) &&
  676                  (!memcmp(snpa, all_is_snpa, len))));
  677 }
  678 
  679 /*
  680  * FUNCTION:            snpac_flushifp
  681  *
  682  * PURPOSE:             Flush entries associated with specific ifp
  683  *
  684  * RETURNS:             nothing
  685  *
  686  * SIDE EFFECTS:
  687  *
  688  * NOTES:
  689  */
  690 void
  691 snpac_flushifp(struct ifnet *ifp)
  692 {
  693         struct llinfo_llc *lc;
  694 
  695         for (lc = llinfo_llc.lh_first; lc != 0; lc = lc->lc_list.le_next) {
  696                 if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID))
  697                         snpac_free(lc);
  698         }
  699 }
  700 
  701 /*
  702  * FUNCTION:            snpac_rtrequest
  703  *
  704  * PURPOSE:             Make a routing request
  705  *
  706  * RETURNS:             nothing
  707  *
  708  * SIDE EFFECTS:
  709  *
  710  * NOTES:               In the future, this should make a request of a user
  711  *                      level routing daemon.
  712  */
  713 void
  714 snpac_rtrequest(int req, struct iso_addr *host, struct iso_addr *gateway,
  715         struct iso_addr *netmask, int flags, struct rtentry **ret_nrt)
  716 {
  717         struct iso_addr *r;
  718 
  719 #ifdef ARGO_DEBUG
  720         if (argo_debug[D_SNPA]) {
  721                 printf("snpac_rtrequest: ");
  722                 if (req == RTM_ADD)
  723                         printf("add");
  724                 else if (req == RTM_DELETE)
  725                         printf("delete");
  726                 else
  727                         printf("unknown command");
  728                 printf(" dst: %s\n", clnp_iso_addrp(host));
  729                 printf("\tgateway: %s\n", clnp_iso_addrp(gateway));
  730         }
  731 #endif
  732 
  733 
  734         zap_isoaddr(dst, host);
  735         zap_isoaddr(gte, gateway);
  736         if (netmask) {
  737                 zap_isoaddr(msk, netmask);
  738                 msk.siso_nlen = 0;
  739                 msk.siso_len = msk.siso_pad - (u_char *) & msk;
  740         }
  741         rtrequest(req, sisotosa(&dst), sisotosa(&gte),
  742         (netmask ? sisotosa(&msk) : (struct sockaddr *) 0), flags, ret_nrt);
  743 }
  744 
  745 /*
  746  * FUNCTION:            snpac_addrt
  747  *
  748  * PURPOSE:             Associate a routing entry with an snpac entry
  749  *
  750  * RETURNS:             nothing
  751  *
  752  * SIDE EFFECTS:
  753  *
  754  * NOTES:               If a cache entry exists for gateway, then
  755  *                      make a routing entry (host, gateway) and associate
  756  *                      with gateway.
  757  *
  758  *                      If a route already exists and is different, first delete
  759  *                      it.
  760  *
  761  *                      This could be made more efficient by checking
  762  *                      the existing route before adding a new one.
  763  */
  764 void
  765 snpac_addrt(struct ifnet *ifp, struct iso_addr *host,
  766     struct iso_addr *gateway, struct iso_addr *netmask)
  767 {
  768         struct iso_addr *r;
  769 
  770         zap_isoaddr(dst, host);
  771         zap_isoaddr(gte, gateway);
  772         if (netmask) {
  773                 zap_isoaddr(msk, netmask);
  774                 msk.siso_nlen = 0;
  775                 msk.siso_len = msk.siso_pad - (u_char *) & msk;
  776                 rtredirect(sisotosa(&dst), sisotosa(&gte), sisotosa(&msk),
  777                            RTF_DONE, sisotosa(&gte), 0);
  778         } else
  779                 rtredirect(sisotosa(&dst), sisotosa(&gte), (struct sockaddr *) 0,
  780                            RTF_DONE | RTF_HOST, sisotosa(&gte), 0);
  781 }
  782 #endif                          /* ISO */

Cache object: 53fdf239e668aef1193be68709b2cf05


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