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*37469Ssklower /* @(#)clnp_input.c 7.4 (Berkeley) 04/22/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 3536370Ssklower #include "../h/types.h" 3636370Ssklower #include "../h/param.h" 3736370Ssklower #include "../h/mbuf.h" 3836370Ssklower #include "../h/domain.h" 3936370Ssklower #include "../h/protosw.h" 4036370Ssklower #include "../h/socket.h" 4136370Ssklower #include "../h/socketvar.h" 4236370Ssklower #include "../h/errno.h" 4336370Ssklower #include "../h/time.h" 4436370Ssklower 4536370Ssklower #include "../net/if.h" 46*37469Ssklower #include "../net/iftypes.h" 4736370Ssklower #include "../net/route.h" 4836370Ssklower 49*37469Ssklower #include "iso.h" 50*37469Ssklower #include "iso_var.h" 51*37469Ssklower #include "iso_snpac.h" 52*37469Ssklower #include "clnp.h" 53*37469Ssklower #include "clnl.h" 54*37469Ssklower #include "../netinet/in_systm.h" 55*37469Ssklower #include "../netinet/ip.h" 56*37469Ssklower #include "eonvar.h" 57*37469Ssklower #include "esis.h" 58*37469Ssklower #include "clnp_stat.h" 59*37469Ssklower #include "argo_debug.h" 6036370Ssklower 6136370Ssklower #ifdef ISO 6236370Ssklower u_char clnp_protox[ISOPROTO_MAX]; 6336370Ssklower struct clnl_protosw clnl_protox[256]; 6436370Ssklower int clnpqmaxlen = IFQ_MAXLEN; /* RAH? why is this a variable */ 6536370Ssklower struct mbuf *clnp_data_ck(); 6636370Ssklower 6736370Ssklower int clnp_input(); 6836370Ssklower 6936370Ssklower int esis_input(); 7036370Ssklower 7136370Ssklower #ifdef ISO_X25ESIS 7236370Ssklower int x25esis_input(); 7336370Ssklower #endif ISO_X25ESIS 7436370Ssklower 7536370Ssklower /* 7636370Ssklower * FUNCTION: clnp_init 7736370Ssklower * 7836370Ssklower * PURPOSE: clnp initialization. Fill in clnp switch tables. 7936370Ssklower * 8036370Ssklower * RETURNS: none 8136370Ssklower * 8236370Ssklower * SIDE EFFECTS: fills in clnp_protox table with correct offsets into 8336370Ssklower * the isosw table. 8436370Ssklower * 8536370Ssklower * NOTES: 8636370Ssklower */ 8736370Ssklower clnp_init() 8836370Ssklower { 8936370Ssklower register struct protosw *pr; 9036370Ssklower 9136370Ssklower /* 9236370Ssklower * CLNP protox initialization 9336370Ssklower */ 9436370Ssklower if ((pr = pffindproto(PF_ISO, ISOPROTO_RAW, SOCK_RAW)) == 0) 9536370Ssklower printf("clnl_init: no raw CLNP\n"); 9636370Ssklower else 9736370Ssklower clnp_protox[ISOPROTO_RAW] = pr - isosw; 9836370Ssklower 9936370Ssklower if ((pr = pffindproto(PF_ISO, ISOPROTO_TP, SOCK_SEQPACKET)) == 0) 10036370Ssklower printf("clnl_init: no tp/clnp\n"); 10136370Ssklower else 10236370Ssklower clnp_protox[ISOPROTO_TP] = pr - isosw; 10336370Ssklower 10436370Ssklower /* 10536370Ssklower * CLNL protox initialization 10636370Ssklower */ 10736370Ssklower clnl_protox[ISO8473_CLNP].clnl_input = clnp_input; 10836370Ssklower 10936370Ssklower clnlintrq.ifq_maxlen = clnpqmaxlen; 11036370Ssklower } 11136370Ssklower 11236370Ssklower /* 11336370Ssklower * FUNCTION: clnlintr 11436370Ssklower * 11536370Ssklower * PURPOSE: Process a packet on the clnl input queue 11636370Ssklower * 11736370Ssklower * RETURNS: nothing. 11836370Ssklower * 11936370Ssklower * SIDE EFFECTS: 12036370Ssklower * 12136370Ssklower * NOTES: 12236370Ssklower */ 12336370Ssklower clnlintr() 12436370Ssklower { 12536370Ssklower register struct mbuf *m; /* ptr to first mbuf of pkt */ 12636370Ssklower register struct clnl_fixed *clnl; /* ptr to fixed part of clnl hdr */ 12736370Ssklower int s; /* save and restore priority */ 12836370Ssklower struct clnl_protosw *clnlsw;/* ptr to protocol switch */ 12936370Ssklower struct snpa_hdr sh; /* subnetwork hdr */ 13036370Ssklower 13136370Ssklower /* 13236370Ssklower * Get next datagram off clnl input queue 13336370Ssklower */ 13436370Ssklower next: 13536370Ssklower s = splimp(); 13636765Ssklower /* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/ 13736765Ssklower IF_DEQUEUE(&clnlintrq, m); 138*37469Ssklower splx(s); 13936370Ssklower 14036765Ssklower 14136765Ssklower if (m == 0) /* nothing to do */ 14236765Ssklower return; 143*37469Ssklower if ((m->m_flags & M_PKTHDR) == 0) { 14436765Ssklower m_freem(m); 14536765Ssklower goto next; 14636765Ssklower } 147*37469Ssklower bzero((caddr_t)&sh, sizeof(sh)); 148*37469Ssklower sh.snh_flags = m->m_flags & (M_MCAST|M_BCAST); 149*37469Ssklower switch((sh.snh_ifp = m->m_pkthdr.rcvif)->if_type) { 150*37469Ssklower extern int ether_output(); 151*37469Ssklower case IFT_EON: 152*37469Ssklower bcopy(mtod(m, caddr_t), (caddr_t)sh.snh_dhost, sizeof(u_long)); 153*37469Ssklower bcopy(sizeof(u_long) + mtod(m, caddr_t), 154*37469Ssklower (caddr_t)sh.snh_shost, sizeof(u_long)); 155*37469Ssklower sh.snh_dhost[4] = mtod(m, u_char *)[sizeof(struct ip) + 156*37469Ssklower _offsetof(struct eon_hdr, eonh_class)]; 157*37469Ssklower m->m_data += EONIPLEN; 158*37469Ssklower m->m_len -= EONIPLEN; 159*37469Ssklower m->m_pkthdr.len -= EONIPLEN; 160*37469Ssklower break; 161*37469Ssklower 162*37469Ssklower default: 163*37469Ssklower if (sh.snh_ifp->if_output == ether_output) { 164*37469Ssklower bcopy((caddr_t)(mtod(m, struct llc_etherhdr *)->dst), 165*37469Ssklower (caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost)); 166*37469Ssklower m->m_data += sizeof (struct llc_etherhdr); 167*37469Ssklower m->m_len -= sizeof (struct llc_etherhdr); 168*37469Ssklower m->m_pkthdr.len -= sizeof (struct llc_etherhdr); 169*37469Ssklower } 170*37469Ssklower } 17136370Ssklower IFDEBUG(D_INPUT) 17236370Ssklower int i; 17336370Ssklower printf("clnlintr: src:"); 17436370Ssklower for (i=0; i<6; i++) 17536370Ssklower printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' '); 17636370Ssklower printf(" dst:"); 17736370Ssklower for (i=0; i<6; i++) 17836370Ssklower printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' '); 17936370Ssklower printf("\n"); 18036370Ssklower ENDDEBUG 18136370Ssklower 18236370Ssklower /* 18336370Ssklower * Get the fixed part of the clnl header into the first mbuf. 18436370Ssklower * Drop the packet if this fails. 18536370Ssklower * Do not call m_pullup if we have a cluster mbuf or the 18636370Ssklower * data is not there. 18736370Ssklower */ 18836370Ssklower if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) && 18936370Ssklower ((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) { 19036370Ssklower INCSTAT(cns_toosmall); /* TODO: use clnl stats */ 19136370Ssklower goto next; /* m_pullup discards mbuf */ 19236370Ssklower } 19336370Ssklower 19436370Ssklower clnl = mtod(m, struct clnl_fixed *); 19536370Ssklower 19636370Ssklower /* 19736370Ssklower * Drop packet if the length of the header is not reasonable. 19836370Ssklower */ 19936370Ssklower if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) || 20036370Ssklower (clnl->cnf_hdr_len > CLNP_HDR_MAX)) { 20136370Ssklower INCSTAT(cns_badhlen); /* TODO: use clnl stats */ 20236370Ssklower m_freem(m); 20336370Ssklower goto next; 20436370Ssklower } 20536370Ssklower 20636370Ssklower /* 20736370Ssklower * If the header is not contained in this mbuf, make it so. 20836370Ssklower * Drop packet if this fails. 20936370Ssklower * Note: m_pullup will allocate a cluster mbuf if necessary 21036370Ssklower */ 21136370Ssklower if (clnl->cnf_hdr_len > m->m_len) { 212*37469Ssklower if ((m = m_pullup(m, (int)clnl->cnf_hdr_len)) == 0) { 21336370Ssklower INCSTAT(cns_badhlen); /* TODO: use clnl stats */ 21436370Ssklower goto next; /* m_pullup discards mbuf */ 21536370Ssklower } 21636370Ssklower clnl = mtod(m, struct clnl_fixed *); 21736370Ssklower } 21836370Ssklower 21936370Ssklower clnlsw = &clnl_protox[clnl->cnf_proto_id]; 22036370Ssklower 22136370Ssklower 22236370Ssklower if (clnlsw->clnl_input) 22336370Ssklower (*clnlsw->clnl_input) (m, &sh); 22436370Ssklower else 22536370Ssklower m_freem(m); 22636370Ssklower 22736370Ssklower goto next; 22836370Ssklower } 22936370Ssklower 23036370Ssklower /* 23136370Ssklower * FUNCTION: clnp_input 23236370Ssklower * 23336370Ssklower * PURPOSE: process an incoming clnp packet 23436370Ssklower * 23536370Ssklower * RETURNS: nothing 23636370Ssklower * 23736370Ssklower * SIDE EFFECTS: increments fields of clnp_stat structure. 23836370Ssklower * 23936370Ssklower * NOTES: 24036370Ssklower * TODO: I would like to make seg_part a pointer into the mbuf, but 24136370Ssklower * will it be correctly aligned? 24236370Ssklower */ 243*37469Ssklower clnp_input(m, shp) 24436370Ssklower struct mbuf *m; /* ptr to first mbuf of pkt */ 24536370Ssklower struct snpa_hdr *shp; /* subnetwork header */ 24636370Ssklower { 24736370Ssklower register struct clnp_fixed *clnp; /* ptr to fixed part of header */ 24836370Ssklower struct iso_addr src; /* source address of pkt */ 24936370Ssklower struct iso_addr dst; /* destination address of pkt */ 25036370Ssklower caddr_t hoff; /* current offset in packet */ 25136370Ssklower caddr_t hend; /* address of end of header info */ 25236370Ssklower struct clnp_segment seg_part; /* segment part of hdr */ 25336370Ssklower int seg_off=0; /* offset of segment part of hdr */ 25436370Ssklower int seg_len;/* length of packet data&hdr in bytes */ 25536370Ssklower struct clnp_optidx oidx, *oidxp = NULL; /* option index */ 25636370Ssklower extern int iso_systype; /* used by ESIS config resp */ 25736766Ssklower int need_afrin = 0; 25836766Ssklower /* true if congestion experienced */ 25936766Ssklower /* which means you need afrin nose */ 26036766Ssklower /* spray. How clever! */ 26136370Ssklower 26236370Ssklower IFDEBUG(D_INPUT) 26336370Ssklower printf( 26436766Ssklower "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n", 26536766Ssklower m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal"); 26636370Ssklower ENDDEBUG 26736766Ssklower need_afrin = 0; 26836370Ssklower 26936370Ssklower /* 27036370Ssklower * If no iso addresses have been set, there is nothing 27136370Ssklower * to do with the packet. 27236370Ssklower */ 27336370Ssklower if (iso_ifaddr == NULL) { 27436370Ssklower clnp_discard(m, ADDR_DESTUNREACH); 27536370Ssklower return; 27636370Ssklower } 27736370Ssklower 27836370Ssklower INCSTAT(cns_total); 27936370Ssklower clnp = mtod(m, struct clnp_fixed *); 28036370Ssklower 28136766Ssklower IFDEBUG(D_DUMPIN) 28236766Ssklower struct mbuf *mhead; 28336766Ssklower int total_len = 0; 28436766Ssklower printf("clnp_input: clnp header:\n"); 28536766Ssklower dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len); 28636766Ssklower printf("clnp_input: mbuf chain:\n"); 28736766Ssklower for (mhead = m; mhead != NULL; mhead=mhead->m_next) { 28836766Ssklower printf("m x%x, len %d\n", mhead, mhead->m_len); 28936766Ssklower total_len += mhead->m_len; 29036766Ssklower } 29136766Ssklower printf("clnp_input: total length of mbuf chain %d:\n", total_len); 29236766Ssklower ENDDEBUG 29336766Ssklower 29436370Ssklower /* 29536370Ssklower * Compute checksum (if necessary) and drop packet if 29636370Ssklower * checksum does not match 29736370Ssklower */ 298*37469Ssklower if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, (int)clnp->cnf_hdr_len)) { 29936370Ssklower INCSTAT(cns_badcsum); 30036370Ssklower clnp_discard(m, GEN_BADCSUM); 301*37469Ssklower return; 30236370Ssklower } 30336370Ssklower 30436370Ssklower if (clnp->cnf_vers != ISO8473_V1) { 30536370Ssklower INCSTAT(cns_badvers); 30636370Ssklower clnp_discard(m, DISC_UNSUPPVERS); 307*37469Ssklower return; 30836370Ssklower } 30936370Ssklower 31036370Ssklower 31136370Ssklower /* check mbuf data length: clnp_data_ck will free mbuf upon error */ 31236370Ssklower CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len); 31336370Ssklower if ((m = clnp_data_ck(m, seg_len)) == 0) 314*37469Ssklower return; 31536370Ssklower 31636370Ssklower clnp = mtod(m, struct clnp_fixed *); 31736370Ssklower hend = (caddr_t)clnp + clnp->cnf_hdr_len; 31836370Ssklower 31936370Ssklower /* 32036370Ssklower * extract the source and destination address 32136370Ssklower * drop packet on failure 32236370Ssklower */ 32336370Ssklower bzero((caddr_t)&src, sizeof(src)); 32436370Ssklower bzero((caddr_t)&dst, sizeof(dst)); 32536370Ssklower 32636370Ssklower hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); 32736370Ssklower CLNP_EXTRACT_ADDR(dst, hoff, hend); 32836370Ssklower if (hoff == (caddr_t)0) { 32936370Ssklower INCSTAT(cns_badaddr); 33036370Ssklower clnp_discard(m, GEN_INCOMPLETE); 331*37469Ssklower return; 33236370Ssklower } 33336370Ssklower CLNP_EXTRACT_ADDR(src, hoff, hend); 33436370Ssklower if (hoff == (caddr_t)0) { 33536370Ssklower INCSTAT(cns_badaddr); 33636370Ssklower clnp_discard(m, GEN_INCOMPLETE); 337*37469Ssklower return; 33836370Ssklower } 33936370Ssklower 34036370Ssklower IFDEBUG(D_INPUT) 34136370Ssklower printf("clnp_input: from %s", clnp_iso_addrp(&src)); 34236370Ssklower printf(" to %s\n", clnp_iso_addrp(&dst)); 34336370Ssklower ENDDEBUG 34436370Ssklower 34536370Ssklower /* 34636370Ssklower * extract the segmentation information, if it is present. 34736370Ssklower * drop packet on failure 34836370Ssklower */ 349*37469Ssklower if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && 350*37469Ssklower (clnp->cnf_type & CNF_SEG_OK)) { 35136370Ssklower if (hoff + sizeof(struct clnp_segment) > hend) { 35236370Ssklower INCSTAT(cns_noseg); 35336370Ssklower clnp_discard(m, GEN_INCOMPLETE); 354*37469Ssklower return; 35536370Ssklower } else { 35636370Ssklower (void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment)); 35736370Ssklower /* make sure segmentation fields are in host order */ 35836370Ssklower seg_part.cng_id = ntohs(seg_part.cng_id); 35936370Ssklower seg_part.cng_off = ntohs(seg_part.cng_off); 36036370Ssklower seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len); 36136370Ssklower seg_off = hoff - (caddr_t)clnp; 36236370Ssklower hoff += sizeof(struct clnp_segment); 36336370Ssklower } 36436370Ssklower } 36536370Ssklower 36636370Ssklower /* 36736370Ssklower * process options if present. If clnp_opt_sanity returns 36836370Ssklower * false (indicating an error was found in the options) or 36936370Ssklower * an unsupported option was found 37036370Ssklower * then drop packet and emit an ER. 37136370Ssklower */ 37236370Ssklower if (hoff < hend) { 37336370Ssklower int errcode; 37436370Ssklower 37536370Ssklower oidxp = &oidx; 37636370Ssklower errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp); 37736370Ssklower 37836370Ssklower /* we do not support security */ 37936370Ssklower if ((errcode == 0) && (oidxp->cni_securep)) 38036370Ssklower errcode = DISC_UNSUPPSECURE; 38136370Ssklower 38236370Ssklower /* the er option is valid with ER pdus only */ 38336370Ssklower if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) && 384*37469Ssklower ((clnp->cnf_type & CNF_TYPE) != CLNP_ER)) 38536370Ssklower errcode = DISC_UNSUPPOPT; 38636370Ssklower 38736766Ssklower #ifdef DECBIT 38836766Ssklower /* check if the congestion experienced bit is set */ 38936766Ssklower if (oidxp->cni_qos_formatp) { 39036766Ssklower caddr_t qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp); 39136766Ssklower u_char qos = *qosp; 39236766Ssklower 39336766Ssklower need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) == 39436766Ssklower (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)); 39536766Ssklower if (need_afrin) 39636766Ssklower INCSTAT(cns_congest_rcvd); 39736766Ssklower } 39836766Ssklower #endif DECBIT 39936766Ssklower 40036370Ssklower if (errcode != 0) { 40136370Ssklower clnp_discard(m, (char)errcode); 40236370Ssklower IFDEBUG(D_INPUT) 40336370Ssklower printf("clnp_input: dropped (err x%x) due to bad options\n", 40436370Ssklower errcode); 40536370Ssklower ENDDEBUG 406*37469Ssklower return; 40736370Ssklower } 40836370Ssklower } 40936370Ssklower 41036370Ssklower /* 41136370Ssklower * check if this packet is for us. if not, then forward 41236370Ssklower */ 41336370Ssklower if (clnp_ours(&dst) == 0) { 41436370Ssklower IFDEBUG(D_INPUT) 41536370Ssklower printf("clnp_input: forwarding packet not for us\n"); 41636370Ssklower ENDDEBUG 41736370Ssklower clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp); 418*37469Ssklower return; 41936370Ssklower } 42036370Ssklower 42136370Ssklower /* 42236370Ssklower * ESIS Configuration Response Function 42336370Ssklower * 42436370Ssklower * If the packet received was sent to the multicast address 42536370Ssklower * all end systems, then send an esh to the source 42636370Ssklower */ 427*37469Ssklower if ((shp->snh_flags & M_MCAST) && (iso_systype == SNPA_ES)) { 42836370Ssklower extern short esis_holding_time; 42936370Ssklower 43036370Ssklower esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time, 43136370Ssklower shp->snh_shost, 6); 43236370Ssklower } 43336370Ssklower 43436370Ssklower /* 43536370Ssklower * If this is a fragment, then try to reassemble it. If clnp_reass 43636370Ssklower * returns non NULL, the packet has been reassembled, and should 43736370Ssklower * be give to TP. Otherwise the fragment has been delt with 43836370Ssklower * by the reassembly code (either stored or deleted). In either case 43936370Ssklower * we should have nothing more to do with it. 44036370Ssklower */ 441*37469Ssklower if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && 442*37469Ssklower (clnp->cnf_type & CNF_SEG_OK) && 44336370Ssklower (seg_len != seg_part.cng_tot_len)) { 44436370Ssklower struct mbuf *m0; 44536370Ssklower 44636370Ssklower if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) { 44736370Ssklower m = m0; 44836370Ssklower clnp = mtod(m, struct clnp_fixed *); 44936370Ssklower } else { 450*37469Ssklower return; 45136370Ssklower } 45236370Ssklower } 45336370Ssklower 45436370Ssklower /* 45536370Ssklower * give the packet to the higher layer 45636370Ssklower * 45736370Ssklower * Note: the total length of packet 45836370Ssklower * is the total length field of the segmentation part, 45936370Ssklower * or, if absent, the segment length field of the 46036370Ssklower * header. 46136370Ssklower */ 462*37469Ssklower switch (clnp->cnf_type & CNF_TYPE) { 46336370Ssklower case CLNP_ER: 46436370Ssklower /* 46536370Ssklower * This ER must have the er option. 46636370Ssklower * If the option is not present, discard datagram. 46736370Ssklower */ 46836370Ssklower if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) { 46936370Ssklower clnp_discard(m, GEN_HDRSYNTAX); 47036370Ssklower } else { 47136370Ssklower clnp_er_input(m, &src, oidxp->cni_er_reason); 47236370Ssklower } 47336370Ssklower break; 47436370Ssklower 47536370Ssklower case CLNP_DT: 47636766Ssklower if (need_afrin) { 47736766Ssklower /* NOTE: do this before TP gets the packet so tp ack can use info*/ 47836766Ssklower IFDEBUG(D_INPUT) 47936766Ssklower printf("clnp_input: Calling tpclnp_ctlinput(%s)\n", 48036766Ssklower clnp_iso_addrp(&src)); 48136766Ssklower ENDDEBUG 48236766Ssklower tpclnp_ctlinput1(PRC_QUENCH2, &src); 48336766Ssklower } 48436370Ssklower (*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &src, &dst, 48536370Ssklower clnp->cnf_hdr_len); 48636370Ssklower break; 48736370Ssklower 48836370Ssklower case CLNP_RAW: 48936370Ssklower case CLNP_ECR: 49036370Ssklower IFDEBUG(D_INPUT) 49136370Ssklower printf("clnp_input: raw input of %d bytes\n", 492*37469Ssklower clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len); 49336370Ssklower ENDDEBUG 49436370Ssklower (*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &src, &dst, 49536370Ssklower clnp->cnf_hdr_len); 49636370Ssklower break; 49736370Ssklower 49836370Ssklower case CLNP_EC: 49936370Ssklower IFDEBUG(D_INPUT) 50036370Ssklower printf("clnp_input: echoing packet\n"); 50136370Ssklower ENDDEBUG 50236370Ssklower /* 50336370Ssklower * Switch the source and destination address, 50436370Ssklower */ 50536370Ssklower hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); 506*37469Ssklower CLNP_INSERT_ADDR(hoff, src); 507*37469Ssklower CLNP_INSERT_ADDR(hoff, dst); 508*37469Ssklower clnp->cnf_type &= ~CNF_TYPE; 509*37469Ssklower clnp->cnf_type |= CLNP_ECR; 51036370Ssklower 51136370Ssklower /* 51236370Ssklower * Forward back to sender 51336370Ssklower */ 514*37469Ssklower clnp_forward(m, (int)(clnp->cnf_type & CNF_SEG_OK?seg_part.cng_tot_len : seg_len), 51536370Ssklower &src, oidxp, seg_off, shp); 51636370Ssklower break; 51736370Ssklower 51836370Ssklower default: 519*37469Ssklower printf("clnp_input: unknown clnp pkt type %d\n", 520*37469Ssklower clnp->cnf_type & CNF_TYPE); 52136370Ssklower clnp_discard(m, GEN_HDRSYNTAX); 52236370Ssklower break; 52336370Ssklower } 52436370Ssklower } 52536370Ssklower #endif ISO 526