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/netccitt/pk_llcsubr.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: pk_llcsubr.c,v 1.17 2005/02/26 22:45:10 perry Exp $    */
    2 
    3 /*
    4  * Copyright (c) 1992, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * Dirk Husemann and the Computer Science Department (IV) of
    9  * the University of Erlangen-Nuremberg, Germany.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  *      @(#)pk_llcsubr.c        8.2 (Berkeley) 2/9/95
   36  */
   37 
   38 /*
   39  * Copyright (c) 1990, 1991, 1992
   40  *              Dirk Husemann, Computer Science Department IV,
   41  *              University of Erlangen-Nuremberg, Germany.
   42  *
   43  * This code is derived from software contributed to Berkeley by
   44  * Dirk Husemann and the Computer Science Department (IV) of
   45  * the University of Erlangen-Nuremberg, Germany.
   46  *
   47  * Redistribution and use in source and binary forms, with or without
   48  * modification, are permitted provided that the following conditions
   49  * are met:
   50  * 1. Redistributions of source code must retain the above copyright
   51  *    notice, this list of conditions and the following disclaimer.
   52  * 2. Redistributions in binary form must reproduce the above copyright
   53  *    notice, this list of conditions and the following disclaimer in the
   54  *    documentation and/or other materials provided with the distribution.
   55  * 3. All advertising materials mentioning features or use of this software
   56  *    must display the following acknowledgement:
   57  *      This product includes software developed by the University of
   58  *      California, Berkeley and its contributors.
   59  * 4. Neither the name of the University nor the names of its contributors
   60  *    may be used to endorse or promote products derived from this software
   61  *    without specific prior written permission.
   62  *
   63  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   64  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   65  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   66  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   67  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   68  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   69  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   70  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   71  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   72  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   73  * SUCH DAMAGE.
   74  *
   75  *      @(#)pk_llcsubr.c        8.2 (Berkeley) 2/9/95
   76  */
   77 
   78 #include <sys/cdefs.h>
   79 __KERNEL_RCSID(0, "$NetBSD: pk_llcsubr.c,v 1.17 2005/02/26 22:45:10 perry Exp $");
   80 
   81 #include "opt_llc.h"
   82 
   83 #include <sys/param.h>
   84 #include <sys/systm.h>
   85 #include <sys/mbuf.h>
   86 #include <sys/domain.h>
   87 #include <sys/socket.h>
   88 #include <sys/socketvar.h>
   89 #include <sys/protosw.h>
   90 #include <sys/errno.h>
   91 #include <sys/time.h>
   92 #include <sys/kernel.h>
   93 
   94 #include <net/if.h>
   95 #include <net/if_dl.h>
   96 #include <net/if_llc.h>
   97 #include <net/if_types.h>
   98 #include <net/route.h>
   99 
  100 #include <netccitt/dll.h>
  101 #include <netccitt/x25.h>
  102 #include <netccitt/pk.h>
  103 #include <netccitt/pk_var.h>
  104 #include <netccitt/pk_extern.h>
  105 #include <netccitt/llc_var.h>
  106 
  107 
  108 /*
  109  * Routing support for X.25
  110  *
  111  * We distinguish between two cases:
  112  * RTF_HOST:
  113  *      rt_key(rt)      X.25 address of host
  114  *      rt_gateway      SNPA (MAC+DLSAP) address of host
  115  *      rt_llinfo       pkcb for rt_key(rt)
  116  *
  117  * RTF_GATEWAY
  118  *      rt_key(rt)      X.25 address of host or suitably masked network
  119  *      rt_gateway      X.25 address of next X.25 gateway (switch)
  120  *      rt_llinfo       rtentry for rt_gateway address
  121  *                      ought to be of type RTF_HOST
  122  *
  123  *
  124  * Mapping of X.121 to pkcbs:
  125  *
  126  * HDLC uses the DTE-DCE model of X.25, therefore we need a many-to-one
  127  * relationship, i.e.:
  128  *
  129  *      {X.121_a, X.121_b, X.121_c, ..., X.121_i} -> pkcb_0
  130  *
  131  * LLC2 uses the DTE-DTE model of X.25, resulting effectively in a
  132  * one-to-one relationship, i.e.:
  133  *
  134  *      {X.121_j}       ->      pkcb_1a
  135  *      {X.121_k}       ->      pkcb_1b
  136  *      ...
  137  *      {X.121_q}       ->      pkcb_1q
  138  *
  139  * It might make sense to allow a many-to-one relation for LLC2 also,
  140  *
  141  *      {X.121_r, X.121_s, X.121_t, X.121_u} -> pkcb_2a
  142  *
  143  * This would make addresses X.121_[r-u] essentially aliases of one
  144  * address ({X.121_[r-u]} would constitute a representative set).
  145  *
  146  * Each one-to-one relation must obviously be entered individually with
  147  * a route add command, whereas a many-to-one relationship can be
  148  * either entered individually or generated by using a netmask.
  149  *
  150  * To facilitate dealings the many-to-one case for LLC2 can only be
  151  * established via a netmask.
  152  *
  153  */
  154 
  155 #define XTRACTPKP(rt)   ((rt)->rt_flags & RTF_GATEWAY ? \
  156                          ((rt)->rt_llinfo ? \
  157                           (struct pkcb *) ((struct rtentry *)((rt)->rt_llinfo))->rt_llinfo : \
  158                           (struct pkcb *) NULL) : \
  159                          (struct pkcb *)((rt)->rt_llinfo))
  160 
  161 #define equal(a1, a2) (bcmp((caddr_t)(a1), \
  162                                (caddr_t)(a2), \
  163                                (a1)->sa_len) == 0)
  164 #define XIFA(rt) ((struct x25_ifaddr *)((rt)->rt_ifa))
  165 #define SA(s) ((struct sockaddr *)s)
  166 
  167 static int cons_rtrequest_internal __P((int, struct rtentry *,
  168     struct rt_addrinfo *));
  169 
  170 /*
  171  * ifa_rtrequest currently does not check the error from the rtrequest call
  172  * so we use a void version of the cons_rtrequest routine.
  173  */
  174 void
  175 cons_rtrequest(cmd, rt, info)
  176         int             cmd;
  177         struct rtentry *rt;
  178         struct rt_addrinfo *info;
  179 {
  180         cons_rtrequest_internal(cmd, rt, info);
  181 }
  182 
  183 
  184 static int
  185 cons_rtrequest_internal(cmd, rt, info)
  186         int             cmd;
  187         struct rtentry *rt;
  188         struct rt_addrinfo *info;
  189 {
  190         struct pkcb *pkp;
  191         char   one_to_one;
  192 
  193         pkp = XTRACTPKP(rt);
  194 
  195         switch (cmd) {
  196         case RTM_RESOLVE:
  197         case RTM_ADD:
  198                 if (pkp)
  199                         return (EEXIST);
  200 
  201                 if (rt->rt_flags & RTF_GATEWAY) {
  202                         if (rt->rt_llinfo)
  203                                 RTFREE((struct rtentry *) rt->rt_llinfo);
  204                         rt->rt_llinfo = (caddr_t) rtalloc1(rt->rt_gateway, 1);
  205                         return (0);
  206                 }
  207                 /*
  208                  * Assumptions: (1) ifnet structure is filled in
  209                  *              (2) at least the pkcb created via
  210                  *                  x25config (ifconfig?) has been
  211                  *                  set up already.
  212                  *              (3) HDLC interfaces have an if_type of
  213                  *                  IFT_X25{,DDN}, LLC2 interfaces
  214                  *                  anything else (any better way to
  215                  *                  do this?)
  216                  *
  217                  */
  218                 if (!rt->rt_ifa)
  219                         return (ENETDOWN);
  220 
  221                 /*
  222                  * We differentiate between dealing with a many-to-one (HDLC:
  223                  * DTE-DCE) and a one-to-one (LLC2: DTE-DTE) relationship (by
  224                  * looking at the if type).
  225                  *
  226                  * Only in case of the many-to-one relationship (HDLC) we set
  227                  * the ia->ia_pkcb pointer to the pkcb allocated via
  228                  * pk_newlink() as we will use just that one pkcb for future
  229                  * route additions (the rtentry->rt_llinfo pointer points to
  230                  * the pkcb allocated for that route).
  231                  *
  232                  * In case of the one-to-one relationship (LLC2) we create a new
  233                  * pkcb (via pk_newlink()) for each new rtentry.
  234                  *
  235                  * NOTE: Only in case of HDLC does ia->ia_pkcb point to a pkcb,
  236                  * in the LLC2 case it doesn't (as we don't need it here)!
  237                  */
  238                 one_to_one = ISISO8802(rt->rt_ifp);
  239 
  240                 if (!(pkp = XIFA(rt)->ia_pkcb) && !one_to_one)
  241                         XIFA(rt)->ia_pkcb = pkp =
  242                                 pk_newlink(XIFA(rt), (caddr_t) 0);
  243                 else if (one_to_one &&
  244                          !equal(rt->rt_gateway, rt->rt_ifa->ifa_addr)) {
  245                         pkp = pk_newlink(XIFA(rt), (caddr_t) 0);
  246                         /*
  247                          * We also need another route entry for mapping
  248                          * MAC+LSAP->X.25 address
  249                          */
  250                         pkp->pk_llrt = npaidb_enter((struct sockaddr_dl *)
  251                                                     rt->rt_gateway, rt_key(rt),
  252                                                     rt, 0);
  253                 }
  254                 if (pkp) {
  255                         if (!pkp->pk_rt)
  256                                 pkp->pk_rt = rt;
  257                         pkp->pk_refcount++;
  258                 }
  259                 rt->rt_llinfo = (caddr_t) pkp;
  260 
  261                 return (0);
  262 
  263         case RTM_DELETE:
  264                 {
  265                         /*
  266                          * The pkp might be empty if we are dealing
  267                          * with an interface route entry for LLC2, in this
  268                          * case we don't need to do anything ...
  269                          */
  270                         if (pkp) {
  271                                 if (rt->rt_flags & RTF_GATEWAY) {
  272                                         if (rt->rt_llinfo)
  273                                                 RTFREE((struct rtentry *) rt->rt_llinfo);
  274                                         return (0);
  275                                 }
  276                                 if (pkp->pk_llrt)
  277                                         npaidb_destroy(pkp->pk_llrt);
  278 
  279                                 pk_dellink(pkp);
  280 
  281                                 return (0);
  282                         }
  283                 }
  284         }
  285         return 0;
  286 }
  287 
  288 /*
  289  * Network Protocol Addressing Information DataBase (npaidb)
  290  *
  291  * To speed up locating the entity dealing with an LLC packet use is made
  292  * of a routing tree. This npaidb routing tree is handled
  293  * by the normal rn_*() routines just like (almost) any other routing tree.
  294  *
  295  * The mapping being done by the npaidb_*() routines is as follows:
  296  *
  297  *     Key:       MAC,LSAP (enhancing struct sockaddr_dl)
  298  *     Gateway:   sockaddr_x25 (i.e. X.25 address - X.121 or NSAP)
  299  *     Llinfo:    npaidbentry {
  300  *                         struct llc_linkcb *npaidb_linkp;
  301  *                         struct rtentry *npaidb_rt;
  302  *                }
  303  *
  304  * Using the npaidbentry provided by llinfo we can then access
  305  *
  306  *       o the pkcb by using (struct pkcb *) (npaidb_rt->rt_llinfo)
  307  *       o the linkcb via npaidb_linkp
  308  *
  309  * The following functions are provided
  310  *
  311  *       o npaidb_enter(struct sockaddr_dl *sdl, struct sockaddr_x25 *sx25,
  312  *                      struct struct llc_linkcb *link, struct rtentry *rt)
  313  *
  314  *       o npaidb_enrich(short type, caddr_t info)
  315  *
  316  */
  317 
  318 struct sockaddr_dl npdl_netmask = {
  319         sizeof(struct sockaddr_dl),     /* _len */
  320         0,                      /* _family */
  321         0,                      /* _index */
  322         0,                      /* _type */
  323         -1,                     /* _nlen */
  324         -1,                     /* _alen */
  325         -1,                     /* _slen */
  326         {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},       /* _data */
  327 };
  328 struct sockaddr npdl_dummy;
  329 
  330 int             npdl_datasize = sizeof(struct sockaddr_dl) -
  331 ((int) ((unsigned long)&((struct sockaddr_dl *) 0)->sdl_data[0]));
  332 
  333 struct rtentry *
  334 npaidb_enter(key, value, rt, link)
  335         struct sockaddr_dl *key;
  336         struct sockaddr *value;
  337         struct rtentry *rt;
  338         struct llc_linkcb *link;
  339 {
  340         struct rtentry *nprt;
  341         int    i;
  342 
  343         USES_AF_LINK_RTS;
  344 
  345         if ((nprt = rtalloc1(SA(key), 0)) == 0) {
  346                 u_int  size = sizeof(struct npaidbentry);
  347                 u_char saploc = LLSAPLOC(key, rt->rt_ifp);
  348 
  349                 /*
  350                  * set up netmask: LLC2 packets have the lowest bit set in
  351                  * response packets (e.g. 0x7e for command packets, 0x7f for
  352                  * response packets), to facilitate the lookup we use a
  353                  * netmask of 11111110 for the SAP position. The remaining
  354                  * positions are zeroed out.
  355                  */
  356                 npdl_netmask.sdl_data[saploc] = NPDL_SAPNETMASK;
  357                 bzero((caddr_t) & npdl_netmask.sdl_data[saploc + 1],
  358                       npdl_datasize - saploc - 1);
  359 
  360                 if (value == 0)
  361                         value = &npdl_dummy;
  362 
  363                 /* now enter it */
  364                 rtrequest(RTM_ADD, SA(key), SA(value),
  365                           SA(&npdl_netmask), 0, &nprt);
  366 
  367                 /* and reset npdl_netmask */
  368                 for (i = saploc; i < npdl_datasize; i++)
  369                         npdl_netmask.sdl_data[i] = -1;
  370 
  371                 nprt->rt_llinfo = malloc(size, M_PCB, M_WAITOK|M_ZERO);
  372                 if (nprt->rt_llinfo) {
  373                         ((struct npaidbentry *) (nprt->rt_llinfo))->np_rt = rt;
  374                 }
  375         } else
  376                 nprt->rt_refcnt--;
  377         return nprt;
  378 }
  379 
  380 struct rtentry *
  381 npaidb_enrich(type, info, sdl)
  382         short           type;
  383         caddr_t         info;
  384         struct sockaddr_dl *sdl;
  385 {
  386         struct rtentry *rt;
  387 
  388         USES_AF_LINK_RTS;
  389 
  390         if ((rt = rtalloc1((struct sockaddr *) sdl, 0)) != NULL) {
  391                 rt->rt_refcnt--;
  392                 switch (type) {
  393                 case NPAIDB_LINK:
  394                         ((struct npaidbentry *) (rt->rt_llinfo))->np_link =
  395                                 (struct llc_linkcb *) info;
  396                         break;
  397                 }
  398                 return rt;
  399         }
  400         return ((struct rtentry *) 0);
  401 
  402 }
  403 
  404 int
  405 npaidb_destroy(rt)
  406         struct rtentry *rt;
  407 {
  408         USES_AF_LINK_RTS;
  409 
  410         if (rt->rt_llinfo)
  411                 free((caddr_t) rt->rt_llinfo, M_PCB);
  412         return (rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
  413                           0, 0));
  414 }
  415 
  416 
  417 #ifdef LLC
  418 /*
  419  * Glue between X.25 and LLC2
  420  */
  421 long
  422 x25_llcglue(prc, addr)
  423         int             prc;
  424         struct sockaddr *addr;
  425 {
  426         struct x25_ifaddr *x25ifa;
  427         struct dll_ctlinfo ctlinfo;
  428         long rv;
  429 
  430         if ((x25ifa = (struct x25_ifaddr *) ifa_ifwithaddr(addr)) == 0)
  431                 return 0;
  432 
  433         ctlinfo.dlcti_cfg = (struct dllconfig *)
  434             (((struct sockaddr_x25 *) (&x25ifa->ia_xc)) + 1);
  435         ctlinfo.dlcti_lsap = LLC_X25_LSAP;
  436 
  437         rv = (long) llc_ctlinput(prc, addr, &ctlinfo);
  438 
  439         return (rv);
  440 }
  441 #endif                          /* LLC */

Cache object: a3b1a1e17d87b1ae8fb94cecc938e6dd


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