149267Sbostic /*-
2*63222Sbostic * Copyright (c) 1991, 1993
3*63222Sbostic * The Regents of the University of California. All rights reserved.
449267Sbostic *
549267Sbostic * %sccs.include.redist.c%
649267Sbostic *
7*63222Sbostic * @(#)clnp_input.c 8.1 (Berkeley) 06/10/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();
7760359Sbostic #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 */
clnp_init()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 */
clnlintr()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 }
41360359Sbostic #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 }
52560359Sbostic #endif /* ISO */
526