2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-03 07:45:20 +00:00

Initial merge of Poger dhclient and linux hacks

This commit is contained in:
Ted Lemon
1997-01-02 12:00:19 +00:00
parent b289b0107c
commit 469cf3a4b5
20 changed files with 2206 additions and 372 deletions

View File

@@ -185,10 +185,10 @@ VARDB = /var/db
CSRC = options.c errwarn.c convert.c \ CSRC = options.c errwarn.c convert.c \
tree.c memory.c alloc.c print.c hash.c tables.c inet.c \ tree.c memory.c alloc.c print.c hash.c tables.c inet.c \
dispatch.c bpf.c packet.c raw.c nit.c socket.c dispatch.c bpf.c packet.c raw.c nit.c socket.c route.c
COBJ = options.o errwarn.o convert.o \ COBJ = options.o errwarn.o convert.o \
tree.o memory.o alloc.o print.o hash.o tables.o inet.o \ tree.o memory.o alloc.o print.o hash.o tables.o inet.o \
dispatch.o bpf.o packet.o raw.o nit.o socket.o dispatch.o bpf.o packet.o raw.o nit.o socket.o route.o
XOBJ = dhcpxlt.o xconflex.o XOBJ = dhcpxlt.o xconflex.o
SRCS = dhcpd.c dhcp.c bootp.c conflex.c confpars.c db.c SRCS = dhcpd.c dhcp.c bootp.c conflex.c confpars.c db.c
OBJS = dhcpd.o dhcp.o bootp.o conflex.o confpars.o db.o OBJS = dhcpd.o dhcp.o bootp.o conflex.o confpars.o db.o

24
bpf.c
View File

@@ -42,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: bpf.c,v 1.13 1996/09/02 21:14:58 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; "$Id: bpf.c,v 1.14 1997/01/02 12:00:14 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"
@@ -368,3 +368,25 @@ size_t receive_packet (interface, buf, len, from, hfrom)
return 0; return 0;
} }
#endif #endif
#if defined (USE_BPF_SEND)
void if_enable (interface)
struct interface_info *interface;
{
struct ifreq ifr;
int sock;
if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
error ("Can't create addrlist socket");
/* Bring the interface down and then up again to clear
* all its routes. */
strncpy(ifr.ifr_name, interface -> name, IFNAMSIZ);
if (ioctl (sock, SIOCGIFFLAGS, &ifr) < 0)
error ("SIOCGIFFLAGS %s: %m", interface -> name);
ifr.ifr_flags |= (IFF_UP|IFF_RUNNING);
if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
error ("SIOCSIFFLAGS %s: %m", interface -> name);
}
#endif

View File

@@ -60,6 +60,9 @@ typedef unsigned long u_int32_t;
extern int h_errno; extern int h_errno;
#include <net/if.h> #include <net/if.h>
#include <net/route.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <sys/time.h> /* gettimeofday()*/ #include <sys/time.h> /* gettimeofday()*/
#include <linux/time.h> /* also necessary */ #include <linux/time.h> /* also necessary */

View File

@@ -52,6 +52,10 @@ extern int h_errno;
#include <net/if.h> #include <net/if.h>
#include <net/if_dl.h> #include <net/if_dl.h>
#include <net/route.h>
#include <sys/sockio.h>
#define ifr_netmask ifr_addr
/* Varargs stuff... */ /* Varargs stuff... */
#include <stdarg.h> #include <stdarg.h>

File diff suppressed because it is too large Load Diff

View File

@@ -42,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: bpf.c,v 1.13 1996/09/02 21:14:58 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; "$Id: bpf.c,v 1.14 1997/01/02 12:00:14 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"
@@ -368,3 +368,25 @@ size_t receive_packet (interface, buf, len, from, hfrom)
return 0; return 0;
} }
#endif #endif
#if defined (USE_BPF_SEND)
void if_enable (interface)
struct interface_info *interface;
{
struct ifreq ifr;
int sock;
if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
error ("Can't create addrlist socket");
/* Bring the interface down and then up again to clear
* all its routes. */
strncpy(ifr.ifr_name, interface -> name, IFNAMSIZ);
if (ioctl (sock, SIOCGIFFLAGS, &ifr) < 0)
error ("SIOCGIFFLAGS %s: %m", interface -> name);
ifr.ifr_flags |= (IFF_UP|IFF_RUNNING);
if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
error ("SIOCSIFFLAGS %s: %m", interface -> name);
}
#endif

View File

@@ -42,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: dispatch.c,v 1.27 1996/11/08 20:06:29 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; "$Id: dispatch.c,v 1.28 1997/01/02 12:00:16 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"
@@ -162,6 +162,44 @@ void discover_interfaces (serverP)
if (ifp -> ifr_addr.sa_family == AF_INET) { if (ifp -> ifr_addr.sa_family == AF_INET) {
struct iaddr addr; struct iaddr addr;
#if defined (SIOCGIFHWADDR) && !defined (AF_LINK)
struct ifreq ifr;
struct sockaddr sa;
int b, sk;
/* Read the hardware address from this interface. */
ifr = *ifp;
if (ioctl (sock, SIOCGIFHWADDR, &ifr) < 0)
error ("Can't get hardware address for %s: %m",
ifr.ifr_name);
sa = *(struct sockaddr *)&ifr.ifr_hwaddr;
switch (sa.sa_family) {
case ARPHRD_LOOPBACK:
/* ignore loopback interface */
break;
case ARPHRD_ETHER:
tmp -> hw_address.hlen = 6;
tmp -> hw_address.htype = ARPHRD_ETHER;
memcpy (tmp -> hw_address.haddr,
sa.sa_data, 6);
break;
case ARPHRD_METRICOM:
tmp -> hw_address.hlen = 6;
tmp -> hw_address.htype = ARPHRD_METRICOM;
memcpy (tmp -> hw_address.haddr,
sa.sa_data, 6);
break;
default:
error ("%s: unknown hardware address type %d",
ifr.ifr_name, sa.sa_family);
}
#endif /* defined (SIOCGIFHWADDR) && !defined (AF_LINK) */
/* Get a pointer to the address... */ /* Get a pointer to the address... */
memcpy (&foo, &ifp -> ifr_addr, memcpy (&foo, &ifp -> ifr_addr,
sizeof ifp -> ifr_addr); sizeof ifp -> ifr_addr);

View File

@@ -42,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: nit.c,v 1.9 1996/09/05 23:56:52 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium. All rights reserved.\n"; "$Id: nit.c,v 1.10 1997/01/02 12:00:17 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -329,3 +329,21 @@ size_t receive_packet (interface, buf, len, from, hfrom)
return length; return length;
} }
#endif #endif
#if defined (USE_NIT_SEND)
void if_enable (interface)
struct interface_info *interface;
{
struct ifreq ifr;
/* Bring the interface down and then up again to clear
* all its routes. */
strncpy(ifr.ifr_name, interface -> name, IFNAMSIZ);
if (ioctl(interface -> rfdesc, SIOCGIFFLAGS, &ifr) < 0)
error ("SIOCGIFFLAGS %s: %m", interface -> name);
ifr.ifr_flags |= (IFF_UP|IFF_RUNNING);
if (ioctl(interface -> rfdesc, SIOCSIFFLAGS, &ifr) == -1)
error ("SIOCSIFFLAGS %s: %m", interface -> name);
}
#endif

View File

@@ -40,9 +40,17 @@
* Enterprises, see ``http://www.vix.com''. * Enterprises, see ``http://www.vix.com''.
*/ */
/* SO_BINDTODEVICE support added by Elliot Poger (poger@leland.stanford.edu).
* This sockopt allows a socket to be bound to a particular interface,
* thus enabling the use of DHCPD on a multihomed host.
* If SO_BINDTODEVICE is defined in your system header files, the use of
* this sockopt will be automatically enabled.
* I have implemented it under Linux; other systems should be doable also.
*/
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: socket.c,v 1.16 1996/08/27 09:54:48 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; "$Id: socket.c,v 1.17 1997/01/02 12:00:18 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"
@@ -62,6 +70,8 @@ int if_register_socket (info, interface)
struct sockaddr_in name; struct sockaddr_in name;
int sock; int sock;
int flag; int flag;
#ifndef SO_BINDTODEVICE
static int once = 0; static int once = 0;
/* Make sure only one interface is registered. */ /* Make sure only one interface is registered. */
@@ -72,22 +82,8 @@ int if_register_socket (info, interface)
"you must compile in BPF or NIT support. If neither ", "you must compile in BPF or NIT support. If neither ",
"option is supported on your system, please let us ", "option is supported on your system, please let us ",
"know."); "know.");
once = 1;
/* Technically, we need to know what interface every packet
comes in on, which means that we can only operate on a
machine with a single interface configured. However,
we generally don't expect to get broadcast packets on
point-to-point interfaces, so we can bend the rules a bit
and not count them. This won't allow DHCP-over-PPP,
but it's probably right in a lot of cases, and the issue
will have to be revisited when DHCP-over-PPP support is
done. Currently we determine whether an interface is
point-to-point by seeing if it has a link-level address.
This only works on 4.4BSD and derivative networking. */
#ifdef AF_LINK
if (info -> hw_address.hlen) /* XXX */
#endif #endif
once = 1;
/* Set up the address we're going to bind to. */ /* Set up the address we're going to bind to. */
name.sin_family = AF_INET; name.sin_family = AF_INET;
@@ -111,10 +107,26 @@ int if_register_socket (info, interface)
(char *)&flag, sizeof flag) < 0) (char *)&flag, sizeof flag) < 0)
error ("Can't set SO_BROADCAST option on dhcp socket: %m"); error ("Can't set SO_BROADCAST option on dhcp socket: %m");
#ifndef USE_SOCKET_FALLBACK
/* The following will make all-ones broadcasts go out this interface
* on those platforms which use the standard sockets API (assuming
* the OS-specific routines called by enable_sending() are present
* for this platform). */
if_enable (info);
#endif
/* Bind the socket to this interface's IP address. */ /* Bind the socket to this interface's IP address. */
if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0) if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0)
error ("Can't bind to dhcp address: %m"); error ("Can't bind to dhcp address: %m");
#ifdef SO_BINDTODEVICE
/* Bind this socket to this interface. */
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
(char *)interface, sizeof(*interface)) < 0) {
error("setting SO_BINDTODEVICE");
}
#endif
return sock; return sock;
} }
#endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE */ #endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE */
@@ -197,3 +209,30 @@ size_t fallback_discard (interface)
(struct sockaddr *)&from, &flen); (struct sockaddr *)&from, &flen);
} }
#endif /* USE_SOCKET_RECEIVE */ #endif /* USE_SOCKET_RECEIVE */
#if defined (USE_SOCKET_SEND) && !defined (USE_SOCKET_FALLBACK)
/* If we're using the standard socket API without SO_BINDTODEVICE,
* we need this kludge to force DHCP broadcasts to go out
* this interface, even though it's not available for general
* use until we get a lease!
* This should work _OK_, but it will cause ALL all-ones
* broadcasts on this host to go out this interface--it
* could interfere with other interfaces. And God help you
* if you run this on multiple interfaces simultaneously.
* SO_BINDTODEVICE really is better! */
void if_enable (interface)
struct interface_info *interface;
{
#ifndef SO_BINDTODEVICE
struct in_addr broad_addr;
broad_addr.s_addr = htonl(INADDR_BROADCAST);
/* Delete old routes for broadcast address. */
remove_routes(NULL, &broad_addr);
/* Add a route for broadcast address to this interface. */
/* POTENTIAL PROBLEM: Don't do this to more than one interface! */
add_route_direct(interface, &broad_addr);
#endif
}
#endif

File diff suppressed because it is too large Load Diff

1
dhcp.h
View File

@@ -52,6 +52,7 @@
#define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN) #define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN)
#define BOOTP_MIN_LEN 300 #define BOOTP_MIN_LEN 300
#define DHCP_MIN_LEN 548
struct dhcp_packet { struct dhcp_packet {
u_int8_t op; /* Message opcode/type */ u_int8_t op; /* Message opcode/type */

43
dhcpd.h
View File

@@ -451,6 +451,9 @@ size_t receive_packet PROTO ((struct interface_info *,
unsigned char *, size_t, unsigned char *, size_t,
struct sockaddr_in *, struct hardware *)); struct sockaddr_in *, struct hardware *));
#endif #endif
#if defined (USE_SOCKET_SEND) && !defined (USE_SOCKET_FALLBACK)
void if_enable PROTO ((struct interface_info *));
#endif
/* bpf.c */ /* bpf.c */
#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)
@@ -469,6 +472,9 @@ size_t receive_packet PROTO ((struct interface_info *,
unsigned char *, size_t, unsigned char *, size_t,
struct sockaddr_in *, struct hardware *)); struct sockaddr_in *, struct hardware *));
#endif #endif
#if defined (USE_BPF_SEND)
void if_enable PROTO ((struct interface_info *));
#endif
/* nit.c */ /* nit.c */
#ifdef USE_NIT_SEND #ifdef USE_NIT_SEND
@@ -484,6 +490,9 @@ size_t receive_packet PROTO ((struct interface_info *,
unsigned char *, size_t, unsigned char *, size_t,
struct sockaddr_in *, struct hardware *)); struct sockaddr_in *, struct hardware *));
#endif #endif
#if defined (USE_BPF_SEND)
void if_enable PROTO ((struct interface_info *));
#endif
/* raw.c */ /* raw.c */
#ifdef USE_RAW_SEND #ifdef USE_RAW_SEND
@@ -541,6 +550,27 @@ void dhcpack PROTO ((struct packet *));
void dhcpnak PROTO ((struct packet *)); void dhcpnak PROTO ((struct packet *));
void send_discover PROTO ((struct interface_info *)); void send_discover PROTO ((struct interface_info *));
void send_request PROTO ((struct packet *)); void send_request PROTO ((struct packet *));
void send_release PROTO ((struct packet *));
void dhclient_fail PROTO ((void));
void handle_kill PROTO ((int));
void disable_interface PROTO ((struct interface_info *));
void route_broadcasts PROTO ((struct interface_info *));
void apply_parameters PROTO ((struct interface_info *, struct packet *));
void dhclient_state_machine PROTO ((void));
int state_init PROTO ((void));
int state_selecting PROTO ((void));
int state_requesting PROTO ((void));
int state_bound PROTO ((void));
int state_renewing PROTO ((void));
int state_rebinding PROTO ((void));
TIME abs_time PROTO ((struct packet *, int));
void deep_packet_copy PROTO ((struct packet *, struct packet *));
void read_packet PROTO ((struct interface_info *, struct packet *));
void send_packet_struct PROTO ((struct interface_info *,
u_long, struct packet *));
void make_discover PROTO ((struct interface_info *, struct packet *));
void make_request PROTO ((struct packet *, struct packet *));
void make_release PROTO ((struct packet *, struct packet *));
/* db.c */ /* db.c */
int write_lease PROTO ((struct lease *)); int write_lease PROTO ((struct lease *));
@@ -584,3 +614,16 @@ void convert_address_range PROTO ((FILE *, jrefproto));
void convert_date PROTO ((FILE *, jrefproto, char *)); void convert_date PROTO ((FILE *, jrefproto, char *));
void convert_numeric_aggregate PROTO ((FILE *, jrefproto, int, int, int, int)); void convert_numeric_aggregate PROTO ((FILE *, jrefproto, int, int, int, int));
void indent PROTO ((int)); void indent PROTO ((int));
/* route.c */
void add_route_direct PROTO ((struct interface_info *, struct in_addr));
void add_route_net PROTO ((struct interface_info *, struct in_addr,
struct in_addr));
void add_route_default_gateway PROTO ((struct interface_info *,
struct in_addr));
void remove_routes PROTO ((struct in_addr));
void remove_if_route PROTO ((struct interface_info *, struct in_addr));
void remove_all_if_routes PROTO ((struct interface_info *));
void set_netmask PROTO ((struct interface_info *, struct in_addr));
void set_broadcast_addr PROTO ((struct interface_info *, struct in_addr));
void set_ip_address PROTO ((struct interface_info *, struct in_addr));

View File

@@ -42,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: dispatch.c,v 1.27 1996/11/08 20:06:29 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; "$Id: dispatch.c,v 1.28 1997/01/02 12:00:16 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"
@@ -162,6 +162,44 @@ void discover_interfaces (serverP)
if (ifp -> ifr_addr.sa_family == AF_INET) { if (ifp -> ifr_addr.sa_family == AF_INET) {
struct iaddr addr; struct iaddr addr;
#if defined (SIOCGIFHWADDR) && !defined (AF_LINK)
struct ifreq ifr;
struct sockaddr sa;
int b, sk;
/* Read the hardware address from this interface. */
ifr = *ifp;
if (ioctl (sock, SIOCGIFHWADDR, &ifr) < 0)
error ("Can't get hardware address for %s: %m",
ifr.ifr_name);
sa = *(struct sockaddr *)&ifr.ifr_hwaddr;
switch (sa.sa_family) {
case ARPHRD_LOOPBACK:
/* ignore loopback interface */
break;
case ARPHRD_ETHER:
tmp -> hw_address.hlen = 6;
tmp -> hw_address.htype = ARPHRD_ETHER;
memcpy (tmp -> hw_address.haddr,
sa.sa_data, 6);
break;
case ARPHRD_METRICOM:
tmp -> hw_address.hlen = 6;
tmp -> hw_address.htype = ARPHRD_METRICOM;
memcpy (tmp -> hw_address.haddr,
sa.sa_data, 6);
break;
default:
error ("%s: unknown hardware address type %d",
ifr.ifr_name, sa.sa_family);
}
#endif /* defined (SIOCGIFHWADDR) && !defined (AF_LINK) */
/* Get a pointer to the address... */ /* Get a pointer to the address... */
memcpy (&foo, &ifp -> ifr_addr, memcpy (&foo, &ifp -> ifr_addr,
sizeof ifp -> ifr_addr); sizeof ifp -> ifr_addr);

View File

@@ -60,6 +60,9 @@ typedef unsigned long u_int32_t;
extern int h_errno; extern int h_errno;
#include <net/if.h> #include <net/if.h>
#include <net/route.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <sys/time.h> /* gettimeofday()*/ #include <sys/time.h> /* gettimeofday()*/
#include <linux/time.h> /* also necessary */ #include <linux/time.h> /* also necessary */

View File

@@ -52,6 +52,10 @@ extern int h_errno;
#include <net/if.h> #include <net/if.h>
#include <net/if_dl.h> #include <net/if_dl.h>
#include <net/route.h>
#include <sys/sockio.h>
#define ifr_netmask ifr_addr
/* Varargs stuff... */ /* Varargs stuff... */
#include <stdarg.h> #include <stdarg.h>

View File

@@ -52,6 +52,7 @@
#define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN) #define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN)
#define BOOTP_MIN_LEN 300 #define BOOTP_MIN_LEN 300
#define DHCP_MIN_LEN 548
struct dhcp_packet { struct dhcp_packet {
u_int8_t op; /* Message opcode/type */ u_int8_t op; /* Message opcode/type */

View File

@@ -451,6 +451,9 @@ size_t receive_packet PROTO ((struct interface_info *,
unsigned char *, size_t, unsigned char *, size_t,
struct sockaddr_in *, struct hardware *)); struct sockaddr_in *, struct hardware *));
#endif #endif
#if defined (USE_SOCKET_SEND) && !defined (USE_SOCKET_FALLBACK)
void if_enable PROTO ((struct interface_info *));
#endif
/* bpf.c */ /* bpf.c */
#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)
@@ -469,6 +472,9 @@ size_t receive_packet PROTO ((struct interface_info *,
unsigned char *, size_t, unsigned char *, size_t,
struct sockaddr_in *, struct hardware *)); struct sockaddr_in *, struct hardware *));
#endif #endif
#if defined (USE_BPF_SEND)
void if_enable PROTO ((struct interface_info *));
#endif
/* nit.c */ /* nit.c */
#ifdef USE_NIT_SEND #ifdef USE_NIT_SEND
@@ -484,6 +490,9 @@ size_t receive_packet PROTO ((struct interface_info *,
unsigned char *, size_t, unsigned char *, size_t,
struct sockaddr_in *, struct hardware *)); struct sockaddr_in *, struct hardware *));
#endif #endif
#if defined (USE_BPF_SEND)
void if_enable PROTO ((struct interface_info *));
#endif
/* raw.c */ /* raw.c */
#ifdef USE_RAW_SEND #ifdef USE_RAW_SEND
@@ -541,6 +550,27 @@ void dhcpack PROTO ((struct packet *));
void dhcpnak PROTO ((struct packet *)); void dhcpnak PROTO ((struct packet *));
void send_discover PROTO ((struct interface_info *)); void send_discover PROTO ((struct interface_info *));
void send_request PROTO ((struct packet *)); void send_request PROTO ((struct packet *));
void send_release PROTO ((struct packet *));
void dhclient_fail PROTO ((void));
void handle_kill PROTO ((int));
void disable_interface PROTO ((struct interface_info *));
void route_broadcasts PROTO ((struct interface_info *));
void apply_parameters PROTO ((struct interface_info *, struct packet *));
void dhclient_state_machine PROTO ((void));
int state_init PROTO ((void));
int state_selecting PROTO ((void));
int state_requesting PROTO ((void));
int state_bound PROTO ((void));
int state_renewing PROTO ((void));
int state_rebinding PROTO ((void));
TIME abs_time PROTO ((struct packet *, int));
void deep_packet_copy PROTO ((struct packet *, struct packet *));
void read_packet PROTO ((struct interface_info *, struct packet *));
void send_packet_struct PROTO ((struct interface_info *,
u_long, struct packet *));
void make_discover PROTO ((struct interface_info *, struct packet *));
void make_request PROTO ((struct packet *, struct packet *));
void make_release PROTO ((struct packet *, struct packet *));
/* db.c */ /* db.c */
int write_lease PROTO ((struct lease *)); int write_lease PROTO ((struct lease *));
@@ -584,3 +614,16 @@ void convert_address_range PROTO ((FILE *, jrefproto));
void convert_date PROTO ((FILE *, jrefproto, char *)); void convert_date PROTO ((FILE *, jrefproto, char *));
void convert_numeric_aggregate PROTO ((FILE *, jrefproto, int, int, int, int)); void convert_numeric_aggregate PROTO ((FILE *, jrefproto, int, int, int, int));
void indent PROTO ((int)); void indent PROTO ((int));
/* route.c */
void add_route_direct PROTO ((struct interface_info *, struct in_addr));
void add_route_net PROTO ((struct interface_info *, struct in_addr,
struct in_addr));
void add_route_default_gateway PROTO ((struct interface_info *,
struct in_addr));
void remove_routes PROTO ((struct in_addr));
void remove_if_route PROTO ((struct interface_info *, struct in_addr));
void remove_all_if_routes PROTO ((struct interface_info *));
void set_netmask PROTO ((struct interface_info *, struct in_addr));
void set_broadcast_addr PROTO ((struct interface_info *, struct in_addr));
void set_ip_address PROTO ((struct interface_info *, struct in_addr));

20
nit.c
View File

@@ -42,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: nit.c,v 1.9 1996/09/05 23:56:52 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium. All rights reserved.\n"; "$Id: nit.c,v 1.10 1997/01/02 12:00:17 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -329,3 +329,21 @@ size_t receive_packet (interface, buf, len, from, hfrom)
return length; return length;
} }
#endif #endif
#if defined (USE_NIT_SEND)
void if_enable (interface)
struct interface_info *interface;
{
struct ifreq ifr;
/* Bring the interface down and then up again to clear
* all its routes. */
strncpy(ifr.ifr_name, interface -> name, IFNAMSIZ);
if (ioctl(interface -> rfdesc, SIOCGIFFLAGS, &ifr) < 0)
error ("SIOCGIFFLAGS %s: %m", interface -> name);
ifr.ifr_flags |= (IFF_UP|IFF_RUNNING);
if (ioctl(interface -> rfdesc, SIOCSIFFLAGS, &ifr) == -1)
error ("SIOCSIFFLAGS %s: %m", interface -> name);
}
#endif

276
route.c
View File

@@ -1,62 +1,234 @@
/* socket.c /* route.c
BSD socket interface code... */
/*
* Copyright (c) 1995, 1996 The Internet Software Consortium.
* All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Routines for updating routing tables and configuring interfaces.
* modification, are permitted provided that the following conditions *
* are met: * Copyright 1996 The Board of Trustees of The Leland Stanford
* Junior University. All Rights Reserved.
* Code originally written by Elliot Poger (poger@leland.stanford.edu).
* *
* 1. Redistributions of source code must retain the above copyright * Permission to use, copy, modify, and distribute this
* notice, this list of conditions and the following disclaimer. * software and its documentation for any purpose and without
* 2. Redistributions in binary form must reproduce the above copyright * fee is hereby granted, provided that the above copyright
* notice, this list of conditions and the following disclaimer in the * notice appear in all copies. Stanford University
* documentation and/or other materials provided with the distribution. * makes no representations about the suitability of this
* 3. Neither the name of The Internet Software Consortium nor the names * software for any purpose. It is provided "as is" without
* of its contributors may be used to endorse or promote products derived * express or implied warranty.
* 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: route.c,v 1.2 1996/08/27 09:53:58 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
#if defined (OLD_ROUTE_HACK) /* Add a route to this destination through this interface. */
#include <net/route.h> void add_route_direct(interface, destination)
struct interface_info *interface;
route_hack (sock) struct in_addr destination;
int sock;
{ {
int rsock = socket (PF_ROUTE, SOCK_RAW, AF_INET); note ("add_route_direct %s: %s",
struct rt_msghdr interface -> name, inet_ntoa (destination));
#if 0
struct in_addr directmask;
if (rsock < 0) directmask.s_addr = htonl (INADDR_BROADCAST); /* this addr only */
error ("Can't make routing socket: %m"); add_route_net(interface, destination, &directmask);
#endif
}
/* Add a route to this subnet through this interface. */
void add_route_net(interface, destination, netmask)
struct interface_info *interface;
struct in_addr destination;
struct in_addr netmask;
{
char nbuf [128];
strncpy (nbuf, inet_ntoa (netmask), sizeof nbuf);
nbuf [(sizeof nbuf) - 1] = 0;
note ("add_route_net %s: %s %s",
interface -> name, inet_ntoa (destination), nbuf);
#if 0
int sock;
struct sockaddr_in *sin;
struct rtentry rt;
memset((char *) &rt, 0, sizeof(struct rtentry));
sin = (struct sockaddr_in *) &rt.rt_dst;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = destination.s_addr;
sin = (struct sockaddr_in *) &rt.rt_genmask;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = netmask.s_addr;
rt.rt_flags = RTF_UP;
rt.rt_dev = interface->name;
if (ioctl(interface -> rfdesc, SIOCADDRT, &rt) < 0)
error ("Can't add route to %s through %s: %m",
inet_ntoa (destination), interface->name);
#endif
}
/* Add a route to the default gateway through this interface. */
void add_route_default_gateway(interface, gateway)
struct interface_info *interface;
struct in_addr gateway;
{
note ("add_route_default_gateway %s: %s",
interface -> name, inet_ntoa (gateway));
#if 0
int sock;
struct sockaddr_in *sin;
struct rtentry rt;
/* Route through the gateway. */
memset((char *) &rt, 0, sizeof(struct rtentry));
sin = (struct sockaddr_in *) &rt.rt_dst;
sin->sin_family = AF_INET;
sin = (struct sockaddr_in *) &rt.rt_gateway;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = gateway.s_addr;
rt.rt_flags = RTF_UP | RTF_GATEWAY;
rt.rt_dev = interface->name;
if (ioctl(interface -> rfdesc, SIOCADDRT, &rt) < 0)
error ("Can't add route to default gateway");
#endif
}
/* Remove all routes matching the specified destination. */
void remove_routes(destination)
struct in_addr destination;
{
note ("remove_routes: %s", inet_ntoa (destination));
#if 0
int sock;
struct ifreq ifr;
struct sockaddr_in *sin;
struct rtentry rt;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
error("Can't open socket to remove routes");
}
/* Remove all routes to this IP destination. */
memset((char *) &rt, 0, sizeof(struct rtentry));
sin = (struct sockaddr_in *) &rt.rt_dst;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = destination->s_addr;
while (ioctl(sock, SIOCDELRT, &rt) >= 0)
;
close(sock);
#endif
}
/* Remove routes on the specified interface matching the specified
destination. */
void remove_if_route (interface, destination)
struct interface_info *interface;
struct in_addr destination;
{
note ("remove_if_routes %s: %s",
interface -> name, inet_ntoa (destination));
#if 0
int sock;
struct ifreq ifr;
struct sockaddr_in *sin;
struct rtentry rt;
/* Remove one specific route. */
/* XXX: does this even work? */
memset((char *) &rt, 0, sizeof(struct rtentry));
sin = (struct sockaddr_in *) &rt.rt_dst;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = destination.s_addr;
rt.rt_dev = interface->name;
if (ioctl(interface -> rfdesc, SIOCDELRT, &rt) == -1)
warn("Error removing route.");
#endif
}
/* Remove all routes on the specified interface. */
void remove_all_if_routes(interface)
struct interface_info *interface;
{
note ("remove_all_if_routes %s", interface -> name);
#if 0
struct ifreq ifr;
/* Bring the interface down and then up again to clear
* all its routes. */
strncpy(ifr.ifr_name, interface->name, IFNAMSIZ);
if (ioctl(interface -> rfdesc, SIOCGIFFLAGS, &ifr) == -1)
error ("SIOCGIFFLAGS %s: %m", interface -> name);
ifr.ifr_flags &= ~(IFF_UP|IFF_RUNNING);
if (ioctl(interface -> rfdesc, SIOCSIFFLAGS, &ifr) == -1)
error ("Can't bring down interface");
strncpy(ifr.ifr_name,interface->name,IFNAMSIZ);
ifr.ifr_flags |= (IFF_UP|IFF_RUNNING);
if (ioctl(interface -> rfdesc, SIOCSIFFLAGS, &ifr) == -1)
error("Can't bring interface back up");
#endif
}
/* Set the netmask (in network byte order!) of this interface. */
void set_netmask(interface, netmask)
struct interface_info *interface;
struct in_addr netmask;
{
note ("set_netmask %s: %s",
interface -> name, inet_ntoa (netmask));
#if 0
int sock;
struct ifreq ifr;
if (ioctl (interface -> rfdesc, SIOCGIFNETMASK, &ifr) == -1)
error ("Can't get old netmask of interface");
(*(struct sockaddr_in *)&ifr.ifr_netmask).sin_addr = netmask;
if (ioctl (interface -> rfdesc, SIOCSIFNETMASK, &ifr) == -1)
error ("Can't set new netmask");
#endif
}
/* Set the broadcast address (in network byte order!) of this interface. */
void set_broadcast_addr(interface, broadcast_addr)
struct interface_info *interface;
struct in_addr broadcast_addr;
{
note ("set_broadcast_addr %s: %s",
interface -> name, inet_ntoa (broadcast_addr));
#if 0
int sock;
struct ifreq ifr;
if (ioctl(interface -> rfdesc, SIOCGIFBRDADDR, &ifr) == -1)
error("Can't get old broadcast address of interface");
(*(struct sockaddr_in *)&ifr.ifr_broadaddr).sin_addr = broadcast_addr;
if (ioctl(sock, SIOCSIFBRDADDR, &ifr) == -1) {
error("Can't set new broadcast address");
}
#endif
}
/* Set the IP address (in network byte order!) of this interface. */
void set_ip_address(interface, ip_addr)
struct interface_info *interface;
struct in_addr ip_addr;
{
note ("set_ip_address %s: %s",
interface -> name, inet_ntoa (ip_addr));
#if 0
int sock;
struct ifreq ifr;
strncpy(ifr.ifr_name, interface->name, IFNAMSIZ);
if (ioctl(sock, SIOCGIFADDR, &ifr) < 0)
error ("Can't get old IP address of interface");
(*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr = ip_addr;
if (ioctl(sock, SIOCSIFADDR, &ifr) < 0)
error("Can't set IP address");
}
#endif
}

View File

@@ -40,9 +40,17 @@
* Enterprises, see ``http://www.vix.com''. * Enterprises, see ``http://www.vix.com''.
*/ */
/* SO_BINDTODEVICE support added by Elliot Poger (poger@leland.stanford.edu).
* This sockopt allows a socket to be bound to a particular interface,
* thus enabling the use of DHCPD on a multihomed host.
* If SO_BINDTODEVICE is defined in your system header files, the use of
* this sockopt will be automatically enabled.
* I have implemented it under Linux; other systems should be doable also.
*/
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: socket.c,v 1.16 1996/08/27 09:54:48 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; "$Id: socket.c,v 1.17 1997/01/02 12:00:18 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"
@@ -62,6 +70,8 @@ int if_register_socket (info, interface)
struct sockaddr_in name; struct sockaddr_in name;
int sock; int sock;
int flag; int flag;
#ifndef SO_BINDTODEVICE
static int once = 0; static int once = 0;
/* Make sure only one interface is registered. */ /* Make sure only one interface is registered. */
@@ -72,22 +82,8 @@ int if_register_socket (info, interface)
"you must compile in BPF or NIT support. If neither ", "you must compile in BPF or NIT support. If neither ",
"option is supported on your system, please let us ", "option is supported on your system, please let us ",
"know."); "know.");
once = 1;
/* Technically, we need to know what interface every packet
comes in on, which means that we can only operate on a
machine with a single interface configured. However,
we generally don't expect to get broadcast packets on
point-to-point interfaces, so we can bend the rules a bit
and not count them. This won't allow DHCP-over-PPP,
but it's probably right in a lot of cases, and the issue
will have to be revisited when DHCP-over-PPP support is
done. Currently we determine whether an interface is
point-to-point by seeing if it has a link-level address.
This only works on 4.4BSD and derivative networking. */
#ifdef AF_LINK
if (info -> hw_address.hlen) /* XXX */
#endif #endif
once = 1;
/* Set up the address we're going to bind to. */ /* Set up the address we're going to bind to. */
name.sin_family = AF_INET; name.sin_family = AF_INET;
@@ -111,10 +107,26 @@ int if_register_socket (info, interface)
(char *)&flag, sizeof flag) < 0) (char *)&flag, sizeof flag) < 0)
error ("Can't set SO_BROADCAST option on dhcp socket: %m"); error ("Can't set SO_BROADCAST option on dhcp socket: %m");
#ifndef USE_SOCKET_FALLBACK
/* The following will make all-ones broadcasts go out this interface
* on those platforms which use the standard sockets API (assuming
* the OS-specific routines called by enable_sending() are present
* for this platform). */
if_enable (info);
#endif
/* Bind the socket to this interface's IP address. */ /* Bind the socket to this interface's IP address. */
if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0) if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0)
error ("Can't bind to dhcp address: %m"); error ("Can't bind to dhcp address: %m");
#ifdef SO_BINDTODEVICE
/* Bind this socket to this interface. */
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
(char *)interface, sizeof(*interface)) < 0) {
error("setting SO_BINDTODEVICE");
}
#endif
return sock; return sock;
} }
#endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE */ #endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE */
@@ -197,3 +209,30 @@ size_t fallback_discard (interface)
(struct sockaddr *)&from, &flen); (struct sockaddr *)&from, &flen);
} }
#endif /* USE_SOCKET_RECEIVE */ #endif /* USE_SOCKET_RECEIVE */
#if defined (USE_SOCKET_SEND) && !defined (USE_SOCKET_FALLBACK)
/* If we're using the standard socket API without SO_BINDTODEVICE,
* we need this kludge to force DHCP broadcasts to go out
* this interface, even though it's not available for general
* use until we get a lease!
* This should work _OK_, but it will cause ALL all-ones
* broadcasts on this host to go out this interface--it
* could interfere with other interfaces. And God help you
* if you run this on multiple interfaces simultaneously.
* SO_BINDTODEVICE really is better! */
void if_enable (interface)
struct interface_info *interface;
{
#ifndef SO_BINDTODEVICE
struct in_addr broad_addr;
broad_addr.s_addr = htonl(INADDR_BROADCAST);
/* Delete old routes for broadcast address. */
remove_routes(NULL, &broad_addr);
/* Add a route for broadcast address to this interface. */
/* POTENTIAL PROBLEM: Don't do this to more than one interface! */
add_route_direct(interface, &broad_addr);
#endif
}
#endif