2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-31 14:25:41 +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 \
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 \
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
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

24
bpf.c
View File

@@ -42,7 +42,7 @@
#ifndef lint
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 */
#include "dhcpd.h"
@@ -368,3 +368,25 @@ size_t receive_packet (interface, buf, len, from, hfrom)
return 0;
}
#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;
#include <net/if.h>
#include <net/route.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <sys/time.h> /* gettimeofday()*/
#include <linux/time.h> /* also necessary */

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -42,7 +42,7 @@
#ifndef lint
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 */
#include "dhcpd.h"
@@ -368,3 +368,25 @@ size_t receive_packet (interface, buf, len, from, hfrom)
return 0;
}
#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
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 */
#include "dhcpd.h"
@@ -162,6 +162,44 @@ void discover_interfaces (serverP)
if (ifp -> ifr_addr.sa_family == AF_INET) {
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... */
memcpy (&foo, &ifp -> ifr_addr,
sizeof ifp -> ifr_addr);

View File

@@ -42,7 +42,7 @@
#ifndef lint
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 */
#include "dhcpd.h"
@@ -329,3 +329,21 @@ size_t receive_packet (interface, buf, len, from, hfrom)
return length;
}
#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''.
*/
/* 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
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 */
#include "dhcpd.h"
@@ -62,6 +70,8 @@ int if_register_socket (info, interface)
struct sockaddr_in name;
int sock;
int flag;
#ifndef SO_BINDTODEVICE
static int once = 0;
/* 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 ",
"option is supported on your system, please let us ",
"know.");
/* 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 */
once = 1;
#endif
once = 1;
/* Set up the address we're going to bind to. */
name.sin_family = AF_INET;
@@ -111,10 +107,26 @@ int if_register_socket (info, interface)
(char *)&flag, sizeof flag) < 0)
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. */
if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0)
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;
}
#endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE */
@@ -197,3 +209,30 @@ size_t fallback_discard (interface)
(struct sockaddr *)&from, &flen);
}
#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 BOOTP_MIN_LEN 300
#define DHCP_MIN_LEN 548
struct dhcp_packet {
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,
struct sockaddr_in *, struct hardware *));
#endif
#if defined (USE_SOCKET_SEND) && !defined (USE_SOCKET_FALLBACK)
void if_enable PROTO ((struct interface_info *));
#endif
/* bpf.c */
#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,
struct sockaddr_in *, struct hardware *));
#endif
#if defined (USE_BPF_SEND)
void if_enable PROTO ((struct interface_info *));
#endif
/* nit.c */
#ifdef USE_NIT_SEND
@@ -484,6 +490,9 @@ size_t receive_packet PROTO ((struct interface_info *,
unsigned char *, size_t,
struct sockaddr_in *, struct hardware *));
#endif
#if defined (USE_BPF_SEND)
void if_enable PROTO ((struct interface_info *));
#endif
/* raw.c */
#ifdef USE_RAW_SEND
@@ -541,6 +550,27 @@ void dhcpack PROTO ((struct packet *));
void dhcpnak PROTO ((struct packet *));
void send_discover PROTO ((struct interface_info *));
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 */
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_numeric_aggregate PROTO ((FILE *, jrefproto, int, int, int, 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
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 */
#include "dhcpd.h"
@@ -162,6 +162,44 @@ void discover_interfaces (serverP)
if (ifp -> ifr_addr.sa_family == AF_INET) {
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... */
memcpy (&foo, &ifp -> ifr_addr,
sizeof ifp -> ifr_addr);

View File

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

View File

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

View File

@@ -52,6 +52,7 @@
#define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN)
#define BOOTP_MIN_LEN 300
#define DHCP_MIN_LEN 548
struct dhcp_packet {
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,
struct sockaddr_in *, struct hardware *));
#endif
#if defined (USE_SOCKET_SEND) && !defined (USE_SOCKET_FALLBACK)
void if_enable PROTO ((struct interface_info *));
#endif
/* bpf.c */
#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,
struct sockaddr_in *, struct hardware *));
#endif
#if defined (USE_BPF_SEND)
void if_enable PROTO ((struct interface_info *));
#endif
/* nit.c */
#ifdef USE_NIT_SEND
@@ -484,6 +490,9 @@ size_t receive_packet PROTO ((struct interface_info *,
unsigned char *, size_t,
struct sockaddr_in *, struct hardware *));
#endif
#if defined (USE_BPF_SEND)
void if_enable PROTO ((struct interface_info *));
#endif
/* raw.c */
#ifdef USE_RAW_SEND
@@ -541,6 +550,27 @@ void dhcpack PROTO ((struct packet *));
void dhcpnak PROTO ((struct packet *));
void send_discover PROTO ((struct interface_info *));
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 */
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_numeric_aggregate PROTO ((FILE *, jrefproto, int, int, int, 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
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 */
#include "dhcpd.h"
@@ -329,3 +329,21 @@ size_t receive_packet (interface, buf, len, from, hfrom)
return length;
}
#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
BSD socket interface code... */
/*
* Copyright (c) 1995, 1996 The Internet Software Consortium.
* All rights reserved.
/* route.c
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Routines for updating routing tables and configuring interfaces.
*
* 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
* 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''.
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. Stanford University
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#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"
#if defined (OLD_ROUTE_HACK)
#include <net/route.h>
route_hack (sock)
int sock;
/* Add a route to this destination through this interface. */
void add_route_direct(interface, destination)
struct interface_info *interface;
struct in_addr destination;
{
int rsock = socket (PF_ROUTE, SOCK_RAW, AF_INET);
struct rt_msghdr
note ("add_route_direct %s: %s",
interface -> name, inet_ntoa (destination));
#if 0
struct in_addr directmask;
if (rsock < 0)
error ("Can't make routing socket: %m");
directmask.s_addr = htonl (INADDR_BROADCAST); /* this addr only */
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''.
*/
/* 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
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 */
#include "dhcpd.h"
@@ -62,6 +70,8 @@ int if_register_socket (info, interface)
struct sockaddr_in name;
int sock;
int flag;
#ifndef SO_BINDTODEVICE
static int once = 0;
/* 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 ",
"option is supported on your system, please let us ",
"know.");
/* 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 */
once = 1;
#endif
once = 1;
/* Set up the address we're going to bind to. */
name.sin_family = AF_INET;
@@ -111,10 +107,26 @@ int if_register_socket (info, interface)
(char *)&flag, sizeof flag) < 0)
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. */
if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0)
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;
}
#endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE */
@@ -197,3 +209,30 @@ size_t fallback_discard (interface)
(struct sockaddr *)&from, &flen);
}
#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