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

Cache object: 04a1af1c1142f29fb7a49f142bf23a2c


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