*p++ = DHO_MAXMESSAGESIZE;
*p++ = 2;
- mtu = if_getmtu(ifp->name);
+ mtu = if_getmtu(ifp);
if (mtu < MTU_MIN) {
- if (if_setmtu(ifp->name, MTU_MIN) == 0)
+ if (if_setmtu(ifp, MTU_MIN) == 0)
sz = MTU_MIN;
} else if (mtu > MTU_MAX) {
/* Even though our MTU could be greater than
ifo = NULL;
ctx.cffile = CONFIG;
ctx.pid_fd = ctx.control_fd = ctx.control_unpriv_fd = ctx.link_fd = -1;
+ ctx.pf_inet_fd = -1;
+#if defined(INET6) && defined(BSD)
+ ctx.pf_inet6_fd = -1;
+#endif
+#ifdef IFLR_ACTIVE
+ ctx.pf_link_fd = -1;
+#endif
+
TAILQ_INIT(&ctx.control_fds);
#ifdef PLUGIN_DEV
ctx.dev_fd = -1;
if (ctx.ifc == 1 && !(ctx.options & DHCPCD_BACKGROUND))
ctx.options |= DHCPCD_WAITIP;
- /* RTM_NEWADDR goes through the link socket as well which we
- * need for IPv6 DAD, so we check for DHCPCD_LINK in
- * dhcpcd_handlecarrier instead.
- * We also need to open this before checking for interfaces below
- * so that we pickup any new addresses during the discover phase. */
- ctx.link_fd = if_openlinksocket();
- if (ctx.link_fd == -1)
- logger(&ctx, LOG_ERR, "open_link_socket: %m");
- else
- eloop_event_add(ctx.eloop, ctx.link_fd,
- handle_link, &ctx, NULL, NULL);
+ /* Open our persistent sockets. */
+ if (if_opensockets(&ctx) == -1) {
+ logger(&ctx, LOG_ERR, "if_opensockets: %m");
+ goto exit_failure;
+ }
+ eloop_event_add(ctx.eloop, ctx.link_fd, handle_link, &ctx, NULL, NULL);
/* Start any dev listening plugin which may want to
* change the interface name provided by the kernel */
eloop_event_delete(ctx.eloop, ctx.link_fd);
close(ctx.link_fd);
}
+ if (ctx.pf_inet_fd != -1)
+ close(ctx.pf_inet_fd);
+#if defined(INET6) && defined(BSD)
+ if (ctx.pf_inet6_fd != -1)
+ close(ctx.pf_inet6_fd);
+#endif
+#ifdef IFLR_ACTIVE
+ if (ctx.pf_link_fd != -1)
+ close(ctx.pf_link_fd);
+#endif
+
free_options(ifo);
free_globals(&ctx);
* dhcpcd can poll it for the relevant flags periodically */
#define IF_POLL_UP 100 /* milliseconds */
+#ifdef __QNX__
+/* QNX carries defines for, but does not actually support PF_LINK */
+#undef IFLR_ACTIVE
+#endif
+
struct interface {
struct dhcpcd_ctx *ctx;
TAILQ_ENTRY(interface) next;
char **ifcv; /* configured interfaces */
unsigned char *duid;
size_t duid_len;
- int link_fd;
struct if_head *ifaces;
+ int pf_inet_fd;
+#if defined(INET6) && defined(BSD)
+ int pf_inet6_fd;
+#endif
+#ifdef IFLR_ACTIVE
+ int pf_link_fd;
+#endif
+ int link_fd;
+
#ifdef USE_SIGNALS
sigset_t sigset;
#endif
#endif
static int
-if_getssid1(const char *ifname, uint8_t *ssid)
+if_getssid1(int s, const char *ifname, uint8_t *ssid)
{
- int s, retval = -1;
+ int retval = -1;
#if defined(SIOCG80211NWID)
struct ifreq ifr;
struct ieee80211_nwid nwid;
char nwid[IEEE80211_NWID_LEN + 1];
#endif
- if ((s = xsocket(PF_INET, SOCK_DGRAM, 0, O_CLOEXEC)) == -1)
- return -1;
-
#if defined(SIOCG80211NWID) /* NetBSD */
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
}
#endif
- close(s);
return retval;
}
{
int r;
- r = if_getssid1(ifp->name, ifp->ssid);
+ r = if_getssid1(ifp->ctx->pf_inet_fd, ifp->name, ifp->ssid);
if (r != -1)
ifp->ssid_len = (unsigned int)r;
return r;
* returning the SSID gives an error.
*/
int
-if_vimaster(const char *ifname)
+if_vimaster(const struct dhcpcd_ctx *ctx, const char *ifname)
{
- int s, r;
+ int r;
struct ifmediareq ifmr;
- if ((s = xsocket(PF_INET, SOCK_DGRAM, 0, O_CLOEXEC)) == -1)
- return -1;
memset(&ifmr, 0, sizeof(ifmr));
strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
- r = ioctl(s, SIOCGIFMEDIA, &ifmr);
- close(s);
+ r = ioctl(ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr);
if (r == -1)
return -1;
if (ifmr.ifm_status & IFM_AVALID &&
IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211)
{
- if (if_getssid1(ifname, NULL) == -1)
+ if (if_getssid1(ctx->pf_inet_fd, ifname, NULL) == -1)
return 1;
}
return 0;
const struct in_addr *netmask, const struct in_addr *broadcast,
int action)
{
- int s, r;
+ int r;
struct in_aliasreq ifra;
- if ((s = xsocket(PF_INET, SOCK_DGRAM, 0, O_CLOEXEC)) == -1)
- return -1;
-
memset(&ifra, 0, sizeof(ifra));
strlcpy(ifra.ifra_name, ifp->name, sizeof(ifra.ifra_name));
ADDADDR(&ifra.ifra_broadaddr, broadcast);
#undef ADDADDR
- r = ioctl(s,
+ r = ioctl(ifp->ctx->pf_inet_fd,
action < 0 ? SIOCDIFADDR : SIOCAIFADDR, &ifra);
- close(s);
return r;
}
} rtm;
char *bp = rtm.buffer;
size_t l;
- int s, retval;
-
- if ((s = xsocket(PF_ROUTE, SOCK_RAW, 0, O_CLOEXEC)) == -1)
- return -1;
#define ADDSU { \
l = RT_ROUNDUP(su.sa.sa_len); \
#undef ADDSU
rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm);
- retval = write(s, &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0;
- close(s);
- return retval;
+ return write(rt->iface->ctx->link_fd,
+ &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0;
}
int
int
if_addrflags(const struct in_addr *addr, const struct interface *ifp)
{
- int s, flags;
struct ifreq ifr;
struct sockaddr_in *sin;
- s = xsocket(PF_INET, SOCK_DGRAM, 0, O_CLOEXEC);
- flags = -1;
- if (s != -1) {
- memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
- sin = (struct sockaddr_in *)(void *)&ifr.ifr_addr;
- sin->sin_family = AF_INET;
- sin->sin_addr = *addr;
- if (ioctl(s, SIOCGIFAFLAG_IN, &ifr) != -1)
- flags = ifr.ifr_addrflags;
- close(s);
- }
- return flags;
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
+ sin = (struct sockaddr_in *)(void *)&ifr.ifr_addr;
+ sin->sin_family = AF_INET;
+ sin->sin_addr = *addr;
+ if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFAFLAG_IN, &ifr) == -1)
+ return -1;
+ return ifr.ifr_addrflags;
}
#else
int
#endif
int
-if_address6(const struct ipv6_addr *a, int action)
+if_address6(const struct ipv6_addr *ia, int action)
{
- int s, r;
struct in6_aliasreq ifa;
struct in6_addr mask;
- if ((s = xsocket(PF_INET6, SOCK_DGRAM, 0, O_CLOEXEC)) == -1)
- return -1;
-
memset(&ifa, 0, sizeof(ifa));
- strlcpy(ifa.ifra_name, a->iface->name, sizeof(ifa.ifra_name));
+ strlcpy(ifa.ifra_name, ia->iface->name, sizeof(ifa.ifra_name));
/*
* We should not set IN6_IFF_TENTATIVE as the kernel should be
* able to work out if it's a new address or not.
* either.
*/
#if 0
- if (a->autoconf)
+ if (ia->autoconf)
ifa.ifra_flags |= IN6_IFF_AUTOCONF;
#endif
#ifdef IPV6_MANGETEMPADDR
- if (a->flags & IPV6_AF_TEMPORARY)
+ if (ia->flags & IPV6_AF_TEMPORARY)
ifa.ifra_flags |= IN6_IFF_TEMPORARY;
#endif
(v)->sin6_addr = *addr; \
}
- ADDADDR(&ifa.ifra_addr, &a->addr);
- ifa_scope(&ifa.ifra_addr, a->iface->index);
- ipv6_mask(&mask, a->prefix_len);
+ ADDADDR(&ifa.ifra_addr, &ia->addr);
+ ifa_scope(&ifa.ifra_addr, ia->iface->index);
+ ipv6_mask(&mask, ia->prefix_len);
ADDADDR(&ifa.ifra_prefixmask, &mask);
- ifa.ifra_lifetime.ia6t_vltime = a->prefix_vltime;
- ifa.ifra_lifetime.ia6t_pltime = a->prefix_pltime;
+ ifa.ifra_lifetime.ia6t_vltime = ia->prefix_vltime;
+ ifa.ifra_lifetime.ia6t_pltime = ia->prefix_pltime;
#undef ADDADDR
- r = ioctl(s, action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
- close(s);
- return r;
+ return ioctl(ia->iface->ctx->pf_inet6_fd,
+ action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
}
} rtm;
char *bp = rtm.buffer;
size_t l;
- int s, retval;
-
- if ((s = xsocket(PF_ROUTE, SOCK_RAW, 0, O_CLOEXEC)) == -1)
- return -1;
#define ADDSU { \
l = RT_ROUNDUP(su.sa.sa_len); \
#undef ADDSU
rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm);
- retval = write(s, &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0;
- close(s);
- return retval;
+ return write(rt->iface->ctx->link_fd,
+ &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0;
}
int
int
if_addrflags6(const struct in6_addr *addr, const struct interface *ifp)
{
- int s, flags;
+ int flags;
struct in6_ifreq ifr6;
- s = xsocket(PF_INET6, SOCK_DGRAM, 0, O_CLOEXEC);
- if (s == -1)
- return -1;
memset(&ifr6, 0, sizeof(ifr6));
strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr.sin6_family = AF_INET6;
ifr6.ifr_addr.sin6_addr = *addr;
ifa_scope(&ifr6.ifr_addr, ifp->index);
- if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) != -1)
+ if (ioctl(ifp->ctx->pf_inet6_fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
flags = ifr6.ifr_ifru.ifru_flags6;
else
flags = -1;
- close(s);
return flags;
}
int
if_getlifetime6(struct ipv6_addr *ia)
{
- int s, r;
+ int r;
struct in6_ifreq ifr6;
+ time_t t;
+ struct in6_addrlifetime *lifetime;
- s = xsocket(PF_INET6, SOCK_DGRAM, 0, O_CLOEXEC);
- if (s == -1)
- return -1;
r = -1;
memset(&ifr6, 0, sizeof(ifr6));
strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr.sin6_family = AF_INET6;
ifr6.ifr_addr.sin6_addr = ia->addr;
ifa_scope(&ifr6.ifr_addr, ia->iface->index);
- if (ioctl(s, SIOCGIFALIFETIME_IN6, &ifr6) == -1)
- goto out;
-
- time_t t;
- struct in6_addrlifetime *lifetime;
+ if (ioctl(ia->iface->ctx->pf_inet6_fd,
+ SIOCGIFALIFETIME_IN6, &ifr6) == -1)
+ return -1;
t = time(NULL);
lifetime = &ifr6.ifr_ifru.ifru_lifetime;
ia->created.tv_sec -= lifetime->ia6t_vltime - ia->prefix_vltime;
} else
ia->prefix_vltime = ND6_INFINITE_LIFETIME;
-
- r = 0;
-out:
- close(s);
- return r;
+ return 0;
}
#endif
int
if_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *ifp, int own)
{
- int s, r;
- if ((s = xsocket(PF_INET6, SOCK_DGRAM, 0, O_CLOEXEC)) == -1)
- return -1;
- r = _if_checkipv6(s, ctx, ifp, own);
- close(s);
- return r;
+ return _if_checkipv6(ctx->pf_inet6_fd, ctx, ifp, own);
}
#endif
/* XXX work out Virtal Interface Masters */
int
-if_vimaster(__unused const char *ifname)
+if_vimaster(__unused const struct dhcpcd_ctx *ctx, __unused const char *ifname)
{
return 0;
#include "ipv4ll.h"
#include "ipv6nd.h"
-#ifdef __QNX__
-/* QNX carries defines for, but does not actually support PF_LINK */
-#undef IFLR_ACTIVE
-#endif
-
void
if_free(struct interface *ifp)
{
}
int
-if_carrier(struct interface *iface)
+if_opensockets(struct dhcpcd_ctx *ctx)
+{
+
+ if ((ctx->link_fd = if_openlinksocket()) == -1)
+ return -1;
+
+ ctx->pf_inet_fd = xsocket(PF_INET, SOCK_DGRAM, 0, O_CLOEXEC);
+ if (ctx->pf_inet_fd == -1)
+ return -1;
+
+#if defined(INET6) && defined(BSD)
+ ctx->pf_inet6_fd = xsocket(PF_INET6, SOCK_DGRAM, 0, O_CLOEXEC);
+ if (ctx->pf_inet6_fd == -1)
+ return -1;
+#endif
+
+#ifdef IFLR_ACTIVE
+ ctx->pf_link_fd = xsocket(PF_LINK, SOCK_DGRAM, 0, O_CLOEXEC);
+ if (ctx->pf_link_fd == -1)
+ return -1;
+#endif
+
+ return 0;
+}
+
+int
+if_carrier(struct interface *ifp)
{
- int s, r;
+ int r;
struct ifreq ifr;
#ifdef SIOCGIFMEDIA
struct ifmediareq ifmr;
#endif
- if ((s = xsocket(PF_INET, SOCK_DGRAM, 0, O_CLOEXEC)) == -1)
- return LINK_UNKNOWN;
memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
- if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) {
- close(s);
+ strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
+ if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1)
return LINK_UNKNOWN;
- }
- iface->flags = (unsigned int)ifr.ifr_flags;
+ ifp->flags = (unsigned int)ifr.ifr_flags;
#ifdef SIOCGIFMEDIA
memset(&ifmr, 0, sizeof(ifmr));
- strlcpy(ifmr.ifm_name, iface->name, sizeof(ifmr.ifm_name));
- if (ioctl(s, SIOCGIFMEDIA, &ifmr) != -1 &&
+ strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name));
+ if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) != -1 &&
ifmr.ifm_status & IFM_AVALID)
r = (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN;
else
#else
r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN;
#endif
- close(s);
return r;
}
if_setflag(struct interface *ifp, short flag)
{
struct ifreq ifr;
- int s, r;
+ int r;
- if ((s = xsocket(PF_INET, SOCK_DGRAM, 0, O_CLOEXEC)) == -1)
- return -1;
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
r = -1;
- if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) {
+ if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == 0) {
if (flag == 0 || (ifr.ifr_flags & flag) == flag)
r = 0;
else {
ifr.ifr_flags |= flag;
- if (ioctl(s, SIOCSIFFLAGS, &ifr) == 0)
+ if (ioctl(ifp->ctx->pf_inet_fd, SIOCSIFFLAGS, &ifr) ==0)
r = 0;
}
ifp->flags = (unsigned int)ifr.ifr_flags;
}
- close(s);
return r;
}
const struct sockaddr_dl *sdl;
#ifdef SIOCGIFPRIORITY
struct ifreq ifr;
- int s_inet;
#endif
#ifdef IFLR_ACTIVE
struct if_laddrreq iflr;
- int s_link;
#endif
-#ifdef SIOCGIFPRIORITY
- if ((s_inet = xsocket(PF_INET, SOCK_DGRAM, 0, O_CLOEXEC)) == -1)
- return NULL;
-#endif
#ifdef IFLR_ACTIVE
- if ((s_link = xsocket(PF_LINK, SOCK_DGRAM, 0, O_CLOEXEC)) == -1) {
-#ifdef SIOCGIFPRIORITY
- close(s_inet);
-#endif
- return NULL;
- }
memset(&iflr, 0, sizeof(iflr));
#endif
#elif AF_PACKET
continue;
}
- if (if_vimaster(p) == 1) {
+ if (if_vimaster(ctx, p) == 1) {
logger(ctx, argc ? LOG_ERR : LOG_DEBUG,
"%s: is a Virtual Interface Master, skipping", p);
continue;
MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr)));
iflr.flags = IFLR_PREFIX;
iflr.prefixlen = (unsigned int)sdl->sdl_alen * NBBY;
- if (ioctl(s_link, SIOCGLIFADDR, &iflr) == -1 ||
+ if (ioctl(ctx->pf_link_fd, SIOCGLIFADDR, &iflr) == -1 ||
!(iflr.flags & IFLR_ACTIVE))
{
if_free(ifp);
}
/* Ensure that the MTU is big enough for DHCP */
- if (if_getmtu(ifp->name) < MTU_MIN &&
- if_setmtu(ifp->name, MTU_MIN) == -1)
+ if (if_getmtu(ifp) < MTU_MIN &&
+ if_setmtu(ifp, MTU_MIN) == -1)
{
logger(ifp->ctx, LOG_ERR, "%s: set_mtu: %m", p);
if_free(ifp);
/* Respect the interface priority */
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
- if (ioctl(s_inet, SIOCGIFPRIORITY, &ifr) == 0)
+ if (ioctl(ctx->pf_inet_fd, SIOCGIFPRIORITY, &ifr) == 0)
ifp->metric = ifr.ifr_metric;
#else
/* We reserve the 100 range for virtual interfaces, if and when
if_learnaddrs1(ctx, ifs, ifaddrs);
freeifaddrs(ifaddrs);
-#ifdef SIOCGIFPRIORITY
- close(s_inet);
-#endif
-#ifdef IFLR_ACTIVE
- close(s_link);
-#endif
-
return ifs;
}
}
int
-if_domtu(const char *ifname, short int mtu)
+if_domtu(const struct interface *ifp, short int mtu)
{
- int s, r;
+ int r;
struct ifreq ifr;
- if ((s = xsocket(PF_INET, SOCK_DGRAM, 0, O_CLOEXEC)) == -1)
- return -1;
memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
ifr.ifr_mtu = mtu;
- r = ioctl(s, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr);
- close(s);
+ r = ioctl(ifp->ctx->pf_inet_fd, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr);
if (r == -1)
return -1;
return ifr.ifr_mtu;
struct interface *if_findindex(struct if_head *, unsigned int);
void if_sortinterfaces(struct dhcpcd_ctx *);
void if_free(struct interface *);
-int if_domtu(const char *, short int);
-#define if_getmtu(iface) if_domtu(iface, 0)
-#define if_setmtu(iface, mtu) if_domtu(iface, mtu)
+int if_domtu(const struct interface *, short int);
+#define if_getmtu(ifp) if_domtu((ifp), 0)
+#define if_setmtu(ifp, mtu) if_domtu((ifp), (mtu))
int if_carrier(struct interface *);
/* The below functions are provided by if-KERNEL.c */
int if_conf(struct interface *);
int if_init(struct interface *);
int if_getssid(struct interface *);
-int if_vimaster(const char *);
+int if_vimaster(const struct dhcpcd_ctx *ctx, const char *);
+int if_opensockets(struct dhcpcd_ctx *);
int if_openlinksocket(void);
int if_managelink(struct dhcpcd_ctx *);
EMALLOC(6, e);
snprintf(env[6], e, "ifflags=%u", ifp->flags);
EMALLOC(7, e);
- snprintf(env[7], e, "ifmtu=%d", if_getmtu(ifp->name));
+ snprintf(env[7], e, "ifmtu=%d", if_getmtu(ifp));
l = e = strlen("interface_order=");
TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
e += strlen(ifp2->name) + 1;