mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-09-01 14:55:30 +00:00
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.
This commit is contained in:
@@ -42,18 +42,22 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
struct interface_info *interfaces, *dummy_interfaces;
|
struct interface_info *interfaces, *dummy_interfaces;
|
||||||
|
struct protocol *protocols;
|
||||||
struct timeout *timeouts;
|
struct timeout *timeouts;
|
||||||
static struct timeout *free_timeouts;
|
static struct timeout *free_timeouts;
|
||||||
static int interfaces_invalidated;
|
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.
|
/* 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,
|
For each interface that's of type INET and not the loopback interface,
|
||||||
@@ -145,7 +149,7 @@ void discover_interfaces (state)
|
|||||||
allocate one. */
|
allocate one. */
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
tmp = ((struct interface_info *)
|
tmp = ((struct interface_info *)
|
||||||
dmalloc (sizeof *tmp, "get_interface_list"));
|
dmalloc (sizeof *tmp, "discover_interfaces"));
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
error ("Insufficient memory to %s %s",
|
error ("Insufficient memory to %s %s",
|
||||||
"record interface", ifp -> ifr_name);
|
"record interface", ifp -> ifr_name);
|
||||||
@@ -333,6 +337,10 @@ void discover_interfaces (state)
|
|||||||
if_register_send (tmp);
|
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);
|
close (sock);
|
||||||
|
|
||||||
#ifdef USE_FALLBACK
|
#ifdef USE_FALLBACK
|
||||||
@@ -340,6 +348,8 @@ void discover_interfaces (state)
|
|||||||
fallback_interface.shared_network = &fallback_network;
|
fallback_interface.shared_network = &fallback_network;
|
||||||
fallback_network.name = "fallback-net";
|
fallback_network.name = "fallback-net";
|
||||||
if_register_fallback (&fallback_interface);
|
if_register_fallback (&fallback_interface);
|
||||||
|
add_protocol ("fallback", fallback_interface.wfdesc,
|
||||||
|
fallback_discard, &fallback_interface);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,10 +381,9 @@ void reinitialize_interfaces ()
|
|||||||
wouldn't do for SysV to make networking *easy*, would it? Rant,
|
wouldn't do for SysV to make networking *easy*, would it? Rant,
|
||||||
rant... */
|
rant... */
|
||||||
|
|
||||||
void dispatch (parse)
|
void dispatch ()
|
||||||
int parse;
|
|
||||||
{
|
{
|
||||||
struct interface_info *l;
|
struct protocol *l;
|
||||||
int nfds = 0;
|
int nfds = 0;
|
||||||
struct pollfd *fds;
|
struct pollfd *fds;
|
||||||
int count;
|
int count;
|
||||||
@@ -382,7 +391,7 @@ void dispatch (parse)
|
|||||||
int to_msec;
|
int to_msec;
|
||||||
|
|
||||||
nfds = 0;
|
nfds = 0;
|
||||||
for (l = interfaces; l; l = l -> next) {
|
for (l = protocols; l; l = l -> next) {
|
||||||
++nfds;
|
++nfds;
|
||||||
}
|
}
|
||||||
#ifdef USE_FALLBACK
|
#ifdef USE_FALLBACK
|
||||||
@@ -423,20 +432,13 @@ void dispatch (parse)
|
|||||||
|
|
||||||
/* Set up the descriptors to be polled. */
|
/* Set up the descriptors to be polled. */
|
||||||
i = 0;
|
i = 0;
|
||||||
for (l = interfaces; l; l = l -> next) {
|
for (l = protocols; l; l = l -> next) {
|
||||||
fds [i].fd = l -> rfdesc;
|
fds [i].fd = l -> fd;
|
||||||
fds [i].events = POLLIN;
|
fds [i].events = POLLIN;
|
||||||
fds [i].revents = 0;
|
fds [i].revents = 0;
|
||||||
++i;
|
++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 */
|
/* Wait for a packet or a timeout... XXX */
|
||||||
count = poll (fds, nfds, to_msec);
|
count = poll (fds, nfds, to_msec);
|
||||||
|
|
||||||
@@ -448,19 +450,16 @@ void dispatch (parse)
|
|||||||
error ("poll: %m");
|
error ("poll: %m");
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
for (l = interfaces; l; l = l -> next) {
|
for (l = protocols; l; l = l -> next) {
|
||||||
if ((fds [i].revents & POLLIN)) {
|
if ((fds [i].revents & POLLIN)) {
|
||||||
fds [i].revents = 0;
|
fds [i].revents = 0;
|
||||||
got_one (l, parse);
|
if (l -> handler)
|
||||||
|
(*(l -> handler)) (l);
|
||||||
if (interfaces_invalidated)
|
if (interfaces_invalidated)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
#ifdef USE_FALLBACK
|
|
||||||
if ((fds [i].revents & POLLIN) && !interfaces_invalidated)
|
|
||||||
fallback_discard (&fallback_interface);
|
|
||||||
#endif
|
|
||||||
interfaces_invalidated = 0;
|
interfaces_invalidated = 0;
|
||||||
} while (1);
|
} while (1);
|
||||||
}
|
}
|
||||||
@@ -470,11 +469,10 @@ void dispatch (parse)
|
|||||||
addressing information from it, and then call do_packet to try to
|
addressing information from it, and then call do_packet to try to
|
||||||
do something with it. */
|
do something with it. */
|
||||||
|
|
||||||
void dispatch (parse)
|
void dispatch ()
|
||||||
int parse;
|
|
||||||
{
|
{
|
||||||
fd_set r, w, x;
|
fd_set r, w, x;
|
||||||
struct interface_info *l;
|
struct protocol *l;
|
||||||
int max = 0;
|
int max = 0;
|
||||||
int count;
|
int count;
|
||||||
struct timeval tv, *tvp;
|
struct timeval tv, *tvp;
|
||||||
@@ -492,7 +490,7 @@ void dispatch (parse)
|
|||||||
if (timeouts -> when <= cur_time) {
|
if (timeouts -> when <= cur_time) {
|
||||||
t = timeouts;
|
t = timeouts;
|
||||||
timeouts = timeouts -> next;
|
timeouts = timeouts -> next;
|
||||||
(*(t -> func)) (t -> interface);
|
(*(t -> func)) (t -> what);
|
||||||
t -> next = free_timeouts;
|
t -> next = free_timeouts;
|
||||||
free_timeouts = t;
|
free_timeouts = t;
|
||||||
goto another;
|
goto another;
|
||||||
@@ -506,17 +504,12 @@ void dispatch (parse)
|
|||||||
/* Set up the read mask. */
|
/* Set up the read mask. */
|
||||||
FD_ZERO (&r);
|
FD_ZERO (&r);
|
||||||
|
|
||||||
for (l = interfaces; l; l = l -> next) {
|
for (l = protocols; l; l = l -> next) {
|
||||||
FD_SET (l -> rfdesc, &r);
|
FD_SET (l -> fd, &r);
|
||||||
FD_SET (l -> rfdesc, &x);
|
FD_SET (l -> fd, &x);
|
||||||
if (l -> rfdesc > max)
|
if (l -> fd > max)
|
||||||
max = l -> rfdesc;
|
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 */
|
/* Wait for a packet or a timeout... XXX */
|
||||||
count = select (max + 1, &r, &w, &x, tvp);
|
count = select (max + 1, &r, &w, &x, tvp);
|
||||||
@@ -528,26 +521,21 @@ void dispatch (parse)
|
|||||||
if (count < 0)
|
if (count < 0)
|
||||||
error ("select: %m");
|
error ("select: %m");
|
||||||
|
|
||||||
for (l = interfaces; l; l = l -> next) {
|
for (l = protocols; l; l = l -> next) {
|
||||||
if (!FD_ISSET (l -> rfdesc, &r))
|
if (!FD_ISSET (l -> fd, &r))
|
||||||
continue;
|
continue;
|
||||||
got_one (l, parse);
|
if (l -> handler)
|
||||||
|
(*(l -> handler)) (l);
|
||||||
if (interfaces_invalidated)
|
if (interfaces_invalidated)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef USE_FALLBACK
|
|
||||||
if (FD_ISSET (fallback_interface.wfdesc, &r) &&
|
|
||||||
!interfaces_invalidated)
|
|
||||||
fallback_discard (&fallback_interface);
|
|
||||||
#endif
|
|
||||||
interfaces_invalidated = 0;
|
interfaces_invalidated = 0;
|
||||||
} while (1);
|
} while (1);
|
||||||
}
|
}
|
||||||
#endif /* USE_POLL */
|
#endif /* USE_POLL */
|
||||||
|
|
||||||
static void got_one (l, parse)
|
static void got_one (l)
|
||||||
struct interface_info *l;
|
struct protocol *l;
|
||||||
int parse;
|
|
||||||
{
|
{
|
||||||
struct sockaddr_in from;
|
struct sockaddr_in from;
|
||||||
struct hardware hfrom;
|
struct hardware hfrom;
|
||||||
@@ -556,54 +544,23 @@ static void got_one (l, parse)
|
|||||||
static unsigned char packbuf [4095]; /* Packet input buffer.
|
static unsigned char packbuf [4095]; /* Packet input buffer.
|
||||||
Must be as large as largest
|
Must be as large as largest
|
||||||
possible MTU. */
|
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) {
|
&from, &hfrom)) < 0) {
|
||||||
warn ("receive_packet failed on %s: %m", l -> name);
|
warn ("receive_packet failed on %s: %m", ip -> name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (parse) {
|
if (bootp_packet_handler) {
|
||||||
ifrom.len = 4;
|
ifrom.len = 4;
|
||||||
memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len);
|
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)
|
(*bootp_packet_handler) (ip, packbuf, result,
|
||||||
struct interface_info *interface;
|
from.sin_port, ifrom, &hfrom);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int locate_network (packet)
|
int locate_network (packet)
|
||||||
@@ -632,15 +589,15 @@ int locate_network (packet)
|
|||||||
|
|
||||||
void add_timeout (when, where, what)
|
void add_timeout (when, where, what)
|
||||||
TIME when;
|
TIME when;
|
||||||
void (*where) PROTO ((struct interface_info *));
|
void (*where) PROTO ((void *));
|
||||||
struct interface_info *what;
|
void *what;
|
||||||
{
|
{
|
||||||
struct timeout *t, *q;
|
struct timeout *t, *q;
|
||||||
|
|
||||||
/* See if this timeout supersedes an existing timeout. */
|
/* See if this timeout supersedes an existing timeout. */
|
||||||
t = (struct timeout *)0;
|
t = (struct timeout *)0;
|
||||||
for (q = timeouts; q; q = q -> next) {
|
for (q = timeouts; q; q = q -> next) {
|
||||||
if (q -> func == where && q -> interface == what) {
|
if (q -> func == where && q -> what == what) {
|
||||||
if (t)
|
if (t)
|
||||||
t -> next = q -> next;
|
t -> next = q -> next;
|
||||||
else
|
else
|
||||||
@@ -657,13 +614,13 @@ void add_timeout (when, where, what)
|
|||||||
q = free_timeouts;
|
q = free_timeouts;
|
||||||
free_timeouts = q -> next;
|
free_timeouts = q -> next;
|
||||||
q -> func = where;
|
q -> func = where;
|
||||||
q -> interface = what;
|
q -> what = what;
|
||||||
} else {
|
} else {
|
||||||
q = (struct timeout *)malloc (sizeof (struct timeout));
|
q = (struct timeout *)malloc (sizeof (struct timeout));
|
||||||
if (!q)
|
if (!q)
|
||||||
error ("Can't allocate timeout structure!");
|
error ("Can't allocate timeout structure!");
|
||||||
q -> func = where;
|
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 cancel_timeout (where, what)
|
||||||
void (*where) PROTO ((struct interface_info *));
|
void (*where) PROTO ((void *));
|
||||||
struct interface_info *what;
|
void *what;
|
||||||
{
|
{
|
||||||
struct timeout *t, *q;
|
struct timeout *t, *q;
|
||||||
|
|
||||||
/* Look for this timeout on the list, and unlink it if we find it. */
|
/* Look for this timeout on the list, and unlink it if we find it. */
|
||||||
t = (struct timeout *)0;
|
t = (struct timeout *)0;
|
||||||
for (q = timeouts; q; q = q -> next) {
|
for (q = timeouts; q; q = q -> next) {
|
||||||
if (q -> func == where && q -> interface == what) {
|
if (q -> func == where && q -> what == what) {
|
||||||
if (t)
|
if (t)
|
||||||
t -> next = q -> next;
|
t -> next = q -> next;
|
||||||
else
|
else
|
||||||
@@ -717,3 +674,24 @@ void cancel_timeout (where, what)
|
|||||||
free_timeouts = q;
|
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;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user