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