149267Sbostic /*- 249267Sbostic * Copyright (c) 1991 The Regents of the University of California. 349267Sbostic * All rights reserved. 449267Sbostic * 549267Sbostic * %sccs.include.redist.c% 649267Sbostic * 7*60359Sbostic * @(#)clnp_input.c 7.16 (Berkeley) 05/25/93 849267Sbostic */ 949267Sbostic 1036370Ssklower /*********************************************************** 1136370Ssklower Copyright IBM Corporation 1987 1236370Ssklower 1336370Ssklower All Rights Reserved 1436370Ssklower 1536370Ssklower Permission to use, copy, modify, and distribute this software and its 1636370Ssklower documentation for any purpose and without fee is hereby granted, 1736370Ssklower provided that the above copyright notice appear in all copies and that 1836370Ssklower both that copyright notice and this permission notice appear in 1936370Ssklower supporting documentation, and that the name of IBM not be 2036370Ssklower used in advertising or publicity pertaining to distribution of the 2136370Ssklower software without specific, written prior permission. 2236370Ssklower 2336370Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436370Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536370Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636370Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736370Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836370Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936370Ssklower SOFTWARE. 3036370Ssklower 3136370Ssklower ******************************************************************/ 3236370Ssklower 3336370Ssklower /* 3436370Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536370Ssklower */ 3636766Ssklower /* $Header: /var/src/sys/netiso/RCS/clnp_input.c,v 5.1 89/02/09 16:20:32 hagens Exp $ */ 3736766Ssklower /* $Source: /var/src/sys/netiso/RCS/clnp_input.c,v $ */ 3836370Ssklower 3956533Sbostic #include <sys/param.h> 4056533Sbostic #include <sys/mbuf.h> 4156533Sbostic #include <sys/domain.h> 4256533Sbostic #include <sys/protosw.h> 4356533Sbostic #include <sys/socket.h> 4456533Sbostic #include <sys/socketvar.h> 4556533Sbostic #include <sys/errno.h> 4656533Sbostic #include <sys/time.h> 4736370Ssklower 4856533Sbostic #include <net/if.h> 4956533Sbostic #include <net/if_types.h> 5056533Sbostic #include <net/route.h> 5136370Ssklower 5256533Sbostic #include <netiso/iso.h> 5356533Sbostic #include <netiso/iso_var.h> 5456533Sbostic #include <netiso/iso_snpac.h> 5556533Sbostic #include <netiso/clnp.h> 5656533Sbostic #include <netiso/clnl.h> 5756533Sbostic #include <netiso/esis.h> 5856533Sbostic #include <netinet/in_systm.h> 5956533Sbostic #include <netinet/ip.h> 6056533Sbostic #include <netinet/if_ether.h> 6156533Sbostic #include <netiso/eonvar.h> 6256533Sbostic #include <netiso/clnp_stat.h> 6356533Sbostic #include <netiso/argo_debug.h> 6436370Ssklower 6536370Ssklower #ifdef ISO 6636370Ssklower u_char clnp_protox[ISOPROTO_MAX]; 6736370Ssklower struct clnl_protosw clnl_protox[256]; 6836370Ssklower int clnpqmaxlen = IFQ_MAXLEN; /* RAH? why is this a variable */ 6936370Ssklower struct mbuf *clnp_data_ck(); 7036370Ssklower 7136370Ssklower int clnp_input(); 7236370Ssklower 7336370Ssklower int esis_input(); 7436370Ssklower 7536370Ssklower #ifdef ISO_X25ESIS 7636370Ssklower int x25esis_input(); 77*60359Sbostic #endif /* ISO_X25ESIS */ 7836370Ssklower 7936370Ssklower /* 8036370Ssklower * FUNCTION: clnp_init 8136370Ssklower * 8236370Ssklower * PURPOSE: clnp initialization. Fill in clnp switch tables. 8336370Ssklower * 8436370Ssklower * RETURNS: none 8536370Ssklower * 8636370Ssklower * SIDE EFFECTS: fills in clnp_protox table with correct offsets into 8736370Ssklower * the isosw table. 8836370Ssklower * 8936370Ssklower * NOTES: 9036370Ssklower */ 9136370Ssklower clnp_init() 9236370Ssklower { 9336370Ssklower register struct protosw *pr; 9436370Ssklower 9536370Ssklower /* 9636370Ssklower * CLNP protox initialization 9736370Ssklower */ 9836370Ssklower if ((pr = pffindproto(PF_ISO, ISOPROTO_RAW, SOCK_RAW)) == 0) 9936370Ssklower printf("clnl_init: no raw CLNP\n"); 10036370Ssklower else 10136370Ssklower clnp_protox[ISOPROTO_RAW] = pr - isosw; 10236370Ssklower 10336370Ssklower if ((pr = pffindproto(PF_ISO, ISOPROTO_TP, SOCK_SEQPACKET)) == 0) 10436370Ssklower printf("clnl_init: no tp/clnp\n"); 10536370Ssklower else 10636370Ssklower clnp_protox[ISOPROTO_TP] = pr - isosw; 10736370Ssklower 10836370Ssklower /* 10936370Ssklower * CLNL protox initialization 11036370Ssklower */ 11136370Ssklower clnl_protox[ISO8473_CLNP].clnl_input = clnp_input; 11236370Ssklower 11336370Ssklower clnlintrq.ifq_maxlen = clnpqmaxlen; 11436370Ssklower } 11536370Ssklower 11636370Ssklower /* 11736370Ssklower * FUNCTION: clnlintr 11836370Ssklower * 11936370Ssklower * PURPOSE: Process a packet on the clnl input queue 12036370Ssklower * 12136370Ssklower * RETURNS: nothing. 12236370Ssklower * 12336370Ssklower * SIDE EFFECTS: 12436370Ssklower * 12536370Ssklower * NOTES: 12636370Ssklower */ 12736370Ssklower clnlintr() 12836370Ssklower { 12936370Ssklower register struct mbuf *m; /* ptr to first mbuf of pkt */ 13036370Ssklower register struct clnl_fixed *clnl; /* ptr to fixed part of clnl hdr */ 13136370Ssklower int s; /* save and restore priority */ 13236370Ssklower struct clnl_protosw *clnlsw;/* ptr to protocol switch */ 13336370Ssklower struct snpa_hdr sh; /* subnetwork hdr */ 13436370Ssklower 13536370Ssklower /* 13636370Ssklower * Get next datagram off clnl input queue 13736370Ssklower */ 13836370Ssklower next: 13936370Ssklower s = splimp(); 14036765Ssklower /* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/ 14136765Ssklower IF_DEQUEUE(&clnlintrq, m); 14237469Ssklower splx(s); 14336370Ssklower 14436765Ssklower 14536765Ssklower if (m == 0) /* nothing to do */ 14636765Ssklower return; 14743332Ssklower if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.rcvif == 0) { 14836765Ssklower m_freem(m); 14936765Ssklower goto next; 15043332Ssklower } else { 15143332Ssklower register struct ifaddr *ifa; 15243332Ssklower for (ifa = m->m_pkthdr.rcvif->if_addrlist; ifa; ifa = ifa->ifa_next) 15343332Ssklower if (ifa->ifa_addr->sa_family == AF_ISO) 15443332Ssklower break; 15543332Ssklower if (ifa == 0) { 15643332Ssklower m_freem(m); 15743332Ssklower goto next; 15843332Ssklower } 15936765Ssklower } 16037469Ssklower bzero((caddr_t)&sh, sizeof(sh)); 16137469Ssklower sh.snh_flags = m->m_flags & (M_MCAST|M_BCAST); 16237469Ssklower switch((sh.snh_ifp = m->m_pkthdr.rcvif)->if_type) { 16337469Ssklower extern int ether_output(); 16437469Ssklower case IFT_EON: 16537469Ssklower bcopy(mtod(m, caddr_t), (caddr_t)sh.snh_dhost, sizeof(u_long)); 16637469Ssklower bcopy(sizeof(u_long) + mtod(m, caddr_t), 16737469Ssklower (caddr_t)sh.snh_shost, sizeof(u_long)); 16837469Ssklower sh.snh_dhost[4] = mtod(m, u_char *)[sizeof(struct ip) + 16937469Ssklower _offsetof(struct eon_hdr, eonh_class)]; 17037469Ssklower m->m_data += EONIPLEN; 17137469Ssklower m->m_len -= EONIPLEN; 17237469Ssklower m->m_pkthdr.len -= EONIPLEN; 17337469Ssklower break; 17437469Ssklower 17537469Ssklower default: 17637469Ssklower if (sh.snh_ifp->if_output == ether_output) { 17738841Ssklower bcopy((caddr_t)(mtod(m, struct ether_header *)->ether_dhost), 17837469Ssklower (caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost)); 17938841Ssklower m->m_data += sizeof (struct ether_header); 18038841Ssklower m->m_len -= sizeof (struct ether_header); 18138841Ssklower m->m_pkthdr.len -= sizeof (struct ether_header); 18237469Ssklower } 18337469Ssklower } 18436370Ssklower IFDEBUG(D_INPUT) 18536370Ssklower int i; 18636370Ssklower printf("clnlintr: src:"); 18736370Ssklower for (i=0; i<6; i++) 18836370Ssklower printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' '); 18936370Ssklower printf(" dst:"); 19036370Ssklower for (i=0; i<6; i++) 19136370Ssklower printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' '); 19236370Ssklower printf("\n"); 19336370Ssklower ENDDEBUG 19436370Ssklower 19536370Ssklower /* 19636370Ssklower * Get the fixed part of the clnl header into the first mbuf. 19736370Ssklower * Drop the packet if this fails. 19836370Ssklower * Do not call m_pullup if we have a cluster mbuf or the 19936370Ssklower * data is not there. 20036370Ssklower */ 20136370Ssklower if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) && 20236370Ssklower ((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) { 20336370Ssklower INCSTAT(cns_toosmall); /* TODO: use clnl stats */ 20436370Ssklower goto next; /* m_pullup discards mbuf */ 20536370Ssklower } 20636370Ssklower 20736370Ssklower clnl = mtod(m, struct clnl_fixed *); 20836370Ssklower 20936370Ssklower /* 21036370Ssklower * Drop packet if the length of the header is not reasonable. 21136370Ssklower */ 21236370Ssklower if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) || 21336370Ssklower (clnl->cnf_hdr_len > CLNP_HDR_MAX)) { 21436370Ssklower INCSTAT(cns_badhlen); /* TODO: use clnl stats */ 21536370Ssklower m_freem(m); 21636370Ssklower goto next; 21736370Ssklower } 21836370Ssklower 21936370Ssklower /* 22036370Ssklower * If the header is not contained in this mbuf, make it so. 22136370Ssklower * Drop packet if this fails. 22236370Ssklower * Note: m_pullup will allocate a cluster mbuf if necessary 22336370Ssklower */ 22436370Ssklower if (clnl->cnf_hdr_len > m->m_len) { 22537469Ssklower if ((m = m_pullup(m, (int)clnl->cnf_hdr_len)) == 0) { 22636370Ssklower INCSTAT(cns_badhlen); /* TODO: use clnl stats */ 22736370Ssklower goto next; /* m_pullup discards mbuf */ 22836370Ssklower } 22936370Ssklower clnl = mtod(m, struct clnl_fixed *); 23036370Ssklower } 23136370Ssklower 23236370Ssklower clnlsw = &clnl_protox[clnl->cnf_proto_id]; 23336370Ssklower 23436370Ssklower 23536370Ssklower if (clnlsw->clnl_input) 23636370Ssklower (*clnlsw->clnl_input) (m, &sh); 23736370Ssklower else 23836370Ssklower m_freem(m); 23936370Ssklower 24036370Ssklower goto next; 24136370Ssklower } 24236370Ssklower 24336370Ssklower /* 24436370Ssklower * FUNCTION: clnp_input 24536370Ssklower * 24636370Ssklower * PURPOSE: process an incoming clnp packet 24736370Ssklower * 24836370Ssklower * RETURNS: nothing 24936370Ssklower * 25036370Ssklower * SIDE EFFECTS: increments fields of clnp_stat structure. 25136370Ssklower * 25236370Ssklower * NOTES: 25336370Ssklower * TODO: I would like to make seg_part a pointer into the mbuf, but 25436370Ssklower * will it be correctly aligned? 25536370Ssklower */ 25637469Ssklower clnp_input(m, shp) 25736370Ssklower struct mbuf *m; /* ptr to first mbuf of pkt */ 25836370Ssklower struct snpa_hdr *shp; /* subnetwork header */ 25936370Ssklower { 26036370Ssklower register struct clnp_fixed *clnp; /* ptr to fixed part of header */ 26139930Ssklower struct sockaddr_iso source; /* source address of pkt */ 26239930Ssklower struct sockaddr_iso target; /* destination address of pkt */ 26339930Ssklower #define src source.siso_addr 26439930Ssklower #define dst target.siso_addr 26536370Ssklower caddr_t hoff; /* current offset in packet */ 26636370Ssklower caddr_t hend; /* address of end of header info */ 26736370Ssklower struct clnp_segment seg_part; /* segment part of hdr */ 26836370Ssklower int seg_off=0; /* offset of segment part of hdr */ 26936370Ssklower int seg_len;/* length of packet data&hdr in bytes */ 27036370Ssklower struct clnp_optidx oidx, *oidxp = NULL; /* option index */ 27136370Ssklower extern int iso_systype; /* used by ESIS config resp */ 27239930Ssklower extern struct sockaddr_iso blank_siso; /* used for initializing */ 27336766Ssklower int need_afrin = 0; 27436766Ssklower /* true if congestion experienced */ 27536766Ssklower /* which means you need afrin nose */ 27636766Ssklower /* spray. How clever! */ 27736370Ssklower 27836370Ssklower IFDEBUG(D_INPUT) 27936370Ssklower printf( 28036766Ssklower "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n", 28136766Ssklower m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal"); 28236370Ssklower ENDDEBUG 28336766Ssklower need_afrin = 0; 28436370Ssklower 28536370Ssklower /* 28636370Ssklower * If no iso addresses have been set, there is nothing 28736370Ssklower * to do with the packet. 28836370Ssklower */ 28936370Ssklower if (iso_ifaddr == NULL) { 29036370Ssklower clnp_discard(m, ADDR_DESTUNREACH); 29136370Ssklower return; 29236370Ssklower } 29336370Ssklower 29436370Ssklower INCSTAT(cns_total); 29536370Ssklower clnp = mtod(m, struct clnp_fixed *); 29636370Ssklower 29736766Ssklower IFDEBUG(D_DUMPIN) 29836766Ssklower struct mbuf *mhead; 29936766Ssklower int total_len = 0; 30036766Ssklower printf("clnp_input: clnp header:\n"); 30136766Ssklower dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len); 30236766Ssklower printf("clnp_input: mbuf chain:\n"); 30336766Ssklower for (mhead = m; mhead != NULL; mhead=mhead->m_next) { 30436766Ssklower printf("m x%x, len %d\n", mhead, mhead->m_len); 30536766Ssklower total_len += mhead->m_len; 30636766Ssklower } 30736766Ssklower printf("clnp_input: total length of mbuf chain %d:\n", total_len); 30836766Ssklower ENDDEBUG 30936766Ssklower 31036370Ssklower /* 31136370Ssklower * Compute checksum (if necessary) and drop packet if 31236370Ssklower * checksum does not match 31336370Ssklower */ 31437469Ssklower if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, (int)clnp->cnf_hdr_len)) { 31536370Ssklower INCSTAT(cns_badcsum); 31636370Ssklower clnp_discard(m, GEN_BADCSUM); 31737469Ssklower return; 31836370Ssklower } 31936370Ssklower 32036370Ssklower if (clnp->cnf_vers != ISO8473_V1) { 32136370Ssklower INCSTAT(cns_badvers); 32236370Ssklower clnp_discard(m, DISC_UNSUPPVERS); 32337469Ssklower return; 32436370Ssklower } 32536370Ssklower 32636370Ssklower 32736370Ssklower /* check mbuf data length: clnp_data_ck will free mbuf upon error */ 32836370Ssklower CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len); 32936370Ssklower if ((m = clnp_data_ck(m, seg_len)) == 0) 33037469Ssklower return; 33136370Ssklower 33236370Ssklower clnp = mtod(m, struct clnp_fixed *); 33336370Ssklower hend = (caddr_t)clnp + clnp->cnf_hdr_len; 33436370Ssklower 33536370Ssklower /* 33636370Ssklower * extract the source and destination address 33736370Ssklower * drop packet on failure 33836370Ssklower */ 33939930Ssklower source = target = blank_siso; 34036370Ssklower 34136370Ssklower hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); 34236370Ssklower CLNP_EXTRACT_ADDR(dst, hoff, hend); 34336370Ssklower if (hoff == (caddr_t)0) { 34436370Ssklower INCSTAT(cns_badaddr); 34536370Ssklower clnp_discard(m, GEN_INCOMPLETE); 34637469Ssklower return; 34736370Ssklower } 34836370Ssklower CLNP_EXTRACT_ADDR(src, hoff, hend); 34936370Ssklower if (hoff == (caddr_t)0) { 35036370Ssklower INCSTAT(cns_badaddr); 35136370Ssklower clnp_discard(m, GEN_INCOMPLETE); 35237469Ssklower return; 35336370Ssklower } 35436370Ssklower 35536370Ssklower IFDEBUG(D_INPUT) 35636370Ssklower printf("clnp_input: from %s", clnp_iso_addrp(&src)); 35736370Ssklower printf(" to %s\n", clnp_iso_addrp(&dst)); 35836370Ssklower ENDDEBUG 35936370Ssklower 36036370Ssklower /* 36136370Ssklower * extract the segmentation information, if it is present. 36236370Ssklower * drop packet on failure 36336370Ssklower */ 36437469Ssklower if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && 36537469Ssklower (clnp->cnf_type & CNF_SEG_OK)) { 36636370Ssklower if (hoff + sizeof(struct clnp_segment) > hend) { 36736370Ssklower INCSTAT(cns_noseg); 36836370Ssklower clnp_discard(m, GEN_INCOMPLETE); 36937469Ssklower return; 37036370Ssklower } else { 37136370Ssklower (void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment)); 37236370Ssklower /* make sure segmentation fields are in host order */ 37336370Ssklower seg_part.cng_id = ntohs(seg_part.cng_id); 37436370Ssklower seg_part.cng_off = ntohs(seg_part.cng_off); 37536370Ssklower seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len); 37636370Ssklower seg_off = hoff - (caddr_t)clnp; 37736370Ssklower hoff += sizeof(struct clnp_segment); 37836370Ssklower } 37936370Ssklower } 38036370Ssklower 38136370Ssklower /* 38236370Ssklower * process options if present. If clnp_opt_sanity returns 38336370Ssklower * false (indicating an error was found in the options) or 38436370Ssklower * an unsupported option was found 38536370Ssklower * then drop packet and emit an ER. 38636370Ssklower */ 38736370Ssklower if (hoff < hend) { 38836370Ssklower int errcode; 38936370Ssklower 39036370Ssklower oidxp = &oidx; 39136370Ssklower errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp); 39236370Ssklower 39336370Ssklower /* we do not support security */ 39436370Ssklower if ((errcode == 0) && (oidxp->cni_securep)) 39536370Ssklower errcode = DISC_UNSUPPSECURE; 39636370Ssklower 39736370Ssklower /* the er option is valid with ER pdus only */ 39836370Ssklower if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) && 39937469Ssklower ((clnp->cnf_type & CNF_TYPE) != CLNP_ER)) 40036370Ssklower errcode = DISC_UNSUPPOPT; 40136370Ssklower 40236766Ssklower #ifdef DECBIT 40336766Ssklower /* check if the congestion experienced bit is set */ 40436766Ssklower if (oidxp->cni_qos_formatp) { 40536766Ssklower caddr_t qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp); 40636766Ssklower u_char qos = *qosp; 40736766Ssklower 40836766Ssklower need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) == 40936766Ssklower (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)); 41036766Ssklower if (need_afrin) 41136766Ssklower INCSTAT(cns_congest_rcvd); 41236766Ssklower } 413*60359Sbostic #endif /* DECBIT */ 41436766Ssklower 41536370Ssklower if (errcode != 0) { 41636370Ssklower clnp_discard(m, (char)errcode); 41736370Ssklower IFDEBUG(D_INPUT) 41836370Ssklower printf("clnp_input: dropped (err x%x) due to bad options\n", 41936370Ssklower errcode); 42036370Ssklower ENDDEBUG 42137469Ssklower return; 42236370Ssklower } 42336370Ssklower } 42436370Ssklower 42536370Ssklower /* 42636370Ssklower * check if this packet is for us. if not, then forward 42736370Ssklower */ 42836370Ssklower if (clnp_ours(&dst) == 0) { 42936370Ssklower IFDEBUG(D_INPUT) 43036370Ssklower printf("clnp_input: forwarding packet not for us\n"); 43136370Ssklower ENDDEBUG 43236370Ssklower clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp); 43337469Ssklower return; 43436370Ssklower } 43536370Ssklower 43636370Ssklower /* 43736370Ssklower * ESIS Configuration Response Function 43836370Ssklower * 43936370Ssklower * If the packet received was sent to the multicast address 44036370Ssklower * all end systems, then send an esh to the source 44136370Ssklower */ 44237469Ssklower if ((shp->snh_flags & M_MCAST) && (iso_systype == SNPA_ES)) { 44336370Ssklower extern short esis_holding_time; 44436370Ssklower 44536370Ssklower esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time, 44643332Ssklower shp->snh_shost, 6, &dst); 44736370Ssklower } 44836370Ssklower 44936370Ssklower /* 45036370Ssklower * If this is a fragment, then try to reassemble it. If clnp_reass 45136370Ssklower * returns non NULL, the packet has been reassembled, and should 45236370Ssklower * be give to TP. Otherwise the fragment has been delt with 45336370Ssklower * by the reassembly code (either stored or deleted). In either case 45436370Ssklower * we should have nothing more to do with it. 45536370Ssklower */ 45637469Ssklower if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && 45737469Ssklower (clnp->cnf_type & CNF_SEG_OK) && 45836370Ssklower (seg_len != seg_part.cng_tot_len)) { 45936370Ssklower struct mbuf *m0; 46036370Ssklower 46136370Ssklower if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) { 46236370Ssklower m = m0; 46336370Ssklower clnp = mtod(m, struct clnp_fixed *); 46439195Ssklower INCSTAT(cns_reassembled); 46536370Ssklower } else { 46637469Ssklower return; 46736370Ssklower } 46836370Ssklower } 46936370Ssklower 47036370Ssklower /* 47136370Ssklower * give the packet to the higher layer 47236370Ssklower * 47336370Ssklower * Note: the total length of packet 47436370Ssklower * is the total length field of the segmentation part, 47536370Ssklower * or, if absent, the segment length field of the 47636370Ssklower * header. 47736370Ssklower */ 47839195Ssklower INCSTAT(cns_delivered); 47937469Ssklower switch (clnp->cnf_type & CNF_TYPE) { 48036370Ssklower case CLNP_ER: 48136370Ssklower /* 48236370Ssklower * This ER must have the er option. 48336370Ssklower * If the option is not present, discard datagram. 48436370Ssklower */ 48536370Ssklower if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) { 48636370Ssklower clnp_discard(m, GEN_HDRSYNTAX); 48736370Ssklower } else { 48836370Ssklower clnp_er_input(m, &src, oidxp->cni_er_reason); 48936370Ssklower } 49036370Ssklower break; 49136370Ssklower 49236370Ssklower case CLNP_DT: 49339930Ssklower (*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &source, &target, 49439931Ssklower clnp->cnf_hdr_len, need_afrin); 49536370Ssklower break; 49636370Ssklower 49736370Ssklower case CLNP_RAW: 49836370Ssklower case CLNP_ECR: 49936370Ssklower IFDEBUG(D_INPUT) 50036370Ssklower printf("clnp_input: raw input of %d bytes\n", 50137469Ssklower clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len); 50236370Ssklower ENDDEBUG 50341338Ssklower (*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &source, &target, 50436370Ssklower clnp->cnf_hdr_len); 50536370Ssklower break; 50636370Ssklower 50736370Ssklower case CLNP_EC: 50836370Ssklower IFDEBUG(D_INPUT) 50936370Ssklower printf("clnp_input: echoing packet\n"); 51036370Ssklower ENDDEBUG 51152487Ssklower (void)clnp_echoreply(m, 51252487Ssklower (clnp->cnf_type & CNF_SEG_OK ? (int)seg_part.cng_tot_len : seg_len), 51352487Ssklower &source, &target, oidxp); 51436370Ssklower break; 51536370Ssklower 51636370Ssklower default: 51737469Ssklower printf("clnp_input: unknown clnp pkt type %d\n", 51837469Ssklower clnp->cnf_type & CNF_TYPE); 51939195Ssklower clnp_stat.cns_delivered--; 52039195Ssklower clnp_stat.cns_noproto++; 52136370Ssklower clnp_discard(m, GEN_HDRSYNTAX); 52236370Ssklower break; 52336370Ssklower } 52436370Ssklower } 525*60359Sbostic #endif /* ISO */ 526