149267Sbostic /*- 249267Sbostic * Copyright (c) 1991 The Regents of the University of California. 349267Sbostic * All rights reserved. 449267Sbostic * 549267Sbostic * %sccs.include.redist.c% 649267Sbostic * 7*52487Ssklower * @(#)clnp_input.c 7.14 (Berkeley) 02/14/92 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 3937536Smckusick #include "types.h" 4037536Smckusick #include "param.h" 4137536Smckusick #include "mbuf.h" 4237536Smckusick #include "domain.h" 4337536Smckusick #include "protosw.h" 4437536Smckusick #include "socket.h" 4537536Smckusick #include "socketvar.h" 4637536Smckusick #include "errno.h" 4737536Smckusick #include "time.h" 4836370Ssklower 4936370Ssklower #include "../net/if.h" 5039195Ssklower #include "../net/if_types.h" 5136370Ssklower #include "../net/route.h" 5236370Ssklower 5337469Ssklower #include "iso.h" 5437469Ssklower #include "iso_var.h" 5537469Ssklower #include "iso_snpac.h" 5637469Ssklower #include "clnp.h" 5737469Ssklower #include "clnl.h" 5838841Ssklower #include "esis.h" 5937469Ssklower #include "../netinet/in_systm.h" 6037469Ssklower #include "../netinet/ip.h" 6138841Ssklower #include "../netinet/if_ether.h" 6237469Ssklower #include "eonvar.h" 6337469Ssklower #include "clnp_stat.h" 6437469Ssklower #include "argo_debug.h" 6536370Ssklower 6636370Ssklower #ifdef ISO 6736370Ssklower u_char clnp_protox[ISOPROTO_MAX]; 6836370Ssklower struct clnl_protosw clnl_protox[256]; 6936370Ssklower int clnpqmaxlen = IFQ_MAXLEN; /* RAH? why is this a variable */ 7036370Ssklower struct mbuf *clnp_data_ck(); 7136370Ssklower 7236370Ssklower int clnp_input(); 7336370Ssklower 7436370Ssklower int esis_input(); 7536370Ssklower 7636370Ssklower #ifdef ISO_X25ESIS 7736370Ssklower int x25esis_input(); 7836370Ssklower #endif ISO_X25ESIS 7936370Ssklower 8036370Ssklower /* 8136370Ssklower * FUNCTION: clnp_init 8236370Ssklower * 8336370Ssklower * PURPOSE: clnp initialization. Fill in clnp switch tables. 8436370Ssklower * 8536370Ssklower * RETURNS: none 8636370Ssklower * 8736370Ssklower * SIDE EFFECTS: fills in clnp_protox table with correct offsets into 8836370Ssklower * the isosw table. 8936370Ssklower * 9036370Ssklower * NOTES: 9136370Ssklower */ 9236370Ssklower clnp_init() 9336370Ssklower { 9436370Ssklower register struct protosw *pr; 9536370Ssklower 9636370Ssklower /* 9736370Ssklower * CLNP protox initialization 9836370Ssklower */ 9936370Ssklower if ((pr = pffindproto(PF_ISO, ISOPROTO_RAW, SOCK_RAW)) == 0) 10036370Ssklower printf("clnl_init: no raw CLNP\n"); 10136370Ssklower else 10236370Ssklower clnp_protox[ISOPROTO_RAW] = pr - isosw; 10336370Ssklower 10436370Ssklower if ((pr = pffindproto(PF_ISO, ISOPROTO_TP, SOCK_SEQPACKET)) == 0) 10536370Ssklower printf("clnl_init: no tp/clnp\n"); 10636370Ssklower else 10736370Ssklower clnp_protox[ISOPROTO_TP] = pr - isosw; 10836370Ssklower 10936370Ssklower /* 11036370Ssklower * CLNL protox initialization 11136370Ssklower */ 11236370Ssklower clnl_protox[ISO8473_CLNP].clnl_input = clnp_input; 11336370Ssklower 11436370Ssklower clnlintrq.ifq_maxlen = clnpqmaxlen; 11536370Ssklower } 11636370Ssklower 11736370Ssklower /* 11836370Ssklower * FUNCTION: clnlintr 11936370Ssklower * 12036370Ssklower * PURPOSE: Process a packet on the clnl input queue 12136370Ssklower * 12236370Ssklower * RETURNS: nothing. 12336370Ssklower * 12436370Ssklower * SIDE EFFECTS: 12536370Ssklower * 12636370Ssklower * NOTES: 12736370Ssklower */ 12836370Ssklower clnlintr() 12936370Ssklower { 13036370Ssklower register struct mbuf *m; /* ptr to first mbuf of pkt */ 13136370Ssklower register struct clnl_fixed *clnl; /* ptr to fixed part of clnl hdr */ 13236370Ssklower int s; /* save and restore priority */ 13336370Ssklower struct clnl_protosw *clnlsw;/* ptr to protocol switch */ 13436370Ssklower struct snpa_hdr sh; /* subnetwork hdr */ 13536370Ssklower 13636370Ssklower /* 13736370Ssklower * Get next datagram off clnl input queue 13836370Ssklower */ 13936370Ssklower next: 14036370Ssklower s = splimp(); 14136765Ssklower /* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/ 14236765Ssklower IF_DEQUEUE(&clnlintrq, m); 14337469Ssklower splx(s); 14436370Ssklower 14536765Ssklower 14636765Ssklower if (m == 0) /* nothing to do */ 14736765Ssklower return; 14843332Ssklower if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.rcvif == 0) { 14936765Ssklower m_freem(m); 15036765Ssklower goto next; 15143332Ssklower } else { 15243332Ssklower register struct ifaddr *ifa; 15343332Ssklower for (ifa = m->m_pkthdr.rcvif->if_addrlist; ifa; ifa = ifa->ifa_next) 15443332Ssklower if (ifa->ifa_addr->sa_family == AF_ISO) 15543332Ssklower break; 15643332Ssklower if (ifa == 0) { 15743332Ssklower m_freem(m); 15843332Ssklower goto next; 15943332Ssklower } 16036765Ssklower } 16137469Ssklower bzero((caddr_t)&sh, sizeof(sh)); 16237469Ssklower sh.snh_flags = m->m_flags & (M_MCAST|M_BCAST); 16337469Ssklower switch((sh.snh_ifp = m->m_pkthdr.rcvif)->if_type) { 16437469Ssklower extern int ether_output(); 16537469Ssklower case IFT_EON: 16637469Ssklower bcopy(mtod(m, caddr_t), (caddr_t)sh.snh_dhost, sizeof(u_long)); 16737469Ssklower bcopy(sizeof(u_long) + mtod(m, caddr_t), 16837469Ssklower (caddr_t)sh.snh_shost, sizeof(u_long)); 16937469Ssklower sh.snh_dhost[4] = mtod(m, u_char *)[sizeof(struct ip) + 17037469Ssklower _offsetof(struct eon_hdr, eonh_class)]; 17137469Ssklower m->m_data += EONIPLEN; 17237469Ssklower m->m_len -= EONIPLEN; 17337469Ssklower m->m_pkthdr.len -= EONIPLEN; 17437469Ssklower break; 17537469Ssklower 17637469Ssklower default: 17737469Ssklower if (sh.snh_ifp->if_output == ether_output) { 17838841Ssklower bcopy((caddr_t)(mtod(m, struct ether_header *)->ether_dhost), 17937469Ssklower (caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost)); 18038841Ssklower m->m_data += sizeof (struct ether_header); 18138841Ssklower m->m_len -= sizeof (struct ether_header); 18238841Ssklower m->m_pkthdr.len -= sizeof (struct ether_header); 18337469Ssklower } 18437469Ssklower } 18536370Ssklower IFDEBUG(D_INPUT) 18636370Ssklower int i; 18736370Ssklower printf("clnlintr: src:"); 18836370Ssklower for (i=0; i<6; i++) 18936370Ssklower printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' '); 19036370Ssklower printf(" dst:"); 19136370Ssklower for (i=0; i<6; i++) 19236370Ssklower printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' '); 19336370Ssklower printf("\n"); 19436370Ssklower ENDDEBUG 19536370Ssklower 19636370Ssklower /* 19736370Ssklower * Get the fixed part of the clnl header into the first mbuf. 19836370Ssklower * Drop the packet if this fails. 19936370Ssklower * Do not call m_pullup if we have a cluster mbuf or the 20036370Ssklower * data is not there. 20136370Ssklower */ 20236370Ssklower if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) && 20336370Ssklower ((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) { 20436370Ssklower INCSTAT(cns_toosmall); /* TODO: use clnl stats */ 20536370Ssklower goto next; /* m_pullup discards mbuf */ 20636370Ssklower } 20736370Ssklower 20836370Ssklower clnl = mtod(m, struct clnl_fixed *); 20936370Ssklower 21036370Ssklower /* 21136370Ssklower * Drop packet if the length of the header is not reasonable. 21236370Ssklower */ 21336370Ssklower if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) || 21436370Ssklower (clnl->cnf_hdr_len > CLNP_HDR_MAX)) { 21536370Ssklower INCSTAT(cns_badhlen); /* TODO: use clnl stats */ 21636370Ssklower m_freem(m); 21736370Ssklower goto next; 21836370Ssklower } 21936370Ssklower 22036370Ssklower /* 22136370Ssklower * If the header is not contained in this mbuf, make it so. 22236370Ssklower * Drop packet if this fails. 22336370Ssklower * Note: m_pullup will allocate a cluster mbuf if necessary 22436370Ssklower */ 22536370Ssklower if (clnl->cnf_hdr_len > m->m_len) { 22637469Ssklower if ((m = m_pullup(m, (int)clnl->cnf_hdr_len)) == 0) { 22736370Ssklower INCSTAT(cns_badhlen); /* TODO: use clnl stats */ 22836370Ssklower goto next; /* m_pullup discards mbuf */ 22936370Ssklower } 23036370Ssklower clnl = mtod(m, struct clnl_fixed *); 23136370Ssklower } 23236370Ssklower 23336370Ssklower clnlsw = &clnl_protox[clnl->cnf_proto_id]; 23436370Ssklower 23536370Ssklower 23636370Ssklower if (clnlsw->clnl_input) 23736370Ssklower (*clnlsw->clnl_input) (m, &sh); 23836370Ssklower else 23936370Ssklower m_freem(m); 24036370Ssklower 24136370Ssklower goto next; 24236370Ssklower } 24336370Ssklower 24436370Ssklower /* 24536370Ssklower * FUNCTION: clnp_input 24636370Ssklower * 24736370Ssklower * PURPOSE: process an incoming clnp packet 24836370Ssklower * 24936370Ssklower * RETURNS: nothing 25036370Ssklower * 25136370Ssklower * SIDE EFFECTS: increments fields of clnp_stat structure. 25236370Ssklower * 25336370Ssklower * NOTES: 25436370Ssklower * TODO: I would like to make seg_part a pointer into the mbuf, but 25536370Ssklower * will it be correctly aligned? 25636370Ssklower */ 25737469Ssklower clnp_input(m, shp) 25836370Ssklower struct mbuf *m; /* ptr to first mbuf of pkt */ 25936370Ssklower struct snpa_hdr *shp; /* subnetwork header */ 26036370Ssklower { 26136370Ssklower register struct clnp_fixed *clnp; /* ptr to fixed part of header */ 26239930Ssklower struct sockaddr_iso source; /* source address of pkt */ 26339930Ssklower struct sockaddr_iso target; /* destination address of pkt */ 26439930Ssklower #define src source.siso_addr 26539930Ssklower #define dst target.siso_addr 26636370Ssklower caddr_t hoff; /* current offset in packet */ 26736370Ssklower caddr_t hend; /* address of end of header info */ 26836370Ssklower struct clnp_segment seg_part; /* segment part of hdr */ 26936370Ssklower int seg_off=0; /* offset of segment part of hdr */ 27036370Ssklower int seg_len;/* length of packet data&hdr in bytes */ 27136370Ssklower struct clnp_optidx oidx, *oidxp = NULL; /* option index */ 27236370Ssklower extern int iso_systype; /* used by ESIS config resp */ 27339930Ssklower extern struct sockaddr_iso blank_siso; /* used for initializing */ 27436766Ssklower int need_afrin = 0; 27536766Ssklower /* true if congestion experienced */ 27636766Ssklower /* which means you need afrin nose */ 27736766Ssklower /* spray. How clever! */ 27836370Ssklower 27936370Ssklower IFDEBUG(D_INPUT) 28036370Ssklower printf( 28136766Ssklower "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n", 28236766Ssklower m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal"); 28336370Ssklower ENDDEBUG 28436766Ssklower need_afrin = 0; 28536370Ssklower 28636370Ssklower /* 28736370Ssklower * If no iso addresses have been set, there is nothing 28836370Ssklower * to do with the packet. 28936370Ssklower */ 29036370Ssklower if (iso_ifaddr == NULL) { 29136370Ssklower clnp_discard(m, ADDR_DESTUNREACH); 29236370Ssklower return; 29336370Ssklower } 29436370Ssklower 29536370Ssklower INCSTAT(cns_total); 29636370Ssklower clnp = mtod(m, struct clnp_fixed *); 29736370Ssklower 29836766Ssklower IFDEBUG(D_DUMPIN) 29936766Ssklower struct mbuf *mhead; 30036766Ssklower int total_len = 0; 30136766Ssklower printf("clnp_input: clnp header:\n"); 30236766Ssklower dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len); 30336766Ssklower printf("clnp_input: mbuf chain:\n"); 30436766Ssklower for (mhead = m; mhead != NULL; mhead=mhead->m_next) { 30536766Ssklower printf("m x%x, len %d\n", mhead, mhead->m_len); 30636766Ssklower total_len += mhead->m_len; 30736766Ssklower } 30836766Ssklower printf("clnp_input: total length of mbuf chain %d:\n", total_len); 30936766Ssklower ENDDEBUG 31036766Ssklower 31136370Ssklower /* 31236370Ssklower * Compute checksum (if necessary) and drop packet if 31336370Ssklower * checksum does not match 31436370Ssklower */ 31537469Ssklower if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, (int)clnp->cnf_hdr_len)) { 31636370Ssklower INCSTAT(cns_badcsum); 31736370Ssklower clnp_discard(m, GEN_BADCSUM); 31837469Ssklower return; 31936370Ssklower } 32036370Ssklower 32136370Ssklower if (clnp->cnf_vers != ISO8473_V1) { 32236370Ssklower INCSTAT(cns_badvers); 32336370Ssklower clnp_discard(m, DISC_UNSUPPVERS); 32437469Ssklower return; 32536370Ssklower } 32636370Ssklower 32736370Ssklower 32836370Ssklower /* check mbuf data length: clnp_data_ck will free mbuf upon error */ 32936370Ssklower CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len); 33036370Ssklower if ((m = clnp_data_ck(m, seg_len)) == 0) 33137469Ssklower return; 33236370Ssklower 33336370Ssklower clnp = mtod(m, struct clnp_fixed *); 33436370Ssklower hend = (caddr_t)clnp + clnp->cnf_hdr_len; 33536370Ssklower 33636370Ssklower /* 33736370Ssklower * extract the source and destination address 33836370Ssklower * drop packet on failure 33936370Ssklower */ 34039930Ssklower source = target = blank_siso; 34136370Ssklower 34236370Ssklower hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); 34336370Ssklower CLNP_EXTRACT_ADDR(dst, hoff, hend); 34436370Ssklower if (hoff == (caddr_t)0) { 34536370Ssklower INCSTAT(cns_badaddr); 34636370Ssklower clnp_discard(m, GEN_INCOMPLETE); 34737469Ssklower return; 34836370Ssklower } 34936370Ssklower CLNP_EXTRACT_ADDR(src, hoff, hend); 35036370Ssklower if (hoff == (caddr_t)0) { 35136370Ssklower INCSTAT(cns_badaddr); 35236370Ssklower clnp_discard(m, GEN_INCOMPLETE); 35337469Ssklower return; 35436370Ssklower } 35536370Ssklower 35636370Ssklower IFDEBUG(D_INPUT) 35736370Ssklower printf("clnp_input: from %s", clnp_iso_addrp(&src)); 35836370Ssklower printf(" to %s\n", clnp_iso_addrp(&dst)); 35936370Ssklower ENDDEBUG 36036370Ssklower 36136370Ssklower /* 36236370Ssklower * extract the segmentation information, if it is present. 36336370Ssklower * drop packet on failure 36436370Ssklower */ 36537469Ssklower if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && 36637469Ssklower (clnp->cnf_type & CNF_SEG_OK)) { 36736370Ssklower if (hoff + sizeof(struct clnp_segment) > hend) { 36836370Ssklower INCSTAT(cns_noseg); 36936370Ssklower clnp_discard(m, GEN_INCOMPLETE); 37037469Ssklower return; 37136370Ssklower } else { 37236370Ssklower (void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment)); 37336370Ssklower /* make sure segmentation fields are in host order */ 37436370Ssklower seg_part.cng_id = ntohs(seg_part.cng_id); 37536370Ssklower seg_part.cng_off = ntohs(seg_part.cng_off); 37636370Ssklower seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len); 37736370Ssklower seg_off = hoff - (caddr_t)clnp; 37836370Ssklower hoff += sizeof(struct clnp_segment); 37936370Ssklower } 38036370Ssklower } 38136370Ssklower 38236370Ssklower /* 38336370Ssklower * process options if present. If clnp_opt_sanity returns 38436370Ssklower * false (indicating an error was found in the options) or 38536370Ssklower * an unsupported option was found 38636370Ssklower * then drop packet and emit an ER. 38736370Ssklower */ 38836370Ssklower if (hoff < hend) { 38936370Ssklower int errcode; 39036370Ssklower 39136370Ssklower oidxp = &oidx; 39236370Ssklower errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp); 39336370Ssklower 39436370Ssklower /* we do not support security */ 39536370Ssklower if ((errcode == 0) && (oidxp->cni_securep)) 39636370Ssklower errcode = DISC_UNSUPPSECURE; 39736370Ssklower 39836370Ssklower /* the er option is valid with ER pdus only */ 39936370Ssklower if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) && 40037469Ssklower ((clnp->cnf_type & CNF_TYPE) != CLNP_ER)) 40136370Ssklower errcode = DISC_UNSUPPOPT; 40236370Ssklower 40336766Ssklower #ifdef DECBIT 40436766Ssklower /* check if the congestion experienced bit is set */ 40536766Ssklower if (oidxp->cni_qos_formatp) { 40636766Ssklower caddr_t qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp); 40736766Ssklower u_char qos = *qosp; 40836766Ssklower 40936766Ssklower need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) == 41036766Ssklower (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)); 41136766Ssklower if (need_afrin) 41236766Ssklower INCSTAT(cns_congest_rcvd); 41336766Ssklower } 41436766Ssklower #endif DECBIT 41536766Ssklower 41636370Ssklower if (errcode != 0) { 41736370Ssklower clnp_discard(m, (char)errcode); 41836370Ssklower IFDEBUG(D_INPUT) 41936370Ssklower printf("clnp_input: dropped (err x%x) due to bad options\n", 42036370Ssklower errcode); 42136370Ssklower ENDDEBUG 42237469Ssklower return; 42336370Ssklower } 42436370Ssklower } 42536370Ssklower 42636370Ssklower /* 42736370Ssklower * check if this packet is for us. if not, then forward 42836370Ssklower */ 42936370Ssklower if (clnp_ours(&dst) == 0) { 43036370Ssklower IFDEBUG(D_INPUT) 43136370Ssklower printf("clnp_input: forwarding packet not for us\n"); 43236370Ssklower ENDDEBUG 43336370Ssklower clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp); 43437469Ssklower return; 43536370Ssklower } 43636370Ssklower 43736370Ssklower /* 43836370Ssklower * ESIS Configuration Response Function 43936370Ssklower * 44036370Ssklower * If the packet received was sent to the multicast address 44136370Ssklower * all end systems, then send an esh to the source 44236370Ssklower */ 44337469Ssklower if ((shp->snh_flags & M_MCAST) && (iso_systype == SNPA_ES)) { 44436370Ssklower extern short esis_holding_time; 44536370Ssklower 44636370Ssklower esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time, 44743332Ssklower shp->snh_shost, 6, &dst); 44836370Ssklower } 44936370Ssklower 45036370Ssklower /* 45136370Ssklower * If this is a fragment, then try to reassemble it. If clnp_reass 45236370Ssklower * returns non NULL, the packet has been reassembled, and should 45336370Ssklower * be give to TP. Otherwise the fragment has been delt with 45436370Ssklower * by the reassembly code (either stored or deleted). In either case 45536370Ssklower * we should have nothing more to do with it. 45636370Ssklower */ 45737469Ssklower if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && 45837469Ssklower (clnp->cnf_type & CNF_SEG_OK) && 45936370Ssklower (seg_len != seg_part.cng_tot_len)) { 46036370Ssklower struct mbuf *m0; 46136370Ssklower 46236370Ssklower if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) { 46336370Ssklower m = m0; 46436370Ssklower clnp = mtod(m, struct clnp_fixed *); 46539195Ssklower INCSTAT(cns_reassembled); 46636370Ssklower } else { 46737469Ssklower return; 46836370Ssklower } 46936370Ssklower } 47036370Ssklower 47136370Ssklower /* 47236370Ssklower * give the packet to the higher layer 47336370Ssklower * 47436370Ssklower * Note: the total length of packet 47536370Ssklower * is the total length field of the segmentation part, 47636370Ssklower * or, if absent, the segment length field of the 47736370Ssklower * header. 47836370Ssklower */ 47939195Ssklower INCSTAT(cns_delivered); 48037469Ssklower switch (clnp->cnf_type & CNF_TYPE) { 48136370Ssklower case CLNP_ER: 48236370Ssklower /* 48336370Ssklower * This ER must have the er option. 48436370Ssklower * If the option is not present, discard datagram. 48536370Ssklower */ 48636370Ssklower if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) { 48736370Ssklower clnp_discard(m, GEN_HDRSYNTAX); 48836370Ssklower } else { 48936370Ssklower clnp_er_input(m, &src, oidxp->cni_er_reason); 49036370Ssklower } 49136370Ssklower break; 49236370Ssklower 49336370Ssklower case CLNP_DT: 49439930Ssklower (*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &source, &target, 49539931Ssklower clnp->cnf_hdr_len, need_afrin); 49636370Ssklower break; 49736370Ssklower 49836370Ssklower case CLNP_RAW: 49936370Ssklower case CLNP_ECR: 50036370Ssklower IFDEBUG(D_INPUT) 50136370Ssklower printf("clnp_input: raw input of %d bytes\n", 50237469Ssklower clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len); 50336370Ssklower ENDDEBUG 50441338Ssklower (*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &source, &target, 50536370Ssklower clnp->cnf_hdr_len); 50636370Ssklower break; 50736370Ssklower 50836370Ssklower case CLNP_EC: 50936370Ssklower IFDEBUG(D_INPUT) 51036370Ssklower printf("clnp_input: echoing packet\n"); 51136370Ssklower ENDDEBUG 512*52487Ssklower (void)clnp_echoreply(m, 513*52487Ssklower (clnp->cnf_type & CNF_SEG_OK ? (int)seg_part.cng_tot_len : seg_len), 514*52487Ssklower &source, &target, oidxp); 51536370Ssklower break; 51636370Ssklower 51736370Ssklower default: 51837469Ssklower printf("clnp_input: unknown clnp pkt type %d\n", 51937469Ssklower clnp->cnf_type & CNF_TYPE); 52039195Ssklower clnp_stat.cns_delivered--; 52139195Ssklower clnp_stat.cns_noproto++; 52236370Ssklower clnp_discard(m, GEN_HDRSYNTAX); 52336370Ssklower break; 52436370Ssklower } 52536370Ssklower } 52636370Ssklower #endif ISO 527