diff --git a/usr.sbin/IPXrouted/af.c b/usr.sbin/IPXrouted/af.c index 0936b436d6d8..05034ab0644a 100644 --- a/usr.sbin/IPXrouted/af.c +++ b/usr.sbin/IPXrouted/af.c @@ -1,280 +1,298 @@ /* * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1995 John Hay. All rights reserved. * * This file includes significant work done at Cornell University by * Bill Nesheim. That work included by permission. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: af.c,v 1.4 1997/02/22 16:00:54 peter Exp $ */ #ifndef lint static char sccsid[] = "@(#)af.c 8.1 (Berkeley) 6/5/93"; #endif /* not lint */ #include "defs.h" /* * Address family support routines */ af_hash_t null_hash; af_netmatch_t null_netmatch; af_output_t null_output; af_portmatch_t null_portmatch; af_portcheck_t null_portcheck; af_checkhost_t null_checkhost; af_ishost_t null_ishost; af_canon_t null_canon; void ipxnet_hash(struct sockaddr_ipx *, struct afhash *); int ipxnet_netmatch(struct sockaddr_ipx *, struct sockaddr_ipx *); void ipxnet_output(int, int, struct sockaddr_ipx *, int); int ipxnet_portmatch(struct sockaddr_ipx *); int ipxnet_checkhost(struct sockaddr_ipx *); int ipxnet_ishost(struct sockaddr_ipx *); void ipxnet_canon(struct sockaddr_ipx *); #define NIL \ { null_hash, null_netmatch, null_output, \ null_portmatch, null_portcheck, null_checkhost, \ null_ishost, null_canon } #define IPXNET \ { (af_hash_t *)ipxnet_hash, \ (af_netmatch_t *)ipxnet_netmatch, \ (af_output_t *)ipxnet_output, \ (af_portmatch_t *)ipxnet_portmatch, \ (af_portcheck_t *)ipxnet_portmatch, \ (af_checkhost_t *)ipxnet_checkhost, \ (af_ishost_t *)ipxnet_ishost, \ (af_canon_t *)ipxnet_canon } struct afswitch afswitch[AF_MAX] = { NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, IPXNET, NIL, NIL }; struct sockaddr_ipx ipxnet_default = { sizeof(struct sockaddr_ipx), AF_IPX }; union ipx_net ipx_anynet; union ipx_net ipx_zeronet; void ipxnet_hash(sipx, hp) register struct sockaddr_ipx *sipx; struct afhash *hp; { - register long hash = 0; - register u_short *s = sipx->sipx_addr.x_host.s_host; - union ipx_net_u net; + long hash; +#if 0 + u_short *s = sipx->sipx_addr.x_host.s_host; +#endif + u_char *c; + + c = sipx->sipx_addr.x_net.c_net; - net.net_e = sipx->sipx_addr.x_net; - hp->afh_nethash = net.long_e; +#define IMVAL 33 + hash = 0; + hash = hash * IMVAL + *c++; + hash = hash * IMVAL + *c++; + hash = hash * IMVAL + *c++; + hash = hash * IMVAL + *c++; +#undef IMVAL + + hp->afh_nethash = hash; + hp->afh_nethash ^= (hash >> 8); + hp->afh_nethash ^= (hash >> 16); + hp->afh_nethash ^= (hash >> 24); + +#if 0 + hash = 0; hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s; hp->afh_hosthash = hash; +#endif } int ipxnet_netmatch(sxn1, sxn2) struct sockaddr_ipx *sxn1, *sxn2; { return (ipx_neteq(sxn1->sipx_addr, sxn2->sipx_addr)); } /* * Verify the message is from the right port. */ int ipxnet_portmatch(sipx) register struct sockaddr_ipx *sipx; { return (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP ); } /* * ipx output routine. */ #ifdef DEBUG int do_output = 0; #endif void ipxnet_output(s, flags, sipx, size) int s; int flags; struct sockaddr_ipx *sipx; int size; { struct sockaddr_ipx dst; dst = *sipx; sipx = &dst; if (sipx->sipx_addr.x_port == 0) sipx->sipx_addr.x_port = htons(IPXPORT_RIP); #ifdef DEBUG if(do_output || ntohs(msg->rip_cmd) == RIPCMD_REQUEST) #endif /* * Kludge to allow us to get routes out to machines that * don't know their addresses yet; send to that address on * ALL connected nets */ if (ipx_neteqnn(sipx->sipx_addr.x_net, ipx_zeronet)) { extern struct interface *ifnet; register struct interface *ifp; for (ifp = ifnet; ifp; ifp = ifp->int_next) { sipx->sipx_addr.x_net = satoipx_addr(ifp->int_addr).x_net; (void) sendto(s, msg, size, flags, (struct sockaddr *)sipx, sizeof (*sipx)); } return; } (void) sendto(s, msg, size, flags, (struct sockaddr *)sipx, sizeof (*sipx)); } /* * Return 1 if we want this route. * We use this to disallow route net G entries for one for multiple * point to point links. */ int ipxnet_checkhost(sipx) struct sockaddr_ipx *sipx; { register struct interface *ifp = if_ifwithnet((struct sockaddr *)sipx); /* * We want this route if there is no more than one * point to point interface with this network. */ if (ifp == 0 || (ifp->int_flags & IFF_POINTOPOINT)==0) return (1); return (ifp->int_sq.n == ifp->int_sq.p); } /* * Return 1 if the address is * for a host, 0 for a network. */ int ipxnet_ishost(sipx) struct sockaddr_ipx *sipx; { register u_short *s = sipx->sipx_addr.x_host.s_host; if ((s[0]==0x0000) && (s[1]==0x0000) && (s[2]==0x0000)) return (0); if ((s[0]==0xffff) && (s[1]==0xffff) && (s[2]==0xffff)) return (0); return (1); } void ipxnet_canon(sipx) struct sockaddr_ipx *sipx; { sipx->sipx_addr.x_port = 0; } void null_hash(addr, hp) struct sockaddr *addr; struct afhash *hp; { hp->afh_nethash = hp->afh_hosthash = 0; } int null_netmatch(a1, a2) struct sockaddr *a1, *a2; { return (0); } void null_output(s, f, a1, n) int s; int f; struct sockaddr *a1; int n; { ; } int null_portmatch(a1) struct sockaddr *a1; { return (0); } int null_portcheck(a1) struct sockaddr *a1; { return (0); } int null_ishost(a1) struct sockaddr *a1; { return (0); } int null_checkhost(a1) struct sockaddr *a1; { return (0); } void null_canon(a1) struct sockaddr *a1; { ; } diff --git a/usr.sbin/IPXrouted/defs.h b/usr.sbin/IPXrouted/defs.h index a2950286d34c..55e08b34c3aa 100644 --- a/usr.sbin/IPXrouted/defs.h +++ b/usr.sbin/IPXrouted/defs.h @@ -1,106 +1,106 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1995 John Hay. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)defs.h 8.1 (Berkeley) 6/5/93 * - * $Id$ + * $Id: defs.h,v 1.5 1997/02/22 16:00:55 peter Exp $ */ #include #include #include #include #if defined(vax) || defined(pdp11) #define xnnet(x) ((u_long) (x)->rip_dst[1] << 16 | (u_long) (x)->rip_dst[0] ) #else #define xnnet(x) ((u_long) (x)->rip_dst[0] << 16 | (u_long) (x)->rip_dst[1] ) #endif #include #include #include #include "protocol.h" #include "sap.h" #include "table.h" #include "trace.h" #include "interface.h" #include "af.h" /* * When we find any interfaces marked down we rescan the * kernel every CHECK_INTERVAL seconds to see if they've * come up. */ #define CHECK_INTERVAL (5*60) #define equal(a1, a2) \ (bcmp((caddr_t)(a1), (caddr_t)(a2), sizeof (struct sockaddr)) == 0) #define min(a,b) ((a)>(b)?(b):(a)) #define max(a,b) ((a)<(b)?(b):(a)) extern int ripsock; /* Socket to listen on */ extern int sapsock; /* Socket to listen on */ extern int kmem; extern int supplier; /* process should supply updates */ extern int dosap; /* SAP is enabled */ extern int install; /* if 1 call kernel */ extern int lookforinterfaces; /* if 1 probe kernel for new up ifs */ extern int performnlist; /* if 1 check if /kernel has changed */ extern int externalinterfaces; /* # of remote and local interfaces */ extern int timeval; /* local idea of time */ extern int noteremoterequests; /* squawk on requests from non-local nets */ extern int r; /* Routing socket to install updates with */ extern int gateway; extern struct sockaddr_ipx ipx_netmask; /* Used in installing routes */ extern char packet[MAXRXPACKETSIZE+1]; extern struct rip *msg; extern char **argv0; #define ADD 1 #define DELETE 2 #define CHANGE 3 -void sndmsg(struct sockaddr *, int, struct interface *); -void supply(struct sockaddr *, int, struct interface *); +void sndmsg(struct sockaddr *, int, struct interface *, int); +void supply(struct sockaddr *, int, struct interface *, int); void addrouteforif(struct interface *); void ifinit(void); -void toall(void (*f)(struct sockaddr *, int, struct interface *), - struct rt_entry *); +void toall(void (*f)(struct sockaddr *, int, struct interface *, int), + struct rt_entry *, int); void rip_input(struct sockaddr *, int); diff --git a/usr.sbin/IPXrouted/if.c b/usr.sbin/IPXrouted/if.c index e8aeaa69f087..c2522a9fb81f 100644 --- a/usr.sbin/IPXrouted/if.c +++ b/usr.sbin/IPXrouted/if.c @@ -1,151 +1,151 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1995 John Hay. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * static char sccsid[] = "@(#)if.c 5.1 (Berkeley) 6/4/85"; (routed/if.c) * - * $Id$ + * $Id: if.c,v 1.3 1997/02/22 16:00:55 peter Exp $ */ #ifndef lint static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93"; #endif /* not lint */ /* * Routing Table Management Daemon */ #include "defs.h" extern struct interface *ifnet; /* * Find the interface with address addr. */ struct interface * if_ifwithaddr(addr) struct sockaddr *addr; { register struct interface *ifp; #define same(a1, a2) \ - (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) + (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 10) == 0) for (ifp = ifnet; ifp; ifp = ifp->int_next) { if (ifp->int_flags & IFF_REMOTE) continue; if (ifp->int_addr.sa_family != addr->sa_family) continue; if (same(&ifp->int_addr, addr)) break; if ((ifp->int_flags & IFF_BROADCAST) && same(&ifp->int_broadaddr, addr)) break; } return (ifp); } /* * Find the point-to-point interface with destination address addr. */ struct interface * if_ifwithdstaddr(addr) struct sockaddr *addr; { register struct interface *ifp; for (ifp = ifnet; ifp; ifp = ifp->int_next) { if ((ifp->int_flags & IFF_POINTOPOINT) == 0) continue; if (same(&ifp->int_dstaddr, addr)) break; } return (ifp); } /* * Find the interface on the network * of the specified address. */ struct interface * if_ifwithnet(addr) register struct sockaddr *addr; { register struct interface *ifp; register int af = addr->sa_family; register int (*netmatch)(); if (af >= AF_MAX) return (0); netmatch = afswitch[af].af_netmatch; for (ifp = ifnet; ifp; ifp = ifp->int_next) { if (ifp->int_flags & IFF_REMOTE) continue; if (af != ifp->int_addr.sa_family) continue; if ((*netmatch)(addr, &ifp->int_addr)) break; } return (ifp); } /* * Find an interface from which the specified address * should have come from. Used for figuring out which * interface a packet came in on -- for tracing. */ struct interface * if_iflookup(addr) struct sockaddr *addr; { register struct interface *ifp, *maybe; register int af = addr->sa_family; register int (*netmatch)(); if (af >= AF_MAX) return (0); maybe = 0; netmatch = afswitch[af].af_netmatch; for (ifp = ifnet; ifp; ifp = ifp->int_next) { if (ifp->int_addr.sa_family != af) continue; if (same(&ifp->int_addr, addr)) break; if ((ifp->int_flags & IFF_BROADCAST) && same(&ifp->int_broadaddr, addr)) break; if (maybe == 0 && (*netmatch)(addr, &ifp->int_addr)) maybe = ifp; } if (ifp == 0) ifp = maybe; return (ifp); } diff --git a/usr.sbin/IPXrouted/input.c b/usr.sbin/IPXrouted/input.c index cf54e89c9a79..a9e2f3924e48 100644 --- a/usr.sbin/IPXrouted/input.c +++ b/usr.sbin/IPXrouted/input.c @@ -1,281 +1,304 @@ /* * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1995 John Hay. All rights reserved. * * This file includes significant work done at Cornell University by * Bill Nesheim. That work included by permission. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: input.c,v 1.5 1997/02/22 16:00:56 peter Exp $ */ #ifndef lint static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93"; #endif /* not lint */ /* * IPX Routing Table Management Daemon */ #include "defs.h" struct sockaddr * ipx_nettosa(net) union ipx_net net; { static struct sockaddr_ipx sxn; bzero(&sxn, sizeof (struct sockaddr_ipx)); sxn.sipx_family = AF_IPX; sxn.sipx_len = sizeof (sxn); sxn.sipx_addr.x_net = net; return( (struct sockaddr *)&sxn); } /* * Process a newly received packet. */ void rip_input(from, size) struct sockaddr *from; int size; { + int newsize; + int rtchanged = 0; struct rt_entry *rt; struct netinfo *n; struct interface *ifp = 0; - int newsize; struct afswitch *afp; struct sockaddr_ipx *ipxp; ifp = if_ifwithnet(from); ipxp = (struct sockaddr_ipx *)from; if (ifp == 0) { if(ftrace) { fprintf(ftrace, "Received bogus packet from %s\n", ipxdp_ntoa(&ipxp->sipx_addr)); } return; } TRACE_INPUT(ifp, from, size); if (from->sa_family >= AF_MAX) return; afp = &afswitch[from->sa_family]; size -= sizeof (u_short) /* command */; n = msg->rip_nets; switch (ntohs(msg->rip_cmd)) { case RIPCMD_REQUEST: if (ipx_hosteq(satoipx_addr(ifp->int_addr), ipxp->sipx_addr)) return; newsize = 0; while (size > 0) { if (size < sizeof (struct netinfo)) break; size -= sizeof (struct netinfo); /* * A single entry with rip_dst == DSTNETS_ALL and * metric ``infinity'' means ``all routes''. * * XXX According to the IPX RIP spec the metric * and tick fields can be anything. So maybe we * should not check the metric??? */ if (ipx_neteqnn(n->rip_dst, ipx_anynet) && ntohs(n->rip_metric) == HOPCNT_INFINITY && size == 0) { - supply(from, 0, ifp); + supply(from, 0, ifp, 0); return; } /* * request for specific nets */ rt = rtlookup(ipx_nettosa(n->rip_dst)); if (ftrace) { fprintf(ftrace, "specific request for %s", ipxdp_nettoa(n->rip_dst)); fprintf(ftrace, " yields route %x\n", (u_int)rt); } /* * XXX We break out on the first net that isn't * found. The specs is a bit vague here. I'm not * sure what we should do. */ if (rt == 0) return; /* XXX * According to the spec we should not include * information about networks for which the number * of hops is 16. */ if (rt->rt_metric == (HOPCNT_INFINITY-1)) return; n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY : min(rt->rt_metric+1, HOPCNT_INFINITY)); n->rip_ticks = htons(rt->rt_ticks+1); /* * We use split horizon with a twist. If the requested * net is the directly connected net we supply an * answer. This is so that the host can learn about * the routers on its net. */ { register struct rt_entry *trt = rt; while (trt) { if ((trt->rt_ifp == ifp) && !ipx_neteqnn(n->rip_dst, satoipx_addr(ifp->int_addr).x_net)) return; trt = trt->rt_clone; } n++; newsize += sizeof (struct netinfo); } } if (newsize > 0) { msg->rip_cmd = htons(RIPCMD_RESPONSE); newsize += sizeof (u_short); /* should check for if with dstaddr(from) first */ (*afp->af_output)(ripsock, 0, from, newsize); TRACE_OUTPUT(ifp, from, newsize); if (ftrace) { /* XXX This should not happen anymore. */ if(ifp == 0) fprintf(ftrace, "--- ifp = 0\n"); else fprintf(ftrace, "request arrived on interface %s\n", ifp->int_name); } } return; case RIPCMD_RESPONSE: /* verify message came from a router */ if ((*afp->af_portmatch)(from) == 0) return; (*afp->af_canon)(from); /* are we talking to ourselves? */ if ((ifp = if_ifwithaddr(from)) != 0) { rt = rtfind(from); - if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0) + if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0) { addrouteforif(ifp); - else + rtchanged = 1; + } else rt->rt_timer = 0; return; } /* Update timer for interface on which the packet arrived. * If from other end of a point-to-point link that isn't * in the routing tables, (re-)add the route. */ if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) { if(ftrace) fprintf(ftrace, "Got route\n"); rt->rt_timer = 0; } else if ((ifp = if_ifwithdstaddr(from)) != 0) { if(ftrace) fprintf(ftrace, "Got partner\n"); addrouteforif(ifp); + rtchanged = 1; } for (; size > 0; size -= sizeof (struct netinfo), n++) { struct sockaddr *sa; if (size < sizeof (struct netinfo)) break; - if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY) + if ((unsigned) ntohs(n->rip_metric) > HOPCNT_INFINITY) continue; rt = rtfind(sa = ipx_nettosa(n->rip_dst)); if (rt == 0) { + if (ntohs(n->rip_metric) == HOPCNT_INFINITY) + continue; rtadd(sa, from, ntohs(n->rip_metric), ntohs(n->rip_ticks), 0); + rtchanged = 1; continue; } /* * A clone is a different route to the same net * with exactly the same cost (ticks and metric). * They must all be recorded because those interfaces * must be handled in the same way as the first route * to that net. ie When using the split horizon * algorithm we must look at these interfaces also. * * Update if from gateway and different, * from anywhere and less ticks or * if same ticks and shorter, * or getting stale and equivalent. - * - * XXX I don't think this is quite right. */ if (!equal(from, &rt->rt_router) && - ntohs(n->rip_ticks == rt->rt_ticks) && - ntohs(n->rip_metric == rt->rt_metric)) { + ntohs(n->rip_ticks) == rt->rt_ticks && + ntohs(n->rip_metric) == rt->rt_metric && + ntohs(n->rip_metric) != HOPCNT_INFINITY) { register struct rt_entry *trt = rt->rt_clone; while (trt) { if (equal(from, &trt->rt_router)) { trt->rt_timer = 0; break; } trt = trt->rt_clone; } if (trt == NULL) { rtadd_clone(rt, sa, from, ntohs(n->rip_metric), ntohs(n->rip_ticks), 0); } continue; } if ((equal(from, &rt->rt_router) && ((ntohs(n->rip_ticks) != rt->rt_ticks) || (ntohs(n->rip_metric) != rt->rt_metric))) || (ntohs(n->rip_ticks) < rt->rt_ticks) || ((ntohs(n->rip_ticks) == rt->rt_ticks) && (ntohs(n->rip_metric) < rt->rt_metric)) || (rt->rt_timer > (EXPIRE_TIME*2/3) && - rt->rt_metric == ntohs(n->rip_metric))) { + rt->rt_metric == ntohs(n->rip_metric) && + ntohs(n->rip_metric) != HOPCNT_INFINITY)) { rtchange(rt, from, ntohs(n->rip_metric), ntohs(n->rip_ticks)); - rt->rt_timer = 0; + if (ntohs(n->rip_metric) == HOPCNT_INFINITY) + rt->rt_timer = EXPIRE_TIME; + else + rt->rt_timer = 0; + rtchanged = 1; } else if (equal(from, &rt->rt_router) && (ntohs(n->rip_ticks) == rt->rt_ticks) && - (ntohs(n->rip_metric) == rt->rt_metric)) { + (ntohs(n->rip_metric) == rt->rt_metric) && + (ntohs(n->rip_metric) != HOPCNT_INFINITY)) { rt->rt_timer = 0; } } + if (rtchanged) { + register struct rthash *rh; + register struct rt_entry *rt; + + toall(supply, NULL, 1); + for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) + for (rt = rh->rt_forw; + rt != (struct rt_entry *)rh; + rt = rt->rt_forw) + rt->rt_state &= ~RTS_CHANGED; + } + return; } } diff --git a/usr.sbin/IPXrouted/main.c b/usr.sbin/IPXrouted/main.c index a441371938bc..9af5b2ec95cb 100644 --- a/usr.sbin/IPXrouted/main.c +++ b/usr.sbin/IPXrouted/main.c @@ -1,363 +1,395 @@ /* * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1995 John Hay. All rights reserved. * * This file includes significant work done at Cornell University by * Bill Nesheim. That work included by permission. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: main.c,v 1.6 1997/02/22 16:00:57 peter Exp $ */ #ifndef lint static char copyright[] = "@(#) Copyright (c) 1985, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93"; #endif /* not lint */ /* * IPX Routing Information Protocol Daemon */ #include "defs.h" #include #include #include #include #include #include #include #include #define SAP_PKT 0 #define RIP_PKT 1 struct sockaddr_ipx addr; /* Daemon's Address */ int ripsock; /* RIP Socket to listen on */ int sapsock; /* SAP Socket to listen on */ int kmem; int install; /* if 1 call kernel */ int lookforinterfaces; /* if 1 probe kernel for new up interfaces */ int performnlist; /* if 1 check if /kernel has changed */ int externalinterfaces; /* # of remote and local interfaces */ int timeval; /* local idea of time */ int noteremoterequests; /* squawk on requests from non-local nets */ int r; /* Routing socket to install updates with */ struct sockaddr_ipx ipx_netmask; /* Used in installing routes */ char packet[MAXRXPACKETSIZE+1]; char **argv0; int supplier = -1; /* process should supply updates */ int dosap = 1; /* By default do SAP services. */ +int dobcast = 1; /* A RIP/SAP broadcast is needed. */ +time_t lastbcast; /* Time of last RIP/SAP broadcast */ struct rip *msg = (struct rip *) &packet[sizeof (struct ipx)]; struct sap_packet *sap_msg = (struct sap_packet *) &packet[sizeof (struct ipx)]; void hup(), fkexit(), timer(); void process(int fd, int pkt_type); int getsocket(int type, int proto, struct sockaddr_ipx *sipx); void getinfo(); +void catchtimer(); int main(argc, argv) int argc; char *argv[]; { int nfds; fd_set fdvar; + time_t ttime; + struct itimerval tval; argv0 = argv; argv++, argc--; while (argc > 0 && **argv == '-') { if (strcmp(*argv, "-s") == 0) { supplier = 1; argv++, argc--; continue; } if (strcmp(*argv, "-q") == 0) { supplier = 0; argv++, argc--; continue; } if (strcmp(*argv, "-R") == 0) { noteremoterequests++; argv++, argc--; continue; } if (strcmp(*argv, "-S") == 0) { dosap = 0; argv++, argc--; continue; } if (strcmp(*argv, "-t") == 0) { tracepackets++; argv++, argc--; ftrace = stderr; tracing = 1; continue; } if (strcmp(*argv, "-g") == 0) { gateway = 1; argv++, argc--; continue; } if (strcmp(*argv, "-l") == 0) { gateway = -1; argv++, argc--; continue; } fprintf(stderr, "usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n"); exit(1); } #ifndef DEBUG if (!tracepackets) daemon(0, 0); #endif openlog("IPXrouted", LOG_PID, LOG_DAEMON); addr.sipx_family = AF_IPX; addr.sipx_len = sizeof(addr); addr.sipx_port = htons(IPXPORT_RIP); ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1; ipx_netmask.sipx_addr.x_net = ipx_anynet; ipx_netmask.sipx_len = 6; ipx_netmask.sipx_family = AF_IPX; r = socket(AF_ROUTE, SOCK_RAW, 0); /* later, get smart about lookingforinterfaces */ if (r) shutdown(r, 0); /* for now, don't want reponses */ else { fprintf(stderr, "IPXrouted: no routing socket\n"); exit(1); } ripsock = getsocket(SOCK_DGRAM, 0, &addr); if (ripsock < 0) exit(1); if (dosap) { addr.sipx_port = htons(IPXPORT_SAP); sapsock = getsocket(SOCK_DGRAM, 0, &addr); if (sapsock < 0) exit(1); } else sapsock = -1; /* * Any extra argument is considered * a tracing log file. */ if (argc > 0) traceon(*argv); /* * Collect an initial view of the world by * snooping in the kernel. Then, send a request packet on all * directly connected networks to find out what * everyone else thinks. */ rtinit(); sapinit(); ifinit(); if (supplier < 0) supplier = 0; /* request the state of the world */ msg->rip_cmd = htons(RIPCMD_REQUEST); msg->rip_nets[0].rip_dst = ipx_anynet; msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); msg->rip_nets[0].rip_ticks = htons(-1); - toall(sndmsg, NULL); + toall(sndmsg, NULL, 0); if (dosap) { sap_msg->sap_cmd = htons(SAP_REQ); sap_msg->sap[0].ServType = htons(SAP_WILDCARD); - toall(sapsndmsg, NULL); + toall(sapsndmsg, NULL, 0); } - signal(SIGALRM, timer); + signal(SIGALRM, catchtimer); signal(SIGHUP, hup); signal(SIGINT, hup); signal(SIGEMT, fkexit); signal(SIGINFO, getinfo); - timer(); - + + tval.it_interval.tv_sec = TIMER_RATE; + tval.it_interval.tv_usec = 0; + tval.it_value.tv_sec = TIMER_RATE; + tval.it_value.tv_usec = 0; + setitimer(ITIMER_REAL, &tval, NULL); + nfds = 1 + max(sapsock, ripsock); for (;;) { + if (dobcast) { + dobcast = 0; + lastbcast = time(NULL); + timer(); + } + FD_ZERO(&fdvar); if (dosap) { FD_SET(sapsock, &fdvar); } FD_SET(ripsock, &fdvar); if(select(nfds, &fdvar, (fd_set *)NULL, (fd_set *)NULL, (struct timeval *)NULL) < 0) { if(errno == EINTR) continue; perror("during select"); exit(1); } if(FD_ISSET(ripsock, &fdvar)) process(ripsock, RIP_PKT); if(dosap && FD_ISSET(sapsock, &fdvar)) process(sapsock, SAP_PKT); + + ttime = time(NULL); + if (ttime > (lastbcast + TIMER_RATE + (TIMER_RATE * 2 / 3))) { + dobcast = 1; + syslog(LOG_ERR, "Missed alarm"); + } } } void process(fd, pkt_type) int fd; int pkt_type; { struct sockaddr from; int fromlen = sizeof (from), cc, omask; struct ipx *ipxdp = (struct ipx *)packet; cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); if (cc <= 0) { if (cc < 0 && errno != EINTR) syslog(LOG_ERR, "recvfrom: %m"); return; } if (tracepackets > 1 && ftrace) { fprintf(ftrace,"rcv %d bytes on %s ", cc, ipxdp_ntoa(&ipxdp->ipx_dna)); fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna)); } if (noteremoterequests && !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) && !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna)) { syslog(LOG_ERR, "net of interface (%s) != net on ether (%s)!\n", ipxdp_nettoa(ipxdp->ipx_dna.x_net), ipxdp_nettoa(ipxdp->ipx_sna.x_net)); } /* We get the IPX header in front of the RIF packet*/ cc -= sizeof (struct ipx); #define mask(s) (1<<((s)-1)) omask = sigblock(mask(SIGALRM)); switch(pkt_type) { case SAP_PKT: sap_input(&from, cc); break; case RIP_PKT: rip_input(&from, cc); break; } sigsetmask(omask); } int getsocket(type, proto, sipx) int type, proto; struct sockaddr_ipx *sipx; { int domain = sipx->sipx_family; int retry, s, on = 1; retry = 1; while ((s = socket(domain, type, proto)) < 0 && retry) { syslog(LOG_ERR, "socket: %m"); sleep(5 * retry); retry <<= 1; } if (retry == 0) return (-1); while (bind(s, (struct sockaddr *)sipx, sizeof (*sipx)) < 0 && retry) { syslog(LOG_ERR, "bind: %m"); sleep(5 * retry); retry <<= 1; } if (retry == 0) return (-1); if (domain==AF_IPX) { struct ipx ipxdp; if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { syslog(LOG_ERR, "setsockopt SEE HEADERS: %m"); exit(1); } if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP) ipxdp.ipx_pt = IPXPROTO_RI; else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP) +#ifdef IPXPROTO_SAP ipxdp.ipx_pt = IPXPROTO_SAP; +#else + ipxdp.ipx_pt = IPXPROTO_PXP; +#endif else { syslog(LOG_ERR, "port should be either RIP or SAP"); exit(1); } if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp))) { syslog(LOG_ERR, "setsockopt SET HEADER: %m"); exit(1); } } if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); exit(1); } return (s); } /* * Fork and exit on EMT-- for profiling. */ void fkexit() { if (fork() == 0) exit(0); } +void +catchtimer() +{ + dobcast = 1; +} + void getinfo() { FILE *fh; fh = fopen("/tmp/ipxrouted.dmp", "a"); if(fh == NULL) return; dumpriptable(fh); dumpsaptable(fh, sap_head); fclose(fh); } diff --git a/usr.sbin/IPXrouted/output.c b/usr.sbin/IPXrouted/output.c index 06b9a1619b73..f824ecd27bfb 100644 --- a/usr.sbin/IPXrouted/output.c +++ b/usr.sbin/IPXrouted/output.c @@ -1,232 +1,231 @@ /* * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1995 John Hay. All rights reserved. * * This file includes significant work done at Cornell University by * Bill Nesheim. That work included by permission. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: output.c,v 1.6 1997/02/22 16:00:58 peter Exp $ */ #ifndef lint static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93"; #endif /* not lint */ /* * Routing Table Management Daemon */ #include #include "defs.h" /* * Apply the function "f" to all non-passive * interfaces. If the interface supports the * use of broadcasting use it, otherwise address * the output to the known router. */ void -toall(f, except) - void (*f)(struct sockaddr *, int, struct interface *); +toall(f, except, changesonly) + void (*f)(struct sockaddr *, int, struct interface *, int); struct rt_entry *except; + int changesonly; { register struct interface *ifp; register struct sockaddr *dst; register int flags; register struct rt_entry *trt; int onlist; extern struct interface *ifnet; for (ifp = ifnet; ifp; ifp = ifp->int_next) { if (ifp->int_flags & IFF_PASSIVE) continue; /* * Don't send it on interfaces in the except list. */ onlist = 0; trt = except; while(trt) { if (ifp == trt->rt_ifp) { onlist = 1; break; } trt = trt->rt_clone; } if (onlist) continue; dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr : ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr : &ifp->int_addr; flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; - (*f)(dst, flags, ifp); + (*f)(dst, flags, ifp, changesonly); } } /* * Output a preformed packet. */ void -sndmsg(dst, flags, ifp) +sndmsg(dst, flags, ifp, changesonly) struct sockaddr *dst; int flags; struct interface *ifp; + int changesonly; { (*afswitch[dst->sa_family].af_output) (ripsock, flags, dst, sizeof (struct rip)); TRACE_OUTPUT(ifp, dst, sizeof (struct rip)); } /* * Supply dst with the contents of the routing tables. * If this won't fit in one packet, chop it up into several. * * This must be done using the split horizon algorithm. * 1. Don't send routing info to the interface from where it was received. * 2. Don't publish an interface to itself. * 3. If a route is received from more than one interface and the cost is * the same, don't publish it on either interface. I am calling this * clones. */ void -supply(dst, flags, ifp) +supply(dst, flags, ifp, changesonly) struct sockaddr *dst; int flags; struct interface *ifp; + int changesonly; { register struct rt_entry *rt; register struct rt_entry *crt; /* Clone route */ register struct rthash *rh; register struct netinfo *nn; register struct netinfo *n = msg->rip_nets; - struct rthash *base = hosthash; struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) dst; af_output_t *output = afswitch[dst->sa_family].af_output; - int doinghost = 1, size, metric, ticks; + int size, metric, ticks; union ipx_net net; int delay = 0; if (sipx->sipx_port == 0) sipx->sipx_port = htons(IPXPORT_RIP); msg->rip_cmd = ntohs(RIPCMD_RESPONSE); -again: - for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) + for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { size = (char *)n - (char *)msg; if (size >= ((MAXRIPNETS * sizeof (struct netinfo)) + sizeof (msg->rip_cmd))) { (*output)(ripsock, flags, dst, size); TRACE_OUTPUT(ifp, dst, size); n = msg->rip_nets; delay++; if(delay == 2) { - usleep(20000); + usleep(50000); delay = 0; } } + if (changesonly && !(rt->rt_state & RTS_CHANGED)) + continue; + /* * This should do rule one and two of the split horizon * algorithm. */ if (rt->rt_ifp == ifp) continue; /* * Rule 3. * Look if we have clones (different routes to the same * place with exactly the same cost). * * We should not publish on any of the clone interfaces. */ crt = rt->rt_clone; while (crt) { if (crt->rt_ifp == ifp) goto next; crt = crt->rt_clone; } sipx = (struct sockaddr_ipx *)&rt->rt_dst; if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST) sipx = (struct sockaddr_ipx *)&rt->rt_router; if (rt->rt_metric == HOPCNT_INFINITY) metric = HOPCNT_INFINITY; else { metric = rt->rt_metric + 1; /* * We don't advertize routes with more than 15 hops. */ if (metric >= HOPCNT_INFINITY) continue; } /* XXX One day we should cater for slow interfaces also. */ ticks = rt->rt_ticks + 1; net = sipx->sipx_addr.x_net; /* * Make sure that we don't put out a two net entries * for a pt to pt link (one for the G route, one for the if) * This is a kludge, and won't work if there are lots of nets. */ for (nn = msg->rip_nets; nn < n; nn++) { if (ipx_neteqnn(net, nn->rip_dst)) { if (ticks < ntohs(nn->rip_ticks)) { nn->rip_metric = htons(metric); nn->rip_ticks = htons(ticks); } else if ((ticks == ntohs(nn->rip_ticks)) && (metric < ntohs(nn->rip_metric))) { nn->rip_metric = htons(metric); nn->rip_ticks = htons(ticks); } goto next; } } n->rip_dst = net; n->rip_metric = htons(metric); n->rip_ticks = htons(ticks); n++; next:; } - if (doinghost) { - doinghost = 0; - base = nethash; - goto again; - } if (n != msg->rip_nets) { size = (char *)n - (char *)msg; (*output)(ripsock, flags, dst, size); TRACE_OUTPUT(ifp, dst, size); } } diff --git a/usr.sbin/IPXrouted/sap.h b/usr.sbin/IPXrouted/sap.h index f5780d65abd6..5473851f08ab 100644 --- a/usr.sbin/IPXrouted/sap.h +++ b/usr.sbin/IPXrouted/sap.h @@ -1,109 +1,108 @@ /* * Copyright (c) 1995 John Hay. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by John Hay. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY John Hay AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL John Hay OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: sap.h,v 1.5 1997/02/22 16:00:59 peter Exp $ */ #ifndef _SAP_H_ #define _SAP_H_ -#define IPXPROTO_SAP IPXPROTO_PXP - #define SAP_REQ 1 #define SAP_RESP 2 #define SAP_REQ_NEAR 3 #define SAP_RESP_NEAR 4 #define SAPCMD_MAX 5 #ifdef SAPCMDS char *sapcmds[SAPCMD_MAX] = { "#0", "REQUEST", "RESPONSE", "REQ NEAREST", "RESP NEAREST"}; #endif #define MAXSAPENTRIES 7 #define SAP_WILDCARD 0xFFFF #define SERVNAMELEN 48 typedef struct sap_info { u_short ServType; char ServName[SERVNAMELEN]; struct ipx_addr ipx; u_short hops; }sap_info; typedef struct sap_packet { u_short sap_cmd; sap_info sap[0]; /* Variable length. */ }sap_packet; typedef struct sap_entry { struct sap_entry *forw; struct sap_entry *back; struct sap_entry *clone; struct interface *ifp; struct sap_info sap; struct sockaddr source; int hash; int state; int timer; - int metric; }sap_entry; -#define SAPHASHSIZ 32 /* Should be a power of 2 */ +#define SAPHASHSIZ 256 /* Should be a power of 2 */ #define SAPHASHMASK (SAPHASHSIZ-1) typedef struct sap_hash { struct sap_entry *forw; struct sap_entry *back; }sap_hash; extern sap_hash sap_head[SAPHASHSIZ]; extern struct sap_packet *sap_msg; void sapinit(void); void sap_input(struct sockaddr *from, int size); -void sapsndmsg(struct sockaddr *dst, int flags, struct interface *ifp); -void sap_supply_toall(void); +void sapsndmsg(struct sockaddr *dst, int flags, struct interface *ifp, + int changesonly); +void sap_supply_toall(int changesonly); void sap_supply(struct sockaddr *dst, int flags, struct interface *ifp, - int ServType); + int ServType, + int changesonly); struct sap_entry *sap_lookup(u_short ServType, char *ServName); struct sap_entry *sap_nearestserver(ushort ServType, struct interface *ifp); void sap_add(struct sap_info *si, struct sockaddr *from); void sap_change(struct sap_entry *sap, struct sap_info *si, struct sockaddr *from); void sap_add_clone(struct sap_entry *sap, struct sap_info *clone, struct sockaddr *from); void sap_delete(struct sap_entry *sap); #endif /*_SAP_H_*/ diff --git a/usr.sbin/IPXrouted/sap_input.c b/usr.sbin/IPXrouted/sap_input.c index c55d82f1dc01..26130fed7eed 100644 --- a/usr.sbin/IPXrouted/sap_input.c +++ b/usr.sbin/IPXrouted/sap_input.c @@ -1,181 +1,212 @@ /* * Copyright (c) 1995 John Hay. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by John Hay. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY John Hay AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL John Hay OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: sap_input.c,v 1.4 1997/02/22 16:00:59 peter Exp $ */ /* * IPX Routing Table Management Daemon */ #include "defs.h" /* * Process a newly received packet. */ void sap_input(from, size) struct sockaddr *from; int size; { + int newsize; + int sapchanged = 0; struct sap_entry *sap; struct sap_info *n; struct interface *ifp = 0; - int newsize; struct afswitch *afp; struct sockaddr_ipx *ipxp; ifp = if_ifwithnet(from); ipxp = (struct sockaddr_ipx *)from; if (ifp == 0) { if(ftrace) { fprintf(ftrace, "Received bogus packet from %s\n", ipxdp_ntoa(&ipxp->sipx_addr)); } return; } if (ftrace) dumpsappacket(ftrace, "received", from, (char *)sap_msg , size); if (from->sa_family >= AF_MAX) return; afp = &afswitch[from->sa_family]; size -= sizeof (u_short) /* command */; n = sap_msg->sap; switch (ntohs(sap_msg->sap_cmd)) { case SAP_REQ_NEAR: if (ftrace) fprintf(ftrace, "Received a sap REQ_NEAR packet.\n"); sap = sap_nearestserver(n->ServType, ifp); if (sap == NULL) return; sap_msg->sap_cmd = htons(SAP_RESP_NEAR); *n = sap->sap; n->hops = htons(ntohs(n->hops) + 1); if (ntohs(n->hops) >= HOPCNT_INFINITY) return; newsize = sizeof(struct sap_info) + sizeof(struct sap_packet); (*afp->af_output)(sapsock, 0, from, newsize); if (ftrace) { fprintf(ftrace, "sap_nearestserver %X %s returned:\n", ntohs(n->ServType), ifp->int_name); fprintf(ftrace, " service %04X %-20.20s " "addr %s.%04X metric %d\n", ntohs(sap->sap.ServType), sap->sap.ServName, ipxdp_ntoa(&sap->sap.ipx), ntohs(sap->sap.ipx.x_port), ntohs(sap->sap.hops)); } return; case SAP_REQ: if (ftrace) fprintf(ftrace, "Received a sap REQ packet.\n"); - sap_supply(from, 0, ifp, n->ServType); + sap_supply(from, 0, ifp, n->ServType, 0); return; case SAP_RESP_NEAR: /* XXX We do nothing here, for the moment. * Maybe we should check if the service is in our table? * */ if (ftrace) fprintf(ftrace, "Received a sap RESP_NEAR packet.\n"); return; case SAP_RESP: if (ftrace) fprintf(ftrace, "Received a sap RESP packet.\n"); (*afp->af_canon)(from); for (; size > 0; size -= sizeof (struct sap_info), n++) { if (size < sizeof (struct netinfo)) break; + /* + * The idea here is that if the hop count is more + * than INFINITY it is bogus and should be discarded. + * If it is equal to INFINITY it is a message to say + * that a service went down. If we don't allready + * have it in our tables discard it. Otherwise + * update our table and set the timer to EXPIRE_TIME + * so that it is removed next time we go through the + * tables. + */ + if (ntohs(n->hops) > HOPCNT_INFINITY) + continue; sap = sap_lookup(n->ServType, n->ServName); if (sap == 0) { + if (ntohs(n->hops) == HOPCNT_INFINITY) + continue; sap_add(n, from); + sapchanged = 1; continue; } /* * A clone is a different route to the same service * with exactly the same cost (metric). * They must all be recorded because those interfaces * must be handled in the same way as the first route * to that service. ie When using the split horizon * algorithm we must look at these interfaces also. * * Update if from gateway and different, * from anywhere and less hops or * getting stale and equivalent. - * - * XXX I don't think this is quite right yet. */ if (((ifp != sap->ifp) || !equal(&sap->source, from)) && (n->hops == sap->sap.hops) && (ntohs(n->hops) != HOPCNT_INFINITY)) { register struct sap_entry *tsap = sap->clone; while (tsap) { if ((ifp == tsap->ifp) && equal(&tsap->source, from)) { tsap->timer = 0; break; } tsap = tsap->clone; } if (tsap == NULL) { sap_add_clone(sap, n, from); } continue; } - if (((ifp == sap->ifp) && - equal(&sap->source, from) && - (n->hops != sap->sap.hops)) || - (ntohs(n->hops) < ntohs(sap->sap.hops)) || - (sap->timer > (EXPIRE_TIME*2/3) && - ntohs(sap->sap.hops) == ntohs(n->hops))) { + if ((ifp == sap->ifp) && + equal(&sap->source, from) && + (ntohs(n->hops) == ntohs(sap->sap.hops))) + sap->timer = 0; + else if (((ifp == sap->ifp) && + equal(&sap->source, from) && + (n->hops != sap->sap.hops)) || + (ntohs(n->hops) < ntohs(sap->sap.hops)) || + (sap->timer > (EXPIRE_TIME*2/3) && + ntohs(sap->sap.hops) == ntohs(n->hops) && + ntohs(n->hops) != HOPCNT_INFINITY)) { sap_change(sap, n, from); + sapchanged = 1; } } + if (sapchanged) { + register struct sap_entry *sap; + register struct sap_hash *sh; + sap_supply_toall(1); + + for (sh = sap_head; sh < &sap_head[SAPHASHSIZ]; sh++) + for (sap = sh->forw; + sap != (struct sap_entry *)sh; + sap = sap->forw) + sap->state &= ~RTS_CHANGED; + } return; } } diff --git a/usr.sbin/IPXrouted/sap_output.c b/usr.sbin/IPXrouted/sap_output.c index 11c9cc0a7cae..7f7dbcde6dc1 100644 --- a/usr.sbin/IPXrouted/sap_output.c +++ b/usr.sbin/IPXrouted/sap_output.c @@ -1,191 +1,197 @@ /* * Copyright (c) 1995 John Hay. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by John Hay. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY John Hay AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL John Hay OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: sap_output.c,v 1.7 1997/02/22 16:01:00 peter Exp $ */ /* * Routing Table Management Daemon */ #include #include "defs.h" /* * Apply the function "f" to all non-passive * interfaces. If the interface supports the * use of broadcasting use it, otherwise address * the output to the known router. */ void -sap_supply_toall(void) +sap_supply_toall(changesonly) + int changesonly; { register struct interface *ifp; struct sockaddr dst; register struct sockaddr_ipx *ipx_dst; register int flags; extern struct interface *ifnet; ipx_dst = (struct sockaddr_ipx *)&dst; for (ifp = ifnet; ifp; ifp = ifp->int_next) { if (ifp->int_flags & IFF_PASSIVE) continue; dst = ifp->int_flags & IFF_BROADCAST ? ifp->int_broadaddr : ifp->int_flags & IFF_POINTOPOINT ? ifp->int_dstaddr : ifp->int_addr; ipx_dst->sipx_addr.x_port = htons(IPXPORT_SAP); flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; - sap_supply(&dst, flags, ifp, SAP_WILDCARD); + sap_supply(&dst, flags, ifp, SAP_WILDCARD, changesonly); } } void -sapsndmsg(dst, flags, ifp) +sapsndmsg(dst, flags, ifp, changesonly) struct sockaddr *dst; int flags; struct interface *ifp; + int changesonly; { struct sockaddr t_dst; struct sockaddr_ipx *ipx_dst; t_dst = *dst; ipx_dst = (struct sockaddr_ipx *)&t_dst; if (ipx_dst->sipx_addr.x_port == 0) ipx_dst->sipx_addr.x_port = htons(IPXPORT_SAP); (*afswitch[dst->sa_family].af_output) (sapsock, flags, &t_dst, sizeof (struct sap_packet) + sizeof(u_short)); TRACE_SAP_OUTPUT(ifp, &t_dst, sizeof (struct sap_packet) + sizeof(u_short)); } /* * Supply dst with the contents of the SAP tables. If the ServType == * SAP_WILDCARD (0xFFFF) supply the whole table, otherwise only the * services that are of ServType. If this won't fit in one packet, chop * it up into several. * * This must be done using the split horizon algorithm. * 1. Don't send SAP info to the interface from where it was received. * 2. If a service is received from more than one interface and the cost is * the same, don't publish it on either interface. I am calling this * clones. */ void -sap_supply(dst, flags, ifp, ServType) +sap_supply(dst, flags, ifp, ServType, changesonly) struct sockaddr *dst; int flags; struct interface *ifp; int ServType; + int changesonly; { register struct sap_entry *sap; register struct sap_entry *csap; /* Clone route */ register struct sap_hash *sh; register struct sap_info *n = sap_msg->sap; struct sap_hash *base = sap_head; struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) dst; af_output_t *output = afswitch[dst->sa_family].af_output; int size, metric; int delay = 0; if (sipx->sipx_port == 0) sipx->sipx_port = htons(IPXPORT_SAP); sap_msg->sap_cmd = ntohs(SAP_RESP); for (sh = base; sh < &base[SAPHASHSIZ]; sh++) for (sap = sh->forw; sap != (struct sap_entry *)sh; sap = sap->forw) { size = (char *)n - (char *)sap_msg; if (size >= ((MAXSAPENTRIES * sizeof (struct sap_info)) + sizeof (sap_msg->sap_cmd))) { (*output)(sapsock, flags, dst, size); TRACE_SAP_OUTPUT(ifp, dst, size); n = sap_msg->sap; delay++; if(delay == 2) { - usleep(20000); + usleep(50000); delay = 0; } } + if (changesonly && !(sap->state & RTS_CHANGED)) + continue; + /* * Check for the servicetype except if the ServType is * a wildcard (0xFFFF). */ if ((ServType != SAP_WILDCARD) && (ServType != sap->sap.ServType)) continue; /* * This should do rule one and two of the split horizon * algorithm. */ if (sap->ifp == ifp) continue; /* * Rule 2. * Look if we have clones (different routes to the same * place with exactly the same cost). * * We should not publish on any of the clone interfaces. */ csap = sap->clone; while (csap) { if (csap->ifp == ifp) goto next; csap = csap->clone; } /* * Don't advertise services with more than 15 hops. It * will be confused with a service that has gone down. */ if (ntohs(sap->sap.hops) == (HOPCNT_INFINITY - 1)) continue; metric = min(ntohs(sap->sap.hops) + 1, HOPCNT_INFINITY); *n = sap->sap; n->hops = htons(metric); n++; next: } if (n != sap_msg->sap) { size = (char *)n - (char *)sap_msg; (*output)(sapsock, flags, dst, size); TRACE_SAP_OUTPUT(ifp, dst, size); } } diff --git a/usr.sbin/IPXrouted/sap_tables.c b/usr.sbin/IPXrouted/sap_tables.c index 1e33dd46fbb9..863943b6c4f3 100644 --- a/usr.sbin/IPXrouted/sap_tables.c +++ b/usr.sbin/IPXrouted/sap_tables.c @@ -1,323 +1,335 @@ /* * Copyright (c) 1995 John Hay. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by John Hay. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY John Hay AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL John Hay OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: sap_tables.c,v 1.3 1997/02/22 16:01:01 peter Exp $ + * $Id: sap_tables.c,v 1.4 1997/07/01 00:33:41 bde Exp $ */ #include "defs.h" #include #include #define FIXLEN(s) { if ((s)->sa_len == 0) (s)->sa_len = sizeof (*(s));} sap_hash sap_head[SAPHASHSIZ]; void sapinit(void) { int i; for (i=0; i> 8); + + for (i=0;i<14;i++) { + hsh = hsh * SMVAL + *ServName++; ServName++; } - hsh = rol(hsh) + (ServType >> 8); - hsh = rol(hsh) + (ServType & 0xff); - hsh = (hsh >> 7) ^ hsh; +#undef SMVAL + return hsh; } /* * Look for an exact match on ServType and ServName. It is * mostly used by the function that process SAP RESPONSE packets. * * A hash is created and used to index into the hash table. Then * that list is walk through searching for a match. * * If no match is found NULL is returned. */ struct sap_entry * sap_lookup(u_short ServType, char *ServName) { register struct sap_entry *sap; register struct sap_hash *sh; int hsh; hsh = saphash(ServType, ServName); sh = &sap_head[hsh & SAPHASHMASK]; for(sap = sh->forw; sap != (sap_entry *)sh; sap = sap->forw) { if ((hsh == sap->hash) && (ServType == sap->sap.ServType) && (strncmp(ServName, sap->sap.ServName, SERVNAMELEN) == 0)) { return sap; } } return NULL; } /* * This returns the nearest service of the specified type. If no * suitable service is found or if that service is on the interface * where the request came from, NULL is returned. * * When checking interfaces clones must be considered also. * * XXX TODO: * Maybe we can use RIP tables to get the fastest service (ticks). */ struct sap_entry * sap_nearestserver(ushort ServType, struct interface *ifp) { register struct sap_entry *sap; register struct sap_entry *csap; struct sap_hash *sh; register struct sap_entry *best = NULL; register int besthops = HOPCNT_INFINITY; sh = sap_head; for (; sh < &sap_head[SAPHASHSIZ]; sh++) for(sap = sh->forw; sap != (sap_entry *)sh; sap = sap->forw) { if (ServType != sap->sap.ServType) continue; if (ifp == sap->ifp) continue; csap = sap->clone; while (csap) { if (ifp == csap->ifp) /* * I would have loved to use * something else here. */ goto next; csap = csap->clone; } if (ntohs(sap->sap.hops) < besthops) { best = sap; besthops = ntohs(best->sap.hops); } next:; } return best; } /* * Add a entry to the SAP table. * * If the malloc fail, the entry will silently be thrown away. */ void sap_add(struct sap_info *si, struct sockaddr *from) { register struct sap_entry *nsap; register struct sap_hash *sh; + if (ntohs(si->hops) == HOPCNT_INFINITY) + return; + FIXLEN(from); nsap = malloc(sizeof(struct sap_entry)); if (nsap == NULL) return; nsap->sap = *si; nsap->source = *from; nsap->clone = NULL; nsap->ifp = if_ifwithnet(from); nsap->state = RTS_CHANGED; nsap->timer = 0; nsap->hash = saphash(si->ServType, si->ServName); sh = &sap_head[nsap->hash & SAPHASHMASK]; insque(nsap, sh); + TRACE_SAP_ACTION("ADD", nsap); } /* * Change an existing SAP entry. If a clone exist for the old one, * check if it is cheaper. If it is change tothe clone, otherwise * delete all the clones. */ void sap_change(struct sap_entry *sap, struct sap_info *si, struct sockaddr *from) { struct sap_entry *osap = NULL; FIXLEN(from); + TRACE_SAP_ACTION("CHANGE FROM", sap); /* * If the hopcount (metric) is HOPCNT_INFINITY (16) it means that * a service has gone down. We should keep it like that for 30 * seconds, so that it will get broadcast and then change to a * clone if one exist. */ if (sap->clone && (ntohs(si->hops) != HOPCNT_INFINITY)) { /* * There are three possibilities: * 1. The new path is cheaper than the old one. * Free all the clones. * * 2. The new path is the same cost as the old ones. * If it is on the list of clones remove it * from the clone list and free it. * * 3. The new path is more expensive than the old one. * Use the values of the first clone and take it * out of the list, to be freed at the end. */ osap = sap->clone; if (ntohs(osap->sap.hops) > ntohs(si->hops)) { struct sap_entry *nsap; while (osap) { nsap = osap->clone; + TRACE_SAP_ACTION("DELETE", osap); free(osap); osap = nsap; } sap->clone = NULL; } else if (ntohs(osap->sap.hops) == ntohs(si->hops)) { struct sap_entry *psap; psap = sap; while (osap) { if (equal(&osap->source, from)) { psap->clone = osap->clone; + TRACE_SAP_ACTION("DELETE", osap); free(osap); osap = psap->clone; } else { psap = osap; osap = osap->clone; } } } else { from = &osap->source; si = &osap->sap; sap->clone = osap->clone; } } sap->sap = *si; sap->source = *from; sap->ifp = if_ifwithnet(from); sap->state = RTS_CHANGED; if (ntohs(si->hops) == HOPCNT_INFINITY) sap->timer = EXPIRE_TIME; else sap->timer = 0; - if (osap) + if (osap) { + TRACE_SAP_ACTION("DELETE", osap); free(osap); + } + TRACE_SAP_ACTION("CHANGE TO", sap); } /* * Add a clone to the specified SAP entry. A clone is a different * route to the same service. We must know about them when we use * the split horizon algorithm. * * If the malloc fail, the entry will silently be thrown away. */ void sap_add_clone(struct sap_entry *sap, struct sap_info *clone, struct sockaddr *from) { register struct sap_entry *nsap; register struct sap_entry *csap; + if (ntohs(clone->hops) == HOPCNT_INFINITY) + return; + FIXLEN(from); nsap = malloc(sizeof(struct sap_entry)); if (nsap == NULL) return; if (ftrace) fprintf(ftrace, "CLONE ADD %04.4X %s.\n", ntohs(clone->ServType), clone->ServName); nsap->sap = *clone; nsap->source = *from; nsap->clone = NULL; nsap->ifp = if_ifwithnet(from); nsap->state = RTS_CHANGED; nsap->timer = 0; nsap->hash = saphash(clone->ServType, clone->ServName); csap = sap; while (csap->clone) csap = csap->clone; csap->clone = nsap; + TRACE_SAP_ACTION("ADD CLONE", nsap); } /* * Remove a SAP entry from the table and free the memory * used by it. * * If the service have clone, do a sap_change to it and free * the clone. */ void sap_delete(struct sap_entry *sap) { if (sap->clone) { sap_change(sap, &sap->clone->sap, &sap->clone->source); return; } remque(sap); + TRACE_SAP_ACTION("DELETE", sap); free(sap); } diff --git a/usr.sbin/IPXrouted/table.h b/usr.sbin/IPXrouted/table.h index 8debdcdc5224..dbfdfe5c3de8 100644 --- a/usr.sbin/IPXrouted/table.h +++ b/usr.sbin/IPXrouted/table.h @@ -1,116 +1,115 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1995 John Hay. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)table.h 5.1 (Berkeley) 6/4/85 (routed/table.h) * * @(#)table.h 8.1 (Berkeley) 6/5/93 * - * $Id$ + * $Id: table.h,v 1.4 1997/02/22 16:01:02 peter Exp $ */ /* * Routing table management daemon. */ /* * Routing table structure; differs a bit from kernel tables. * * Note: the union below must agree in the first 4 members * so the ioctl's will work. */ struct rthash { struct rt_entry *rt_forw; struct rt_entry *rt_back; }; #ifdef RTM_ADD #define rtentry ortentry #endif struct rt_entry { struct rt_entry *rt_forw; struct rt_entry *rt_back; union { struct rtentry rtu_rt; struct rtuentry { u_long rtu_hash; struct sockaddr rtu_dst; struct sockaddr rtu_router; short rtu_rtflags; /* used by old rtioctl */ short rtu_wasted; /* XXX routed does it this way. */ int rtu_flags; int rtu_state; int rtu_timer; int rtu_metric; int rtu_ticks; struct interface *rtu_ifp; } rtu_entry; } rt_rtu; struct rt_entry *rt_clone; }; #define rt_rt rt_rtu.rtu_entry /* pass to ioctl */ #define rt_hash rt_rtu.rtu_entry.rtu_hash /* for net or host */ #define rt_dst rt_rtu.rtu_entry.rtu_dst /* match value */ #define rt_router rt_rtu.rtu_entry.rtu_router /* who to forward to */ #define rt_flags rt_rtu.rtu_entry.rtu_flags /* kernel flags */ #define rt_timer rt_rtu.rtu_entry.rtu_timer /* for invalidation */ #define rt_state rt_rtu.rtu_entry.rtu_state /* see below */ #define rt_metric rt_rtu.rtu_entry.rtu_metric /* cost of route */ #define rt_ticks rt_rtu.rtu_entry.rtu_ticks /* time of route */ #define rt_ifp rt_rtu.rtu_entry.rtu_ifp /* interface to take */ -#define ROUTEHASHSIZ 32 /* must be a power of 2 */ +#define ROUTEHASHSIZ 128 /* must be a power of 2 */ #define ROUTEHASHMASK (ROUTEHASHSIZ - 1) /* * "State" of routing table entry. */ #define RTS_CHANGED 0x1 /* route has been altered recently */ #define RTS_PASSIVE IFF_PASSIVE /* don't time out route */ #define RTS_INTERFACE IFF_INTERFACE /* route is for network interface */ #define RTS_REMOTE IFF_REMOTE /* route is for ``remote'' entity */ extern struct rthash nethash[ROUTEHASHSIZ]; -extern struct rthash hosthash[ROUTEHASHSIZ]; struct rt_entry *rtlookup(struct sockaddr *); struct rt_entry *rtfind(struct sockaddr *); void rtadd(struct sockaddr *, struct sockaddr *, short, short, int); void rtadd_clone(struct rt_entry *, struct sockaddr *, struct sockaddr *, short, short, int); void rtchange(struct rt_entry *, struct sockaddr *, short, short); void rtdelete(struct rt_entry *); int rtioctl(int, struct rtuentry *); void rtinit(void); diff --git a/usr.sbin/IPXrouted/tables.c b/usr.sbin/IPXrouted/tables.c index 17b266080a79..9fe7f456f683 100644 --- a/usr.sbin/IPXrouted/tables.c +++ b/usr.sbin/IPXrouted/tables.c @@ -1,467 +1,434 @@ /* * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1995 John Hay. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: tables.c,v 1.4 1997/02/22 16:01:03 peter Exp $ + * $Id: tables.c,v 1.5 1997/07/01 00:33:42 bde Exp $ */ #ifndef lint static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 6/5/93"; #endif /* not lint */ /* * Routing Table Management Daemon */ #include "defs.h" #include #include #include #include #ifndef DEBUG #define DEBUG 0 #endif #define FIXLEN(s) { if ((s)->sa_len == 0) (s)->sa_len = sizeof (*(s));} int install = !DEBUG; /* if 1 call kernel */ int delete = 1; struct rthash nethash[ROUTEHASHSIZ]; -struct rthash hosthash[ROUTEHASHSIZ]; /* * Lookup dst in the tables for an exact match. */ struct rt_entry * rtlookup(dst) struct sockaddr *dst; { register struct rt_entry *rt; register struct rthash *rh; register u_int hash; struct afhash h; - int doinghost = 1; if (dst->sa_family >= AF_MAX) return (0); (*afswitch[dst->sa_family].af_hash)(dst, &h); - hash = h.afh_hosthash; - rh = &hosthash[hash & ROUTEHASHMASK]; -again: + hash = h.afh_nethash; + rh = &nethash[hash & ROUTEHASHMASK]; for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { if (rt->rt_hash != hash) continue; if (equal(&rt->rt_dst, dst)) return (rt); } - if (doinghost) { - doinghost = 0; - hash = h.afh_nethash; - rh = &nethash[hash & ROUTEHASHMASK]; - goto again; - } return (0); } /* * Find a route to dst as the kernel would. */ struct rt_entry * rtfind(dst) struct sockaddr *dst; { register struct rt_entry *rt; register struct rthash *rh; register u_int hash; struct afhash h; int af = dst->sa_family; - int doinghost = 1, (*match)() = 0; + int (*match)() = 0; if (af >= AF_MAX) return (0); (*afswitch[af].af_hash)(dst, &h); - hash = h.afh_hosthash; - rh = &hosthash[hash & ROUTEHASHMASK]; -again: + hash = h.afh_nethash; + rh = &nethash[hash & ROUTEHASHMASK]; + match = afswitch[af].af_netmatch; for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { if (rt->rt_hash != hash) continue; - if (doinghost) { - if (equal(&rt->rt_dst, dst)) - return (rt); - } else { - if (rt->rt_dst.sa_family == af && - (match != 0) && - (*match)(&rt->rt_dst, dst)) - return (rt); - } - } - if (doinghost) { - doinghost = 0; - hash = h.afh_nethash; - rh = &nethash[hash & ROUTEHASHMASK]; - match = afswitch[af].af_netmatch; - goto again; + if (rt->rt_dst.sa_family == af && + (*match)(&rt->rt_dst, dst)) + return (rt); } return (0); } void rtadd(dst, gate, metric, ticks, state) struct sockaddr *dst, *gate; short metric, ticks; int state; { struct afhash h; register struct rt_entry *rt; struct rthash *rh; int af = dst->sa_family, flags; u_int hash; FIXLEN(dst); FIXLEN(gate); if (af >= AF_MAX) return; (*afswitch[af].af_hash)(dst, &h); flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0; - if (flags & RTF_HOST) { - hash = h.afh_hosthash; - rh = &hosthash[hash & ROUTEHASHMASK]; - } else { - hash = h.afh_nethash; - rh = &nethash[hash & ROUTEHASHMASK]; - } + hash = h.afh_nethash; + rh = &nethash[hash & ROUTEHASHMASK]; rt = (struct rt_entry *)malloc(sizeof (*rt)); if (rt == 0) return; rt->rt_hash = hash; rt->rt_dst = *dst; rt->rt_router = *gate; rt->rt_metric = metric; rt->rt_ticks = ticks; rt->rt_timer = 0; rt->rt_flags = RTF_UP | flags; rt->rt_state = state | RTS_CHANGED; rt->rt_ifp = if_ifwithnet(&rt->rt_router); rt->rt_clone = NULL; if (metric) rt->rt_flags |= RTF_GATEWAY; insque(rt, rh); - TRACE_ACTION(ADD, rt); + TRACE_ACTION("ADD", rt); /* * If the ioctl fails because the gateway is unreachable * from this host, discard the entry. This should only * occur because of an incorrect entry in /etc/gateways. */ if (install && rtioctl(ADD, &rt->rt_rt) < 0) { if (errno != EEXIST) perror("SIOCADDRT"); if (errno == ENETUNREACH) { - TRACE_ACTION(DELETE, rt); + TRACE_ACTION("DELETE", rt); remque(rt); free((char *)rt); } } } void rtadd_clone(ort, dst, gate, metric, ticks, state) struct rt_entry *ort; struct sockaddr *dst, *gate; short metric, ticks; int state; { struct afhash h; register struct rt_entry *rt; struct rthash *rh; int af = dst->sa_family, flags; u_int hash; FIXLEN(dst); FIXLEN(gate); if (af >= AF_MAX) return; (*afswitch[af].af_hash)(dst, &h); flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0; - if (flags & RTF_HOST) { - hash = h.afh_hosthash; - rh = &hosthash[hash & ROUTEHASHMASK]; - } else { - hash = h.afh_nethash; - rh = &nethash[hash & ROUTEHASHMASK]; - } + hash = h.afh_nethash; + rh = &nethash[hash & ROUTEHASHMASK]; rt = (struct rt_entry *)malloc(sizeof (*rt)); if (rt == 0) return; rt->rt_hash = hash; rt->rt_dst = *dst; rt->rt_router = *gate; rt->rt_metric = metric; rt->rt_ticks = ticks; rt->rt_timer = 0; rt->rt_flags = RTF_UP | flags; rt->rt_state = state | RTS_CHANGED; rt->rt_ifp = if_ifwithnet(&rt->rt_router); rt->rt_clone = NULL; rt->rt_forw = NULL; rt->rt_back = NULL; if (metric) rt->rt_flags |= RTF_GATEWAY; while(ort->rt_clone != NULL) ort = ort->rt_clone; ort->rt_clone = rt; - TRACE_ACTION(ADD_CLONE, rt); + TRACE_ACTION("ADD_CLONE", rt); } void rtchange(rt, gate, metric, ticks) struct rt_entry *rt; struct sockaddr *gate; short metric, ticks; { int doioctl = 0, metricchanged = 0; struct rtuentry oldroute; FIXLEN(gate); /* * Handling of clones. * When the route changed and it had clones, handle it special. * 1. If the new route is cheaper than the clone(s), free the clones. * 2. If the new route is the same cost, it may be one of the clones, * search for it and free it. * 3. If the new route is more expensive than the clone(s), use the * values of the clone(s). */ if (rt->rt_clone) { if ((ticks < rt->rt_clone->rt_ticks) || ((ticks == rt->rt_clone->rt_ticks) && (metric < rt->rt_clone->rt_metric))) { /* * Free all clones. */ struct rt_entry *trt, *nrt; trt = rt->rt_clone; rt->rt_clone = NULL; while(trt) { nrt = trt->rt_clone; free((char *)trt); trt = nrt; } } else if ((ticks == rt->rt_clone->rt_ticks) && (metric == rt->rt_clone->rt_metric)) { struct rt_entry *prt, *trt; prt = rt; trt = rt->rt_clone; while(trt) { if (equal(&trt->rt_router, gate)) { prt->rt_clone = trt->rt_clone; free(trt); trt = prt->rt_clone; } else { prt = trt; trt = trt->rt_clone; } } } else { /* * Use the values of the first clone. * Delete the corresponding clone. */ struct rt_entry *trt; trt = rt->rt_clone; rt->rt_clone = rt->rt_clone->rt_clone; metric = trt->rt_metric; ticks = trt->rt_ticks; *gate = trt->rt_router; free((char *)trt); } } if (!equal(&rt->rt_router, gate)) doioctl++; if ((metric != rt->rt_metric) || (ticks != rt->rt_ticks)) metricchanged++; if (doioctl || metricchanged) { - TRACE_ACTION(CHANGE FROM, rt); + TRACE_ACTION("CHANGE FROM", rt); if (doioctl) { oldroute = rt->rt_rt; rt->rt_router = *gate; } rt->rt_metric = metric; rt->rt_ticks = ticks; if ((rt->rt_state & RTS_INTERFACE) && metric) { rt->rt_state &= ~RTS_INTERFACE; if(rt->rt_ifp) syslog(LOG_ERR, "changing route from interface %s (timed out)", rt->rt_ifp->int_name); else syslog(LOG_ERR, "changing route from interface ??? (timed out)"); } if (metric) rt->rt_flags |= RTF_GATEWAY; else rt->rt_flags &= ~RTF_GATEWAY; + rt->rt_ifp = if_ifwithnet(&rt->rt_router); rt->rt_state |= RTS_CHANGED; - TRACE_ACTION(CHANGE TO, rt); + TRACE_ACTION("CHANGE TO", rt); } if (doioctl && install) { #ifndef RTM_ADD if (rtioctl(ADD, &rt->rt_rt) < 0) syslog(LOG_ERR, "rtioctl ADD dst %s, gw %s: %m", - xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr), - xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr)); + ipx_ntoa(&((struct sockaddr_ipx *)&rt->rt_dst)->sipx_addr), + ipx_ntoa(&((struct sockaddr_ipx *)&rt->rt_router)->sipx_addr)); if (delete && rtioctl(DELETE, &oldroute) < 0) perror("rtioctl DELETE"); #else if (delete == 0) { if (rtioctl(ADD, &rt->rt_rt) >= 0) return; } else { if (rtioctl(CHANGE, &rt->rt_rt) >= 0) return; } syslog(LOG_ERR, "rtioctl ADD dst %s, gw %s: %m", ipxdp_ntoa(&((struct sockaddr_ipx *)&rt->rt_dst)->sipx_addr), ipxdp_ntoa(&((struct sockaddr_ipx *)&rt->rt_router)->sipx_addr)); #endif } } void rtdelete(rt) struct rt_entry *rt; { struct sockaddr *sa = &(rt->rt_router); FIXLEN(sa); sa = &(rt->rt_dst); FIXLEN(sa); if (rt->rt_clone) { /* * If there is a clone we just do a rt_change to it. */ struct rt_entry *trt = rt->rt_clone; rtchange(rt, &trt->rt_router, trt->rt_metric, trt->rt_ticks); return; } if (rt->rt_state & RTS_INTERFACE) { if (rt->rt_ifp) syslog(LOG_ERR, "deleting route to interface %s (timed out)", rt->rt_ifp->int_name); else syslog(LOG_ERR, "deleting route to interface ??? (timed out)"); } - TRACE_ACTION(DELETE, rt); + TRACE_ACTION("DELETE", rt); if (install && rtioctl(DELETE, &rt->rt_rt) < 0) perror("rtioctl DELETE"); remque(rt); free((char *)rt); } void rtinit(void) { register struct rthash *rh; for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; - for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++) - rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; } int seqno; int rtioctl(action, ort) int action; struct rtuentry *ort; { #ifndef RTM_ADD if (install == 0) return (errno = 0); ort->rtu_rtflags = ort->rtu_flags; switch (action) { case ADD: return (ioctl(s, SIOCADDRT, (char *)ort)); case DELETE: return (ioctl(s, SIOCDELRT, (char *)ort)); default: return (-1); } #else /* RTM_ADD */ struct { struct rt_msghdr w_rtm; struct sockaddr w_dst; struct sockaddr w_gate; struct sockaddr_ipx w_netmask; } w; #define rtm w.w_rtm bzero((char *)&w, sizeof(w)); rtm.rtm_msglen = sizeof(w); rtm.rtm_version = RTM_VERSION; rtm.rtm_type = (action == ADD ? RTM_ADD : (action == DELETE ? RTM_DELETE : RTM_CHANGE)); rtm.rtm_flags = ort->rtu_flags; rtm.rtm_seq = ++seqno; rtm.rtm_addrs = RTA_DST|RTA_GATEWAY; bcopy((char *)&ort->rtu_dst, (char *)&w.w_dst, sizeof(w.w_dst)); bcopy((char *)&ort->rtu_router, (char *)&w.w_gate, sizeof(w.w_gate)); w.w_gate.sa_family = w.w_dst.sa_family = AF_IPX; w.w_gate.sa_len = w.w_dst.sa_len = sizeof(w.w_dst); if (rtm.rtm_flags & RTF_HOST) { rtm.rtm_msglen -= sizeof(w.w_netmask); } else { rtm.rtm_addrs |= RTA_NETMASK; w.w_netmask = ipx_netmask; rtm.rtm_msglen -= sizeof(w.w_netmask) - ipx_netmask.sipx_len; } errno = 0; return write(r, (char *)&w, rtm.rtm_msglen); #endif /* RTM_ADD */ } diff --git a/usr.sbin/IPXrouted/timer.c b/usr.sbin/IPXrouted/timer.c index d6b064e7e168..ea75a98d3628 100644 --- a/usr.sbin/IPXrouted/timer.c +++ b/usr.sbin/IPXrouted/timer.c @@ -1,234 +1,239 @@ /* * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1995 John Hay. All rights reserved. * * This file includes significant work done at Cornell University by * Bill Nesheim. That work included by permission. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: timer.c,v 1.3 1997/02/22 16:01:03 peter Exp $ */ #ifndef lint static char sccsid[] = "@(#)timer.c 8.1 (Berkeley) 6/5/93"; #endif /* not lint */ /* * Routing Table Management Daemon */ #include "defs.h" #include #include int timeval = -TIMER_RATE; /* * Timer routine. Performs routing information supply * duties and manages timers on routing and SAP table entries. */ void timer() { register struct rthash *rh; register struct rt_entry *rt; - struct rthash *base = hosthash; register struct sap_hash *sh; register struct sap_entry *sap; struct sap_hash *sap_base = sap_head; - int doinghost = 1, timetobroadcast, ripbroadcast, sapbroadcast; + int timetobroadcast, ripbroadcast, sapbroadcast; timeval += TIMER_RATE; if (lookforinterfaces && (timeval % CHECK_INTERVAL) == 0) ifinit(); timetobroadcast = supplier && (timeval % SUPPLY_INTERVAL) == 0; ripbroadcast = supplier && timetobroadcast && (timeval % RIP_INTERVAL) == 0; sapbroadcast = timetobroadcast && dosap && !ripbroadcast; -again: - for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) { + for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) { rt = rh->rt_forw; for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { if (rt->rt_clone) { struct rt_entry *trt, *prt; /* * If a clone expire free it and mark the * main route RTS_CHANGED. */ prt = rt; trt = rt->rt_clone; while (trt) { trt->rt_timer += TIMER_RATE; if (trt->rt_timer >= EXPIRE_TIME) { prt->rt_clone = trt->rt_clone; free((char *)trt); trt = prt->rt_clone; rt->rt_state |= RTS_CHANGED; } else { prt = trt; trt = prt->rt_clone; } } } /* * We don't advance time on a routing entry for * a passive gateway or that for our only interface. * The latter is excused because we don't act as * a routing information supplier and hence would * time it out. This is fair as if it's down * we're cut off from the world anyway and it's * not likely we'll grow any new hardware in * the mean time. */ if (!(rt->rt_state & RTS_PASSIVE) && !(rt->rt_state & RTS_INTERFACE)) rt->rt_timer += TIMER_RATE; - if (rt->rt_timer >= EXPIRE_TIME) + if (rt->rt_timer >= EXPIRE_TIME) { rt->rt_metric = HOPCNT_INFINITY; + rt->rt_state |= RTS_CHANGED; + } if (rt->rt_timer >= GARBAGE_TIME) { rt = rt->rt_back; /* Perhaps we should send a REQUEST for this route? */ rtdelete(rt->rt_forw); continue; } if (rt->rt_state & RTS_CHANGED) { rt->rt_state &= ~RTS_CHANGED; /* don't send extraneous packets */ if (!supplier || ripbroadcast) continue; + if ((rt->rt_metric + 1) == HOPCNT_INFINITY) + continue; msg->rip_cmd = htons(RIPCMD_RESPONSE); msg->rip_nets[0].rip_dst = (satoipx_addr(rt->rt_dst)).x_net; msg->rip_nets[0].rip_metric = htons(min(rt->rt_metric+1, HOPCNT_INFINITY)); msg->rip_nets[0].rip_ticks = htons(rt->rt_ticks + 1); - toall(sndmsg, rt); + toall(sndmsg, rt, 0); } } } - if (doinghost) { - doinghost = 0; - base = nethash; - goto again; - } if (ripbroadcast) - toall(supply, NULL); + toall(supply, NULL, 0); /* * Now do the SAP stuff. */ for (sh = sap_base; sh < &sap_base[SAPHASHSIZ]; sh++) { sap = sh->forw; for (; sap != (struct sap_entry *)sh; sap = sap->forw) { if (sap->clone) { struct sap_entry *tsap, *psap; /* * If a clone expire free it and mark the * main sap entry RTS_CHANGED. */ psap = sap; tsap = sap->clone; while (tsap) { tsap->timer += TIMER_RATE; if (tsap->timer >= EXPIRE_TIME) { psap->clone = tsap->clone; free((char *)tsap); tsap = psap->clone; sap->state |= RTS_CHANGED; } else { psap = tsap; tsap = psap->clone; } } } sap->timer += TIMER_RATE; - if (sap->timer >= EXPIRE_TIME) - sap->metric = HOPCNT_INFINITY; + if (sap->timer >= EXPIRE_TIME) { + sap->sap.hops = htons(HOPCNT_INFINITY); + sap->state |= RTS_CHANGED; + } if (sap->timer >= GARBAGE_TIME) { sap = sap->back; /* Perhaps we should send a REQUEST for this route? */ sap_delete(sap->forw); continue; } /* * XXX sap_sndmsg on RTS_CHANGED */ + if (sap->state & RTS_CHANGED) { + sap->state &= ~RTS_CHANGED; +#ifdef notyet + /* don't send extraneous packets */ + if (!supplier || sapbroadcast) + continue; + if ((ntohs(sap->sap.hops) + 1) == HOPCNT_INFINITY) + continue; + sap_msg->sap_cmd = htons(SAP_RESP); + sap_msg->sap[0] = sap->sap; + sap_msg->sap[0].hops = + htons(min(sap->sap.hops+1, HOPCNT_INFINITY)); + toall(sapsndmsg, rt, 0); +#endif + } } } if (sapbroadcast) - sap_supply_toall(); + sap_supply_toall(0); if (ftrace && sapbroadcast) dumpsaptable(ftrace, sap_head); - alarm(TIMER_RATE); } /* * On hangup, let everyone know we're going away. */ void hup() { register struct rthash *rh; register struct rt_entry *rt; - struct rthash *base = hosthash; register struct sap_hash *sh; register struct sap_entry *sap; - int doinghost = 1; if (supplier) { -again: - for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) { + for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) { rt = rh->rt_forw; for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) rt->rt_metric = HOPCNT_INFINITY; } - if (doinghost) { - doinghost = 0; - base = nethash; - goto again; - } - toall(supply, NULL); + toall(supply, NULL, 0); /* * Now for SAP. */ for (sh = sap_head; sh < &sap_head[SAPHASHSIZ]; sh++) { sap = sh->forw; for (; sap != (struct sap_entry *)sh; sap = sap->forw) sap->sap.hops = htons(HOPCNT_INFINITY); } if (dosap) - sap_supply_toall(); + sap_supply_toall(0); } exit(1); } diff --git a/usr.sbin/IPXrouted/trace.c b/usr.sbin/IPXrouted/trace.c index 3b76d2ca375c..a4c5df95342b 100644 --- a/usr.sbin/IPXrouted/trace.c +++ b/usr.sbin/IPXrouted/trace.c @@ -1,438 +1,519 @@ /* * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1995 John Hay. All rights reserved. * * This file includes significant work done at Cornell University by * Bill Nesheim. That work included by permission. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: trace.c,v 1.4 1997/02/22 16:01:04 peter Exp $ */ #ifndef lint static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93"; #endif /* not lint */ /* * Routing Table Management Daemon */ #define RIPCMDS #define SAPCMDS #include #include #include #include #include "defs.h" #define NRECORDS 50 /* size of circular trace buffer */ #ifdef DEBUG FILE *ftrace = stdout; int tracing = 1; #else DEBUG FILE *ftrace = NULL; int tracing = 0; #endif void dumpif(FILE *fd, struct interface *ifp); void dumptrace(FILE *fd, char *dir, struct ifdebug *ifd); void traceinit(ifp) register struct interface *ifp; { static int iftraceinit(); if (iftraceinit(ifp, &ifp->int_input) && iftraceinit(ifp, &ifp->int_output)) return; tracing = 0; syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name); } static int iftraceinit(ifp, ifd) struct interface *ifp; register struct ifdebug *ifd; { register struct iftrace *t; ifd->ifd_records = (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); if (ifd->ifd_records == 0) return (0); ifd->ifd_front = ifd->ifd_records; ifd->ifd_count = 0; for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { t->ift_size = 0; t->ift_packet = 0; } ifd->ifd_if = ifp; return (1); } void traceon(file) char *file; { if (ftrace != NULL) return; ftrace = fopen(file, "a"); if (ftrace == NULL) return; dup2(fileno(ftrace), 1); dup2(fileno(ftrace), 2); tracing = 1; } void traceoff(void) { if (!tracing) return; if (ftrace != NULL) fclose(ftrace); ftrace = NULL; tracing = 0; } void trace(ifd, who, p, len, m) register struct ifdebug *ifd; struct sockaddr *who; char *p; int len, m; { register struct iftrace *t; if (ifd->ifd_records == 0) return; t = ifd->ifd_front++; if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) ifd->ifd_front = ifd->ifd_records; if (ifd->ifd_count < NRECORDS) ifd->ifd_count++; if (t->ift_size > 0 && t->ift_packet) free(t->ift_packet); t->ift_packet = 0; t->ift_stamp = time(0); t->ift_who = *who; if (len > 0) { t->ift_packet = malloc(len); if (t->ift_packet) bcopy(p, t->ift_packet, len); else len = 0; } t->ift_size = len; t->ift_metric = m; } void traceaction(fd, action, rt) FILE *fd; char *action; struct rt_entry *rt; { struct sockaddr_ipx *dst, *gate; static struct bits { int t_bits; char *t_name; } flagbits[] = { { RTF_UP, "UP" }, { RTF_GATEWAY, "GATEWAY" }, { RTF_HOST, "HOST" }, { 0 } }, statebits[] = { { RTS_PASSIVE, "PASSIVE" }, { RTS_REMOTE, "REMOTE" }, { RTS_INTERFACE,"INTERFACE" }, { RTS_CHANGED, "CHANGED" }, { 0 } }; register struct bits *p; register int first; char *cp; if (fd == NULL) return; fprintf(fd, "%s ", action); dst = (struct sockaddr_ipx *)&rt->rt_dst; gate = (struct sockaddr_ipx *)&rt->rt_router; fprintf(fd, "dst %s, ", ipxdp_ntoa(&dst->sipx_addr)); fprintf(fd, "router %s, metric %d, ticks %d, flags", ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks); cp = " %s"; for (first = 1, p = flagbits; p->t_bits > 0; p++) { if ((rt->rt_flags & p->t_bits) == 0) continue; fprintf(fd, cp, p->t_name); if (first) { cp = "|%s"; first = 0; } } fprintf(fd, " state"); cp = " %s"; for (first = 1, p = statebits; p->t_bits > 0; p++) { if ((rt->rt_state & p->t_bits) == 0) continue; fprintf(fd, cp, p->t_name); if (first) { cp = "|%s"; first = 0; } } putc('\n', fd); if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) dumpif(fd, rt->rt_ifp); fflush(fd); } +void +traceactionlog(action, rt) + char *action; + struct rt_entry *rt; +{ + struct sockaddr_ipx *dst, *gate; + static struct bits { + int t_bits; + char *t_name; + } flagbits[] = { + { RTF_UP, "UP" }, + { RTF_GATEWAY, "GATEWAY" }, + { RTF_HOST, "HOST" }, + { 0 } + }, statebits[] = { + { RTS_PASSIVE, "PASSIVE" }, + { RTS_REMOTE, "REMOTE" }, + { RTS_INTERFACE,"INTERFACE" }, + { RTS_CHANGED, "CHANGED" }, + { 0 } + }; + register struct bits *p; + register int first; + char *cp; + char *lstr, *olstr; + + dst = (struct sockaddr_ipx *)&rt->rt_dst; + gate = (struct sockaddr_ipx *)&rt->rt_router; + asprintf(&lstr, "%s dst %s,", action, ipxdp_ntoa(&dst->sipx_addr)); + olstr = lstr; + asprintf(&lstr, "%s router %s, metric %d, ticks %d, flags", + olstr, ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks); + free(olstr); + olstr = lstr; + cp = "%s %s"; + for (first = 1, p = flagbits; p->t_bits > 0; p++) { + if ((rt->rt_flags & p->t_bits) == 0) + continue; + asprintf(&lstr, cp, olstr, p->t_name); + free(olstr); + olstr = lstr; + if (first) { + cp = "%s|%s"; + first = 0; + } + } + asprintf(&lstr, "%s state", olstr); + free(olstr); + olstr = lstr; + cp = "%s %s"; + for (first = 1, p = statebits; p->t_bits > 0; p++) { + if ((rt->rt_state & p->t_bits) == 0) + continue; + asprintf(&lstr, cp, olstr, p->t_name); + free(olstr); + olstr = lstr; + if (first) { + cp = "%s|%s"; + first = 0; + } + } + syslog(LOG_DEBUG, lstr); + free(lstr); +} + +void +tracesapactionlog(action, sap) + char *action; + struct sap_entry *sap; +{ + syslog(LOG_DEBUG, "%-12.12s service %04X %-20.20s " + "addr %s.%04X %c metric %d\n", + action, + ntohs(sap->sap.ServType), + sap->sap.ServName, + ipxdp_ntoa(&sap->sap.ipx), + ntohs(sap->sap.ipx.x_port), + (sap->clone ? 'C' : ' '), + ntohs(sap->sap.hops)); +} + void dumpif(fd, ifp) register struct interface *ifp; FILE *fd; { if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { fprintf(fd, "*** Packet history for interface %s ***\n", ifp->int_name); dumptrace(fd, "to", &ifp->int_output); dumptrace(fd, "from", &ifp->int_input); fprintf(fd, "*** end packet history ***\n"); } } void dumptrace(fd, dir, ifd) FILE *fd; char *dir; register struct ifdebug *ifd; { register struct iftrace *t; char *cp = !strcmp(dir, "to") ? "Output" : "Input"; if (ifd->ifd_front == ifd->ifd_records && ifd->ifd_front->ift_size == 0) { fprintf(fd, "%s: no packets.\n", cp); return; } fprintf(fd, "%s trace:\n", cp); t = ifd->ifd_front - ifd->ifd_count; if (t < ifd->ifd_records) t += NRECORDS; for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { if (t >= ifd->ifd_records + NRECORDS) t = ifd->ifd_records; if (t->ift_size == 0) continue; fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp), t->ift_metric); dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size); } } void dumppacket(fd, dir, source, cp, size) FILE *fd; char *dir; struct sockaddr *source; char *cp; register int size; { register struct rip *msg = (struct rip *)cp; register struct netinfo *n; struct sockaddr_ipx *who = (struct sockaddr_ipx *)source; if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX) fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)], dir, ipxdp_ntoa(&who->sipx_addr), ntohs(who->sipx_addr.x_port)); else { fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd), dir, ipxdp_ntoa(&who->sipx_addr), ntohs(who->sipx_addr.x_port)); fprintf(fd, "size=%d cp=%x packet=%x\n", size, (u_int)cp, (u_int)packet); return; } switch (ntohs(msg->rip_cmd)) { case RIPCMD_REQUEST: case RIPCMD_RESPONSE: fprintf(fd, ":\n"); size -= sizeof (u_short); n = msg->rip_nets; for (; size > 0; n++, size -= sizeof (struct netinfo)) { if (size < sizeof (struct netinfo)) break; fprintf(fd, "\tnet %s metric %d ticks %d\n", ipxdp_nettoa(n->rip_dst), ntohs(n->rip_metric), ntohs(n->rip_ticks)); } break; } } void dumpsappacket(fd, dir, source, cp, size) FILE *fd; char *dir; struct sockaddr *source; char *cp; register int size; { register struct sap_packet *msg = (struct sap_packet *)cp; register struct sap_info *n; struct sockaddr_ipx *who = (struct sockaddr_ipx *)source; if (msg->sap_cmd && ntohs(msg->sap_cmd) < SAPCMD_MAX) fprintf(fd, "%s %s %s#%x", sapcmds[ntohs(msg->sap_cmd)], dir, ipxdp_ntoa(&who->sipx_addr), ntohs(who->sipx_addr.x_port)); else { fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->sap_cmd), dir, ipxdp_ntoa(&who->sipx_addr), ntohs(who->sipx_addr.x_port)); fprintf(fd, "size=%d cp=%x packet=%x\n", size, (u_int)cp, (u_int)packet); return; } switch (ntohs(msg->sap_cmd)) { case SAP_REQ: case SAP_RESP: case SAP_REQ_NEAR: case SAP_RESP_NEAR: fprintf(fd, ":\n"); size -= sizeof (u_short); n = msg->sap; for (; size > 0; n++, size -= sizeof (struct sap_info)) { if (size < sizeof (struct sap_info)) break; fprintf(fd, " service %04X %-20.20s " "addr %s.%04X metric %d\n", ntohs(n->ServType), n->ServName, ipxdp_ntoa(&n->ipx), ntohs(n->ipx.x_port), ntohs(n->hops)); } break; } } void dumpsaptable(fd, sh) FILE *fd; struct sap_hash *sh; { register struct sap_entry *sap; struct sap_hash *hash; int x = 0; fprintf(fd, "------- SAP table dump. -------\n"); for (hash = sh; hash < &sh[SAPHASHSIZ]; hash++, x++) { fprintf(fd, "HASH %d\n", x); sap = hash->forw; for (; sap != (struct sap_entry *)hash; sap = sap->forw) { fprintf(fd, " service %04X %-20.20s " "addr %s.%04X %c metric %d\n", ntohs(sap->sap.ServType), sap->sap.ServName, ipxdp_ntoa(&sap->sap.ipx), ntohs(sap->sap.ipx.x_port), (sap->clone ? 'C' : ' '), ntohs(sap->sap.hops)); } } fprintf(fd, "\n"); } void dumpriptable(fd) FILE *fd; { register struct rt_entry *rip; struct rthash *hash; int x; struct rthash *rh = nethash; fprintf(fd, "------- RIP table dump. -------\n"); x = 0; fprintf(fd, "Network table.\n"); for (hash = rh; hash < &rh[ROUTEHASHSIZ]; hash++, x++) { fprintf(fd, "HASH %d\n", x); rip = hash->rt_forw; for (; rip != (struct rt_entry *)hash; rip = rip->rt_forw) { fprintf(fd, " dest %s\t", ipxdp_ntoa(&satoipx_addr(rip->rt_dst))); fprintf(fd, "%s metric %d, ticks %d\n", ipxdp_ntoa(&satoipx_addr(rip->rt_router)), rip->rt_metric, rip->rt_ticks); } } fprintf(fd, "\n"); } union ipx_net_u net; char * ipxdp_nettoa(val) union ipx_net val; { static char buf[100]; net.net_e = val; (void)sprintf(buf, "%lx", ntohl(net.long_e)); return (buf); } char * ipxdp_ntoa(addr) struct ipx_addr *addr; { static char buf[100]; (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x", ipxdp_nettoa(addr->x_net), addr->x_host.c_host[0], addr->x_host.c_host[1], addr->x_host.c_host[2], addr->x_host.c_host[3], addr->x_host.c_host[4], addr->x_host.c_host[5]); return(buf); } diff --git a/usr.sbin/IPXrouted/trace.h b/usr.sbin/IPXrouted/trace.h index cbe52d5481b6..17fef0f8774b 100644 --- a/usr.sbin/IPXrouted/trace.h +++ b/usr.sbin/IPXrouted/trace.h @@ -1,132 +1,138 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1995 John Hay. All rights reserved. * * This file includes significant work done at Cornell University by * Bill Nesheim. That work included by permission. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)trace.h 8.1 (Berkeley) 6/5/93 * - * $Id$ + * $Id: trace.h,v 1.5 1997/02/22 16:01:04 peter Exp $ */ /* * IPX Routing Information Protocol. */ /* * Trace record format. */ struct iftrace { time_t ift_stamp; /* time stamp */ struct sockaddr ift_who; /* from/to */ char *ift_packet; /* pointer to packet */ short ift_size; /* size of packet */ short ift_metric; /* metric */ }; /* * Per interface packet tracing buffers. An incoming and * outgoing circular buffer of packets is maintained, per * interface, for debugging. Buffers are dumped whenever * an interface is marked down. */ struct ifdebug { struct iftrace *ifd_records; /* array of trace records */ struct iftrace *ifd_front; /* next empty trace record */ int ifd_count; /* number of unprinted records */ struct interface *ifd_if; /* for locating stuff */ }; /* * Packet tracing stuff. */ int tracepackets; /* watch packets as they go by */ int tracing; /* on/off */ FILE *ftrace; /* output trace file */ #define TRACE_ACTION(action, route) { \ if (tracing) \ traceaction(ftrace, "action", route); \ + traceactionlog(action, route); \ + } +#define TRACE_SAP_ACTION(action, service) { \ + tracesapactionlog(action, service); \ } #define TRACE_INPUT(ifp, src, size) { \ if (tracing) { \ ifp = if_iflookup(src); \ if (ifp) \ trace(&ifp->int_input, src, \ &packet[sizeof(struct ipx)], size, \ ntohl(ifp->int_metric)); \ } \ if (tracepackets && ftrace) \ dumppacket(ftrace, "from", src, \ &packet[sizeof(struct ipx)], size); \ } #define TRACE_OUTPUT(ifp, dst, size) { \ if (tracing) { \ ifp = if_iflookup(dst); \ if (ifp) \ trace(&ifp->int_output, dst, \ &packet[sizeof(struct ipx)], \ size, ifp->int_metric); \ } \ if (tracepackets && ftrace) \ dumppacket(ftrace, "to", dst, \ &packet[sizeof(struct ipx)], size); \ } #define TRACE_SAP_OUTPUT(ifp, dst, size) { \ if (tracing) { \ ifp = if_iflookup(dst); \ if (ifp) \ trace(&ifp->int_output, dst, \ &packet[sizeof(struct ipx)], \ size, ifp->int_metric); \ } \ if (tracepackets && ftrace) \ dumpsappacket(ftrace, "to", dst, \ &packet[sizeof(struct ipx)], size); \ } void traceinit(struct interface *); void traceon(char *file); void traceoff(void); void traceaction(FILE *, char *, struct rt_entry *); +void traceactionlog(char *, struct rt_entry *); +void tracesapactionlog(char *action, struct sap_entry *sap); void trace(struct ifdebug *, struct sockaddr *, char *, int, int); void dumppacket(FILE *, char *, struct sockaddr *, char *, int); void dumpsappacket(FILE *, char *, struct sockaddr *, char *, int); void dumpsaptable(FILE *fd, struct sap_hash *sh); void dumpriptable(FILE *fd); char *ipxdp_nettoa(union ipx_net); char *ipxdp_ntoa(struct ipx_addr *);