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