Commit 99fe695e authored by Shane Kerr's avatar Shane Kerr
Browse files

FreeBSD, NetBSD, OpenBSD support added in (again).

See RT ticket #16865 for more (still expect some warnings).
parent 3496f11e
......@@ -21,7 +21,7 @@ pages.
There are a number of DHCPv6 limitiations and features missing in this
release, which will be addressed shortly:
- Only Solaris and Linux are supported.
- Only Solaris, Linux, FreeBSD, NetBSD, and OpenBSD are supported.
- There is no DHCPv6 Relay support.
......
......@@ -34,7 +34,7 @@
#ifndef lint
static char copyright[] =
"$Id: bpf.c,v 1.51 2007/04/27 23:54:05 each Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
"$Id: bpf.c,v 1.52 2007/05/16 22:27:34 shane Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
......@@ -59,6 +59,8 @@ static char copyright[] =
#include "includes/netinet/if_ether.h"
#endif
#include <ifaddrs.h>
/* Reinitializes the specified interface after an address change. This
is not required for packet-filter APIs. */
......@@ -543,4 +545,60 @@ void maybe_setup_fallback ()
interface_dereference (&fbi, MDL);
}
}
void
get_hw_addr(const char *name, struct hardware *hw) {
struct ifaddrs *ifa;
struct ifaddrs *p;
struct sockaddr *sa;
if (getifaddrs(&ifa) != 0) {
log_fatal("Error getting interface information; %m");
}
/*
* Loop through our interfaces finding a match.
*/
sa = NULL;
for (p=ifa; (p != NULL) && (sa == NULL); p = p->ifa_next) {
if ((p->ifa_addr->sa_family == AF_LINK) &&
!strcmp(p->ifa_name, name)) {
sa = p->ifa_addr;
}
}
if (sa == NULL) {
log_fatal("No interface called '%s'", name);
}
/*
* Pull out the appropriate information.
*/
switch (sa->sa_family) {
case ARPHRD_ETHER:
hw->hlen = 7;
hw->hbuf[0] = HTYPE_ETHER;
memcpy(&hw->hbuf[1], sa->sa_data, 6);
break;
case ARPHRD_IEEE802:
#ifdef ARPHRD_IEEE802_TR
case ARPHRD_IEEE802_TR:
#endif /* ARPHRD_IEEE802_TR */
hw->hlen = 7;
hw->hbuf[0] = HTYPE_IEEE802;
memcpy(&hw->hbuf[1], sa->sa_data, 6);
break;
#ifdef ARPHRD_FDDI
case ARPHRD_FDDI:
hw->hlen = 17;
hw->hbuf[0] = HTYPE_FDDI;
memcpy(&hw->hbuf[1], sa->sa_data, 16);
break;
#endif /* ARPHRD_FDDI */
default:
log_fatal("Unsupported device type %d for \"%s\"",
sa->sa_family, name);
}
freeifaddrs(ifa);
}
#endif
......@@ -34,7 +34,7 @@
#ifndef lint
static char copyright[] =
"$Id: discover.c,v 1.53 2007/05/08 23:05:20 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
"$Id: discover.c,v 1.54 2007/05/16 22:27:34 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
......@@ -225,7 +225,7 @@ begin_iface_scan(struct iface_conf_list *ifaces) {
* Retrieve the next interface.
*
* Returns information in the info structure.
* Sets err to 1 if there is an error, otherwise 1.
* Sets err to 1 if there is an error, otherwise 0.
*/
int
next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
......@@ -635,7 +635,7 @@ next_iface6(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
* Retrieve the next interface.
*
* Returns information in the info structure.
* Sets err to 1 if there is an error, otherwise 1.
* Sets err to 1 if there is an error, otherwise 0.
*/
int
next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
......@@ -664,8 +664,88 @@ end_iface_scan(struct iface_conf_list *ifaces) {
ifaces->fp6 = NULL;
#endif
}
#else
/* XXX: need to define non-Solaris, non-Linux iterators */
#else /* !HAVE_SIOCGLIFCONF, !__linux */
/*
* BSD support
* -----------
*
* FreeBSD, NetBSD, OpenBSD, and OS X all have the getifaddrs()
* function.
*
* The getifaddrs() man page describes the use.
*/
#include <ifaddrs.h>
/*
* Structure holding state about the scan.
*/
struct iface_conf_list {
struct ifaddrs *head; /* beginning of the list */
struct ifaddrs *next; /* current position in the list */
};
/*
* Structure used to return information about a specific interface.
*/
struct iface_info {
char name[IFNAMSIZ]; /* name of the interface, e.g. "bge0" */
struct sockaddr_storage addr; /* address information */
isc_uint64_t flags; /* interface flags, e.g. IFF_LOOPBACK */
};
/*
* Start a scan of interfaces.
*
* The iface_conf_list structure maintains state for this process.
*/
int
begin_iface_scan(struct iface_conf_list *ifaces) {
if (getifaddrs(&ifaces->head) != 0) {
log_error("Error getting interfaces; %m");
return 0;
}
ifaces->next = ifaces->head;
return 1;
}
/*
* Retrieve the next interface.
*
* Returns information in the info structure.
* Sets err to 1 if there is an error, otherwise 0.
*/
int
next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
if (ifaces->next == NULL) {
*err = 0;
return 0;
}
if (strlen(ifaces->next->ifa_name) >= sizeof(info->name)) {
log_error("Interface name '%s' too long",
ifaces->next->ifa_name);
*err = 1;
return 0;
}
strcpy(info->name, ifaces->next->ifa_name);
memcpy(&info->addr, ifaces->next->ifa_addr,
ifaces->next->ifa_addr->sa_len);
info->flags = ifaces->next->ifa_flags;
ifaces->next = ifaces->next->ifa_next;
*err = 0;
return 1;
}
/*
* End scan of interfaces.
*/
void
end_iface_scan(struct iface_conf_list *ifaces) {
freeifaddrs(ifaces->head);
ifaces->head = NULL;
ifaces->next = NULL;
}
#endif
/* XXX: perhaps create drealloc() rather than do it manually */
......@@ -849,29 +929,6 @@ discover_interfaces(int state) {
add_ipv4_addr_to_interface(tmp, &a->sin_addr);
/*
* XXX: We don't have ifreq in Solaris-land if we want IPv6. Fortunately,
* we don't actually need this for anything on Solaris.
*/
#if 0
/* If this is the first real IP address we've
found, keep a pointer to ifreq structure in
which we found it. */
if (!tmp -> ifp) {
#ifdef HAVE_SA_LEN
unsigned len = ((sizeof ifp -> ifr_name) +
ifp -> ifr_addr.sa_len);
#else
unsigned len = sizeof *ifp;
#endif
tif = (struct ifreq *)dmalloc (len, MDL);
if (!tif)
log_fatal ("no space for ifp.");
memcpy (tif, ifp, len);
tmp -> ifp = tif;
}
#endif /* 0 */
/* invoke the setup hook */
addr.len = 4;
memcpy(addr.iabuf, &a->sin_addr.s_addr, addr.len);
......@@ -898,30 +955,6 @@ discover_interfaces(int state) {
add_ipv6_addr_to_interface(tmp, &a->sin6_addr);
/*
* XXX: We don't have ifreq in Solaris-land if we want IPv6. Fortunately,
* we don't actually need this for anything on Solaris.
*/
#if 0
/* If this is the first real IP address we've
found, keep a pointer to ifreq structure in
which we found it. */
if (!tmp -> ifp) {
#ifdef HAVE_SA_LEN
unsigned len = ((sizeof ifp -> ifr_name) +
ifp -> ifr_addr.sa_len);
#else
unsigned len = sizeof *ifp;
#endif
tif = (struct ifreq *)dmalloc (len, MDL);
if (!tif)
log_fatal ("no space for ifp.");
memcpy (tif, ifp, len);
tmp -> ifp = tif;
tmp -> primary_address = foo.sin_addr;
}
#endif /* 0 */
/* invoke the setup hook */
addr.len = 16;
memcpy(addr.iabuf, &a->sin6_addr, addr.len);
......@@ -937,95 +970,6 @@ discover_interfaces(int state) {
end_iface_scan(&ifaces);
#if 0
#if defined (LINUX_SLASHPROC_DISCOVERY)
/* On Linux, interfaces that don't have IP addresses don't
show up in the SIOCGIFCONF syscall. This only matters for
the DHCP client, of course - the relay agent and server
should only care about interfaces that are configured with
IP addresses anyway.
The PROCDEV_DEVICE (/proc/net/dev) is a kernel-supplied file
that, when read, prints a human readable network status. We
extract the names of the network devices by skipping the first
two lines (which are header) and then parsing off everything
up to the colon in each subsequent line - these lines start
with the interface name, then a colon, then a bunch of
statistics. */
if (state == DISCOVER_UNCONFIGURED) {
FILE *proc_dev;
char buffer [256];
int skip = 2;
proc_dev = fopen (PROCDEV_DEVICE, "r");
if (!proc_dev)
log_fatal ("%s: %m", PROCDEV_DEVICE);
while (fgets (buffer, sizeof buffer, proc_dev)) {
char *name = buffer;
char *sep;
/* Skip the first two blocks, which are header
lines. */
if (skip) {
--skip;
continue;
}
sep = strrchr (buffer, ':');
if (sep)
*sep = '\0';
while (*name == ' ')
name++;
/* See if we've seen an interface that matches
this one. */
for (tmp = interfaces; tmp; tmp = tmp -> next)
if (!strcmp (tmp -> name, name))
break;
/* If we found one, nothing more to do.. */
if (tmp)
continue;
strncpy (ifr.ifr_name, name, IFNAMSIZ);
/* Skip non broadcast interfaces (plus loopback and
* point-to-point in case an OS incorrectly marks them
* as broadcast).
*/
if ((ioctl (sock, SIOCGIFFLAGS, &ifr) < 0) ||
(!(ifr.ifr_flags & IFF_BROADCAST)) ||
(ifr.ifr_flags & IFF_LOOPBACK ) ||
(ifr.ifr_flags & IFF_POINTOPOINT))
continue;
/* Otherwise, allocate one. */
tmp = (struct interface_info *)0;
status = interface_allocate (&tmp, MDL);
if (status != ISC_R_SUCCESS)
log_fatal ("Can't allocate interface %s: %s",
name, isc_result_totext (status));
tmp -> flags = ir;
strncpy (tmp -> name, name, IFNAMSIZ);
if (interfaces) {
interface_reference (&tmp -> next,
interfaces, MDL);
interface_dereference (&interfaces, MDL);
}
interface_reference (&interfaces, tmp, MDL);
interface_dereference (&tmp, MDL);
tmp = interfaces;
if (dhcp_interface_discovery_hook)
(*dhcp_interface_discovery_hook) (tmp);
}
fclose (proc_dev);
}
#endif
#endif /* 0 */
/* Now cycle through all the interfaces we found, looking for
hardware addresses. */
......@@ -1167,8 +1111,6 @@ discover_interfaces(int state) {
state == DISCOVER_REQUESTED)
tmp -> flags &= ~(INTERFACE_AUTOMATIC |
INTERFACE_REQUESTED);
/* XXX: no ifp in Solaris */
/* if (!tmp -> ifp || !(tmp -> flags & INTERFACE_REQUESTED)) {*/
if (!(tmp->flags & INTERFACE_REQUESTED)) {
if ((tmp -> flags & INTERFACE_REQUESTED) != ir)
log_fatal ("%s: not found", tmp -> name);
......@@ -1202,10 +1144,6 @@ discover_interfaces(int state) {
}
last = tmp;
/* XXX: no ifp in Solaris */
/* memcpy (&foo, &tmp -> ifp -> ifr_addr,
sizeof tmp -> ifp -> ifr_addr);*/
/* We must have a subnet declaration for each interface. */
if (!tmp->shared_network && (state == DISCOVER_SERVER)) {
log_error("%s", "");
......
......@@ -28,7 +28,7 @@
#ifndef lint
static char copyright[] =
"$Id: lpf.c,v 1.32 2007/05/08 23:05:20 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
"$Id: lpf.c,v 1.33 2007/05/16 22:27:34 shane Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
......@@ -443,9 +443,9 @@ get_hw_addr(const char *name, struct hardware *hw) {
memcpy(&hw->hbuf[1], sa->sa_data, 6);
break;
case ARPHRD_IEEE802:
#ifdef ARPHDR_IEEE802_TR
#ifdef ARPHRD_IEEE802_TR
case ARPHRD_IEEE802_TR:
#endif /* ARPHDR_IEEE802_TR */
#endif /* ARPHRD_IEEE802_TR */
hw->hlen = 7;
hw->hbuf[0] = HTYPE_IEEE802;
memcpy(&hw->hbuf[1], sa->sa_data, 6);
......
......@@ -42,12 +42,13 @@
#ifndef lint
static char copyright[] =
"$Id: socket.c,v 1.61 2007/05/11 15:50:18 dhankins Exp $ "
"$Id: socket.c,v 1.62 2007/05/16 22:27:34 shane Exp $ "
"Copyright (c) 2004-2006 Internet Systems Consortium.\n";
#endif /* not lint */
#include "dhcpd.h"
#include <sys/uio.h>
#include <sys/uio.h>
#ifdef USE_SOCKET_FALLBACK
# if !defined (USE_SOCKET_SEND)
......
......@@ -2046,6 +2046,13 @@ int supports_multiple_interfaces (struct interface_info *);
void maybe_setup_fallback PROTO ((void));
#endif
void if_register6(struct interface_info *info, int do_multicast);
ssize_t receive_packet6(struct interface_info *interface,
unsigned char *buf, size_t len,
struct sockaddr_in6 *from, struct in6_addr *to_addr);
void if_deregister6(struct interface_info *info);
/* bpf.c */
#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)
int if_register_bpf PROTO ( (struct interface_info *));
......
......@@ -17,6 +17,7 @@
/* TODO: assert() */
/* TODO: simplify functions, as pool is now in iaaddr */
#include <sys/types.h>
#include <time.h>
#include <netinet/in.h>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment