Module Name: src
Committed By: christos
Date: Mon Apr 8 02:16:03 UTC 2013
Modified Files:
src/external/bsd/dhcp/dist/common: bpf.c
Log Message:
Use the active link local layer address instead of the first one you find.
It would be nice if getifaddrs gave all the information needed instead of
needed a separate ioctl. Or at least if the inactive addresses were marked
down in flags?
To generate a diff of this commit:
cvs rdiff -u -r1.1.1.2 -r1.2 src/external/bsd/dhcp/dist/common/bpf.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/external/bsd/dhcp/dist/common/bpf.c
diff -u src/external/bsd/dhcp/dist/common/bpf.c:1.1.1.2 src/external/bsd/dhcp/dist/common/bpf.c:1.2
--- src/external/bsd/dhcp/dist/common/bpf.c:1.1.1.2 Tue Mar 26 20:31:33 2013
+++ src/external/bsd/dhcp/dist/common/bpf.c Sun Apr 7 22:16:03 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: bpf.c,v 1.1.1.2 2013/03/27 00:31:33 christos Exp $ */
+/* $NetBSD: bpf.c,v 1.2 2013/04/08 02:16:03 christos Exp $ */
/* bpf.c
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: bpf.c,v 1.1.1.2 2013/03/27 00:31:33 christos Exp $");
+__RCSID("$NetBSD: bpf.c,v 1.2 2013/04/08 02:16:03 christos Exp $");
#include "dhcpd.h"
#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) \
@@ -54,6 +54,7 @@ __RCSID("$NetBSD: bpf.c,v 1.1.1.2 2013/0
# endif
# endif
+#include <sys/param.h>
#include <netinet/in_systm.h>
#include "includes/netinet/ip.h"
#include "includes/netinet/udp.h"
@@ -556,11 +557,50 @@ void maybe_setup_fallback ()
}
}
+static int
+lladdr_active(int s, const char *name, const struct ifaddrs *ifa)
+{
+ if (ifa->ifa_addr->sa_family != AF_LINK)
+ return 0;
+ if (strcmp(ifa->ifa_name, name) != 0)
+ return 0;
+
+#ifdef SIOCGLIFADDR
+{
+ struct if_laddrreq iflr;
+ const struct sockaddr_dl *sdl;
+
+ sdl = satocsdl(ifa->ifa_addr);
+ memset(&iflr, 0, sizeof(iflr));
+
+ strlcpy(iflr.iflr_name, ifa->ifa_name, sizeof(iflr.iflr_name));
+ memcpy(&iflr.addr, ifa->ifa_addr, MIN(ifa->ifa_addr->sa_len,
+ sizeof(iflr.addr)));
+ iflr.flags = IFLR_PREFIX;
+ iflr.prefixlen = sdl->sdl_alen * NBBY;
+
+ if (ioctl(s, SIOCGLIFADDR, &iflr) == -1) {
+ log_fatal("ioctl(SIOCGLIFADDR): %m");
+ }
+
+ if ((iflr.flags & IFLR_ACTIVE) == 0)
+ return 0;
+}
+#endif
+ return 1;
+}
+
+
void
get_hw_addr(const char *name, struct hardware *hw) {
struct ifaddrs *ifa;
struct ifaddrs *p;
struct sockaddr_dl *sa;
+ int s;
+
+ if ((s = socket(AF_LINK, SOCK_DGRAM, 0)) == -1) {
+ log_fatal("socket AF_LINK: %m");
+ }
if (getifaddrs(&ifa) != 0) {
log_fatal("Error getting interface information; %m");
@@ -570,15 +610,16 @@ get_hw_addr(const char *name, struct har
* 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)) {
+ for (p = ifa; p != NULL; p = p->ifa_next) {
+ if (lladdr_active(s, name, p)) {
sa = (struct sockaddr_dl *)p->ifa_addr;
+ break;
}
}
if (sa == NULL) {
log_fatal("No interface called '%s'", name);
}
+ close(s);
/*
* Pull out the appropriate information.