136372Ssklower /*********************************************************** 236372Ssklower Copyright IBM Corporation 1987 336372Ssklower 436372Ssklower All Rights Reserved 536372Ssklower 636372Ssklower Permission to use, copy, modify, and distribute this software and its 736372Ssklower documentation for any purpose and without fee is hereby granted, 836372Ssklower provided that the above copyright notice appear in all copies and that 936372Ssklower both that copyright notice and this permission notice appear in 1036372Ssklower supporting documentation, and that the name of IBM not be 1136372Ssklower used in advertising or publicity pertaining to distribution of the 1236372Ssklower software without specific, written prior permission. 1336372Ssklower 1436372Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536372Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636372Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736372Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836372Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936372Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036372Ssklower SOFTWARE. 2136372Ssklower 2236372Ssklower ******************************************************************/ 2336372Ssklower 2436372Ssklower /* 2536372Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636372Ssklower */ 2736768Ssklower /* $Header: /var/src/sys/netiso/RCS/clnp_output.c,v 5.0 89/02/08 12:00:15 hagens Exp $ */ 2836768Ssklower /* $Source: /var/src/sys/netiso/RCS/clnp_output.c,v $ */ 29*42865Ssklower /* @(#)clnp_output.c 7.8 (Berkeley) 06/04/90 */ 3036372Ssklower 3136372Ssklower #ifndef lint 3236768Ssklower static char *rcsid = "$Header: /var/src/sys/netiso/RCS/clnp_output.c,v 5.0 89/02/08 12:00:15 hagens Exp $"; 3336372Ssklower #endif lint 3436372Ssklower 3537469Ssklower #include "param.h" 3637469Ssklower #include "mbuf.h" 3737469Ssklower #include "domain.h" 3837469Ssklower #include "protosw.h" 3937469Ssklower #include "socket.h" 4037469Ssklower #include "socketvar.h" 4137469Ssklower #include "errno.h" 4237469Ssklower #include "time.h" 4336372Ssklower 4436372Ssklower #include "../net/if.h" 4536372Ssklower #include "../net/route.h" 4636372Ssklower 4737469Ssklower #include "iso.h" 4837469Ssklower #include "iso_var.h" 4937469Ssklower #include "iso_pcb.h" 5037469Ssklower #include "clnp.h" 5137469Ssklower #include "clnp_stat.h" 5237469Ssklower #include "argo_debug.h" 5336372Ssklower 5436372Ssklower static struct clnp_fixed dt_template = { 5536372Ssklower ISO8473_CLNP, /* network identifier */ 5636372Ssklower 0, /* length */ 5736372Ssklower ISO8473_V1, /* version */ 5836372Ssklower CLNP_TTL, /* ttl */ 5937469Ssklower CLNP_DT|CNF_SEG_OK|CNF_ERR_OK, /* type */ 6036372Ssklower 0, /* segment length */ 6136372Ssklower 0 /* checksum */ 6236372Ssklower }; 6336372Ssklower 6436372Ssklower static struct clnp_fixed raw_template = { 6536372Ssklower ISO8473_CLNP, /* network identifier */ 6636372Ssklower 0, /* length */ 6736372Ssklower ISO8473_V1, /* version */ 6836372Ssklower CLNP_TTL, /* ttl */ 6937469Ssklower CLNP_RAW|CNF_SEG_OK|CNF_ERR_OK, /* type */ 7036372Ssklower 0, /* segment length */ 7136372Ssklower 0 /* checksum */ 7236372Ssklower }; 7336372Ssklower 7436372Ssklower static struct clnp_fixed echo_template = { 7536372Ssklower ISO8473_CLNP, /* network identifier */ 7636372Ssklower 0, /* length */ 7736372Ssklower ISO8473_V1, /* version */ 7836372Ssklower CLNP_TTL, /* ttl */ 7937469Ssklower CLNP_EC|CNF_SEG_OK|CNF_ERR_OK, /* type */ 8036372Ssklower 0, /* segment length */ 8136372Ssklower 0 /* checksum */ 8236372Ssklower }; 8336372Ssklower 8436768Ssklower #ifdef DECBIT 8536768Ssklower u_char qos_option[] = {CLNPOVAL_QOS, 1, 8636768Ssklower CLNPOVAL_GLOBAL|CLNPOVAL_SEQUENCING|CLNPOVAL_LOWDELAY}; 8736768Ssklower #endif DECBIT 8836768Ssklower 8936372Ssklower int clnp_id = 0; /* id for segmented dgrams */ 9036372Ssklower 9136372Ssklower /* 9236372Ssklower * FUNCTION: clnp_output 9336372Ssklower * 9436372Ssklower * PURPOSE: output the data in the mbuf as a clnp datagram 9536372Ssklower * 9636372Ssklower * The data specified by m0 is sent as a clnp datagram. 9736372Ssklower * The mbuf chain m0 will be freed when this routine has 9836372Ssklower * returned. 9936372Ssklower * 10036372Ssklower * If options is non-null, it points to an mbuf which contains 10136372Ssklower * options to be sent with the datagram. The options must 10236372Ssklower * be formatted in the mbuf according to clnp rules. Options 10336372Ssklower * will not be freed. 10436372Ssklower * 10536372Ssklower * Datalen specifies the length of the data in m0. 10636372Ssklower * 10736372Ssklower * Src and dst are the addresses for the packet. 10836372Ssklower * 10936372Ssklower * If route is non-null, it is used as the route for 11036372Ssklower * the packet. 11136372Ssklower * 11236372Ssklower * By default, a DT is sent. However, if flags & CNLP_SEND_ER 11336372Ssklower * then an ER will be sent. If flags & CLNP_SEND_RAW, then 11436372Ssklower * the packet will be send as raw clnp. 11536372Ssklower * 11636372Ssklower * RETURNS: 0 success 11736372Ssklower * appropriate error code 11836372Ssklower * 11936372Ssklower * SIDE EFFECTS: none 12036372Ssklower * 12136372Ssklower * NOTES: 12236372Ssklower * Flags are interpretated as follows: 12336372Ssklower * CLNP_NO_SEG - do not allow this pkt to be segmented. 12436372Ssklower * CLNP_NO_ER - have pkt request ER suppression. 12536372Ssklower * CLNP_SEND_RAW - send pkt as RAW DT rather than TP DT 12636372Ssklower * CLNP_NO_CKSUM - don't compute clnp checksum 12736372Ssklower * CLNP_ECHO - send as ECHO packet 12836372Ssklower * 12936372Ssklower * When checking for a cached packet, clnp checks 13036372Ssklower * that the route taken is still up. It does not 13136372Ssklower * check that the route is still to the same destination. 13236372Ssklower * This means that any entity that alters an existing 13336372Ssklower * route for an isopcb (such as when a redirect arrives) 13436372Ssklower * must invalidate the clnp cache. It might be perferable 13536372Ssklower * to have clnp check that the route has the same dest, but 13636372Ssklower * by avoiding this check, we save a call to iso_addrmatch1. 13736372Ssklower */ 13838841Ssklower clnp_output(m0, isop, datalen, flags) 13936372Ssklower struct mbuf *m0; /* data for the packet */ 14036372Ssklower struct isopcb *isop; /* iso pcb */ 14138841Ssklower int datalen; /* number of bytes of data in m0 */ 14236372Ssklower int flags; /* flags */ 14336372Ssklower { 14436372Ssklower int error = 0; /* return value of function */ 14537469Ssklower register struct mbuf *m = m0; /* mbuf for clnp header chain */ 14636372Ssklower register struct clnp_fixed *clnp; /* ptr to fixed part of hdr */ 14736372Ssklower register caddr_t hoff; /* offset into header */ 14836372Ssklower int total_len; /* total length of packet */ 14936372Ssklower struct iso_addr *src; /* ptr to source address */ 15036372Ssklower struct iso_addr *dst; /* ptr to destination address */ 15136372Ssklower struct clnp_cache clc; /* storage for cache information */ 15236372Ssklower struct clnp_cache *clcp = NULL; /* ptr to clc */ 15336768Ssklower int hdrlen = 0; 15436372Ssklower 15537469Ssklower dst = &isop->isop_faddr->siso_addr; 15641338Ssklower if (isop->isop_laddr == 0) { 15741338Ssklower struct iso_ifaddr *ia = 0; 15841338Ssklower clnp_route(dst, &isop->isop_route, flags, 0, &ia); 15941338Ssklower if (ia == 0 || ia->ia_ifa.ifa_addr->sa_family != AF_ISO) 16041338Ssklower return (ENETUNREACH); 16141338Ssklower src = &ia->ia_addr.siso_addr; 16241338Ssklower } else 16341338Ssklower src = &isop->isop_laddr->siso_addr; 16436372Ssklower 16536372Ssklower IFDEBUG(D_OUTPUT) 16636372Ssklower printf("clnp_output: to %s", clnp_iso_addrp(dst)); 16736372Ssklower printf(" from %s of %d bytes\n", clnp_iso_addrp(src), datalen); 16836372Ssklower printf("\toptions x%x, flags x%x, isop_clnpcache x%x\n", 16936372Ssklower isop->isop_options, flags, isop->isop_clnpcache); 17036372Ssklower ENDDEBUG 17136372Ssklower 17236372Ssklower if (isop->isop_clnpcache != NULL) { 17336372Ssklower clcp = mtod(isop->isop_clnpcache, struct clnp_cache *); 17436372Ssklower } 17536372Ssklower 17636372Ssklower /* 17736372Ssklower * Check if cache is valid ... 17836372Ssklower */ 17936372Ssklower IFDEBUG(D_OUTPUT) 18036372Ssklower printf("clnp_output: ck cache: clcp %x\n", clcp); 18136372Ssklower if (clcp != NULL) { 18236372Ssklower printf("\tclc_dst %s\n", clnp_iso_addrp(&clcp->clc_dst)); 18336372Ssklower printf("\tisop_opts x%x, clc_opts x%x\n", isop->isop_options, 18436372Ssklower clcp->clc_options); 18536372Ssklower if (isop->isop_route.ro_rt) 18636372Ssklower printf("\tro_rt x%x, rt_flags x%x\n", 18736372Ssklower isop->isop_route.ro_rt, isop->isop_route.ro_rt->rt_flags); 18836372Ssklower printf("\tflags x%x, clc_flags x%x\n", flags, clcp->clc_flags); 18936372Ssklower printf("\tclc_hdr x%x\n", clcp->clc_hdr); 19036372Ssklower } 19136372Ssklower ENDDEBUG 19236372Ssklower if ((clcp != NULL) && /* cache exists */ 19336372Ssklower (isop->isop_options == clcp->clc_options) && /* same options */ 19436372Ssklower (iso_addrmatch1(dst, &clcp->clc_dst)) && /* dst still same */ 19536372Ssklower (isop->isop_route.ro_rt != NULL) && /* route exists */ 19640777Ssklower (isop->isop_route.ro_rt == clcp->clc_rt) && /* and is cached */ 19736372Ssklower (isop->isop_route.ro_rt->rt_flags & RTF_UP) && /* route still up */ 19836372Ssklower (flags == clcp->clc_flags) && /* same flags */ 19936372Ssklower (clcp->clc_hdr != NULL)) { /* hdr mbuf exists */ 20036372Ssklower /* 20136372Ssklower * The cache is valid 20236372Ssklower */ 20336372Ssklower 20436372Ssklower IFDEBUG(D_OUTPUT) 20536372Ssklower printf("clnp_output: using cache\n"); 20636372Ssklower ENDDEBUG 20736372Ssklower 20837469Ssklower m = m_copy(clcp->clc_hdr, 0, (int)M_COPYALL); 20936372Ssklower if (m == NULL) { 21036372Ssklower /* 21136372Ssklower * No buffers left to copy cached packet header. Use 21236372Ssklower * the cached packet header this time, and 21336372Ssklower * mark the hdr as vacant 21436372Ssklower */ 21536372Ssklower m = clcp->clc_hdr; 21636372Ssklower clcp->clc_hdr = NULL; 21736372Ssklower } 21836372Ssklower m->m_next = m0; /* ASSUMES pkt hdr is 1 mbuf long */ 21936372Ssklower clnp = mtod(m, struct clnp_fixed *); 22036372Ssklower } else { 22136372Ssklower struct clnp_optidx *oidx = NULL; /* index to clnp options */ 22236372Ssklower 22336372Ssklower /* 22436372Ssklower * The cache is not valid. Allocate an mbuf (if necessary) 22536372Ssklower * to hold cached info. If one is not available, then 22636372Ssklower * don't bother with the cache 22736372Ssklower */ 22836372Ssklower INCSTAT(cns_cachemiss); 22936372Ssklower if (flags & CLNP_NOCACHE) { 23036372Ssklower clcp = &clc; 23136372Ssklower } else { 23236372Ssklower if (isop->isop_clnpcache == NULL) { 23336372Ssklower /* 23436372Ssklower * There is no clnpcache. Allocate an mbuf to hold one 23536372Ssklower */ 23636372Ssklower if ((isop->isop_clnpcache = m_get(M_DONTWAIT, MT_HEADER)) 23736372Ssklower == NULL) { 23836372Ssklower /* 23936372Ssklower * No mbufs available. Pretend that we don't want 24036372Ssklower * caching this time. 24136372Ssklower */ 24236372Ssklower IFDEBUG(D_OUTPUT) 24336372Ssklower printf("clnp_output: no mbufs to allocate to cache\n"); 24436372Ssklower ENDDEBUG 24536372Ssklower flags |= CLNP_NOCACHE; 24636372Ssklower clcp = &clc; 24736372Ssklower } else { 24836372Ssklower clcp = mtod(isop->isop_clnpcache, struct clnp_cache *); 24936372Ssklower } 25036372Ssklower } else { 25136372Ssklower /* 25236372Ssklower * A clnpcache mbuf exists. If the clc_hdr is not null, 25336372Ssklower * we must free it, as a new one is about to be created. 25436372Ssklower */ 25536372Ssklower clcp = mtod(isop->isop_clnpcache, struct clnp_cache *); 25636372Ssklower if (clcp->clc_hdr != NULL) { 25736372Ssklower /* 25836372Ssklower * The clc_hdr is not null but a clnpcache mbuf exists. 25936372Ssklower * This means that there was a cache, but the existing 26036372Ssklower * copy of the hdr is no longer valid. Free it now 26136372Ssklower * before we lose the pointer to it. 26236372Ssklower */ 26336372Ssklower IFDEBUG(D_OUTPUT) 26436372Ssklower printf("clnp_output: freeing old clc_hdr 0x%x\n", 26536372Ssklower clcp->clc_hdr); 26636372Ssklower ENDDEBUG 26736372Ssklower m_free(clcp->clc_hdr); 26836372Ssklower IFDEBUG(D_OUTPUT) 26936372Ssklower printf("clnp_output: freed old clc_hdr (done)\n"); 27036372Ssklower ENDDEBUG 27136372Ssklower } 27236372Ssklower } 27336372Ssklower } 27436372Ssklower IFDEBUG(D_OUTPUT) 27536372Ssklower printf("clnp_output: NEW clcp x%x\n",clcp); 27636372Ssklower ENDDEBUG 27736372Ssklower bzero((caddr_t)clcp, sizeof(struct clnp_cache)); 27836372Ssklower 27936372Ssklower if (isop->isop_optindex) 28036372Ssklower oidx = mtod(isop->isop_optindex, struct clnp_optidx *); 28136372Ssklower 28236372Ssklower /* 28336372Ssklower * Don't allow packets with security, quality of service, 28436372Ssklower * priority, or error report options to be sent. 28536372Ssklower */ 28636372Ssklower if ((isop->isop_options) && (oidx)) { 28736372Ssklower if ((oidx->cni_securep) || 28836372Ssklower (oidx->cni_priorp) || 28936372Ssklower (oidx->cni_qos_formatp) || 29036372Ssklower (oidx->cni_er_reason != ER_INVALREAS)) { 29136372Ssklower IFDEBUG(D_OUTPUT) 29236372Ssklower printf("clnp_output: pkt dropped - option unsupported\n"); 29336372Ssklower ENDDEBUG 29436372Ssklower m_freem(m0); 29536372Ssklower return(EINVAL); 29636372Ssklower } 29736372Ssklower } 29836372Ssklower 29936372Ssklower /* 30036372Ssklower * Don't allow any invalid flags to be set 30136372Ssklower */ 30236372Ssklower if ((flags & (CLNP_VFLAGS)) != flags) { 30336372Ssklower IFDEBUG(D_OUTPUT) 30436372Ssklower printf("clnp_output: packet dropped - flags unsupported\n"); 30536372Ssklower ENDDEBUG 30639195Ssklower INCSTAT(cns_odropped); 30736372Ssklower m_freem(m0); 30836372Ssklower return(EINVAL); 30936372Ssklower } 31036372Ssklower 31136372Ssklower /* 31236372Ssklower * Don't allow funny lengths on dst; src may be zero in which 31336372Ssklower * case we insert the source address based upon the interface 31436372Ssklower */ 31536372Ssklower if ((src->isoa_len > sizeof(struct iso_addr)) || 31636372Ssklower (dst->isoa_len == 0) || 31736372Ssklower (dst->isoa_len > sizeof(struct iso_addr))) { 31836372Ssklower m_freem(m0); 31939195Ssklower INCSTAT(cns_odropped); 32036372Ssklower return(ENAMETOOLONG); 32136372Ssklower } 32236372Ssklower 32336372Ssklower /* 32436372Ssklower * Grab mbuf to contain header 32536372Ssklower */ 32637469Ssklower MGETHDR(m, M_DONTWAIT, MT_HEADER); 32736372Ssklower if (m == 0) { 32836372Ssklower m_freem(m0); 32939195Ssklower INCSTAT(cns_odropped); 33036372Ssklower return(ENOBUFS); 33136372Ssklower } 33239195Ssklower INCSTAT(cns_sent); 33336372Ssklower m->m_next = m0; 33436372Ssklower clnp = mtod(m, struct clnp_fixed *); 33536372Ssklower clcp->clc_segoff = 0; 33636372Ssklower 33736372Ssklower /* 33836372Ssklower * Fill in all of fixed hdr except lengths and checksum 33936372Ssklower */ 34036372Ssklower if (flags & CLNP_SEND_RAW) { 34136372Ssklower *clnp = raw_template; 34236372Ssklower } else if (flags & CLNP_ECHO) { 34336372Ssklower *clnp = echo_template; 34436372Ssklower } else { 34536372Ssklower *clnp = dt_template; 34636372Ssklower } 34736372Ssklower if (flags & CLNP_NO_SEG) 34837469Ssklower clnp->cnf_type &= ~CNF_SEG_OK; 34936372Ssklower if (flags & CLNP_NO_ER) 35037469Ssklower clnp->cnf_type &= ~CNF_ERR_OK; 35136372Ssklower 35236372Ssklower /* 35336372Ssklower * Route packet; special case for source rt 35436372Ssklower */ 35536372Ssklower if ((isop->isop_options) && CLNPSRCRT_VALID(oidx)) { 35636372Ssklower IFDEBUG(D_OUTPUT) 35736372Ssklower printf("clnp_output: calling clnp_srcroute\n"); 35836372Ssklower ENDDEBUG 35936372Ssklower error = clnp_srcroute(isop->isop_options, oidx, &isop->isop_route, 36037469Ssklower &clcp->clc_firsthop, &clcp->clc_ifa, dst); 36136372Ssklower } else { 36236372Ssklower IFDEBUG(D_OUTPUT) 36336372Ssklower ENDDEBUG 36436372Ssklower error = clnp_route(dst, &isop->isop_route, flags, 36537469Ssklower &clcp->clc_firsthop, &clcp->clc_ifa); 36636372Ssklower } 36737469Ssklower if (error || (clcp->clc_ifa == 0)) { 36836372Ssklower IFDEBUG(D_OUTPUT) 36936372Ssklower printf("clnp_output: route failed, errno %d\n", error); 37036372Ssklower printf("@clcp:\n"); 37136372Ssklower dump_buf(clcp, sizeof (struct clnp_cache)); 37236372Ssklower ENDDEBUG 37336372Ssklower goto bad; 37436372Ssklower } 37540777Ssklower clcp->clc_rt = isop->isop_route.ro_rt; /* XXX */ 37636372Ssklower 37736372Ssklower IFDEBUG(D_OUTPUT) 37836372Ssklower printf("clnp_output: packet routed to %s\n", 37936372Ssklower clnp_iso_addrp( 38036372Ssklower &((struct sockaddr_iso *)clcp->clc_firsthop)->siso_addr)); 38136372Ssklower ENDDEBUG 38236372Ssklower 38336372Ssklower /* 38436372Ssklower * If src address is not yet specified, use address of 38536372Ssklower * interface. NOTE: this will now update the laddr field in 38636372Ssklower * the isopcb. Is this desirable? RAH? 38736372Ssklower */ 38836372Ssklower if (src->isoa_len == 0) { 38937469Ssklower src = &(clcp->clc_ifa->ia_addr.siso_addr); 39036372Ssklower IFDEBUG(D_OUTPUT) 39136372Ssklower printf("clnp_output: new src %s\n", clnp_iso_addrp(src)); 39236372Ssklower ENDDEBUG 39336372Ssklower } 39436372Ssklower 39536372Ssklower /* 39636372Ssklower * Insert the source and destination address, 39736372Ssklower */ 39836372Ssklower hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); 39937469Ssklower CLNP_INSERT_ADDR(hoff, *dst); 40037469Ssklower CLNP_INSERT_ADDR(hoff, *src); 40136372Ssklower 40236372Ssklower /* 40336372Ssklower * Leave room for the segment part, if segmenting is selected 40436372Ssklower */ 40537469Ssklower if (clnp->cnf_type & CNF_SEG_OK) { 40636372Ssklower clcp->clc_segoff = hoff - (caddr_t)clnp; 40736372Ssklower hoff += sizeof(struct clnp_segment); 40836372Ssklower } 40936372Ssklower 41036372Ssklower clnp->cnf_hdr_len = m->m_len = (u_char)(hoff - (caddr_t)clnp); 41136768Ssklower hdrlen = clnp->cnf_hdr_len; 41236372Ssklower 41336768Ssklower #ifdef DECBIT 41436372Ssklower /* 41536768Ssklower * Add the globally unique QOS (with room for congestion experienced 41636768Ssklower * bit). I can safely assume that this option is not in the options 41736768Ssklower * mbuf below because I checked that the option was not specified 41836768Ssklower * previously 41936768Ssklower */ 42036768Ssklower if ((m->m_len + sizeof(qos_option)) < MLEN) { 42136768Ssklower bcopy((caddr_t)qos_option, hoff, sizeof(qos_option)); 42236768Ssklower clnp->cnf_hdr_len += sizeof(qos_option); 42336768Ssklower hdrlen += sizeof(qos_option); 42436768Ssklower m->m_len += sizeof(qos_option); 42536768Ssklower } 42636768Ssklower #endif DECBIT 42736768Ssklower 42836768Ssklower /* 42936372Ssklower * If an options mbuf is present, concatenate a copy to the hdr mbuf. 43036372Ssklower */ 43136372Ssklower if (isop->isop_options) { 43237469Ssklower struct mbuf *opt_copy = m_copy(isop->isop_options, 0, (int)M_COPYALL); 43336372Ssklower if (opt_copy == NULL) { 43436372Ssklower error = ENOBUFS; 43536372Ssklower goto bad; 43636372Ssklower } 43736372Ssklower /* Link in place */ 43836372Ssklower opt_copy->m_next = m->m_next; 43936372Ssklower m->m_next = opt_copy; 44036372Ssklower 44136372Ssklower /* update size of header */ 44236372Ssklower clnp->cnf_hdr_len += opt_copy->m_len; 44336768Ssklower hdrlen += opt_copy->m_len; 44436372Ssklower } 44536372Ssklower 44636768Ssklower if (hdrlen > CLNP_HDR_MAX) { 44736768Ssklower error = EMSGSIZE; 44836768Ssklower goto bad; 44936768Ssklower } 45036768Ssklower 45136372Ssklower /* 45236372Ssklower * Now set up the cache entry in the pcb 45336372Ssklower */ 45436372Ssklower if ((flags & CLNP_NOCACHE) == 0) { 45537469Ssklower if (clcp->clc_hdr = m_copy(m, 0, (int)clnp->cnf_hdr_len)) { 45637469Ssklower clcp->clc_dst = *dst; 45736372Ssklower clcp->clc_flags = flags; 45836372Ssklower clcp->clc_options = isop->isop_options; 45936372Ssklower } 46036372Ssklower } 46136372Ssklower } 46236372Ssklower /* 46336372Ssklower * If small enough for interface, send directly 46436372Ssklower * Fill in segmentation part of hdr if using the full protocol 46536372Ssklower */ 466*42865Ssklower total_len = clnp->cnf_hdr_len + datalen; 467*42865Ssklower if (clnp->cnf_type & CNF_SEG_OK) { 468*42865Ssklower struct clnp_segment seg_part; /* segment part of hdr */ 469*42865Ssklower seg_part.cng_id = htons(clnp_id++); 470*42865Ssklower seg_part.cng_off = htons(0); 471*42865Ssklower seg_part.cng_tot_len = htons(total_len); 472*42865Ssklower (void) bcopy((caddr_t)&seg_part, (caddr_t) clnp + clcp->clc_segoff, 473*42865Ssklower sizeof(seg_part)); 474*42865Ssklower } 475*42865Ssklower if (total_len <= SN_MTU(clcp->clc_ifa->ia_ifp)) { 47636372Ssklower HTOC(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, total_len); 47737469Ssklower m->m_pkthdr.len = total_len; 47836372Ssklower /* 47936372Ssklower * Compute clnp checksum (on header only) 48036372Ssklower */ 48136372Ssklower if (flags & CLNP_NO_CKSUM) { 48236372Ssklower HTOC(clnp->cnf_cksum_msb, clnp->cnf_cksum_lsb, 0); 48336372Ssklower } else { 48436372Ssklower iso_gen_csum(m, CLNP_CKSUM_OFF, (int)clnp->cnf_hdr_len); 48536372Ssklower } 48636372Ssklower 48736372Ssklower IFDEBUG(D_DUMPOUT) 48836372Ssklower struct mbuf *mdump = m; 48936372Ssklower printf("clnp_output: sending dg:\n"); 49036372Ssklower while (mdump != NULL) { 49136372Ssklower dump_buf(mtod(mdump, caddr_t), mdump->m_len); 49236372Ssklower mdump = mdump->m_next; 49336372Ssklower } 49436372Ssklower ENDDEBUG 49536372Ssklower 49636372Ssklower error = SN_OUTPUT(clcp, m); 49736372Ssklower goto done; 49836372Ssklower } else { 49936372Ssklower /* 50036372Ssklower * Too large for interface; fragment if possible. 50136372Ssklower */ 50239195Ssklower error = clnp_fragment(clcp->clc_ifa->ia_ifp, m, clcp->clc_firsthop, 50340777Ssklower total_len, clcp->clc_segoff, flags, clcp->clc_rt); 50436372Ssklower goto done; 50536372Ssklower } 50636372Ssklower bad: 50736372Ssklower m_freem(m); 50836372Ssklower done: 50939195Ssklower if (error) { 51039195Ssklower clnp_stat.cns_sent--; 51139195Ssklower clnp_stat.cns_odropped++; 51239195Ssklower } 51339195Ssklower return (error); 51436372Ssklower } 51536372Ssklower 51636372Ssklower int clnp_ctloutput() 51736372Ssklower { 51836372Ssklower } 519