1*36375Ssklower /*********************************************************** 2*36375Ssklower Copyright IBM Corporation 1987 3*36375Ssklower 4*36375Ssklower All Rights Reserved 5*36375Ssklower 6*36375Ssklower Permission to use, copy, modify, and distribute this software and its 7*36375Ssklower documentation for any purpose and without fee is hereby granted, 8*36375Ssklower provided that the above copyright notice appear in all copies and that 9*36375Ssklower both that copyright notice and this permission notice appear in 10*36375Ssklower supporting documentation, and that the name of IBM not be 11*36375Ssklower used in advertising or publicity pertaining to distribution of the 12*36375Ssklower software without specific, written prior permission. 13*36375Ssklower 14*36375Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15*36375Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16*36375Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17*36375Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18*36375Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19*36375Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*36375Ssklower SOFTWARE. 21*36375Ssklower 22*36375Ssklower ******************************************************************/ 23*36375Ssklower 24*36375Ssklower /* 25*36375Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26*36375Ssklower */ 27*36375Ssklower /* $Header: clnp_subr.c,v 4.10 88/09/14 11:31:33 hagens Exp $ */ 28*36375Ssklower /* $Source: /usr/argo/sys/netiso/RCS/clnp_subr.c,v $ */ 29*36375Ssklower 30*36375Ssklower #ifndef lint 31*36375Ssklower static char *rcsid = "$Header: clnp_subr.c,v 4.10 88/09/14 11:31:33 hagens Exp $"; 32*36375Ssklower #endif lint 33*36375Ssklower 34*36375Ssklower #ifdef ISO 35*36375Ssklower 36*36375Ssklower #include "../h/types.h" 37*36375Ssklower #include "../h/param.h" 38*36375Ssklower #include "../h/mbuf.h" 39*36375Ssklower #include "../h/domain.h" 40*36375Ssklower #include "../h/protosw.h" 41*36375Ssklower #include "../h/socket.h" 42*36375Ssklower #include "../h/socketvar.h" 43*36375Ssklower #include "../h/errno.h" 44*36375Ssklower #include "../h/time.h" 45*36375Ssklower 46*36375Ssklower #include "../net/if.h" 47*36375Ssklower #include "../net/route.h" 48*36375Ssklower 49*36375Ssklower #include "../netiso/iso.h" 50*36375Ssklower #include "../netiso/iso_var.h" 51*36375Ssklower #include "../netiso/clnp.h" 52*36375Ssklower #include "../netiso/clnp_stat.h" 53*36375Ssklower #include "../netiso/argo_debug.h" 54*36375Ssklower #include "../netiso/iso_snpac.h" 55*36375Ssklower 56*36375Ssklower /* 57*36375Ssklower * FUNCTION: clnp_data_ck 58*36375Ssklower * 59*36375Ssklower * PURPOSE: Check that the amount of data in the mbuf chain is 60*36375Ssklower * at least as much as the clnp header would have us 61*36375Ssklower * expect. Trim mbufs if longer than expected, drop 62*36375Ssklower * packet if shorter than expected. 63*36375Ssklower * 64*36375Ssklower * RETURNS: success - ptr to mbuf chain 65*36375Ssklower * failure - 0 66*36375Ssklower * 67*36375Ssklower * SIDE EFFECTS: 68*36375Ssklower * 69*36375Ssklower * NOTES: 70*36375Ssklower */ 71*36375Ssklower struct mbuf * 72*36375Ssklower clnp_data_ck(m, length) 73*36375Ssklower register struct mbuf *m; /* ptr to mbuf chain containing hdr & data */ 74*36375Ssklower int length; /* length (in bytes) of packet */ 75*36375Ssklower { 76*36375Ssklower register int len; /* length of data */ 77*36375Ssklower register struct mbuf *mhead; /* ptr to head of chain */ 78*36375Ssklower 79*36375Ssklower len = -length; 80*36375Ssklower mhead = m; 81*36375Ssklower for (;;) { 82*36375Ssklower len += m->m_len; 83*36375Ssklower if (m->m_next == 0) 84*36375Ssklower break; 85*36375Ssklower m = m->m_next; 86*36375Ssklower } 87*36375Ssklower if (len != 0) { 88*36375Ssklower if (len < 0) { 89*36375Ssklower INCSTAT(cns_toosmall); 90*36375Ssklower clnp_discard(mhead, GEN_INCOMPLETE); 91*36375Ssklower return 0; 92*36375Ssklower } 93*36375Ssklower if (len <= m->m_len) 94*36375Ssklower m->m_len -= len; 95*36375Ssklower else 96*36375Ssklower m_adj(mhead, -len); 97*36375Ssklower } 98*36375Ssklower return mhead; 99*36375Ssklower } 100*36375Ssklower 101*36375Ssklower #ifdef ndef 102*36375Ssklower /* 103*36375Ssklower * FUNCTION: clnp_extract_addr 104*36375Ssklower * 105*36375Ssklower * PURPOSE: Extract the source and destination address from the 106*36375Ssklower * supplied buffer. Place them in the supplied address buffers. 107*36375Ssklower * If insufficient data is supplied, then fail. 108*36375Ssklower * 109*36375Ssklower * RETURNS: success - Address of first byte in the packet past 110*36375Ssklower * the address part. 111*36375Ssklower * failure - 0 112*36375Ssklower * 113*36375Ssklower * SIDE EFFECTS: 114*36375Ssklower * 115*36375Ssklower * NOTES: 116*36375Ssklower */ 117*36375Ssklower caddr_t 118*36375Ssklower clnp_extract_addr(bufp, buflen, srcp, destp) 119*36375Ssklower caddr_t bufp; /* ptr to buffer containing addresses */ 120*36375Ssklower int buflen; /* length of buffer */ 121*36375Ssklower register struct iso_addr *srcp; /* ptr to source address buffer */ 122*36375Ssklower register struct iso_addr *destp; /* ptr to destination address buffer */ 123*36375Ssklower { 124*36375Ssklower int len; /* argument to bcopy */ 125*36375Ssklower 126*36375Ssklower /* 127*36375Ssklower * check that we have enough data. Plus1 is for length octet 128*36375Ssklower */ 129*36375Ssklower if ((u_char)*bufp + 1 > buflen) { 130*36375Ssklower return((caddr_t)0); 131*36375Ssklower } 132*36375Ssklower len = destp->isoa_len = (u_char)*bufp++; 133*36375Ssklower (void) bcopy(bufp, (caddr_t)destp, len); 134*36375Ssklower buflen -= len; 135*36375Ssklower bufp += len; 136*36375Ssklower 137*36375Ssklower /* 138*36375Ssklower * check that we have enough data. Plus1 is for length octet 139*36375Ssklower */ 140*36375Ssklower if ((u_char)*bufp + 1 > buflen) { 141*36375Ssklower return((caddr_t)0); 142*36375Ssklower } 143*36375Ssklower len = srcp->isoa_len = (u_char)* bufp++; 144*36375Ssklower (void) bcopy(bufp, (caddr_t)srcp, len); 145*36375Ssklower bufp += len; 146*36375Ssklower 147*36375Ssklower /* 148*36375Ssklower * Insure that the addresses make sense 149*36375Ssklower */ 150*36375Ssklower if (iso_ck_addr(srcp) && iso_ck_addr(destp)) 151*36375Ssklower return bufp; 152*36375Ssklower else 153*36375Ssklower return (caddr_t) 0; 154*36375Ssklower } 155*36375Ssklower #endif ndef 156*36375Ssklower 157*36375Ssklower /* 158*36375Ssklower * FUNCTION: clnp_ours 159*36375Ssklower * 160*36375Ssklower * PURPOSE: Decide whether the supplied packet is destined for 161*36375Ssklower * us, or that it should be forwarded on. 162*36375Ssklower * 163*36375Ssklower * RETURNS: packet is for us - 1 164*36375Ssklower * packet is not for us - 0 165*36375Ssklower * 166*36375Ssklower * SIDE EFFECTS: 167*36375Ssklower * 168*36375Ssklower * NOTES: 169*36375Ssklower */ 170*36375Ssklower clnp_ours(dst) 171*36375Ssklower register struct iso_addr *dst; /* ptr to destination address */ 172*36375Ssklower { 173*36375Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 174*36375Ssklower 175*36375Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 176*36375Ssklower IFDEBUG(D_ROUTE) 177*36375Ssklower printf("clnp_ours: ia_sis x%x, dst x%x\n", &IA_SIS(ia)->siso_addr, 178*36375Ssklower dst); 179*36375Ssklower ENDDEBUG 180*36375Ssklower /* PHASE 2: uses iso_addrmatch & mask from iso_ifaddr */ 181*36375Ssklower if (iso_addrmatch1(&IA_SIS(ia)->siso_addr, dst)) 182*36375Ssklower return 1; 183*36375Ssklower } 184*36375Ssklower return 0; 185*36375Ssklower } 186*36375Ssklower 187*36375Ssklower /* 188*36375Ssklower * FUNCTION: clnp_forward 189*36375Ssklower * 190*36375Ssklower * PURPOSE: Forward the datagram passed 191*36375Ssklower * clnpintr guarantees that the header will be 192*36375Ssklower * contigious (a cluster mbuf will be used if necessary). 193*36375Ssklower * 194*36375Ssklower * If oidx is NULL, no options are present. 195*36375Ssklower * 196*36375Ssklower * RETURNS: nothing 197*36375Ssklower * 198*36375Ssklower * SIDE EFFECTS: 199*36375Ssklower * 200*36375Ssklower * NOTES: 201*36375Ssklower */ 202*36375Ssklower clnp_forward(m, len, dst, oidx, seg_off, inbound_shp) 203*36375Ssklower struct mbuf *m; /* pkt to forward */ 204*36375Ssklower int len; /* length of pkt */ 205*36375Ssklower struct iso_addr *dst; /* destination address */ 206*36375Ssklower struct clnp_optidx *oidx; /* option index */ 207*36375Ssklower int seg_off;/* offset of segmentation part */ 208*36375Ssklower struct snpa_hdr *inbound_shp; /* subnetwork header of inbound packet */ 209*36375Ssklower { 210*36375Ssklower struct clnp_fixed *clnp; /* ptr to fixed part of header */ 211*36375Ssklower int error; /* return value of route function */ 212*36375Ssklower struct sockaddr *next_hop; /* next hop for dgram */ 213*36375Ssklower struct ifnet *ifp; /* ptr to outgoing interface */ 214*36375Ssklower struct route route; /* filled in by clnp_route */ 215*36375Ssklower extern int iso_systype; 216*36375Ssklower 217*36375Ssklower clnp = mtod(m, struct clnp_fixed *); 218*36375Ssklower bzero((caddr_t)&route, sizeof(route)); /* MUST be done before "bad:" */ 219*36375Ssklower 220*36375Ssklower /* 221*36375Ssklower * Don't forward multicast or broadcast packets 222*36375Ssklower */ 223*36375Ssklower if ((inbound_shp) && (IS_MULTICAST(inbound_shp->snh_dhost))) { 224*36375Ssklower IFDEBUG(D_FORWARD) 225*36375Ssklower printf("clnp_forward: dropping multicast packet\n"); 226*36375Ssklower ENDDEBUG 227*36375Ssklower clnp->cnf_err_ok = 0; /* so we don't generate an ER */ 228*36375Ssklower clnp_discard(m, 0); 229*36375Ssklower goto done; 230*36375Ssklower } 231*36375Ssklower 232*36375Ssklower IFDEBUG(D_FORWARD) 233*36375Ssklower printf("clnp_forward: %d bytes, to %s, options x%x\n", len, 234*36375Ssklower clnp_iso_addrp(dst), oidx); 235*36375Ssklower ENDDEBUG 236*36375Ssklower 237*36375Ssklower /* 238*36375Ssklower * Decrement ttl, and if zero drop datagram 239*36375Ssklower * Can't compare ttl as less than zero 'cause its a unsigned 240*36375Ssklower */ 241*36375Ssklower if ((clnp->cnf_ttl == 0) || (--clnp->cnf_ttl == 0)) { 242*36375Ssklower IFDEBUG(D_FORWARD) 243*36375Ssklower printf("clnp_forward: discarding datagram because ttl is zero\n"); 244*36375Ssklower ENDDEBUG 245*36375Ssklower INCSTAT(cns_ttlexpired); 246*36375Ssklower clnp_discard(m, TTL_EXPTRANSIT); 247*36375Ssklower goto done; 248*36375Ssklower } 249*36375Ssklower 250*36375Ssklower /* 251*36375Ssklower * Route packet; special case for source rt 252*36375Ssklower */ 253*36375Ssklower if CLNPSRCRT_VALID(oidx) { 254*36375Ssklower /* 255*36375Ssklower * Update src route first 256*36375Ssklower */ 257*36375Ssklower clnp_update_srcrt(m, oidx); 258*36375Ssklower error = clnp_srcroute(m, oidx, &route, &next_hop, &ifp, dst); 259*36375Ssklower } else { 260*36375Ssklower error = clnp_route(dst, &route, 0, &next_hop, &ifp); 261*36375Ssklower } 262*36375Ssklower if (error) { 263*36375Ssklower IFDEBUG(D_FORWARD) 264*36375Ssklower printf("clnp_forward: can't route packet (errno %d)\n", error); 265*36375Ssklower ENDDEBUG 266*36375Ssklower clnp_discard(m, ADDR_DESTUNREACH); 267*36375Ssklower goto done; 268*36375Ssklower } 269*36375Ssklower 270*36375Ssklower IFDEBUG(D_FORWARD) 271*36375Ssklower printf("clnp_forward: packet routed to %s\n", 272*36375Ssklower clnp_iso_addrp(&((struct sockaddr_iso *)next_hop)->siso_addr)); 273*36375Ssklower ENDDEBUG 274*36375Ssklower 275*36375Ssklower INCSTAT(cns_forward); 276*36375Ssklower 277*36375Ssklower /* 278*36375Ssklower * If we are an intermediate system and 279*36375Ssklower * we are routing outbound on the same ifp that the packet 280*36375Ssklower * arrived upon, and we know the next hop snpa, 281*36375Ssklower * then generate a redirect request 282*36375Ssklower */ 283*36375Ssklower if ((iso_systype & SNPA_IS) && (inbound_shp) && 284*36375Ssklower (ifp == inbound_shp->snh_ifp)) { 285*36375Ssklower struct snpa_cache *sc; 286*36375Ssklower 287*36375Ssklower sc = snpac_look(&((struct sockaddr_iso *)next_hop)->siso_addr); 288*36375Ssklower if (sc != NULL) { 289*36375Ssklower esis_rdoutput(inbound_shp, m, oidx, dst, sc); 290*36375Ssklower } 291*36375Ssklower } 292*36375Ssklower 293*36375Ssklower /* 294*36375Ssklower * If options are present, update them 295*36375Ssklower */ 296*36375Ssklower if (oidx) { 297*36375Ssklower struct iso_addr *mysrc = 298*36375Ssklower clnp_srcaddr(ifp, &((struct sockaddr_iso *)next_hop)->siso_addr); 299*36375Ssklower if (mysrc == NULL) { 300*36375Ssklower clnp_discard(m, ADDR_DESTUNREACH); 301*36375Ssklower goto done; 302*36375Ssklower } else { 303*36375Ssklower (void) clnp_dooptions(m, oidx, ifp, mysrc); 304*36375Ssklower } 305*36375Ssklower } 306*36375Ssklower 307*36375Ssklower /* 308*36375Ssklower * Dispatch the datagram if it is small enough, otherwise fragment 309*36375Ssklower */ 310*36375Ssklower if (len <= SN_MTU(ifp)) { 311*36375Ssklower iso_gen_csum(m, CLNP_CKSUM_OFF, (int)clnp->cnf_hdr_len); 312*36375Ssklower (void) (*ifp->if_output)(ifp, m, next_hop); 313*36375Ssklower } else { 314*36375Ssklower (void) clnp_fragment(ifp, m, next_hop, len, seg_off, /* flags */0); 315*36375Ssklower } 316*36375Ssklower 317*36375Ssklower done: 318*36375Ssklower /* 319*36375Ssklower * Free route 320*36375Ssklower */ 321*36375Ssklower if (route.ro_rt != NULL) { 322*36375Ssklower RTFREE(route.ro_rt); 323*36375Ssklower } 324*36375Ssklower } 325*36375Ssklower 326*36375Ssklower #ifdef ndef 327*36375Ssklower /* 328*36375Ssklower * FUNCTION: clnp_insert_addr 329*36375Ssklower * 330*36375Ssklower * PURPOSE: Insert the address part into a clnp datagram. 331*36375Ssklower * 332*36375Ssklower * RETURNS: Address of first byte after address part in datagram. 333*36375Ssklower * 334*36375Ssklower * SIDE EFFECTS: 335*36375Ssklower * 336*36375Ssklower * NOTES: Assume that there is enough space for the address part. 337*36375Ssklower */ 338*36375Ssklower caddr_t 339*36375Ssklower clnp_insert_addr(bufp, srcp, dstp) 340*36375Ssklower caddr_t bufp; /* address of where addr part goes */ 341*36375Ssklower register struct iso_addr *srcp; /* ptr to src addr */ 342*36375Ssklower register struct iso_addr *dstp; /* ptr to dst addr */ 343*36375Ssklower { 344*36375Ssklower *bufp++ = dstp->isoa_len; 345*36375Ssklower (void) bcopy((caddr_t)dstp, bufp, dstp->isoa_len); 346*36375Ssklower bufp += dstp->isoa_len; 347*36375Ssklower 348*36375Ssklower *bufp++ = srcp->isoa_len; 349*36375Ssklower (void) bcopy((caddr_t)srcp, bufp, srcp->isoa_len); 350*36375Ssklower bufp += srcp->isoa_len; 351*36375Ssklower 352*36375Ssklower return bufp; 353*36375Ssklower } 354*36375Ssklower 355*36375Ssklower #endif ndef 356*36375Ssklower 357*36375Ssklower /* 358*36375Ssklower * FUNCTION: clnp_route 359*36375Ssklower * 360*36375Ssklower * PURPOSE: Route a clnp datagram to the first hop toward its 361*36375Ssklower * destination. In many cases, the first hop will be 362*36375Ssklower * the destination. The address of a route 363*36375Ssklower * is specified. If a routing entry is present in 364*36375Ssklower * that route, and it is still up to the same destination, 365*36375Ssklower * then no further action is necessary. Otherwise, a 366*36375Ssklower * new routing entry will be allocated. 367*36375Ssklower * 368*36375Ssklower * RETURNS: route found - 0 369*36375Ssklower * unix error code 370*36375Ssklower * 371*36375Ssklower * SIDE EFFECTS: 372*36375Ssklower * 373*36375Ssklower * NOTES: It is up to the caller to free the routing entry 374*36375Ssklower * allocated in route. 375*36375Ssklower */ 376*36375Ssklower clnp_route(dst, ro, flags, first_hop, ifp) 377*36375Ssklower struct iso_addr *dst; /* ptr to datagram destination */ 378*36375Ssklower struct route *ro; /* existing route structure */ 379*36375Ssklower int flags; /* flags for routing */ 380*36375Ssklower struct sockaddr **first_hop; /* result: fill in with ptr to firsthop */ 381*36375Ssklower struct ifnet **ifp; /* result: fill in with ptr to interface */ 382*36375Ssklower { 383*36375Ssklower register struct sockaddr_iso *ro_dst; /* ptr to route's destination */ 384*36375Ssklower 385*36375Ssklower ro_dst = (struct sockaddr_iso *)&ro->ro_dst; 386*36375Ssklower 387*36375Ssklower /* 388*36375Ssklower * If there is a cached route, check that it is still up and to 389*36375Ssklower * the same destination. If not, free it and try again. 390*36375Ssklower */ 391*36375Ssklower if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || 392*36375Ssklower (!iso_addrmatch1(&ro_dst->siso_addr, dst)))) { 393*36375Ssklower IFDEBUG(D_ROUTE) 394*36375Ssklower printf("clnp_route: freeing old route: ro->ro_rt 0x%x\n", 395*36375Ssklower ro->ro_rt); 396*36375Ssklower printf("clnp_route: old route refcnt: 0x%x\n", 397*36375Ssklower ro->ro_rt->rt_refcnt); 398*36375Ssklower ENDDEBUG 399*36375Ssklower 400*36375Ssklower /* free old route entry */ 401*36375Ssklower RTFREE(ro->ro_rt); 402*36375Ssklower ro->ro_rt = (struct rtentry *)0; 403*36375Ssklower } else { 404*36375Ssklower IFDEBUG(D_ROUTE) 405*36375Ssklower printf("clnp_route: OK route exists\n"); 406*36375Ssklower ENDDEBUG 407*36375Ssklower } 408*36375Ssklower 409*36375Ssklower if (ro->ro_rt == 0) { 410*36375Ssklower /* set up new route structure */ 411*36375Ssklower ro_dst->siso_family = AF_ISO; 412*36375Ssklower ro_dst->siso_addr = *dst; 413*36375Ssklower 414*36375Ssklower /* allocate new route */ 415*36375Ssklower IFDEBUG(D_ROUTE) 416*36375Ssklower printf("clnp_route: allocating new route to %s\n", 417*36375Ssklower clnp_iso_addrp(dst)); 418*36375Ssklower ENDDEBUG 419*36375Ssklower rtalloc(ro); 420*36375Ssklower } 421*36375Ssklower 422*36375Ssklower if ((ro->ro_rt == 0) || ((*ifp = ro->ro_rt->rt_ifp) == 0)) { 423*36375Ssklower return(ENETUNREACH); /* rtalloc failed */ 424*36375Ssklower } 425*36375Ssklower 426*36375Ssklower ro->ro_rt->rt_use++; 427*36375Ssklower if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 428*36375Ssklower *first_hop = &ro->ro_rt->rt_gateway; 429*36375Ssklower else 430*36375Ssklower *first_hop = (struct sockaddr *)ro_dst; 431*36375Ssklower 432*36375Ssklower return(0); 433*36375Ssklower } 434*36375Ssklower 435*36375Ssklower /* 436*36375Ssklower * FUNCTION: clnp_srcroute 437*36375Ssklower * 438*36375Ssklower * PURPOSE: Source route the datagram. If complete source 439*36375Ssklower * routing is specified but not possible, then 440*36375Ssklower * return an error. If src routing is terminated, then 441*36375Ssklower * try routing on destination. 442*36375Ssklower * Usage of first_hop, 443*36375Ssklower * ifp, and error return is identical to clnp_route. 444*36375Ssklower * 445*36375Ssklower * RETURNS: 0 or unix error code 446*36375Ssklower * 447*36375Ssklower * SIDE EFFECTS: 448*36375Ssklower * 449*36375Ssklower * NOTES: Remember that option index pointers are really 450*36375Ssklower * offsets from the beginning of the mbuf. 451*36375Ssklower */ 452*36375Ssklower clnp_srcroute(options, oidx, route, first_hop, ifp, final_dst) 453*36375Ssklower struct mbuf *options; /* ptr to options */ 454*36375Ssklower struct clnp_optidx *oidx; /* index to options */ 455*36375Ssklower struct route *route; /* route structure */ 456*36375Ssklower struct sockaddr **first_hop; /* RETURN: fill in with ptr to firsthop */ 457*36375Ssklower struct ifnet **ifp; /* RETURN: fill in with ptr to interface */ 458*36375Ssklower struct iso_addr *final_dst; /* final destination */ 459*36375Ssklower { 460*36375Ssklower struct iso_addr dst; /* first hop specified by src rt */ 461*36375Ssklower int error = 0; /* return code */ 462*36375Ssklower 463*36375Ssklower /* 464*36375Ssklower * Check if we have run out of routes 465*36375Ssklower * If so, then try to route on destination. 466*36375Ssklower */ 467*36375Ssklower if CLNPSRCRT_TERM(oidx, options) { 468*36375Ssklower dst.isoa_len = final_dst->isoa_len; 469*36375Ssklower bcopy((caddr_t)final_dst, (caddr_t)&dst, dst.isoa_len); 470*36375Ssklower } else { 471*36375Ssklower /* 472*36375Ssklower * setup dst based on src rt specified 473*36375Ssklower */ 474*36375Ssklower dst.isoa_len = CLNPSRCRT_CLEN(oidx, options); 475*36375Ssklower bcopy(CLNPSRCRT_CADDR(oidx, options), (caddr_t)&dst, dst.isoa_len); 476*36375Ssklower } 477*36375Ssklower 478*36375Ssklower /* 479*36375Ssklower * try to route it 480*36375Ssklower */ 481*36375Ssklower error = clnp_route(&dst, route, 0, first_hop, ifp); 482*36375Ssklower if (error != 0) 483*36375Ssklower return error; 484*36375Ssklower 485*36375Ssklower /* 486*36375Ssklower * If complete src rt, first hop must be equal to dst 487*36375Ssklower */ 488*36375Ssklower if ((CLNPSRCRT_TYPE(oidx, options) == CLNPOVAL_COMPRT) && 489*36375Ssklower (!iso_addrmatch1(&(*(struct sockaddr_iso **)first_hop)->siso_addr,&dst))){ 490*36375Ssklower IFDEBUG(D_OPTIONS) 491*36375Ssklower printf("clnp_srcroute: complete src route failed\n"); 492*36375Ssklower ENDDEBUG 493*36375Ssklower return EHOSTUNREACH; /* RAH? would like ESRCRTFAILED */ 494*36375Ssklower } 495*36375Ssklower 496*36375Ssklower return error; 497*36375Ssklower } 498*36375Ssklower 499*36375Ssklower /* 500*36375Ssklower * FUNCTION: clnp_srcaddr 501*36375Ssklower * 502*36375Ssklower * PURPOSE: Build the correct source address for a datagram based on the 503*36375Ssklower * outgoing interface and firsthop. The firsthop information 504*36375Ssklower * is needed inorder to decide which addr to use if 505*36375Ssklower * >1 ISO addr is present for an ifp. 506*36375Ssklower * 507*36375Ssklower * RETURNS: a ptr to a static copy of the source address. 508*36375Ssklower * or NULL 509*36375Ssklower * 510*36375Ssklower * SIDE EFFECTS: 511*36375Ssklower * 512*36375Ssklower * NOTES: The ifp must be valid, or we will return NULL 513*36375Ssklower */ 514*36375Ssklower static struct iso_addr mysrc; 515*36375Ssklower struct iso_addr * 516*36375Ssklower clnp_srcaddr(ifp, firsthop) 517*36375Ssklower struct ifnet *ifp; /* ptr to interface to send packet on */ 518*36375Ssklower struct iso_addr *firsthop; /* ptr to first hop for packet */ 519*36375Ssklower { 520*36375Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 521*36375Ssklower struct iso_addr *maybe = NULL; 522*36375Ssklower 523*36375Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 524*36375Ssklower if (ia->ia_ifp == ifp) { 525*36375Ssklower struct iso_addr *isoa = &IA_SIS(ia)->siso_addr; 526*36375Ssklower 527*36375Ssklower IFDEBUG(D_ROUTE) 528*36375Ssklower printf("clnp_srcaddr: isoa is %s\n", clnp_iso_addrp(isoa)); 529*36375Ssklower ENDDEBUG 530*36375Ssklower 531*36375Ssklower if (iso_eqtype(isoa, firsthop)) { 532*36375Ssklower mysrc.isoa_len = isoa->isoa_len; 533*36375Ssklower bcopy((caddr_t)isoa, (caddr_t)&mysrc, mysrc.isoa_len); 534*36375Ssklower return(&mysrc); 535*36375Ssklower } else 536*36375Ssklower maybe = isoa; 537*36375Ssklower } 538*36375Ssklower } 539*36375Ssklower 540*36375Ssklower if (maybe != NULL) { 541*36375Ssklower mysrc.isoa_len = maybe->isoa_len; 542*36375Ssklower bcopy((caddr_t)maybe, (caddr_t)&mysrc, mysrc.isoa_len); 543*36375Ssklower return(&mysrc); 544*36375Ssklower } else { 545*36375Ssklower /* 546*36375Ssklower * This will only happen if there are routes involving 547*36375Ssklower * an interface that has just had all iso addresses deleted 548*36375Ssklower * from it. This will happen if esisd has added a default 549*36375Ssklower * route to an interface, and then the interface was 550*36375Ssklower * marked down. As soon as esisd tries to send a pdu on that 551*36375Ssklower * interface, it will discover it is down, and remove the 552*36375Ssklower * route. Nonetheless, there is a window for this discrepancy, 553*36375Ssklower * so we will return null here rather than panicing. 554*36375Ssklower */ 555*36375Ssklower return(NULL); 556*36375Ssklower } 557*36375Ssklower } 558*36375Ssklower 559*36375Ssklower /* 560*36375Ssklower * FUNCTION: clnp_ypocb - backwards bcopy 561*36375Ssklower * 562*36375Ssklower * PURPOSE: bcopy starting at end of src rather than beginning. 563*36375Ssklower * 564*36375Ssklower * RETURNS: none 565*36375Ssklower * 566*36375Ssklower * SIDE EFFECTS: 567*36375Ssklower * 568*36375Ssklower * NOTES: No attempt has been made to make this efficient 569*36375Ssklower */ 570*36375Ssklower clnp_ypocb(from, to, len) 571*36375Ssklower caddr_t from; /* src buffer */ 572*36375Ssklower caddr_t to; /* dst buffer */ 573*36375Ssklower u_int len; /* number of bytes */ 574*36375Ssklower { 575*36375Ssklower while (len--) 576*36375Ssklower *(to + len) = *(from + len); 577*36375Ssklower } 578*36375Ssklower 579*36375Ssklower /* 580*36375Ssklower * FUNCTION: clnp_hdrsize 581*36375Ssklower * 582*36375Ssklower * PURPOSE: Return the size of a typical clnp hdr. 583*36375Ssklower * 584*36375Ssklower * RETURNS: Size of hdr in bytes. 585*36375Ssklower * 586*36375Ssklower * SIDE EFFECTS: 587*36375Ssklower * 588*36375Ssklower * NOTES: Assumes segmenting subset. If addrlen is 589*36375Ssklower * zero, default to largest nsap address size. 590*36375Ssklower */ 591*36375Ssklower clnp_hdrsize(addrlen) 592*36375Ssklower u_char addrlen; /* length of nsap address */ 593*36375Ssklower { 594*36375Ssklower if (addrlen == 0) 595*36375Ssklower addrlen = 20; 596*36375Ssklower 597*36375Ssklower addrlen++; /* length of address byte */ 598*36375Ssklower addrlen *= 2; /* src and dst addresses */ 599*36375Ssklower addrlen += sizeof(struct clnp_fixed) + sizeof(struct clnp_segment); 600*36375Ssklower 601*36375Ssklower return(addrlen); 602*36375Ssklower } 603*36375Ssklower #endif ISO 604