Skip to content

Commit

Permalink
linux: Support old kernels by not including linux/if.h
Browse files Browse the repository at this point in the history
I wish the linux team used #defines rather than enums, but heh ho.
Ensure we can test IFF_LOWER_UP, IFF_DORMANT and IFA_FLAGS
based on nearest matching #defines available when the respective
feature was comitted.

Fixes #373.
  • Loading branch information
rsmarples committed Oct 10, 2024
1 parent 3989dbf commit 8ef970d
Showing 1 changed file with 33 additions and 10 deletions.
43 changes: 33 additions & 10 deletions src/if-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,6 @@
#include <linux/if_arp.h>
#endif

#ifndef IFF_DORMANT
/* Inlcude this *after* net/if.h so we get IFF_DORMANT */
#include <linux/if.h>
#endif

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
Expand Down Expand Up @@ -109,6 +104,27 @@ int if_getssid_wext(const char *ifname, uint8_t *ssid);
#define SOL_NETLINK 270
#endif

/*
* We cannot include linux/if.h due to the need to support old kernels.
* IFLA_LINKINFO is a define which was added after IFF_LOWER_UP and
* IFF_DORMANT.
* So we miss a few versions, but it's the best we can do.
*/
#ifdef IFLA_LINKINFO
#ifndef IFF_LOWER_UP
#define IFF_LOWER_UP 0x10000
#endif
#ifndef IFF_DORMANT
#define IFF_DORMANT 0x20000
#endif
#endif

/* Linux defines IFA_FLAGS as an enum.
* For older kernels we know it exists if IFA_F_MANAGETEMPADDR does. */
#ifdef IFA_F_MANAGETEMPADDR
#define IFA_FLAGS IFA_FLAGS
#endif

/*
* Someone should fix kernel headers for clang alignment warnings.
* But this is unlikely.
Expand Down Expand Up @@ -1208,13 +1224,15 @@ add_attr_l(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
return 0;
}

#if defined(HAVE_ROUTE_PREF) || defined(HAVE_IN6_ADDR_GEN_MODE_NONE)
static int
add_attr_8(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
uint8_t data)
{

return add_attr_l(n, maxlen, type, &data, sizeof(data));
}
#endif

static int
add_attr_32(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
Expand Down Expand Up @@ -1997,7 +2015,7 @@ if_address6(unsigned char cmd, const struct ipv6_addr *ia)
nlm.ifa.ifa_flags |= IFA_F_TEMPORARY;
#endif
}
#elif IFA_F_MANAGETEMPADDR
#elif defined(IFA_F_MANAGETEMPADDR)
if (ia->flags & IPV6_AF_AUTOCONF && IA6_CANAUTOCONF(ia))
flags |= IFA_F_MANAGETEMPADDR;
#endif
Expand Down Expand Up @@ -2037,12 +2055,15 @@ _if_addrflags6(__unused struct dhcpcd_ctx *ctx,
struct rtattr *rta;
struct ifaddrmsg *ifa;
struct in6_addr *local = NULL, *address = NULL;
uint32_t *flags = NULL;
uint32_t flags;

ifa = NLMSG_DATA(nlm);
if (ifa->ifa_index != ia->ifa_ifindex || ifa->ifa_family != AF_INET6)
return 0;

/* Old kernels set flags here, newer ones as attributed data. */
flags = ifa->ifa_flags;

rta = IFA_RTA(ifa);
len = NLMSG_PAYLOAD(nlm, sizeof(*ifa));
for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
Expand All @@ -2053,9 +2074,11 @@ _if_addrflags6(__unused struct dhcpcd_ctx *ctx,
case IFA_LOCAL:
local = (struct in6_addr *)RTA_DATA(rta);
break;
#ifdef IFA_F_MANAGETEMPADDR /* IFA_FLAGS is an enum, can't test that */
case IFA_FLAGS:
flags = (uint32_t *)RTA_DATA(rta);
memcpy(&flags, RTA_DATA(rta), sizeof(flags));
break;
#endif
}
}

Expand All @@ -2066,8 +2089,8 @@ _if_addrflags6(__unused struct dhcpcd_ctx *ctx,
if (IN6_ARE_ADDR_EQUAL(&ia->ifa_addr, address))
ia->ifa_found = true;
}
if (flags && ia->ifa_found)
memcpy(&ia->ifa_flags, flags, sizeof(ia->ifa_flags));
if (ia->ifa_found)
ia->ifa_flags = flags;
return 0;
}

Expand Down

0 comments on commit 8ef970d

Please sign in to comment.