|
|
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_subr.c 7.13 (Berkeley) 5/6/91
! 34: * clnp_subr.c,v 1.2 1993/05/20 05:26:57 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: #ifdef ISO
65:
66: #include "types.h"
67: #include "param.h"
68: #include "mbuf.h"
69: #include "domain.h"
70: #include "protosw.h"
71: #include "socket.h"
72: #include "socketvar.h"
73: #include "errno.h"
74: #include "time.h"
75:
76: #include "../net/if.h"
77: #include "../net/route.h"
78: #include "../net/if_dl.h"
79:
80: #include "iso.h"
81: #include "iso_var.h"
82: #include "iso_pcb.h"
83: #include "iso_snpac.h"
84: #include "clnp.h"
85: #include "clnp_stat.h"
86: #include "argo_debug.h"
87:
88: /*
89: * FUNCTION: clnp_data_ck
90: *
91: * PURPOSE: Check that the amount of data in the mbuf chain is
92: * at least as much as the clnp header would have us
93: * expect. Trim mbufs if longer than expected, drop
94: * packet if shorter than expected.
95: *
96: * RETURNS: success - ptr to mbuf chain
97: * failure - 0
98: *
99: * SIDE EFFECTS:
100: *
101: * NOTES:
102: */
103: struct mbuf *
104: clnp_data_ck(m, length)
105: register struct mbuf *m; /* ptr to mbuf chain containing hdr & data */
106: int length; /* length (in bytes) of packet */
107: {
108: register int len; /* length of data */
109: register struct mbuf *mhead; /* ptr to head of chain */
110:
111: len = -length;
112: mhead = m;
113: for (;;) {
114: len += m->m_len;
115: if (m->m_next == 0)
116: break;
117: m = m->m_next;
118: }
119: if (len != 0) {
120: if (len < 0) {
121: INCSTAT(cns_toosmall);
122: clnp_discard(mhead, GEN_INCOMPLETE);
123: return 0;
124: }
125: if (len <= m->m_len)
126: m->m_len -= len;
127: else
128: m_adj(mhead, -len);
129: }
130: return mhead;
131: }
132:
133: #ifdef notdef
134: /*
135: * FUNCTION: clnp_extract_addr
136: *
137: * PURPOSE: Extract the source and destination address from the
138: * supplied buffer. Place them in the supplied address buffers.
139: * If insufficient data is supplied, then fail.
140: *
141: * RETURNS: success - Address of first byte in the packet past
142: * the address part.
143: * failure - 0
144: *
145: * SIDE EFFECTS:
146: *
147: * NOTES:
148: */
149: caddr_t
150: clnp_extract_addr(bufp, buflen, srcp, destp)
151: caddr_t bufp; /* ptr to buffer containing addresses */
152: int buflen; /* length of buffer */
153: register struct iso_addr *srcp; /* ptr to source address buffer */
154: register struct iso_addr *destp; /* ptr to destination address buffer */
155: {
156: int len; /* argument to bcopy */
157:
158: /*
159: * check that we have enough data. Plus1 is for length octet
160: */
161: if ((u_char)*bufp + 1 > buflen) {
162: return((caddr_t)0);
163: }
164: len = destp->isoa_len = (u_char)*bufp++;
165: (void) bcopy(bufp, (caddr_t)destp, len);
166: buflen -= len;
167: bufp += len;
168:
169: /*
170: * check that we have enough data. Plus1 is for length octet
171: */
172: if ((u_char)*bufp + 1 > buflen) {
173: return((caddr_t)0);
174: }
175: len = srcp->isoa_len = (u_char)* bufp++;
176: (void) bcopy(bufp, (caddr_t)srcp, len);
177: bufp += len;
178:
179: /*
180: * Insure that the addresses make sense
181: */
182: if (iso_ck_addr(srcp) && iso_ck_addr(destp))
183: return bufp;
184: else
185: return (caddr_t) 0;
186: }
187: #endif notdef
188:
189: /*
190: * FUNCTION: clnp_ours
191: *
192: * PURPOSE: Decide whether the supplied packet is destined for
193: * us, or that it should be forwarded on.
194: *
195: * RETURNS: packet is for us - 1
196: * packet is not for us - 0
197: *
198: * SIDE EFFECTS:
199: *
200: * NOTES:
201: */
202: clnp_ours(dst)
203: register struct iso_addr *dst; /* ptr to destination address */
204: {
205: register struct iso_ifaddr *ia; /* scan through interface addresses */
206:
207: for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
208: IFDEBUG(D_ROUTE)
209: printf("clnp_ours: ia_sis x%x, dst x%x\n", &ia->ia_addr,
210: dst);
211: ENDDEBUG
212: /*
213: * XXX Warning:
214: * We are overloading siso_tlen in the if's address, as an nsel length.
215: */
216: if (dst->isoa_len == ia->ia_addr.siso_nlen &&
217: bcmp((caddr_t)ia->ia_addr.siso_addr.isoa_genaddr,
218: (caddr_t)dst->isoa_genaddr,
219: ia->ia_addr.siso_nlen - ia->ia_addr.siso_tlen) == 0)
220: return 1;
221: }
222: return 0;
223: }
224:
225: /* Dec bit set if ifp qlen is greater than congest_threshold */
226: int congest_threshold = 0;
227:
228: /*
229: * FUNCTION: clnp_forward
230: *
231: * PURPOSE: Forward the datagram passed
232: * clnpintr guarantees that the header will be
233: * contigious (a cluster mbuf will be used if necessary).
234: *
235: * If oidx is NULL, no options are present.
236: *
237: * RETURNS: nothing
238: *
239: * SIDE EFFECTS:
240: *
241: * NOTES:
242: */
243: clnp_forward(m, len, dst, oidx, seg_off, inbound_shp)
244: struct mbuf *m; /* pkt to forward */
245: int len; /* length of pkt */
246: struct iso_addr *dst; /* destination address */
247: struct clnp_optidx *oidx; /* option index */
248: int seg_off;/* offset of segmentation part */
249: struct snpa_hdr *inbound_shp; /* subnetwork header of inbound packet */
250: {
251: struct clnp_fixed *clnp; /* ptr to fixed part of header */
252: int error; /* return value of route function */
253: struct sockaddr *next_hop; /* next hop for dgram */
254: struct ifnet *ifp; /* ptr to outgoing interface */
255: struct iso_ifaddr *ia = 0;/* ptr to iso name for ifp */
256: struct route_iso route; /* filled in by clnp_route */
257: extern int iso_systype;
258:
259: clnp = mtod(m, struct clnp_fixed *);
260: bzero((caddr_t)&route, sizeof(route)); /* MUST be done before "bad:" */
261:
262: /*
263: * Don't forward multicast or broadcast packets
264: */
265: if ((inbound_shp) && (IS_MULTICAST(inbound_shp->snh_dhost))) {
266: IFDEBUG(D_FORWARD)
267: printf("clnp_forward: dropping multicast packet\n");
268: ENDDEBUG
269: clnp->cnf_type &= ~CNF_ERR_OK; /* so we don't generate an ER */
270: clnp_discard(m, 0);
271: INCSTAT(cns_cantforward);
272: goto done;
273: }
274:
275: IFDEBUG(D_FORWARD)
276: printf("clnp_forward: %d bytes, to %s, options x%x\n", len,
277: clnp_iso_addrp(dst), oidx);
278: ENDDEBUG
279:
280: /*
281: * Decrement ttl, and if zero drop datagram
282: * Can't compare ttl as less than zero 'cause its a unsigned
283: */
284: if ((clnp->cnf_ttl == 0) || (--clnp->cnf_ttl == 0)) {
285: IFDEBUG(D_FORWARD)
286: printf("clnp_forward: discarding datagram because ttl is zero\n");
287: ENDDEBUG
288: INCSTAT(cns_ttlexpired);
289: clnp_discard(m, TTL_EXPTRANSIT);
290: goto done;
291: }
292: /*
293: * Route packet; special case for source rt
294: */
295: if CLNPSRCRT_VALID(oidx) {
296: /*
297: * Update src route first
298: */
299: clnp_update_srcrt(m, oidx);
300: error = clnp_srcroute(m, oidx, &route, &next_hop, &ia, dst);
301: } else {
302: error = clnp_route(dst, &route, 0, &next_hop, &ia);
303: }
304: if (error || ia == 0) {
305: IFDEBUG(D_FORWARD)
306: printf("clnp_forward: can't route packet (errno %d)\n", error);
307: ENDDEBUG
308: clnp_discard(m, ADDR_DESTUNREACH);
309: INCSTAT(cns_cantforward);
310: goto done;
311: }
312: ifp = ia->ia_ifp;
313:
314: IFDEBUG(D_FORWARD)
315: printf("clnp_forward: packet routed to %s\n",
316: clnp_iso_addrp(&((struct sockaddr_iso *)next_hop)->siso_addr));
317: ENDDEBUG
318:
319: INCSTAT(cns_forward);
320:
321: /*
322: * If we are an intermediate system and
323: * we are routing outbound on the same ifp that the packet
324: * arrived upon, and we know the next hop snpa,
325: * then generate a redirect request
326: */
327: if ((iso_systype & SNPA_IS) && (inbound_shp) &&
328: (ifp == inbound_shp->snh_ifp))
329: esis_rdoutput(inbound_shp, m, oidx, dst, route.ro_rt);
330: /*
331: * If options are present, update them
332: */
333: if (oidx) {
334: struct iso_addr *mysrc = &ia->ia_addr.siso_addr;
335: if (mysrc == NULL) {
336: clnp_discard(m, ADDR_DESTUNREACH);
337: INCSTAT(cns_cantforward);
338: clnp_stat.cns_forward--;
339: goto done;
340: } else {
341: (void) clnp_dooptions(m, oidx, ifp, mysrc);
342: }
343: }
344:
345: #ifdef DECBIT
346: if (ifp->if_snd.ifq_len > congest_threshold) {
347: /*
348: * Congestion! Set the Dec Bit and thank Dave Oran
349: */
350: IFDEBUG(D_FORWARD)
351: printf("clnp_forward: congestion experienced\n");
352: ENDDEBUG
353: if ((oidx) && (oidx->cni_qos_formatp)) {
354: caddr_t qosp = CLNP_OFFTOOPT(m, oidx->cni_qos_formatp);
355: u_char qos = *qosp;
356: IFDEBUG(D_FORWARD)
357: printf("clnp_forward: setting congestion bit (qos x%x)\n", qos);
358: ENDDEBUG
359: if ((qos & CLNPOVAL_GLOBAL) == CLNPOVAL_GLOBAL) {
360: qos |= CLNPOVAL_CONGESTED;
361: INCSTAT(cns_congest_set);
362: *qosp = qos;
363: }
364: }
365: }
366: #endif DECBIT
367:
368: /*
369: * Dispatch the datagram if it is small enough, otherwise fragment
370: */
371: if (len <= SN_MTU(ifp, route.ro_rt)) {
372: iso_gen_csum(m, CLNP_CKSUM_OFF, (int)clnp->cnf_hdr_len);
373: (void) (*ifp->if_output)(ifp, m, next_hop, route.ro_rt);
374: } else {
375: (void) clnp_fragment(ifp, m, next_hop, len, seg_off, /* flags */0, route.ro_rt);
376: }
377:
378: done:
379: /*
380: * Free route
381: */
382: if (route.ro_rt != NULL) {
383: RTFREE(route.ro_rt);
384: }
385: }
386:
387: #ifdef notdef
388: /*
389: * FUNCTION: clnp_insert_addr
390: *
391: * PURPOSE: Insert the address part into a clnp datagram.
392: *
393: * RETURNS: Address of first byte after address part in datagram.
394: *
395: * SIDE EFFECTS:
396: *
397: * NOTES: Assume that there is enough space for the address part.
398: */
399: caddr_t
400: clnp_insert_addr(bufp, srcp, dstp)
401: caddr_t bufp; /* address of where addr part goes */
402: register struct iso_addr *srcp; /* ptr to src addr */
403: register struct iso_addr *dstp; /* ptr to dst addr */
404: {
405: *bufp++ = dstp->isoa_len;
406: (void) bcopy((caddr_t)dstp, bufp, dstp->isoa_len);
407: bufp += dstp->isoa_len;
408:
409: *bufp++ = srcp->isoa_len;
410: (void) bcopy((caddr_t)srcp, bufp, srcp->isoa_len);
411: bufp += srcp->isoa_len;
412:
413: return bufp;
414: }
415:
416: #endif notdef
417:
418: /*
419: * FUNCTION: clnp_route
420: *
421: * PURPOSE: Route a clnp datagram to the first hop toward its
422: * destination. In many cases, the first hop will be
423: * the destination. The address of a route
424: * is specified. If a routing entry is present in
425: * that route, and it is still up to the same destination,
426: * then no further action is necessary. Otherwise, a
427: * new routing entry will be allocated.
428: *
429: * RETURNS: route found - 0
430: * unix error code
431: *
432: * SIDE EFFECTS:
433: *
434: * NOTES: It is up to the caller to free the routing entry
435: * allocated in route.
436: */
437: clnp_route(dst, ro, flags, first_hop, ifa)
438: struct iso_addr *dst; /* ptr to datagram destination */
439: register struct route_iso *ro; /* existing route structure */
440: int flags; /* flags for routing */
441: struct sockaddr **first_hop; /* result: fill in with ptr to firsthop */
442: struct iso_ifaddr **ifa; /* result: fill in with ptr to interface */
443: {
444: if (flags & SO_DONTROUTE) {
445: struct iso_ifaddr *ia;
446:
447: if (ro->ro_rt) {
448: RTFREE(ro->ro_rt);
449: ro->ro_rt = 0;
450: }
451: bzero((caddr_t)&ro->ro_dst, sizeof(ro->ro_dst));
452: bcopy((caddr_t)dst, (caddr_t)&ro->ro_dst.siso_addr,
453: 1 + (unsigned)dst->isoa_len);
454: ro->ro_dst.siso_family = AF_ISO;
455: ro->ro_dst.siso_len = sizeof(ro->ro_dst);
456: ia = iso_localifa(&ro->ro_dst);
457: if (ia == 0)
458: return EADDRNOTAVAIL;
459: if (ifa)
460: *ifa = ia;
461: if (first_hop)
462: *first_hop = (struct sockaddr *)&ro->ro_dst;
463: return 0;
464: }
465: /*
466: * If there is a cached route, check that it is still up and to
467: * the same destination. If not, free it and try again.
468: */
469: if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
470: (Bcmp(ro->ro_dst.siso_data, dst->isoa_genaddr, dst->isoa_len)))) {
471: IFDEBUG(D_ROUTE)
472: printf("clnp_route: freeing old route: ro->ro_rt 0x%x\n",
473: ro->ro_rt);
474: printf("clnp_route: old route refcnt: 0x%x\n",
475: ro->ro_rt->rt_refcnt);
476: ENDDEBUG
477:
478: /* free old route entry */
479: RTFREE(ro->ro_rt);
480: ro->ro_rt = (struct rtentry *)0;
481: } else {
482: IFDEBUG(D_ROUTE)
483: printf("clnp_route: OK route exists\n");
484: ENDDEBUG
485: }
486:
487: if (ro->ro_rt == 0) {
488: /* set up new route structure */
489: bzero((caddr_t)&ro->ro_dst, sizeof(ro->ro_dst));
490: ro->ro_dst.siso_len = sizeof(ro->ro_dst);
491: ro->ro_dst.siso_family = AF_ISO;
492: Bcopy(dst, &ro->ro_dst.siso_addr, 1 + dst->isoa_len);
493: /* allocate new route */
494: IFDEBUG(D_ROUTE)
495: printf("clnp_route: allocating new route to %s\n",
496: clnp_iso_addrp(dst));
497: ENDDEBUG
498: rtalloc((struct route *)ro);
499: }
500: if (ro->ro_rt == 0)
501: return(ENETUNREACH); /* rtalloc failed */
502: ro->ro_rt->rt_use++;
503: if (ifa)
504: if ((*ifa = (struct iso_ifaddr *)ro->ro_rt->rt_ifa) == 0)
505: panic("clnp_route");
506: if (first_hop) {
507: if (ro->ro_rt->rt_flags & RTF_GATEWAY)
508: *first_hop = ro->ro_rt->rt_gateway;
509: else
510: *first_hop = (struct sockaddr *)&ro->ro_dst;
511: }
512: return(0);
513: }
514:
515: /*
516: * FUNCTION: clnp_srcroute
517: *
518: * PURPOSE: Source route the datagram. If complete source
519: * routing is specified but not possible, then
520: * return an error. If src routing is terminated, then
521: * try routing on destination.
522: * Usage of first_hop,
523: * ifp, and error return is identical to clnp_route.
524: *
525: * RETURNS: 0 or unix error code
526: *
527: * SIDE EFFECTS:
528: *
529: * NOTES: Remember that option index pointers are really
530: * offsets from the beginning of the mbuf.
531: */
532: clnp_srcroute(options, oidx, ro, first_hop, ifa, final_dst)
533: struct mbuf *options; /* ptr to options */
534: struct clnp_optidx *oidx; /* index to options */
535: struct route_iso *ro; /* route structure */
536: struct sockaddr **first_hop; /* RETURN: fill in with ptr to firsthop */
537: struct iso_ifaddr **ifa; /* RETURN: fill in with ptr to interface */
538: struct iso_addr *final_dst; /* final destination */
539: {
540: struct iso_addr dst; /* first hop specified by src rt */
541: int error = 0; /* return code */
542:
543: /*
544: * Check if we have run out of routes
545: * If so, then try to route on destination.
546: */
547: if CLNPSRCRT_TERM(oidx, options) {
548: dst.isoa_len = final_dst->isoa_len;
549: bcopy(final_dst->isoa_genaddr, dst.isoa_genaddr, dst.isoa_len);
550: } else {
551: /*
552: * setup dst based on src rt specified
553: */
554: dst.isoa_len = CLNPSRCRT_CLEN(oidx, options);
555: bcopy(CLNPSRCRT_CADDR(oidx, options), dst.isoa_genaddr, dst.isoa_len);
556: }
557:
558: /*
559: * try to route it
560: */
561: error = clnp_route(&dst, ro, 0, first_hop, ifa);
562: if (error != 0)
563: return error;
564:
565: /*
566: * If complete src rt, first hop must be equal to dst
567: */
568: if ((CLNPSRCRT_TYPE(oidx, options) == CLNPOVAL_COMPRT) &&
569: (!iso_addrmatch1(&(*(struct sockaddr_iso **)first_hop)->siso_addr,&dst))){
570: IFDEBUG(D_OPTIONS)
571: printf("clnp_srcroute: complete src route failed\n");
572: ENDDEBUG
573: return EHOSTUNREACH; /* RAH? would like ESRCRTFAILED */
574: }
575:
576: return error;
577: }
578:
579: /*
580: * FUNCTION: clnp_badmtu
581: *
582: * PURPOSE: print notice of route with mtu not initialized.
583: *
584: * RETURNS: mtu of ifp.
585: *
586: * SIDE EFFECTS: prints notice, slows down system.
587: */
588: clnp_badmtu(ifp, rt, line, file)
589: struct ifnet *ifp; /* outgoing interface */
590: struct rtentry *rt; /* dst route */
591: int line; /* where the dirty deed occured */
592: char *file; /* where the dirty deed occured */
593: {
594: printf("sending on route %x with no mtu, line %s of file %s\n",
595: rt, line, file);
596: #ifdef ARGO_DEBUG
597: printf("route dst is");
598: dump_isoaddr(rt_key(rt));
599: #endif
600: return ifp->if_mtu;
601: }
602:
603: /*
604: * FUNCTION: clnp_ypocb - backwards bcopy
605: *
606: * PURPOSE: bcopy starting at end of src rather than beginning.
607: *
608: * RETURNS: none
609: *
610: * SIDE EFFECTS:
611: *
612: * NOTES: No attempt has been made to make this efficient
613: */
614: clnp_ypocb(from, to, len)
615: caddr_t from; /* src buffer */
616: caddr_t to; /* dst buffer */
617: u_int len; /* number of bytes */
618: {
619: while (len--)
620: *(to + len) = *(from + len);
621: }
622: #endif ISO
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.