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