149267Sbostic /*- 249267Sbostic * Copyright (c) 1991 The Regents of the University of California. 349267Sbostic * All rights reserved. 449267Sbostic * 549267Sbostic * %sccs.include.redist.c% 649267Sbostic * 7*61290Ssklower * @(#)clnp_subr.c 7.17 (Berkeley) 06/04/93 849267Sbostic */ 949267Sbostic 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 4156533Sbostic #include <sys/param.h> 4256533Sbostic #include <sys/mbuf.h> 4356533Sbostic #include <sys/domain.h> 4456533Sbostic #include <sys/protosw.h> 4556533Sbostic #include <sys/socket.h> 4656533Sbostic #include <sys/socketvar.h> 4756533Sbostic #include <sys/errno.h> 4856533Sbostic #include <sys/time.h> 4936375Ssklower 5056533Sbostic #include <net/if.h> 5156533Sbostic #include <net/route.h> 5256533Sbostic #include <net/if_dl.h> 5336375Ssklower 5456533Sbostic #include <netiso/iso.h> 5556533Sbostic #include <netiso/iso_var.h> 5656533Sbostic #include <netiso/iso_pcb.h> 5756533Sbostic #include <netiso/iso_snpac.h> 5856533Sbostic #include <netiso/clnp.h> 5956533Sbostic #include <netiso/clnp_stat.h> 6056533Sbostic #include <netiso/argo_debug.h> 6136375Ssklower 6236375Ssklower /* 6336375Ssklower * FUNCTION: clnp_data_ck 6436375Ssklower * 6536375Ssklower * PURPOSE: Check that the amount of data in the mbuf chain is 6636375Ssklower * at least as much as the clnp header would have us 6736375Ssklower * expect. Trim mbufs if longer than expected, drop 6836375Ssklower * packet if shorter than expected. 6936375Ssklower * 7036375Ssklower * RETURNS: success - ptr to mbuf chain 7136375Ssklower * failure - 0 7236375Ssklower * 7336375Ssklower * SIDE EFFECTS: 7436375Ssklower * 7536375Ssklower * NOTES: 7636375Ssklower */ 7736375Ssklower struct mbuf * 7836375Ssklower clnp_data_ck(m, length) 7936375Ssklower register struct mbuf *m; /* ptr to mbuf chain containing hdr & data */ 8036375Ssklower int length; /* length (in bytes) of packet */ 8136375Ssklower { 8236375Ssklower register int len; /* length of data */ 8336375Ssklower register struct mbuf *mhead; /* ptr to head of chain */ 8436375Ssklower 8536375Ssklower len = -length; 8636375Ssklower mhead = m; 8736375Ssklower for (;;) { 8836375Ssklower len += m->m_len; 8936375Ssklower if (m->m_next == 0) 9036375Ssklower break; 9136375Ssklower m = m->m_next; 9236375Ssklower } 9336375Ssklower if (len != 0) { 9436375Ssklower if (len < 0) { 9536375Ssklower INCSTAT(cns_toosmall); 9636375Ssklower clnp_discard(mhead, GEN_INCOMPLETE); 9736375Ssklower return 0; 9836375Ssklower } 9936375Ssklower if (len <= m->m_len) 10036375Ssklower m->m_len -= len; 10136375Ssklower else 10236375Ssklower m_adj(mhead, -len); 10336375Ssklower } 10436375Ssklower return mhead; 10536375Ssklower } 10636375Ssklower 10748740Ssklower #ifdef notdef 10836375Ssklower /* 10936375Ssklower * FUNCTION: clnp_extract_addr 11036375Ssklower * 11136375Ssklower * PURPOSE: Extract the source and destination address from the 11236375Ssklower * supplied buffer. Place them in the supplied address buffers. 11336375Ssklower * If insufficient data is supplied, then fail. 11436375Ssklower * 11536375Ssklower * RETURNS: success - Address of first byte in the packet past 11636375Ssklower * the address part. 11736375Ssklower * failure - 0 11836375Ssklower * 11936375Ssklower * SIDE EFFECTS: 12036375Ssklower * 12136375Ssklower * NOTES: 12236375Ssklower */ 12336375Ssklower caddr_t 12436375Ssklower clnp_extract_addr(bufp, buflen, srcp, destp) 12536375Ssklower caddr_t bufp; /* ptr to buffer containing addresses */ 12636375Ssklower int buflen; /* length of buffer */ 12736375Ssklower register struct iso_addr *srcp; /* ptr to source address buffer */ 12836375Ssklower register struct iso_addr *destp; /* ptr to destination address buffer */ 12936375Ssklower { 13036375Ssklower int len; /* argument to bcopy */ 13136375Ssklower 13236375Ssklower /* 13336375Ssklower * check that we have enough data. Plus1 is for length octet 13436375Ssklower */ 13536375Ssklower if ((u_char)*bufp + 1 > buflen) { 13636375Ssklower return((caddr_t)0); 13736375Ssklower } 13836375Ssklower len = destp->isoa_len = (u_char)*bufp++; 13936375Ssklower (void) bcopy(bufp, (caddr_t)destp, len); 14036375Ssklower buflen -= len; 14136375Ssklower bufp += len; 14236375Ssklower 14336375Ssklower /* 14436375Ssklower * check that we have enough data. Plus1 is for length octet 14536375Ssklower */ 14636375Ssklower if ((u_char)*bufp + 1 > buflen) { 14736375Ssklower return((caddr_t)0); 14836375Ssklower } 14936375Ssklower len = srcp->isoa_len = (u_char)* bufp++; 15036375Ssklower (void) bcopy(bufp, (caddr_t)srcp, len); 15136375Ssklower bufp += len; 15236375Ssklower 15336375Ssklower /* 15436375Ssklower * Insure that the addresses make sense 15536375Ssklower */ 15636375Ssklower if (iso_ck_addr(srcp) && iso_ck_addr(destp)) 15736375Ssklower return bufp; 15836375Ssklower else 15936375Ssklower return (caddr_t) 0; 16036375Ssklower } 161*61290Ssklower #endif /* notdef */ 16236375Ssklower 16336375Ssklower /* 16436375Ssklower * FUNCTION: clnp_ours 16536375Ssklower * 16636375Ssklower * PURPOSE: Decide whether the supplied packet is destined for 16736375Ssklower * us, or that it should be forwarded on. 16836375Ssklower * 16936375Ssklower * RETURNS: packet is for us - 1 17036375Ssklower * packet is not for us - 0 17136375Ssklower * 17236375Ssklower * SIDE EFFECTS: 17336375Ssklower * 17436375Ssklower * NOTES: 17536375Ssklower */ 17636375Ssklower clnp_ours(dst) 17736375Ssklower register struct iso_addr *dst; /* ptr to destination address */ 17836375Ssklower { 17936375Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 18036375Ssklower 18136375Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 18236375Ssklower IFDEBUG(D_ROUTE) 18342949Ssklower printf("clnp_ours: ia_sis x%x, dst x%x\n", &ia->ia_addr, 18436375Ssklower dst); 18536375Ssklower ENDDEBUG 18642949Ssklower /* 18742949Ssklower * XXX Warning: 18842949Ssklower * We are overloading siso_tlen in the if's address, as an nsel length. 18942949Ssklower */ 19043332Ssklower if (dst->isoa_len == ia->ia_addr.siso_nlen && 19142949Ssklower bcmp((caddr_t)ia->ia_addr.siso_addr.isoa_genaddr, 19243332Ssklower (caddr_t)dst->isoa_genaddr, 19343332Ssklower ia->ia_addr.siso_nlen - ia->ia_addr.siso_tlen) == 0) 19442949Ssklower return 1; 19536375Ssklower } 19636375Ssklower return 0; 19736375Ssklower } 19836375Ssklower 19936770Ssklower /* Dec bit set if ifp qlen is greater than congest_threshold */ 20036770Ssklower int congest_threshold = 0; 20136770Ssklower 20236375Ssklower /* 20336375Ssklower * FUNCTION: clnp_forward 20436375Ssklower * 20536375Ssklower * PURPOSE: Forward the datagram passed 20636375Ssklower * clnpintr guarantees that the header will be 20736375Ssklower * contigious (a cluster mbuf will be used if necessary). 20836375Ssklower * 20936375Ssklower * If oidx is NULL, no options are present. 21036375Ssklower * 21136375Ssklower * RETURNS: nothing 21236375Ssklower * 21336375Ssklower * SIDE EFFECTS: 21436375Ssklower * 21536375Ssklower * NOTES: 21636375Ssklower */ 21736375Ssklower clnp_forward(m, len, dst, oidx, seg_off, inbound_shp) 21836375Ssklower struct mbuf *m; /* pkt to forward */ 21936375Ssklower int len; /* length of pkt */ 22036375Ssklower struct iso_addr *dst; /* destination address */ 22136375Ssklower struct clnp_optidx *oidx; /* option index */ 22236375Ssklower int seg_off;/* offset of segmentation part */ 22336375Ssklower struct snpa_hdr *inbound_shp; /* subnetwork header of inbound packet */ 22436375Ssklower { 22536375Ssklower struct clnp_fixed *clnp; /* ptr to fixed part of header */ 22636375Ssklower int error; /* return value of route function */ 22736375Ssklower struct sockaddr *next_hop; /* next hop for dgram */ 22836375Ssklower struct ifnet *ifp; /* ptr to outgoing interface */ 22937469Ssklower struct iso_ifaddr *ia = 0;/* ptr to iso name for ifp */ 23036769Ssklower struct route_iso route; /* filled in by clnp_route */ 23136375Ssklower extern int iso_systype; 23236375Ssklower 23336375Ssklower clnp = mtod(m, struct clnp_fixed *); 23436375Ssklower bzero((caddr_t)&route, sizeof(route)); /* MUST be done before "bad:" */ 23536375Ssklower 23636375Ssklower /* 23736375Ssklower * Don't forward multicast or broadcast packets 23836375Ssklower */ 23936375Ssklower if ((inbound_shp) && (IS_MULTICAST(inbound_shp->snh_dhost))) { 24036375Ssklower IFDEBUG(D_FORWARD) 24136375Ssklower printf("clnp_forward: dropping multicast packet\n"); 24236375Ssklower ENDDEBUG 24337469Ssklower clnp->cnf_type &= ~CNF_ERR_OK; /* so we don't generate an ER */ 24436375Ssklower clnp_discard(m, 0); 24539198Ssklower INCSTAT(cns_cantforward); 24636375Ssklower goto done; 24736375Ssklower } 24836375Ssklower 24936375Ssklower IFDEBUG(D_FORWARD) 25036375Ssklower printf("clnp_forward: %d bytes, to %s, options x%x\n", len, 25136375Ssklower clnp_iso_addrp(dst), oidx); 25236375Ssklower ENDDEBUG 25336375Ssklower 25436375Ssklower /* 25536375Ssklower * Decrement ttl, and if zero drop datagram 25636375Ssklower * Can't compare ttl as less than zero 'cause its a unsigned 25736375Ssklower */ 25836375Ssklower if ((clnp->cnf_ttl == 0) || (--clnp->cnf_ttl == 0)) { 25936375Ssklower IFDEBUG(D_FORWARD) 26036375Ssklower printf("clnp_forward: discarding datagram because ttl is zero\n"); 26136375Ssklower ENDDEBUG 26236375Ssklower INCSTAT(cns_ttlexpired); 26336375Ssklower clnp_discard(m, TTL_EXPTRANSIT); 26436375Ssklower goto done; 26536375Ssklower } 26636375Ssklower /* 26736375Ssklower * Route packet; special case for source rt 26836375Ssklower */ 26936375Ssklower if CLNPSRCRT_VALID(oidx) { 27036375Ssklower /* 27136375Ssklower * Update src route first 27236375Ssklower */ 27336375Ssklower clnp_update_srcrt(m, oidx); 27437469Ssklower error = clnp_srcroute(m, oidx, &route, &next_hop, &ia, dst); 27536375Ssklower } else { 27637469Ssklower error = clnp_route(dst, &route, 0, &next_hop, &ia); 27736375Ssklower } 27837469Ssklower if (error || ia == 0) { 27936375Ssklower IFDEBUG(D_FORWARD) 28036375Ssklower printf("clnp_forward: can't route packet (errno %d)\n", error); 28136375Ssklower ENDDEBUG 28236375Ssklower clnp_discard(m, ADDR_DESTUNREACH); 28339198Ssklower INCSTAT(cns_cantforward); 28436375Ssklower goto done; 28536375Ssklower } 28637469Ssklower ifp = ia->ia_ifp; 28736375Ssklower 28836375Ssklower IFDEBUG(D_FORWARD) 28936375Ssklower printf("clnp_forward: packet routed to %s\n", 29036375Ssklower clnp_iso_addrp(&((struct sockaddr_iso *)next_hop)->siso_addr)); 29136375Ssklower ENDDEBUG 29236375Ssklower 29336375Ssklower INCSTAT(cns_forward); 29436375Ssklower 29536375Ssklower /* 29636375Ssklower * If we are an intermediate system and 29736375Ssklower * we are routing outbound on the same ifp that the packet 29836375Ssklower * arrived upon, and we know the next hop snpa, 29936375Ssklower * then generate a redirect request 30036375Ssklower */ 30136375Ssklower if ((iso_systype & SNPA_IS) && (inbound_shp) && 30243332Ssklower (ifp == inbound_shp->snh_ifp)) 30343332Ssklower esis_rdoutput(inbound_shp, m, oidx, dst, route.ro_rt); 30436375Ssklower /* 30536375Ssklower * If options are present, update them 30636375Ssklower */ 30736375Ssklower if (oidx) { 30837469Ssklower struct iso_addr *mysrc = &ia->ia_addr.siso_addr; 30936375Ssklower if (mysrc == NULL) { 31036375Ssklower clnp_discard(m, ADDR_DESTUNREACH); 31139198Ssklower INCSTAT(cns_cantforward); 31239198Ssklower clnp_stat.cns_forward--; 31336375Ssklower goto done; 31436375Ssklower } else { 31536770Ssklower (void) clnp_dooptions(m, oidx, ifp, mysrc); 31636375Ssklower } 31736375Ssklower } 31836770Ssklower 31936770Ssklower #ifdef DECBIT 32036770Ssklower if (ifp->if_snd.ifq_len > congest_threshold) { 32136770Ssklower /* 32236770Ssklower * Congestion! Set the Dec Bit and thank Dave Oran 32336770Ssklower */ 32436770Ssklower IFDEBUG(D_FORWARD) 32536770Ssklower printf("clnp_forward: congestion experienced\n"); 32636770Ssklower ENDDEBUG 32736770Ssklower if ((oidx) && (oidx->cni_qos_formatp)) { 32836770Ssklower caddr_t qosp = CLNP_OFFTOOPT(m, oidx->cni_qos_formatp); 32936770Ssklower u_char qos = *qosp; 33036770Ssklower IFDEBUG(D_FORWARD) 33136770Ssklower printf("clnp_forward: setting congestion bit (qos x%x)\n", qos); 33236770Ssklower ENDDEBUG 33336770Ssklower if ((qos & CLNPOVAL_GLOBAL) == CLNPOVAL_GLOBAL) { 33436770Ssklower qos |= CLNPOVAL_CONGESTED; 33536770Ssklower INCSTAT(cns_congest_set); 33636770Ssklower *qosp = qos; 33736770Ssklower } 33836770Ssklower } 33936770Ssklower } 340*61290Ssklower #endif /* DECBIT */ 34136375Ssklower 34236375Ssklower /* 34336375Ssklower * Dispatch the datagram if it is small enough, otherwise fragment 34436375Ssklower */ 34548740Ssklower if (len <= SN_MTU(ifp, route.ro_rt)) { 34636375Ssklower iso_gen_csum(m, CLNP_CKSUM_OFF, (int)clnp->cnf_hdr_len); 34740776Ssklower (void) (*ifp->if_output)(ifp, m, next_hop, route.ro_rt); 34836375Ssklower } else { 34940776Ssklower (void) clnp_fragment(ifp, m, next_hop, len, seg_off, /* flags */0, route.ro_rt); 35036375Ssklower } 35136375Ssklower 35236375Ssklower done: 35336375Ssklower /* 35436375Ssklower * Free route 35536375Ssklower */ 35636375Ssklower if (route.ro_rt != NULL) { 35736375Ssklower RTFREE(route.ro_rt); 35836375Ssklower } 35936375Ssklower } 36036375Ssklower 36148740Ssklower #ifdef notdef 36236375Ssklower /* 36336375Ssklower * FUNCTION: clnp_insert_addr 36436375Ssklower * 36536375Ssklower * PURPOSE: Insert the address part into a clnp datagram. 36636375Ssklower * 36736375Ssklower * RETURNS: Address of first byte after address part in datagram. 36836375Ssklower * 36936375Ssklower * SIDE EFFECTS: 37036375Ssklower * 37136375Ssklower * NOTES: Assume that there is enough space for the address part. 37236375Ssklower */ 37336375Ssklower caddr_t 37436375Ssklower clnp_insert_addr(bufp, srcp, dstp) 37536375Ssklower caddr_t bufp; /* address of where addr part goes */ 37636375Ssklower register struct iso_addr *srcp; /* ptr to src addr */ 37736375Ssklower register struct iso_addr *dstp; /* ptr to dst addr */ 37836375Ssklower { 37936375Ssklower *bufp++ = dstp->isoa_len; 38036375Ssklower (void) bcopy((caddr_t)dstp, bufp, dstp->isoa_len); 38136375Ssklower bufp += dstp->isoa_len; 38236375Ssklower 38336375Ssklower *bufp++ = srcp->isoa_len; 38436375Ssklower (void) bcopy((caddr_t)srcp, bufp, srcp->isoa_len); 38536375Ssklower bufp += srcp->isoa_len; 38636375Ssklower 38736375Ssklower return bufp; 38836375Ssklower } 38936375Ssklower 390*61290Ssklower #endif /* notdef */ 39136375Ssklower 39236375Ssklower /* 39336375Ssklower * FUNCTION: clnp_route 39436375Ssklower * 39536375Ssklower * PURPOSE: Route a clnp datagram to the first hop toward its 39636375Ssklower * destination. In many cases, the first hop will be 39736375Ssklower * the destination. The address of a route 39836375Ssklower * is specified. If a routing entry is present in 39936375Ssklower * that route, and it is still up to the same destination, 40036375Ssklower * then no further action is necessary. Otherwise, a 40136375Ssklower * new routing entry will be allocated. 40236375Ssklower * 40336375Ssklower * RETURNS: route found - 0 40436375Ssklower * unix error code 40536375Ssklower * 40636375Ssklower * SIDE EFFECTS: 40736375Ssklower * 40836375Ssklower * NOTES: It is up to the caller to free the routing entry 40936375Ssklower * allocated in route. 41036375Ssklower */ 41137469Ssklower clnp_route(dst, ro, flags, first_hop, ifa) 41237469Ssklower struct iso_addr *dst; /* ptr to datagram destination */ 41337469Ssklower register struct route_iso *ro; /* existing route structure */ 41437469Ssklower int flags; /* flags for routing */ 41537469Ssklower struct sockaddr **first_hop; /* result: fill in with ptr to firsthop */ 41637469Ssklower struct iso_ifaddr **ifa; /* result: fill in with ptr to interface */ 41736375Ssklower { 41837469Ssklower if (flags & SO_DONTROUTE) { 41937469Ssklower struct iso_ifaddr *ia; 42036375Ssklower 42138476Ssklower if (ro->ro_rt) { 42238476Ssklower RTFREE(ro->ro_rt); 42338476Ssklower ro->ro_rt = 0; 42438476Ssklower } 42538476Ssklower bzero((caddr_t)&ro->ro_dst, sizeof(ro->ro_dst)); 42638476Ssklower bcopy((caddr_t)dst, (caddr_t)&ro->ro_dst.siso_addr, 42737469Ssklower 1 + (unsigned)dst->isoa_len); 42838476Ssklower ro->ro_dst.siso_family = AF_ISO; 42938476Ssklower ro->ro_dst.siso_len = sizeof(ro->ro_dst); 43038476Ssklower ia = iso_localifa(&ro->ro_dst); 43137469Ssklower if (ia == 0) 43237469Ssklower return EADDRNOTAVAIL; 43337469Ssklower if (ifa) 43438476Ssklower *ifa = ia; 43538476Ssklower if (first_hop) 43638476Ssklower *first_hop = (struct sockaddr *)&ro->ro_dst; 43737469Ssklower return 0; 43837469Ssklower } 43936375Ssklower /* 44036375Ssklower * If there is a cached route, check that it is still up and to 44136375Ssklower * the same destination. If not, free it and try again. 44236375Ssklower */ 44336375Ssklower if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || 44437469Ssklower (Bcmp(ro->ro_dst.siso_data, dst->isoa_genaddr, dst->isoa_len)))) { 44536375Ssklower IFDEBUG(D_ROUTE) 44636375Ssklower printf("clnp_route: freeing old route: ro->ro_rt 0x%x\n", 44736375Ssklower ro->ro_rt); 44836375Ssklower printf("clnp_route: old route refcnt: 0x%x\n", 44936375Ssklower ro->ro_rt->rt_refcnt); 45036375Ssklower ENDDEBUG 45136375Ssklower 45236375Ssklower /* free old route entry */ 45336375Ssklower RTFREE(ro->ro_rt); 45436375Ssklower ro->ro_rt = (struct rtentry *)0; 45536375Ssklower } else { 45636375Ssklower IFDEBUG(D_ROUTE) 45736375Ssklower printf("clnp_route: OK route exists\n"); 45836375Ssklower ENDDEBUG 45936375Ssklower } 46036375Ssklower 46136375Ssklower if (ro->ro_rt == 0) { 46236375Ssklower /* set up new route structure */ 46337469Ssklower bzero((caddr_t)&ro->ro_dst, sizeof(ro->ro_dst)); 46437469Ssklower ro->ro_dst.siso_len = sizeof(ro->ro_dst); 46537469Ssklower ro->ro_dst.siso_family = AF_ISO; 46637469Ssklower Bcopy(dst, &ro->ro_dst.siso_addr, 1 + dst->isoa_len); 46736375Ssklower /* allocate new route */ 46836375Ssklower IFDEBUG(D_ROUTE) 46936375Ssklower printf("clnp_route: allocating new route to %s\n", 47036375Ssklower clnp_iso_addrp(dst)); 47136375Ssklower ENDDEBUG 47237469Ssklower rtalloc((struct route *)ro); 47336375Ssklower } 47437469Ssklower if (ro->ro_rt == 0) 47536375Ssklower return(ENETUNREACH); /* rtalloc failed */ 47637469Ssklower ro->ro_rt->rt_use++; 47737469Ssklower if (ifa) 47837469Ssklower if ((*ifa = (struct iso_ifaddr *)ro->ro_rt->rt_ifa) == 0) 47937469Ssklower panic("clnp_route"); 48037469Ssklower if (first_hop) { 48140776Ssklower if (ro->ro_rt->rt_flags & RTF_GATEWAY) 48237469Ssklower *first_hop = ro->ro_rt->rt_gateway; 48337469Ssklower else 48437469Ssklower *first_hop = (struct sockaddr *)&ro->ro_dst; 48536375Ssklower } 48636375Ssklower return(0); 48736375Ssklower } 48836375Ssklower 48936375Ssklower /* 49036375Ssklower * FUNCTION: clnp_srcroute 49136375Ssklower * 49236375Ssklower * PURPOSE: Source route the datagram. If complete source 49336375Ssklower * routing is specified but not possible, then 49436375Ssklower * return an error. If src routing is terminated, then 49536375Ssklower * try routing on destination. 49636375Ssklower * Usage of first_hop, 49736375Ssklower * ifp, and error return is identical to clnp_route. 49836375Ssklower * 49936375Ssklower * RETURNS: 0 or unix error code 50036375Ssklower * 50136375Ssklower * SIDE EFFECTS: 50236375Ssklower * 50336375Ssklower * NOTES: Remember that option index pointers are really 50436375Ssklower * offsets from the beginning of the mbuf. 50536375Ssklower */ 50643332Ssklower clnp_srcroute(options, oidx, ro, first_hop, ifa, final_dst) 50736375Ssklower struct mbuf *options; /* ptr to options */ 50836375Ssklower struct clnp_optidx *oidx; /* index to options */ 50943332Ssklower struct route_iso *ro; /* route structure */ 51036375Ssklower struct sockaddr **first_hop; /* RETURN: fill in with ptr to firsthop */ 51137469Ssklower struct iso_ifaddr **ifa; /* RETURN: fill in with ptr to interface */ 51236375Ssklower struct iso_addr *final_dst; /* final destination */ 51336375Ssklower { 51436375Ssklower struct iso_addr dst; /* first hop specified by src rt */ 51536375Ssklower int error = 0; /* return code */ 51636375Ssklower 51736375Ssklower /* 51836375Ssklower * Check if we have run out of routes 51936375Ssklower * If so, then try to route on destination. 52036375Ssklower */ 52136375Ssklower if CLNPSRCRT_TERM(oidx, options) { 52236375Ssklower dst.isoa_len = final_dst->isoa_len; 52337469Ssklower bcopy(final_dst->isoa_genaddr, dst.isoa_genaddr, dst.isoa_len); 52436375Ssklower } else { 52536375Ssklower /* 52636375Ssklower * setup dst based on src rt specified 52736375Ssklower */ 52836375Ssklower dst.isoa_len = CLNPSRCRT_CLEN(oidx, options); 52937469Ssklower bcopy(CLNPSRCRT_CADDR(oidx, options), dst.isoa_genaddr, dst.isoa_len); 53036375Ssklower } 53136375Ssklower 53236375Ssklower /* 53336375Ssklower * try to route it 53436375Ssklower */ 53543332Ssklower error = clnp_route(&dst, ro, 0, first_hop, ifa); 53636375Ssklower if (error != 0) 53736375Ssklower return error; 53836375Ssklower 53936375Ssklower /* 54036375Ssklower * If complete src rt, first hop must be equal to dst 54136375Ssklower */ 54236375Ssklower if ((CLNPSRCRT_TYPE(oidx, options) == CLNPOVAL_COMPRT) && 54336375Ssklower (!iso_addrmatch1(&(*(struct sockaddr_iso **)first_hop)->siso_addr,&dst))){ 54436375Ssklower IFDEBUG(D_OPTIONS) 54536375Ssklower printf("clnp_srcroute: complete src route failed\n"); 54636375Ssklower ENDDEBUG 54736375Ssklower return EHOSTUNREACH; /* RAH? would like ESRCRTFAILED */ 54836375Ssklower } 54936375Ssklower 55036375Ssklower return error; 55136375Ssklower } 55236375Ssklower 55336375Ssklower /* 55452487Ssklower * FUNCTION: clnp_echoreply 55552487Ssklower * 55652487Ssklower * PURPOSE: generate an echo reply packet and transmit 55752487Ssklower * 55852487Ssklower * RETURNS: result of clnp_output 55952487Ssklower * 56052487Ssklower * SIDE EFFECTS: 56152487Ssklower */ 56252487Ssklower clnp_echoreply(ec_m, ec_len, ec_src, ec_dst, ec_oidxp) 56352487Ssklower struct mbuf *ec_m; /* echo request */ 56452487Ssklower int ec_len; /* length of ec */ 56552487Ssklower struct sockaddr_iso *ec_src; /* src of ec */ 56652487Ssklower struct sockaddr_iso *ec_dst; /* destination of ec (i.e., us) */ 56752487Ssklower struct clnp_optidx *ec_oidxp; /* options index to ec packet */ 56852487Ssklower { 56952487Ssklower struct isopcb isopcb; 57052487Ssklower int flags = CLNP_NOCACHE|CLNP_ECHOR; 57152487Ssklower int ret; 57252487Ssklower 57352487Ssklower /* fill in fake isopcb to pass to output function */ 57452487Ssklower bzero(&isopcb, sizeof(isopcb)); 57552487Ssklower isopcb.isop_laddr = ec_dst; 57652487Ssklower isopcb.isop_faddr = ec_src; 57752487Ssklower 57852487Ssklower /* forget copying the options for now. If implemented, need only 57952487Ssklower * copy record route option, but it must be reset to zero length */ 58052487Ssklower 58152487Ssklower ret = clnp_output(ec_m, &isopcb, ec_len, flags); 58252487Ssklower 58352487Ssklower IFDEBUG(D_OUTPUT) 58452487Ssklower printf("clnp_echoreply: output returns %d\n", ret); 58552487Ssklower ENDDEBUG 58652487Ssklower return ret; 58752487Ssklower } 58852487Ssklower 58952487Ssklower /* 59048740Ssklower * FUNCTION: clnp_badmtu 59148740Ssklower * 59248740Ssklower * PURPOSE: print notice of route with mtu not initialized. 59348740Ssklower * 59448740Ssklower * RETURNS: mtu of ifp. 59548740Ssklower * 59648740Ssklower * SIDE EFFECTS: prints notice, slows down system. 59748740Ssklower */ 59848740Ssklower clnp_badmtu(ifp, rt, line, file) 59948740Ssklower struct ifnet *ifp; /* outgoing interface */ 60048740Ssklower struct rtentry *rt; /* dst route */ 60148740Ssklower int line; /* where the dirty deed occured */ 60248740Ssklower char *file; /* where the dirty deed occured */ 60348740Ssklower { 60457951Ssklower printf("sending on route 0x%x with no mtu, line %d of file %s\n", 60548740Ssklower rt, line, file); 60648740Ssklower #ifdef ARGO_DEBUG 60757951Ssklower printf("route dst is "); 60848740Ssklower dump_isoaddr(rt_key(rt)); 60948740Ssklower #endif 61048740Ssklower return ifp->if_mtu; 61148740Ssklower } 61248740Ssklower 61348740Ssklower /* 61436375Ssklower * FUNCTION: clnp_ypocb - backwards bcopy 61536375Ssklower * 61636375Ssklower * PURPOSE: bcopy starting at end of src rather than beginning. 61736375Ssklower * 61836375Ssklower * RETURNS: none 61936375Ssklower * 62036375Ssklower * SIDE EFFECTS: 62136375Ssklower * 62236375Ssklower * NOTES: No attempt has been made to make this efficient 62336375Ssklower */ 62436375Ssklower clnp_ypocb(from, to, len) 62536375Ssklower caddr_t from; /* src buffer */ 62636375Ssklower caddr_t to; /* dst buffer */ 62736375Ssklower u_int len; /* number of bytes */ 62836375Ssklower { 62936375Ssklower while (len--) 63036375Ssklower *(to + len) = *(from + len); 63136375Ssklower } 632*61290Ssklower #endif /* ISO */ 633