1147039Ssam/* $NetBSD: clnp_subr.c,v 1.32 2009/03/18 15:14:32 cegger Exp $ */ 2147039Ssam 3189263Ssam/*- 4172319Ssam * Copyright (c) 1991, 1993 5234711Sbschmidt * The Regents of the University of California. All rights reserved. 6147039Ssam * 7147039Ssam * Redistribution and use in source and binary forms, with or without 8234711Sbschmidt * modification, are permitted provided that the following conditions 9234711Sbschmidt * are met: 10234711Sbschmidt * 1. Redistributions of source code must retain the above copyright 11234711Sbschmidt * notice, this list of conditions and the following disclaimer. 12234711Sbschmidt * 2. Redistributions in binary form must reproduce the above copyright 13234711Sbschmidt * notice, this list of conditions and the following disclaimer in the 14234711Sbschmidt * documentation and/or other materials provided with the distribution. 15234711Sbschmidt * 3. Neither the name of the University nor the names of its contributors 16234711Sbschmidt * may be used to endorse or promote products derived from this software 17234711Sbschmidt * without specific prior written permission. 18234711Sbschmidt * 19234711Sbschmidt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20234711Sbschmidt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21234711Sbschmidt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22234711Sbschmidt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23234711Sbschmidt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24234711Sbschmidt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25234711Sbschmidt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26234711Sbschmidt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27234711Sbschmidt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28234711Sbschmidt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29234711Sbschmidt * SUCH DAMAGE. 30234711Sbschmidt * 31234711Sbschmidt * @(#)clnp_subr.c 8.1 (Berkeley) 6/10/93 32234711Sbschmidt */ 33234711Sbschmidt 34234711Sbschmidt/*********************************************************** 35234711Sbschmidt Copyright IBM Corporation 1987 36234711Sbschmidt 37234711Sbschmidt All Rights Reserved 38234711Sbschmidt 39234711SbschmidtPermission to use, copy, modify, and distribute this software and its 40234711Sbschmidtdocumentation for any purpose and without fee is hereby granted, 41234711Sbschmidtprovided that the above copyright notice appear in all copies and that 42234711Sbschmidtboth that copyright notice and this permission notice appear in 43234711Sbschmidtsupporting documentation, and that the name of IBM not be 44234711Sbschmidtused in advertising or publicity pertaining to distribution of the 45234711Sbschmidtsoftware without specific, written prior permission. 46234711Sbschmidt 47234711SbschmidtIBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 48234711SbschmidtALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 49234711SbschmidtIBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 50234711SbschmidtANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 51234711SbschmidtWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 52234711SbschmidtARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 53234711SbschmidtSOFTWARE. 54234711Sbschmidt 55234711Sbschmidt******************************************************************/ 56234711Sbschmidt 57234711Sbschmidt/* 58147039Ssam * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 59147453Ssam */ 60147453Ssam 61173530Ssam#include <sys/cdefs.h> 62173530Ssam__KERNEL_RCSID(0, "$NetBSD: clnp_subr.c,v 1.32 2009/03/18 15:14:32 cegger Exp $"); 63189263Ssam 64173530Ssam#include "opt_iso.h" 65173530Ssam 66173530Ssam#ifdef ISO 67234711Sbschmidt 68234711Sbschmidt#include <sys/param.h> 69234711Sbschmidt#include <sys/mbuf.h> 70234711Sbschmidt#include <sys/domain.h> 71234711Sbschmidt#include <sys/protosw.h> 72172319Ssam#include <sys/socket.h> 73172319Ssam#include <sys/socketvar.h> 74172319Ssam#include <sys/errno.h> 75214735Srpaulo#include <sys/time.h> 76214735Srpaulo#include <sys/systm.h> 77214735Srpaulo 78172319Ssam#include <net/if.h> 79172319Ssam#include <net/route.h> 80189263Ssam#include <net/if_dl.h> 81189263Ssam 82189263Ssam#include <netiso/iso.h> 83189263Ssam#include <netiso/iso_var.h> 84172319Ssam#include <netiso/iso_pcb.h> 85172319Ssam#include <netiso/iso_snpac.h> 86172319Ssam#include <netiso/clnp.h> 87234711Sbschmidt#include <netiso/clnp_stat.h> 88234711Sbschmidt#include <netiso/argo_debug.h> 89234711Sbschmidt#include <netiso/esis.h> 90234711Sbschmidt 91234711Sbschmidt/* 92234711Sbschmidt * FUNCTION: clnp_data_ck 93234711Sbschmidt * 94234711Sbschmidt * PURPOSE: Check that the amount of data in the mbuf chain is 95234711Sbschmidt * at least as much as the clnp header would have us 96234711Sbschmidt * expect. Trim mbufs if longer than expected, drop 97234711Sbschmidt * packet if shorter than expected. 98234711Sbschmidt * 99234711Sbschmidt * RETURNS: success - ptr to mbuf chain 100234711Sbschmidt * failure - 0 101234711Sbschmidt * 102234711Sbschmidt * SIDE EFFECTS: 103234711Sbschmidt * 104234711Sbschmidt * NOTES: 105234711Sbschmidt */ 106234711Sbschmidtstruct mbuf * 107234711Sbschmidtclnp_data_ck( 108172319Ssam struct mbuf *m, /* ptr to mbuf chain containing hdr & data */ 109172319Ssam int length) /* length (in bytes) of packet */ 110172319Ssam{ 111234711Sbschmidt int len; /* length of data */ 112234711Sbschmidt struct mbuf *mhead; /* ptr to head of chain */ 113172319Ssam 114172319Ssam len = -length; 115172319Ssam mhead = m; 116172319Ssam for (;;) { 117234711Sbschmidt len += m->m_len; 118172319Ssam if (m->m_next == 0) 119172319Ssam break; 120172319Ssam m = m->m_next; 121234711Sbschmidt } 122234711Sbschmidt if (len != 0) { 123234711Sbschmidt if (len < 0) { 124234711Sbschmidt INCSTAT(cns_toosmall); 125172319Ssam clnp_discard(mhead, GEN_INCOMPLETE); 126172319Ssam return 0; 127172319Ssam } 128172319Ssam if (len <= m->m_len) 129234711Sbschmidt m->m_len -= len; 130234711Sbschmidt else 131172319Ssam m_adj(mhead, -len); 132234711Sbschmidt } 133172319Ssam return mhead; 134172319Ssam} 135172319Ssam 136234711Sbschmidt#ifdef notdef 137234711Sbschmidt/* 138172319Ssam * FUNCTION: clnp_extract_addr 139172319Ssam * 140172319Ssam * PURPOSE: Extract the source and destination address from the 141234711Sbschmidt * supplied buffer. Place them in the supplied address buffers. 142234711Sbschmidt * If insufficient data is supplied, then fail. 143172319Ssam * 144172319Ssam * RETURNS: success - Address of first byte in the packet past 145172319Ssam * the address part. 146172319Ssam * failure - 0 147172319Ssam * 148172319Ssam * SIDE EFFECTS: 149172319Ssam * 150172319Ssam * NOTES: 151234711Sbschmidt */ 152234711Sbschmidtvoid * 153172319Ssamclnp_extract_addr( 154172319Ssam void * bufp, /* ptr to buffer containing addresses */ 155234711Sbschmidt int buflen, /* length of buffer */ 156234711Sbschmidt struct iso_addr *srcp, /* ptr to source address buffer */ 157234711Sbschmidt struct iso_addr *destp) /* ptr to destination address 158234711Sbschmidt * buffer */ 159234711Sbschmidt{ 160234711Sbschmidt size_t len; /* argument to memcpy */ 161234711Sbschmidt 162234711Sbschmidt /* 163172319Ssam * check that we have enough data. Plus1 is for length octet 164172319Ssam */ 165172319Ssam len = (u_char)*bufp++; 166172319Ssam if (len > buflen) 167172319Ssam return NULL; 168172319Ssam destp->isoa_len = len; 169171326Ssam (void)memcpy(destp, bufp, len); 170171326Ssam buflen -= len; 171171326Ssam bufp += len; 172172319Ssam 173172319Ssam /* 174147039Ssam * check that we have enough data. Plus1 is for length octet 175147039Ssam */ 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 */ 206int 207clnp_ours( 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 memcmp((void *) ia->ia_addr.siso_addr.isoa_genaddr, 225 (void *) 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 */ 233int 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 */ 250void 251clnp_forward( 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 const 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 route; /* filled in by clnp_route */ 266 struct rtentry *rt; 267 extern int iso_systype; 268 269 clnp = mtod(m, struct clnp_fixed *); 270 memset((void *) & route, 0, sizeof(route)); /* MUST be done before 271 * "bad:" */ 272 273 /* 274 * Don't forward multicast or broadcast packets 275 */ 276 if ((inbound_shp) && (IS_MULTICAST(inbound_shp->snh_dhost))) { 277#ifdef ARGO_DEBUG 278 if (argo_debug[D_FORWARD]) { 279 printf("clnp_forward: dropping multicast packet\n"); 280 } 281#endif 282 clnp->cnf_type &= ~CNF_ERR_OK; /* so we don't generate an ER */ 283 clnp_discard(m, 0); 284 INCSTAT(cns_cantforward); 285 goto done; 286 } 287#ifdef ARGO_DEBUG 288 if (argo_debug[D_FORWARD]) { 289 printf("clnp_forward: %d bytes, to %s, options %p\n", len, 290 clnp_iso_addrp(dst), oidx); 291 } 292#endif 293 294 /* 295 * Decrement ttl, and if zero drop datagram 296 * Can't compare ttl as less than zero 'cause its a unsigned 297 */ 298 if ((clnp->cnf_ttl == 0) || (--clnp->cnf_ttl == 0)) { 299#ifdef ARGO_DEBUG 300 if (argo_debug[D_FORWARD]) { 301 printf("clnp_forward: discarding datagram because ttl is zero\n"); 302 } 303#endif 304 INCSTAT(cns_ttlexpired); 305 clnp_discard(m, TTL_EXPTRANSIT); 306 goto done; 307 } 308 /* 309 * Route packet; special case for source rt 310 */ 311 if CLNPSRCRT_VALID 312 (oidx) { 313 /* 314 * Update src route first 315 */ 316 clnp_update_srcrt(m, oidx); 317 error = clnp_srcroute(m, oidx, &route, &next_hop, &ia, dst); 318 } else { 319 error = clnp_route(dst, &route, 0, &next_hop, &ia); 320 } 321 if (error || ia == 0) { 322#ifdef ARGO_DEBUG 323 if (argo_debug[D_FORWARD]) { 324 printf("clnp_forward: can't route packet (errno %d)\n", error); 325 } 326#endif 327 clnp_discard(m, ADDR_DESTUNREACH); 328 INCSTAT(cns_cantforward); 329 goto done; 330 } 331 ifp = ia->ia_ifp; 332 333#ifdef ARGO_DEBUG 334 if (argo_debug[D_FORWARD]) { 335 printf("clnp_forward: packet routed to %s\n", 336 clnp_iso_addrp(&satocsiso(next_hop)->siso_addr)); 337 } 338#endif 339 340 INCSTAT(cns_forward); 341 342 /* 343 * If we are an intermediate system and 344 * we are routing outbound on the same ifp that the packet 345 * arrived upon, and we know the next hop snpa, 346 * then generate a redirect request 347 */ 348 if ((iso_systype & SNPA_IS) && (inbound_shp) && 349 (ifp == inbound_shp->snh_ifp)) 350 esis_rdoutput(inbound_shp, m, oidx, dst, rtcache_validate(&route)); 351 /* 352 * If options are present, update them 353 */ 354 if (oidx) { 355 struct iso_addr *mysrc = &ia->ia_addr.siso_addr; 356 if (mysrc == NULL) { 357 clnp_discard(m, ADDR_DESTUNREACH); 358 INCSTAT(cns_cantforward); 359 clnp_stat.cns_forward--; 360 goto done; 361 } else { 362 (void) clnp_dooptions(m, oidx, ifp, mysrc); 363 } 364 } 365#ifdef DECBIT 366 if (ifp->if_snd.ifq_len > congest_threshold) { 367 /* 368 * Congestion! Set the Dec Bit and thank Dave Oran 369 */ 370#ifdef ARGO_DEBUG 371 if (argo_debug[D_FORWARD]) { 372 printf("clnp_forward: congestion experienced\n"); 373 } 374#endif 375 if ((oidx) && (oidx->cni_qos_formatp)) { 376 char * qosp = CLNP_OFFTOOPT(m, oidx->cni_qos_formatp); 377 u_char qos = *qosp; 378#ifdef ARGO_DEBUG 379 if (argo_debug[D_FORWARD]) { 380 printf("clnp_forward: setting congestion bit (qos x%x)\n", qos); 381 } 382#endif 383 if ((qos & CLNPOVAL_GLOBAL) == CLNPOVAL_GLOBAL) { 384 qos |= CLNPOVAL_CONGESTED; 385 INCSTAT(cns_congest_set); 386 *qosp = qos; 387 } 388 } 389 } 390#endif /* DECBIT */ 391 392 /* 393 * Dispatch the datagram if it is small enough, otherwise fragment 394 */ 395 if ((rt = rtcache_validate(&route)) == NULL) 396 ; 397 else if (len <= SN_MTU(ifp, rt)) { 398 iso_gen_csum(m, CLNP_CKSUM_OFF, (int) clnp->cnf_hdr_len); 399 (void) (*ifp->if_output) (ifp, m, next_hop, rt); 400 } else { 401 (void) clnp_fragment(ifp, m, next_hop, len, seg_off, /* flags */ 0, rt); 402 } 403 404done: 405 /* 406 * Free route 407 */ 408 rtcache_free(&route); 409} 410 411#ifdef notdef 412/* 413 * FUNCTION: clnp_insert_addr 414 * 415 * PURPOSE: Insert the address part into a clnp datagram. 416 * 417 * RETURNS: Address of first byte after address part in datagram. 418 * 419 * SIDE EFFECTS: 420 * 421 * NOTES: Assume that there is enough space for the address part. 422 */ 423void * 424clnp_insert_addr( 425 void * bufp, /* address of where addr part goes */ 426 struct iso_addr *srcp, /* ptr to src addr */ 427 struct iso_addr *dstp) /* ptr to dst addr */ 428{ 429 *bufp++ = dstp->isoa_len; 430 (void)memcpy(bufp, dstp, dstp->isoa_len); 431 bufp += dstp->isoa_len; 432 433 *bufp++ = srcp->isoa_len; 434 (void)memcpy(bufp, srcp, srcp->isoa_len); 435 bufp += srcp->isoa_len; 436 437 return bufp; 438} 439 440#endif /* notdef */ 441 442/* 443 * FUNCTION: clnp_route 444 * 445 * PURPOSE: Route a clnp datagram to the first hop toward its 446 * destination. In many cases, the first hop will be 447 * the destination. The address of a route 448 * is specified. If a routing entry is present in 449 * that route, and it is still up to the same destination, 450 * then no further action is necessary. Otherwise, a 451 * new routing entry will be allocated. 452 * 453 * RETURNS: route found - 0 454 * unix error code 455 * 456 * SIDE EFFECTS: 457 * 458 * NOTES: It is up to the caller to free the routing entry 459 * allocated in route. 460 */ 461int 462clnp_route( 463 struct iso_addr *dst, /* ptr to datagram destination */ 464 struct route *ro, /* existing route structure */ 465 int flags, /* flags for routing */ 466 const struct sockaddr **first_hop, /* result: fill in with ptr to 467 * firsthop */ 468 struct iso_ifaddr **ifa) /* result: fill in with ptr to ifa */ 469{ 470 struct rtentry *rt; 471 int rc; 472 union { 473 struct sockaddr dst; 474 struct sockaddr_iso dsti; 475 } u; 476 477 if (flags & SO_DONTROUTE) { 478 struct iso_ifaddr *ia; 479 480 if ((rc = sockaddr_iso_init(&u.dsti, dst)) != 0) 481 return rc; 482 rtcache_setdst(ro, &u.dst); 483 484 if (rtcache_getdst(ro) == NULL) 485 return EADDRNOTAVAIL; 486 ia = iso_localifa(satocsiso(rtcache_getdst(ro))); 487 if (ia == NULL) 488 return EADDRNOTAVAIL; 489 if (ifa != NULL) 490 *ifa = ia; 491 if (first_hop != NULL) 492 *first_hop = rtcache_getdst(ro); 493 return 0; 494 } 495 496 /* set up new route structure */ 497 if ((rc = sockaddr_iso_init(&u.dsti, dst)) != 0) 498 return rc; 499 if ((rt = rtcache_lookup(ro, &u.dst)) == NULL) { 500 rtcache_free(ro); 501 return ENETUNREACH; 502 } 503 rt->rt_use++; 504 if (ifa != NULL) 505 if ((*ifa = (struct iso_ifaddr *)rt->rt_ifa) == NULL) 506 panic("clnp_route"); 507 if (first_hop != NULL) { 508 if (rt->rt_flags & RTF_GATEWAY) 509 *first_hop = rt->rt_gateway; 510 else 511 *first_hop = rtcache_getdst(ro); 512 } 513 return 0; 514} 515 516/* 517 * FUNCTION: clnp_srcroute 518 * 519 * PURPOSE: Source route the datagram. If complete source 520 * routing is specified but not possible, then 521 * return an error. If src routing is terminated, then 522 * try routing on destination. 523 * Usage of first_hop, 524 * ifp, and error return is identical to clnp_route. 525 * 526 * RETURNS: 0 or unix error code 527 * 528 * SIDE EFFECTS: 529 * 530 * NOTES: Remember that option index pointers are really 531 * offsets from the beginning of the mbuf. 532 */ 533int 534clnp_srcroute( 535 struct mbuf *options, /* ptr to options */ 536 struct clnp_optidx *oidx, /* index to options */ 537 struct route *ro, /* route structure */ 538 const struct sockaddr **first_hop, /* RETURN: fill in with ptr to 539 * firsthop */ 540 struct iso_ifaddr **ifa, /* RETURN: fill in with ptr to ifa */ 541 struct iso_addr *final_dst) /* final destination */ 542{ 543 struct iso_addr dst; /* first hop specified by src rt */ 544 int error = 0; /* return code */ 545 546 /* 547 * Check if we have run out of routes 548 * If so, then try to route on destination. 549 */ 550 if CLNPSRCRT_TERM 551 (oidx, options) { 552 dst.isoa_len = final_dst->isoa_len; 553 if (sizeof(dst.isoa_genaddr) < (size_t)dst.isoa_len) 554 return EINVAL; 555 (void)memcpy(dst.isoa_genaddr, final_dst->isoa_genaddr, 556 (size_t)dst.isoa_len); 557 } else { 558 /* 559 * setup dst based on src rt specified 560 */ 561 dst.isoa_len = CLNPSRCRT_CLEN(oidx, options); 562 if (sizeof(dst.isoa_genaddr) < (unsigned)dst.isoa_len) 563 return EINVAL; 564 (void)memcpy(dst.isoa_genaddr, CLNPSRCRT_CADDR(oidx, options), 565 (size_t)dst.isoa_len); 566 } 567 568 /* 569 * try to route it 570 */ 571 error = clnp_route(&dst, ro, 0, first_hop, ifa); 572 if (error != 0) 573 return error; 574 575 /* 576 * If complete src rt, first hop must be equal to dst 577 */ 578 if ((CLNPSRCRT_TYPE(oidx, options) == CLNPOVAL_COMPRT) && 579 (!iso_addrmatch1(&satocsiso(*first_hop)->siso_addr, &dst))) { 580#ifdef ARGO_DEBUG 581 if (argo_debug[D_OPTIONS]) { 582 printf("clnp_srcroute: complete src route failed\n"); 583 } 584#endif 585 return EHOSTUNREACH; /* RAH? would like ESRCRTFAILED */ 586 } 587 return error; 588} 589 590/* 591 * FUNCTION: clnp_echoreply 592 * 593 * PURPOSE: generate an echo reply packet and transmit 594 * 595 * RETURNS: result of clnp_output 596 * 597 * SIDE EFFECTS: 598 */ 599int 600clnp_echoreply( 601 struct mbuf *ec_m, /* echo request */ 602 int ec_len, /* length of ec */ 603 struct sockaddr_iso *ec_src, /* src of ec */ 604 struct sockaddr_iso *ec_dst, /* destination of ec (i.e., us) */ 605 struct clnp_optidx *ec_oidxp) /* options index to ec packet */ 606{ 607 struct isopcb isopcb; 608 int flags = CLNP_NOCACHE | CLNP_ECHOR; 609 int ret; 610 611 /* fill in fake isopcb to pass to output function */ 612 memset(&isopcb, 0, sizeof(isopcb)); 613 isopcb.isop_laddr = ec_dst; 614 isopcb.isop_faddr = ec_src; 615 616 /* 617 * forget copying the options for now. If implemented, need only copy 618 * record route option, but it must be reset to zero length 619 */ 620 621 ret = clnp_output(ec_m, &isopcb, ec_len, flags); 622 623#ifdef ARGO_DEBUG 624 if (argo_debug[D_OUTPUT]) { 625 printf("clnp_echoreply: output returns %d\n", ret); 626 } 627#endif 628 return ret; 629} 630 631/* 632 * FUNCTION: clnp_badmtu 633 * 634 * PURPOSE: print notice of route with mtu not initialized. 635 * 636 * RETURNS: mtu of ifp. 637 * 638 * SIDE EFFECTS: prints notice, slows down system. 639 */ 640int 641clnp_badmtu( 642 struct ifnet *ifp, /* outgoing interface */ 643 struct rtentry *rt, /* dst route */ 644 int line, /* where the dirty deed occurred */ 645 const char *file) /* where the dirty deed occurred */ 646{ 647 printf("sending on route %p with no mtu, line %d of file %s\n", 648 rt, line, file); 649#ifdef ARGO_DEBUG 650 printf("route dst is "); 651 dump_isoaddr(satocsiso(rt_getkey(rt))); 652#endif 653 return ifp->if_mtu; 654} 655 656/* 657 * FUNCTION: clnp_ypocb - backwards bcopy 658 * 659 * PURPOSE: bcopy starting at end of src rather than beginning. 660 * 661 * RETURNS: none 662 * 663 * SIDE EFFECTS: 664 * 665 * NOTES: No attempt has been made to make this efficient 666 */ 667void 668clnp_ypocb( 669 void * from, /* src buffer */ 670 void * to, /* dst buffer */ 671 u_int len) /* number of bytes */ 672{ 673 while (len--) 674 *((char *)to + len) = *((char *)from + len); 675} 676#endif /* ISO */ 677