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