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

Cache object: af9f47bcea35da9f022b2ce772dff1e6


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