aboutsummaryrefslogtreecommitdiff
path: root/contrib/isc-dhcp/common
diff options
context:
space:
mode:
authorDavid E. O'Brien <obrien@FreeBSD.org>1999-06-23 23:40:02 +0000
committerDavid E. O'Brien <obrien@FreeBSD.org>1999-06-23 23:40:02 +0000
commitf1b2a73d600a397664f7e0bb0759d114e4bd9338 (patch)
tree1f762fde578b5005be25198c106c89beb9550ae2 /contrib/isc-dhcp/common
parentf96b6240a8bcccf45bd5180f78bf9512c3339a18 (diff)
downloadsrc-f1b2a73d600a397664f7e0bb0759d114e4bd9338.tar.gz
src-f1b2a73d600a397664f7e0bb0759d114e4bd9338.zip
Virgin import of ISC-DHCP v2.0
Notes
Notes: svn path=/vendor/isc-dhcp/dist/; revision=48146
Diffstat (limited to 'contrib/isc-dhcp/common')
-rw-r--r--contrib/isc-dhcp/common/bpf.c16
-rw-r--r--contrib/isc-dhcp/common/ethernet.c110
-rw-r--r--contrib/isc-dhcp/common/lpf.c68
-rw-r--r--contrib/isc-dhcp/common/memory.c3
-rw-r--r--contrib/isc-dhcp/common/options.c23
-rw-r--r--contrib/isc-dhcp/common/packet.c44
-rw-r--r--contrib/isc-dhcp/common/tr.c307
7 files changed, 517 insertions, 54 deletions
diff --git a/contrib/isc-dhcp/common/bpf.c b/contrib/isc-dhcp/common/bpf.c
index d1c3b1a7be85..e204dfe2e0f1 100644
--- a/contrib/isc-dhcp/common/bpf.c
+++ b/contrib/isc-dhcp/common/bpf.c
@@ -42,7 +42,7 @@
#ifndef lint
static char copyright[] =
-"$Id: bpf.c,v 1.19.2.9 1999/03/29 22:07:12 mellon Exp $ Copyright (c) 1995, 1996, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
+"$Id: bpf.c,v 1.19.2.10 1999/05/27 17:44:51 mellon Exp $ Copyright (c) 1995, 1996, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -186,6 +186,20 @@ struct bpf_insn dhcp_bpf_filter [] = {
};
int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn);
+
+struct bpf_insn dhcp_bpf_tr_filter [] = {
+ /* accept all token ring packets due to variable length header */
+ /* if we want to get clever, insert the program here */
+
+ /* If we passed all the tests, ask for the whole packet. */
+ BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
+
+ /* Otherwise, drop it. */
+ BPF_STMT(BPF_RET+BPF_K, 0),
+};
+
+int dhcp_bpf_tr_filter_len = (sizeof dhcp_bpf_tr_filter /
+ sizeof (struct bpf_insn));
#endif
#if defined (USE_BPF_RECEIVE)
diff --git a/contrib/isc-dhcp/common/ethernet.c b/contrib/isc-dhcp/common/ethernet.c
new file mode 100644
index 000000000000..311c3c9af714
--- /dev/null
+++ b/contrib/isc-dhcp/common/ethernet.c
@@ -0,0 +1,110 @@
+/* packet.c
+
+ Packet assembly code, originally contributed by Archie Cobbs. */
+
+/*
+ * Copyright (c) 1995, 1996 The Internet Software Consortium.
+ * 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. Neither the name of The Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: ethernet.c,v 1.1.2.1 1999/05/27 17:35:47 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+#if defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING)
+#include "includes/netinet/if_ether.h"
+#endif /* PACKET_ASSEMBLY || PACKET_DECODING */
+
+#if defined (PACKET_ASSEMBLY)
+/* Assemble an hardware header... */
+/* XXX currently only supports ethernet; doesn't check for other types. */
+
+void assemble_ethernet_header (interface, buf, bufix, to)
+ struct interface_info *interface;
+ unsigned char *buf;
+ int *bufix;
+ struct hardware *to;
+{
+ struct ether_header eh;
+
+ if (to && to -> hlen == 6) /* XXX */
+ memcpy (eh.ether_dhost, to -> haddr, sizeof eh.ether_dhost);
+ else
+ memset (eh.ether_dhost, 0xff, sizeof (eh.ether_dhost));
+ if (interface -> hw_address.hlen == sizeof (eh.ether_shost))
+ memcpy (eh.ether_shost, interface -> hw_address.haddr,
+ sizeof (eh.ether_shost));
+ else
+ memset (eh.ether_shost, 0x00, sizeof (eh.ether_shost));
+
+#ifdef BROKEN_FREEBSD_BPF /* Fixed in FreeBSD 2.2 */
+ eh.ether_type = ETHERTYPE_IP;
+#else
+ eh.ether_type = htons (ETHERTYPE_IP);
+#endif
+
+ memcpy (&buf [*bufix], &eh, sizeof eh);
+ *bufix += sizeof eh;
+}
+#endif /* PACKET_ASSEMBLY */
+
+#ifdef PACKET_DECODING
+/* Decode a hardware header... */
+
+ssize_t decode_ethernet_header (interface, buf, bufix, from)
+ struct interface_info *interface;
+ unsigned char *buf;
+ int bufix;
+ struct hardware *from;
+{
+ struct ether_header eh;
+
+ memcpy (&eh, buf + bufix, sizeof eh);
+
+#ifdef USERLAND_FILTER
+ if (ntohs (eh.ether_type) != ETHERTYPE_IP)
+ return -1;
+#endif
+ memcpy (from -> haddr, eh.ether_shost, sizeof (eh.ether_shost));
+ from -> htype = ARPHRD_ETHER;
+ from -> hlen = sizeof eh.ether_shost;
+
+ return sizeof eh;
+}
+#endif /* PACKET_DECODING */
diff --git a/contrib/isc-dhcp/common/lpf.c b/contrib/isc-dhcp/common/lpf.c
index 4deecf85f24f..9e566849f749 100644
--- a/contrib/isc-dhcp/common/lpf.c
+++ b/contrib/isc-dhcp/common/lpf.c
@@ -43,7 +43,7 @@
#ifndef lint
static char copyright[] =
-"$Id: lpf.c,v 1.1.2.8 1999/03/29 22:07:13 mellon Exp $ Copyright (c) 1995, 1996, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
+"$Id: lpf.c,v 1.1.2.9 1999/05/27 17:44:52 mellon Exp $ Copyright (c) 1995, 1996, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -59,6 +59,9 @@ static char copyright[] =
#include "includes/netinet/udp.h"
#include "includes/netinet/if_ether.h"
+static void lpf_gen_filter_setup PROTO ((struct interface_info *));
+static void lpf_tr_filter_setup PROTO ((struct interface_info *));
+
/* Reinitializes the specified interface after an address change. This
is not required for packet-filter APIs. */
@@ -149,15 +152,36 @@ void if_register_send (info)
in bpf includes... */
extern struct sock_filter dhcp_bpf_filter [];
extern int dhcp_bpf_filter_len;
+extern struct sock_filter dhcp_bpf_tr_filter [];
+extern int dhcp_bpf_tr_filter_len;
void if_register_receive (info)
struct interface_info *info;
{
- struct sock_fprog p;
-
/* Open a LPF device and hang it on this interface... */
info -> rfdesc = if_register_lpf (info);
+ if (info -> hw_address.htype == HTYPE_IEEE802)
+ lpf_tr_filter_setup (info);
+ else
+ lpf_gen_filter_setup (info);
+
+ if (!quiet_interface_discovery)
+ note ("Listening on LPF/%s/%s%s%s",
+ info -> name,
+ print_hw_addr (info -> hw_address.htype,
+ info -> hw_address.hlen,
+ info -> hw_address.haddr),
+ (info -> shared_network ? "/" : ""),
+ (info -> shared_network ?
+ info -> shared_network -> name : ""));
+}
+
+static void lpf_gen_filter_setup (info)
+ struct interface_info *info;
+{
+ struct sock_fprog p;
+
/* Set up the bpf filter program structure. This is defined in
bpf.c */
p.len = dhcp_bpf_filter_len;
@@ -178,15 +202,35 @@ void if_register_receive (info)
"in your kernel configuration");
error ("Can't install packet filter program: %m");
}
- if (!quiet_interface_discovery)
- note ("Listening on LPF/%s/%s%s%s",
- info -> name,
- print_hw_addr (info -> hw_address.htype,
- info -> hw_address.hlen,
- info -> hw_address.haddr),
- (info -> shared_network ? "/" : ""),
- (info -> shared_network ?
- info -> shared_network -> name : ""));
+}
+
+static void lpf_tr_filter_setup (info)
+ struct interface_info *info;
+{
+ struct sock_fprog p;
+
+ /* Set up the bpf filter program structure. This is defined in
+ bpf.c */
+ p.len = dhcp_bpf_tr_filter_len;
+ p.filter = dhcp_bpf_tr_filter;
+
+ /* Patch the server port into the LPF program...
+ XXX changes to filter program may require changes
+ XXX to the insn number(s) used below!
+ XXX Token ring filter is null - when/if we have a filter
+ XXX that's not, we'll need this code.
+ XXX dhcp_bpf_filter [?].k = ntohs (local_port); */
+
+ if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
+ sizeof p) < 0) {
+ if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
+ errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
+ errno == EAFNOSUPPORT)
+ error ("socket: %m - make sure %s %s!",
+ "CONFIG_PACKET and CONFIG_FILTER are defined",
+ "in your kernel configuration");
+ error ("Can't install packet filter program: %m");
+ }
}
#endif /* USE_LPF_RECEIVE */
diff --git a/contrib/isc-dhcp/common/memory.c b/contrib/isc-dhcp/common/memory.c
index 871fe0772d4a..c293217eb272 100644
--- a/contrib/isc-dhcp/common/memory.c
+++ b/contrib/isc-dhcp/common/memory.c
@@ -42,7 +42,7 @@
#ifndef lint
static char copyright[] =
-"$Id: memory.c,v 1.35.2.3 1998/11/24 22:32:43 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
+"$Id: memory.c,v 1.35.2.4 1999/05/27 17:47:43 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -527,7 +527,6 @@ int supersede_lease (comp, lease, commit)
/* Copy the data files, but not the linkages. */
comp -> starts = lease -> starts;
- comp -> timestamp = lease -> timestamp;
if (lease -> uid) {
if (lease -> uid_len < sizeof (lease -> uid_buf)) {
memcpy (comp -> uid_buf,
diff --git a/contrib/isc-dhcp/common/options.c b/contrib/isc-dhcp/common/options.c
index b1c463fd2c0e..21e13597a8d3 100644
--- a/contrib/isc-dhcp/common/options.c
+++ b/contrib/isc-dhcp/common/options.c
@@ -42,11 +42,12 @@
#ifndef lint
static char copyright[] =
-"$Id: options.c,v 1.26.2.7 1999/03/30 02:57:47 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
+"$Id: options.c,v 1.26.2.10 1999/05/06 21:54:34 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#define DHCP_OPTION_DATA
#include "dhcpd.h"
+#include <ctype.h>
/* Parse all available options out of the specified packet. */
@@ -439,7 +440,7 @@ char *pretty_print_option (code, data, len, emit_commas, emit_quotes)
int numhunk = -1;
int numelem = 0;
char fmtbuf [32];
- int i, j;
+ int i, j, k;
char *op = optbuf;
unsigned char *dp = data;
struct in_addr foo;
@@ -471,11 +472,21 @@ char *pretty_print_option (code, data, len, emit_commas, emit_quotes)
numhunk = 0;
break;
case 'X':
- fmtbuf [i] = 'x';
+ for (k = 0; k < len; k++) {
+ if (!isascii (data [k]) ||
+ !isprint (data [k]))
+ break;
+ }
+ if (k == len) {
+ fmtbuf [i] = 't';
+ numhunk = -2;
+ } else {
+ fmtbuf [i] = 'x';
+ hunksize++;
+ comma = ':';
+ numhunk = 0;
+ }
fmtbuf [i + 1] = 0;
- hunksize++;
- numhunk = 0;
- comma = ':';
break;
case 't':
fmtbuf [i] = 't';
diff --git a/contrib/isc-dhcp/common/packet.c b/contrib/isc-dhcp/common/packet.c
index b5ad42748b5f..6a15fcf1e4df 100644
--- a/contrib/isc-dhcp/common/packet.c
+++ b/contrib/isc-dhcp/common/packet.c
@@ -3,7 +3,7 @@
Packet assembly code, originally contributed by Archie Cobbs. */
/*
- * Copyright (c) 1995, 1996 The Internet Software Consortium.
+ * Copyright (c) 1995, 1996, 1999 The Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,7 +42,7 @@
#ifndef lint
static char copyright[] =
-"$Id: packet.c,v 1.18.2.4 1999/04/24 15:31:47 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium. All rights reserved.\n";
+"$Id: packet.c,v 1.18.2.6 1999/06/10 00:58:16 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -50,7 +50,6 @@ static char copyright[] =
#if defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING)
#include "includes/netinet/ip.h"
#include "includes/netinet/udp.h"
-#include "includes/netinet/if_ether.h"
#endif /* PACKET_ASSEMBLY || PACKET_DECODING */
/* Compute the easy part of the checksum on a range of bytes. */
@@ -122,26 +121,13 @@ void assemble_hw_header (interface, buf, bufix, to)
int *bufix;
struct hardware *to;
{
- struct ether_header eh;
-
- if (to && to -> hlen == 6) /* XXX */
- memcpy (eh.ether_dhost, to -> haddr, sizeof eh.ether_dhost);
- else
- memset (eh.ether_dhost, 0xff, sizeof (eh.ether_dhost));
- if (interface -> hw_address.hlen == sizeof (eh.ether_shost))
- memcpy (eh.ether_shost, interface -> hw_address.haddr,
- sizeof (eh.ether_shost));
+#if defined (HAVE_TR_SUPPORT)
+ if (interface -> hw_address.htype == HTYPE_IEEE802)
+ assemble_tr_header (interface, buf, bufix, to);
else
- memset (eh.ether_shost, 0x00, sizeof (eh.ether_shost));
-
-#ifdef BROKEN_FREEBSD_BPF /* Fixed in FreeBSD 2.2 */
- eh.ether_type = ETHERTYPE_IP;
-#else
- eh.ether_type = htons (ETHERTYPE_IP);
#endif
+ assemble_ethernet_header (interface, buf, bufix, to);
- memcpy (&buf [*bufix], &eh, sizeof eh);
- *bufix += sizeof eh;
}
/* UDP header and IP header assembled together for convenience. */
@@ -207,7 +193,6 @@ void assemble_udp_ip_header (interface, buf, bufix,
#ifdef PACKET_DECODING
/* Decode a hardware header... */
-/* XXX currently only supports ethernet; doesn't check for other types. */
ssize_t decode_hw_header (interface, buf, bufix, from)
struct interface_info *interface;
@@ -215,19 +200,12 @@ ssize_t decode_hw_header (interface, buf, bufix, from)
int bufix;
struct hardware *from;
{
- struct ether_header eh;
-
- memcpy (&eh, buf + bufix, sizeof eh);
-
-#ifdef USERLAND_FILTER
- if (ntohs (eh.ether_type) != ETHERTYPE_IP)
- return -1;
+#if defined (HAVE_TR_SUPPORT)
+ if (interface -> hw_address.htype == HTYPE_IEEE802)
+ return decode_tr_header (interface, buf, bufix, from);
+ else
#endif
- memcpy (from -> haddr, eh.ether_shost, sizeof (eh.ether_shost));
- from -> htype = ARPHRD_ETHER;
- from -> hlen = sizeof eh.ether_shost;
-
- return sizeof eh;
+ return decode_ethernet_header (interface, buf, bufix, from);
}
/* UDP header and IP header decoded together for convenience. */
diff --git a/contrib/isc-dhcp/common/tr.c b/contrib/isc-dhcp/common/tr.c
new file mode 100644
index 000000000000..b19c1833fc88
--- /dev/null
+++ b/contrib/isc-dhcp/common/tr.c
@@ -0,0 +1,307 @@
+/*
+ * packet_tr.c - token ring interface code, contributed in May of 1999
+ * by Andrew Chittenden
+ */
+
+#include "dhcpd.h"
+
+#if defined (HAVE_TR_SUPPORT) && \
+ (defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING))
+#include "includes/netinet/ip.h"
+#include "includes/netinet/udp.h"
+#include "includes/netinet/if_ether.h"
+#include "netinet/if_tr.h"
+#include <sys/time.h>
+
+/*
+ * token ring device handling subroutines. These are required as token-ring
+ * does not have a simple on-the-wire header but requires the use of
+ * source routing
+ */
+
+static int insert_source_routing PROTO ((struct trh_hdr *trh, struct interface_info* interface));
+static void save_source_routing PROTO ((struct trh_hdr *trh, struct interface_info* interface));
+static void expire_routes PROTO ((void));
+
+/*
+ * As we keep a list of interesting routing information only, a singly
+ * linked list is all we need
+ */
+struct routing_entry {
+ struct routing_entry *next;
+ unsigned char addr[TR_ALEN];
+ unsigned char iface[5];
+ __u16 rcf; /* route control field */
+ __u16 rseg[8]; /* routing registers */
+ unsigned long access_time; /* time we last used this entry */
+};
+
+static struct routing_entry *routing_info = NULL;
+
+static int routing_timeout = 10;
+static struct timeval routing_timer;
+
+void assemble_tr_header (interface, buf, bufix, to)
+ struct interface_info *interface;
+ unsigned char *buf;
+ int *bufix;
+ struct hardware *to;
+{
+ struct trh_hdr *trh;
+ int hdr_len;
+ struct trllc *llc;
+
+
+ /* set up the token header */
+ trh = (struct trh_hdr *) &buf[*bufix];
+ if (interface -> hw_address.hlen == sizeof (trh->saddr))
+ memcpy (trh->saddr, interface -> hw_address.haddr,
+ sizeof (trh->saddr));
+ else
+ memset (trh->saddr, 0x00, sizeof (trh->saddr));
+
+ if (to && to -> hlen == 6) /* XXX */
+ memcpy (trh->daddr, to -> haddr, sizeof trh->daddr);
+ else
+ memset (trh->daddr, 0xff, sizeof (trh->daddr));
+
+ hdr_len = insert_source_routing (trh, interface);
+
+ trh->ac = AC;
+ trh->fc = LLC_FRAME;
+
+ /* set up the llc header for snap encoding after the tr header */
+ llc = (struct trllc *)(buf + *bufix + hdr_len);
+ llc->dsap = EXTENDED_SAP;
+ llc->ssap = EXTENDED_SAP;
+ llc->llc = UI_CMD;
+ llc->protid[0] = 0;
+ llc->protid[1] = 0;
+ llc->protid[2] = 0;
+ llc->ethertype = htons(ETHERTYPE_IP);
+
+ hdr_len += sizeof(struct trllc);
+
+ *bufix += hdr_len;
+}
+
+
+static unsigned char tr_broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+/*
+ * decoding the token header is a bit complex as you can see here. It is
+ * further complicated by the linux kernel stripping off some valuable
+ * information (see comment below) even though we've asked for the raw
+ * packets.
+ */
+ssize_t decode_tr_header (interface, buf, bufix, from)
+ struct interface_info *interface;
+ unsigned char *buf;
+ int bufix;
+ struct hardware *from;
+{
+ struct trh_hdr *trh = (struct trh_hdr *) buf + bufix;
+ struct trllc *llc;
+ struct ip *ip;
+ struct udphdr *udp;
+ unsigned int route_len = 0;
+ ssize_t hdr_len;
+ struct timeval now;
+
+ /* see whether any source routing information has expired */
+ gettimeofday(&now, NULL);
+
+ if (routing_timer.tv_sec == 0)
+ routing_timer.tv_sec = now.tv_sec + routing_timeout;
+ else if ((now.tv_sec - routing_timer.tv_sec) > 0)
+ expire_routes();
+
+ /* the kernel might have stripped off the source
+ * routing bit. We try a heuristic to determine whether
+ * this is the case and put it back on if so
+ */
+ route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
+ llc = (struct trllc *)(buf + bufix + sizeof(struct trh_hdr)-TR_MAXRIFLEN+route_len);
+ if (llc->dsap == EXTENDED_SAP
+ && llc->ssap == EXTENDED_SAP
+ && llc->llc == UI_CMD
+ && llc->protid[0] == 0
+ && llc->protid[1] == 0
+ && llc->protid[2] == 0) {
+ /* say there is source routing information present */
+ trh->saddr[0] |= TR_RII;
+ }
+
+ if (trh->saddr[0] & TR_RII)
+ route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
+ else
+ route_len = 0;
+
+ hdr_len = sizeof (struct trh_hdr) - TR_MAXRIFLEN + route_len;
+
+ /* now filter out unwanted packets: this is based on the packet
+ * filter code in bpf.c */
+ llc = (struct trllc *)(buf + bufix + hdr_len);
+ ip = (struct ip *) (llc + 1);
+ udp = (struct udphdr *) ((unsigned char*) ip + ip->ip_hl * 4);
+
+ /* make sure it is a snap encoded, IP, UDP, unfragmented packet sent
+ * to our port */
+ if (llc->dsap != EXTENDED_SAP
+ || ntohs(llc->ethertype) != ETHERTYPE_IP
+ || ip->ip_p != IPPROTO_UDP
+ || (ip->ip_off & IP_OFFMASK) != 0
+ || udp->uh_dport != local_port)
+ return -1;
+
+ /* only save source routing information for packets from valued hosts */
+ save_source_routing(trh, interface);
+
+ return hdr_len + sizeof (struct trllc);
+}
+
+/* insert_source_routing inserts source route information into the token ring
+ * header
+ */
+static int insert_source_routing (trh, interface)
+ struct trh_hdr *trh;
+ struct interface_info* interface;
+{
+ struct routing_entry *rover;
+ struct timeval now;
+ unsigned int route_len = 0;
+
+ gettimeofday(&now, NULL);
+
+ /* single route broadcasts as per rfc 1042 */
+ if (memcmp(trh->daddr, tr_broadcast,TR_ALEN) == 0) {
+ trh->saddr[0] |= TR_RII;
+ trh->rcf = ((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK;
+ trh->rcf |= (TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
+ trh->rcf = htons(trh->rcf);
+ } else {
+ /* look for a routing entry */
+ for (rover = routing_info; rover != NULL; rover = rover->next) {
+ if (memcmp(rover->addr, trh->daddr, TR_ALEN) == 0)
+ break;
+ }
+
+ if (rover != NULL) {
+ /* success: route that frame */
+ if ((rover->rcf & TR_RCF_LEN_MASK) >> 8) {
+ __u16 rcf = rover->rcf;
+ memcpy(trh->rseg,rover->rseg,sizeof(trh->rseg));
+ rcf ^= TR_RCF_DIR_BIT;
+ rcf &= ~TR_RCF_BROADCAST_MASK;
+ trh->rcf = htons(rcf);
+ trh->saddr[0] |= TR_RII;
+ }
+ rover->access_time = now.tv_sec;
+ } else {
+ /* we don't have any routing information so send a
+ * limited broadcast */
+ trh->saddr[0] |= TR_RII;
+ trh->rcf = ((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK;
+ trh->rcf |= (TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
+ trh->rcf = htons(trh->rcf);
+ }
+ }
+
+ /* return how much of the header we've actually used */
+ if (trh->saddr[0] & TR_RII)
+ route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
+ else
+ route_len = 0;
+
+ return sizeof (struct trh_hdr) - TR_MAXRIFLEN + route_len;
+}
+
+/*
+ * save any source routing information
+ */
+static void save_source_routing(trh, interface)
+ struct trh_hdr *trh;
+ struct interface_info *interface;
+{
+ struct routing_entry *rover;
+ struct timeval now;
+ unsigned char saddr[TR_ALEN];
+ __u16 rcf = 0;
+
+ gettimeofday(&now, NULL);
+
+ memcpy(saddr, trh->saddr, sizeof(saddr));
+ saddr[0] &= 0x7f; /* strip off source routing present flag */
+
+ /* scan our table to see if we've got it */
+ for (rover = routing_info; rover != NULL; rover = rover->next) {
+ if (memcmp(&rover->addr[0], &saddr[0], TR_ALEN) == 0)
+ break;
+ }
+
+ /* found an entry so update it with fresh information */
+ if (rover != NULL) {
+ if ((trh->saddr[0] & TR_RII)
+ && (((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2)) {
+ rcf = ntohs(trh->rcf);
+ rcf &= ~TR_RCF_BROADCAST_MASK;
+ memcpy(rover->rseg, trh->rseg, sizeof(rover->rseg));
+ }
+ rover->rcf = rcf;
+ rover->access_time = now.tv_sec;
+ return; /* that's all folks */
+ }
+
+ /* no entry found, so create one */
+ rover = malloc(sizeof(struct routing_entry));
+ if (rover == NULL) {
+ fprintf(stderr,
+ "%s: unable to save source routing information\n",
+ __FILE__);
+ return;
+ }
+
+ memcpy(rover->addr, saddr, sizeof(rover->addr));
+ memcpy(rover->iface, interface->name, 5);
+ rover->access_time = now.tv_sec;
+ if (trh->saddr[0] & TR_RII) {
+ if (((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) {
+ rcf = ntohs(trh->rcf);
+ rcf &= ~TR_RCF_BROADCAST_MASK;
+ memcpy(rover->rseg, trh->rseg, sizeof(rover->rseg));
+ }
+ rover->rcf = rcf;
+ }
+
+ /* insert into list */
+ rover->next = routing_info;
+ routing_info = rover;
+
+ return;
+}
+
+/*
+ * get rid of old routes
+ */
+static void expire_routes()
+{
+ struct routing_entry *rover;
+ struct routing_entry **prover = &routing_info;
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
+
+ while((rover = *prover) != NULL) {
+ if ((now.tv_sec - rover->access_time) > routing_timeout) {
+ *prover = rover->next;
+ free(rover);
+ } else
+ prover = &rover->next;
+ }
+
+ /* Reset the timer */
+ routing_timer.tv_sec = now.tv_sec + routing_timeout;
+ routing_timer.tv_usec = now.tv_usec;
+}
+
+#endif