Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Linux: set broadcast flag by default for ipvlan interfaces. #33

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@
#define ROUNDUP4(a) (1 + (((a) - 1) | 3))
#define ROUNDUP8(a) (1 + (((a) - 1) | 7))

#ifndef FIELD_SIZEOF
#define FIELD_SIZEOF(t, f) sizeof(((t *)0)->f)
#endif

/* Some systems don't define timespec macros */
#ifndef timespecclear
#define timespecclear(tsp) (tsp)->tv_sec = (time_t)((tsp)->tv_nsec = 0L)
Expand Down
2 changes: 1 addition & 1 deletion src/dhcpcd.8.in
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ of a randomly generated number.
.It Fl J , Fl Fl broadcast
Instructs the DHCP server to broadcast replies back to the client.
Normally this is only set for non-Ethernet interfaces,
such as FireWire and InfiniBand.
such as FireWire and InfiniBand, and on Linux-based systems for ipvlan as well.
In most instances,
.Nm
will set this automatically.
Expand Down
2 changes: 1 addition & 1 deletion src/dhcpcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ configure_interface1(struct interface *ifp)

if (!(ifo->options & DHCPCD_IAID)) {
/*
* An IAID is for identifying a unqiue interface within
* An IAID is for identifying an unique interface within
* the client. It is 4 bytes long. Working out a default
* value is problematic.
*
Expand Down
48 changes: 48 additions & 0 deletions src/if-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <linux/if_vlan.h>
#include <linux/filter.h>
#include <linux/netlink.h>
#include <linux/ethtool.h> /* for ipvlan detection */
#include <linux/sockios.h>
#include <linux/rtnetlink.h>

Expand Down Expand Up @@ -309,12 +310,59 @@ if_init(struct interface *ifp)
return if_writepathuint(ifp->ctx, path, 1) == -1 ? -1 : 0;
}

/* Return values:
* -1 = ioctl error
* 0 = no driver name or driver name indeterminate
* >0 = length of driver name written to provided buffer. */
static ssize_t
if_get_driver(struct interface *ifp, char *driver, const size_t driverlen)
{
struct ethtool_drvinfo drvinfo = { .cmd = ETHTOOL_GDRVINFO };
struct ifreq ifr = { .ifr_data = (void *)&drvinfo };

strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
if (ioctl(ifp->ctx->pf_inet_fd, SIOCETHTOOL, &ifr) != 0) {
logerr("%s: SIOCETHTOOL ifname=%s", __func__, ifp->name);
return -1; /* -1 means ioctl error */
}
return (ssize_t)strlcpy(driver, drvinfo.driver, driverlen);
}

static bool
if_cmp_driver(struct interface *ifp, const char *driver)
{
char ifdriver[FIELD_SIZEOF(struct ethtool_drvinfo, driver)];
ssize_t n = if_get_driver(ifp, ifdriver, sizeof(ifdriver));

if (n == -1) {
logerr("%s: if_get_driver ifname=%s", __func__, ifp->name);
} else if (n == 0) {
logerr("%s: driver name empty ifname=%s", __func__, ifp->name);
}
if ((n >= 0) && (strncmp(ifdriver, driver, (size_t)n) == 0))
return true;
return false;
}

static bool
if_ipvlan(struct interface *ifp)
{
if (if_cmp_driver(ifp, "ipvlan"))
return true;
return false;
}

int
if_conf(struct interface *ifp)
{
char path[sizeof(SYS_LAYER2) + IF_NAMESIZE];
int n;

/* Set broadcast flag for ipvlan interfaces.
* XXX: move this out to dhcpcd if needed on other platforms. */
if (if_ipvlan(ifp))
ifp->options->options |= DHCPCD_BROADCAST;
ido marked this conversation as resolved.
Show resolved Hide resolved

/* Some qeth setups require the use of the broadcast flag. */
snprintf(path, sizeof(path), SYS_LAYER2, ifp->name);
n = check_proc_int(ifp->ctx, path);
Expand Down