136375Ssklower /*********************************************************** 236375Ssklower Copyright IBM Corporation 1987 336375Ssklower 436375Ssklower All Rights Reserved 536375Ssklower 636375Ssklower Permission to use, copy, modify, and distribute this software and its 736375Ssklower documentation for any purpose and without fee is hereby granted, 836375Ssklower provided that the above copyright notice appear in all copies and that 936375Ssklower both that copyright notice and this permission notice appear in 1036375Ssklower supporting documentation, and that the name of IBM not be 1136375Ssklower used in advertising or publicity pertaining to distribution of the 1236375Ssklower software without specific, written prior permission. 1336375Ssklower 1436375Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536375Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636375Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736375Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836375Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936375Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036375Ssklower SOFTWARE. 2136375Ssklower 2236375Ssklower ******************************************************************/ 2336375Ssklower 2436375Ssklower /* 2536375Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636375Ssklower */ 2736375Ssklower /* $Header: clnp_subr.c,v 4.10 88/09/14 11:31:33 hagens Exp $ */ 2836375Ssklower /* $Source: /usr/argo/sys/netiso/RCS/clnp_subr.c,v $ */ 2936375Ssklower 3036375Ssklower #ifndef lint 3136375Ssklower static char *rcsid = "$Header: clnp_subr.c,v 4.10 88/09/14 11:31:33 hagens Exp $"; 3236375Ssklower #endif lint 3336375Ssklower 3436375Ssklower #ifdef ISO 3536375Ssklower 3636375Ssklower #include "../h/types.h" 3736375Ssklower #include "../h/param.h" 3836375Ssklower #include "../h/mbuf.h" 3936375Ssklower #include "../h/domain.h" 4036375Ssklower #include "../h/protosw.h" 4136375Ssklower #include "../h/socket.h" 4236375Ssklower #include "../h/socketvar.h" 4336375Ssklower #include "../h/errno.h" 4436375Ssklower #include "../h/time.h" 4536375Ssklower 4636375Ssklower #include "../net/if.h" 4736375Ssklower #include "../net/route.h" 4836375Ssklower 4936375Ssklower #include "../netiso/iso.h" 5036375Ssklower #include "../netiso/iso_var.h" 5136375Ssklower #include "../netiso/clnp.h" 5236375Ssklower #include "../netiso/clnp_stat.h" 5336375Ssklower #include "../netiso/argo_debug.h" 5436375Ssklower #include "../netiso/iso_snpac.h" 5536375Ssklower 5636375Ssklower /* 5736375Ssklower * FUNCTION: clnp_data_ck 5836375Ssklower * 5936375Ssklower * PURPOSE: Check that the amount of data in the mbuf chain is 6036375Ssklower * at least as much as the clnp header would have us 6136375Ssklower * expect. Trim mbufs if longer than expected, drop 6236375Ssklower * packet if shorter than expected. 6336375Ssklower * 6436375Ssklower * RETURNS: success - ptr to mbuf chain 6536375Ssklower * failure - 0 6636375Ssklower * 6736375Ssklower * SIDE EFFECTS: 6836375Ssklower * 6936375Ssklower * NOTES: 7036375Ssklower */ 7136375Ssklower struct mbuf * 7236375Ssklower clnp_data_ck(m, length) 7336375Ssklower register struct mbuf *m; /* ptr to mbuf chain containing hdr & data */ 7436375Ssklower int length; /* length (in bytes) of packet */ 7536375Ssklower { 7636375Ssklower register int len; /* length of data */ 7736375Ssklower register struct mbuf *mhead; /* ptr to head of chain */ 7836375Ssklower 7936375Ssklower len = -length; 8036375Ssklower mhead = m; 8136375Ssklower for (;;) { 8236375Ssklower len += m->m_len; 8336375Ssklower if (m->m_next == 0) 8436375Ssklower break; 8536375Ssklower m = m->m_next; 8636375Ssklower } 8736375Ssklower if (len != 0) { 8836375Ssklower if (len < 0) { 8936375Ssklower INCSTAT(cns_toosmall); 9036375Ssklower clnp_discard(mhead, GEN_INCOMPLETE); 9136375Ssklower return 0; 9236375Ssklower } 9336375Ssklower if (len <= m->m_len) 9436375Ssklower m->m_len -= len; 9536375Ssklower else 9636375Ssklower m_adj(mhead, -len); 9736375Ssklower } 9836375Ssklower return mhead; 9936375Ssklower } 10036375Ssklower 10136375Ssklower #ifdef ndef 10236375Ssklower /* 10336375Ssklower * FUNCTION: clnp_extract_addr 10436375Ssklower * 10536375Ssklower * PURPOSE: Extract the source and destination address from the 10636375Ssklower * supplied buffer. Place them in the supplied address buffers. 10736375Ssklower * If insufficient data is supplied, then fail. 10836375Ssklower * 10936375Ssklower * RETURNS: success - Address of first byte in the packet past 11036375Ssklower * the address part. 11136375Ssklower * failure - 0 11236375Ssklower * 11336375Ssklower * SIDE EFFECTS: 11436375Ssklower * 11536375Ssklower * NOTES: 11636375Ssklower */ 11736375Ssklower caddr_t 11836375Ssklower clnp_extract_addr(bufp, buflen, srcp, destp) 11936375Ssklower caddr_t bufp; /* ptr to buffer containing addresses */ 12036375Ssklower int buflen; /* length of buffer */ 12136375Ssklower register struct iso_addr *srcp; /* ptr to source address buffer */ 12236375Ssklower register struct iso_addr *destp; /* ptr to destination address buffer */ 12336375Ssklower { 12436375Ssklower int len; /* argument to bcopy */ 12536375Ssklower 12636375Ssklower /* 12736375Ssklower * check that we have enough data. Plus1 is for length octet 12836375Ssklower */ 12936375Ssklower if ((u_char)*bufp + 1 > buflen) { 13036375Ssklower return((caddr_t)0); 13136375Ssklower } 13236375Ssklower len = destp->isoa_len = (u_char)*bufp++; 13336375Ssklower (void) bcopy(bufp, (caddr_t)destp, len); 13436375Ssklower buflen -= len; 13536375Ssklower bufp += len; 13636375Ssklower 13736375Ssklower /* 13836375Ssklower * check that we have enough data. Plus1 is for length octet 13936375Ssklower */ 14036375Ssklower if ((u_char)*bufp + 1 > buflen) { 14136375Ssklower return((caddr_t)0); 14236375Ssklower } 14336375Ssklower len = srcp->isoa_len = (u_char)* bufp++; 14436375Ssklower (void) bcopy(bufp, (caddr_t)srcp, len); 14536375Ssklower bufp += len; 14636375Ssklower 14736375Ssklower /* 14836375Ssklower * Insure that the addresses make sense 14936375Ssklower */ 15036375Ssklower if (iso_ck_addr(srcp) && iso_ck_addr(destp)) 15136375Ssklower return bufp; 15236375Ssklower else 15336375Ssklower return (caddr_t) 0; 15436375Ssklower } 15536375Ssklower #endif ndef 15636375Ssklower 15736375Ssklower /* 15836375Ssklower * FUNCTION: clnp_ours 15936375Ssklower * 16036375Ssklower * PURPOSE: Decide whether the supplied packet is destined for 16136375Ssklower * us, or that it should be forwarded on. 16236375Ssklower * 16336375Ssklower * RETURNS: packet is for us - 1 16436375Ssklower * packet is not for us - 0 16536375Ssklower * 16636375Ssklower * SIDE EFFECTS: 16736375Ssklower * 16836375Ssklower * NOTES: 16936375Ssklower */ 17036375Ssklower clnp_ours(dst) 17136375Ssklower register struct iso_addr *dst; /* ptr to destination address */ 17236375Ssklower { 17336375Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 17436375Ssklower 17536375Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 17636375Ssklower IFDEBUG(D_ROUTE) 17736375Ssklower printf("clnp_ours: ia_sis x%x, dst x%x\n", &IA_SIS(ia)->siso_addr, 17836375Ssklower dst); 17936375Ssklower ENDDEBUG 18036375Ssklower /* PHASE 2: uses iso_addrmatch & mask from iso_ifaddr */ 18136375Ssklower if (iso_addrmatch1(&IA_SIS(ia)->siso_addr, dst)) 18236375Ssklower return 1; 18336375Ssklower } 18436375Ssklower return 0; 18536375Ssklower } 18636375Ssklower 18736375Ssklower /* 18836375Ssklower * FUNCTION: clnp_forward 18936375Ssklower * 19036375Ssklower * PURPOSE: Forward the datagram passed 19136375Ssklower * clnpintr guarantees that the header will be 19236375Ssklower * contigious (a cluster mbuf will be used if necessary). 19336375Ssklower * 19436375Ssklower * If oidx is NULL, no options are present. 19536375Ssklower * 19636375Ssklower * RETURNS: nothing 19736375Ssklower * 19836375Ssklower * SIDE EFFECTS: 19936375Ssklower * 20036375Ssklower * NOTES: 20136375Ssklower */ 20236375Ssklower clnp_forward(m, len, dst, oidx, seg_off, inbound_shp) 20336375Ssklower struct mbuf *m; /* pkt to forward */ 20436375Ssklower int len; /* length of pkt */ 20536375Ssklower struct iso_addr *dst; /* destination address */ 20636375Ssklower struct clnp_optidx *oidx; /* option index */ 20736375Ssklower int seg_off;/* offset of segmentation part */ 20836375Ssklower struct snpa_hdr *inbound_shp; /* subnetwork header of inbound packet */ 20936375Ssklower { 21036375Ssklower struct clnp_fixed *clnp; /* ptr to fixed part of header */ 21136375Ssklower int error; /* return value of route function */ 21236375Ssklower struct sockaddr *next_hop; /* next hop for dgram */ 21336375Ssklower struct ifnet *ifp; /* ptr to outgoing interface */ 214*36769Ssklower struct route_iso route; /* filled in by clnp_route */ 21536375Ssklower extern int iso_systype; 21636375Ssklower 21736375Ssklower clnp = mtod(m, struct clnp_fixed *); 21836375Ssklower bzero((caddr_t)&route, sizeof(route)); /* MUST be done before "bad:" */ 21936375Ssklower 22036375Ssklower /* 22136375Ssklower * Don't forward multicast or broadcast packets 22236375Ssklower */ 22336375Ssklower if ((inbound_shp) && (IS_MULTICAST(inbound_shp->snh_dhost))) { 22436375Ssklower IFDEBUG(D_FORWARD) 22536375Ssklower printf("clnp_forward: dropping multicast packet\n"); 22636375Ssklower ENDDEBUG 22736375Ssklower clnp->cnf_err_ok = 0; /* so we don't generate an ER */ 22836375Ssklower clnp_discard(m, 0); 22936375Ssklower goto done; 23036375Ssklower } 23136375Ssklower 23236375Ssklower IFDEBUG(D_FORWARD) 23336375Ssklower printf("clnp_forward: %d bytes, to %s, options x%x\n", len, 23436375Ssklower clnp_iso_addrp(dst), oidx); 23536375Ssklower ENDDEBUG 23636375Ssklower 23736375Ssklower /* 23836375Ssklower * Decrement ttl, and if zero drop datagram 23936375Ssklower * Can't compare ttl as less than zero 'cause its a unsigned 24036375Ssklower */ 24136375Ssklower if ((clnp->cnf_ttl == 0) || (--clnp->cnf_ttl == 0)) { 24236375Ssklower IFDEBUG(D_FORWARD) 24336375Ssklower printf("clnp_forward: discarding datagram because ttl is zero\n"); 24436375Ssklower ENDDEBUG 24536375Ssklower INCSTAT(cns_ttlexpired); 24636375Ssklower clnp_discard(m, TTL_EXPTRANSIT); 24736375Ssklower goto done; 24836375Ssklower } 24936375Ssklower 25036375Ssklower /* 25136375Ssklower * Route packet; special case for source rt 25236375Ssklower */ 25336375Ssklower if CLNPSRCRT_VALID(oidx) { 25436375Ssklower /* 25536375Ssklower * Update src route first 25636375Ssklower */ 25736375Ssklower clnp_update_srcrt(m, oidx); 25836375Ssklower error = clnp_srcroute(m, oidx, &route, &next_hop, &ifp, dst); 25936375Ssklower } else { 26036375Ssklower error = clnp_route(dst, &route, 0, &next_hop, &ifp); 26136375Ssklower } 26236375Ssklower if (error) { 26336375Ssklower IFDEBUG(D_FORWARD) 26436375Ssklower printf("clnp_forward: can't route packet (errno %d)\n", error); 26536375Ssklower ENDDEBUG 26636375Ssklower clnp_discard(m, ADDR_DESTUNREACH); 26736375Ssklower goto done; 26836375Ssklower } 26936375Ssklower 27036375Ssklower IFDEBUG(D_FORWARD) 27136375Ssklower printf("clnp_forward: packet routed to %s\n", 27236375Ssklower clnp_iso_addrp(&((struct sockaddr_iso *)next_hop)->siso_addr)); 27336375Ssklower ENDDEBUG 27436375Ssklower 27536375Ssklower INCSTAT(cns_forward); 27636375Ssklower 27736375Ssklower /* 27836375Ssklower * If we are an intermediate system and 27936375Ssklower * we are routing outbound on the same ifp that the packet 28036375Ssklower * arrived upon, and we know the next hop snpa, 28136375Ssklower * then generate a redirect request 28236375Ssklower */ 28336375Ssklower if ((iso_systype & SNPA_IS) && (inbound_shp) && 28436375Ssklower (ifp == inbound_shp->snh_ifp)) { 28536375Ssklower struct snpa_cache *sc; 28636375Ssklower 28736375Ssklower sc = snpac_look(&((struct sockaddr_iso *)next_hop)->siso_addr); 28836375Ssklower if (sc != NULL) { 28936375Ssklower esis_rdoutput(inbound_shp, m, oidx, dst, sc); 29036375Ssklower } 29136375Ssklower } 29236375Ssklower 29336375Ssklower /* 29436375Ssklower * If options are present, update them 29536375Ssklower */ 29636375Ssklower if (oidx) { 29736375Ssklower struct iso_addr *mysrc = 29836375Ssklower clnp_srcaddr(ifp, &((struct sockaddr_iso *)next_hop)->siso_addr); 29936375Ssklower if (mysrc == NULL) { 30036375Ssklower clnp_discard(m, ADDR_DESTUNREACH); 30136375Ssklower goto done; 30236375Ssklower } else { 30336375Ssklower (void) clnp_dooptions(m, oidx, ifp, mysrc); 30436375Ssklower } 30536375Ssklower } 30636375Ssklower 30736375Ssklower /* 30836375Ssklower * Dispatch the datagram if it is small enough, otherwise fragment 30936375Ssklower */ 31036375Ssklower if (len <= SN_MTU(ifp)) { 31136375Ssklower iso_gen_csum(m, CLNP_CKSUM_OFF, (int)clnp->cnf_hdr_len); 31236375Ssklower (void) (*ifp->if_output)(ifp, m, next_hop); 31336375Ssklower } else { 31436375Ssklower (void) clnp_fragment(ifp, m, next_hop, len, seg_off, /* flags */0); 31536375Ssklower } 31636375Ssklower 31736375Ssklower done: 31836375Ssklower /* 31936375Ssklower * Free route 32036375Ssklower */ 32136375Ssklower if (route.ro_rt != NULL) { 32236375Ssklower RTFREE(route.ro_rt); 32336375Ssklower } 32436375Ssklower } 32536375Ssklower 32636375Ssklower #ifdef ndef 32736375Ssklower /* 32836375Ssklower * FUNCTION: clnp_insert_addr 32936375Ssklower * 33036375Ssklower * PURPOSE: Insert the address part into a clnp datagram. 33136375Ssklower * 33236375Ssklower * RETURNS: Address of first byte after address part in datagram. 33336375Ssklower * 33436375Ssklower * SIDE EFFECTS: 33536375Ssklower * 33636375Ssklower * NOTES: Assume that there is enough space for the address part. 33736375Ssklower */ 33836375Ssklower caddr_t 33936375Ssklower clnp_insert_addr(bufp, srcp, dstp) 34036375Ssklower caddr_t bufp; /* address of where addr part goes */ 34136375Ssklower register struct iso_addr *srcp; /* ptr to src addr */ 34236375Ssklower register struct iso_addr *dstp; /* ptr to dst addr */ 34336375Ssklower { 34436375Ssklower *bufp++ = dstp->isoa_len; 34536375Ssklower (void) bcopy((caddr_t)dstp, bufp, dstp->isoa_len); 34636375Ssklower bufp += dstp->isoa_len; 34736375Ssklower 34836375Ssklower *bufp++ = srcp->isoa_len; 34936375Ssklower (void) bcopy((caddr_t)srcp, bufp, srcp->isoa_len); 35036375Ssklower bufp += srcp->isoa_len; 35136375Ssklower 35236375Ssklower return bufp; 35336375Ssklower } 35436375Ssklower 35536375Ssklower #endif ndef 35636375Ssklower 35736375Ssklower /* 35836375Ssklower * FUNCTION: clnp_route 35936375Ssklower * 36036375Ssklower * PURPOSE: Route a clnp datagram to the first hop toward its 36136375Ssklower * destination. In many cases, the first hop will be 36236375Ssklower * the destination. The address of a route 36336375Ssklower * is specified. If a routing entry is present in 36436375Ssklower * that route, and it is still up to the same destination, 36536375Ssklower * then no further action is necessary. Otherwise, a 36636375Ssklower * new routing entry will be allocated. 36736375Ssklower * 36836375Ssklower * RETURNS: route found - 0 36936375Ssklower * unix error code 37036375Ssklower * 37136375Ssklower * SIDE EFFECTS: 37236375Ssklower * 37336375Ssklower * NOTES: It is up to the caller to free the routing entry 37436375Ssklower * allocated in route. 37536375Ssklower */ 37636375Ssklower clnp_route(dst, ro, flags, first_hop, ifp) 37736375Ssklower struct iso_addr *dst; /* ptr to datagram destination */ 378*36769Ssklower struct route_iso *ro; /* existing route structure */ 37936375Ssklower int flags; /* flags for routing */ 38036375Ssklower struct sockaddr **first_hop; /* result: fill in with ptr to firsthop */ 38136375Ssklower struct ifnet **ifp; /* result: fill in with ptr to interface */ 38236375Ssklower { 38336375Ssklower register struct sockaddr_iso *ro_dst; /* ptr to route's destination */ 38436375Ssklower 38536375Ssklower ro_dst = (struct sockaddr_iso *)&ro->ro_dst; 38636375Ssklower 38736375Ssklower /* 38836375Ssklower * If there is a cached route, check that it is still up and to 38936375Ssklower * the same destination. If not, free it and try again. 39036375Ssklower */ 39136375Ssklower if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || 39236375Ssklower (!iso_addrmatch1(&ro_dst->siso_addr, dst)))) { 39336375Ssklower IFDEBUG(D_ROUTE) 39436375Ssklower printf("clnp_route: freeing old route: ro->ro_rt 0x%x\n", 39536375Ssklower ro->ro_rt); 39636375Ssklower printf("clnp_route: old route refcnt: 0x%x\n", 39736375Ssklower ro->ro_rt->rt_refcnt); 39836375Ssklower ENDDEBUG 39936375Ssklower 40036375Ssklower /* free old route entry */ 40136375Ssklower RTFREE(ro->ro_rt); 40236375Ssklower ro->ro_rt = (struct rtentry *)0; 40336375Ssklower } else { 40436375Ssklower IFDEBUG(D_ROUTE) 40536375Ssklower printf("clnp_route: OK route exists\n"); 40636375Ssklower ENDDEBUG 40736375Ssklower } 40836375Ssklower 40936375Ssklower if (ro->ro_rt == 0) { 41036375Ssklower /* set up new route structure */ 41136375Ssklower ro_dst->siso_family = AF_ISO; 41236375Ssklower ro_dst->siso_addr = *dst; 41336375Ssklower 41436375Ssklower /* allocate new route */ 41536375Ssklower IFDEBUG(D_ROUTE) 41636375Ssklower printf("clnp_route: allocating new route to %s\n", 41736375Ssklower clnp_iso_addrp(dst)); 41836375Ssklower ENDDEBUG 41936375Ssklower rtalloc(ro); 42036375Ssklower } 42136375Ssklower 42236375Ssklower if ((ro->ro_rt == 0) || ((*ifp = ro->ro_rt->rt_ifp) == 0)) { 42336375Ssklower return(ENETUNREACH); /* rtalloc failed */ 42436375Ssklower } 42536375Ssklower 42636375Ssklower ro->ro_rt->rt_use++; 42736375Ssklower if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 42836375Ssklower *first_hop = &ro->ro_rt->rt_gateway; 42936375Ssklower else 43036375Ssklower *first_hop = (struct sockaddr *)ro_dst; 43136375Ssklower 43236375Ssklower return(0); 43336375Ssklower } 43436375Ssklower 43536375Ssklower /* 43636375Ssklower * FUNCTION: clnp_srcroute 43736375Ssklower * 43836375Ssklower * PURPOSE: Source route the datagram. If complete source 43936375Ssklower * routing is specified but not possible, then 44036375Ssklower * return an error. If src routing is terminated, then 44136375Ssklower * try routing on destination. 44236375Ssklower * Usage of first_hop, 44336375Ssklower * ifp, and error return is identical to clnp_route. 44436375Ssklower * 44536375Ssklower * RETURNS: 0 or unix error code 44636375Ssklower * 44736375Ssklower * SIDE EFFECTS: 44836375Ssklower * 44936375Ssklower * NOTES: Remember that option index pointers are really 45036375Ssklower * offsets from the beginning of the mbuf. 45136375Ssklower */ 45236375Ssklower clnp_srcroute(options, oidx, route, first_hop, ifp, final_dst) 45336375Ssklower struct mbuf *options; /* ptr to options */ 45436375Ssklower struct clnp_optidx *oidx; /* index to options */ 45536375Ssklower struct route *route; /* route structure */ 45636375Ssklower struct sockaddr **first_hop; /* RETURN: fill in with ptr to firsthop */ 45736375Ssklower struct ifnet **ifp; /* RETURN: fill in with ptr to interface */ 45836375Ssklower struct iso_addr *final_dst; /* final destination */ 45936375Ssklower { 46036375Ssklower struct iso_addr dst; /* first hop specified by src rt */ 46136375Ssklower int error = 0; /* return code */ 46236375Ssklower 46336375Ssklower /* 46436375Ssklower * Check if we have run out of routes 46536375Ssklower * If so, then try to route on destination. 46636375Ssklower */ 46736375Ssklower if CLNPSRCRT_TERM(oidx, options) { 46836375Ssklower dst.isoa_len = final_dst->isoa_len; 46936375Ssklower bcopy((caddr_t)final_dst, (caddr_t)&dst, dst.isoa_len); 47036375Ssklower } else { 47136375Ssklower /* 47236375Ssklower * setup dst based on src rt specified 47336375Ssklower */ 47436375Ssklower dst.isoa_len = CLNPSRCRT_CLEN(oidx, options); 47536375Ssklower bcopy(CLNPSRCRT_CADDR(oidx, options), (caddr_t)&dst, dst.isoa_len); 47636375Ssklower } 47736375Ssklower 47836375Ssklower /* 47936375Ssklower * try to route it 48036375Ssklower */ 48136375Ssklower error = clnp_route(&dst, route, 0, first_hop, ifp); 48236375Ssklower if (error != 0) 48336375Ssklower return error; 48436375Ssklower 48536375Ssklower /* 48636375Ssklower * If complete src rt, first hop must be equal to dst 48736375Ssklower */ 48836375Ssklower if ((CLNPSRCRT_TYPE(oidx, options) == CLNPOVAL_COMPRT) && 48936375Ssklower (!iso_addrmatch1(&(*(struct sockaddr_iso **)first_hop)->siso_addr,&dst))){ 49036375Ssklower IFDEBUG(D_OPTIONS) 49136375Ssklower printf("clnp_srcroute: complete src route failed\n"); 49236375Ssklower ENDDEBUG 49336375Ssklower return EHOSTUNREACH; /* RAH? would like ESRCRTFAILED */ 49436375Ssklower } 49536375Ssklower 49636375Ssklower return error; 49736375Ssklower } 49836375Ssklower 49936375Ssklower /* 50036375Ssklower * FUNCTION: clnp_srcaddr 50136375Ssklower * 50236375Ssklower * PURPOSE: Build the correct source address for a datagram based on the 50336375Ssklower * outgoing interface and firsthop. The firsthop information 50436375Ssklower * is needed inorder to decide which addr to use if 50536375Ssklower * >1 ISO addr is present for an ifp. 50636375Ssklower * 50736375Ssklower * RETURNS: a ptr to a static copy of the source address. 50836375Ssklower * or NULL 50936375Ssklower * 51036375Ssklower * SIDE EFFECTS: 51136375Ssklower * 51236375Ssklower * NOTES: The ifp must be valid, or we will return NULL 51336375Ssklower */ 51436375Ssklower static struct iso_addr mysrc; 51536375Ssklower struct iso_addr * 51636375Ssklower clnp_srcaddr(ifp, firsthop) 51736375Ssklower struct ifnet *ifp; /* ptr to interface to send packet on */ 51836375Ssklower struct iso_addr *firsthop; /* ptr to first hop for packet */ 51936375Ssklower { 52036375Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 52136375Ssklower struct iso_addr *maybe = NULL; 52236375Ssklower 52336375Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 52436375Ssklower if (ia->ia_ifp == ifp) { 52536375Ssklower struct iso_addr *isoa = &IA_SIS(ia)->siso_addr; 52636375Ssklower 52736375Ssklower IFDEBUG(D_ROUTE) 52836375Ssklower printf("clnp_srcaddr: isoa is %s\n", clnp_iso_addrp(isoa)); 52936375Ssklower ENDDEBUG 53036375Ssklower 53136375Ssklower if (iso_eqtype(isoa, firsthop)) { 53236375Ssklower mysrc.isoa_len = isoa->isoa_len; 53336375Ssklower bcopy((caddr_t)isoa, (caddr_t)&mysrc, mysrc.isoa_len); 53436375Ssklower return(&mysrc); 53536375Ssklower } else 53636375Ssklower maybe = isoa; 53736375Ssklower } 53836375Ssklower } 53936375Ssklower 54036375Ssklower if (maybe != NULL) { 54136375Ssklower mysrc.isoa_len = maybe->isoa_len; 54236375Ssklower bcopy((caddr_t)maybe, (caddr_t)&mysrc, mysrc.isoa_len); 54336375Ssklower return(&mysrc); 54436375Ssklower } else { 54536375Ssklower /* 54636375Ssklower * This will only happen if there are routes involving 54736375Ssklower * an interface that has just had all iso addresses deleted 54836375Ssklower * from it. This will happen if esisd has added a default 54936375Ssklower * route to an interface, and then the interface was 55036375Ssklower * marked down. As soon as esisd tries to send a pdu on that 55136375Ssklower * interface, it will discover it is down, and remove the 55236375Ssklower * route. Nonetheless, there is a window for this discrepancy, 55336375Ssklower * so we will return null here rather than panicing. 55436375Ssklower */ 55536375Ssklower return(NULL); 55636375Ssklower } 55736375Ssklower } 55836375Ssklower 55936375Ssklower /* 56036375Ssklower * FUNCTION: clnp_ypocb - backwards bcopy 56136375Ssklower * 56236375Ssklower * PURPOSE: bcopy starting at end of src rather than beginning. 56336375Ssklower * 56436375Ssklower * RETURNS: none 56536375Ssklower * 56636375Ssklower * SIDE EFFECTS: 56736375Ssklower * 56836375Ssklower * NOTES: No attempt has been made to make this efficient 56936375Ssklower */ 57036375Ssklower clnp_ypocb(from, to, len) 57136375Ssklower caddr_t from; /* src buffer */ 57236375Ssklower caddr_t to; /* dst buffer */ 57336375Ssklower u_int len; /* number of bytes */ 57436375Ssklower { 57536375Ssklower while (len--) 57636375Ssklower *(to + len) = *(from + len); 57736375Ssklower } 57836375Ssklower 57936375Ssklower /* 58036375Ssklower * FUNCTION: clnp_hdrsize 58136375Ssklower * 58236375Ssklower * PURPOSE: Return the size of a typical clnp hdr. 58336375Ssklower * 58436375Ssklower * RETURNS: Size of hdr in bytes. 58536375Ssklower * 58636375Ssklower * SIDE EFFECTS: 58736375Ssklower * 58836375Ssklower * NOTES: Assumes segmenting subset. If addrlen is 58936375Ssklower * zero, default to largest nsap address size. 59036375Ssklower */ 59136375Ssklower clnp_hdrsize(addrlen) 59236375Ssklower u_char addrlen; /* length of nsap address */ 59336375Ssklower { 59436375Ssklower if (addrlen == 0) 59536375Ssklower addrlen = 20; 59636375Ssklower 59736375Ssklower addrlen++; /* length of address byte */ 59836375Ssklower addrlen *= 2; /* src and dst addresses */ 59936375Ssklower addrlen += sizeof(struct clnp_fixed) + sizeof(struct clnp_segment); 60036375Ssklower 60136375Ssklower return(addrlen); 60236375Ssklower } 60336375Ssklower #endif ISO 604