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. ok? Index: bpf.c =================================================================== RCS file: /cvs/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 16:29:14 -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: /cvs/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 16:29:14 -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: /cvs/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 16:29:14 -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: /cvs/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 16:29:14 -0000 @@ -79,15 +79,14 @@ 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; 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"); @@ -120,31 +119,23 @@ 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 (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);