On Wed, Dec 07, 2016 at 05:34:05PM +0100, Rafael Zalamena wrote:
> This diff simplifies the get_interface function and makes it more
> straightforward, it also makes dhcrelay(8) throw a more informative error
> message when running layer 3 mode (default) on interfaces without an
> address.
>
> I'll use this code later to be able to get_interfaces() without an IP address.
I forgot to make it return NULL if no interfaces are found (e.g. invalid
interface name) and then it started failing with a cryptic death message:
"Can't attach interface vip1 to bpf device: Device not configured"
This updated diff fix the problem.
ok?
Index: bpf.c
===================================================================
RCS file: /home/obsdcvs/src/usr.sbin/dhcrelay/bpf.c,v
retrieving revision 1.11
diff -u -p -r1.11 bpf.c
--- bpf.c 28 May 2016 07:00:18 -0000 1.11
+++ bpf.c 7 Dec 2016 17:49:16 -0000
@@ -75,7 +75,7 @@ if_register_bpf(struct interface_info *i
error("Can't open bpf device: %m");
/* Set the BPF device to point at this interface. */
- if (ioctl(sock, BIOCSETIF, info->ifp) == -1)
+ if (ioctl(sock, BIOCSETIF, &info->ifr) == -1)
error("Can't attach interface %s to bpf device: %m",
info->name);
Index: dhcpd.h
===================================================================
RCS file: /home/obsdcvs/src/usr.sbin/dhcrelay/dhcpd.h,v
retrieving revision 1.15
diff -u -p -r1.15 dhcpd.h
--- dhcpd.h 7 Dec 2016 13:19:18 -0000 1.15
+++ dhcpd.h 7 Dec 2016 17:49:16 -0000
@@ -76,7 +76,7 @@ struct interface_info {
size_t rbuf_max;
size_t rbuf_offset;
size_t rbuf_len;
- struct ifreq *ifp;
+ struct ifreq ifr;
int noifmedia;
int errors;
int dead;
Index: dhcrelay.c
===================================================================
RCS file: /home/obsdcvs/src/usr.sbin/dhcrelay/dhcrelay.c,v
retrieving revision 1.44
diff -u -p -r1.44 dhcrelay.c
--- dhcrelay.c 7 Dec 2016 13:19:18 -0000 1.44
+++ dhcrelay.c 7 Dec 2016 17:49:16 -0000
@@ -165,6 +165,9 @@ main(int argc, char *argv[])
if (interfaces == NULL)
error("no interface given");
+ if (interfaces->primary_address.s_addr == 0)
+ error("interface '%s' does not have an address",
+ interfaces->name);
/* Default DHCP/BOOTP ports. */
server_port = htons(SERVER_PORT);
Index: dispatch.c
===================================================================
RCS file: /home/obsdcvs/src/usr.sbin/dhcrelay/dispatch.c,v
retrieving revision 1.12
diff -u -p -r1.12 dispatch.c
--- dispatch.c 7 Dec 2016 13:19:18 -0000 1.12
+++ dispatch.c 7 Dec 2016 17:49:16 -0000
@@ -79,15 +79,15 @@ get_interface(const char *ifname, void (
{
struct interface_info *iface;
struct ifaddrs *ifap, *ifa;
- struct ifreq *tif;
- struct sockaddr_in foo;
+ struct sockaddr_in *sin;
+ int found = 0;
if ((iface = calloc(1, sizeof(*iface))) == NULL)
error("failed to allocate memory");
if (strlcpy(iface->name, ifname, sizeof(iface->name)) >=
sizeof(iface->name))
- error("interface name too long");
+ error("interface name '%s' too long", ifname);
if (getifaddrs(&ifap) != 0)
error("getifaddrs failed");
@@ -101,6 +101,8 @@ get_interface(const char *ifname, void (
if (strcmp(ifname, ifa->ifa_name))
continue;
+ found = 1;
+
/*
* If we have the capability, extract link information
* and record it in a linked list.
@@ -120,31 +122,28 @@ get_interface(const char *ifname, void (
memcpy(iface->hw_address.haddr,
LLADDR(foo), foo->sdl_alen);
} else if (ifa->ifa_addr->sa_family == AF_INET) {
- struct iaddr addr;
+ /* We already have the primary address. */
+ if (iface->primary_address.s_addr != 0)
+ continue;
- memcpy(&foo, ifa->ifa_addr, sizeof(foo));
- if (foo.sin_addr.s_addr == htonl(INADDR_LOOPBACK))
+ sin = (struct sockaddr_in *)ifa->ifa_addr;
+ if (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
continue;
- if (!iface->ifp) {
- int len = IFNAMSIZ + ifa->ifa_addr->sa_len;
- if ((tif = malloc(len)) == NULL)
- error("no space to remember ifp");
- strlcpy(tif->ifr_name, ifa->ifa_name, IFNAMSIZ);
- memcpy(&tif->ifr_addr, ifa->ifa_addr,
- ifa->ifa_addr->sa_len);
- iface->ifp = tif;
- iface->primary_address = foo.sin_addr;
- }
- addr.len = 4;
- memcpy(addr.iabuf, &foo.sin_addr.s_addr, addr.len);
+ iface->primary_address = sin->sin_addr;
}
}
freeifaddrs(ifap);
- if (!iface->ifp)
- error("%s: not found", iface->name);
+ if (!found) {
+ free(iface);
+ return (NULL);
+ }
+
+ if (strlcpy(iface->ifr.ifr_name, ifname,
+ sizeof(iface->ifr.ifr_name)) >= sizeof(iface->ifr.ifr_name))
+ error("interface name '%s' too long", ifname);
/* Register the interface... */
if_register_receive(iface);