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*43332Ssklower /* @(#)clnp_subr.c 7.11 (Berkeley) 06/20/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" 4943071Ssklower #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 */ 187*43332Ssklower if (dst->isoa_len == ia->ia_addr.siso_nlen && 18842949Ssklower bcmp((caddr_t)ia->ia_addr.siso_addr.isoa_genaddr, 189*43332Ssklower (caddr_t)dst->isoa_genaddr, 190*43332Ssklower ia->ia_addr.siso_nlen - ia->ia_addr.siso_tlen) == 0) 19142949Ssklower return 1; 19236375Ssklower } 19336375Ssklower return 0; 19436375Ssklower } 19536375Ssklower 19636770Ssklower /* Dec bit set if ifp qlen is greater than congest_threshold */ 19736770Ssklower int congest_threshold = 0; 19836770Ssklower 19936375Ssklower /* 20036375Ssklower * FUNCTION: clnp_forward 20136375Ssklower * 20236375Ssklower * PURPOSE: Forward the datagram passed 20336375Ssklower * clnpintr guarantees that the header will be 20436375Ssklower * contigious (a cluster mbuf will be used if necessary). 20536375Ssklower * 20636375Ssklower * If oidx is NULL, no options are present. 20736375Ssklower * 20836375Ssklower * RETURNS: nothing 20936375Ssklower * 21036375Ssklower * SIDE EFFECTS: 21136375Ssklower * 21236375Ssklower * NOTES: 21336375Ssklower */ 21436375Ssklower clnp_forward(m, len, dst, oidx, seg_off, inbound_shp) 21536375Ssklower struct mbuf *m; /* pkt to forward */ 21636375Ssklower int len; /* length of pkt */ 21736375Ssklower struct iso_addr *dst; /* destination address */ 21836375Ssklower struct clnp_optidx *oidx; /* option index */ 21936375Ssklower int seg_off;/* offset of segmentation part */ 22036375Ssklower struct snpa_hdr *inbound_shp; /* subnetwork header of inbound packet */ 22136375Ssklower { 22236375Ssklower struct clnp_fixed *clnp; /* ptr to fixed part of header */ 22336375Ssklower int error; /* return value of route function */ 22436375Ssklower struct sockaddr *next_hop; /* next hop for dgram */ 22536375Ssklower struct ifnet *ifp; /* ptr to outgoing interface */ 22637469Ssklower struct iso_ifaddr *ia = 0;/* ptr to iso name for ifp */ 22736769Ssklower struct route_iso route; /* filled in by clnp_route */ 22836375Ssklower extern int iso_systype; 22936375Ssklower 23036375Ssklower clnp = mtod(m, struct clnp_fixed *); 23136375Ssklower bzero((caddr_t)&route, sizeof(route)); /* MUST be done before "bad:" */ 23236375Ssklower 23336375Ssklower /* 23436375Ssklower * Don't forward multicast or broadcast packets 23536375Ssklower */ 23636375Ssklower if ((inbound_shp) && (IS_MULTICAST(inbound_shp->snh_dhost))) { 23736375Ssklower IFDEBUG(D_FORWARD) 23836375Ssklower printf("clnp_forward: dropping multicast packet\n"); 23936375Ssklower ENDDEBUG 24037469Ssklower clnp->cnf_type &= ~CNF_ERR_OK; /* so we don't generate an ER */ 24136375Ssklower clnp_discard(m, 0); 24239198Ssklower INCSTAT(cns_cantforward); 24336375Ssklower goto done; 24436375Ssklower } 24536375Ssklower 24636375Ssklower IFDEBUG(D_FORWARD) 24736375Ssklower printf("clnp_forward: %d bytes, to %s, options x%x\n", len, 24836375Ssklower clnp_iso_addrp(dst), oidx); 24936375Ssklower ENDDEBUG 25036375Ssklower 25136375Ssklower /* 25236375Ssklower * Decrement ttl, and if zero drop datagram 25336375Ssklower * Can't compare ttl as less than zero 'cause its a unsigned 25436375Ssklower */ 25536375Ssklower if ((clnp->cnf_ttl == 0) || (--clnp->cnf_ttl == 0)) { 25636375Ssklower IFDEBUG(D_FORWARD) 25736375Ssklower printf("clnp_forward: discarding datagram because ttl is zero\n"); 25836375Ssklower ENDDEBUG 25936375Ssklower INCSTAT(cns_ttlexpired); 26036375Ssklower clnp_discard(m, TTL_EXPTRANSIT); 26136375Ssklower goto done; 26236375Ssklower } 26336375Ssklower /* 26436375Ssklower * Route packet; special case for source rt 26536375Ssklower */ 26636375Ssklower if CLNPSRCRT_VALID(oidx) { 26736375Ssklower /* 26836375Ssklower * Update src route first 26936375Ssklower */ 27036375Ssklower clnp_update_srcrt(m, oidx); 27137469Ssklower error = clnp_srcroute(m, oidx, &route, &next_hop, &ia, dst); 27236375Ssklower } else { 27337469Ssklower error = clnp_route(dst, &route, 0, &next_hop, &ia); 27436375Ssklower } 27537469Ssklower if (error || ia == 0) { 27636375Ssklower IFDEBUG(D_FORWARD) 27736375Ssklower printf("clnp_forward: can't route packet (errno %d)\n", error); 27836375Ssklower ENDDEBUG 27936375Ssklower clnp_discard(m, ADDR_DESTUNREACH); 28039198Ssklower INCSTAT(cns_cantforward); 28136375Ssklower goto done; 28236375Ssklower } 28337469Ssklower ifp = ia->ia_ifp; 28436375Ssklower 28536375Ssklower IFDEBUG(D_FORWARD) 28636375Ssklower printf("clnp_forward: packet routed to %s\n", 28736375Ssklower clnp_iso_addrp(&((struct sockaddr_iso *)next_hop)->siso_addr)); 28836375Ssklower ENDDEBUG 28936375Ssklower 29036375Ssklower INCSTAT(cns_forward); 29136375Ssklower 29236375Ssklower /* 29336375Ssklower * If we are an intermediate system and 29436375Ssklower * we are routing outbound on the same ifp that the packet 29536375Ssklower * arrived upon, and we know the next hop snpa, 29636375Ssklower * then generate a redirect request 29736375Ssklower */ 29836375Ssklower if ((iso_systype & SNPA_IS) && (inbound_shp) && 299*43332Ssklower (ifp == inbound_shp->snh_ifp)) 300*43332Ssklower esis_rdoutput(inbound_shp, m, oidx, dst, route.ro_rt); 30136375Ssklower /* 30236375Ssklower * If options are present, update them 30336375Ssklower */ 30436375Ssklower if (oidx) { 30537469Ssklower struct iso_addr *mysrc = &ia->ia_addr.siso_addr; 30636375Ssklower if (mysrc == NULL) { 30736375Ssklower clnp_discard(m, ADDR_DESTUNREACH); 30839198Ssklower INCSTAT(cns_cantforward); 30939198Ssklower clnp_stat.cns_forward--; 31036375Ssklower goto done; 31136375Ssklower } else { 31236770Ssklower (void) clnp_dooptions(m, oidx, ifp, mysrc); 31336375Ssklower } 31436375Ssklower } 31536770Ssklower 31636770Ssklower #ifdef DECBIT 31736770Ssklower if (ifp->if_snd.ifq_len > congest_threshold) { 31836770Ssklower /* 31936770Ssklower * Congestion! Set the Dec Bit and thank Dave Oran 32036770Ssklower */ 32136770Ssklower IFDEBUG(D_FORWARD) 32236770Ssklower printf("clnp_forward: congestion experienced\n"); 32336770Ssklower ENDDEBUG 32436770Ssklower if ((oidx) && (oidx->cni_qos_formatp)) { 32536770Ssklower caddr_t qosp = CLNP_OFFTOOPT(m, oidx->cni_qos_formatp); 32636770Ssklower u_char qos = *qosp; 32736770Ssklower IFDEBUG(D_FORWARD) 32836770Ssklower printf("clnp_forward: setting congestion bit (qos x%x)\n", qos); 32936770Ssklower ENDDEBUG 33036770Ssklower if ((qos & CLNPOVAL_GLOBAL) == CLNPOVAL_GLOBAL) { 33136770Ssklower qos |= CLNPOVAL_CONGESTED; 33236770Ssklower INCSTAT(cns_congest_set); 33336770Ssklower *qosp = qos; 33436770Ssklower } 33536770Ssklower } 33636770Ssklower } 33736770Ssklower #endif DECBIT 33836375Ssklower 33936375Ssklower /* 34036375Ssklower * Dispatch the datagram if it is small enough, otherwise fragment 34136375Ssklower */ 34236375Ssklower if (len <= SN_MTU(ifp)) { 34336375Ssklower iso_gen_csum(m, CLNP_CKSUM_OFF, (int)clnp->cnf_hdr_len); 34440776Ssklower (void) (*ifp->if_output)(ifp, m, next_hop, route.ro_rt); 34536375Ssklower } else { 34640776Ssklower (void) clnp_fragment(ifp, m, next_hop, len, seg_off, /* flags */0, route.ro_rt); 34736375Ssklower } 34836375Ssklower 34936375Ssklower done: 35036375Ssklower /* 35136375Ssklower * Free route 35236375Ssklower */ 35336375Ssklower if (route.ro_rt != NULL) { 35436375Ssklower RTFREE(route.ro_rt); 35536375Ssklower } 35636375Ssklower } 35736375Ssklower 35836375Ssklower #ifdef ndef 35936375Ssklower /* 36036375Ssklower * FUNCTION: clnp_insert_addr 36136375Ssklower * 36236375Ssklower * PURPOSE: Insert the address part into a clnp datagram. 36336375Ssklower * 36436375Ssklower * RETURNS: Address of first byte after address part in datagram. 36536375Ssklower * 36636375Ssklower * SIDE EFFECTS: 36736375Ssklower * 36836375Ssklower * NOTES: Assume that there is enough space for the address part. 36936375Ssklower */ 37036375Ssklower caddr_t 37136375Ssklower clnp_insert_addr(bufp, srcp, dstp) 37236375Ssklower caddr_t bufp; /* address of where addr part goes */ 37336375Ssklower register struct iso_addr *srcp; /* ptr to src addr */ 37436375Ssklower register struct iso_addr *dstp; /* ptr to dst addr */ 37536375Ssklower { 37636375Ssklower *bufp++ = dstp->isoa_len; 37736375Ssklower (void) bcopy((caddr_t)dstp, bufp, dstp->isoa_len); 37836375Ssklower bufp += dstp->isoa_len; 37936375Ssklower 38036375Ssklower *bufp++ = srcp->isoa_len; 38136375Ssklower (void) bcopy((caddr_t)srcp, bufp, srcp->isoa_len); 38236375Ssklower bufp += srcp->isoa_len; 38336375Ssklower 38436375Ssklower return bufp; 38536375Ssklower } 38636375Ssklower 38736375Ssklower #endif ndef 38836375Ssklower 38936375Ssklower /* 39036375Ssklower * FUNCTION: clnp_route 39136375Ssklower * 39236375Ssklower * PURPOSE: Route a clnp datagram to the first hop toward its 39336375Ssklower * destination. In many cases, the first hop will be 39436375Ssklower * the destination. The address of a route 39536375Ssklower * is specified. If a routing entry is present in 39636375Ssklower * that route, and it is still up to the same destination, 39736375Ssklower * then no further action is necessary. Otherwise, a 39836375Ssklower * new routing entry will be allocated. 39936375Ssklower * 40036375Ssklower * RETURNS: route found - 0 40136375Ssklower * unix error code 40236375Ssklower * 40336375Ssklower * SIDE EFFECTS: 40436375Ssklower * 40536375Ssklower * NOTES: It is up to the caller to free the routing entry 40636375Ssklower * allocated in route. 40736375Ssklower */ 40837469Ssklower clnp_route(dst, ro, flags, first_hop, ifa) 40937469Ssklower struct iso_addr *dst; /* ptr to datagram destination */ 41037469Ssklower register struct route_iso *ro; /* existing route structure */ 41137469Ssklower int flags; /* flags for routing */ 41237469Ssklower struct sockaddr **first_hop; /* result: fill in with ptr to firsthop */ 41337469Ssklower struct iso_ifaddr **ifa; /* result: fill in with ptr to interface */ 41436375Ssklower { 41537469Ssklower if (flags & SO_DONTROUTE) { 41637469Ssklower struct iso_ifaddr *ia; 41736375Ssklower 41838476Ssklower if (ro->ro_rt) { 41938476Ssklower RTFREE(ro->ro_rt); 42038476Ssklower ro->ro_rt = 0; 42138476Ssklower } 42238476Ssklower bzero((caddr_t)&ro->ro_dst, sizeof(ro->ro_dst)); 42338476Ssklower bcopy((caddr_t)dst, (caddr_t)&ro->ro_dst.siso_addr, 42437469Ssklower 1 + (unsigned)dst->isoa_len); 42538476Ssklower ro->ro_dst.siso_family = AF_ISO; 42638476Ssklower ro->ro_dst.siso_len = sizeof(ro->ro_dst); 42738476Ssklower ia = iso_localifa(&ro->ro_dst); 42837469Ssklower if (ia == 0) 42937469Ssklower return EADDRNOTAVAIL; 43037469Ssklower if (ifa) 43138476Ssklower *ifa = ia; 43238476Ssklower if (first_hop) 43338476Ssklower *first_hop = (struct sockaddr *)&ro->ro_dst; 43437469Ssklower return 0; 43537469Ssklower } 43636375Ssklower /* 43736375Ssklower * If there is a cached route, check that it is still up and to 43836375Ssklower * the same destination. If not, free it and try again. 43936375Ssklower */ 44036375Ssklower if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || 44137469Ssklower (Bcmp(ro->ro_dst.siso_data, dst->isoa_genaddr, dst->isoa_len)))) { 44236375Ssklower IFDEBUG(D_ROUTE) 44336375Ssklower printf("clnp_route: freeing old route: ro->ro_rt 0x%x\n", 44436375Ssklower ro->ro_rt); 44536375Ssklower printf("clnp_route: old route refcnt: 0x%x\n", 44636375Ssklower ro->ro_rt->rt_refcnt); 44736375Ssklower ENDDEBUG 44836375Ssklower 44936375Ssklower /* free old route entry */ 45036375Ssklower RTFREE(ro->ro_rt); 45136375Ssklower ro->ro_rt = (struct rtentry *)0; 45236375Ssklower } else { 45336375Ssklower IFDEBUG(D_ROUTE) 45436375Ssklower printf("clnp_route: OK route exists\n"); 45536375Ssklower ENDDEBUG 45636375Ssklower } 45736375Ssklower 45836375Ssklower if (ro->ro_rt == 0) { 45936375Ssklower /* set up new route structure */ 46037469Ssklower bzero((caddr_t)&ro->ro_dst, sizeof(ro->ro_dst)); 46137469Ssklower ro->ro_dst.siso_len = sizeof(ro->ro_dst); 46237469Ssklower ro->ro_dst.siso_family = AF_ISO; 46337469Ssklower Bcopy(dst, &ro->ro_dst.siso_addr, 1 + dst->isoa_len); 46436375Ssklower /* allocate new route */ 46536375Ssklower IFDEBUG(D_ROUTE) 46636375Ssklower printf("clnp_route: allocating new route to %s\n", 46736375Ssklower clnp_iso_addrp(dst)); 46836375Ssklower ENDDEBUG 46937469Ssklower rtalloc((struct route *)ro); 47036375Ssklower } 47137469Ssklower if (ro->ro_rt == 0) 47236375Ssklower return(ENETUNREACH); /* rtalloc failed */ 47337469Ssklower ro->ro_rt->rt_use++; 47437469Ssklower if (ifa) 47537469Ssklower if ((*ifa = (struct iso_ifaddr *)ro->ro_rt->rt_ifa) == 0) 47637469Ssklower panic("clnp_route"); 47737469Ssklower if (first_hop) { 47840776Ssklower if (ro->ro_rt->rt_flags & RTF_GATEWAY) 47937469Ssklower *first_hop = ro->ro_rt->rt_gateway; 48037469Ssklower else 48137469Ssklower *first_hop = (struct sockaddr *)&ro->ro_dst; 48236375Ssklower } 48336375Ssklower return(0); 48436375Ssklower } 48536375Ssklower 48636375Ssklower /* 48736375Ssklower * FUNCTION: clnp_srcroute 48836375Ssklower * 48936375Ssklower * PURPOSE: Source route the datagram. If complete source 49036375Ssklower * routing is specified but not possible, then 49136375Ssklower * return an error. If src routing is terminated, then 49236375Ssklower * try routing on destination. 49336375Ssklower * Usage of first_hop, 49436375Ssklower * ifp, and error return is identical to clnp_route. 49536375Ssklower * 49636375Ssklower * RETURNS: 0 or unix error code 49736375Ssklower * 49836375Ssklower * SIDE EFFECTS: 49936375Ssklower * 50036375Ssklower * NOTES: Remember that option index pointers are really 50136375Ssklower * offsets from the beginning of the mbuf. 50236375Ssklower */ 503*43332Ssklower clnp_srcroute(options, oidx, ro, first_hop, ifa, final_dst) 50436375Ssklower struct mbuf *options; /* ptr to options */ 50536375Ssklower struct clnp_optidx *oidx; /* index to options */ 506*43332Ssklower struct route_iso *ro; /* route structure */ 50736375Ssklower struct sockaddr **first_hop; /* RETURN: fill in with ptr to firsthop */ 50837469Ssklower struct iso_ifaddr **ifa; /* RETURN: fill in with ptr to interface */ 50936375Ssklower struct iso_addr *final_dst; /* final destination */ 51036375Ssklower { 51136375Ssklower struct iso_addr dst; /* first hop specified by src rt */ 51236375Ssklower int error = 0; /* return code */ 51336375Ssklower 51436375Ssklower /* 51536375Ssklower * Check if we have run out of routes 51636375Ssklower * If so, then try to route on destination. 51736375Ssklower */ 51836375Ssklower if CLNPSRCRT_TERM(oidx, options) { 51936375Ssklower dst.isoa_len = final_dst->isoa_len; 52037469Ssklower bcopy(final_dst->isoa_genaddr, dst.isoa_genaddr, dst.isoa_len); 52136375Ssklower } else { 52236375Ssklower /* 52336375Ssklower * setup dst based on src rt specified 52436375Ssklower */ 52536375Ssklower dst.isoa_len = CLNPSRCRT_CLEN(oidx, options); 52637469Ssklower bcopy(CLNPSRCRT_CADDR(oidx, options), dst.isoa_genaddr, dst.isoa_len); 52736375Ssklower } 52836375Ssklower 52936375Ssklower /* 53036375Ssklower * try to route it 53136375Ssklower */ 532*43332Ssklower error = clnp_route(&dst, ro, 0, first_hop, ifa); 53336375Ssklower if (error != 0) 53436375Ssklower return error; 53536375Ssklower 53636375Ssklower /* 53736375Ssklower * If complete src rt, first hop must be equal to dst 53836375Ssklower */ 53936375Ssklower if ((CLNPSRCRT_TYPE(oidx, options) == CLNPOVAL_COMPRT) && 54036375Ssklower (!iso_addrmatch1(&(*(struct sockaddr_iso **)first_hop)->siso_addr,&dst))){ 54136375Ssklower IFDEBUG(D_OPTIONS) 54236375Ssklower printf("clnp_srcroute: complete src route failed\n"); 54336375Ssklower ENDDEBUG 54436375Ssklower return EHOSTUNREACH; /* RAH? would like ESRCRTFAILED */ 54536375Ssklower } 54636375Ssklower 54736375Ssklower return error; 54836375Ssklower } 54936375Ssklower 55036375Ssklower /* 55136375Ssklower * FUNCTION: clnp_ypocb - backwards bcopy 55236375Ssklower * 55336375Ssklower * PURPOSE: bcopy starting at end of src rather than beginning. 55436375Ssklower * 55536375Ssklower * RETURNS: none 55636375Ssklower * 55736375Ssklower * SIDE EFFECTS: 55836375Ssklower * 55936375Ssklower * NOTES: No attempt has been made to make this efficient 56036375Ssklower */ 56136375Ssklower clnp_ypocb(from, to, len) 56236375Ssklower caddr_t from; /* src buffer */ 56336375Ssklower caddr_t to; /* dst buffer */ 56436375Ssklower u_int len; /* number of bytes */ 56536375Ssklower { 56636375Ssklower while (len--) 56736375Ssklower *(to + len) = *(from + len); 56836375Ssklower } 56936375Ssklower 57036375Ssklower /* 57136375Ssklower * FUNCTION: clnp_hdrsize 57236375Ssklower * 57336375Ssklower * PURPOSE: Return the size of a typical clnp hdr. 57436375Ssklower * 57536375Ssklower * RETURNS: Size of hdr in bytes. 57636375Ssklower * 57736375Ssklower * SIDE EFFECTS: 57836375Ssklower * 57936375Ssklower * NOTES: Assumes segmenting subset. If addrlen is 58036375Ssklower * zero, default to largest nsap address size. 58136375Ssklower */ 58236375Ssklower clnp_hdrsize(addrlen) 58336375Ssklower u_char addrlen; /* length of nsap address */ 58436375Ssklower { 58536375Ssklower if (addrlen == 0) 58636375Ssklower addrlen = 20; 58736375Ssklower 58836375Ssklower addrlen++; /* length of address byte */ 58936375Ssklower addrlen *= 2; /* src and dst addresses */ 59036375Ssklower addrlen += sizeof(struct clnp_fixed) + sizeof(struct clnp_segment); 59136375Ssklower 59236375Ssklower return(addrlen); 59336375Ssklower } 59436375Ssklower #endif ISO 595