|
|
1.1 root 1: /*-
2: * Copyright (c) 1991 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)clnp_input.c 7.13 (Berkeley) 5/6/91
34: */
35:
36: /***********************************************************
37: Copyright IBM Corporation 1987
38:
39: All Rights Reserved
40:
41: Permission to use, copy, modify, and distribute this software and its
42: documentation for any purpose and without fee is hereby granted,
43: provided that the above copyright notice appear in all copies and that
44: both that copyright notice and this permission notice appear in
45: supporting documentation, and that the name of IBM not be
46: used in advertising or publicity pertaining to distribution of the
47: software without specific, written prior permission.
48:
49: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
50: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
51: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
52: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
53: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
54: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
55: SOFTWARE.
56:
57: ******************************************************************/
58:
59: /*
60: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
61: */
62: /* $Header: /var/src/sys/netiso/RCS/clnp_input.c,v 5.1 89/02/09 16:20:32 hagens Exp $ */
63: /* $Source: /var/src/sys/netiso/RCS/clnp_input.c,v $ */
64:
65: #include "types.h"
66: #include "param.h"
67: #include "mbuf.h"
68: #include "domain.h"
69: #include "protosw.h"
70: #include "socket.h"
71: #include "socketvar.h"
72: #include "errno.h"
73: #include "time.h"
74:
75: #include "../net/if.h"
76: #include "../net/if_types.h"
77: #include "../net/route.h"
78:
79: #include "iso.h"
80: #include "iso_var.h"
81: #include "iso_snpac.h"
82: #include "clnp.h"
83: #include "clnl.h"
84: #include "esis.h"
85: #include "../netinet/in_systm.h"
86: #include "../netinet/ip.h"
87: #include "../netinet/if_ether.h"
88: #include "eonvar.h"
89: #include "clnp_stat.h"
90: #include "argo_debug.h"
91:
92: #ifdef ISO
93: u_char clnp_protox[ISOPROTO_MAX];
94: struct clnl_protosw clnl_protox[256];
95: int clnpqmaxlen = IFQ_MAXLEN; /* RAH? why is this a variable */
96: struct mbuf *clnp_data_ck();
97:
98: int clnp_input();
99:
100: int esis_input();
101:
102: #ifdef ISO_X25ESIS
103: int x25esis_input();
104: #endif ISO_X25ESIS
105:
106: /*
107: * FUNCTION: clnp_init
108: *
109: * PURPOSE: clnp initialization. Fill in clnp switch tables.
110: *
111: * RETURNS: none
112: *
113: * SIDE EFFECTS: fills in clnp_protox table with correct offsets into
114: * the isosw table.
115: *
116: * NOTES:
117: */
118: clnp_init()
119: {
120: register struct protosw *pr;
121:
122: /*
123: * CLNP protox initialization
124: */
125: if ((pr = pffindproto(PF_ISO, ISOPROTO_RAW, SOCK_RAW)) == 0)
126: printf("clnl_init: no raw CLNP\n");
127: else
128: clnp_protox[ISOPROTO_RAW] = pr - isosw;
129:
130: if ((pr = pffindproto(PF_ISO, ISOPROTO_TP, SOCK_SEQPACKET)) == 0)
131: printf("clnl_init: no tp/clnp\n");
132: else
133: clnp_protox[ISOPROTO_TP] = pr - isosw;
134:
135: /*
136: * CLNL protox initialization
137: */
138: clnl_protox[ISO8473_CLNP].clnl_input = clnp_input;
139:
140: clnlintrq.ifq_maxlen = clnpqmaxlen;
141: }
142:
143: /*
144: * FUNCTION: clnlintr
145: *
146: * PURPOSE: Process a packet on the clnl input queue
147: *
148: * RETURNS: nothing.
149: *
150: * SIDE EFFECTS:
151: *
152: * NOTES:
153: */
154: clnlintr()
155: {
156: register struct mbuf *m; /* ptr to first mbuf of pkt */
157: register struct clnl_fixed *clnl; /* ptr to fixed part of clnl hdr */
158: int s; /* save and restore priority */
159: struct clnl_protosw *clnlsw;/* ptr to protocol switch */
160: struct snpa_hdr sh; /* subnetwork hdr */
161:
162: /*
163: * Get next datagram off clnl input queue
164: */
165: next:
166: s = splimp();
167: /* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/
168: IF_DEQUEUE(&clnlintrq, m);
169: splx(s);
170:
171:
172: if (m == 0) /* nothing to do */
173: return;
174: if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.rcvif == 0) {
175: m_freem(m);
176: goto next;
177: } else {
178: register struct ifaddr *ifa;
179: for (ifa = m->m_pkthdr.rcvif->if_addrlist; ifa; ifa = ifa->ifa_next)
180: if (ifa->ifa_addr->sa_family == AF_ISO)
181: break;
182: if (ifa == 0) {
183: m_freem(m);
184: goto next;
185: }
186: }
187: bzero((caddr_t)&sh, sizeof(sh));
188: sh.snh_flags = m->m_flags & (M_MCAST|M_BCAST);
189: switch((sh.snh_ifp = m->m_pkthdr.rcvif)->if_type) {
190: extern int ether_output();
191: case IFT_EON:
192: bcopy(mtod(m, caddr_t), (caddr_t)sh.snh_dhost, sizeof(u_long));
193: bcopy(sizeof(u_long) + mtod(m, caddr_t),
194: (caddr_t)sh.snh_shost, sizeof(u_long));
195: sh.snh_dhost[4] = mtod(m, u_char *)[sizeof(struct ip) +
196: _offsetof(struct eon_hdr, eonh_class)];
197: m->m_data += EONIPLEN;
198: m->m_len -= EONIPLEN;
199: m->m_pkthdr.len -= EONIPLEN;
200: break;
201:
202: default:
203: if (sh.snh_ifp->if_output == ether_output) {
204: bcopy((caddr_t)(mtod(m, struct ether_header *)->ether_dhost),
205: (caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost));
206: m->m_data += sizeof (struct ether_header);
207: m->m_len -= sizeof (struct ether_header);
208: m->m_pkthdr.len -= sizeof (struct ether_header);
209: }
210: }
211: IFDEBUG(D_INPUT)
212: int i;
213: printf("clnlintr: src:");
214: for (i=0; i<6; i++)
215: printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' ');
216: printf(" dst:");
217: for (i=0; i<6; i++)
218: printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' ');
219: printf("\n");
220: ENDDEBUG
221:
222: /*
223: * Get the fixed part of the clnl header into the first mbuf.
224: * Drop the packet if this fails.
225: * Do not call m_pullup if we have a cluster mbuf or the
226: * data is not there.
227: */
228: if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) &&
229: ((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) {
230: INCSTAT(cns_toosmall); /* TODO: use clnl stats */
231: goto next; /* m_pullup discards mbuf */
232: }
233:
234: clnl = mtod(m, struct clnl_fixed *);
235:
236: /*
237: * Drop packet if the length of the header is not reasonable.
238: */
239: if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) ||
240: (clnl->cnf_hdr_len > CLNP_HDR_MAX)) {
241: INCSTAT(cns_badhlen); /* TODO: use clnl stats */
242: m_freem(m);
243: goto next;
244: }
245:
246: /*
247: * If the header is not contained in this mbuf, make it so.
248: * Drop packet if this fails.
249: * Note: m_pullup will allocate a cluster mbuf if necessary
250: */
251: if (clnl->cnf_hdr_len > m->m_len) {
252: if ((m = m_pullup(m, (int)clnl->cnf_hdr_len)) == 0) {
253: INCSTAT(cns_badhlen); /* TODO: use clnl stats */
254: goto next; /* m_pullup discards mbuf */
255: }
256: clnl = mtod(m, struct clnl_fixed *);
257: }
258:
259: clnlsw = &clnl_protox[clnl->cnf_proto_id];
260:
261:
262: if (clnlsw->clnl_input)
263: (*clnlsw->clnl_input) (m, &sh);
264: else
265: m_freem(m);
266:
267: goto next;
268: }
269:
270: /*
271: * FUNCTION: clnp_input
272: *
273: * PURPOSE: process an incoming clnp packet
274: *
275: * RETURNS: nothing
276: *
277: * SIDE EFFECTS: increments fields of clnp_stat structure.
278: *
279: * NOTES:
280: * TODO: I would like to make seg_part a pointer into the mbuf, but
281: * will it be correctly aligned?
282: */
283: clnp_input(m, shp)
284: struct mbuf *m; /* ptr to first mbuf of pkt */
285: struct snpa_hdr *shp; /* subnetwork header */
286: {
287: register struct clnp_fixed *clnp; /* ptr to fixed part of header */
288: struct sockaddr_iso source; /* source address of pkt */
289: struct sockaddr_iso target; /* destination address of pkt */
290: #define src source.siso_addr
291: #define dst target.siso_addr
292: caddr_t hoff; /* current offset in packet */
293: caddr_t hend; /* address of end of header info */
294: struct clnp_segment seg_part; /* segment part of hdr */
295: int seg_off=0; /* offset of segment part of hdr */
296: int seg_len;/* length of packet data&hdr in bytes */
297: struct clnp_optidx oidx, *oidxp = NULL; /* option index */
298: extern int iso_systype; /* used by ESIS config resp */
299: extern struct sockaddr_iso blank_siso; /* used for initializing */
300: int need_afrin = 0;
301: /* true if congestion experienced */
302: /* which means you need afrin nose */
303: /* spray. How clever! */
304:
305: IFDEBUG(D_INPUT)
306: printf(
307: "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n",
308: m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal");
309: ENDDEBUG
310: need_afrin = 0;
311:
312: /*
313: * If no iso addresses have been set, there is nothing
314: * to do with the packet.
315: */
316: if (iso_ifaddr == NULL) {
317: clnp_discard(m, ADDR_DESTUNREACH);
318: return;
319: }
320:
321: INCSTAT(cns_total);
322: clnp = mtod(m, struct clnp_fixed *);
323:
324: IFDEBUG(D_DUMPIN)
325: struct mbuf *mhead;
326: int total_len = 0;
327: printf("clnp_input: clnp header:\n");
328: dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len);
329: printf("clnp_input: mbuf chain:\n");
330: for (mhead = m; mhead != NULL; mhead=mhead->m_next) {
331: printf("m x%x, len %d\n", mhead, mhead->m_len);
332: total_len += mhead->m_len;
333: }
334: printf("clnp_input: total length of mbuf chain %d:\n", total_len);
335: ENDDEBUG
336:
337: /*
338: * Compute checksum (if necessary) and drop packet if
339: * checksum does not match
340: */
341: if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, (int)clnp->cnf_hdr_len)) {
342: INCSTAT(cns_badcsum);
343: clnp_discard(m, GEN_BADCSUM);
344: return;
345: }
346:
347: if (clnp->cnf_vers != ISO8473_V1) {
348: INCSTAT(cns_badvers);
349: clnp_discard(m, DISC_UNSUPPVERS);
350: return;
351: }
352:
353:
354: /* check mbuf data length: clnp_data_ck will free mbuf upon error */
355: CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len);
356: if ((m = clnp_data_ck(m, seg_len)) == 0)
357: return;
358:
359: clnp = mtod(m, struct clnp_fixed *);
360: hend = (caddr_t)clnp + clnp->cnf_hdr_len;
361:
362: /*
363: * extract the source and destination address
364: * drop packet on failure
365: */
366: source = target = blank_siso;
367:
368: hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
369: CLNP_EXTRACT_ADDR(dst, hoff, hend);
370: if (hoff == (caddr_t)0) {
371: INCSTAT(cns_badaddr);
372: clnp_discard(m, GEN_INCOMPLETE);
373: return;
374: }
375: CLNP_EXTRACT_ADDR(src, hoff, hend);
376: if (hoff == (caddr_t)0) {
377: INCSTAT(cns_badaddr);
378: clnp_discard(m, GEN_INCOMPLETE);
379: return;
380: }
381:
382: IFDEBUG(D_INPUT)
383: printf("clnp_input: from %s", clnp_iso_addrp(&src));
384: printf(" to %s\n", clnp_iso_addrp(&dst));
385: ENDDEBUG
386:
387: /*
388: * extract the segmentation information, if it is present.
389: * drop packet on failure
390: */
391: if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
392: (clnp->cnf_type & CNF_SEG_OK)) {
393: if (hoff + sizeof(struct clnp_segment) > hend) {
394: INCSTAT(cns_noseg);
395: clnp_discard(m, GEN_INCOMPLETE);
396: return;
397: } else {
398: (void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment));
399: /* make sure segmentation fields are in host order */
400: seg_part.cng_id = ntohs(seg_part.cng_id);
401: seg_part.cng_off = ntohs(seg_part.cng_off);
402: seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len);
403: seg_off = hoff - (caddr_t)clnp;
404: hoff += sizeof(struct clnp_segment);
405: }
406: }
407:
408: /*
409: * process options if present. If clnp_opt_sanity returns
410: * false (indicating an error was found in the options) or
411: * an unsupported option was found
412: * then drop packet and emit an ER.
413: */
414: if (hoff < hend) {
415: int errcode;
416:
417: oidxp = &oidx;
418: errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp);
419:
420: /* we do not support security */
421: if ((errcode == 0) && (oidxp->cni_securep))
422: errcode = DISC_UNSUPPSECURE;
423:
424: /* the er option is valid with ER pdus only */
425: if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) &&
426: ((clnp->cnf_type & CNF_TYPE) != CLNP_ER))
427: errcode = DISC_UNSUPPOPT;
428:
429: #ifdef DECBIT
430: /* check if the congestion experienced bit is set */
431: if (oidxp->cni_qos_formatp) {
432: caddr_t qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp);
433: u_char qos = *qosp;
434:
435: need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) ==
436: (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED));
437: if (need_afrin)
438: INCSTAT(cns_congest_rcvd);
439: }
440: #endif DECBIT
441:
442: if (errcode != 0) {
443: clnp_discard(m, (char)errcode);
444: IFDEBUG(D_INPUT)
445: printf("clnp_input: dropped (err x%x) due to bad options\n",
446: errcode);
447: ENDDEBUG
448: return;
449: }
450: }
451:
452: /*
453: * check if this packet is for us. if not, then forward
454: */
455: if (clnp_ours(&dst) == 0) {
456: IFDEBUG(D_INPUT)
457: printf("clnp_input: forwarding packet not for us\n");
458: ENDDEBUG
459: clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp);
460: return;
461: }
462:
463: /*
464: * ESIS Configuration Response Function
465: *
466: * If the packet received was sent to the multicast address
467: * all end systems, then send an esh to the source
468: */
469: if ((shp->snh_flags & M_MCAST) && (iso_systype == SNPA_ES)) {
470: extern short esis_holding_time;
471:
472: esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time,
473: shp->snh_shost, 6, &dst);
474: }
475:
476: /*
477: * If this is a fragment, then try to reassemble it. If clnp_reass
478: * returns non NULL, the packet has been reassembled, and should
479: * be give to TP. Otherwise the fragment has been delt with
480: * by the reassembly code (either stored or deleted). In either case
481: * we should have nothing more to do with it.
482: */
483: if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
484: (clnp->cnf_type & CNF_SEG_OK) &&
485: (seg_len != seg_part.cng_tot_len)) {
486: struct mbuf *m0;
487:
488: if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) {
489: m = m0;
490: clnp = mtod(m, struct clnp_fixed *);
491: INCSTAT(cns_reassembled);
492: } else {
493: return;
494: }
495: }
496:
497: /*
498: * give the packet to the higher layer
499: *
500: * Note: the total length of packet
501: * is the total length field of the segmentation part,
502: * or, if absent, the segment length field of the
503: * header.
504: */
505: INCSTAT(cns_delivered);
506: switch (clnp->cnf_type & CNF_TYPE) {
507: case CLNP_ER:
508: /*
509: * This ER must have the er option.
510: * If the option is not present, discard datagram.
511: */
512: if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) {
513: clnp_discard(m, GEN_HDRSYNTAX);
514: } else {
515: clnp_er_input(m, &src, oidxp->cni_er_reason);
516: }
517: break;
518:
519: case CLNP_DT:
520: (*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &source, &target,
521: clnp->cnf_hdr_len, need_afrin);
522: break;
523:
524: case CLNP_RAW:
525: case CLNP_ECR:
526: IFDEBUG(D_INPUT)
527: printf("clnp_input: raw input of %d bytes\n",
528: clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len);
529: ENDDEBUG
530: (*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &source, &target,
531: clnp->cnf_hdr_len);
532: break;
533:
534: case CLNP_EC:
535: IFDEBUG(D_INPUT)
536: printf("clnp_input: echoing packet\n");
537: ENDDEBUG
538: /*
539: * Switch the source and destination address,
540: */
541: hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
542: CLNP_INSERT_ADDR(hoff, src);
543: CLNP_INSERT_ADDR(hoff, dst);
544: clnp->cnf_type &= ~CNF_TYPE;
545: clnp->cnf_type |= CLNP_ECR;
546:
547: /*
548: * Forward back to sender
549: */
550: clnp_forward(m, (int)
551: (clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len),
552: &src, oidxp, seg_off, 0);
553: break;
554:
555: default:
556: printf("clnp_input: unknown clnp pkt type %d\n",
557: clnp->cnf_type & CNF_TYPE);
558: clnp_stat.cns_delivered--;
559: clnp_stat.cns_noproto++;
560: clnp_discard(m, GEN_HDRSYNTAX);
561: break;
562: }
563: }
564: #endif ISO
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.