summaryrefslogtreecommitdiff
path: root/common/dispatch.c
diff options
context:
space:
mode:
authorTed Lemon <source@isc.org>1997-03-06 06:52:30 +0000
committerTed Lemon <source@isc.org>1997-03-06 06:52:30 +0000
commite4749e754c63b7828130b9c3bc5d95736439feb7 (patch)
tree8578e3828eb2c4fa8ff6d3e2692775b49531c95f /common/dispatch.c
parentdd5804ad620a2ca0b8eeb2eae91bfd335bbf6398 (diff)
downloadisc-dhcp-e4749e754c63b7828130b9c3bc5d95736439feb7.tar.gz
Make dispatch() run through a list of protocol structures to select against, rather than running through the interface list and then special casing other stuff. This simplifies things substantially. add_protocol() function allows new protocols to be selected against. Timeouts now pass a void * instead of a struct interface_info *. Move do_packet into options.c so that options.c isn't pulled into dhcrelay.
Diffstat (limited to 'common/dispatch.c')
-rw-r--r--common/dispatch.c164
1 files changed, 71 insertions, 93 deletions
diff --git a/common/dispatch.c b/common/dispatch.c
index 2674fb62..3ae4c012 100644
--- a/common/dispatch.c
+++ b/common/dispatch.c
@@ -42,18 +42,22 @@
#ifndef lint
static char copyright[] =
-"$Id: dispatch.c,v 1.35 1997/03/05 08:39:38 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+"$Id: dispatch.c,v 1.36 1997/03/06 06:52:30 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
#include <sys/ioctl.h>
struct interface_info *interfaces, *dummy_interfaces;
+struct protocol *protocols;
struct timeout *timeouts;
static struct timeout *free_timeouts;
static int interfaces_invalidated;
+void (*bootp_packet_handler) PROTO ((struct interface_info *,
+ unsigned char *, int, unsigned short,
+ struct iaddr, struct hardware *));
-static void got_one PROTO ((struct interface_info *, int));
+static void got_one PROTO ((struct protocol *));
/* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces.
For each interface that's of type INET and not the loopback interface,
@@ -145,7 +149,7 @@ void discover_interfaces (state)
allocate one. */
if (!tmp) {
tmp = ((struct interface_info *)
- dmalloc (sizeof *tmp, "get_interface_list"));
+ dmalloc (sizeof *tmp, "discover_interfaces"));
if (!tmp)
error ("Insufficient memory to %s %s",
"record interface", ifp -> ifr_name);
@@ -333,6 +337,10 @@ void discover_interfaces (state)
if_register_send (tmp);
}
+ /* Now register all the remaining interfaces as protocols. */
+ for (tmp = interfaces; tmp; tmp = tmp -> next)
+ add_protocol (tmp -> name, tmp -> rfdesc, got_one, tmp);
+
close (sock);
#ifdef USE_FALLBACK
@@ -340,6 +348,8 @@ void discover_interfaces (state)
fallback_interface.shared_network = &fallback_network;
fallback_network.name = "fallback-net";
if_register_fallback (&fallback_interface);
+ add_protocol ("fallback", fallback_interface.wfdesc,
+ fallback_discard, &fallback_interface);
#endif
}
@@ -371,10 +381,9 @@ void reinitialize_interfaces ()
wouldn't do for SysV to make networking *easy*, would it? Rant,
rant... */
-void dispatch (parse)
- int parse;
+void dispatch ()
{
- struct interface_info *l;
+ struct protocol *l;
int nfds = 0;
struct pollfd *fds;
int count;
@@ -382,7 +391,7 @@ void dispatch (parse)
int to_msec;
nfds = 0;
- for (l = interfaces; l; l = l -> next) {
+ for (l = protocols; l; l = l -> next) {
++nfds;
}
#ifdef USE_FALLBACK
@@ -423,20 +432,13 @@ void dispatch (parse)
/* Set up the descriptors to be polled. */
i = 0;
- for (l = interfaces; l; l = l -> next) {
- fds [i].fd = l -> rfdesc;
+ for (l = protocols; l; l = l -> next) {
+ fds [i].fd = l -> fd;
fds [i].events = POLLIN;
fds [i].revents = 0;
++i;
}
-#ifdef USE_FALLBACK
- fds [i].fd = fallback_interface.wfdesc;
- fds [i].events = POLLIN;
- fds [i].revents = 0;
- ++i;
-#endif
-
/* Wait for a packet or a timeout... XXX */
count = poll (fds, nfds, to_msec);
@@ -448,19 +450,16 @@ void dispatch (parse)
error ("poll: %m");
i = 0;
- for (l = interfaces; l; l = l -> next) {
+ for (l = protocols; l; l = l -> next) {
if ((fds [i].revents & POLLIN)) {
fds [i].revents = 0;
- got_one (l, parse);
+ if (l -> handler)
+ (*(l -> handler)) (l);
if (interfaces_invalidated)
break;
}
++i;
}
-#ifdef USE_FALLBACK
- if ((fds [i].revents & POLLIN) && !interfaces_invalidated)
- fallback_discard (&fallback_interface);
-#endif
interfaces_invalidated = 0;
} while (1);
}
@@ -470,11 +469,10 @@ void dispatch (parse)
addressing information from it, and then call do_packet to try to
do something with it. */
-void dispatch (parse)
- int parse;
+void dispatch ()
{
fd_set r, w, x;
- struct interface_info *l;
+ struct protocol *l;
int max = 0;
int count;
struct timeval tv, *tvp;
@@ -492,7 +490,7 @@ void dispatch (parse)
if (timeouts -> when <= cur_time) {
t = timeouts;
timeouts = timeouts -> next;
- (*(t -> func)) (t -> interface);
+ (*(t -> func)) (t -> what);
t -> next = free_timeouts;
free_timeouts = t;
goto another;
@@ -506,17 +504,12 @@ void dispatch (parse)
/* Set up the read mask. */
FD_ZERO (&r);
- for (l = interfaces; l; l = l -> next) {
- FD_SET (l -> rfdesc, &r);
- FD_SET (l -> rfdesc, &x);
- if (l -> rfdesc > max)
- max = l -> rfdesc;
+ for (l = protocols; l; l = l -> next) {
+ FD_SET (l -> fd, &r);
+ FD_SET (l -> fd, &x);
+ if (l -> fd > max)
+ max = l -> fd;
}
-#ifdef USE_FALLBACK
- FD_SET (fallback_interface.wfdesc, &r);
- if (fallback_interface.wfdesc > max)
- max = fallback_interface.wfdesc;
-#endif
/* Wait for a packet or a timeout... XXX */
count = select (max + 1, &r, &w, &x, tvp);
@@ -528,26 +521,21 @@ void dispatch (parse)
if (count < 0)
error ("select: %m");
- for (l = interfaces; l; l = l -> next) {
- if (!FD_ISSET (l -> rfdesc, &r))
+ for (l = protocols; l; l = l -> next) {
+ if (!FD_ISSET (l -> fd, &r))
continue;
- got_one (l, parse);
+ if (l -> handler)
+ (*(l -> handler)) (l);
if (interfaces_invalidated)
break;
}
-#ifdef USE_FALLBACK
- if (FD_ISSET (fallback_interface.wfdesc, &r) &&
- !interfaces_invalidated)
- fallback_discard (&fallback_interface);
-#endif
interfaces_invalidated = 0;
} while (1);
}
#endif /* USE_POLL */
-static void got_one (l, parse)
- struct interface_info *l;
- int parse;
+static void got_one (l)
+ struct protocol *l;
{
struct sockaddr_in from;
struct hardware hfrom;
@@ -556,54 +544,23 @@ static void got_one (l, parse)
static unsigned char packbuf [4095]; /* Packet input buffer.
Must be as large as largest
possible MTU. */
+ struct interface_info *ip = l -> local;
- if ((result = receive_packet (l, packbuf, sizeof packbuf,
+ if ((result = receive_packet (ip, packbuf, sizeof packbuf,
&from, &hfrom)) < 0) {
- warn ("receive_packet failed on %s: %m", l -> name);
+ warn ("receive_packet failed on %s: %m", ip -> name);
return;
}
if (result == 0)
return;
- if (parse) {
+ if (bootp_packet_handler) {
ifrom.len = 4;
memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len);
-
- do_packet (l, packbuf, result,
- from.sin_port, ifrom, &hfrom);
- } else
- relay (l, (struct dhcp_packet *)packbuf, result);
-}
-void do_packet (interface, packbuf, len, from_port, from, hfrom)
- struct interface_info *interface;
- unsigned char *packbuf;
- int len;
- unsigned short from_port;
- struct iaddr from;
- struct hardware *hfrom;
-{
- struct packet tp;
- struct dhcp_packet tdp;
-
- memcpy (&tdp, packbuf, len);
- memset (&tp, 0, sizeof tp);
- tp.raw = &tdp;
- tp.packet_length = len;
- tp.client_port = from_port;
- tp.client_addr = from;
- tp.interface = interface;
- tp.haddr = hfrom;
-
- parse_options (&tp);
- if (tp.options_valid &&
- tp.options [DHO_DHCP_MESSAGE_TYPE].data)
- tp.packet_type =
- tp.options [DHO_DHCP_MESSAGE_TYPE].data [0];
- if (tp.packet_type)
- dhcp (&tp);
- else if (tdp.op == BOOTREQUEST)
- bootp (&tp);
+ (*bootp_packet_handler) (ip, packbuf, result,
+ from.sin_port, ifrom, &hfrom);
+ }
}
int locate_network (packet)
@@ -632,15 +589,15 @@ int locate_network (packet)
void add_timeout (when, where, what)
TIME when;
- void (*where) PROTO ((struct interface_info *));
- struct interface_info *what;
+ void (*where) PROTO ((void *));
+ void *what;
{
struct timeout *t, *q;
/* See if this timeout supersedes an existing timeout. */
t = (struct timeout *)0;
for (q = timeouts; q; q = q -> next) {
- if (q -> func == where && q -> interface == what) {
+ if (q -> func == where && q -> what == what) {
if (t)
t -> next = q -> next;
else
@@ -657,13 +614,13 @@ void add_timeout (when, where, what)
q = free_timeouts;
free_timeouts = q -> next;
q -> func = where;
- q -> interface = what;
+ q -> what = what;
} else {
q = (struct timeout *)malloc (sizeof (struct timeout));
if (!q)
error ("Can't allocate timeout structure!");
q -> func = where;
- q -> interface = what;
+ q -> what = what;
}
}
@@ -693,15 +650,15 @@ void add_timeout (when, where, what)
}
void cancel_timeout (where, what)
- void (*where) PROTO ((struct interface_info *));
- struct interface_info *what;
+ void (*where) PROTO ((void *));
+ void *what;
{
struct timeout *t, *q;
/* Look for this timeout on the list, and unlink it if we find it. */
t = (struct timeout *)0;
for (q = timeouts; q; q = q -> next) {
- if (q -> func == where && q -> interface == what) {
+ if (q -> func == where && q -> what == what) {
if (t)
t -> next = q -> next;
else
@@ -717,3 +674,24 @@ void cancel_timeout (where, what)
free_timeouts = q;
}
}
+
+/* Add a protocol to the list of protocols... */
+void add_protocol (name, fd, handler, local)
+ char *name;
+ int fd;
+ void (*handler) (struct protocol *);
+ void *local;
+{
+ struct protocol *p;
+
+ p = (struct protocol *)malloc (sizeof *p);
+ if (!p)
+ error ("can't allocate protocol struct for %s", name);
+
+ p -> fd = fd;
+ p -> handler = handler;
+ p -> local = local;
+
+ p -> next = protocols;
+ protocols = p;
+}