|
42 | 42 | #include <linux/if_vlan.h>
|
43 | 43 | #include <linux/filter.h>
|
44 | 44 | #include <linux/netlink.h>
|
| 45 | +#include <linux/ethtool.h> /* for ipvlan detection */ |
45 | 46 | #include <linux/sockios.h>
|
46 | 47 | #include <linux/rtnetlink.h>
|
47 | 48 |
|
@@ -309,12 +310,55 @@ if_init(struct interface *ifp)
|
309 | 310 | return if_writepathuint(ifp->ctx, path, 1) == -1 ? -1 : 0;
|
310 | 311 | }
|
311 | 312 |
|
| 313 | +/* Returns number of bytes written to driver, else 0 (error or indeterminate). */ |
| 314 | +static size_t |
| 315 | +if_get_driver(struct interface *ifp, char *driver, const size_t driverlen) |
| 316 | +{ |
| 317 | + struct ethtool_drvinfo drvinfo = { .cmd = ETHTOOL_GDRVINFO }; |
| 318 | + struct ifreq ifr = { .ifr_data = (void *)&drvinfo }; |
| 319 | + |
| 320 | + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); |
| 321 | + if (ioctl(ifp->ctx->pf_inet_fd, SIOCETHTOOL, &ifr) != 0) { |
| 322 | + logerr("%s: SIOCETHTOOL ifname=%s", __func__, ifp->name); |
| 323 | + return 0; /* 0 means error or indeterminate driver name */ |
| 324 | + } |
| 325 | + return strlcpy(driver, drvinfo.driver, driverlen); |
| 326 | +} |
| 327 | + |
| 328 | +static bool |
| 329 | +if_cmp_driver(struct interface *ifp, const char *driver) |
| 330 | +{ |
| 331 | + char ifdriver[FIELD_SIZEOF(struct ethtool_drvinfo, driver)]; |
| 332 | + size_t n = if_get_driver(ifp, ifdriver, sizeof(ifdriver)); |
| 333 | + |
| 334 | + if (n == 0) { |
| 335 | + logerr("%s: if_get_driver ifname=%s", __func__, ifp->name); |
| 336 | + return false; |
| 337 | + } |
| 338 | + if (strncmp(ifdriver, driver, n) == 0) |
| 339 | + return true; |
| 340 | + return false; |
| 341 | +} |
| 342 | + |
| 343 | +static bool |
| 344 | +if_ipvlan(struct interface *ifp) |
| 345 | +{ |
| 346 | + if (if_cmp_driver(ifp, "ipvlan")) |
| 347 | + return true; |
| 348 | + return false; |
| 349 | +} |
| 350 | + |
312 | 351 | int
|
313 | 352 | if_conf(struct interface *ifp)
|
314 | 353 | {
|
315 | 354 | char path[sizeof(SYS_LAYER2) + IF_NAMESIZE];
|
316 | 355 | int n;
|
317 | 356 |
|
| 357 | + /* Set broadcast flag for ipvlan interfaces. |
| 358 | + * XXX: move this out to dhcpcd if needed on other platforms. */ |
| 359 | + if (if_ipvlan(ifp)) |
| 360 | + ifp->options->options |= DHCPCD_BROADCAST; |
| 361 | + |
318 | 362 | /* Some qeth setups require the use of the broadcast flag. */
|
319 | 363 | snprintf(path, sizeof(path), SYS_LAYER2, ifp->name);
|
320 | 364 | n = check_proc_int(ifp->ctx, path);
|
|
0 commit comments