1*49267Sbostic /*- 2*49267Sbostic * Copyright (c) 1991 The Regents of the University of California. 3*49267Sbostic * All rights reserved. 4*49267Sbostic * 5*49267Sbostic * %sccs.include.redist.c% 6*49267Sbostic * 7*49267Sbostic * @(#)clnp_subr.c 7.13 (Berkeley) 05/06/91 8*49267Sbostic */ 9*49267Sbostic 1036375Ssklower /*********************************************************** 1136375Ssklower Copyright IBM Corporation 1987 1236375Ssklower 1336375Ssklower All Rights Reserved 1436375Ssklower 1536375Ssklower Permission to use, copy, modify, and distribute this software and its 1636375Ssklower documentation for any purpose and without fee is hereby granted, 1736375Ssklower provided that the above copyright notice appear in all copies and that 1836375Ssklower both that copyright notice and this permission notice appear in 1936375Ssklower supporting documentation, and that the name of IBM not be 2036375Ssklower used in advertising or publicity pertaining to distribution of the 2136375Ssklower software without specific, written prior permission. 2236375Ssklower 2336375Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436375Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536375Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636375Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736375Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836375Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936375Ssklower SOFTWARE. 3036375Ssklower 3136375Ssklower ******************************************************************/ 3236375Ssklower 3336375Ssklower /* 3436375Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536375Ssklower */ 3636770Ssklower /* $Header: /var/src/sys/netiso/RCS/clnp_subr.c,v 5.1 89/02/09 16:20:46 hagens Exp $ */ 3736770Ssklower /* $Source: /var/src/sys/netiso/RCS/clnp_subr.c,v $ */ 3836375Ssklower 3936375Ssklower #ifdef ISO 4036375Ssklower 4137469Ssklower #include "types.h" 4237469Ssklower #include "param.h" 4337469Ssklower #include "mbuf.h" 4437469Ssklower #include "domain.h" 4537469Ssklower #include "protosw.h" 4637469Ssklower #include "socket.h" 4737469Ssklower #include "socketvar.h" 4837469Ssklower #include "errno.h" 4937469Ssklower #include "time.h" 5036375Ssklower 5136375Ssklower #include "../net/if.h" 5236375Ssklower #include "../net/route.h" 5343071Ssklower #include "../net/if_dl.h" 5436375Ssklower 5537469Ssklower #include "iso.h" 5637469Ssklower #include "iso_var.h" 5737469Ssklower #include "iso_pcb.h" 5837469Ssklower #include "iso_snpac.h" 5937469Ssklower #include "clnp.h" 6037469Ssklower #include "clnp_stat.h" 6137469Ssklower #include "argo_debug.h" 6236375Ssklower 6336375Ssklower /* 6436375Ssklower * FUNCTION: clnp_data_ck 6536375Ssklower * 6636375Ssklower * PURPOSE: Check that the amount of data in the mbuf chain is 6736375Ssklower * at least as much as the clnp header would have us 6836375Ssklower * expect. Trim mbufs if longer than expected, drop 6936375Ssklower * packet if shorter than expected. 7036375Ssklower * 7136375Ssklower * RETURNS: success - ptr to mbuf chain 7236375Ssklower * failure - 0 7336375Ssklower * 7436375Ssklower * SIDE EFFECTS: 7536375Ssklower * 7636375Ssklower * NOTES: 7736375Ssklower */ 7836375Ssklower struct mbuf * 7936375Ssklower clnp_data_ck(m, length) 8036375Ssklower register struct mbuf *m; /* ptr to mbuf chain containing hdr & data */ 8136375Ssklower int length; /* length (in bytes) of packet */ 8236375Ssklower { 8336375Ssklower register int len; /* length of data */ 8436375Ssklower register struct mbuf *mhead; /* ptr to head of chain */ 8536375Ssklower 8636375Ssklower len = -length; 8736375Ssklower mhead = m; 8836375Ssklower for (;;) { 8936375Ssklower len += m->m_len; 9036375Ssklower if (m->m_next == 0) 9136375Ssklower break; 9236375Ssklower m = m->m_next; 9336375Ssklower } 9436375Ssklower if (len != 0) { 9536375Ssklower if (len < 0) { 9636375Ssklower INCSTAT(cns_toosmall); 9736375Ssklower clnp_discard(mhead, GEN_INCOMPLETE); 9836375Ssklower return 0; 9936375Ssklower } 10036375Ssklower if (len <= m->m_len) 10136375Ssklower m->m_len -= len; 10236375Ssklower else 10336375Ssklower m_adj(mhead, -len); 10436375Ssklower } 10536375Ssklower return mhead; 10636375Ssklower } 10736375Ssklower 10848740Ssklower #ifdef notdef 10936375Ssklower /* 11036375Ssklower * FUNCTION: clnp_extract_addr 11136375Ssklower * 11236375Ssklower * PURPOSE: Extract the source and destination address from the 11336375Ssklower * supplied buffer. Place them in the supplied address buffers. 11436375Ssklower * If insufficient data is supplied, then fail. 11536375Ssklower * 11636375Ssklower * RETURNS: success - Address of first byte in the packet past 11736375Ssklower * the address part. 11836375Ssklower * failure - 0 11936375Ssklower * 12036375Ssklower * SIDE EFFECTS: 12136375Ssklower * 12236375Ssklower * NOTES: 12336375Ssklower */ 12436375Ssklower caddr_t 12536375Ssklower clnp_extract_addr(bufp, buflen, srcp, destp) 12636375Ssklower caddr_t bufp; /* ptr to buffer containing addresses */ 12736375Ssklower int buflen; /* length of buffer */ 12836375Ssklower register struct iso_addr *srcp; /* ptr to source address buffer */ 12936375Ssklower register struct iso_addr *destp; /* ptr to destination address buffer */ 13036375Ssklower { 13136375Ssklower int len; /* argument to bcopy */ 13236375Ssklower 13336375Ssklower /* 13436375Ssklower * check that we have enough data. Plus1 is for length octet 13536375Ssklower */ 13636375Ssklower if ((u_char)*bufp + 1 > buflen) { 13736375Ssklower return((caddr_t)0); 13836375Ssklower } 13936375Ssklower len = destp->isoa_len = (u_char)*bufp++; 14036375Ssklower (void) bcopy(bufp, (caddr_t)destp, len); 14136375Ssklower buflen -= len; 14236375Ssklower bufp += len; 14336375Ssklower 14436375Ssklower /* 14536375Ssklower * check that we have enough data. Plus1 is for length octet 14636375Ssklower */ 14736375Ssklower if ((u_char)*bufp + 1 > buflen) { 14836375Ssklower return((caddr_t)0); 14936375Ssklower } 15036375Ssklower len = srcp->isoa_len = (u_char)* bufp++; 15136375Ssklower (void) bcopy(bufp, (caddr_t)srcp, len); 15236375Ssklower bufp += len; 15336375Ssklower 15436375Ssklower /* 15536375Ssklower * Insure that the addresses make sense 15636375Ssklower */ 15736375Ssklower if (iso_ck_addr(srcp) && iso_ck_addr(destp)) 15836375Ssklower return bufp; 15936375Ssklower else 16036375Ssklower return (caddr_t) 0; 16136375Ssklower } 16248740Ssklower #endif notdef 16336375Ssklower 16436375Ssklower /* 16536375Ssklower * FUNCTION: clnp_ours 16636375Ssklower * 16736375Ssklower * PURPOSE: Decide whether the supplied packet is destined for 16836375Ssklower * us, or that it should be forwarded on. 16936375Ssklower * 17036375Ssklower * RETURNS: packet is for us - 1 17136375Ssklower * packet is not for us - 0 17236375Ssklower * 17336375Ssklower * SIDE EFFECTS: 17436375Ssklower * 17536375Ssklower * NOTES: 17636375Ssklower */ 17736375Ssklower clnp_ours(dst) 17836375Ssklower register struct iso_addr *dst; /* ptr to destination address */ 17936375Ssklower { 18036375Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 18136375Ssklower 18236375Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 18336375Ssklower IFDEBUG(D_ROUTE) 18442949Ssklower printf("clnp_ours: ia_sis x%x, dst x%x\n", &ia->ia_addr, 18536375Ssklower dst); 18636375Ssklower ENDDEBUG 18742949Ssklower /* 18842949Ssklower * XXX Warning: 18942949Ssklower * We are overloading siso_tlen in the if's address, as an nsel length. 19042949Ssklower */ 19143332Ssklower if (dst->isoa_len == ia->ia_addr.siso_nlen && 19242949Ssklower bcmp((caddr_t)ia->ia_addr.siso_addr.isoa_genaddr, 19343332Ssklower (caddr_t)dst->isoa_genaddr, 19443332Ssklower ia->ia_addr.siso_nlen - ia->ia_addr.siso_tlen) == 0) 19542949Ssklower return 1; 19636375Ssklower } 19736375Ssklower return 0; 19836375Ssklower } 19936375Ssklower 20036770Ssklower /* Dec bit set if ifp qlen is greater than congest_threshold */ 20136770Ssklower int congest_threshold = 0; 20236770Ssklower 20336375Ssklower /* 20436375Ssklower * FUNCTION: clnp_forward 20536375Ssklower * 20636375Ssklower * PURPOSE: Forward the datagram passed 20736375Ssklower * clnpintr guarantees that the header will be 20836375Ssklower * contigious (a cluster mbuf will be used if necessary). 20936375Ssklower * 21036375Ssklower * If oidx is NULL, no options are present. 21136375Ssklower * 21236375Ssklower * RETURNS: nothing 21336375Ssklower * 21436375Ssklower * SIDE EFFECTS: 21536375Ssklower * 21636375Ssklower * NOTES: 21736375Ssklower */ 21836375Ssklower clnp_forward(m, len, dst, oidx, seg_off, inbound_shp) 21936375Ssklower struct mbuf *m; /* pkt to forward */ 22036375Ssklower int len; /* length of pkt */ 22136375Ssklower struct iso_addr *dst; /* destination address */ 22236375Ssklower struct clnp_optidx *oidx; /* option index */ 22336375Ssklower int seg_off;/* offset of segmentation part */ 22436375Ssklower struct snpa_hdr *inbound_shp; /* subnetwork header of inbound packet */ 22536375Ssklower { 22636375Ssklower struct clnp_fixed *clnp; /* ptr to fixed part of header */ 22736375Ssklower int error; /* return value of route function */ 22836375Ssklower struct sockaddr *next_hop; /* next hop for dgram */ 22936375Ssklower struct ifnet *ifp; /* ptr to outgoing interface */ 23037469Ssklower struct iso_ifaddr *ia = 0;/* ptr to iso name for ifp */ 23136769Ssklower struct route_iso route; /* filled in by clnp_route */ 23236375Ssklower extern int iso_systype; 23336375Ssklower 23436375Ssklower clnp = mtod(m, struct clnp_fixed *); 23536375Ssklower bzero((caddr_t)&route, sizeof(route)); /* MUST be done before "bad:" */ 23636375Ssklower 23736375Ssklower /* 23836375Ssklower * Don't forward multicast or broadcast packets 23936375Ssklower */ 24036375Ssklower if ((inbound_shp) && (IS_MULTICAST(inbound_shp->snh_dhost))) { 24136375Ssklower IFDEBUG(D_FORWARD) 24236375Ssklower printf("clnp_forward: dropping multicast packet\n"); 24336375Ssklower ENDDEBUG 24437469Ssklower clnp->cnf_type &= ~CNF_ERR_OK; /* so we don't generate an ER */ 24536375Ssklower clnp_discard(m, 0); 24639198Ssklower INCSTAT(cns_cantforward); 24736375Ssklower goto done; 24836375Ssklower } 24936375Ssklower 25036375Ssklower IFDEBUG(D_FORWARD) 25136375Ssklower printf("clnp_forward: %d bytes, to %s, options x%x\n", len, 25236375Ssklower clnp_iso_addrp(dst), oidx); 25336375Ssklower ENDDEBUG 25436375Ssklower 25536375Ssklower /* 25636375Ssklower * Decrement ttl, and if zero drop datagram 25736375Ssklower * Can't compare ttl as less than zero 'cause its a unsigned 25836375Ssklower */ 25936375Ssklower if ((clnp->cnf_ttl == 0) || (--clnp->cnf_ttl == 0)) { 26036375Ssklower IFDEBUG(D_FORWARD) 26136375Ssklower printf("clnp_forward: discarding datagram because ttl is zero\n"); 26236375Ssklower ENDDEBUG 26336375Ssklower INCSTAT(cns_ttlexpired); 26436375Ssklower clnp_discard(m, TTL_EXPTRANSIT); 26536375Ssklower goto done; 26636375Ssklower } 26736375Ssklower /* 26836375Ssklower * Route packet; special case for source rt 26936375Ssklower */ 27036375Ssklower if CLNPSRCRT_VALID(oidx) { 27136375Ssklower /* 27236375Ssklower * Update src route first 27336375Ssklower */ 27436375Ssklower clnp_update_srcrt(m, oidx); 27537469Ssklower error = clnp_srcroute(m, oidx, &route, &next_hop, &ia, dst); 27636375Ssklower } else { 27737469Ssklower error = clnp_route(dst, &route, 0, &next_hop, &ia); 27836375Ssklower } 27937469Ssklower if (error || ia == 0) { 28036375Ssklower IFDEBUG(D_FORWARD) 28136375Ssklower printf("clnp_forward: can't route packet (errno %d)\n", error); 28236375Ssklower ENDDEBUG 28336375Ssklower clnp_discard(m, ADDR_DESTUNREACH); 28439198Ssklower INCSTAT(cns_cantforward); 28536375Ssklower goto done; 28636375Ssklower } 28737469Ssklower ifp = ia->ia_ifp; 28836375Ssklower 28936375Ssklower IFDEBUG(D_FORWARD) 29036375Ssklower printf("clnp_forward: packet routed to %s\n", 29136375Ssklower clnp_iso_addrp(&((struct sockaddr_iso *)next_hop)->siso_addr)); 29236375Ssklower ENDDEBUG 29336375Ssklower 29436375Ssklower INCSTAT(cns_forward); 29536375Ssklower 29636375Ssklower /* 29736375Ssklower * If we are an intermediate system and 29836375Ssklower * we are routing outbound on the same ifp that the packet 29936375Ssklower * arrived upon, and we know the next hop snpa, 30036375Ssklower * then generate a redirect request 30136375Ssklower */ 30236375Ssklower if ((iso_systype & SNPA_IS) && (inbound_shp) && 30343332Ssklower (ifp == inbound_shp->snh_ifp)) 30443332Ssklower esis_rdoutput(inbound_shp, m, oidx, dst, route.ro_rt); 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 */ 34648740Ssklower if (len <= SN_MTU(ifp, route.ro_rt)) { 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 36248740Ssklower #ifdef notdef 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 39148740Ssklower #endif notdef 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 */ 50743332Ssklower clnp_srcroute(options, oidx, ro, first_hop, ifa, final_dst) 50836375Ssklower struct mbuf *options; /* ptr to options */ 50936375Ssklower struct clnp_optidx *oidx; /* index to options */ 51043332Ssklower struct route_iso *ro; /* 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 */ 53643332Ssklower error = clnp_route(&dst, ro, 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 /* 55548740Ssklower * FUNCTION: clnp_badmtu 55648740Ssklower * 55748740Ssklower * PURPOSE: print notice of route with mtu not initialized. 55848740Ssklower * 55948740Ssklower * RETURNS: mtu of ifp. 56048740Ssklower * 56148740Ssklower * SIDE EFFECTS: prints notice, slows down system. 56248740Ssklower */ 56348740Ssklower clnp_badmtu(ifp, rt, line, file) 56448740Ssklower struct ifnet *ifp; /* outgoing interface */ 56548740Ssklower struct rtentry *rt; /* dst route */ 56648740Ssklower int line; /* where the dirty deed occured */ 56748740Ssklower char *file; /* where the dirty deed occured */ 56848740Ssklower { 56948740Ssklower printf("sending on route %x with no mtu, line %s of file %s\n", 57048740Ssklower rt, line, file); 57148740Ssklower #ifdef ARGO_DEBUG 57248740Ssklower printf("route dst is"); 57348740Ssklower dump_isoaddr(rt_key(rt)); 57448740Ssklower #endif 57548740Ssklower return ifp->if_mtu; 57648740Ssklower } 57748740Ssklower 57848740Ssklower /* 57936375Ssklower * FUNCTION: clnp_ypocb - backwards bcopy 58036375Ssklower * 58136375Ssklower * PURPOSE: bcopy starting at end of src rather than beginning. 58236375Ssklower * 58336375Ssklower * RETURNS: none 58436375Ssklower * 58536375Ssklower * SIDE EFFECTS: 58636375Ssklower * 58736375Ssklower * NOTES: No attempt has been made to make this efficient 58836375Ssklower */ 58936375Ssklower clnp_ypocb(from, to, len) 59036375Ssklower caddr_t from; /* src buffer */ 59136375Ssklower caddr_t to; /* dst buffer */ 59236375Ssklower u_int len; /* number of bytes */ 59336375Ssklower { 59436375Ssklower while (len--) 59536375Ssklower *(to + len) = *(from + len); 59636375Ssklower } 59736375Ssklower #endif ISO 598