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/clnp_output.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: clnp_output.c,v 1.14 2003/08/07 16:33:33 agc 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  *      @(#)clnp_output.c       8.1 (Berkeley) 6/10/93
   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: clnp_output.c,v 1.14 2003/08/07 16:33:33 agc Exp $");
   63 
   64 #include <sys/param.h>
   65 #include <sys/mbuf.h>
   66 #include <sys/domain.h>
   67 #include <sys/protosw.h>
   68 #include <sys/socket.h>
   69 #include <sys/socketvar.h>
   70 #include <sys/errno.h>
   71 #include <sys/time.h>
   72 #include <sys/systm.h>
   73 
   74 #include <net/if.h>
   75 #include <net/route.h>
   76 
   77 #include <netiso/iso.h>
   78 #include <netiso/iso_var.h>
   79 #include <netiso/iso_pcb.h>
   80 #include <netiso/clnp.h>
   81 #include <netiso/clnp_stat.h>
   82 #include <netiso/argo_debug.h>
   83 
   84 #include <machine/stdarg.h>
   85 
   86 static struct clnp_fixed dt_template = {
   87         ISO8473_CLNP,           /* network identifier */
   88         0,                      /* length */
   89         ISO8473_V1,             /* version */
   90         CLNP_TTL,               /* ttl */
   91         CLNP_DT | CNF_SEG_OK | CNF_ERR_OK,      /* type */
   92         0,                      /* segment length */
   93         0                       /* checksum */
   94 };
   95 
   96 static struct clnp_fixed raw_template = {
   97         ISO8473_CLNP,           /* network identifier */
   98         0,                      /* length */
   99         ISO8473_V1,             /* version */
  100         CLNP_TTL,               /* ttl */
  101         CLNP_RAW | CNF_SEG_OK | CNF_ERR_OK,     /* type */
  102         0,                      /* segment length */
  103         0                       /* checksum */
  104 };
  105 
  106 static struct clnp_fixed echo_template = {
  107         ISO8473_CLNP,           /* network identifier */
  108         0,                      /* length */
  109         ISO8473_V1,             /* version */
  110         CLNP_TTL,               /* ttl */
  111         CLNP_EC | CNF_SEG_OK | CNF_ERR_OK,      /* type */
  112         0,                      /* segment length */
  113         0                       /* checksum */
  114 };
  115 
  116 static struct clnp_fixed echor_template = {
  117         ISO8473_CLNP,           /* network identifier */
  118         0,                      /* length */
  119         ISO8473_V1,             /* version */
  120         CLNP_TTL,               /* ttl */
  121         CLNP_ECR | CNF_SEG_OK | CNF_ERR_OK,     /* type */
  122         0,                      /* segment length */
  123         0                       /* checksum */
  124 };
  125 
  126 #ifdef  DECBIT
  127 u_char          qos_option[] = {CLNPOVAL_QOS, 1,
  128 CLNPOVAL_GLOBAL | CLNPOVAL_SEQUENCING | CLNPOVAL_LOWDELAY};
  129 #endif                          /* DECBIT */
  130 
  131 int             clnp_id = 0;    /* id for segmented dgrams */
  132 
  133 /*
  134  * FUNCTION:            clnp_output
  135  *
  136  * PURPOSE:             output the data in the mbuf as a clnp datagram
  137  *
  138  *                      The data specified by m0 is sent as a clnp datagram.
  139  *                      The mbuf chain m0 will be freed when this routine has
  140  *                      returned.
  141  *
  142  *                      If options is non-null, it points to an mbuf which
  143  *                      contains options to be sent with the datagram. The
  144  *                      options must be formatted in the mbuf according to
  145  *                      clnp rules. Options will not be freed.
  146  *
  147  *                      Datalen specifies the length of the data in m0.
  148  *
  149  *                      Src and dst are the addresses for the packet.
  150  *
  151  *                      If route is non-null, it is used as the route for
  152  *                      the packet.
  153  *
  154  *                      By default, a DT is sent. However,
  155  *                      if flags & CNLP_SEND_ER then an ER will be sent.
  156  *                      If flags & CLNP_SEND_RAW, then the packet will
  157  *                      be send as raw clnp.
  158  *
  159  * RETURNS:             0       success
  160  *                              appropriate error code
  161  *
  162  * SIDE EFFECTS:        none
  163  *
  164  * NOTES:               Flags are interpretated as follows:
  165  *                      CLNP_NO_SEG - do not allow this pkt to be segmented.
  166  *                      CLNP_NO_ER  - have pkt request ER suppression.
  167  *                      CLNP_SEND_RAW - send pkt as RAW DT rather than TP DT
  168  *                      CLNP_NO_CKSUM - don't compute clnp checksum
  169  *                      CLNP_ECHO - send as ECHO packet
  170  *
  171  *                      When checking for a cached packet, clnp checks
  172  *                      that the route taken is still up. It does not
  173  *                      check that the route is still to the same destination.
  174  *                      This means that any entity that alters an existing
  175  *                      route for an isopcb (such as when a redirect arrives)
  176  *                      must invalidate the clnp cache. It might be perferable
  177  *                      to have clnp check that the route has the same dest, but
  178  *                      by avoiding this check, we save a call to
  179  *                      iso_addrmatch1.
  180  */
  181 int
  182 #if __STDC__
  183 clnp_output(struct mbuf *m0, ...)
  184 #else
  185 clnp_output(m0, va_alist)
  186         struct mbuf    *m0;     /* data for the packet */
  187         va_dcl
  188 #endif
  189 {
  190         struct isopcb  *isop;   /* iso pcb */
  191         int             datalen;/* number of bytes of data in m0 */
  192         int             flags;  /* flags */
  193         int             error = 0;      /* return value of function */
  194         struct mbuf *m = m0;            /* mbuf for clnp header chain */
  195         struct clnp_fixed *clnp;        /* ptr to fixed part of hdr */
  196         caddr_t hoff;                   /* offset into header */
  197         int             total_len;      /* total length of packet */
  198         struct iso_addr *src;   /* ptr to source address */
  199         struct iso_addr *dst;   /* ptr to destination address */
  200         struct clnp_cache clc;  /* storage for cache information */
  201         struct clnp_cache *clcp = NULL; /* ptr to clc */
  202         int             hdrlen = 0;
  203         va_list ap;
  204 
  205         va_start(ap, m0);
  206         isop = va_arg(ap, struct isopcb  *);
  207         datalen = va_arg(ap, int);
  208         flags = va_arg(ap, int);
  209         va_end(ap);
  210 
  211         dst = &isop->isop_faddr->siso_addr;
  212         if (isop->isop_laddr == 0) {
  213                 struct iso_ifaddr *ia = 0;
  214                 clnp_route(dst, &isop->isop_route, flags, 0, &ia);
  215                 if (ia == 0 || ia->ia_ifa.ifa_addr->sa_family != AF_ISO)
  216                         return (ENETUNREACH);
  217                 src = &ia->ia_addr.siso_addr;
  218         } else
  219                 src = &isop->isop_laddr->siso_addr;
  220 
  221 #ifdef ARGO_DEBUG
  222         if (argo_debug[D_OUTPUT]) {
  223                 printf("clnp_output: to %s", clnp_iso_addrp(dst));
  224                 printf(" from %s of %d bytes\n", clnp_iso_addrp(src), datalen);
  225                 printf("\toptions %p, flags x%x, isop_clnpcache %p\n",
  226                     isop->isop_options, flags, isop->isop_clnpcache);
  227         }
  228 #endif
  229 
  230         if (isop->isop_clnpcache != NULL) {
  231                 clcp = mtod(isop->isop_clnpcache, struct clnp_cache *);
  232         }
  233         /*
  234          *      Check if cache is valid ...
  235          */
  236 #ifdef ARGO_DEBUG
  237         if (argo_debug[D_OUTPUT]) {
  238                 printf("clnp_output: ck cache: clcp %p\n", clcp);
  239                 if (clcp != NULL) {
  240                         printf("\tclc_dst %s\n", clnp_iso_addrp(&clcp->clc_dst));
  241                         printf("\tisop_opts %p, clc_opts %p\n",
  242                             isop->isop_options, clcp->clc_options);
  243                         if (isop->isop_route.ro_rt)
  244                                 printf("\tro_rt %p, rt_flags x%x\n",
  245                                     isop->isop_route.ro_rt,
  246                                     isop->isop_route.ro_rt->rt_flags);
  247                         printf("\tflags x%x, clc_flags x%x\n", flags,
  248                             clcp->clc_flags);
  249                         printf("\tclc_hdr %p\n", clcp->clc_hdr);
  250                 }
  251         }
  252 #endif
  253         if ((clcp != NULL) &&   /* cache exists */
  254             (isop->isop_options == clcp->clc_options) &&        /* same options */
  255             (iso_addrmatch1(dst, &clcp->clc_dst)) &&    /* dst still same */
  256             (isop->isop_route.ro_rt != NULL) && /* route exists */
  257             (isop->isop_route.ro_rt == clcp->clc_rt) && /* and is cached */
  258             (isop->isop_route.ro_rt->rt_flags & RTF_UP) &&      /* route still up */
  259             (flags == clcp->clc_flags) &&       /* same flags */
  260             (clcp->clc_hdr != NULL)) {  /* hdr mbuf exists */
  261                 /*
  262                  * The cache is valid
  263                  */
  264 
  265 #ifdef ARGO_DEBUG
  266                 if (argo_debug[D_OUTPUT]) {
  267                         printf("clnp_output: using cache\n");
  268                 }
  269 #endif
  270 
  271                 m = m_copy(clcp->clc_hdr, 0, (int) M_COPYALL);
  272                 if (m == NULL) {
  273                         /*
  274                          * No buffers left to copy cached packet header. Use
  275                          * the cached packet header this time, and
  276                          * mark the hdr as vacant
  277                          */
  278                         m = clcp->clc_hdr;
  279                         clcp->clc_hdr = NULL;
  280                 }
  281                 m->m_next = m0; /* ASSUMES pkt hdr is 1 mbuf long */
  282                 clnp = mtod(m, struct clnp_fixed *);
  283         } else {
  284                 struct clnp_optidx *oidx = NULL;        /* index to clnp options */
  285 
  286                 /*
  287                  * The cache is not valid. Allocate an mbuf (if necessary)
  288                  * to hold cached info. If one is not available, then
  289                  * don't bother with the cache
  290                  */
  291                 INCSTAT(cns_cachemiss);
  292                 if (flags & CLNP_NOCACHE) {
  293                         clcp = &clc;
  294                 } else {
  295                         if (isop->isop_clnpcache == NULL) {
  296                                 /*
  297                                  * There is no clnpcache. Allocate an mbuf
  298                                  * to hold one
  299                                  */
  300                                 if ((isop->isop_clnpcache = m_get(M_DONTWAIT, MT_HEADER))
  301                                     == NULL) {
  302                                         /*
  303                                          * No mbufs available. Pretend that we
  304                                          * don't want caching this time.
  305                                          */
  306 #ifdef ARGO_DEBUG
  307                                         if (argo_debug[D_OUTPUT]) {
  308                                                 printf("clnp_output: no mbufs to allocate to cache\n");
  309                                         }
  310 #endif
  311                                         flags |= CLNP_NOCACHE;
  312                                         clcp = &clc;
  313                                 } else {
  314                                         clcp = mtod(isop->isop_clnpcache, struct clnp_cache *);
  315                                 }
  316                         } else {
  317                                 /*
  318                                  * A clnpcache mbuf exists. If the clc_hdr
  319                                  * is not null, we must free it, as a new one
  320                                  * is about to be created.
  321                                  */
  322                                 clcp = mtod(isop->isop_clnpcache, struct clnp_cache *);
  323                                 if (clcp->clc_hdr != NULL) {
  324                                         /*
  325                                          * The clc_hdr is not null but a
  326                                          * clnpcache mbuf exists. This means
  327                                          * that there was a cache, but the
  328                                          * existing copy of the hdr is no
  329                                          * longer valid. Free it now
  330                                          * before we lose the pointer to it.
  331                                          */
  332 #ifdef ARGO_DEBUG
  333                                         if (argo_debug[D_OUTPUT]) {
  334                                                 printf(
  335                                     "clnp_output: freeing old clc_hdr %p\n",
  336                                                clcp->clc_hdr);
  337                                         }
  338 #endif
  339                                         m_free(clcp->clc_hdr);
  340 #ifdef ARGO_DEBUG
  341                                         if (argo_debug[D_OUTPUT]) {
  342                                                 printf("clnp_output: freed old clc_hdr (done)\n");
  343                                         }
  344 #endif
  345                                 }
  346                         }
  347                 }
  348 #ifdef ARGO_DEBUG
  349                 if (argo_debug[D_OUTPUT]) {
  350                         printf("clnp_output: NEW clcp %p\n", clcp);
  351                 }
  352 #endif
  353                 bzero((caddr_t) clcp, sizeof(struct clnp_cache));
  354 
  355                 if (isop->isop_optindex)
  356                         oidx = mtod(isop->isop_optindex, struct clnp_optidx *);
  357 
  358                 /*
  359                  * Don't allow packets with security, quality of service,
  360                  * priority, or error report options to be sent.
  361                  */
  362                 if ((isop->isop_options) && (oidx)) {
  363                         if ((oidx->cni_securep) ||
  364                             (oidx->cni_priorp) ||
  365                             (oidx->cni_qos_formatp) ||
  366                             (oidx->cni_er_reason != ER_INVALREAS)) {
  367 #ifdef ARGO_DEBUG
  368                                 if (argo_debug[D_OUTPUT]) {
  369                                         printf("clnp_output: pkt dropped - option unsupported\n");
  370                                 }
  371 #endif
  372                                 m_freem(m0);
  373                                 return (EINVAL);
  374                         }
  375                 }
  376                 /*
  377                  * Don't allow any invalid flags to be set
  378                  */
  379                 if ((flags & (CLNP_VFLAGS)) != flags) {
  380 #ifdef ARGO_DEBUG
  381                         if (argo_debug[D_OUTPUT]) {
  382                                 printf("clnp_output: packet dropped - flags unsupported\n");
  383                         }
  384 #endif
  385                         INCSTAT(cns_odropped);
  386                         m_freem(m0);
  387                         return (EINVAL);
  388                 }
  389                 /*
  390                  * Don't allow funny lengths on dst; src may be zero in which
  391                  * case we insert the source address based upon the interface
  392                  */
  393                 if ((src->isoa_len > sizeof(struct iso_addr)) ||
  394                     (dst->isoa_len == 0) ||
  395                     (dst->isoa_len > sizeof(struct iso_addr))) {
  396                         m_freem(m0);
  397                         INCSTAT(cns_odropped);
  398                         return (ENAMETOOLONG);
  399                 }
  400                 /*
  401                  *      Grab mbuf to contain header
  402                  */
  403                 MGETHDR(m, M_DONTWAIT, MT_HEADER);
  404                 if (m == 0) {
  405                         m_freem(m0);
  406                         INCSTAT(cns_odropped);
  407                         return (ENOBUFS);
  408                 }
  409                 INCSTAT(cns_sent);
  410                 m->m_next = m0;
  411                 clnp = mtod(m, struct clnp_fixed *);
  412                 clcp->clc_segoff = 0;
  413 
  414                 /*
  415                  * Fill in all of fixed hdr except lengths and checksum
  416                  */
  417                 if (flags & CLNP_SEND_RAW) {
  418                         *clnp = raw_template;
  419                 } else if (flags & CLNP_ECHO) {
  420                         *clnp = echo_template;
  421                 } else if (flags & CLNP_ECHOR) {
  422                         *clnp = echor_template;
  423                 } else {
  424                         *clnp = dt_template;
  425                 }
  426                 if (flags & CLNP_NO_SEG)
  427                         clnp->cnf_type &= ~CNF_SEG_OK;
  428                 if (flags & CLNP_NO_ER)
  429                         clnp->cnf_type &= ~CNF_ERR_OK;
  430 
  431                 /*
  432                  *      Route packet; special case for source rt
  433                  */
  434                 if ((isop->isop_options) && CLNPSRCRT_VALID(oidx)) {
  435 #ifdef ARGO_DEBUG
  436                         if (argo_debug[D_OUTPUT]) {
  437                                 printf("clnp_output: calling clnp_srcroute\n");
  438                         }
  439 #endif
  440                         error = clnp_srcroute(isop->isop_options, oidx, &isop->isop_route,
  441                                   &clcp->clc_firsthop, &clcp->clc_ifa, dst);
  442                 } else {
  443 #ifdef ARGO_DEBUG
  444                         if (argo_debug[D_OUTPUT]) {
  445                         }
  446 #endif
  447                         error = clnp_route(dst, &isop->isop_route, flags,
  448                                        &clcp->clc_firsthop, &clcp->clc_ifa);
  449                 }
  450                 if (error || (clcp->clc_ifa == 0)) {
  451 #ifdef ARGO_DEBUG
  452                         if (argo_debug[D_OUTPUT]) {
  453                                 printf("clnp_output: route failed, errno %d\n", error);
  454                                 printf("@clcp:\n");
  455                                 dump_buf(clcp, sizeof(struct clnp_cache));
  456                         }
  457 #endif
  458                         goto bad;
  459                 }
  460                 clcp->clc_rt = isop->isop_route.ro_rt;  /* XXX */
  461                 clcp->clc_ifp = clcp->clc_ifa->ia_ifp;  /* XXX */
  462 
  463 #ifdef ARGO_DEBUG
  464                 if (argo_debug[D_OUTPUT]) {
  465                         printf("clnp_output: packet routed to %s\n",
  466                             clnp_iso_addrp(
  467                                  &satosiso(clcp->clc_firsthop)->siso_addr));
  468                 }
  469 #endif
  470 
  471                 /*
  472                  * If src address is not yet specified, use address of
  473                  * interface. NOTE: this will now update the laddr field in
  474                  * the isopcb. Is this desirable? RAH?
  475                  */
  476                 if (src->isoa_len == 0) {
  477                         src = &(clcp->clc_ifa->ia_addr.siso_addr);
  478 #ifdef ARGO_DEBUG
  479                         if (argo_debug[D_OUTPUT]) {
  480                                 printf("clnp_output: new src %s\n", clnp_iso_addrp(src));
  481                         }
  482 #endif
  483                 }
  484                 /*
  485                  * Insert the source and destination address,
  486                  */
  487                 hoff = (caddr_t) clnp + sizeof(struct clnp_fixed);
  488                 CLNP_INSERT_ADDR(hoff, *dst);
  489                 CLNP_INSERT_ADDR(hoff, *src);
  490 
  491                 /*
  492                  * Leave room for the segment part, if segmenting is selected
  493                  */
  494                 if (clnp->cnf_type & CNF_SEG_OK) {
  495                         clcp->clc_segoff = hoff - (caddr_t) clnp;
  496                         hoff += sizeof(struct clnp_segment);
  497                 }
  498                 clnp->cnf_hdr_len = m->m_len = (u_char) (hoff - (caddr_t) clnp);
  499                 hdrlen = clnp->cnf_hdr_len;
  500 
  501 #ifdef  DECBIT
  502                 /*
  503                  * Add the globally unique QOS (with room for congestion
  504                  * experienced bit). I can safely assume that this option
  505                  * is not in the options mbuf below because I checked that
  506                  * the option was not specified previously
  507                  */
  508                 if ((m->m_len + sizeof(qos_option)) < MLEN) {
  509                         bcopy((caddr_t) qos_option, hoff, sizeof(qos_option));
  510                         clnp->cnf_hdr_len += sizeof(qos_option);
  511                         hdrlen += sizeof(qos_option);
  512                         m->m_len += sizeof(qos_option);
  513                 }
  514 #endif                          /* DECBIT */
  515 
  516                 /*
  517                  * If an options mbuf is present, concatenate a copy to the hdr mbuf.
  518                  */
  519                 if (isop->isop_options) {
  520                         struct mbuf    *opt_copy =
  521                                 m_copy(isop->isop_options, 0, (int) M_COPYALL);
  522                         if (opt_copy == NULL) {
  523                                 error = ENOBUFS;
  524                                 goto bad;
  525                         }
  526                         /* Link in place */
  527                         opt_copy->m_next = m->m_next;
  528                         m->m_next = opt_copy;
  529 
  530                         /* update size of header */
  531                         clnp->cnf_hdr_len += opt_copy->m_len;
  532                         hdrlen += opt_copy->m_len;
  533                 }
  534                 if (hdrlen > CLNP_HDR_MAX) {
  535                         error = EMSGSIZE;
  536                         goto bad;
  537                 }
  538                 /*
  539                  * Now set up the cache entry in the pcb
  540                  */
  541                 if ((flags & CLNP_NOCACHE) == 0) {
  542                         clcp->clc_hdr = m_copy(m, 0, (int) clnp->cnf_hdr_len);
  543                         if (clcp->clc_hdr) {
  544                                 clcp->clc_dst = *dst;
  545                                 clcp->clc_flags = flags;
  546                                 clcp->clc_options = isop->isop_options;
  547                         }
  548                 }
  549         }
  550         /*
  551          *      If small enough for interface, send directly
  552          *      Fill in segmentation part of hdr if using the full protocol
  553          */
  554         total_len = clnp->cnf_hdr_len + datalen;
  555         if (clnp->cnf_type & CNF_SEG_OK) {
  556                 struct clnp_segment seg_part;   /* segment part of hdr */
  557                 seg_part.cng_id = htons(clnp_id++);
  558                 seg_part.cng_off = htons(0);
  559                 seg_part.cng_tot_len = htons(total_len);
  560                 (void) bcopy((caddr_t) & seg_part, (caddr_t) clnp + clcp->clc_segoff,
  561                              sizeof(seg_part));
  562         }
  563         if (total_len <= SN_MTU(clcp->clc_ifp, clcp->clc_rt)) {
  564                 HTOC(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, total_len);
  565                 m->m_pkthdr.len = total_len;
  566                 /*
  567                  *      Compute clnp checksum (on header only)
  568                  */
  569                 if (flags & CLNP_NO_CKSUM) {
  570                         HTOC(clnp->cnf_cksum_msb, clnp->cnf_cksum_lsb, 0);
  571                 } else {
  572                         iso_gen_csum(m, CLNP_CKSUM_OFF, (int) clnp->cnf_hdr_len);
  573                 }
  574 
  575 #ifdef ARGO_DEBUG
  576                 if (argo_debug[D_DUMPOUT]) {
  577                         struct mbuf    *mdump = m;
  578                         printf("clnp_output: sending dg:\n");
  579                         while (mdump != NULL) {
  580                                 dump_buf(mtod(mdump, caddr_t), mdump->m_len);
  581                                 mdump = mdump->m_next;
  582                         }
  583                 }
  584 #endif
  585 
  586                 error = SN_OUTPUT(clcp, m);
  587                 goto done;
  588         } else {
  589                 /*
  590                  * Too large for interface; fragment if possible.
  591                  */
  592                 error = clnp_fragment(clcp->clc_ifp, m, clcp->clc_firsthop,
  593                           total_len, clcp->clc_segoff, flags, clcp->clc_rt);
  594                 goto done;
  595         }
  596 bad:
  597         m_freem(m);
  598 done:
  599         if (error) {
  600                 clnp_stat.cns_sent--;
  601                 clnp_stat.cns_odropped++;
  602         }
  603         return (error);
  604 }
  605 
  606 void
  607 clnp_ctloutput()
  608 {
  609 }

Cache object: 95ac609333a8b1382abcbad6812d073b


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