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*38841Ssklower /* @(#)clnp_input.c 7.6 (Berkeley) 08/29/89 */ 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" 4637469Ssklower #include "../net/iftypes.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" 54*38841Ssklower #include "esis.h" 5537469Ssklower #include "../netinet/in_systm.h" 5637469Ssklower #include "../netinet/ip.h" 57*38841Ssklower #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; 14437469Ssklower if ((m->m_flags & M_PKTHDR) == 0) { 14536765Ssklower m_freem(m); 14636765Ssklower goto next; 14736765Ssklower } 14837469Ssklower bzero((caddr_t)&sh, sizeof(sh)); 14937469Ssklower sh.snh_flags = m->m_flags & (M_MCAST|M_BCAST); 15037469Ssklower switch((sh.snh_ifp = m->m_pkthdr.rcvif)->if_type) { 15137469Ssklower extern int ether_output(); 15237469Ssklower case IFT_EON: 15337469Ssklower bcopy(mtod(m, caddr_t), (caddr_t)sh.snh_dhost, sizeof(u_long)); 15437469Ssklower bcopy(sizeof(u_long) + mtod(m, caddr_t), 15537469Ssklower (caddr_t)sh.snh_shost, sizeof(u_long)); 15637469Ssklower sh.snh_dhost[4] = mtod(m, u_char *)[sizeof(struct ip) + 15737469Ssklower _offsetof(struct eon_hdr, eonh_class)]; 15837469Ssklower m->m_data += EONIPLEN; 15937469Ssklower m->m_len -= EONIPLEN; 16037469Ssklower m->m_pkthdr.len -= EONIPLEN; 16137469Ssklower break; 16237469Ssklower 16337469Ssklower default: 16437469Ssklower if (sh.snh_ifp->if_output == ether_output) { 165*38841Ssklower bcopy((caddr_t)(mtod(m, struct ether_header *)->ether_dhost), 16637469Ssklower (caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost)); 167*38841Ssklower m->m_data += sizeof (struct ether_header); 168*38841Ssklower m->m_len -= sizeof (struct ether_header); 169*38841Ssklower m->m_pkthdr.len -= sizeof (struct ether_header); 17037469Ssklower } 17137469Ssklower } 17236370Ssklower IFDEBUG(D_INPUT) 17336370Ssklower int i; 17436370Ssklower printf("clnlintr: src:"); 17536370Ssklower for (i=0; i<6; i++) 17636370Ssklower printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' '); 17736370Ssklower printf(" dst:"); 17836370Ssklower for (i=0; i<6; i++) 17936370Ssklower printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' '); 18036370Ssklower printf("\n"); 18136370Ssklower ENDDEBUG 18236370Ssklower 18336370Ssklower /* 18436370Ssklower * Get the fixed part of the clnl header into the first mbuf. 18536370Ssklower * Drop the packet if this fails. 18636370Ssklower * Do not call m_pullup if we have a cluster mbuf or the 18736370Ssklower * data is not there. 18836370Ssklower */ 18936370Ssklower if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) && 19036370Ssklower ((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) { 19136370Ssklower INCSTAT(cns_toosmall); /* TODO: use clnl stats */ 19236370Ssklower goto next; /* m_pullup discards mbuf */ 19336370Ssklower } 19436370Ssklower 19536370Ssklower clnl = mtod(m, struct clnl_fixed *); 19636370Ssklower 19736370Ssklower /* 19836370Ssklower * Drop packet if the length of the header is not reasonable. 19936370Ssklower */ 20036370Ssklower if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) || 20136370Ssklower (clnl->cnf_hdr_len > CLNP_HDR_MAX)) { 20236370Ssklower INCSTAT(cns_badhlen); /* TODO: use clnl stats */ 20336370Ssklower m_freem(m); 20436370Ssklower goto next; 20536370Ssklower } 20636370Ssklower 20736370Ssklower /* 20836370Ssklower * If the header is not contained in this mbuf, make it so. 20936370Ssklower * Drop packet if this fails. 21036370Ssklower * Note: m_pullup will allocate a cluster mbuf if necessary 21136370Ssklower */ 21236370Ssklower if (clnl->cnf_hdr_len > m->m_len) { 21337469Ssklower if ((m = m_pullup(m, (int)clnl->cnf_hdr_len)) == 0) { 21436370Ssklower INCSTAT(cns_badhlen); /* TODO: use clnl stats */ 21536370Ssklower goto next; /* m_pullup discards mbuf */ 21636370Ssklower } 21736370Ssklower clnl = mtod(m, struct clnl_fixed *); 21836370Ssklower } 21936370Ssklower 22036370Ssklower clnlsw = &clnl_protox[clnl->cnf_proto_id]; 22136370Ssklower 22236370Ssklower 22336370Ssklower if (clnlsw->clnl_input) 22436370Ssklower (*clnlsw->clnl_input) (m, &sh); 22536370Ssklower else 22636370Ssklower m_freem(m); 22736370Ssklower 22836370Ssklower goto next; 22936370Ssklower } 23036370Ssklower 23136370Ssklower /* 23236370Ssklower * FUNCTION: clnp_input 23336370Ssklower * 23436370Ssklower * PURPOSE: process an incoming clnp packet 23536370Ssklower * 23636370Ssklower * RETURNS: nothing 23736370Ssklower * 23836370Ssklower * SIDE EFFECTS: increments fields of clnp_stat structure. 23936370Ssklower * 24036370Ssklower * NOTES: 24136370Ssklower * TODO: I would like to make seg_part a pointer into the mbuf, but 24236370Ssklower * will it be correctly aligned? 24336370Ssklower */ 24437469Ssklower clnp_input(m, shp) 24536370Ssklower struct mbuf *m; /* ptr to first mbuf of pkt */ 24636370Ssklower struct snpa_hdr *shp; /* subnetwork header */ 24736370Ssklower { 24836370Ssklower register struct clnp_fixed *clnp; /* ptr to fixed part of header */ 24936370Ssklower struct iso_addr src; /* source address of pkt */ 25036370Ssklower struct iso_addr dst; /* destination address of pkt */ 25136370Ssklower caddr_t hoff; /* current offset in packet */ 25236370Ssklower caddr_t hend; /* address of end of header info */ 25336370Ssklower struct clnp_segment seg_part; /* segment part of hdr */ 25436370Ssklower int seg_off=0; /* offset of segment part of hdr */ 25536370Ssklower int seg_len;/* length of packet data&hdr in bytes */ 25636370Ssklower struct clnp_optidx oidx, *oidxp = NULL; /* option index */ 25736370Ssklower extern int iso_systype; /* used by ESIS config resp */ 25836766Ssklower int need_afrin = 0; 25936766Ssklower /* true if congestion experienced */ 26036766Ssklower /* which means you need afrin nose */ 26136766Ssklower /* spray. How clever! */ 26236370Ssklower 26336370Ssklower IFDEBUG(D_INPUT) 26436370Ssklower printf( 26536766Ssklower "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n", 26636766Ssklower m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal"); 26736370Ssklower ENDDEBUG 26836766Ssklower need_afrin = 0; 26936370Ssklower 27036370Ssklower /* 27136370Ssklower * If no iso addresses have been set, there is nothing 27236370Ssklower * to do with the packet. 27336370Ssklower */ 27436370Ssklower if (iso_ifaddr == NULL) { 27536370Ssklower clnp_discard(m, ADDR_DESTUNREACH); 27636370Ssklower return; 27736370Ssklower } 27836370Ssklower 27936370Ssklower INCSTAT(cns_total); 28036370Ssklower clnp = mtod(m, struct clnp_fixed *); 28136370Ssklower 28236766Ssklower IFDEBUG(D_DUMPIN) 28336766Ssklower struct mbuf *mhead; 28436766Ssklower int total_len = 0; 28536766Ssklower printf("clnp_input: clnp header:\n"); 28636766Ssklower dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len); 28736766Ssklower printf("clnp_input: mbuf chain:\n"); 28836766Ssklower for (mhead = m; mhead != NULL; mhead=mhead->m_next) { 28936766Ssklower printf("m x%x, len %d\n", mhead, mhead->m_len); 29036766Ssklower total_len += mhead->m_len; 29136766Ssklower } 29236766Ssklower printf("clnp_input: total length of mbuf chain %d:\n", total_len); 29336766Ssklower ENDDEBUG 29436766Ssklower 29536370Ssklower /* 29636370Ssklower * Compute checksum (if necessary) and drop packet if 29736370Ssklower * checksum does not match 29836370Ssklower */ 29937469Ssklower if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, (int)clnp->cnf_hdr_len)) { 30036370Ssklower INCSTAT(cns_badcsum); 30136370Ssklower clnp_discard(m, GEN_BADCSUM); 30237469Ssklower return; 30336370Ssklower } 30436370Ssklower 30536370Ssklower if (clnp->cnf_vers != ISO8473_V1) { 30636370Ssklower INCSTAT(cns_badvers); 30736370Ssklower clnp_discard(m, DISC_UNSUPPVERS); 30837469Ssklower return; 30936370Ssklower } 31036370Ssklower 31136370Ssklower 31236370Ssklower /* check mbuf data length: clnp_data_ck will free mbuf upon error */ 31336370Ssklower CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len); 31436370Ssklower if ((m = clnp_data_ck(m, seg_len)) == 0) 31537469Ssklower return; 31636370Ssklower 31736370Ssklower clnp = mtod(m, struct clnp_fixed *); 31836370Ssklower hend = (caddr_t)clnp + clnp->cnf_hdr_len; 31936370Ssklower 32036370Ssklower /* 32136370Ssklower * extract the source and destination address 32236370Ssklower * drop packet on failure 32336370Ssklower */ 32436370Ssklower bzero((caddr_t)&src, sizeof(src)); 32536370Ssklower bzero((caddr_t)&dst, sizeof(dst)); 32636370Ssklower 32736370Ssklower hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); 32836370Ssklower CLNP_EXTRACT_ADDR(dst, hoff, hend); 32936370Ssklower if (hoff == (caddr_t)0) { 33036370Ssklower INCSTAT(cns_badaddr); 33136370Ssklower clnp_discard(m, GEN_INCOMPLETE); 33237469Ssklower return; 33336370Ssklower } 33436370Ssklower CLNP_EXTRACT_ADDR(src, hoff, hend); 33536370Ssklower if (hoff == (caddr_t)0) { 33636370Ssklower INCSTAT(cns_badaddr); 33736370Ssklower clnp_discard(m, GEN_INCOMPLETE); 33837469Ssklower return; 33936370Ssklower } 34036370Ssklower 34136370Ssklower IFDEBUG(D_INPUT) 34236370Ssklower printf("clnp_input: from %s", clnp_iso_addrp(&src)); 34336370Ssklower printf(" to %s\n", clnp_iso_addrp(&dst)); 34436370Ssklower ENDDEBUG 34536370Ssklower 34636370Ssklower /* 34736370Ssklower * extract the segmentation information, if it is present. 34836370Ssklower * drop packet on failure 34936370Ssklower */ 35037469Ssklower if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && 35137469Ssklower (clnp->cnf_type & CNF_SEG_OK)) { 35236370Ssklower if (hoff + sizeof(struct clnp_segment) > hend) { 35336370Ssklower INCSTAT(cns_noseg); 35436370Ssklower clnp_discard(m, GEN_INCOMPLETE); 35537469Ssklower return; 35636370Ssklower } else { 35736370Ssklower (void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment)); 35836370Ssklower /* make sure segmentation fields are in host order */ 35936370Ssklower seg_part.cng_id = ntohs(seg_part.cng_id); 36036370Ssklower seg_part.cng_off = ntohs(seg_part.cng_off); 36136370Ssklower seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len); 36236370Ssklower seg_off = hoff - (caddr_t)clnp; 36336370Ssklower hoff += sizeof(struct clnp_segment); 36436370Ssklower } 36536370Ssklower } 36636370Ssklower 36736370Ssklower /* 36836370Ssklower * process options if present. If clnp_opt_sanity returns 36936370Ssklower * false (indicating an error was found in the options) or 37036370Ssklower * an unsupported option was found 37136370Ssklower * then drop packet and emit an ER. 37236370Ssklower */ 37336370Ssklower if (hoff < hend) { 37436370Ssklower int errcode; 37536370Ssklower 37636370Ssklower oidxp = &oidx; 37736370Ssklower errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp); 37836370Ssklower 37936370Ssklower /* we do not support security */ 38036370Ssklower if ((errcode == 0) && (oidxp->cni_securep)) 38136370Ssklower errcode = DISC_UNSUPPSECURE; 38236370Ssklower 38336370Ssklower /* the er option is valid with ER pdus only */ 38436370Ssklower if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) && 38537469Ssklower ((clnp->cnf_type & CNF_TYPE) != CLNP_ER)) 38636370Ssklower errcode = DISC_UNSUPPOPT; 38736370Ssklower 38836766Ssklower #ifdef DECBIT 38936766Ssklower /* check if the congestion experienced bit is set */ 39036766Ssklower if (oidxp->cni_qos_formatp) { 39136766Ssklower caddr_t qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp); 39236766Ssklower u_char qos = *qosp; 39336766Ssklower 39436766Ssklower need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) == 39536766Ssklower (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)); 39636766Ssklower if (need_afrin) 39736766Ssklower INCSTAT(cns_congest_rcvd); 39836766Ssklower } 39936766Ssklower #endif DECBIT 40036766Ssklower 40136370Ssklower if (errcode != 0) { 40236370Ssklower clnp_discard(m, (char)errcode); 40336370Ssklower IFDEBUG(D_INPUT) 40436370Ssklower printf("clnp_input: dropped (err x%x) due to bad options\n", 40536370Ssklower errcode); 40636370Ssklower ENDDEBUG 40737469Ssklower return; 40836370Ssklower } 40936370Ssklower } 41036370Ssklower 41136370Ssklower /* 41236370Ssklower * check if this packet is for us. if not, then forward 41336370Ssklower */ 41436370Ssklower if (clnp_ours(&dst) == 0) { 41536370Ssklower IFDEBUG(D_INPUT) 41636370Ssklower printf("clnp_input: forwarding packet not for us\n"); 41736370Ssklower ENDDEBUG 41836370Ssklower clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp); 41937469Ssklower return; 42036370Ssklower } 42136370Ssklower 42236370Ssklower /* 42336370Ssklower * ESIS Configuration Response Function 42436370Ssklower * 42536370Ssklower * If the packet received was sent to the multicast address 42636370Ssklower * all end systems, then send an esh to the source 42736370Ssklower */ 42837469Ssklower if ((shp->snh_flags & M_MCAST) && (iso_systype == SNPA_ES)) { 42936370Ssklower extern short esis_holding_time; 43036370Ssklower 43136370Ssklower esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time, 43236370Ssklower shp->snh_shost, 6); 43336370Ssklower } 43436370Ssklower 43536370Ssklower /* 43636370Ssklower * If this is a fragment, then try to reassemble it. If clnp_reass 43736370Ssklower * returns non NULL, the packet has been reassembled, and should 43836370Ssklower * be give to TP. Otherwise the fragment has been delt with 43936370Ssklower * by the reassembly code (either stored or deleted). In either case 44036370Ssklower * we should have nothing more to do with it. 44136370Ssklower */ 44237469Ssklower if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && 44337469Ssklower (clnp->cnf_type & CNF_SEG_OK) && 44436370Ssklower (seg_len != seg_part.cng_tot_len)) { 44536370Ssklower struct mbuf *m0; 44636370Ssklower 44736370Ssklower if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) { 44836370Ssklower m = m0; 44936370Ssklower clnp = mtod(m, struct clnp_fixed *); 45036370Ssklower } else { 45137469Ssklower return; 45236370Ssklower } 45336370Ssklower } 45436370Ssklower 45536370Ssklower /* 45636370Ssklower * give the packet to the higher layer 45736370Ssklower * 45836370Ssklower * Note: the total length of packet 45936370Ssklower * is the total length field of the segmentation part, 46036370Ssklower * or, if absent, the segment length field of the 46136370Ssklower * header. 46236370Ssklower */ 46337469Ssklower switch (clnp->cnf_type & CNF_TYPE) { 46436370Ssklower case CLNP_ER: 46536370Ssklower /* 46636370Ssklower * This ER must have the er option. 46736370Ssklower * If the option is not present, discard datagram. 46836370Ssklower */ 46936370Ssklower if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) { 47036370Ssklower clnp_discard(m, GEN_HDRSYNTAX); 47136370Ssklower } else { 47236370Ssklower clnp_er_input(m, &src, oidxp->cni_er_reason); 47336370Ssklower } 47436370Ssklower break; 47536370Ssklower 47636370Ssklower case CLNP_DT: 47736766Ssklower if (need_afrin) { 47836766Ssklower /* NOTE: do this before TP gets the packet so tp ack can use info*/ 47936766Ssklower IFDEBUG(D_INPUT) 48036766Ssklower printf("clnp_input: Calling tpclnp_ctlinput(%s)\n", 48136766Ssklower clnp_iso_addrp(&src)); 48236766Ssklower ENDDEBUG 48336766Ssklower tpclnp_ctlinput1(PRC_QUENCH2, &src); 48436766Ssklower } 48536370Ssklower (*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &src, &dst, 48636370Ssklower clnp->cnf_hdr_len); 48736370Ssklower break; 48836370Ssklower 48936370Ssklower case CLNP_RAW: 49036370Ssklower case CLNP_ECR: 49136370Ssklower IFDEBUG(D_INPUT) 49236370Ssklower printf("clnp_input: raw input of %d bytes\n", 49337469Ssklower clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len); 49436370Ssklower ENDDEBUG 49536370Ssklower (*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &src, &dst, 49636370Ssklower clnp->cnf_hdr_len); 49736370Ssklower break; 49836370Ssklower 49936370Ssklower case CLNP_EC: 50036370Ssklower IFDEBUG(D_INPUT) 50136370Ssklower printf("clnp_input: echoing packet\n"); 50236370Ssklower ENDDEBUG 50336370Ssklower /* 50436370Ssklower * Switch the source and destination address, 50536370Ssklower */ 50636370Ssklower hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); 50737469Ssklower CLNP_INSERT_ADDR(hoff, src); 50837469Ssklower CLNP_INSERT_ADDR(hoff, dst); 50937469Ssklower clnp->cnf_type &= ~CNF_TYPE; 51037469Ssklower clnp->cnf_type |= CLNP_ECR; 51136370Ssklower 51236370Ssklower /* 51336370Ssklower * Forward back to sender 51436370Ssklower */ 51537469Ssklower clnp_forward(m, (int)(clnp->cnf_type & CNF_SEG_OK?seg_part.cng_tot_len : seg_len), 51636370Ssklower &src, oidxp, seg_off, shp); 51736370Ssklower break; 51836370Ssklower 51936370Ssklower default: 52037469Ssklower printf("clnp_input: unknown clnp pkt type %d\n", 52137469Ssklower clnp->cnf_type & CNF_TYPE); 52236370Ssklower clnp_discard(m, GEN_HDRSYNTAX); 52336370Ssklower break; 52436370Ssklower } 52536370Ssklower } 52636370Ssklower #endif ISO 527