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 */ 2736770Ssklower /* $Header: /var/src/sys/netiso/RCS/clnp_subr.c,v 5.1 89/02/09 16:20:46 hagens Exp $ */ 2836770Ssklower /* $Source: /var/src/sys/netiso/RCS/clnp_subr.c,v $ */ 29*43071Ssklower /* @(#)clnp_subr.c 7.10 (Berkeley) 06/09/90 */ 3036375Ssklower 3136375Ssklower #ifndef lint 3236770Ssklower static char *rcsid = "$Header: /var/src/sys/netiso/RCS/clnp_subr.c,v 5.1 89/02/09 16:20:46 hagens Exp $"; 3336375Ssklower #endif lint 3436375Ssklower 3536375Ssklower #ifdef ISO 3636375Ssklower 3737469Ssklower #include "types.h" 3837469Ssklower #include "param.h" 3937469Ssklower #include "mbuf.h" 4037469Ssklower #include "domain.h" 4137469Ssklower #include "protosw.h" 4237469Ssklower #include "socket.h" 4337469Ssklower #include "socketvar.h" 4437469Ssklower #include "errno.h" 4537469Ssklower #include "time.h" 4636375Ssklower 4736375Ssklower #include "../net/if.h" 4836375Ssklower #include "../net/route.h" 49*43071Ssklower #include "../net/if_dl.h" 5036375Ssklower 5137469Ssklower #include "iso.h" 5237469Ssklower #include "iso_var.h" 5337469Ssklower #include "iso_pcb.h" 5437469Ssklower #include "iso_snpac.h" 5537469Ssklower #include "clnp.h" 5637469Ssklower #include "clnp_stat.h" 5737469Ssklower #include "argo_debug.h" 5836375Ssklower 5936375Ssklower /* 6036375Ssklower * FUNCTION: clnp_data_ck 6136375Ssklower * 6236375Ssklower * PURPOSE: Check that the amount of data in the mbuf chain is 6336375Ssklower * at least as much as the clnp header would have us 6436375Ssklower * expect. Trim mbufs if longer than expected, drop 6536375Ssklower * packet if shorter than expected. 6636375Ssklower * 6736375Ssklower * RETURNS: success - ptr to mbuf chain 6836375Ssklower * failure - 0 6936375Ssklower * 7036375Ssklower * SIDE EFFECTS: 7136375Ssklower * 7236375Ssklower * NOTES: 7336375Ssklower */ 7436375Ssklower struct mbuf * 7536375Ssklower clnp_data_ck(m, length) 7636375Ssklower register struct mbuf *m; /* ptr to mbuf chain containing hdr & data */ 7736375Ssklower int length; /* length (in bytes) of packet */ 7836375Ssklower { 7936375Ssklower register int len; /* length of data */ 8036375Ssklower register struct mbuf *mhead; /* ptr to head of chain */ 8136375Ssklower 8236375Ssklower len = -length; 8336375Ssklower mhead = m; 8436375Ssklower for (;;) { 8536375Ssklower len += m->m_len; 8636375Ssklower if (m->m_next == 0) 8736375Ssklower break; 8836375Ssklower m = m->m_next; 8936375Ssklower } 9036375Ssklower if (len != 0) { 9136375Ssklower if (len < 0) { 9236375Ssklower INCSTAT(cns_toosmall); 9336375Ssklower clnp_discard(mhead, GEN_INCOMPLETE); 9436375Ssklower return 0; 9536375Ssklower } 9636375Ssklower if (len <= m->m_len) 9736375Ssklower m->m_len -= len; 9836375Ssklower else 9936375Ssklower m_adj(mhead, -len); 10036375Ssklower } 10136375Ssklower return mhead; 10236375Ssklower } 10336375Ssklower 10436375Ssklower #ifdef ndef 10536375Ssklower /* 10636375Ssklower * FUNCTION: clnp_extract_addr 10736375Ssklower * 10836375Ssklower * PURPOSE: Extract the source and destination address from the 10936375Ssklower * supplied buffer. Place them in the supplied address buffers. 11036375Ssklower * If insufficient data is supplied, then fail. 11136375Ssklower * 11236375Ssklower * RETURNS: success - Address of first byte in the packet past 11336375Ssklower * the address part. 11436375Ssklower * failure - 0 11536375Ssklower * 11636375Ssklower * SIDE EFFECTS: 11736375Ssklower * 11836375Ssklower * NOTES: 11936375Ssklower */ 12036375Ssklower caddr_t 12136375Ssklower clnp_extract_addr(bufp, buflen, srcp, destp) 12236375Ssklower caddr_t bufp; /* ptr to buffer containing addresses */ 12336375Ssklower int buflen; /* length of buffer */ 12436375Ssklower register struct iso_addr *srcp; /* ptr to source address buffer */ 12536375Ssklower register struct iso_addr *destp; /* ptr to destination address buffer */ 12636375Ssklower { 12736375Ssklower int len; /* argument to bcopy */ 12836375Ssklower 12936375Ssklower /* 13036375Ssklower * check that we have enough data. Plus1 is for length octet 13136375Ssklower */ 13236375Ssklower if ((u_char)*bufp + 1 > buflen) { 13336375Ssklower return((caddr_t)0); 13436375Ssklower } 13536375Ssklower len = destp->isoa_len = (u_char)*bufp++; 13636375Ssklower (void) bcopy(bufp, (caddr_t)destp, len); 13736375Ssklower buflen -= len; 13836375Ssklower bufp += len; 13936375Ssklower 14036375Ssklower /* 14136375Ssklower * check that we have enough data. Plus1 is for length octet 14236375Ssklower */ 14336375Ssklower if ((u_char)*bufp + 1 > buflen) { 14436375Ssklower return((caddr_t)0); 14536375Ssklower } 14636375Ssklower len = srcp->isoa_len = (u_char)* bufp++; 14736375Ssklower (void) bcopy(bufp, (caddr_t)srcp, len); 14836375Ssklower bufp += len; 14936375Ssklower 15036375Ssklower /* 15136375Ssklower * Insure that the addresses make sense 15236375Ssklower */ 15336375Ssklower if (iso_ck_addr(srcp) && iso_ck_addr(destp)) 15436375Ssklower return bufp; 15536375Ssklower else 15636375Ssklower return (caddr_t) 0; 15736375Ssklower } 15836375Ssklower #endif ndef 15936375Ssklower 16036375Ssklower /* 16136375Ssklower * FUNCTION: clnp_ours 16236375Ssklower * 16336375Ssklower * PURPOSE: Decide whether the supplied packet is destined for 16436375Ssklower * us, or that it should be forwarded on. 16536375Ssklower * 16636375Ssklower * RETURNS: packet is for us - 1 16736375Ssklower * packet is not for us - 0 16836375Ssklower * 16936375Ssklower * SIDE EFFECTS: 17036375Ssklower * 17136375Ssklower * NOTES: 17236375Ssklower */ 17336375Ssklower clnp_ours(dst) 17436375Ssklower register struct iso_addr *dst; /* ptr to destination address */ 17536375Ssklower { 17636375Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 17736375Ssklower 17836375Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 17936375Ssklower IFDEBUG(D_ROUTE) 18042949Ssklower printf("clnp_ours: ia_sis x%x, dst x%x\n", &ia->ia_addr, 18136375Ssklower dst); 18236375Ssklower ENDDEBUG 18342949Ssklower /* 18442949Ssklower * XXX Warning: 18542949Ssklower * We are overloading siso_tlen in the if's address, as an nsel length. 18642949Ssklower */ 18742949Ssklower if (dst->isoa_len == ia->ia_addr.siso_tlen + ia->ia_addr.siso_nlen && 18842949Ssklower bcmp((caddr_t)ia->ia_addr.siso_addr.isoa_genaddr, 18942949Ssklower (caddr_t)dst->isoa_genaddr, ia->ia_addr.siso_nlen) == 0) 19042949Ssklower return 1; 19136375Ssklower } 19236375Ssklower return 0; 19336375Ssklower } 19436375Ssklower 19536770Ssklower /* Dec bit set if ifp qlen is greater than congest_threshold */ 19636770Ssklower int congest_threshold = 0; 19736770Ssklower 19836375Ssklower /* 19936375Ssklower * FUNCTION: clnp_forward 20036375Ssklower * 20136375Ssklower * PURPOSE: Forward the datagram passed 20236375Ssklower * clnpintr guarantees that the header will be 20336375Ssklower * contigious (a cluster mbuf will be used if necessary). 20436375Ssklower * 20536375Ssklower * If oidx is NULL, no options are present. 20636375Ssklower * 20736375Ssklower * RETURNS: nothing 20836375Ssklower * 20936375Ssklower * SIDE EFFECTS: 21036375Ssklower * 21136375Ssklower * NOTES: 21236375Ssklower */ 21336375Ssklower clnp_forward(m, len, dst, oidx, seg_off, inbound_shp) 21436375Ssklower struct mbuf *m; /* pkt to forward */ 21536375Ssklower int len; /* length of pkt */ 21636375Ssklower struct iso_addr *dst; /* destination address */ 21736375Ssklower struct clnp_optidx *oidx; /* option index */ 21836375Ssklower int seg_off;/* offset of segmentation part */ 21936375Ssklower struct snpa_hdr *inbound_shp; /* subnetwork header of inbound packet */ 22036375Ssklower { 22136375Ssklower struct clnp_fixed *clnp; /* ptr to fixed part of header */ 22236375Ssklower int error; /* return value of route function */ 22336375Ssklower struct sockaddr *next_hop; /* next hop for dgram */ 22436375Ssklower struct ifnet *ifp; /* ptr to outgoing interface */ 22537469Ssklower struct iso_ifaddr *ia = 0;/* ptr to iso name for ifp */ 22636769Ssklower struct route_iso route; /* filled in by clnp_route */ 22736375Ssklower extern int iso_systype; 22836375Ssklower 22936375Ssklower clnp = mtod(m, struct clnp_fixed *); 23036375Ssklower bzero((caddr_t)&route, sizeof(route)); /* MUST be done before "bad:" */ 23136375Ssklower 23236375Ssklower /* 23336375Ssklower * Don't forward multicast or broadcast packets 23436375Ssklower */ 23536375Ssklower if ((inbound_shp) && (IS_MULTICAST(inbound_shp->snh_dhost))) { 23636375Ssklower IFDEBUG(D_FORWARD) 23736375Ssklower printf("clnp_forward: dropping multicast packet\n"); 23836375Ssklower ENDDEBUG 23937469Ssklower clnp->cnf_type &= ~CNF_ERR_OK; /* so we don't generate an ER */ 24036375Ssklower clnp_discard(m, 0); 24139198Ssklower INCSTAT(cns_cantforward); 24236375Ssklower goto done; 24336375Ssklower } 24436375Ssklower 24536375Ssklower IFDEBUG(D_FORWARD) 24636375Ssklower printf("clnp_forward: %d bytes, to %s, options x%x\n", len, 24736375Ssklower clnp_iso_addrp(dst), oidx); 24836375Ssklower ENDDEBUG 24936375Ssklower 25036375Ssklower /* 25136375Ssklower * Decrement ttl, and if zero drop datagram 25236375Ssklower * Can't compare ttl as less than zero 'cause its a unsigned 25336375Ssklower */ 25436375Ssklower if ((clnp->cnf_ttl == 0) || (--clnp->cnf_ttl == 0)) { 25536375Ssklower IFDEBUG(D_FORWARD) 25636375Ssklower printf("clnp_forward: discarding datagram because ttl is zero\n"); 25736375Ssklower ENDDEBUG 25836375Ssklower INCSTAT(cns_ttlexpired); 25936375Ssklower clnp_discard(m, TTL_EXPTRANSIT); 26036375Ssklower goto done; 26136375Ssklower } 26236375Ssklower /* 26336375Ssklower * Route packet; special case for source rt 26436375Ssklower */ 26536375Ssklower if CLNPSRCRT_VALID(oidx) { 26636375Ssklower /* 26736375Ssklower * Update src route first 26836375Ssklower */ 26936375Ssklower clnp_update_srcrt(m, oidx); 27037469Ssklower error = clnp_srcroute(m, oidx, &route, &next_hop, &ia, dst); 27136375Ssklower } else { 27237469Ssklower error = clnp_route(dst, &route, 0, &next_hop, &ia); 27336375Ssklower } 27437469Ssklower if (error || ia == 0) { 27536375Ssklower IFDEBUG(D_FORWARD) 27636375Ssklower printf("clnp_forward: can't route packet (errno %d)\n", error); 27736375Ssklower ENDDEBUG 27836375Ssklower clnp_discard(m, ADDR_DESTUNREACH); 27939198Ssklower INCSTAT(cns_cantforward); 28036375Ssklower goto done; 28136375Ssklower } 28237469Ssklower ifp = ia->ia_ifp; 28336375Ssklower 28436375Ssklower IFDEBUG(D_FORWARD) 28536375Ssklower printf("clnp_forward: packet routed to %s\n", 28636375Ssklower clnp_iso_addrp(&((struct sockaddr_iso *)next_hop)->siso_addr)); 28736375Ssklower ENDDEBUG 28836375Ssklower 28936375Ssklower INCSTAT(cns_forward); 29036375Ssklower 29136375Ssklower /* 29236375Ssklower * If we are an intermediate system and 29336375Ssklower * we are routing outbound on the same ifp that the packet 29436375Ssklower * arrived upon, and we know the next hop snpa, 29536375Ssklower * then generate a redirect request 29636375Ssklower */ 29736375Ssklower if ((iso_systype & SNPA_IS) && (inbound_shp) && 29836375Ssklower (ifp == inbound_shp->snh_ifp)) { 299*43071Ssklower register struct sockaddr_dl *sdl = 300*43071Ssklower (struct sockaddr_dl *) route.ro_rt->rt_gateway; 301*43071Ssklower if (sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) 302*43071Ssklower esis_rdoutput(inbound_shp, m, oidx, dst, route.ro_rt); 30336375Ssklower } 30436375Ssklower 30536375Ssklower /* 30636375Ssklower * If options are present, update them 30736375Ssklower */ 30836375Ssklower if (oidx) { 30937469Ssklower struct iso_addr *mysrc = &ia->ia_addr.siso_addr; 31036375Ssklower if (mysrc == NULL) { 31136375Ssklower clnp_discard(m, ADDR_DESTUNREACH); 31239198Ssklower INCSTAT(cns_cantforward); 31339198Ssklower clnp_stat.cns_forward--; 31436375Ssklower goto done; 31536375Ssklower } else { 31636770Ssklower (void) clnp_dooptions(m, oidx, ifp, mysrc); 31736375Ssklower } 31836375Ssklower } 31936770Ssklower 32036770Ssklower #ifdef DECBIT 32136770Ssklower if (ifp->if_snd.ifq_len > congest_threshold) { 32236770Ssklower /* 32336770Ssklower * Congestion! Set the Dec Bit and thank Dave Oran 32436770Ssklower */ 32536770Ssklower IFDEBUG(D_FORWARD) 32636770Ssklower printf("clnp_forward: congestion experienced\n"); 32736770Ssklower ENDDEBUG 32836770Ssklower if ((oidx) && (oidx->cni_qos_formatp)) { 32936770Ssklower caddr_t qosp = CLNP_OFFTOOPT(m, oidx->cni_qos_formatp); 33036770Ssklower u_char qos = *qosp; 33136770Ssklower IFDEBUG(D_FORWARD) 33236770Ssklower printf("clnp_forward: setting congestion bit (qos x%x)\n", qos); 33336770Ssklower ENDDEBUG 33436770Ssklower if ((qos & CLNPOVAL_GLOBAL) == CLNPOVAL_GLOBAL) { 33536770Ssklower qos |= CLNPOVAL_CONGESTED; 33636770Ssklower INCSTAT(cns_congest_set); 33736770Ssklower *qosp = qos; 33836770Ssklower } 33936770Ssklower } 34036770Ssklower } 34136770Ssklower #endif DECBIT 34236375Ssklower 34336375Ssklower /* 34436375Ssklower * Dispatch the datagram if it is small enough, otherwise fragment 34536375Ssklower */ 34636375Ssklower if (len <= SN_MTU(ifp)) { 34736375Ssklower iso_gen_csum(m, CLNP_CKSUM_OFF, (int)clnp->cnf_hdr_len); 34840776Ssklower (void) (*ifp->if_output)(ifp, m, next_hop, route.ro_rt); 34936375Ssklower } else { 35040776Ssklower (void) clnp_fragment(ifp, m, next_hop, len, seg_off, /* flags */0, route.ro_rt); 35136375Ssklower } 35236375Ssklower 35336375Ssklower done: 35436375Ssklower /* 35536375Ssklower * Free route 35636375Ssklower */ 35736375Ssklower if (route.ro_rt != NULL) { 35836375Ssklower RTFREE(route.ro_rt); 35936375Ssklower } 36036375Ssklower } 36136375Ssklower 36236375Ssklower #ifdef ndef 36336375Ssklower /* 36436375Ssklower * FUNCTION: clnp_insert_addr 36536375Ssklower * 36636375Ssklower * PURPOSE: Insert the address part into a clnp datagram. 36736375Ssklower * 36836375Ssklower * RETURNS: Address of first byte after address part in datagram. 36936375Ssklower * 37036375Ssklower * SIDE EFFECTS: 37136375Ssklower * 37236375Ssklower * NOTES: Assume that there is enough space for the address part. 37336375Ssklower */ 37436375Ssklower caddr_t 37536375Ssklower clnp_insert_addr(bufp, srcp, dstp) 37636375Ssklower caddr_t bufp; /* address of where addr part goes */ 37736375Ssklower register struct iso_addr *srcp; /* ptr to src addr */ 37836375Ssklower register struct iso_addr *dstp; /* ptr to dst addr */ 37936375Ssklower { 38036375Ssklower *bufp++ = dstp->isoa_len; 38136375Ssklower (void) bcopy((caddr_t)dstp, bufp, dstp->isoa_len); 38236375Ssklower bufp += dstp->isoa_len; 38336375Ssklower 38436375Ssklower *bufp++ = srcp->isoa_len; 38536375Ssklower (void) bcopy((caddr_t)srcp, bufp, srcp->isoa_len); 38636375Ssklower bufp += srcp->isoa_len; 38736375Ssklower 38836375Ssklower return bufp; 38936375Ssklower } 39036375Ssklower 39136375Ssklower #endif ndef 39236375Ssklower 39336375Ssklower /* 39436375Ssklower * FUNCTION: clnp_route 39536375Ssklower * 39636375Ssklower * PURPOSE: Route a clnp datagram to the first hop toward its 39736375Ssklower * destination. In many cases, the first hop will be 39836375Ssklower * the destination. The address of a route 39936375Ssklower * is specified. If a routing entry is present in 40036375Ssklower * that route, and it is still up to the same destination, 40136375Ssklower * then no further action is necessary. Otherwise, a 40236375Ssklower * new routing entry will be allocated. 40336375Ssklower * 40436375Ssklower * RETURNS: route found - 0 40536375Ssklower * unix error code 40636375Ssklower * 40736375Ssklower * SIDE EFFECTS: 40836375Ssklower * 40936375Ssklower * NOTES: It is up to the caller to free the routing entry 41036375Ssklower * allocated in route. 41136375Ssklower */ 41237469Ssklower clnp_route(dst, ro, flags, first_hop, ifa) 41337469Ssklower struct iso_addr *dst; /* ptr to datagram destination */ 41437469Ssklower register struct route_iso *ro; /* existing route structure */ 41537469Ssklower int flags; /* flags for routing */ 41637469Ssklower struct sockaddr **first_hop; /* result: fill in with ptr to firsthop */ 41737469Ssklower struct iso_ifaddr **ifa; /* result: fill in with ptr to interface */ 41836375Ssklower { 41937469Ssklower if (flags & SO_DONTROUTE) { 42037469Ssklower struct iso_ifaddr *ia; 42136375Ssklower 42238476Ssklower if (ro->ro_rt) { 42338476Ssklower RTFREE(ro->ro_rt); 42438476Ssklower ro->ro_rt = 0; 42538476Ssklower } 42638476Ssklower bzero((caddr_t)&ro->ro_dst, sizeof(ro->ro_dst)); 42738476Ssklower bcopy((caddr_t)dst, (caddr_t)&ro->ro_dst.siso_addr, 42837469Ssklower 1 + (unsigned)dst->isoa_len); 42938476Ssklower ro->ro_dst.siso_family = AF_ISO; 43038476Ssklower ro->ro_dst.siso_len = sizeof(ro->ro_dst); 43138476Ssklower ia = iso_localifa(&ro->ro_dst); 43237469Ssklower if (ia == 0) 43337469Ssklower return EADDRNOTAVAIL; 43437469Ssklower if (ifa) 43538476Ssklower *ifa = ia; 43638476Ssklower if (first_hop) 43738476Ssklower *first_hop = (struct sockaddr *)&ro->ro_dst; 43837469Ssklower return 0; 43937469Ssklower } 44036375Ssklower /* 44136375Ssklower * If there is a cached route, check that it is still up and to 44236375Ssklower * the same destination. If not, free it and try again. 44336375Ssklower */ 44436375Ssklower if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || 44537469Ssklower (Bcmp(ro->ro_dst.siso_data, dst->isoa_genaddr, dst->isoa_len)))) { 44636375Ssklower IFDEBUG(D_ROUTE) 44736375Ssklower printf("clnp_route: freeing old route: ro->ro_rt 0x%x\n", 44836375Ssklower ro->ro_rt); 44936375Ssklower printf("clnp_route: old route refcnt: 0x%x\n", 45036375Ssklower ro->ro_rt->rt_refcnt); 45136375Ssklower ENDDEBUG 45236375Ssklower 45336375Ssklower /* free old route entry */ 45436375Ssklower RTFREE(ro->ro_rt); 45536375Ssklower ro->ro_rt = (struct rtentry *)0; 45636375Ssklower } else { 45736375Ssklower IFDEBUG(D_ROUTE) 45836375Ssklower printf("clnp_route: OK route exists\n"); 45936375Ssklower ENDDEBUG 46036375Ssklower } 46136375Ssklower 46236375Ssklower if (ro->ro_rt == 0) { 46336375Ssklower /* set up new route structure */ 46437469Ssklower bzero((caddr_t)&ro->ro_dst, sizeof(ro->ro_dst)); 46537469Ssklower ro->ro_dst.siso_len = sizeof(ro->ro_dst); 46637469Ssklower ro->ro_dst.siso_family = AF_ISO; 46737469Ssklower Bcopy(dst, &ro->ro_dst.siso_addr, 1 + dst->isoa_len); 46836375Ssklower /* allocate new route */ 46936375Ssklower IFDEBUG(D_ROUTE) 47036375Ssklower printf("clnp_route: allocating new route to %s\n", 47136375Ssklower clnp_iso_addrp(dst)); 47236375Ssklower ENDDEBUG 47337469Ssklower rtalloc((struct route *)ro); 47436375Ssklower } 47537469Ssklower if (ro->ro_rt == 0) 47636375Ssklower return(ENETUNREACH); /* rtalloc failed */ 47737469Ssklower ro->ro_rt->rt_use++; 47837469Ssklower if (ifa) 47937469Ssklower if ((*ifa = (struct iso_ifaddr *)ro->ro_rt->rt_ifa) == 0) 48037469Ssklower panic("clnp_route"); 48137469Ssklower if (first_hop) { 48240776Ssklower if (ro->ro_rt->rt_flags & RTF_GATEWAY) 48337469Ssklower *first_hop = ro->ro_rt->rt_gateway; 48437469Ssklower else 48537469Ssklower *first_hop = (struct sockaddr *)&ro->ro_dst; 48636375Ssklower } 48736375Ssklower return(0); 48836375Ssklower } 48936375Ssklower 49036375Ssklower /* 49136375Ssklower * FUNCTION: clnp_srcroute 49236375Ssklower * 49336375Ssklower * PURPOSE: Source route the datagram. If complete source 49436375Ssklower * routing is specified but not possible, then 49536375Ssklower * return an error. If src routing is terminated, then 49636375Ssklower * try routing on destination. 49736375Ssklower * Usage of first_hop, 49836375Ssklower * ifp, and error return is identical to clnp_route. 49936375Ssklower * 50036375Ssklower * RETURNS: 0 or unix error code 50136375Ssklower * 50236375Ssklower * SIDE EFFECTS: 50336375Ssklower * 50436375Ssklower * NOTES: Remember that option index pointers are really 50536375Ssklower * offsets from the beginning of the mbuf. 50636375Ssklower */ 50737469Ssklower clnp_srcroute(options, oidx, route, first_hop, ifa, final_dst) 50836375Ssklower struct mbuf *options; /* ptr to options */ 50936375Ssklower struct clnp_optidx *oidx; /* index to options */ 51037469Ssklower struct route_iso *route; /* route structure */ 51136375Ssklower struct sockaddr **first_hop; /* RETURN: fill in with ptr to firsthop */ 51237469Ssklower struct iso_ifaddr **ifa; /* RETURN: fill in with ptr to interface */ 51336375Ssklower struct iso_addr *final_dst; /* final destination */ 51436375Ssklower { 51536375Ssklower struct iso_addr dst; /* first hop specified by src rt */ 51636375Ssklower int error = 0; /* return code */ 51736375Ssklower 51836375Ssklower /* 51936375Ssklower * Check if we have run out of routes 52036375Ssklower * If so, then try to route on destination. 52136375Ssklower */ 52236375Ssklower if CLNPSRCRT_TERM(oidx, options) { 52336375Ssklower dst.isoa_len = final_dst->isoa_len; 52437469Ssklower bcopy(final_dst->isoa_genaddr, dst.isoa_genaddr, dst.isoa_len); 52536375Ssklower } else { 52636375Ssklower /* 52736375Ssklower * setup dst based on src rt specified 52836375Ssklower */ 52936375Ssklower dst.isoa_len = CLNPSRCRT_CLEN(oidx, options); 53037469Ssklower bcopy(CLNPSRCRT_CADDR(oidx, options), dst.isoa_genaddr, dst.isoa_len); 53136375Ssklower } 53236375Ssklower 53336375Ssklower /* 53436375Ssklower * try to route it 53536375Ssklower */ 53637469Ssklower error = clnp_route(&dst, route, 0, first_hop, ifa); 53736375Ssklower if (error != 0) 53836375Ssklower return error; 53936375Ssklower 54036375Ssklower /* 54136375Ssklower * If complete src rt, first hop must be equal to dst 54236375Ssklower */ 54336375Ssklower if ((CLNPSRCRT_TYPE(oidx, options) == CLNPOVAL_COMPRT) && 54436375Ssklower (!iso_addrmatch1(&(*(struct sockaddr_iso **)first_hop)->siso_addr,&dst))){ 54536375Ssklower IFDEBUG(D_OPTIONS) 54636375Ssklower printf("clnp_srcroute: complete src route failed\n"); 54736375Ssklower ENDDEBUG 54836375Ssklower return EHOSTUNREACH; /* RAH? would like ESRCRTFAILED */ 54936375Ssklower } 55036375Ssklower 55136375Ssklower return error; 55236375Ssklower } 55336375Ssklower 55436375Ssklower /* 55536375Ssklower * FUNCTION: clnp_ypocb - backwards bcopy 55636375Ssklower * 55736375Ssklower * PURPOSE: bcopy starting at end of src rather than beginning. 55836375Ssklower * 55936375Ssklower * RETURNS: none 56036375Ssklower * 56136375Ssklower * SIDE EFFECTS: 56236375Ssklower * 56336375Ssklower * NOTES: No attempt has been made to make this efficient 56436375Ssklower */ 56536375Ssklower clnp_ypocb(from, to, len) 56636375Ssklower caddr_t from; /* src buffer */ 56736375Ssklower caddr_t to; /* dst buffer */ 56836375Ssklower u_int len; /* number of bytes */ 56936375Ssklower { 57036375Ssklower while (len--) 57136375Ssklower *(to + len) = *(from + len); 57236375Ssklower } 57336375Ssklower 57436375Ssklower /* 57536375Ssklower * FUNCTION: clnp_hdrsize 57636375Ssklower * 57736375Ssklower * PURPOSE: Return the size of a typical clnp hdr. 57836375Ssklower * 57936375Ssklower * RETURNS: Size of hdr in bytes. 58036375Ssklower * 58136375Ssklower * SIDE EFFECTS: 58236375Ssklower * 58336375Ssklower * NOTES: Assumes segmenting subset. If addrlen is 58436375Ssklower * zero, default to largest nsap address size. 58536375Ssklower */ 58636375Ssklower clnp_hdrsize(addrlen) 58736375Ssklower u_char addrlen; /* length of nsap address */ 58836375Ssklower { 58936375Ssklower if (addrlen == 0) 59036375Ssklower addrlen = 20; 59136375Ssklower 59236375Ssklower addrlen++; /* length of address byte */ 59336375Ssklower addrlen *= 2; /* src and dst addresses */ 59436375Ssklower addrlen += sizeof(struct clnp_fixed) + sizeof(struct clnp_segment); 59536375Ssklower 59636375Ssklower return(addrlen); 59736375Ssklower } 59836375Ssklower #endif ISO 599