From 08d0610487a6192a11d0803de49d2ed6e9dd16f7 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 26 Oct 1995 21:28:30 +0000 Subject: Reviewed by: julian and Mike Mitchel Submitted by: john Hay (John.Hay@csir.co.za) John's IPXrouted.. this has not yet been seen to run correctly with Mike's IPX/SPX code (he has his own) bringing them both in is the first step in merging the two packages for 2.2 --- usr.sbin/IPXrouted/IPXrouted.8 | 184 ++++++++++++++++ usr.sbin/IPXrouted/Makefile | 11 + usr.sbin/IPXrouted/af.c | 278 ++++++++++++++++++++++++ usr.sbin/IPXrouted/af.h | 77 +++++++ usr.sbin/IPXrouted/defs.h | 107 +++++++++ usr.sbin/IPXrouted/if.c | 151 +++++++++++++ usr.sbin/IPXrouted/input.c | 282 ++++++++++++++++++++++++ usr.sbin/IPXrouted/interface.h | 95 ++++++++ usr.sbin/IPXrouted/main.c | 345 +++++++++++++++++++++++++++++ usr.sbin/IPXrouted/output.c | 224 +++++++++++++++++++ usr.sbin/IPXrouted/protocol.h | 91 ++++++++ usr.sbin/IPXrouted/sap.h | 106 +++++++++ usr.sbin/IPXrouted/sap_input.c | 180 ++++++++++++++++ usr.sbin/IPXrouted/sap_output.c | 182 ++++++++++++++++ usr.sbin/IPXrouted/sap_tables.c | 326 ++++++++++++++++++++++++++++ usr.sbin/IPXrouted/startup.c | 277 ++++++++++++++++++++++++ usr.sbin/IPXrouted/table.h | 116 ++++++++++ usr.sbin/IPXrouted/tables.c | 466 ++++++++++++++++++++++++++++++++++++++++ usr.sbin/IPXrouted/timer.c | 234 ++++++++++++++++++++ usr.sbin/IPXrouted/trace.c | 410 +++++++++++++++++++++++++++++++++++ usr.sbin/IPXrouted/trace.h | 123 +++++++++++ 21 files changed, 4265 insertions(+) create mode 100644 usr.sbin/IPXrouted/IPXrouted.8 create mode 100644 usr.sbin/IPXrouted/Makefile create mode 100644 usr.sbin/IPXrouted/af.c create mode 100644 usr.sbin/IPXrouted/af.h create mode 100644 usr.sbin/IPXrouted/defs.h create mode 100644 usr.sbin/IPXrouted/if.c create mode 100644 usr.sbin/IPXrouted/input.c create mode 100644 usr.sbin/IPXrouted/interface.h create mode 100644 usr.sbin/IPXrouted/main.c create mode 100644 usr.sbin/IPXrouted/output.c create mode 100644 usr.sbin/IPXrouted/protocol.h create mode 100644 usr.sbin/IPXrouted/sap.h create mode 100644 usr.sbin/IPXrouted/sap_input.c create mode 100644 usr.sbin/IPXrouted/sap_output.c create mode 100644 usr.sbin/IPXrouted/sap_tables.c create mode 100644 usr.sbin/IPXrouted/startup.c create mode 100644 usr.sbin/IPXrouted/table.h create mode 100644 usr.sbin/IPXrouted/tables.c create mode 100644 usr.sbin/IPXrouted/timer.c create mode 100644 usr.sbin/IPXrouted/trace.c create mode 100644 usr.sbin/IPXrouted/trace.h diff --git a/usr.sbin/IPXrouted/IPXrouted.8 b/usr.sbin/IPXrouted/IPXrouted.8 new file mode 100644 index 0000000..e43055e --- /dev/null +++ b/usr.sbin/IPXrouted/IPXrouted.8 @@ -0,0 +1,184 @@ +.\" Copyright (c) 1986, 1991, 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. +.\" +.Dd Oct 11, 1995 +.Dt IPXROUTED 8 +.Os FreeBSD +.Sh NAME +.Nm IPXrouted +.Nd IPX Routing Information Protocol daemon +.Sh SYNOPSIS +.Nm IPXrouted +.Op Fl q +.Op Fl s +.Op Fl S +.Op Fl t +.Op Ar logfile +.Sh DESCRIPTION +.Nm IPXrouted +is invoked at boot time to manage the IPX routing tables. +The IPX routing daemon uses the Novell IPX Routing +Information Protocol in maintaining up to date kernel routing +table entries. +.Pp +Available options: +.Bl -tag -width logfile +.It Fl q +Do not supply routing information (opposite of +.Fl s +option below). +.It Fl s +Forces +.Nm IPXrouted +to supply routing information whether it is acting as an internetwork +router or not. +.It Fl S +Do not supply Service Advertizing Protocol +.Nm (SAP) +information. The default is to supply +.Nm SAP +information. +.It Fl t +All packets sent or received are +printed on the standard output. In addition, +.Nm IPXrouted +will not divorce itself from the controlling terminal +so that interrupts from the keyboard will kill the process. +.It Ar logfile +Name of file in which +.Nm IPXrouted Ns 's +actions should be logged. This log contains information +about any changes to the routing tables and a history of +recent messages sent and received which are related to +the changed route. +.El +.Pp +In normal operation +.Nm IPXrouted +listens +for routing information packets. If the host is connected to +multiple IPX networks, it periodically supplies copies +of its routing tables to any directly connected hosts +and networks. +.Pp +When +.Nm IPXrouted +is started, it uses the +.Dv SIOCGIFCONF +.Xr ioctl 2 +to find those +directly connected interfaces configured into the +system and marked +.Dq up +(the software loopback interface +is ignored). If multiple interfaces +are present, it is assumed the host will forward packets +between networks. +.Nm IPXrouted +then transmits a +.Em request +packet on each interface (using a broadcast packet if +the interface supports it) and enters a loop, listening +for +.Em request +and +.Em response +packets from other hosts. +.Pp +When a +.Em request +packet is received, +.Nm IPXrouted +formulates a reply based on the information maintained in its +internal tables. The +.Em response +packet generated contains a list of known routes, each marked +with a +.Dq hop count +metric (a count of 16, or greater, is +considered +.Dq infinite ) . +The metric associated with each +route returned provides a metric +.Em relative to the sender . +.Pp +.Em Response +packets received by +.Nm IPXrouted +are used to update the routing tables if one of the following +conditions is satisfied: +.Bl -bullet +.It +No routing table entry exists for the destination network +or host, and the metric indicates the destination is ``reachable'' +(i.e. the hop count is not infinite). +.It +The source host of the packet is the same as the router in the +existing routing table entry. That is, updated information is +being received from the very internetwork router through which +packets for the destination are being routed. +.It +The existing entry in the routing table has not been updated for +some time (defined to be 90 seconds) and the route is at least +as cost effective as the current route. +.It +The new route describes a shorter route to the destination than +the one currently stored in the routing tables; the metric of +the new route is compared against the one stored in the table +to decide this. +.El +.Pp +When an update is applied, +.Nm IPXrouted +records the change in its internal tables and generates a +.Em response +packet to all directly connected hosts and networks. +.Xr Routed 8 +waits a short period +of time (no more than 30 seconds) before modifying the kernel's +routing tables to allow possible unstable situations to settle. +.Pp +In addition to processing incoming packets, +.Nm IPXrouted +also periodically checks the routing table entries. +If an entry has not been updated for 3 minutes, the entry's metric +is set to infinity and marked for deletion. Deletions are delayed +an additional 60 seconds to insure the invalidation is propagated +to other routers. +.Pp +Hosts acting as internetwork routers gratuitously supply their +routing tables every 30 seconds to all directly connected hosts +and networks. +.Sh SEE ALSO +.Xr ipx 4 +.Sh HISTORY diff --git a/usr.sbin/IPXrouted/Makefile b/usr.sbin/IPXrouted/Makefile new file mode 100644 index 0000000..7d4e41c --- /dev/null +++ b/usr.sbin/IPXrouted/Makefile @@ -0,0 +1,11 @@ +# @(#)Makefile 8.1 (Berkeley) 6/5/93 +# $Id: Makefile,v 1.4 1995/03/15 08:44:14 jhay Exp $ + +PROG= IPXrouted +MAN8= IPXrouted.8 +SRCS= af.c if.c input.c main.c output.c startup.c tables.c timer.c trace.c +SRCS+= sap_input.c sap_tables.c sap_output.c +DPADD= ${LIBCOMPAT} ${LIBIPX} +LDADD= -lcompat -lipx + +.include diff --git a/usr.sbin/IPXrouted/af.c b/usr.sbin/IPXrouted/af.c new file mode 100644 index 0000000..28c231c --- /dev/null +++ b/usr.sbin/IPXrouted/af.c @@ -0,0 +1,278 @@ +/* + * 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: af.c,v 1.4 1995/10/11 18:57:05 jhay 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; + + net.net_e = sipx->sipx_addr.x_net; + hp->afh_nethash = net.long_e; + hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s; + hp->afh_hosthash = hash; +} + +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]==0xffff) && (s[1]==0xffff) && (s[2]==0xffff)) + return (0); + else + 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/af.h b/usr.sbin/IPXrouted/af.h new file mode 100644 index 0000000..2781cef --- /dev/null +++ b/usr.sbin/IPXrouted/af.h @@ -0,0 +1,77 @@ +/* + * 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. + * + * @(#)af.h 5.1 (Berkeley) 6/4/85 (routed/af.h) + * + * @(#)af.h 8.1 (Berkeley) 6/5/93 + * + * $Id: af.h,v 1.3 1995/10/11 18:57:09 jhay Exp $ + */ + +/* + * Routing table management daemon. + */ + +/* + * Structure returned by af_hash routines. + */ +struct afhash { + u_int afh_hosthash; /* host based hash */ + u_int afh_nethash; /* network based hash */ +}; + +/* + * Per address family routines. + */ +typedef void af_hash_t(struct sockaddr *, struct afhash *); +typedef int af_netmatch_t(struct sockaddr *, struct sockaddr *); +typedef void af_output_t(int, int, struct sockaddr *, int); +typedef int af_portmatch_t(struct sockaddr *); +typedef int af_portcheck_t(struct sockaddr *); +typedef int af_checkhost_t(struct sockaddr *); +typedef int af_ishost_t(struct sockaddr *); +typedef void af_canon_t(struct sockaddr *); + +struct afswitch { + af_hash_t *af_hash; /* returns keys based on address */ + af_netmatch_t *af_netmatch; /* verifies net # matching */ + af_output_t *af_output; /* interprets address for sending */ + af_portmatch_t *af_portmatch; /* packet from some other router? */ + af_portcheck_t *af_portcheck; /* packet from privileged peer? */ + af_checkhost_t *af_checkhost; /* tells if address for host or net */ + af_ishost_t *af_ishost; /* tells if address is valid */ + af_canon_t *af_canon; /* canonicalize address for compares */ +}; + +struct afswitch afswitch[AF_MAX]; /* table proper */ diff --git a/usr.sbin/IPXrouted/defs.h b/usr.sbin/IPXrouted/defs.h new file mode 100644 index 0000000..810bd7c --- /dev/null +++ b/usr.sbin/IPXrouted/defs.h @@ -0,0 +1,107 @@ +/* + * 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: defs.h,v 1.5 1995/10/11 18:57:12 jhay Exp $ + */ + +#include +#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[MAXPACKETSIZE+sizeof(struct ipxdp)+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 addrouteforif(struct interface *); +void ifinit(void); +void toall(void (*f)(struct sockaddr *, int, struct interface *), + struct rt_entry *); +void rip_input(struct sockaddr *, int); + diff --git a/usr.sbin/IPXrouted/if.c b/usr.sbin/IPXrouted/if.c new file mode 100644 index 0000000..3ea0d51 --- /dev/null +++ b/usr.sbin/IPXrouted/if.c @@ -0,0 +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: if.c,v 1.2 1995/10/11 18:57:14 jhay 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) + 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 new file mode 100644 index 0000000..0aec53a --- /dev/null +++ b/usr.sbin/IPXrouted/input.c @@ -0,0 +1,282 @@ +/* + * 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: input.c,v 1.9 1995/10/11 18:57:17 jhay 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; + extern char ether_broadcast_addr[6]; + + bzero(&sxn, sizeof (struct sockaddr_ipx)); + sxn.sipx_family = AF_IPX; + sxn.sipx_len = sizeof (sxn); + sxn.sipx_addr.x_net = net; + sxn.sipx_addr.x_host = *(union ipx_host *)ether_broadcast_addr; + return( (struct sockaddr *)&sxn); + +} + +/* + * Process a newly received packet. + */ +void +rip_input(from, size) + struct sockaddr *from; + int size; +{ + 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); + 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) + addrouteforif(ifp); + 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); + } + 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) + continue; + rt = rtfind(sa = ipx_nettosa(n->rip_dst)); + if (rt == 0) { + rtadd(sa, from, ntohs(n->rip_metric), + ntohs(n->rip_ticks), 0); + 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)) { + register struct rt_entry *trt = rt->rt_clone; + + while (trt) { + if (equal(from, &trt->rt_router)) { + trt->rt_timer = 0; + break; + } + } + 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))) { + rtchange(rt, from, ntohs(n->rip_metric), + ntohs(n->rip_ticks)); + rt->rt_timer = 0; + } else if (equal(from, &rt->rt_router) && + (ntohs(n->rip_ticks) == rt->rt_ticks) && + (ntohs(n->rip_metric) == rt->rt_metric)) { + rt->rt_timer = 0; + } + } + return; + } +} diff --git a/usr.sbin/IPXrouted/interface.h b/usr.sbin/IPXrouted/interface.h new file mode 100644 index 0000000..f80ced8 --- /dev/null +++ b/usr.sbin/IPXrouted/interface.h @@ -0,0 +1,95 @@ +/* + * 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. + * + * @(#)interface.h 8.1 (Berkeley) 6/5/93 + * + * $Id: interface.h,v 1.3 1995/10/11 18:57:19 jhay Exp $ + */ + +/* + * Routing table management daemon. + */ + +/* + * An ``interface'' is similar to an ifnet structure, + * except it doesn't contain q'ing info, and it also + * handles ``logical'' interfaces (remote gateways + * that we want to keep polling even if they go down). + * The list of interfaces which we maintain is used + * in supplying the gratuitous routing table updates. + * We list only one address for each interface, the AF_IPX one. + */ +struct interface { + struct interface *int_next; + struct sockaddr int_addr; /* address on this host */ + union { + struct sockaddr intu_broadaddr; + struct sockaddr intu_dstaddr; + } int_intu; +#define int_broadaddr int_intu.intu_broadaddr /* broadcast address */ +#define int_dstaddr int_intu.intu_dstaddr /* other end of p-to-p link */ + int int_metric; /* init's routing entry */ + int int_flags; /* see below */ + struct ifdebug int_input, int_output; /* packet tracing stuff */ + int int_ipackets; /* input packets received */ + int int_opackets; /* output packets sent */ + char *int_name; /* from kernel if structure */ + u_short int_transitions; /* times gone up-down */ + + /* XXX IPX Specific entry */ + struct sameq { + struct sameq *n; /* q of other pt-to-pt links */ + struct sameq *p; /* with same net # */ + } int_sq; +}; + +/* + * 0x1 to 0x10 are reused from the kernel's ifnet definitions, + * the others agree with the RTS_ flags defined elsewhere. + */ +#define IFF_UP 0x1 /* interface is up */ +#define IFF_BROADCAST 0x2 /* broadcast address valid */ +#define IFF_DEBUG 0x4 /* turn on debugging */ +#define IFF_ROUTE 0x8 /* routing entry installed */ +#define IFF_POINTOPOINT 0x10 /* interface is point-to-point link */ + +#define IFF_PASSIVE 0x200000 /* can't tell if up/down */ +#define IFF_INTERFACE 0x400000 /* hardware interface */ +#define IFF_REMOTE 0x800000 /* interface isn't on this machine */ + +struct interface *if_ifwithaddr(struct sockaddr *); +struct interface *if_ifwithdstaddr(struct sockaddr *); +struct interface *if_ifwithnet(struct sockaddr *); +struct interface *if_iflookup(struct sockaddr *); + diff --git a/usr.sbin/IPXrouted/main.c b/usr.sbin/IPXrouted/main.c new file mode 100644 index 0000000..9a0a6ab --- /dev/null +++ b/usr.sbin/IPXrouted/main.c @@ -0,0 +1,345 @@ +/* + * 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: main.c,v 1.6 1995/10/11 18:57:21 jhay 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[MAXPACKETSIZE+sizeof(struct ipxdp)+1]; + +char **argv0; + +int supplier = -1; /* process should supply updates */ +int dosap = 1; /* By default do SAP services. */ + +struct rip *msg = (struct rip *) &packet[sizeof (struct ipxdp)]; +struct sap_packet *sap_msg = + (struct sap_packet *) &packet[sizeof (struct ipxdp)]; +void hup(), fkexit(), timer(); +void process(int fd, int pkt_type); +int getsocket(int type, int proto, struct sockaddr_ipx *sipx); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int nfds; + fd_set fdvar; + + 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); + + if (dosap) { + sap_msg->sap_cmd = htons(SAP_REQ); + sap_msg->sap[0].ServType = htons(SAP_WILDCARD); + toall(sapsndmsg, NULL); + } + + signal(SIGALRM, timer); + signal(SIGHUP, hup); + signal(SIGINT, hup); + signal(SIGEMT, fkexit); + timer(); + + nfds = 1 + max(sapsock, ripsock); + + for (;;) { + 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) { + perror("during select"); + exit(1); + } + } + + if(FD_ISSET(ripsock, &fdvar)) + process(ripsock, RIP_PKT); + + if(dosap && FD_ISSET(sapsock, &fdvar)) + process(sapsock, SAP_PKT); + } +} + +void +process(fd, pkt_type) + int fd; + int pkt_type; +{ + struct sockaddr from; + int fromlen = sizeof (from), cc, omask; + struct ipxdp *ipxdp = (struct ipxdp *)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->ipxdp_dna)); + fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipxdp_sna)); + } + + if (noteremoterequests && + !ipx_neteqnn(ipxdp->ipxdp_sna.x_net, ipx_zeronet) && + !ipx_neteq(ipxdp->ipxdp_sna, ipxdp->ipxdp_dna)) + { + syslog(LOG_ERR, + "net of interface (%s) != net on ether (%s)!\n", + ipxdp_nettoa(ipxdp->ipxdp_dna.x_net), + ipxdp_nettoa(ipxdp->ipxdp_sna.x_net)); + } + + /* We get the IPX header in front of the RIF packet*/ + cc -= sizeof (struct ipxdp); +#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 ipxdp 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.ipxdp_pt = IPXPROTO_RI; + else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP) + ipxdp.ipxdp_pt = IPXPROTO_SAP; + 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); +} diff --git a/usr.sbin/IPXrouted/output.c b/usr.sbin/IPXrouted/output.c new file mode 100644 index 0000000..e2dcb56 --- /dev/null +++ b/usr.sbin/IPXrouted/output.c @@ -0,0 +1,224 @@ +/* + * 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: output.c,v 1.6 1995/10/11 18:57:22 jhay Exp $ + */ + +#ifndef lint +static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +/* + * Routing Table Management Daemon + */ +#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 *); + struct rt_entry *except; +{ + 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); + } +} + +/* + * Output a preformed packet. + */ +void +sndmsg(dst, flags, ifp) + struct sockaddr *dst; + int flags; + struct interface *ifp; +{ + + (*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) + struct sockaddr *dst; + int flags; + struct interface *ifp; +{ + 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; + union ipx_net net; + + 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 (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { + size = (char *)n - (char *)msg; + if (size > MAXPACKETSIZE - sizeof (struct netinfo)) { + (*output)(ripsock, flags, dst, size); + TRACE_OUTPUT(ifp, dst, size); + n = msg->rip_nets; + } + + /* + * 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) + continue; + 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/protocol.h b/usr.sbin/IPXrouted/protocol.h new file mode 100644 index 0000000..e41f5c7 --- /dev/null +++ b/usr.sbin/IPXrouted/protocol.h @@ -0,0 +1,91 @@ +/* + * 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. + * + * @(#)protocol.h 8.1 (Berkeley) 6/5/93 + * + * $Id: protocol.h,v 1.4 1995/10/11 18:57:24 jhay Exp $ + */ + +/* + * IPX Routing Information Protocol + * + */ + +struct netinfo { + union ipx_net rip_dst; /* destination net */ + u_short rip_metric; /* cost of route */ + u_short rip_ticks; /* cost of route */ +}; + +struct rip { + u_short rip_cmd; /* request/response */ + struct netinfo rip_nets[1]; /* variable length */ +}; + +/* + * Packet types. + */ +#define RIPCMD_REQUEST 1 /* want info */ +#define RIPCMD_RESPONSE 2 /* responding to request */ + +#define RIPCMD_MAX 3 +#ifdef RIPCMDS +char *ripcmds[RIPCMD_MAX] = + { "#0", "REQUEST", "RESPONSE" }; +#endif + +#define HOPCNT_INFINITY 16 /* per IPX */ +#define DSTNETS_ALL 0xffffffff /* per IPX */ +#define MAXPACKETSIZE 512 /* max broadcast size */ + +extern union ipx_net ipx_anynet; +extern union ipx_net ipx_zeronet; + +/* + * Timer values used in managing the routing table. + * Every update forces an entry's timer to be reset. After + * EXPIRE_TIME without updates, the entry is marked invalid, + * but held onto until GARBAGE_TIME so that others may + * see it "be deleted". + */ +#define TIMER_RATE 30 /* alarm clocks every 30 seconds */ + +#define SUPPLY_INTERVAL 30 /* time to supply tables */ +#define RIP_INTERVAL 60 /* time to supply rip tables */ + +#define EXPIRE_TIME 180 /* time to mark entry invalid */ +#define GARBAGE_TIME 240 /* time to garbage collect */ diff --git a/usr.sbin/IPXrouted/sap.h b/usr.sbin/IPXrouted/sap.h new file mode 100644 index 0000000..9b7cb53 --- /dev/null +++ b/usr.sbin/IPXrouted/sap.h @@ -0,0 +1,106 @@ +/* + * 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.h,v 1.5 1995/10/11 18:57:26 jhay Exp $ + */ +#ifndef _SAP_H_ +#define _SAP_H_ + +#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 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 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 sap_supply(struct sockaddr *dst, + int flags, + struct interface *ifp, + int ServType); + +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 new file mode 100644 index 0000000..44b6290 --- /dev/null +++ b/usr.sbin/IPXrouted/sap_input.c @@ -0,0 +1,180 @@ +/* + * 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_input.c,v 1.6 1995/10/11 18:57:27 jhay Exp $ + */ + +/* + * IPX Routing Table Management Daemon + */ +#include "defs.h" + + +/* + * Process a newly received packet. + */ +void +sap_input(from, size) + struct sockaddr *from; + int size; +{ + 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); + 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; + sap = sap_lookup(n->ServType, n->ServName); + if (sap == 0) { + sap_add(n, from); + 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; + } + } + 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))) { + sap_change(sap, n, from); + } + } + return; + } +} diff --git a/usr.sbin/IPXrouted/sap_output.c b/usr.sbin/IPXrouted/sap_output.c new file mode 100644 index 0000000..e074c3a --- /dev/null +++ b/usr.sbin/IPXrouted/sap_output.c @@ -0,0 +1,182 @@ +/* + * 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_output.c,v 1.4 1995/10/11 18:57:28 jhay Exp $ + */ + +/* + * Routing Table Management Daemon + */ +#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) +{ + 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; + if (ipx_dst->sipx_addr.x_port == 0) + 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); + } +} + +void +sapsndmsg(dst, flags, ifp) + struct sockaddr *dst; + int flags; + struct interface *ifp; +{ + 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) + struct sockaddr *dst; + int flags; + struct interface *ifp; + int ServType; +{ + 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; + + 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 > MAXPACKETSIZE - sizeof (struct sap_info)) { + (*output)(sapsock, flags, dst, size); + TRACE_SAP_OUTPUT(ifp, dst, size); + n = sap_msg->sap; + } + + /* + * 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) + continue; + 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++; + } + 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 new file mode 100644 index 0000000..4f64a4c --- /dev/null +++ b/usr.sbin/IPXrouted/sap_tables.c @@ -0,0 +1,326 @@ +/* + * 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.9 1995/10/11 18:57:29 jhay Exp $ + */ + +#include "defs.h" +#include +#include +/* XXX I thought that this should work! #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); + hsh = rol(hsh) + (ServType & 0xff); + hsh = (hsh >> 7) ^ hsh; + 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; + + 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); +} + +/* + * 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); + /* + * 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; + 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; + 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) + free(osap); +} + +/* + * 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; + + 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; +} + +/* + * 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); + free(sap); +} + diff --git a/usr.sbin/IPXrouted/startup.c b/usr.sbin/IPXrouted/startup.c new file mode 100644 index 0000000..c3b3e05 --- /dev/null +++ b/usr.sbin/IPXrouted/startup.c @@ -0,0 +1,277 @@ +/* + * 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: startup.c,v 1.3 1995/10/11 18:57:30 jhay Exp $ + */ + +#ifndef lint +static char sccsid[] = "@(#)startup.c 8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +/* + * Routing Table Management Daemon + */ +#include "defs.h" + +#include +#include +#include + +#include +#include + +#include +#include + +struct interface *ifnet; +int lookforinterfaces = 1; +int performnlist = 1; +int gateway = 0; +int externalinterfaces = 0; /* # of remote and local interfaces */ +char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + +void +quit(s) + char *s; +{ + extern int errno; + int sverrno = errno; + + (void) fprintf(stderr, "IPXroute: "); + if (s) + (void) fprintf(stderr, "%s: ", s); + (void) fprintf(stderr, "%s\n", strerror(sverrno)); + exit(1); + /* NOTREACHED */ +} + +struct rt_addrinfo info; +/* Sleazy use of local variables throughout file, warning!!!! */ +#define netmask info.rti_info[RTAX_NETMASK] +#define ifaaddr info.rti_info[RTAX_IFA] +#define brdaddr info.rti_info[RTAX_BRD] + +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +void +rt_xaddrs(cp, cplim, rtinfo) + register caddr_t cp, cplim; + register struct rt_addrinfo *rtinfo; +{ + register struct sockaddr *sa; + register int i; + + bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); + for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { + if ((rtinfo->rti_addrs & (1 << i)) == 0) + continue; + rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; + ADVANCE(cp, sa); + } +} + +/* + * Find the network interfaces which have configured themselves. + * If the interface is present but not yet up (for example an + * ARPANET IMP), set the lookforinterfaces flag so we'll + * come back later and look again. + */ +void +ifinit(void) +{ + struct interface ifs, *ifp; + size_t needed; + int mib[6], no_ipxaddr = 0, flags = 0; + char *buf, *cplim, *cp; + register struct if_msghdr *ifm; + register struct ifa_msghdr *ifam; + struct sockaddr_dl *sdl = 0; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = AF_IPX; + mib[4] = NET_RT_IFLIST; + mib[5] = 0; + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + quit("route-sysctl-estimate"); + if ((buf = malloc(needed)) == NULL) + quit("malloc"); + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) + lookforinterfaces = 0; + cplim = buf + needed; + for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) { + ifm = (struct if_msghdr *)cp; + if (ifm->ifm_type == RTM_IFINFO) { + bzero(&ifs, sizeof(ifs)); + ifs.int_flags = flags = ifm->ifm_flags | IFF_INTERFACE; + if ((flags & IFF_UP) == 0 || no_ipxaddr) + lookforinterfaces = 1; + sdl = (struct sockaddr_dl *) (ifm + 1); + sdl->sdl_data[sdl->sdl_nlen] = 0; + no_ipxaddr = 1; + continue; + } + if (ifm->ifm_type != RTM_NEWADDR) + quit("ifinit: out of sync"); + if ((flags & IFF_UP) == 0) + continue; + ifam = (struct ifa_msghdr *)ifm; + info.rti_addrs = ifam->ifam_addrs; + rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info); + if (ifaaddr == 0) { + syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data); + continue; + } + ifs.int_addr = *ifaaddr; + if (ifs.int_addr.sa_family != AF_IPX) + continue; + no_ipxaddr = 0; + if (ifs.int_flags & IFF_POINTOPOINT) { + if (brdaddr == 0) { + syslog(LOG_ERR, "%s: (get dstaddr)", + sdl->sdl_data); + continue; + } + if (brdaddr->sa_family == AF_UNSPEC) { + lookforinterfaces = 1; + continue; + } + ifs.int_dstaddr = *brdaddr; + } + if (ifs.int_flags & IFF_BROADCAST) { + if (brdaddr == 0) { + syslog(LOG_ERR, "%s: (get broadaddr)", + sdl->sdl_data); + continue; + } + ifs.int_dstaddr = *brdaddr; + } + /* + * already known to us? + * what makes a POINTOPOINT if unique is its dst addr, + * NOT its source address + */ + if ( ((ifs.int_flags & IFF_POINTOPOINT) && + if_ifwithdstaddr(&ifs.int_dstaddr)) || + ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) && + if_ifwithaddr(&ifs.int_addr))) + continue; + /* no one cares about software loopback interfaces */ + if (ifs.int_flags & IFF_LOOPBACK) + continue; + ifp = (struct interface *) + malloc(sdl->sdl_nlen + 1 + sizeof(ifs)); + if (ifp == 0) { + syslog(LOG_ERR, "IPXrouted: out of memory\n"); + lookforinterfaces = 1; + break; + } + *ifp = ifs; + /* + * Count the # of directly connected networks + * and point to point links which aren't looped + * back to ourself. This is used below to + * decide if we should be a routing ``supplier''. + */ + if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || + if_ifwithaddr(&ifs.int_dstaddr) == 0) + externalinterfaces++; + /* + * If we have a point-to-point link, we want to act + * as a supplier even if it's our only interface, + * as that's the only way our peer on the other end + * can tell that the link is up. + */ + if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) + supplier = 1; + ifp->int_name = (char *)(ifp + 1); + strcpy(ifp->int_name, sdl->sdl_data); + + ifp->int_metric = ifam->ifam_metric; + ifp->int_next = ifnet; + ifnet = ifp; + traceinit(ifp); + addrouteforif(ifp); + } + if (externalinterfaces > 1 && supplier < 0) + supplier = 1; + free(buf); +} + +void +addrouteforif(ifp) + struct interface *ifp; +{ + struct sockaddr *dst; + struct rt_entry *rt; + + if (ifp->int_flags & IFF_POINTOPOINT) { + int (*match)(); + register struct interface *ifp2 = ifnet; + + dst = &ifp->int_dstaddr; + + /* Search for interfaces with the same net */ + ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq); + match = afswitch[dst->sa_family].af_netmatch; + if (match) + for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) { + if (ifp->int_flags & IFF_POINTOPOINT == 0) + continue; + if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) { + insque(&ifp2->int_sq,&ifp->int_sq); + break; + } + } + } else { + dst = &ifp->int_broadaddr; + } + rt = rtlookup(dst); + if (rt) + rtdelete(rt); + if (tracing) + fprintf(stderr, "Adding route to interface %s\n", ifp->int_name); + if (ifp->int_transitions++ > 0) + syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); + rtadd(dst, &ifp->int_addr, ifp->int_metric, 0, + ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); +} + diff --git a/usr.sbin/IPXrouted/table.h b/usr.sbin/IPXrouted/table.h new file mode 100644 index 0000000..b029dcc --- /dev/null +++ b/usr.sbin/IPXrouted/table.h @@ -0,0 +1,116 @@ +/* + * 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: table.h,v 1.4 1995/10/11 18:57:30 jhay 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 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 */ + +struct rthash nethash[ROUTEHASHSIZ]; +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 new file mode 100644 index 0000000..2faf523 --- /dev/null +++ b/usr.sbin/IPXrouted/tables.c @@ -0,0 +1,466 @@ +/* + * 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.6 1995/10/11 18:57:31 jhay 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 +/* XXX I thought that this should work! #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; +/* + * 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: + 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; + + if (af >= AF_MAX) + return (0); + (*afswitch[af].af_hash)(dst, &h); + hash = h.afh_hosthash; + rh = &hosthash[hash & ROUTEHASHMASK]; + +again: + 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; + } + 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]; + } + 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); + /* + * 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); + 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]; + } + 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); +} + +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); + 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_state |= RTS_CHANGED; + 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)); + 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); + 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 new file mode 100644 index 0000000..d7e8124 --- /dev/null +++ b/usr.sbin/IPXrouted/timer.c @@ -0,0 +1,234 @@ +/* + * 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: timer.c,v 1.8 1995/10/11 18:57:32 jhay 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; + + 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++) { + 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) + rt->rt_metric = HOPCNT_INFINITY; + 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; + 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); + } + } + } + if (doinghost) { + doinghost = 0; + base = nethash; + goto again; + } + if (ripbroadcast) + toall(supply, NULL); + + /* + * 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 >= 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 (sapbroadcast) + sap_supply_toall(); + 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++) { + 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); + + /* + * 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(); + } + exit(1); +} diff --git a/usr.sbin/IPXrouted/trace.c b/usr.sbin/IPXrouted/trace.c new file mode 100644 index 0000000..bf51116 --- /dev/null +++ b/usr.sbin/IPXrouted/trace.c @@ -0,0 +1,410 @@ +/* + * 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: trace.c,v 1.6 1995/10/11 18:57:33 jhay 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 +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"); +} + +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 new file mode 100644 index 0000000..41d21ae --- /dev/null +++ b/usr.sbin/IPXrouted/trace.h @@ -0,0 +1,123 @@ +/* + * 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: trace.h,v 1.4 1995/10/11 18:57:34 jhay 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); \ + } +#define TRACE_INPUT(ifp, src, size) { \ + if (tracing) { \ + ifp = if_iflookup(src); \ + if (ifp) \ + trace(&ifp->int_input, src, &packet[sizeof(struct ipxdp)], size, \ + ntohl(ifp->int_metric)); \ + } \ + if (tracepackets && ftrace) \ + dumppacket(ftrace, "from", src, &packet[sizeof(struct ipxdp)], size); \ + } +#define TRACE_OUTPUT(ifp, dst, size) { \ + if (tracing) { \ + ifp = if_iflookup(dst); \ + if (ifp) \ + trace(&ifp->int_output, dst, &packet[sizeof(struct ipxdp)], size, ifp->int_metric); \ + } \ + if (tracepackets && ftrace) \ + dumppacket(ftrace, "to", dst, &packet[sizeof(struct ipxdp)], size); \ + } + +#define TRACE_SAP_OUTPUT(ifp, dst, size) { \ + if (tracing) { \ + ifp = if_iflookup(dst); \ + if (ifp) \ + trace(&ifp->int_output, dst, &packet[sizeof(struct ipxdp)], size, ifp->int_metric); \ + } \ + if (tracepackets && ftrace) \ + dumpsappacket(ftrace, "to", dst, &packet[sizeof(struct ipxdp)], size); \ + } + +void traceinit(struct interface *); +void traceon(char *file); +void traceoff(void); +void traceaction(FILE *, char *, struct rt_entry *); +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); + +char *ipxdp_nettoa(union ipx_net); +char *ipxdp_ntoa(struct ipx_addr *); + -- cgit v1.1