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