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 $ */ 2936375Ssklower 3036375Ssklower #ifndef lint 3136770Ssklower static char *rcsid = "$Header: /var/src/sys/netiso/RCS/clnp_subr.c,v 5.1 89/02/09 16:20:46 hagens Exp $"; 3236375Ssklower #endif lint 3336375Ssklower 3436375Ssklower #ifdef ISO 3536375Ssklower 3637469Ssklower #include "types.h" 3737469Ssklower #include "param.h" 3837469Ssklower #include "mbuf.h" 3937469Ssklower #include "domain.h" 4037469Ssklower #include "protosw.h" 4137469Ssklower #include "socket.h" 4237469Ssklower #include "socketvar.h" 4337469Ssklower #include "errno.h" 4437469Ssklower #include "time.h" 4536375Ssklower 4636375Ssklower #include "../net/if.h" 4736375Ssklower #include "../net/route.h" 4836375Ssklower 4937469Ssklower #include "iso.h" 5037469Ssklower #include "iso_var.h" 5137469Ssklower #include "iso_pcb.h" 5237469Ssklower #include "iso_snpac.h" 5337469Ssklower #include "clnp.h" 5437469Ssklower #include "clnp_stat.h" 5537469Ssklower #include "argo_debug.h" 5636375Ssklower 5736375Ssklower /* 5836375Ssklower * FUNCTION: clnp_data_ck 5936375Ssklower * 6036375Ssklower * PURPOSE: Check that the amount of data in the mbuf chain is 6136375Ssklower * at least as much as the clnp header would have us 6236375Ssklower * expect. Trim mbufs if longer than expected, drop 6336375Ssklower * packet if shorter than expected. 6436375Ssklower * 6536375Ssklower * RETURNS: success - ptr to mbuf chain 6636375Ssklower * failure - 0 6736375Ssklower * 6836375Ssklower * SIDE EFFECTS: 6936375Ssklower * 7036375Ssklower * NOTES: 7136375Ssklower */ 7236375Ssklower struct mbuf * 7336375Ssklower clnp_data_ck(m, length) 7436375Ssklower register struct mbuf *m; /* ptr to mbuf chain containing hdr & data */ 7536375Ssklower int length; /* length (in bytes) of packet */ 7636375Ssklower { 7736375Ssklower register int len; /* length of data */ 7836375Ssklower register struct mbuf *mhead; /* ptr to head of chain */ 7936375Ssklower 8036375Ssklower len = -length; 8136375Ssklower mhead = m; 8236375Ssklower for (;;) { 8336375Ssklower len += m->m_len; 8436375Ssklower if (m->m_next == 0) 8536375Ssklower break; 8636375Ssklower m = m->m_next; 8736375Ssklower } 8836375Ssklower if (len != 0) { 8936375Ssklower if (len < 0) { 9036375Ssklower INCSTAT(cns_toosmall); 9136375Ssklower clnp_discard(mhead, GEN_INCOMPLETE); 9236375Ssklower return 0; 9336375Ssklower } 9436375Ssklower if (len <= m->m_len) 9536375Ssklower m->m_len -= len; 9636375Ssklower else 9736375Ssklower m_adj(mhead, -len); 9836375Ssklower } 9936375Ssklower return mhead; 10036375Ssklower } 10136375Ssklower 10236375Ssklower #ifdef ndef 10336375Ssklower /* 10436375Ssklower * FUNCTION: clnp_extract_addr 10536375Ssklower * 10636375Ssklower * PURPOSE: Extract the source and destination address from the 10736375Ssklower * supplied buffer. Place them in the supplied address buffers. 10836375Ssklower * If insufficient data is supplied, then fail. 10936375Ssklower * 11036375Ssklower * RETURNS: success - Address of first byte in the packet past 11136375Ssklower * the address part. 11236375Ssklower * failure - 0 11336375Ssklower * 11436375Ssklower * SIDE EFFECTS: 11536375Ssklower * 11636375Ssklower * NOTES: 11736375Ssklower */ 11836375Ssklower caddr_t 11936375Ssklower clnp_extract_addr(bufp, buflen, srcp, destp) 12036375Ssklower caddr_t bufp; /* ptr to buffer containing addresses */ 12136375Ssklower int buflen; /* length of buffer */ 12236375Ssklower register struct iso_addr *srcp; /* ptr to source address buffer */ 12336375Ssklower register struct iso_addr *destp; /* ptr to destination address buffer */ 12436375Ssklower { 12536375Ssklower int len; /* argument to bcopy */ 12636375Ssklower 12736375Ssklower /* 12836375Ssklower * check that we have enough data. Plus1 is for length octet 12936375Ssklower */ 13036375Ssklower if ((u_char)*bufp + 1 > buflen) { 13136375Ssklower return((caddr_t)0); 13236375Ssklower } 13336375Ssklower len = destp->isoa_len = (u_char)*bufp++; 13436375Ssklower (void) bcopy(bufp, (caddr_t)destp, len); 13536375Ssklower buflen -= len; 13636375Ssklower bufp += len; 13736375Ssklower 13836375Ssklower /* 13936375Ssklower * check that we have enough data. Plus1 is for length octet 14036375Ssklower */ 14136375Ssklower if ((u_char)*bufp + 1 > buflen) { 14236375Ssklower return((caddr_t)0); 14336375Ssklower } 14436375Ssklower len = srcp->isoa_len = (u_char)* bufp++; 14536375Ssklower (void) bcopy(bufp, (caddr_t)srcp, len); 14636375Ssklower bufp += len; 14736375Ssklower 14836375Ssklower /* 14936375Ssklower * Insure that the addresses make sense 15036375Ssklower */ 15136375Ssklower if (iso_ck_addr(srcp) && iso_ck_addr(destp)) 15236375Ssklower return bufp; 15336375Ssklower else 15436375Ssklower return (caddr_t) 0; 15536375Ssklower } 15636375Ssklower #endif ndef 15736375Ssklower 15836375Ssklower /* 15936375Ssklower * FUNCTION: clnp_ours 16036375Ssklower * 16136375Ssklower * PURPOSE: Decide whether the supplied packet is destined for 16236375Ssklower * us, or that it should be forwarded on. 16336375Ssklower * 16436375Ssklower * RETURNS: packet is for us - 1 16536375Ssklower * packet is not for us - 0 16636375Ssklower * 16736375Ssklower * SIDE EFFECTS: 16836375Ssklower * 16936375Ssklower * NOTES: 17036375Ssklower */ 17136375Ssklower clnp_ours(dst) 17236375Ssklower register struct iso_addr *dst; /* ptr to destination address */ 17336375Ssklower { 17436375Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 17536375Ssklower 17636375Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 17736375Ssklower IFDEBUG(D_ROUTE) 17836375Ssklower printf("clnp_ours: ia_sis x%x, dst x%x\n", &IA_SIS(ia)->siso_addr, 17936375Ssklower dst); 18036375Ssklower ENDDEBUG 18136375Ssklower /* PHASE 2: uses iso_addrmatch & mask from iso_ifaddr */ 18236375Ssklower if (iso_addrmatch1(&IA_SIS(ia)->siso_addr, dst)) 18336375Ssklower return 1; 18436375Ssklower } 18536375Ssklower return 0; 18636375Ssklower } 18736375Ssklower 18836770Ssklower /* Dec bit set if ifp qlen is greater than congest_threshold */ 18936770Ssklower int congest_threshold = 0; 19036770Ssklower 19136375Ssklower /* 19236375Ssklower * FUNCTION: clnp_forward 19336375Ssklower * 19436375Ssklower * PURPOSE: Forward the datagram passed 19536375Ssklower * clnpintr guarantees that the header will be 19636375Ssklower * contigious (a cluster mbuf will be used if necessary). 19736375Ssklower * 19836375Ssklower * If oidx is NULL, no options are present. 19936375Ssklower * 20036375Ssklower * RETURNS: nothing 20136375Ssklower * 20236375Ssklower * SIDE EFFECTS: 20336375Ssklower * 20436375Ssklower * NOTES: 20536375Ssklower */ 20636375Ssklower clnp_forward(m, len, dst, oidx, seg_off, inbound_shp) 20736375Ssklower struct mbuf *m; /* pkt to forward */ 20836375Ssklower int len; /* length of pkt */ 20936375Ssklower struct iso_addr *dst; /* destination address */ 21036375Ssklower struct clnp_optidx *oidx; /* option index */ 21136375Ssklower int seg_off;/* offset of segmentation part */ 21236375Ssklower struct snpa_hdr *inbound_shp; /* subnetwork header of inbound packet */ 21336375Ssklower { 21436375Ssklower struct clnp_fixed *clnp; /* ptr to fixed part of header */ 21536375Ssklower int error; /* return value of route function */ 21636375Ssklower struct sockaddr *next_hop; /* next hop for dgram */ 21736375Ssklower struct ifnet *ifp; /* ptr to outgoing interface */ 21837469Ssklower struct iso_ifaddr *ia = 0;/* ptr to iso name for ifp */ 21936769Ssklower struct route_iso route; /* filled in by clnp_route */ 22036375Ssklower extern int iso_systype; 22136375Ssklower 22236375Ssklower clnp = mtod(m, struct clnp_fixed *); 22336375Ssklower bzero((caddr_t)&route, sizeof(route)); /* MUST be done before "bad:" */ 22436375Ssklower 22536375Ssklower /* 22636375Ssklower * Don't forward multicast or broadcast packets 22736375Ssklower */ 22836375Ssklower if ((inbound_shp) && (IS_MULTICAST(inbound_shp->snh_dhost))) { 22936375Ssklower IFDEBUG(D_FORWARD) 23036375Ssklower printf("clnp_forward: dropping multicast packet\n"); 23136375Ssklower ENDDEBUG 23237469Ssklower clnp->cnf_type &= ~CNF_ERR_OK; /* so we don't generate an ER */ 23336375Ssklower clnp_discard(m, 0); 23436375Ssklower goto done; 23536375Ssklower } 23636375Ssklower 23736375Ssklower IFDEBUG(D_FORWARD) 23836375Ssklower printf("clnp_forward: %d bytes, to %s, options x%x\n", len, 23936375Ssklower clnp_iso_addrp(dst), oidx); 24036375Ssklower ENDDEBUG 24136375Ssklower 24236375Ssklower /* 24336375Ssklower * Decrement ttl, and if zero drop datagram 24436375Ssklower * Can't compare ttl as less than zero 'cause its a unsigned 24536375Ssklower */ 24636375Ssklower if ((clnp->cnf_ttl == 0) || (--clnp->cnf_ttl == 0)) { 24736375Ssklower IFDEBUG(D_FORWARD) 24836375Ssklower printf("clnp_forward: discarding datagram because ttl is zero\n"); 24936375Ssklower ENDDEBUG 25036375Ssklower INCSTAT(cns_ttlexpired); 25136375Ssklower clnp_discard(m, TTL_EXPTRANSIT); 25236375Ssklower goto done; 25336375Ssklower } 25436375Ssklower /* 25536375Ssklower * Route packet; special case for source rt 25636375Ssklower */ 25736375Ssklower if CLNPSRCRT_VALID(oidx) { 25836375Ssklower /* 25936375Ssklower * Update src route first 26036375Ssklower */ 26136375Ssklower clnp_update_srcrt(m, oidx); 26237469Ssklower error = clnp_srcroute(m, oidx, &route, &next_hop, &ia, dst); 26336375Ssklower } else { 26437469Ssklower error = clnp_route(dst, &route, 0, &next_hop, &ia); 26536375Ssklower } 26637469Ssklower if (error || ia == 0) { 26736375Ssklower IFDEBUG(D_FORWARD) 26836375Ssklower printf("clnp_forward: can't route packet (errno %d)\n", error); 26936375Ssklower ENDDEBUG 27036375Ssklower clnp_discard(m, ADDR_DESTUNREACH); 27136375Ssklower goto done; 27236375Ssklower } 27337469Ssklower ifp = ia->ia_ifp; 27436375Ssklower 27536375Ssklower IFDEBUG(D_FORWARD) 27636375Ssklower printf("clnp_forward: packet routed to %s\n", 27736375Ssklower clnp_iso_addrp(&((struct sockaddr_iso *)next_hop)->siso_addr)); 27836375Ssklower ENDDEBUG 27936375Ssklower 28036375Ssklower INCSTAT(cns_forward); 28136375Ssklower 28236375Ssklower /* 28336375Ssklower * If we are an intermediate system and 28436375Ssklower * we are routing outbound on the same ifp that the packet 28536375Ssklower * arrived upon, and we know the next hop snpa, 28636375Ssklower * then generate a redirect request 28736375Ssklower */ 28836375Ssklower if ((iso_systype & SNPA_IS) && (inbound_shp) && 28936375Ssklower (ifp == inbound_shp->snh_ifp)) { 29036375Ssklower struct snpa_cache *sc; 29136375Ssklower 29236375Ssklower sc = snpac_look(&((struct sockaddr_iso *)next_hop)->siso_addr); 29336375Ssklower if (sc != NULL) { 29436375Ssklower esis_rdoutput(inbound_shp, m, oidx, dst, sc); 29536375Ssklower } 29636375Ssklower } 29736375Ssklower 29836375Ssklower /* 29936375Ssklower * If options are present, update them 30036375Ssklower */ 30136375Ssklower if (oidx) { 30237469Ssklower struct iso_addr *mysrc = &ia->ia_addr.siso_addr; 30336375Ssklower if (mysrc == NULL) { 30436375Ssklower clnp_discard(m, ADDR_DESTUNREACH); 30536375Ssklower goto done; 30636375Ssklower } else { 30736770Ssklower (void) clnp_dooptions(m, oidx, ifp, mysrc); 30836375Ssklower } 30936375Ssklower } 31036770Ssklower 31136770Ssklower #ifdef DECBIT 31236770Ssklower if (ifp->if_snd.ifq_len > congest_threshold) { 31336770Ssklower /* 31436770Ssklower * Congestion! Set the Dec Bit and thank Dave Oran 31536770Ssklower */ 31636770Ssklower IFDEBUG(D_FORWARD) 31736770Ssklower printf("clnp_forward: congestion experienced\n"); 31836770Ssklower ENDDEBUG 31936770Ssklower if ((oidx) && (oidx->cni_qos_formatp)) { 32036770Ssklower caddr_t qosp = CLNP_OFFTOOPT(m, oidx->cni_qos_formatp); 32136770Ssklower u_char qos = *qosp; 32236770Ssklower IFDEBUG(D_FORWARD) 32336770Ssklower printf("clnp_forward: setting congestion bit (qos x%x)\n", qos); 32436770Ssklower ENDDEBUG 32536770Ssklower if ((qos & CLNPOVAL_GLOBAL) == CLNPOVAL_GLOBAL) { 32636770Ssklower qos |= CLNPOVAL_CONGESTED; 32736770Ssklower INCSTAT(cns_congest_set); 32836770Ssklower *qosp = qos; 32936770Ssklower } 33036770Ssklower } 33136770Ssklower } 33236770Ssklower #endif DECBIT 33336375Ssklower 33436375Ssklower /* 33536375Ssklower * Dispatch the datagram if it is small enough, otherwise fragment 33636375Ssklower */ 33736375Ssklower if (len <= SN_MTU(ifp)) { 33836375Ssklower iso_gen_csum(m, CLNP_CKSUM_OFF, (int)clnp->cnf_hdr_len); 33936375Ssklower (void) (*ifp->if_output)(ifp, m, next_hop); 34036375Ssklower } else { 34136375Ssklower (void) clnp_fragment(ifp, m, next_hop, len, seg_off, /* flags */0); 34236375Ssklower } 34336375Ssklower 34436375Ssklower done: 34536375Ssklower /* 34636375Ssklower * Free route 34736375Ssklower */ 34836375Ssklower if (route.ro_rt != NULL) { 34936375Ssklower RTFREE(route.ro_rt); 35036375Ssklower } 35136375Ssklower } 35236375Ssklower 35336375Ssklower #ifdef ndef 35436375Ssklower /* 35536375Ssklower * FUNCTION: clnp_insert_addr 35636375Ssklower * 35736375Ssklower * PURPOSE: Insert the address part into a clnp datagram. 35836375Ssklower * 35936375Ssklower * RETURNS: Address of first byte after address part in datagram. 36036375Ssklower * 36136375Ssklower * SIDE EFFECTS: 36236375Ssklower * 36336375Ssklower * NOTES: Assume that there is enough space for the address part. 36436375Ssklower */ 36536375Ssklower caddr_t 36636375Ssklower clnp_insert_addr(bufp, srcp, dstp) 36736375Ssklower caddr_t bufp; /* address of where addr part goes */ 36836375Ssklower register struct iso_addr *srcp; /* ptr to src addr */ 36936375Ssklower register struct iso_addr *dstp; /* ptr to dst addr */ 37036375Ssklower { 37136375Ssklower *bufp++ = dstp->isoa_len; 37236375Ssklower (void) bcopy((caddr_t)dstp, bufp, dstp->isoa_len); 37336375Ssklower bufp += dstp->isoa_len; 37436375Ssklower 37536375Ssklower *bufp++ = srcp->isoa_len; 37636375Ssklower (void) bcopy((caddr_t)srcp, bufp, srcp->isoa_len); 37736375Ssklower bufp += srcp->isoa_len; 37836375Ssklower 37936375Ssklower return bufp; 38036375Ssklower } 38136375Ssklower 38236375Ssklower #endif ndef 38336375Ssklower 38436375Ssklower /* 38536375Ssklower * FUNCTION: clnp_route 38636375Ssklower * 38736375Ssklower * PURPOSE: Route a clnp datagram to the first hop toward its 38836375Ssklower * destination. In many cases, the first hop will be 38936375Ssklower * the destination. The address of a route 39036375Ssklower * is specified. If a routing entry is present in 39136375Ssklower * that route, and it is still up to the same destination, 39236375Ssklower * then no further action is necessary. Otherwise, a 39336375Ssklower * new routing entry will be allocated. 39436375Ssklower * 39536375Ssklower * RETURNS: route found - 0 39636375Ssklower * unix error code 39736375Ssklower * 39836375Ssklower * SIDE EFFECTS: 39936375Ssklower * 40036375Ssklower * NOTES: It is up to the caller to free the routing entry 40136375Ssklower * allocated in route. 40236375Ssklower */ 40337469Ssklower clnp_route(dst, ro, flags, first_hop, ifa) 40437469Ssklower struct iso_addr *dst; /* ptr to datagram destination */ 40537469Ssklower register struct route_iso *ro; /* existing route structure */ 40637469Ssklower int flags; /* flags for routing */ 40737469Ssklower struct sockaddr **first_hop; /* result: fill in with ptr to firsthop */ 40837469Ssklower struct iso_ifaddr **ifa; /* result: fill in with ptr to interface */ 40936375Ssklower { 41037469Ssklower if (flags & SO_DONTROUTE) { 41137469Ssklower struct iso_ifaddr *ia; 41236375Ssklower 413*38476Ssklower if (ro->ro_rt) { 414*38476Ssklower RTFREE(ro->ro_rt); 415*38476Ssklower ro->ro_rt = 0; 416*38476Ssklower } 417*38476Ssklower bzero((caddr_t)&ro->ro_dst, sizeof(ro->ro_dst)); 418*38476Ssklower bcopy((caddr_t)dst, (caddr_t)&ro->ro_dst.siso_addr, 41937469Ssklower 1 + (unsigned)dst->isoa_len); 420*38476Ssklower ro->ro_dst.siso_family = AF_ISO; 421*38476Ssklower ro->ro_dst.siso_len = sizeof(ro->ro_dst); 422*38476Ssklower ia = iso_localifa(&ro->ro_dst); 42337469Ssklower if (ia == 0) 42437469Ssklower return EADDRNOTAVAIL; 42537469Ssklower if (ifa) 426*38476Ssklower *ifa = ia; 427*38476Ssklower if (first_hop) 428*38476Ssklower *first_hop = (struct sockaddr *)&ro->ro_dst; 42937469Ssklower return 0; 43037469Ssklower } 43136375Ssklower /* 43236375Ssklower * If there is a cached route, check that it is still up and to 43336375Ssklower * the same destination. If not, free it and try again. 43436375Ssklower */ 43536375Ssklower if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || 43637469Ssklower (Bcmp(ro->ro_dst.siso_data, dst->isoa_genaddr, dst->isoa_len)))) { 43736375Ssklower IFDEBUG(D_ROUTE) 43836375Ssklower printf("clnp_route: freeing old route: ro->ro_rt 0x%x\n", 43936375Ssklower ro->ro_rt); 44036375Ssklower printf("clnp_route: old route refcnt: 0x%x\n", 44136375Ssklower ro->ro_rt->rt_refcnt); 44236375Ssklower ENDDEBUG 44336375Ssklower 44436375Ssklower /* free old route entry */ 44536375Ssklower RTFREE(ro->ro_rt); 44636375Ssklower ro->ro_rt = (struct rtentry *)0; 44736375Ssklower } else { 44836375Ssklower IFDEBUG(D_ROUTE) 44936375Ssklower printf("clnp_route: OK route exists\n"); 45036375Ssklower ENDDEBUG 45136375Ssklower } 45236375Ssklower 45336375Ssklower if (ro->ro_rt == 0) { 45436375Ssklower /* set up new route structure */ 45537469Ssklower bzero((caddr_t)&ro->ro_dst, sizeof(ro->ro_dst)); 45637469Ssklower ro->ro_dst.siso_len = sizeof(ro->ro_dst); 45737469Ssklower ro->ro_dst.siso_family = AF_ISO; 45837469Ssklower Bcopy(dst, &ro->ro_dst.siso_addr, 1 + dst->isoa_len); 45936375Ssklower /* allocate new route */ 46036375Ssklower IFDEBUG(D_ROUTE) 46136375Ssklower printf("clnp_route: allocating new route to %s\n", 46236375Ssklower clnp_iso_addrp(dst)); 46336375Ssklower ENDDEBUG 46437469Ssklower rtalloc((struct route *)ro); 46536375Ssklower } 46637469Ssklower if (ro->ro_rt == 0) 46736375Ssklower return(ENETUNREACH); /* rtalloc failed */ 46837469Ssklower ro->ro_rt->rt_use++; 46937469Ssklower if (ifa) 47037469Ssklower if ((*ifa = (struct iso_ifaddr *)ro->ro_rt->rt_ifa) == 0) 47137469Ssklower panic("clnp_route"); 47237469Ssklower if (first_hop) { 47337469Ssklower if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 47437469Ssklower *first_hop = ro->ro_rt->rt_gateway; 47537469Ssklower else 47637469Ssklower *first_hop = (struct sockaddr *)&ro->ro_dst; 47736375Ssklower } 47836375Ssklower return(0); 47936375Ssklower } 48036375Ssklower 48136375Ssklower /* 48236375Ssklower * FUNCTION: clnp_srcroute 48336375Ssklower * 48436375Ssklower * PURPOSE: Source route the datagram. If complete source 48536375Ssklower * routing is specified but not possible, then 48636375Ssklower * return an error. If src routing is terminated, then 48736375Ssklower * try routing on destination. 48836375Ssklower * Usage of first_hop, 48936375Ssklower * ifp, and error return is identical to clnp_route. 49036375Ssklower * 49136375Ssklower * RETURNS: 0 or unix error code 49236375Ssklower * 49336375Ssklower * SIDE EFFECTS: 49436375Ssklower * 49536375Ssklower * NOTES: Remember that option index pointers are really 49636375Ssklower * offsets from the beginning of the mbuf. 49736375Ssklower */ 49837469Ssklower clnp_srcroute(options, oidx, route, first_hop, ifa, final_dst) 49936375Ssklower struct mbuf *options; /* ptr to options */ 50036375Ssklower struct clnp_optidx *oidx; /* index to options */ 50137469Ssklower struct route_iso *route; /* route structure */ 50236375Ssklower struct sockaddr **first_hop; /* RETURN: fill in with ptr to firsthop */ 50337469Ssklower struct iso_ifaddr **ifa; /* RETURN: fill in with ptr to interface */ 50436375Ssklower struct iso_addr *final_dst; /* final destination */ 50536375Ssklower { 50636375Ssklower struct iso_addr dst; /* first hop specified by src rt */ 50736375Ssklower int error = 0; /* return code */ 50836375Ssklower 50936375Ssklower /* 51036375Ssklower * Check if we have run out of routes 51136375Ssklower * If so, then try to route on destination. 51236375Ssklower */ 51336375Ssklower if CLNPSRCRT_TERM(oidx, options) { 51436375Ssklower dst.isoa_len = final_dst->isoa_len; 51537469Ssklower bcopy(final_dst->isoa_genaddr, dst.isoa_genaddr, dst.isoa_len); 51636375Ssklower } else { 51736375Ssklower /* 51836375Ssklower * setup dst based on src rt specified 51936375Ssklower */ 52036375Ssklower dst.isoa_len = CLNPSRCRT_CLEN(oidx, options); 52137469Ssklower bcopy(CLNPSRCRT_CADDR(oidx, options), dst.isoa_genaddr, dst.isoa_len); 52236375Ssklower } 52336375Ssklower 52436375Ssklower /* 52536375Ssklower * try to route it 52636375Ssklower */ 52737469Ssklower error = clnp_route(&dst, route, 0, first_hop, ifa); 52836375Ssklower if (error != 0) 52936375Ssklower return error; 53036375Ssklower 53136375Ssklower /* 53236375Ssklower * If complete src rt, first hop must be equal to dst 53336375Ssklower */ 53436375Ssklower if ((CLNPSRCRT_TYPE(oidx, options) == CLNPOVAL_COMPRT) && 53536375Ssklower (!iso_addrmatch1(&(*(struct sockaddr_iso **)first_hop)->siso_addr,&dst))){ 53636375Ssklower IFDEBUG(D_OPTIONS) 53736375Ssklower printf("clnp_srcroute: complete src route failed\n"); 53836375Ssklower ENDDEBUG 53936375Ssklower return EHOSTUNREACH; /* RAH? would like ESRCRTFAILED */ 54036375Ssklower } 54136375Ssklower 54236375Ssklower return error; 54336375Ssklower } 54436375Ssklower 54536375Ssklower /* 54636375Ssklower * FUNCTION: clnp_ypocb - backwards bcopy 54736375Ssklower * 54836375Ssklower * PURPOSE: bcopy starting at end of src rather than beginning. 54936375Ssklower * 55036375Ssklower * RETURNS: none 55136375Ssklower * 55236375Ssklower * SIDE EFFECTS: 55336375Ssklower * 55436375Ssklower * NOTES: No attempt has been made to make this efficient 55536375Ssklower */ 55636375Ssklower clnp_ypocb(from, to, len) 55736375Ssklower caddr_t from; /* src buffer */ 55836375Ssklower caddr_t to; /* dst buffer */ 55936375Ssklower u_int len; /* number of bytes */ 56036375Ssklower { 56136375Ssklower while (len--) 56236375Ssklower *(to + len) = *(from + len); 56336375Ssklower } 56436375Ssklower 56536375Ssklower /* 56636375Ssklower * FUNCTION: clnp_hdrsize 56736375Ssklower * 56836375Ssklower * PURPOSE: Return the size of a typical clnp hdr. 56936375Ssklower * 57036375Ssklower * RETURNS: Size of hdr in bytes. 57136375Ssklower * 57236375Ssklower * SIDE EFFECTS: 57336375Ssklower * 57436375Ssklower * NOTES: Assumes segmenting subset. If addrlen is 57536375Ssklower * zero, default to largest nsap address size. 57636375Ssklower */ 57736375Ssklower clnp_hdrsize(addrlen) 57836375Ssklower u_char addrlen; /* length of nsap address */ 57936375Ssklower { 58036375Ssklower if (addrlen == 0) 58136375Ssklower addrlen = 20; 58236375Ssklower 58336375Ssklower addrlen++; /* length of address byte */ 58436375Ssklower addrlen *= 2; /* src and dst addresses */ 58536375Ssklower addrlen += sizeof(struct clnp_fixed) + sizeof(struct clnp_segment); 58636375Ssklower 58736375Ssklower return(addrlen); 58836375Ssklower } 58936375Ssklower #endif ISO 590