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

Cache object: ffdf5e5c6847aa37efaaca32bfaff11b


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