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-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: clnp_output.c,v 1.15 2004/04/19 05:16:45 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  *      @(#)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.15 2004/04/19 05:16:45 matt 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 clnp_output(struct mbuf *m0, ...)
  183 {
  184         struct isopcb  *isop;   /* iso pcb */
  185         int             datalen;/* number of bytes of data in m0 */
  186         int             flags;  /* flags */
  187         int             error = 0;      /* return value of function */
  188         struct mbuf *m = m0;            /* mbuf for clnp header chain */
  189         struct clnp_fixed *clnp;        /* ptr to fixed part of hdr */
  190         caddr_t hoff;                   /* offset into header */
  191         int             total_len;      /* total length of packet */
  192         struct iso_addr *src;   /* ptr to source address */
  193         struct iso_addr *dst;   /* ptr to destination address */
  194         struct clnp_cache clc;  /* storage for cache information */
  195         struct clnp_cache *clcp = NULL; /* ptr to clc */
  196         int             hdrlen = 0;
  197         va_list ap;
  198 
  199         va_start(ap, m0);
  200         isop = va_arg(ap, struct isopcb  *);
  201         datalen = va_arg(ap, int);
  202         flags = va_arg(ap, int);
  203         va_end(ap);
  204 
  205         dst = &isop->isop_faddr->siso_addr;
  206         if (isop->isop_laddr == 0) {
  207                 struct iso_ifaddr *ia = 0;
  208                 clnp_route(dst, &isop->isop_route, flags, 0, &ia);
  209                 if (ia == 0 || ia->ia_ifa.ifa_addr->sa_family != AF_ISO)
  210                         return (ENETUNREACH);
  211                 src = &ia->ia_addr.siso_addr;
  212         } else
  213                 src = &isop->isop_laddr->siso_addr;
  214 
  215 #ifdef ARGO_DEBUG
  216         if (argo_debug[D_OUTPUT]) {
  217                 printf("clnp_output: to %s", clnp_iso_addrp(dst));
  218                 printf(" from %s of %d bytes\n", clnp_iso_addrp(src), datalen);
  219                 printf("\toptions %p, flags x%x, isop_clnpcache %p\n",
  220                     isop->isop_options, flags, isop->isop_clnpcache);
  221         }
  222 #endif
  223 
  224         if (isop->isop_clnpcache != NULL) {
  225                 clcp = mtod(isop->isop_clnpcache, struct clnp_cache *);
  226         }
  227         /*
  228          *      Check if cache is valid ...
  229          */
  230 #ifdef ARGO_DEBUG
  231         if (argo_debug[D_OUTPUT]) {
  232                 printf("clnp_output: ck cache: clcp %p\n", clcp);
  233                 if (clcp != NULL) {
  234                         printf("\tclc_dst %s\n", clnp_iso_addrp(&clcp->clc_dst));
  235                         printf("\tisop_opts %p, clc_opts %p\n",
  236                             isop->isop_options, clcp->clc_options);
  237                         if (isop->isop_route.ro_rt)
  238                                 printf("\tro_rt %p, rt_flags x%x\n",
  239                                     isop->isop_route.ro_rt,
  240                                     isop->isop_route.ro_rt->rt_flags);
  241                         printf("\tflags x%x, clc_flags x%x\n", flags,
  242                             clcp->clc_flags);
  243                         printf("\tclc_hdr %p\n", clcp->clc_hdr);
  244                 }
  245         }
  246 #endif
  247         if ((clcp != NULL) &&   /* cache exists */
  248             (isop->isop_options == clcp->clc_options) &&        /* same options */
  249             (iso_addrmatch1(dst, &clcp->clc_dst)) &&    /* dst still same */
  250             (isop->isop_route.ro_rt != NULL) && /* route exists */
  251             (isop->isop_route.ro_rt == clcp->clc_rt) && /* and is cached */
  252             (isop->isop_route.ro_rt->rt_flags & RTF_UP) &&      /* route still up */
  253             (flags == clcp->clc_flags) &&       /* same flags */
  254             (clcp->clc_hdr != NULL)) {  /* hdr mbuf exists */
  255                 /*
  256                  * The cache is valid
  257                  */
  258 
  259 #ifdef ARGO_DEBUG
  260                 if (argo_debug[D_OUTPUT]) {
  261                         printf("clnp_output: using cache\n");
  262                 }
  263 #endif
  264 
  265                 m = m_copy(clcp->clc_hdr, 0, (int) M_COPYALL);
  266                 if (m == NULL) {
  267                         /*
  268                          * No buffers left to copy cached packet header. Use
  269                          * the cached packet header this time, and
  270                          * mark the hdr as vacant
  271                          */
  272                         m = clcp->clc_hdr;
  273                         clcp->clc_hdr = NULL;
  274                 }
  275                 m->m_next = m0; /* ASSUMES pkt hdr is 1 mbuf long */
  276                 clnp = mtod(m, struct clnp_fixed *);
  277         } else {
  278                 struct clnp_optidx *oidx = NULL;        /* index to clnp options */
  279 
  280                 /*
  281                  * The cache is not valid. Allocate an mbuf (if necessary)
  282                  * to hold cached info. If one is not available, then
  283                  * don't bother with the cache
  284                  */
  285                 INCSTAT(cns_cachemiss);
  286                 if (flags & CLNP_NOCACHE) {
  287                         clcp = &clc;
  288                 } else {
  289                         if (isop->isop_clnpcache == NULL) {
  290                                 /*
  291                                  * There is no clnpcache. Allocate an mbuf
  292                                  * to hold one
  293                                  */
  294                                 if ((isop->isop_clnpcache = m_get(M_DONTWAIT, MT_HEADER))
  295                                     == NULL) {
  296                                         /*
  297                                          * No mbufs available. Pretend that we
  298                                          * don't want caching this time.
  299                                          */
  300 #ifdef ARGO_DEBUG
  301                                         if (argo_debug[D_OUTPUT]) {
  302                                                 printf("clnp_output: no mbufs to allocate to cache\n");
  303                                         }
  304 #endif
  305                                         flags |= CLNP_NOCACHE;
  306                                         clcp = &clc;
  307                                 } else {
  308                                         clcp = mtod(isop->isop_clnpcache, struct clnp_cache *);
  309                                 }
  310                         } else {
  311                                 /*
  312                                  * A clnpcache mbuf exists. If the clc_hdr
  313                                  * is not null, we must free it, as a new one
  314                                  * is about to be created.
  315                                  */
  316                                 clcp = mtod(isop->isop_clnpcache, struct clnp_cache *);
  317                                 if (clcp->clc_hdr != NULL) {
  318                                         /*
  319                                          * The clc_hdr is not null but a
  320                                          * clnpcache mbuf exists. This means
  321                                          * that there was a cache, but the
  322                                          * existing copy of the hdr is no
  323                                          * longer valid. Free it now
  324                                          * before we lose the pointer to it.
  325                                          */
  326 #ifdef ARGO_DEBUG
  327                                         if (argo_debug[D_OUTPUT]) {
  328                                                 printf(
  329                                     "clnp_output: freeing old clc_hdr %p\n",
  330                                                clcp->clc_hdr);
  331                                         }
  332 #endif
  333                                         m_free(clcp->clc_hdr);
  334 #ifdef ARGO_DEBUG
  335                                         if (argo_debug[D_OUTPUT]) {
  336                                                 printf("clnp_output: freed old clc_hdr (done)\n");
  337                                         }
  338 #endif
  339                                 }
  340                         }
  341                 }
  342 #ifdef ARGO_DEBUG
  343                 if (argo_debug[D_OUTPUT]) {
  344                         printf("clnp_output: NEW clcp %p\n", clcp);
  345                 }
  346 #endif
  347                 bzero((caddr_t) clcp, sizeof(struct clnp_cache));
  348 
  349                 if (isop->isop_optindex)
  350                         oidx = mtod(isop->isop_optindex, struct clnp_optidx *);
  351 
  352                 /*
  353                  * Don't allow packets with security, quality of service,
  354                  * priority, or error report options to be sent.
  355                  */
  356                 if ((isop->isop_options) && (oidx)) {
  357                         if ((oidx->cni_securep) ||
  358                             (oidx->cni_priorp) ||
  359                             (oidx->cni_qos_formatp) ||
  360                             (oidx->cni_er_reason != ER_INVALREAS)) {
  361 #ifdef ARGO_DEBUG
  362                                 if (argo_debug[D_OUTPUT]) {
  363                                         printf("clnp_output: pkt dropped - option unsupported\n");
  364                                 }
  365 #endif
  366                                 m_freem(m0);
  367                                 return (EINVAL);
  368                         }
  369                 }
  370                 /*
  371                  * Don't allow any invalid flags to be set
  372                  */
  373                 if ((flags & (CLNP_VFLAGS)) != flags) {
  374 #ifdef ARGO_DEBUG
  375                         if (argo_debug[D_OUTPUT]) {
  376                                 printf("clnp_output: packet dropped - flags unsupported\n");
  377                         }
  378 #endif
  379                         INCSTAT(cns_odropped);
  380                         m_freem(m0);
  381                         return (EINVAL);
  382                 }
  383                 /*
  384                  * Don't allow funny lengths on dst; src may be zero in which
  385                  * case we insert the source address based upon the interface
  386                  */
  387                 if ((src->isoa_len > sizeof(struct iso_addr)) ||
  388                     (dst->isoa_len == 0) ||
  389                     (dst->isoa_len > sizeof(struct iso_addr))) {
  390                         m_freem(m0);
  391                         INCSTAT(cns_odropped);
  392                         return (ENAMETOOLONG);
  393                 }
  394                 /*
  395                  *      Grab mbuf to contain header
  396                  */
  397                 MGETHDR(m, M_DONTWAIT, MT_HEADER);
  398                 if (m == 0) {
  399                         m_freem(m0);
  400                         INCSTAT(cns_odropped);
  401                         return (ENOBUFS);
  402                 }
  403                 INCSTAT(cns_sent);
  404                 m->m_next = m0;
  405                 clnp = mtod(m, struct clnp_fixed *);
  406                 clcp->clc_segoff = 0;
  407 
  408                 /*
  409                  * Fill in all of fixed hdr except lengths and checksum
  410                  */
  411                 if (flags & CLNP_SEND_RAW) {
  412                         *clnp = raw_template;
  413                 } else if (flags & CLNP_ECHO) {
  414                         *clnp = echo_template;
  415                 } else if (flags & CLNP_ECHOR) {
  416                         *clnp = echor_template;
  417                 } else {
  418                         *clnp = dt_template;
  419                 }
  420                 if (flags & CLNP_NO_SEG)
  421                         clnp->cnf_type &= ~CNF_SEG_OK;
  422                 if (flags & CLNP_NO_ER)
  423                         clnp->cnf_type &= ~CNF_ERR_OK;
  424 
  425                 /*
  426                  *      Route packet; special case for source rt
  427                  */
  428                 if ((isop->isop_options) && CLNPSRCRT_VALID(oidx)) {
  429 #ifdef ARGO_DEBUG
  430                         if (argo_debug[D_OUTPUT]) {
  431                                 printf("clnp_output: calling clnp_srcroute\n");
  432                         }
  433 #endif
  434                         error = clnp_srcroute(isop->isop_options, oidx, &isop->isop_route,
  435                                   &clcp->clc_firsthop, &clcp->clc_ifa, dst);
  436                 } else {
  437 #ifdef ARGO_DEBUG
  438                         if (argo_debug[D_OUTPUT]) {
  439                         }
  440 #endif
  441                         error = clnp_route(dst, &isop->isop_route, flags,
  442                                        &clcp->clc_firsthop, &clcp->clc_ifa);
  443                 }
  444                 if (error || (clcp->clc_ifa == 0)) {
  445 #ifdef ARGO_DEBUG
  446                         if (argo_debug[D_OUTPUT]) {
  447                                 printf("clnp_output: route failed, errno %d\n", error);
  448                                 printf("@clcp:\n");
  449                                 dump_buf(clcp, sizeof(struct clnp_cache));
  450                         }
  451 #endif
  452                         goto bad;
  453                 }
  454                 clcp->clc_rt = isop->isop_route.ro_rt;  /* XXX */
  455                 clcp->clc_ifp = clcp->clc_ifa->ia_ifp;  /* XXX */
  456 
  457 #ifdef ARGO_DEBUG
  458                 if (argo_debug[D_OUTPUT]) {
  459                         printf("clnp_output: packet routed to %s\n",
  460                             clnp_iso_addrp(
  461                                  &satosiso(clcp->clc_firsthop)->siso_addr));
  462                 }
  463 #endif
  464 
  465                 /*
  466                  * If src address is not yet specified, use address of
  467                  * interface. NOTE: this will now update the laddr field in
  468                  * the isopcb. Is this desirable? RAH?
  469                  */
  470                 if (src->isoa_len == 0) {
  471                         src = &(clcp->clc_ifa->ia_addr.siso_addr);
  472 #ifdef ARGO_DEBUG
  473                         if (argo_debug[D_OUTPUT]) {
  474                                 printf("clnp_output: new src %s\n", clnp_iso_addrp(src));
  475                         }
  476 #endif
  477                 }
  478                 /*
  479                  * Insert the source and destination address,
  480                  */
  481                 hoff = (caddr_t) clnp + sizeof(struct clnp_fixed);
  482                 CLNP_INSERT_ADDR(hoff, *dst);
  483                 CLNP_INSERT_ADDR(hoff, *src);
  484 
  485                 /*
  486                  * Leave room for the segment part, if segmenting is selected
  487                  */
  488                 if (clnp->cnf_type & CNF_SEG_OK) {
  489                         clcp->clc_segoff = hoff - (caddr_t) clnp;
  490                         hoff += sizeof(struct clnp_segment);
  491                 }
  492                 clnp->cnf_hdr_len = m->m_len = (u_char) (hoff - (caddr_t) clnp);
  493                 hdrlen = clnp->cnf_hdr_len;
  494 
  495 #ifdef  DECBIT
  496                 /*
  497                  * Add the globally unique QOS (with room for congestion
  498                  * experienced bit). I can safely assume that this option
  499                  * is not in the options mbuf below because I checked that
  500                  * the option was not specified previously
  501                  */
  502                 if ((m->m_len + sizeof(qos_option)) < MLEN) {
  503                         bcopy((caddr_t) qos_option, hoff, sizeof(qos_option));
  504                         clnp->cnf_hdr_len += sizeof(qos_option);
  505                         hdrlen += sizeof(qos_option);
  506                         m->m_len += sizeof(qos_option);
  507                 }
  508 #endif                          /* DECBIT */
  509 
  510                 /*
  511                  * If an options mbuf is present, concatenate a copy to the hdr mbuf.
  512                  */
  513                 if (isop->isop_options) {
  514                         struct mbuf    *opt_copy =
  515                                 m_copy(isop->isop_options, 0, (int) M_COPYALL);
  516                         if (opt_copy == NULL) {
  517                                 error = ENOBUFS;
  518                                 goto bad;
  519                         }
  520                         /* Link in place */
  521                         opt_copy->m_next = m->m_next;
  522                         m->m_next = opt_copy;
  523 
  524                         /* update size of header */
  525                         clnp->cnf_hdr_len += opt_copy->m_len;
  526                         hdrlen += opt_copy->m_len;
  527                 }
  528                 if (hdrlen > CLNP_HDR_MAX) {
  529                         error = EMSGSIZE;
  530                         goto bad;
  531                 }
  532                 /*
  533                  * Now set up the cache entry in the pcb
  534                  */
  535                 if ((flags & CLNP_NOCACHE) == 0) {
  536                         clcp->clc_hdr = m_copy(m, 0, (int) clnp->cnf_hdr_len);
  537                         if (clcp->clc_hdr) {
  538                                 clcp->clc_dst = *dst;
  539                                 clcp->clc_flags = flags;
  540                                 clcp->clc_options = isop->isop_options;
  541                         }
  542                 }
  543         }
  544         /*
  545          *      If small enough for interface, send directly
  546          *      Fill in segmentation part of hdr if using the full protocol
  547          */
  548         total_len = clnp->cnf_hdr_len + datalen;
  549         if (clnp->cnf_type & CNF_SEG_OK) {
  550                 struct clnp_segment seg_part;   /* segment part of hdr */
  551                 seg_part.cng_id = htons(clnp_id++);
  552                 seg_part.cng_off = htons(0);
  553                 seg_part.cng_tot_len = htons(total_len);
  554                 (void) bcopy((caddr_t) & seg_part, (caddr_t) clnp + clcp->clc_segoff,
  555                              sizeof(seg_part));
  556         }
  557         if (total_len <= SN_MTU(clcp->clc_ifp, clcp->clc_rt)) {
  558                 HTOC(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, total_len);
  559                 m->m_pkthdr.len = total_len;
  560                 /*
  561                  *      Compute clnp checksum (on header only)
  562                  */
  563                 if (flags & CLNP_NO_CKSUM) {
  564                         HTOC(clnp->cnf_cksum_msb, clnp->cnf_cksum_lsb, 0);
  565                 } else {
  566                         iso_gen_csum(m, CLNP_CKSUM_OFF, (int) clnp->cnf_hdr_len);
  567                 }
  568 
  569 #ifdef ARGO_DEBUG
  570                 if (argo_debug[D_DUMPOUT]) {
  571                         struct mbuf    *mdump = m;
  572                         printf("clnp_output: sending dg:\n");
  573                         while (mdump != NULL) {
  574                                 dump_buf(mtod(mdump, caddr_t), mdump->m_len);
  575                                 mdump = mdump->m_next;
  576                         }
  577                 }
  578 #endif
  579 
  580                 error = SN_OUTPUT(clcp, m);
  581                 goto done;
  582         } else {
  583                 /*
  584                  * Too large for interface; fragment if possible.
  585                  */
  586                 error = clnp_fragment(clcp->clc_ifp, m, clcp->clc_firsthop,
  587                           total_len, clcp->clc_segoff, flags, clcp->clc_rt);
  588                 goto done;
  589         }
  590 bad:
  591         m_freem(m);
  592 done:
  593         if (error) {
  594                 clnp_stat.cns_sent--;
  595                 clnp_stat.cns_odropped++;
  596         }
  597         return (error);
  598 }
  599 
  600 #ifdef notyet
  601 void
  602 clnp_ctloutput(void)
  603 {
  604 }
  605 #endif

Cache object: 317794c99c16a6718e1b921d701a9711


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