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*38841Ssklower /* @(#)clnp_output.c 7.4 (Berkeley) 08/29/89 */ 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 3536372Ssklower #ifdef ISO 3637469Ssklower #include "types.h" 3737469Ssklower #include "param.h" 3837469Ssklower #include "mbuf.h" 3937469Ssklower #include "domain.h" 4037469Ssklower #include "protosw.h" 4137469Ssklower #include "socket.h" 4237469Ssklower #include "socketvar.h" 4337469Ssklower #include "errno.h" 4437469Ssklower #include "time.h" 4536372Ssklower 4636372Ssklower #include "../net/if.h" 4736372Ssklower #include "../net/route.h" 4836372Ssklower 4937469Ssklower #include "iso.h" 5037469Ssklower #include "iso_var.h" 5137469Ssklower #include "iso_pcb.h" 5237469Ssklower #include "clnp.h" 5337469Ssklower #include "clnp_stat.h" 5437469Ssklower #include "argo_debug.h" 5536372Ssklower 5636372Ssklower static struct clnp_fixed dt_template = { 5736372Ssklower ISO8473_CLNP, /* network identifier */ 5836372Ssklower 0, /* length */ 5936372Ssklower ISO8473_V1, /* version */ 6036372Ssklower CLNP_TTL, /* ttl */ 6137469Ssklower CLNP_DT|CNF_SEG_OK|CNF_ERR_OK, /* type */ 6236372Ssklower 0, /* segment length */ 6336372Ssklower 0 /* checksum */ 6436372Ssklower }; 6536372Ssklower 6636372Ssklower static struct clnp_fixed raw_template = { 6736372Ssklower ISO8473_CLNP, /* network identifier */ 6836372Ssklower 0, /* length */ 6936372Ssklower ISO8473_V1, /* version */ 7036372Ssklower CLNP_TTL, /* ttl */ 7137469Ssklower CLNP_RAW|CNF_SEG_OK|CNF_ERR_OK, /* type */ 7236372Ssklower 0, /* segment length */ 7336372Ssklower 0 /* checksum */ 7436372Ssklower }; 7536372Ssklower 7636372Ssklower static struct clnp_fixed echo_template = { 7736372Ssklower ISO8473_CLNP, /* network identifier */ 7836372Ssklower 0, /* length */ 7936372Ssklower ISO8473_V1, /* version */ 8036372Ssklower CLNP_TTL, /* ttl */ 8137469Ssklower CLNP_EC|CNF_SEG_OK|CNF_ERR_OK, /* type */ 8236372Ssklower 0, /* segment length */ 8336372Ssklower 0 /* checksum */ 8436372Ssklower }; 8536372Ssklower 8636768Ssklower #ifdef DECBIT 8736768Ssklower u_char qos_option[] = {CLNPOVAL_QOS, 1, 8836768Ssklower CLNPOVAL_GLOBAL|CLNPOVAL_SEQUENCING|CLNPOVAL_LOWDELAY}; 8936768Ssklower #endif DECBIT 9036768Ssklower 9136372Ssklower int clnp_id = 0; /* id for segmented dgrams */ 9236372Ssklower 9336372Ssklower /* 9436372Ssklower * FUNCTION: clnp_output 9536372Ssklower * 9636372Ssklower * PURPOSE: output the data in the mbuf as a clnp datagram 9736372Ssklower * 9836372Ssklower * The data specified by m0 is sent as a clnp datagram. 9936372Ssklower * The mbuf chain m0 will be freed when this routine has 10036372Ssklower * returned. 10136372Ssklower * 10236372Ssklower * If options is non-null, it points to an mbuf which contains 10336372Ssklower * options to be sent with the datagram. The options must 10436372Ssklower * be formatted in the mbuf according to clnp rules. Options 10536372Ssklower * will not be freed. 10636372Ssklower * 10736372Ssklower * Datalen specifies the length of the data in m0. 10836372Ssklower * 10936372Ssklower * Src and dst are the addresses for the packet. 11036372Ssklower * 11136372Ssklower * If route is non-null, it is used as the route for 11236372Ssklower * the packet. 11336372Ssklower * 11436372Ssklower * By default, a DT is sent. However, if flags & CNLP_SEND_ER 11536372Ssklower * then an ER will be sent. If flags & CLNP_SEND_RAW, then 11636372Ssklower * the packet will be send as raw clnp. 11736372Ssklower * 11836372Ssklower * RETURNS: 0 success 11936372Ssklower * appropriate error code 12036372Ssklower * 12136372Ssklower * SIDE EFFECTS: none 12236372Ssklower * 12336372Ssklower * NOTES: 12436372Ssklower * Flags are interpretated as follows: 12536372Ssklower * CLNP_NO_SEG - do not allow this pkt to be segmented. 12636372Ssklower * CLNP_NO_ER - have pkt request ER suppression. 12736372Ssklower * CLNP_SEND_RAW - send pkt as RAW DT rather than TP DT 12836372Ssklower * CLNP_NO_CKSUM - don't compute clnp checksum 12936372Ssklower * CLNP_ECHO - send as ECHO packet 13036372Ssklower * 13136372Ssklower * When checking for a cached packet, clnp checks 13236372Ssklower * that the route taken is still up. It does not 13336372Ssklower * check that the route is still to the same destination. 13436372Ssklower * This means that any entity that alters an existing 13536372Ssklower * route for an isopcb (such as when a redirect arrives) 13636372Ssklower * must invalidate the clnp cache. It might be perferable 13736372Ssklower * to have clnp check that the route has the same dest, but 13836372Ssklower * by avoiding this check, we save a call to iso_addrmatch1. 13936372Ssklower */ 140*38841Ssklower clnp_output(m0, isop, datalen, flags) 14136372Ssklower struct mbuf *m0; /* data for the packet */ 14236372Ssklower struct isopcb *isop; /* iso pcb */ 143*38841Ssklower int datalen; /* number of bytes of data in m0 */ 14436372Ssklower int flags; /* flags */ 14536372Ssklower { 14636372Ssklower int error = 0; /* return value of function */ 14737469Ssklower register struct mbuf *m = m0; /* mbuf for clnp header chain */ 14836372Ssklower register struct clnp_fixed *clnp; /* ptr to fixed part of hdr */ 14936372Ssklower register caddr_t hoff; /* offset into header */ 15036372Ssklower int total_len; /* total length of packet */ 15136372Ssklower struct iso_addr *src; /* ptr to source address */ 15236372Ssklower struct iso_addr *dst; /* ptr to destination address */ 15336372Ssklower struct clnp_cache clc; /* storage for cache information */ 15436372Ssklower struct clnp_cache *clcp = NULL; /* ptr to clc */ 15536768Ssklower int hdrlen = 0; 15636372Ssklower 15737469Ssklower src = &isop->isop_laddr->siso_addr; 15837469Ssklower dst = &isop->isop_faddr->siso_addr; 15936372Ssklower 16036372Ssklower IFDEBUG(D_OUTPUT) 16136372Ssklower printf("clnp_output: to %s", clnp_iso_addrp(dst)); 16236372Ssklower printf(" from %s of %d bytes\n", clnp_iso_addrp(src), datalen); 16336372Ssklower printf("\toptions x%x, flags x%x, isop_clnpcache x%x\n", 16436372Ssklower isop->isop_options, flags, isop->isop_clnpcache); 16536372Ssklower ENDDEBUG 16636372Ssklower 16736372Ssklower if (isop->isop_clnpcache != NULL) { 16836372Ssklower clcp = mtod(isop->isop_clnpcache, struct clnp_cache *); 16936372Ssklower } 17036372Ssklower 17136372Ssklower /* 17236372Ssklower * Check if cache is valid ... 17336372Ssklower */ 17436372Ssklower IFDEBUG(D_OUTPUT) 17536372Ssklower printf("clnp_output: ck cache: clcp %x\n", clcp); 17636372Ssklower if (clcp != NULL) { 17736372Ssklower printf("\tclc_dst %s\n", clnp_iso_addrp(&clcp->clc_dst)); 17836372Ssklower printf("\tisop_opts x%x, clc_opts x%x\n", isop->isop_options, 17936372Ssklower clcp->clc_options); 18036372Ssklower if (isop->isop_route.ro_rt) 18136372Ssklower printf("\tro_rt x%x, rt_flags x%x\n", 18236372Ssklower isop->isop_route.ro_rt, isop->isop_route.ro_rt->rt_flags); 18336372Ssklower printf("\tflags x%x, clc_flags x%x\n", flags, clcp->clc_flags); 18436372Ssklower printf("\tclc_hdr x%x\n", clcp->clc_hdr); 18536372Ssklower } 18636372Ssklower ENDDEBUG 18736372Ssklower if ((clcp != NULL) && /* cache exists */ 18836372Ssklower (isop->isop_options == clcp->clc_options) && /* same options */ 18936372Ssklower (iso_addrmatch1(dst, &clcp->clc_dst)) && /* dst still same */ 19036372Ssklower (isop->isop_route.ro_rt != NULL) && /* route exists */ 19136372Ssklower (isop->isop_route.ro_rt->rt_flags & RTF_UP) && /* route still up */ 19236372Ssklower (flags == clcp->clc_flags) && /* same flags */ 19336372Ssklower (clcp->clc_hdr != NULL)) { /* hdr mbuf exists */ 19436372Ssklower /* 19536372Ssklower * The cache is valid 19636372Ssklower */ 19736372Ssklower 19836372Ssklower IFDEBUG(D_OUTPUT) 19936372Ssklower printf("clnp_output: using cache\n"); 20036372Ssklower ENDDEBUG 20136372Ssklower 20237469Ssklower m = m_copy(clcp->clc_hdr, 0, (int)M_COPYALL); 20336372Ssklower if (m == NULL) { 20436372Ssklower /* 20536372Ssklower * No buffers left to copy cached packet header. Use 20636372Ssklower * the cached packet header this time, and 20736372Ssklower * mark the hdr as vacant 20836372Ssklower */ 20936372Ssklower m = clcp->clc_hdr; 21036372Ssklower clcp->clc_hdr = NULL; 21136372Ssklower } 21236372Ssklower m->m_next = m0; /* ASSUMES pkt hdr is 1 mbuf long */ 21336372Ssklower clnp = mtod(m, struct clnp_fixed *); 21436372Ssklower } else { 21536372Ssklower struct clnp_optidx *oidx = NULL; /* index to clnp options */ 21636372Ssklower 21736372Ssklower /* 21836372Ssklower * The cache is not valid. Allocate an mbuf (if necessary) 21936372Ssklower * to hold cached info. If one is not available, then 22036372Ssklower * don't bother with the cache 22136372Ssklower */ 22236372Ssklower INCSTAT(cns_cachemiss); 22336372Ssklower if (flags & CLNP_NOCACHE) { 22436372Ssklower clcp = &clc; 22536372Ssklower } else { 22636372Ssklower if (isop->isop_clnpcache == NULL) { 22736372Ssklower /* 22836372Ssklower * There is no clnpcache. Allocate an mbuf to hold one 22936372Ssklower */ 23036372Ssklower if ((isop->isop_clnpcache = m_get(M_DONTWAIT, MT_HEADER)) 23136372Ssklower == NULL) { 23236372Ssklower /* 23336372Ssklower * No mbufs available. Pretend that we don't want 23436372Ssklower * caching this time. 23536372Ssklower */ 23636372Ssklower IFDEBUG(D_OUTPUT) 23736372Ssklower printf("clnp_output: no mbufs to allocate to cache\n"); 23836372Ssklower ENDDEBUG 23936372Ssklower flags |= CLNP_NOCACHE; 24036372Ssklower clcp = &clc; 24136372Ssklower } else { 24236372Ssklower clcp = mtod(isop->isop_clnpcache, struct clnp_cache *); 24336372Ssklower } 24436372Ssklower } else { 24536372Ssklower /* 24636372Ssklower * A clnpcache mbuf exists. If the clc_hdr is not null, 24736372Ssklower * we must free it, as a new one is about to be created. 24836372Ssklower */ 24936372Ssklower clcp = mtod(isop->isop_clnpcache, struct clnp_cache *); 25036372Ssklower if (clcp->clc_hdr != NULL) { 25136372Ssklower /* 25236372Ssklower * The clc_hdr is not null but a clnpcache mbuf exists. 25336372Ssklower * This means that there was a cache, but the existing 25436372Ssklower * copy of the hdr is no longer valid. Free it now 25536372Ssklower * before we lose the pointer to it. 25636372Ssklower */ 25736372Ssklower IFDEBUG(D_OUTPUT) 25836372Ssklower printf("clnp_output: freeing old clc_hdr 0x%x\n", 25936372Ssklower clcp->clc_hdr); 26036372Ssklower ENDDEBUG 26136372Ssklower m_free(clcp->clc_hdr); 26236372Ssklower IFDEBUG(D_OUTPUT) 26336372Ssklower printf("clnp_output: freed old clc_hdr (done)\n"); 26436372Ssklower ENDDEBUG 26536372Ssklower } 26636372Ssklower } 26736372Ssklower } 26836372Ssklower IFDEBUG(D_OUTPUT) 26936372Ssklower printf("clnp_output: NEW clcp x%x\n",clcp); 27036372Ssklower ENDDEBUG 27136372Ssklower bzero((caddr_t)clcp, sizeof(struct clnp_cache)); 27236372Ssklower 27336372Ssklower if (isop->isop_optindex) 27436372Ssklower oidx = mtod(isop->isop_optindex, struct clnp_optidx *); 27536372Ssklower 27636372Ssklower /* 27736372Ssklower * Don't allow packets with security, quality of service, 27836372Ssklower * priority, or error report options to be sent. 27936372Ssklower */ 28036372Ssklower if ((isop->isop_options) && (oidx)) { 28136372Ssklower if ((oidx->cni_securep) || 28236372Ssklower (oidx->cni_priorp) || 28336372Ssklower (oidx->cni_qos_formatp) || 28436372Ssklower (oidx->cni_er_reason != ER_INVALREAS)) { 28536372Ssklower IFDEBUG(D_OUTPUT) 28636372Ssklower printf("clnp_output: pkt dropped - option unsupported\n"); 28736372Ssklower ENDDEBUG 28836372Ssklower m_freem(m0); 28936372Ssklower return(EINVAL); 29036372Ssklower } 29136372Ssklower } 29236372Ssklower 29336372Ssklower /* 29436372Ssklower * Don't allow any invalid flags to be set 29536372Ssklower */ 29636372Ssklower if ((flags & (CLNP_VFLAGS)) != flags) { 29736372Ssklower IFDEBUG(D_OUTPUT) 29836372Ssklower printf("clnp_output: packet dropped - flags unsupported\n"); 29936372Ssklower ENDDEBUG 30036372Ssklower m_freem(m0); 30136372Ssklower return(EINVAL); 30236372Ssklower } 30336372Ssklower 30436372Ssklower /* 30536372Ssklower * Don't allow funny lengths on dst; src may be zero in which 30636372Ssklower * case we insert the source address based upon the interface 30736372Ssklower */ 30836372Ssklower if ((src->isoa_len > sizeof(struct iso_addr)) || 30936372Ssklower (dst->isoa_len == 0) || 31036372Ssklower (dst->isoa_len > sizeof(struct iso_addr))) { 31136372Ssklower m_freem(m0); 31236372Ssklower return(ENAMETOOLONG); 31336372Ssklower } 31436372Ssklower 31536372Ssklower /* 31636372Ssklower * Grab mbuf to contain header 31736372Ssklower */ 31837469Ssklower MGETHDR(m, M_DONTWAIT, MT_HEADER); 31936372Ssklower if (m == 0) { 32036372Ssklower m_freem(m0); 32136372Ssklower return(ENOBUFS); 32236372Ssklower } 32336372Ssklower 32436372Ssklower m->m_next = m0; 32536372Ssklower clnp = mtod(m, struct clnp_fixed *); 32636372Ssklower clcp->clc_segoff = 0; 32736372Ssklower 32836372Ssklower /* 32936372Ssklower * Fill in all of fixed hdr except lengths and checksum 33036372Ssklower */ 33136372Ssklower if (flags & CLNP_SEND_RAW) { 33236372Ssklower *clnp = raw_template; 33336372Ssklower } else if (flags & CLNP_ECHO) { 33436372Ssklower *clnp = echo_template; 33536372Ssklower } else { 33636372Ssklower *clnp = dt_template; 33736372Ssklower } 33836372Ssklower if (flags & CLNP_NO_SEG) 33937469Ssklower clnp->cnf_type &= ~CNF_SEG_OK; 34036372Ssklower if (flags & CLNP_NO_ER) 34137469Ssklower clnp->cnf_type &= ~CNF_ERR_OK; 34236372Ssklower 34336372Ssklower /* 34436372Ssklower * Route packet; special case for source rt 34536372Ssklower */ 34636372Ssklower if ((isop->isop_options) && CLNPSRCRT_VALID(oidx)) { 34736372Ssklower IFDEBUG(D_OUTPUT) 34836372Ssklower printf("clnp_output: calling clnp_srcroute\n"); 34936372Ssklower ENDDEBUG 35036372Ssklower error = clnp_srcroute(isop->isop_options, oidx, &isop->isop_route, 35137469Ssklower &clcp->clc_firsthop, &clcp->clc_ifa, dst); 35236372Ssklower } else { 35336372Ssklower IFDEBUG(D_OUTPUT) 35436372Ssklower ENDDEBUG 35536372Ssklower error = clnp_route(dst, &isop->isop_route, flags, 35637469Ssklower &clcp->clc_firsthop, &clcp->clc_ifa); 35736372Ssklower } 35837469Ssklower if (error || (clcp->clc_ifa == 0)) { 35936372Ssklower IFDEBUG(D_OUTPUT) 36036372Ssklower printf("clnp_output: route failed, errno %d\n", error); 36136372Ssklower printf("@clcp:\n"); 36236372Ssklower dump_buf(clcp, sizeof (struct clnp_cache)); 36336372Ssklower ENDDEBUG 36436372Ssklower goto bad; 36536372Ssklower } 36636372Ssklower 36736372Ssklower IFDEBUG(D_OUTPUT) 36836372Ssklower printf("clnp_output: packet routed to %s\n", 36936372Ssklower clnp_iso_addrp( 37036372Ssklower &((struct sockaddr_iso *)clcp->clc_firsthop)->siso_addr)); 37136372Ssklower ENDDEBUG 37236372Ssklower 37336372Ssklower /* 37436372Ssklower * If src address is not yet specified, use address of 37536372Ssklower * interface. NOTE: this will now update the laddr field in 37636372Ssklower * the isopcb. Is this desirable? RAH? 37736372Ssklower */ 37836372Ssklower if (src->isoa_len == 0) { 37937469Ssklower src = &(clcp->clc_ifa->ia_addr.siso_addr); 38036372Ssklower IFDEBUG(D_OUTPUT) 38136372Ssklower printf("clnp_output: new src %s\n", clnp_iso_addrp(src)); 38236372Ssklower ENDDEBUG 38336372Ssklower } 38436372Ssklower 38536372Ssklower /* 38636372Ssklower * Insert the source and destination address, 38736372Ssklower */ 38836372Ssklower hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); 38937469Ssklower CLNP_INSERT_ADDR(hoff, *dst); 39037469Ssklower CLNP_INSERT_ADDR(hoff, *src); 39136372Ssklower 39236372Ssklower /* 39336372Ssklower * Leave room for the segment part, if segmenting is selected 39436372Ssklower */ 39537469Ssklower if (clnp->cnf_type & CNF_SEG_OK) { 39636372Ssklower clcp->clc_segoff = hoff - (caddr_t)clnp; 39736372Ssklower hoff += sizeof(struct clnp_segment); 39836372Ssklower } 39936372Ssklower 40036372Ssklower clnp->cnf_hdr_len = m->m_len = (u_char)(hoff - (caddr_t)clnp); 40136768Ssklower hdrlen = clnp->cnf_hdr_len; 40236372Ssklower 40336768Ssklower #ifdef DECBIT 40436372Ssklower /* 40536768Ssklower * Add the globally unique QOS (with room for congestion experienced 40636768Ssklower * bit). I can safely assume that this option is not in the options 40736768Ssklower * mbuf below because I checked that the option was not specified 40836768Ssklower * previously 40936768Ssklower */ 41036768Ssklower if ((m->m_len + sizeof(qos_option)) < MLEN) { 41136768Ssklower bcopy((caddr_t)qos_option, hoff, sizeof(qos_option)); 41236768Ssklower clnp->cnf_hdr_len += sizeof(qos_option); 41336768Ssklower hdrlen += sizeof(qos_option); 41436768Ssklower m->m_len += sizeof(qos_option); 41536768Ssklower } 41636768Ssklower #endif DECBIT 41736768Ssklower 41836768Ssklower /* 41936372Ssklower * If an options mbuf is present, concatenate a copy to the hdr mbuf. 42036372Ssklower */ 42136372Ssklower if (isop->isop_options) { 42237469Ssklower struct mbuf *opt_copy = m_copy(isop->isop_options, 0, (int)M_COPYALL); 42336372Ssklower if (opt_copy == NULL) { 42436372Ssklower error = ENOBUFS; 42536372Ssklower goto bad; 42636372Ssklower } 42736372Ssklower /* Link in place */ 42836372Ssklower opt_copy->m_next = m->m_next; 42936372Ssklower m->m_next = opt_copy; 43036372Ssklower 43136372Ssklower /* update size of header */ 43236372Ssklower clnp->cnf_hdr_len += opt_copy->m_len; 43336768Ssklower hdrlen += opt_copy->m_len; 43436372Ssklower } 43536372Ssklower 43636768Ssklower if (hdrlen > CLNP_HDR_MAX) { 43736768Ssklower error = EMSGSIZE; 43836768Ssklower goto bad; 43936768Ssklower } 44036768Ssklower 44136372Ssklower /* 44236372Ssklower * Now set up the cache entry in the pcb 44336372Ssklower */ 44436372Ssklower if ((flags & CLNP_NOCACHE) == 0) { 44537469Ssklower if (clcp->clc_hdr = m_copy(m, 0, (int)clnp->cnf_hdr_len)) { 44637469Ssklower clcp->clc_dst = *dst; 44736372Ssklower clcp->clc_flags = flags; 44836372Ssklower clcp->clc_options = isop->isop_options; 44936372Ssklower } 45036372Ssklower } 45136372Ssklower } 45236372Ssklower INCSTAT(cns_sent); 45336372Ssklower /* 45436372Ssklower * If small enough for interface, send directly 45536372Ssklower * Fill in segmentation part of hdr if using the full protocol 45636372Ssklower */ 45737469Ssklower if ((total_len = clnp->cnf_hdr_len + datalen) 45837469Ssklower <= SN_MTU(clcp->clc_ifa->ia_ifp)) { 45937469Ssklower if (clnp->cnf_type & CNF_SEG_OK) { 46036372Ssklower struct clnp_segment seg_part; /* segment part of hdr */ 46136372Ssklower seg_part.cng_id = htons(clnp_id++); 46236372Ssklower seg_part.cng_off = htons(0); 46336372Ssklower seg_part.cng_tot_len = htons(total_len); 46436372Ssklower (void) bcopy((caddr_t)&seg_part, (caddr_t) clnp + clcp->clc_segoff, 46536372Ssklower sizeof(seg_part)); 46636372Ssklower } 46736372Ssklower HTOC(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, total_len); 46837469Ssklower m->m_pkthdr.len = total_len; 46936372Ssklower /* 47036372Ssklower * Compute clnp checksum (on header only) 47136372Ssklower */ 47236372Ssklower if (flags & CLNP_NO_CKSUM) { 47336372Ssklower HTOC(clnp->cnf_cksum_msb, clnp->cnf_cksum_lsb, 0); 47436372Ssklower } else { 47536372Ssklower iso_gen_csum(m, CLNP_CKSUM_OFF, (int)clnp->cnf_hdr_len); 47636372Ssklower } 47736372Ssklower 47836372Ssklower IFDEBUG(D_DUMPOUT) 47936372Ssklower struct mbuf *mdump = m; 48036372Ssklower printf("clnp_output: sending dg:\n"); 48136372Ssklower while (mdump != NULL) { 48236372Ssklower dump_buf(mtod(mdump, caddr_t), mdump->m_len); 48336372Ssklower mdump = mdump->m_next; 48436372Ssklower } 48536372Ssklower ENDDEBUG 48636372Ssklower 48736372Ssklower error = SN_OUTPUT(clcp, m); 48836372Ssklower goto done; 48936372Ssklower } else { 49036372Ssklower /* 49136372Ssklower * Too large for interface; fragment if possible. 49236372Ssklower */ 49337469Ssklower error = clnp_fragment(clcp->clc_ifa->ia_ifp, m, clcp->clc_firsthop, total_len, 49436372Ssklower clcp->clc_segoff, flags); 49536372Ssklower goto done; 49636372Ssklower } 49736372Ssklower bad: 49836372Ssklower m_freem(m); 49936372Ssklower 50036372Ssklower done: 50136372Ssklower return(error); 50236372Ssklower } 50336372Ssklower 50436372Ssklower int clnp_ctloutput() 50536372Ssklower { 50636372Ssklower } 50736372Ssklower 50836372Ssklower #endif ISO 509