Skip to content

Commit cb74cb9

Browse files
committed
Linux: set broadcast flag by default for ipvlan interfaces.
1 parent 17b761c commit cb74cb9

File tree

2 files changed

+37
-27
lines changed

2 files changed

+37
-27
lines changed

src/dhcpcd.8.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ of a randomly generated number.
651651
.It Fl J , Fl Fl broadcast
652652
Instructs the DHCP server to broadcast replies back to the client.
653653
Normally this is only set for non-Ethernet interfaces,
654-
such as FireWire and InfiniBand.
654+
such as FireWire and InfiniBand, and for ipvlan interfaces.
655655
In most instances,
656656
.Nm
657657
will set this automatically.

src/if-linux.c

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -310,47 +310,57 @@ if_init(struct interface *ifp)
310310
return if_writepathuint(ifp->ctx, path, 1) == -1 ? -1 : 0;
311311
}
312312

313-
/* @maxlen should be greater than or equal to 32; see ethtool_drvinfo. */
314-
static int
315-
if_get_driver(const char *ifname, char *driver, const size_t maxlen)
313+
/* Returns number of bytes written to driver, 0 on error.
314+
* @driverlen note that sizeof(ethtool_drvinfo.driver) = 32 */
315+
static size_t
316+
if_get_driver(const char *ifname, char *driver, const size_t driverlen)
316317
{
317-
struct ifreq ifr;
318+
struct ifreq ifr = { .ifr_flags = 0 };
318319
struct ethtool_drvinfo drvinfo;
319320
int fd;
320-
if (!ifname || !*ifname)
321-
return -1;
321+
size_t n = 0;
322322

323323
fd = socket(AF_INET, SOCK_STREAM, 0);
324324
if (fd == -1) {
325-
logerr("if_get_driver: failed socket creation: %s", strerror(errno));
326-
return -1;
325+
logerr("%s: socket ifname=%s", __func__, ifname);
326+
goto eexit;
327327
}
328-
329328
memset(&ifr, 0, sizeof(ifr));
330329
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
331330
drvinfo.cmd = ETHTOOL_GDRVINFO;
332331
ifr.ifr_data = (void *)&drvinfo;
333-
if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) {
334-
const int err = errno;
335-
logerr("if_get_driver: failed ethtool ioctl on interface %s: %s",
336-
ifname, strerror(errno));
337-
close(fd);
338-
return -1;
332+
if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) {
333+
logerr("%s: SIOCETHTOOL ifname=%s", __func__, ifname);
334+
goto eexit;
339335
}
340-
close(fd);
341-
return strlcpy(driver, drvinfo.driver,
342-
MIN(sizeof(drvinfo.driver), maxlen));
336+
n = strlcpy(driver, drvinfo.driver, driverlen);
337+
eexit:
338+
if (fd != -1)
339+
close(fd);
340+
return n;
343341
}
344342

345343
static bool
346-
if_ipvlan(const char *ifname)
344+
if_cmp_driver(const char *ifname, const char *driver)
347345
{
348-
char driver[32]; /* sizeof(ethtool_drvinfo.driver) = 32 */
349-
if (if_get_driver(ifname, driver, sizeof(driver)) < 0) {
350-
logerr("if_ipvlan: failed to get driver name %s.", ifname);
346+
char ifdriver[32]; /* see ethtool_drvinfo.driver declaration */
347+
size_t n = if_get_driver(ifname, ifdriver, sizeof(ifdriver));
348+
349+
if (n == 0) {
350+
logerr("%s: if_get_driver ifname=%s", __func__, ifname);
351351
return false;
352352
}
353-
return (strncmp(driver, "ipvlan", sizeof(driver)) == 0);
353+
if (strncmp(ifdriver, driver, n) == 0)
354+
return true;
355+
return false;
356+
}
357+
358+
static bool
359+
if_ipvlan(struct interface *ifp)
360+
{
361+
if (if_cmp_driver(ifp->name, "ipvlan"))
362+
return true;
363+
return false;
354364
}
355365

356366
int
@@ -359,10 +369,10 @@ if_conf(struct interface *ifp)
359369
char path[sizeof(SYS_LAYER2) + IF_NAMESIZE];
360370
int n;
361371

362-
/* Set broadcast flag for ipvlan interfaces. */
363-
if (if_ipvlan(ifp->name)) {
372+
/* Set broadcast flag for ipvlan interfaces.
373+
* XXX: move this out to dhcpcd if needed on other platforms. */
374+
if (if_ipvlan(ifp))
364375
ifp->options->options |= DHCPCD_BROADCAST;
365-
}
366376

367377
/* Some qeth setups require the use of the broadcast flag. */
368378
snprintf(path, sizeof(path), SYS_LAYER2, ifp->name);

0 commit comments

Comments
 (0)