1 /* $NetBSD: clnp_subr.c,v 1.15.2.1 2007/03/29 08:57:16 ghen Exp $ */
2
3 /*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * @(#)clnp_subr.c 8.1 (Berkeley) 6/10/93
32 */
33
34 /***********************************************************
35 Copyright IBM Corporation 1987
36
37 All Rights Reserved
38
39 Permission to use, copy, modify, and distribute this software and its
40 documentation for any purpose and without fee is hereby granted,
41 provided that the above copyright notice appear in all copies and that
42 both that copyright notice and this permission notice appear in
43 supporting documentation, and that the name of IBM not be
44 used in advertising or publicity pertaining to distribution of the
45 software without specific, written prior permission.
46
47 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
48 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
49 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
50 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
51 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
52 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 SOFTWARE.
54
55 ******************************************************************/
56
57 /*
58 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
59 */
60
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: clnp_subr.c,v 1.15.2.1 2007/03/29 08:57:16 ghen Exp $");
63
64 #include "opt_iso.h"
65
66 #ifdef ISO
67
68 #include <sys/param.h>
69 #include <sys/mbuf.h>
70 #include <sys/domain.h>
71 #include <sys/protosw.h>
72 #include <sys/socket.h>
73 #include <sys/socketvar.h>
74 #include <sys/errno.h>
75 #include <sys/time.h>
76 #include <sys/systm.h>
77
78 #include <net/if.h>
79 #include <net/route.h>
80 #include <net/if_dl.h>
81
82 #include <netiso/iso.h>
83 #include <netiso/iso_var.h>
84 #include <netiso/iso_pcb.h>
85 #include <netiso/iso_snpac.h>
86 #include <netiso/clnp.h>
87 #include <netiso/clnp_stat.h>
88 #include <netiso/argo_debug.h>
89 #include <netiso/esis.h>
90
91 /*
92 * FUNCTION: clnp_data_ck
93 *
94 * PURPOSE: Check that the amount of data in the mbuf chain is
95 * at least as much as the clnp header would have us
96 * expect. Trim mbufs if longer than expected, drop
97 * packet if shorter than expected.
98 *
99 * RETURNS: success - ptr to mbuf chain
100 * failure - 0
101 *
102 * SIDE EFFECTS:
103 *
104 * NOTES:
105 */
106 struct mbuf *
107 clnp_data_ck(m, length)
108 struct mbuf *m;/* ptr to mbuf chain containing hdr & data */
109 int length; /* length (in bytes) of packet */
110 {
111 int len; /* length of data */
112 struct mbuf *mhead; /* ptr to head of chain */
113
114 len = -length;
115 mhead = m;
116 for (;;) {
117 len += m->m_len;
118 if (m->m_next == 0)
119 break;
120 m = m->m_next;
121 }
122 if (len != 0) {
123 if (len < 0) {
124 INCSTAT(cns_toosmall);
125 clnp_discard(mhead, GEN_INCOMPLETE);
126 return 0;
127 }
128 if (len <= m->m_len)
129 m->m_len -= len;
130 else
131 m_adj(mhead, -len);
132 }
133 return mhead;
134 }
135
136 #ifdef notdef
137 /*
138 * FUNCTION: clnp_extract_addr
139 *
140 * PURPOSE: Extract the source and destination address from the
141 * supplied buffer. Place them in the supplied address buffers.
142 * If insufficient data is supplied, then fail.
143 *
144 * RETURNS: success - Address of first byte in the packet past
145 * the address part.
146 * failure - 0
147 *
148 * SIDE EFFECTS:
149 *
150 * NOTES:
151 */
152 caddr_t
153 clnp_extract_addr(bufp, buflen, srcp, destp)
154 caddr_t bufp; /* ptr to buffer containing addresses */
155 int buflen; /* length of buffer */
156 struct iso_addr *srcp; /* ptr to source address buffer */
157 struct iso_addr *destp; /* ptr to destination address
158 * buffer */
159 {
160 size_t len; /* argument to memcpy */
161
162 /*
163 * check that we have enough data. Plus1 is for length octet
164 */
165 len = (u_char)*bufp++;
166 if (len > buflen)
167 return NULL;
168 destp->isoa_len = len;
169 (void)memcpy(destp, bufp, len);
170 buflen -= len;
171 bufp += len;
172
173 /*
174 * check that we have enough data. Plus1 is for length octet
175 */
176 len = (u_char)*bufp++;
177 if (len > buflen)
178 return NULL;
179 srcp->isoa_len = len;
180 (void)memcpy(srcp, bufp, len);
181 bufp += len;
182
183 /*
184 * Insure that the addresses make sense
185 */
186 if (iso_ck_addr(srcp) && iso_ck_addr(destp))
187 return bufp;
188 else
189 return NULL;
190 }
191 #endif /* notdef */
192
193 /*
194 * FUNCTION: clnp_ours
195 *
196 * PURPOSE: Decide whether the supplied packet is destined for
197 * us, or that it should be forwarded on.
198 *
199 * RETURNS: packet is for us - 1
200 * packet is not for us - 0
201 *
202 * SIDE EFFECTS:
203 *
204 * NOTES:
205 */
206 int
207 clnp_ours(dst)
208 struct iso_addr *dst; /* ptr to destination address */
209 {
210 struct iso_ifaddr *ia; /* scan through interface addresses */
211
212 for (ia = iso_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next) {
213 #ifdef ARGO_DEBUG
214 if (argo_debug[D_ROUTE]) {
215 printf("clnp_ours: ia_sis %p, dst %p\n",
216 &ia->ia_addr, dst);
217 }
218 #endif
219 /*
220 * XXX Warning:
221 * We are overloading siso_tlen in the if's address, as an nsel length.
222 */
223 if (dst->isoa_len == ia->ia_addr.siso_nlen &&
224 bcmp((caddr_t) ia->ia_addr.siso_addr.isoa_genaddr,
225 (caddr_t) dst->isoa_genaddr,
226 ia->ia_addr.siso_nlen - ia->ia_addr.siso_tlen) == 0)
227 return 1;
228 }
229 return 0;
230 }
231
232 /* Dec bit set if ifp qlen is greater than congest_threshold */
233 int congest_threshold = 0;
234
235 /*
236 * FUNCTION: clnp_forward
237 *
238 * PURPOSE: Forward the datagram passed
239 * clnpintr guarantees that the header will be
240 * contigious (a cluster mbuf will be used if necessary).
241 *
242 * If oidx is NULL, no options are present.
243 *
244 * RETURNS: nothing
245 *
246 * SIDE EFFECTS:
247 *
248 * NOTES:
249 */
250 void
251 clnp_forward(m, len, dst, oidx, seg_off, inbound_shp)
252 struct mbuf *m; /* pkt to forward */
253 int len; /* length of pkt */
254 struct iso_addr *dst; /* destination address */
255 struct clnp_optidx *oidx; /* option index */
256 int seg_off;/* offset of segmentation part */
257 struct snpa_hdr *inbound_shp; /* subnetwork header of inbound
258 * packet */
259 {
260 struct clnp_fixed *clnp;/* ptr to fixed part of header */
261 int error; /* return value of route function */
262 struct sockaddr *next_hop; /* next hop for dgram */
263 struct ifnet *ifp; /* ptr to outgoing interface */
264 struct iso_ifaddr *ia = 0; /* ptr to iso name for ifp */
265 struct route_iso route; /* filled in by clnp_route */
266 extern int iso_systype;
267
268 clnp = mtod(m, struct clnp_fixed *);
269 bzero((caddr_t) & route, sizeof(route)); /* MUST be done before
270 * "bad:" */
271
272 /*
273 * Don't forward multicast or broadcast packets
274 */
275 if ((inbound_shp) && (IS_MULTICAST(inbound_shp->snh_dhost))) {
276 #ifdef ARGO_DEBUG
277 if (argo_debug[D_FORWARD]) {
278 printf("clnp_forward: dropping multicast packet\n");
279 }
280 #endif
281 clnp->cnf_type &= ~CNF_ERR_OK; /* so we don't generate an ER */
282 clnp_discard(m, 0);
283 INCSTAT(cns_cantforward);
284 goto done;
285 }
286 #ifdef ARGO_DEBUG
287 if (argo_debug[D_FORWARD]) {
288 printf("clnp_forward: %d bytes, to %s, options %p\n", len,
289 clnp_iso_addrp(dst), oidx);
290 }
291 #endif
292
293 /*
294 * Decrement ttl, and if zero drop datagram
295 * Can't compare ttl as less than zero 'cause its a unsigned
296 */
297 if ((clnp->cnf_ttl == 0) || (--clnp->cnf_ttl == 0)) {
298 #ifdef ARGO_DEBUG
299 if (argo_debug[D_FORWARD]) {
300 printf("clnp_forward: discarding datagram because ttl is zero\n");
301 }
302 #endif
303 INCSTAT(cns_ttlexpired);
304 clnp_discard(m, TTL_EXPTRANSIT);
305 goto done;
306 }
307 /*
308 * Route packet; special case for source rt
309 */
310 if CLNPSRCRT_VALID
311 (oidx) {
312 /*
313 * Update src route first
314 */
315 clnp_update_srcrt(m, oidx);
316 error = clnp_srcroute(m, oidx, &route, &next_hop, &ia, dst);
317 } else {
318 error = clnp_route(dst, &route, 0, &next_hop, &ia);
319 }
320 if (error || ia == 0) {
321 #ifdef ARGO_DEBUG
322 if (argo_debug[D_FORWARD]) {
323 printf("clnp_forward: can't route packet (errno %d)\n", error);
324 }
325 #endif
326 clnp_discard(m, ADDR_DESTUNREACH);
327 INCSTAT(cns_cantforward);
328 goto done;
329 }
330 ifp = ia->ia_ifp;
331
332 #ifdef ARGO_DEBUG
333 if (argo_debug[D_FORWARD]) {
334 printf("clnp_forward: packet routed to %s\n",
335 clnp_iso_addrp(&satosiso(next_hop)->siso_addr));
336 }
337 #endif
338
339 INCSTAT(cns_forward);
340
341 /*
342 * If we are an intermediate system and
343 * we are routing outbound on the same ifp that the packet
344 * arrived upon, and we know the next hop snpa,
345 * then generate a redirect request
346 */
347 if ((iso_systype & SNPA_IS) && (inbound_shp) &&
348 (ifp == inbound_shp->snh_ifp))
349 esis_rdoutput(inbound_shp, m, oidx, dst, route.ro_rt);
350 /*
351 * If options are present, update them
352 */
353 if (oidx) {
354 struct iso_addr *mysrc = &ia->ia_addr.siso_addr;
355 if (mysrc == NULL) {
356 clnp_discard(m, ADDR_DESTUNREACH);
357 INCSTAT(cns_cantforward);
358 clnp_stat.cns_forward--;
359 goto done;
360 } else {
361 (void) clnp_dooptions(m, oidx, ifp, mysrc);
362 }
363 }
364 #ifdef DECBIT
365 if (ifp->if_snd.ifq_len > congest_threshold) {
366 /*
367 * Congestion! Set the Dec Bit and thank Dave Oran
368 */
369 #ifdef ARGO_DEBUG
370 if (argo_debug[D_FORWARD]) {
371 printf("clnp_forward: congestion experienced\n");
372 }
373 #endif
374 if ((oidx) && (oidx->cni_qos_formatp)) {
375 caddr_t qosp = CLNP_OFFTOOPT(m, oidx->cni_qos_formatp);
376 u_char qos = *qosp;
377 #ifdef ARGO_DEBUG
378 if (argo_debug[D_FORWARD]) {
379 printf("clnp_forward: setting congestion bit (qos x%x)\n", qos);
380 }
381 #endif
382 if ((qos & CLNPOVAL_GLOBAL) == CLNPOVAL_GLOBAL) {
383 qos |= CLNPOVAL_CONGESTED;
384 INCSTAT(cns_congest_set);
385 *qosp = qos;
386 }
387 }
388 }
389 #endif /* DECBIT */
390
391 /*
392 * Dispatch the datagram if it is small enough, otherwise fragment
393 */
394 if (len <= SN_MTU(ifp, route.ro_rt)) {
395 iso_gen_csum(m, CLNP_CKSUM_OFF, (int) clnp->cnf_hdr_len);
396 (void) (*ifp->if_output) (ifp, m, next_hop, route.ro_rt);
397 } else {
398 (void) clnp_fragment(ifp, m, next_hop, len, seg_off, /* flags */ 0, route.ro_rt);
399 }
400
401 done:
402 /*
403 * Free route
404 */
405 if (route.ro_rt != NULL) {
406 RTFREE(route.ro_rt);
407 }
408 }
409
410 #ifdef notdef
411 /*
412 * FUNCTION: clnp_insert_addr
413 *
414 * PURPOSE: Insert the address part into a clnp datagram.
415 *
416 * RETURNS: Address of first byte after address part in datagram.
417 *
418 * SIDE EFFECTS:
419 *
420 * NOTES: Assume that there is enough space for the address part.
421 */
422 caddr_t
423 clnp_insert_addr(bufp, srcp, dstp)
424 caddr_t bufp; /* address of where addr part goes */
425 struct iso_addr *srcp; /* ptr to src addr */
426 struct iso_addr *dstp; /* ptr to dst addr */
427 {
428 *bufp++ = dstp->isoa_len;
429 (void)memcpy(bufp, dstp, dstp->isoa_len);
430 bufp += dstp->isoa_len;
431
432 *bufp++ = srcp->isoa_len;
433 (void)memcpy(bufp, srcp, srcp->isoa_len);
434 bufp += srcp->isoa_len;
435
436 return bufp;
437 }
438
439 #endif /* notdef */
440
441 /*
442 * FUNCTION: clnp_route
443 *
444 * PURPOSE: Route a clnp datagram to the first hop toward its
445 * destination. In many cases, the first hop will be
446 * the destination. The address of a route
447 * is specified. If a routing entry is present in
448 * that route, and it is still up to the same destination,
449 * then no further action is necessary. Otherwise, a
450 * new routing entry will be allocated.
451 *
452 * RETURNS: route found - 0
453 * unix error code
454 *
455 * SIDE EFFECTS:
456 *
457 * NOTES: It is up to the caller to free the routing entry
458 * allocated in route.
459 */
460 int
461 clnp_route(dst, ro, flags, first_hop, ifa)
462 struct iso_addr *dst; /* ptr to datagram destination */
463 struct route_iso *ro; /* existing route structure */
464 int flags; /* flags for routing */
465 struct sockaddr **first_hop; /* result: fill in with ptr to
466 * firsthop */
467 struct iso_ifaddr **ifa;/* result: fill in with ptr to interface */
468 {
469 if (flags & SO_DONTROUTE) {
470 struct iso_ifaddr *ia;
471 size_t len = 1 + (unsigned)dst->isoa_len;
472
473 if (ro->ro_rt) {
474 RTFREE(ro->ro_rt);
475 ro->ro_rt = 0;
476 }
477 if (sizeof(ro->ro_dst.siso_addr) < len)
478 return EINVAL;
479 (void)memset(&ro->ro_dst, 0, sizeof(ro->ro_dst));
480 (void)memcpy(&ro->ro_dst.siso_addr, dst, len);
481 ro->ro_dst.siso_family = AF_ISO;
482 ro->ro_dst.siso_len = sizeof(ro->ro_dst);
483 ia = iso_localifa(&ro->ro_dst);
484 if (ia == 0)
485 return EADDRNOTAVAIL;
486 if (ifa)
487 *ifa = ia;
488 if (first_hop)
489 *first_hop = sisotosa(&ro->ro_dst);
490 return 0;
491 }
492 /*
493 * If there is a cached route, check that it is still up and to
494 * the same destination. If not, free it and try again.
495 */
496 if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
497 (Bcmp(ro->ro_dst.siso_data, dst->isoa_genaddr, dst->isoa_len)))) {
498 #ifdef ARGO_DEBUG
499 if (argo_debug[D_ROUTE]) {
500 printf("clnp_route: freeing old route: ro->ro_rt %p\n",
501 ro->ro_rt);
502 printf("clnp_route: old route refcnt: 0x%x\n",
503 ro->ro_rt->rt_refcnt);
504 }
505 #endif
506
507 /* free old route entry */
508 RTFREE(ro->ro_rt);
509 ro->ro_rt = (struct rtentry *) 0;
510 } else {
511 #ifdef ARGO_DEBUG
512 if (argo_debug[D_ROUTE]) {
513 printf("clnp_route: OK route exists\n");
514 }
515 #endif
516 }
517
518 if (ro->ro_rt == 0) {
519 size_t len = 1 + (unsigned)dst->isoa_len;
520
521 /* set up new route structure */
522 if (sizeof(ro->ro_dst.siso_addr) < len)
523 return EINVAL;
524 (void)memset(&ro->ro_dst, 0, sizeof(ro->ro_dst));
525 ro->ro_dst.siso_len = sizeof(ro->ro_dst);
526 ro->ro_dst.siso_family = AF_ISO;
527 (void)memcpy(&ro->ro_dst.siso_addr, dst, len);
528 /* allocate new route */
529 #ifdef ARGO_DEBUG
530 if (argo_debug[D_ROUTE]) {
531 printf("clnp_route: allocating new route to %s\n",
532 clnp_iso_addrp(dst));
533 }
534 #endif
535 rtalloc((struct route *) ro);
536 }
537 if (ro->ro_rt == 0)
538 return (ENETUNREACH); /* rtalloc failed */
539 ro->ro_rt->rt_use++;
540 if (ifa)
541 if ((*ifa = (struct iso_ifaddr *) ro->ro_rt->rt_ifa) == 0)
542 panic("clnp_route");
543 if (first_hop) {
544 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
545 *first_hop = ro->ro_rt->rt_gateway;
546 else
547 *first_hop = sisotosa(&ro->ro_dst);
548 }
549 return (0);
550 }
551
552 /*
553 * FUNCTION: clnp_srcroute
554 *
555 * PURPOSE: Source route the datagram. If complete source
556 * routing is specified but not possible, then
557 * return an error. If src routing is terminated, then
558 * try routing on destination.
559 * Usage of first_hop,
560 * ifp, and error return is identical to clnp_route.
561 *
562 * RETURNS: 0 or unix error code
563 *
564 * SIDE EFFECTS:
565 *
566 * NOTES: Remember that option index pointers are really
567 * offsets from the beginning of the mbuf.
568 */
569 int
570 clnp_srcroute(options, oidx, ro, first_hop, ifa, final_dst)
571 struct mbuf *options;/* ptr to options */
572 struct clnp_optidx *oidx; /* index to options */
573 struct route_iso *ro; /* route structure */
574 struct sockaddr **first_hop; /* RETURN: fill in with ptr to
575 * firsthop */
576 struct iso_ifaddr **ifa;/* RETURN: fill in with ptr to interface */
577 struct iso_addr *final_dst; /* final destination */
578 {
579 struct iso_addr dst; /* first hop specified by src rt */
580 int error = 0; /* return code */
581
582 /*
583 * Check if we have run out of routes
584 * If so, then try to route on destination.
585 */
586 if CLNPSRCRT_TERM
587 (oidx, options) {
588 dst.isoa_len = final_dst->isoa_len;
589 if (sizeof(dst.isoa_genaddr) < (size_t)dst.isoa_len)
590 return EINVAL;
591 (void)memcpy(dst.isoa_genaddr, final_dst->isoa_genaddr,
592 (size_t)dst.isoa_len);
593 } else {
594 /*
595 * setup dst based on src rt specified
596 */
597 dst.isoa_len = CLNPSRCRT_CLEN(oidx, options);
598 if (sizeof(dst.isoa_genaddr) < (unsigned)dst.isoa_len)
599 return EINVAL;
600 (void)memcpy(dst.isoa_genaddr, CLNPSRCRT_CADDR(oidx, options),
601 (size_t)dst.isoa_len);
602 }
603
604 /*
605 * try to route it
606 */
607 error = clnp_route(&dst, ro, 0, first_hop, ifa);
608 if (error != 0)
609 return error;
610
611 /*
612 * If complete src rt, first hop must be equal to dst
613 */
614 if ((CLNPSRCRT_TYPE(oidx, options) == CLNPOVAL_COMPRT) &&
615 (!iso_addrmatch1(&satosiso(*first_hop)->siso_addr, &dst))) {
616 #ifdef ARGO_DEBUG
617 if (argo_debug[D_OPTIONS]) {
618 printf("clnp_srcroute: complete src route failed\n");
619 }
620 #endif
621 return EHOSTUNREACH; /* RAH? would like ESRCRTFAILED */
622 }
623 return error;
624 }
625
626 /*
627 * FUNCTION: clnp_echoreply
628 *
629 * PURPOSE: generate an echo reply packet and transmit
630 *
631 * RETURNS: result of clnp_output
632 *
633 * SIDE EFFECTS:
634 */
635 int
636 clnp_echoreply(ec_m, ec_len, ec_src, ec_dst, ec_oidxp)
637 struct mbuf *ec_m; /* echo request */
638 int ec_len; /* length of ec */
639 struct sockaddr_iso *ec_src; /* src of ec */
640 struct sockaddr_iso *ec_dst; /* destination of ec (i.e., us) */
641 struct clnp_optidx *ec_oidxp; /* options index to ec packet */
642 {
643 struct isopcb isopcb;
644 int flags = CLNP_NOCACHE | CLNP_ECHOR;
645 int ret;
646
647 /* fill in fake isopcb to pass to output function */
648 bzero(&isopcb, sizeof(isopcb));
649 isopcb.isop_laddr = ec_dst;
650 isopcb.isop_faddr = ec_src;
651
652 /*
653 * forget copying the options for now. If implemented, need only copy
654 * record route option, but it must be reset to zero length
655 */
656
657 ret = clnp_output(ec_m, &isopcb, ec_len, flags);
658
659 #ifdef ARGO_DEBUG
660 if (argo_debug[D_OUTPUT]) {
661 printf("clnp_echoreply: output returns %d\n", ret);
662 }
663 #endif
664 return ret;
665 }
666
667 /*
668 * FUNCTION: clnp_badmtu
669 *
670 * PURPOSE: print notice of route with mtu not initialized.
671 *
672 * RETURNS: mtu of ifp.
673 *
674 * SIDE EFFECTS: prints notice, slows down system.
675 */
676 int
677 clnp_badmtu(ifp, rt, line, file)
678 struct ifnet *ifp; /* outgoing interface */
679 struct rtentry *rt; /* dst route */
680 int line; /* where the dirty deed occurred */
681 char *file; /* where the dirty deed occurred */
682 {
683 printf("sending on route %p with no mtu, line %d of file %s\n",
684 rt, line, file);
685 #ifdef ARGO_DEBUG
686 printf("route dst is ");
687 dump_isoaddr((struct sockaddr_iso *) rt_key(rt));
688 #endif
689 return ifp->if_mtu;
690 }
691
692 /*
693 * FUNCTION: clnp_ypocb - backwards bcopy
694 *
695 * PURPOSE: bcopy starting at end of src rather than beginning.
696 *
697 * RETURNS: none
698 *
699 * SIDE EFFECTS:
700 *
701 * NOTES: No attempt has been made to make this efficient
702 */
703 void
704 clnp_ypocb(from, to, len)
705 caddr_t from; /* src buffer */
706 caddr_t to; /* dst buffer */
707 u_int len; /* number of bytes */
708 {
709 while (len--)
710 *(to + len) = *(from + len);
711 }
712 #endif /* ISO */
Cache object: 7e5876a5c556b655b168faff4e400975
|