136370Ssklower /*********************************************************** 236370Ssklower Copyright IBM Corporation 1987 336370Ssklower 436370Ssklower All Rights Reserved 536370Ssklower 636370Ssklower Permission to use, copy, modify, and distribute this software and its 736370Ssklower documentation for any purpose and without fee is hereby granted, 836370Ssklower provided that the above copyright notice appear in all copies and that 936370Ssklower both that copyright notice and this permission notice appear in 1036370Ssklower supporting documentation, and that the name of IBM not be 1136370Ssklower used in advertising or publicity pertaining to distribution of the 1236370Ssklower software without specific, written prior permission. 1336370Ssklower 1436370Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536370Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636370Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736370Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836370Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936370Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036370Ssklower SOFTWARE. 2136370Ssklower 2236370Ssklower ******************************************************************/ 2336370Ssklower 2436370Ssklower /* 2536370Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636370Ssklower */ 2736766Ssklower /* $Header: /var/src/sys/netiso/RCS/clnp_input.c,v 5.1 89/02/09 16:20:32 hagens Exp $ */ 2836766Ssklower /* $Source: /var/src/sys/netiso/RCS/clnp_input.c,v $ */ 29*43332Ssklower /* @(#)clnp_input.c 7.12 (Berkeley) 06/20/90 */ 3036370Ssklower 3136370Ssklower #ifndef lint 3236766Ssklower static char *rcsid = "$Header: /var/src/sys/netiso/RCS/clnp_input.c,v 5.1 89/02/09 16:20:32 hagens Exp $"; 3336370Ssklower #endif lint 3436370Ssklower 3537536Smckusick #include "types.h" 3637536Smckusick #include "param.h" 3737536Smckusick #include "mbuf.h" 3837536Smckusick #include "domain.h" 3937536Smckusick #include "protosw.h" 4037536Smckusick #include "socket.h" 4137536Smckusick #include "socketvar.h" 4237536Smckusick #include "errno.h" 4337536Smckusick #include "time.h" 4436370Ssklower 4536370Ssklower #include "../net/if.h" 4639195Ssklower #include "../net/if_types.h" 4736370Ssklower #include "../net/route.h" 4836370Ssklower 4937469Ssklower #include "iso.h" 5037469Ssklower #include "iso_var.h" 5137469Ssklower #include "iso_snpac.h" 5237469Ssklower #include "clnp.h" 5337469Ssklower #include "clnl.h" 5438841Ssklower #include "esis.h" 5537469Ssklower #include "../netinet/in_systm.h" 5637469Ssklower #include "../netinet/ip.h" 5738841Ssklower #include "../netinet/if_ether.h" 5837469Ssklower #include "eonvar.h" 5937469Ssklower #include "clnp_stat.h" 6037469Ssklower #include "argo_debug.h" 6136370Ssklower 6236370Ssklower #ifdef ISO 6336370Ssklower u_char clnp_protox[ISOPROTO_MAX]; 6436370Ssklower struct clnl_protosw clnl_protox[256]; 6536370Ssklower int clnpqmaxlen = IFQ_MAXLEN; /* RAH? why is this a variable */ 6636370Ssklower struct mbuf *clnp_data_ck(); 6736370Ssklower 6836370Ssklower int clnp_input(); 6936370Ssklower 7036370Ssklower int esis_input(); 7136370Ssklower 7236370Ssklower #ifdef ISO_X25ESIS 7336370Ssklower int x25esis_input(); 7436370Ssklower #endif ISO_X25ESIS 7536370Ssklower 7636370Ssklower /* 7736370Ssklower * FUNCTION: clnp_init 7836370Ssklower * 7936370Ssklower * PURPOSE: clnp initialization. Fill in clnp switch tables. 8036370Ssklower * 8136370Ssklower * RETURNS: none 8236370Ssklower * 8336370Ssklower * SIDE EFFECTS: fills in clnp_protox table with correct offsets into 8436370Ssklower * the isosw table. 8536370Ssklower * 8636370Ssklower * NOTES: 8736370Ssklower */ 8836370Ssklower clnp_init() 8936370Ssklower { 9036370Ssklower register struct protosw *pr; 9136370Ssklower 9236370Ssklower /* 9336370Ssklower * CLNP protox initialization 9436370Ssklower */ 9536370Ssklower if ((pr = pffindproto(PF_ISO, ISOPROTO_RAW, SOCK_RAW)) == 0) 9636370Ssklower printf("clnl_init: no raw CLNP\n"); 9736370Ssklower else 9836370Ssklower clnp_protox[ISOPROTO_RAW] = pr - isosw; 9936370Ssklower 10036370Ssklower if ((pr = pffindproto(PF_ISO, ISOPROTO_TP, SOCK_SEQPACKET)) == 0) 10136370Ssklower printf("clnl_init: no tp/clnp\n"); 10236370Ssklower else 10336370Ssklower clnp_protox[ISOPROTO_TP] = pr - isosw; 10436370Ssklower 10536370Ssklower /* 10636370Ssklower * CLNL protox initialization 10736370Ssklower */ 10836370Ssklower clnl_protox[ISO8473_CLNP].clnl_input = clnp_input; 10936370Ssklower 11036370Ssklower clnlintrq.ifq_maxlen = clnpqmaxlen; 11136370Ssklower } 11236370Ssklower 11336370Ssklower /* 11436370Ssklower * FUNCTION: clnlintr 11536370Ssklower * 11636370Ssklower * PURPOSE: Process a packet on the clnl input queue 11736370Ssklower * 11836370Ssklower * RETURNS: nothing. 11936370Ssklower * 12036370Ssklower * SIDE EFFECTS: 12136370Ssklower * 12236370Ssklower * NOTES: 12336370Ssklower */ 12436370Ssklower clnlintr() 12536370Ssklower { 12636370Ssklower register struct mbuf *m; /* ptr to first mbuf of pkt */ 12736370Ssklower register struct clnl_fixed *clnl; /* ptr to fixed part of clnl hdr */ 12836370Ssklower int s; /* save and restore priority */ 12936370Ssklower struct clnl_protosw *clnlsw;/* ptr to protocol switch */ 13036370Ssklower struct snpa_hdr sh; /* subnetwork hdr */ 13136370Ssklower 13236370Ssklower /* 13336370Ssklower * Get next datagram off clnl input queue 13436370Ssklower */ 13536370Ssklower next: 13636370Ssklower s = splimp(); 13736765Ssklower /* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/ 13836765Ssklower IF_DEQUEUE(&clnlintrq, m); 13937469Ssklower splx(s); 14036370Ssklower 14136765Ssklower 14236765Ssklower if (m == 0) /* nothing to do */ 14336765Ssklower return; 144*43332Ssklower if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.rcvif == 0) { 14536765Ssklower m_freem(m); 14636765Ssklower goto next; 147*43332Ssklower } else { 148*43332Ssklower register struct ifaddr *ifa; 149*43332Ssklower for (ifa = m->m_pkthdr.rcvif->if_addrlist; ifa; ifa = ifa->ifa_next) 150*43332Ssklower if (ifa->ifa_addr->sa_family == AF_ISO) 151*43332Ssklower break; 152*43332Ssklower if (ifa == 0) { 153*43332Ssklower m_freem(m); 154*43332Ssklower goto next; 155*43332Ssklower } 15636765Ssklower } 15737469Ssklower bzero((caddr_t)&sh, sizeof(sh)); 15837469Ssklower sh.snh_flags = m->m_flags & (M_MCAST|M_BCAST); 15937469Ssklower switch((sh.snh_ifp = m->m_pkthdr.rcvif)->if_type) { 16037469Ssklower extern int ether_output(); 16137469Ssklower case IFT_EON: 16237469Ssklower bcopy(mtod(m, caddr_t), (caddr_t)sh.snh_dhost, sizeof(u_long)); 16337469Ssklower bcopy(sizeof(u_long) + mtod(m, caddr_t), 16437469Ssklower (caddr_t)sh.snh_shost, sizeof(u_long)); 16537469Ssklower sh.snh_dhost[4] = mtod(m, u_char *)[sizeof(struct ip) + 16637469Ssklower _offsetof(struct eon_hdr, eonh_class)]; 16737469Ssklower m->m_data += EONIPLEN; 16837469Ssklower m->m_len -= EONIPLEN; 16937469Ssklower m->m_pkthdr.len -= EONIPLEN; 17037469Ssklower break; 17137469Ssklower 17237469Ssklower default: 17337469Ssklower if (sh.snh_ifp->if_output == ether_output) { 17438841Ssklower bcopy((caddr_t)(mtod(m, struct ether_header *)->ether_dhost), 17537469Ssklower (caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost)); 17638841Ssklower m->m_data += sizeof (struct ether_header); 17738841Ssklower m->m_len -= sizeof (struct ether_header); 17838841Ssklower m->m_pkthdr.len -= sizeof (struct ether_header); 17937469Ssklower } 18037469Ssklower } 18136370Ssklower IFDEBUG(D_INPUT) 18236370Ssklower int i; 18336370Ssklower printf("clnlintr: src:"); 18436370Ssklower for (i=0; i<6; i++) 18536370Ssklower printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' '); 18636370Ssklower printf(" dst:"); 18736370Ssklower for (i=0; i<6; i++) 18836370Ssklower printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' '); 18936370Ssklower printf("\n"); 19036370Ssklower ENDDEBUG 19136370Ssklower 19236370Ssklower /* 19336370Ssklower * Get the fixed part of the clnl header into the first mbuf. 19436370Ssklower * Drop the packet if this fails. 19536370Ssklower * Do not call m_pullup if we have a cluster mbuf or the 19636370Ssklower * data is not there. 19736370Ssklower */ 19836370Ssklower if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) && 19936370Ssklower ((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) { 20036370Ssklower INCSTAT(cns_toosmall); /* TODO: use clnl stats */ 20136370Ssklower goto next; /* m_pullup discards mbuf */ 20236370Ssklower } 20336370Ssklower 20436370Ssklower clnl = mtod(m, struct clnl_fixed *); 20536370Ssklower 20636370Ssklower /* 20736370Ssklower * Drop packet if the length of the header is not reasonable. 20836370Ssklower */ 20936370Ssklower if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) || 21036370Ssklower (clnl->cnf_hdr_len > CLNP_HDR_MAX)) { 21136370Ssklower INCSTAT(cns_badhlen); /* TODO: use clnl stats */ 21236370Ssklower m_freem(m); 21336370Ssklower goto next; 21436370Ssklower } 21536370Ssklower 21636370Ssklower /* 21736370Ssklower * If the header is not contained in this mbuf, make it so. 21836370Ssklower * Drop packet if this fails. 21936370Ssklower * Note: m_pullup will allocate a cluster mbuf if necessary 22036370Ssklower */ 22136370Ssklower if (clnl->cnf_hdr_len > m->m_len) { 22237469Ssklower if ((m = m_pullup(m, (int)clnl->cnf_hdr_len)) == 0) { 22336370Ssklower INCSTAT(cns_badhlen); /* TODO: use clnl stats */ 22436370Ssklower goto next; /* m_pullup discards mbuf */ 22536370Ssklower } 22636370Ssklower clnl = mtod(m, struct clnl_fixed *); 22736370Ssklower } 22836370Ssklower 22936370Ssklower clnlsw = &clnl_protox[clnl->cnf_proto_id]; 23036370Ssklower 23136370Ssklower 23236370Ssklower if (clnlsw->clnl_input) 23336370Ssklower (*clnlsw->clnl_input) (m, &sh); 23436370Ssklower else 23536370Ssklower m_freem(m); 23636370Ssklower 23736370Ssklower goto next; 23836370Ssklower } 23936370Ssklower 24036370Ssklower /* 24136370Ssklower * FUNCTION: clnp_input 24236370Ssklower * 24336370Ssklower * PURPOSE: process an incoming clnp packet 24436370Ssklower * 24536370Ssklower * RETURNS: nothing 24636370Ssklower * 24736370Ssklower * SIDE EFFECTS: increments fields of clnp_stat structure. 24836370Ssklower * 24936370Ssklower * NOTES: 25036370Ssklower * TODO: I would like to make seg_part a pointer into the mbuf, but 25136370Ssklower * will it be correctly aligned? 25236370Ssklower */ 25337469Ssklower clnp_input(m, shp) 25436370Ssklower struct mbuf *m; /* ptr to first mbuf of pkt */ 25536370Ssklower struct snpa_hdr *shp; /* subnetwork header */ 25636370Ssklower { 25736370Ssklower register struct clnp_fixed *clnp; /* ptr to fixed part of header */ 25839930Ssklower struct sockaddr_iso source; /* source address of pkt */ 25939930Ssklower struct sockaddr_iso target; /* destination address of pkt */ 26039930Ssklower #define src source.siso_addr 26139930Ssklower #define dst target.siso_addr 26236370Ssklower caddr_t hoff; /* current offset in packet */ 26336370Ssklower caddr_t hend; /* address of end of header info */ 26436370Ssklower struct clnp_segment seg_part; /* segment part of hdr */ 26536370Ssklower int seg_off=0; /* offset of segment part of hdr */ 26636370Ssklower int seg_len;/* length of packet data&hdr in bytes */ 26736370Ssklower struct clnp_optidx oidx, *oidxp = NULL; /* option index */ 26836370Ssklower extern int iso_systype; /* used by ESIS config resp */ 26939930Ssklower extern struct sockaddr_iso blank_siso; /* used for initializing */ 27036766Ssklower int need_afrin = 0; 27136766Ssklower /* true if congestion experienced */ 27236766Ssklower /* which means you need afrin nose */ 27336766Ssklower /* spray. How clever! */ 27436370Ssklower 27536370Ssklower IFDEBUG(D_INPUT) 27636370Ssklower printf( 27736766Ssklower "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n", 27836766Ssklower m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal"); 27936370Ssklower ENDDEBUG 28036766Ssklower need_afrin = 0; 28136370Ssklower 28236370Ssklower /* 28336370Ssklower * If no iso addresses have been set, there is nothing 28436370Ssklower * to do with the packet. 28536370Ssklower */ 28636370Ssklower if (iso_ifaddr == NULL) { 28736370Ssklower clnp_discard(m, ADDR_DESTUNREACH); 28836370Ssklower return; 28936370Ssklower } 29036370Ssklower 29136370Ssklower INCSTAT(cns_total); 29236370Ssklower clnp = mtod(m, struct clnp_fixed *); 29336370Ssklower 29436766Ssklower IFDEBUG(D_DUMPIN) 29536766Ssklower struct mbuf *mhead; 29636766Ssklower int total_len = 0; 29736766Ssklower printf("clnp_input: clnp header:\n"); 29836766Ssklower dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len); 29936766Ssklower printf("clnp_input: mbuf chain:\n"); 30036766Ssklower for (mhead = m; mhead != NULL; mhead=mhead->m_next) { 30136766Ssklower printf("m x%x, len %d\n", mhead, mhead->m_len); 30236766Ssklower total_len += mhead->m_len; 30336766Ssklower } 30436766Ssklower printf("clnp_input: total length of mbuf chain %d:\n", total_len); 30536766Ssklower ENDDEBUG 30636766Ssklower 30736370Ssklower /* 30836370Ssklower * Compute checksum (if necessary) and drop packet if 30936370Ssklower * checksum does not match 31036370Ssklower */ 31137469Ssklower if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, (int)clnp->cnf_hdr_len)) { 31236370Ssklower INCSTAT(cns_badcsum); 31336370Ssklower clnp_discard(m, GEN_BADCSUM); 31437469Ssklower return; 31536370Ssklower } 31636370Ssklower 31736370Ssklower if (clnp->cnf_vers != ISO8473_V1) { 31836370Ssklower INCSTAT(cns_badvers); 31936370Ssklower clnp_discard(m, DISC_UNSUPPVERS); 32037469Ssklower return; 32136370Ssklower } 32236370Ssklower 32336370Ssklower 32436370Ssklower /* check mbuf data length: clnp_data_ck will free mbuf upon error */ 32536370Ssklower CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len); 32636370Ssklower if ((m = clnp_data_ck(m, seg_len)) == 0) 32737469Ssklower return; 32836370Ssklower 32936370Ssklower clnp = mtod(m, struct clnp_fixed *); 33036370Ssklower hend = (caddr_t)clnp + clnp->cnf_hdr_len; 33136370Ssklower 33236370Ssklower /* 33336370Ssklower * extract the source and destination address 33436370Ssklower * drop packet on failure 33536370Ssklower */ 33639930Ssklower source = target = blank_siso; 33736370Ssklower 33836370Ssklower hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); 33936370Ssklower CLNP_EXTRACT_ADDR(dst, hoff, hend); 34036370Ssklower if (hoff == (caddr_t)0) { 34136370Ssklower INCSTAT(cns_badaddr); 34236370Ssklower clnp_discard(m, GEN_INCOMPLETE); 34337469Ssklower return; 34436370Ssklower } 34536370Ssklower CLNP_EXTRACT_ADDR(src, hoff, hend); 34636370Ssklower if (hoff == (caddr_t)0) { 34736370Ssklower INCSTAT(cns_badaddr); 34836370Ssklower clnp_discard(m, GEN_INCOMPLETE); 34937469Ssklower return; 35036370Ssklower } 35136370Ssklower 35236370Ssklower IFDEBUG(D_INPUT) 35336370Ssklower printf("clnp_input: from %s", clnp_iso_addrp(&src)); 35436370Ssklower printf(" to %s\n", clnp_iso_addrp(&dst)); 35536370Ssklower ENDDEBUG 35636370Ssklower 35736370Ssklower /* 35836370Ssklower * extract the segmentation information, if it is present. 35936370Ssklower * drop packet on failure 36036370Ssklower */ 36137469Ssklower if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && 36237469Ssklower (clnp->cnf_type & CNF_SEG_OK)) { 36336370Ssklower if (hoff + sizeof(struct clnp_segment) > hend) { 36436370Ssklower INCSTAT(cns_noseg); 36536370Ssklower clnp_discard(m, GEN_INCOMPLETE); 36637469Ssklower return; 36736370Ssklower } else { 36836370Ssklower (void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment)); 36936370Ssklower /* make sure segmentation fields are in host order */ 37036370Ssklower seg_part.cng_id = ntohs(seg_part.cng_id); 37136370Ssklower seg_part.cng_off = ntohs(seg_part.cng_off); 37236370Ssklower seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len); 37336370Ssklower seg_off = hoff - (caddr_t)clnp; 37436370Ssklower hoff += sizeof(struct clnp_segment); 37536370Ssklower } 37636370Ssklower } 37736370Ssklower 37836370Ssklower /* 37936370Ssklower * process options if present. If clnp_opt_sanity returns 38036370Ssklower * false (indicating an error was found in the options) or 38136370Ssklower * an unsupported option was found 38236370Ssklower * then drop packet and emit an ER. 38336370Ssklower */ 38436370Ssklower if (hoff < hend) { 38536370Ssklower int errcode; 38636370Ssklower 38736370Ssklower oidxp = &oidx; 38836370Ssklower errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp); 38936370Ssklower 39036370Ssklower /* we do not support security */ 39136370Ssklower if ((errcode == 0) && (oidxp->cni_securep)) 39236370Ssklower errcode = DISC_UNSUPPSECURE; 39336370Ssklower 39436370Ssklower /* the er option is valid with ER pdus only */ 39536370Ssklower if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) && 39637469Ssklower ((clnp->cnf_type & CNF_TYPE) != CLNP_ER)) 39736370Ssklower errcode = DISC_UNSUPPOPT; 39836370Ssklower 39936766Ssklower #ifdef DECBIT 40036766Ssklower /* check if the congestion experienced bit is set */ 40136766Ssklower if (oidxp->cni_qos_formatp) { 40236766Ssklower caddr_t qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp); 40336766Ssklower u_char qos = *qosp; 40436766Ssklower 40536766Ssklower need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) == 40636766Ssklower (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)); 40736766Ssklower if (need_afrin) 40836766Ssklower INCSTAT(cns_congest_rcvd); 40936766Ssklower } 41036766Ssklower #endif DECBIT 41136766Ssklower 41236370Ssklower if (errcode != 0) { 41336370Ssklower clnp_discard(m, (char)errcode); 41436370Ssklower IFDEBUG(D_INPUT) 41536370Ssklower printf("clnp_input: dropped (err x%x) due to bad options\n", 41636370Ssklower errcode); 41736370Ssklower ENDDEBUG 41837469Ssklower return; 41936370Ssklower } 42036370Ssklower } 42136370Ssklower 42236370Ssklower /* 42336370Ssklower * check if this packet is for us. if not, then forward 42436370Ssklower */ 42536370Ssklower if (clnp_ours(&dst) == 0) { 42636370Ssklower IFDEBUG(D_INPUT) 42736370Ssklower printf("clnp_input: forwarding packet not for us\n"); 42836370Ssklower ENDDEBUG 42936370Ssklower clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp); 43037469Ssklower return; 43136370Ssklower } 43236370Ssklower 43336370Ssklower /* 43436370Ssklower * ESIS Configuration Response Function 43536370Ssklower * 43636370Ssklower * If the packet received was sent to the multicast address 43736370Ssklower * all end systems, then send an esh to the source 43836370Ssklower */ 43937469Ssklower if ((shp->snh_flags & M_MCAST) && (iso_systype == SNPA_ES)) { 44036370Ssklower extern short esis_holding_time; 44136370Ssklower 44236370Ssklower esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time, 443*43332Ssklower shp->snh_shost, 6, &dst); 44436370Ssklower } 44536370Ssklower 44636370Ssklower /* 44736370Ssklower * If this is a fragment, then try to reassemble it. If clnp_reass 44836370Ssklower * returns non NULL, the packet has been reassembled, and should 44936370Ssklower * be give to TP. Otherwise the fragment has been delt with 45036370Ssklower * by the reassembly code (either stored or deleted). In either case 45136370Ssklower * we should have nothing more to do with it. 45236370Ssklower */ 45337469Ssklower if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && 45437469Ssklower (clnp->cnf_type & CNF_SEG_OK) && 45536370Ssklower (seg_len != seg_part.cng_tot_len)) { 45636370Ssklower struct mbuf *m0; 45736370Ssklower 45836370Ssklower if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) { 45936370Ssklower m = m0; 46036370Ssklower clnp = mtod(m, struct clnp_fixed *); 46139195Ssklower INCSTAT(cns_reassembled); 46236370Ssklower } else { 46337469Ssklower return; 46436370Ssklower } 46536370Ssklower } 46636370Ssklower 46736370Ssklower /* 46836370Ssklower * give the packet to the higher layer 46936370Ssklower * 47036370Ssklower * Note: the total length of packet 47136370Ssklower * is the total length field of the segmentation part, 47236370Ssklower * or, if absent, the segment length field of the 47336370Ssklower * header. 47436370Ssklower */ 47539195Ssklower INCSTAT(cns_delivered); 47637469Ssklower switch (clnp->cnf_type & CNF_TYPE) { 47736370Ssklower case CLNP_ER: 47836370Ssklower /* 47936370Ssklower * This ER must have the er option. 48036370Ssklower * If the option is not present, discard datagram. 48136370Ssklower */ 48236370Ssklower if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) { 48336370Ssklower clnp_discard(m, GEN_HDRSYNTAX); 48436370Ssklower } else { 48536370Ssklower clnp_er_input(m, &src, oidxp->cni_er_reason); 48636370Ssklower } 48736370Ssklower break; 48836370Ssklower 48936370Ssklower case CLNP_DT: 49039930Ssklower (*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &source, &target, 49139931Ssklower clnp->cnf_hdr_len, need_afrin); 49236370Ssklower break; 49336370Ssklower 49436370Ssklower case CLNP_RAW: 49536370Ssklower case CLNP_ECR: 49636370Ssklower IFDEBUG(D_INPUT) 49736370Ssklower printf("clnp_input: raw input of %d bytes\n", 49837469Ssklower clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len); 49936370Ssklower ENDDEBUG 50041338Ssklower (*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &source, &target, 50136370Ssklower clnp->cnf_hdr_len); 50236370Ssklower break; 50336370Ssklower 50436370Ssklower case CLNP_EC: 50536370Ssklower IFDEBUG(D_INPUT) 50636370Ssklower printf("clnp_input: echoing packet\n"); 50736370Ssklower ENDDEBUG 50836370Ssklower /* 50936370Ssklower * Switch the source and destination address, 51036370Ssklower */ 51136370Ssklower hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); 51237469Ssklower CLNP_INSERT_ADDR(hoff, src); 51337469Ssklower CLNP_INSERT_ADDR(hoff, dst); 51437469Ssklower clnp->cnf_type &= ~CNF_TYPE; 51537469Ssklower clnp->cnf_type |= CLNP_ECR; 51636370Ssklower 51736370Ssklower /* 51836370Ssklower * Forward back to sender 51936370Ssklower */ 52039232Ssklower clnp_forward(m, (int) 52139232Ssklower (clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len), 52239232Ssklower &src, oidxp, seg_off, 0); 52336370Ssklower break; 52436370Ssklower 52536370Ssklower default: 52637469Ssklower printf("clnp_input: unknown clnp pkt type %d\n", 52737469Ssklower clnp->cnf_type & CNF_TYPE); 52839195Ssklower clnp_stat.cns_delivered--; 52939195Ssklower clnp_stat.cns_noproto++; 53036370Ssklower clnp_discard(m, GEN_HDRSYNTAX); 53136370Ssklower break; 53236370Ssklower } 53336370Ssklower } 53436370Ssklower #endif ISO 535