unsigned short vlanid;
unsigned int metric;
int carrier;
- bool media_valid;
bool wireless;
uint8_t ssid[IF_SSIDLEN];
unsigned int ssid_len;
close(priv->pf_inet6_fd);
}
+static int
+if_carrier_flags(struct interface *ifp, unsigned int flags)
+{
+ struct ifmediareq ifmr = { .ifm_status = 0 };
+
+ 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))
+ return flags & IFF_RUNNING ? LINK_UP : LINK_UNKNOWN;
+
+ return (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN;
+}
+
+int
+if_carrier(struct interface *ifp)
+{
+
+ if (if_getflags(ifp) == -1)
+ return LINK_UNKNOWN;
+ return if_carrier_flags(ifp, ifp->flags);
+}
+
static void
if_linkaddr(struct sockaddr_dl *sdl, const struct interface *ifp)
{
{
struct interface *ifp;
int link_state;
+ unsigned int flags;
if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL)
return;
+ flags = (unsigned int)ifm->ifm_flags;
switch (ifm->ifm_data.ifi_link_state) {
case LINK_STATE_UNKNOWN:
- if (ifp->media_valid) {
+ /* In theory this is only set when an interface is first
+ * initiaised.
+ * However whilst some drivers report an active link
+ * via SIOCGIFMEDIA, they don't bother to announce it
+ * via a routing message. */
+ if (ifp->wireless) /* Wireless need to work correctly. */
link_state = LINK_DOWN;
- break;
- }
- /* Interface does not report media state, so we have
- * to rely on IFF_UP. */
- /* FALLTHROUGH */
+ else
+ link_state = if_carrier_flags(ifp, flags);
+ break;
case LINK_STATE_UP:
link_state = ifm->ifm_flags & IFF_UP ? LINK_UP : LINK_DOWN;
break;
break;
}
- dhcpcd_handlecarrier(ctx, link_state,
- (unsigned int)ifm->ifm_flags, ifp->name);
+ dhcpcd_handlecarrier(ctx, link_state, flags, ifp->name);
}
static void
}
}
+int
+if_carrier(struct interface *ifp)
+{
+
+ if (if_getflags(ifp) == -1)
+ return LINK_UNKNOWN;
+ return ifp->flags & IFF_RUNNING ? LINK_UP : LINK_DOWN;
+}
+
static int
get_netlink(struct dhcpcd_ctx *ctx, struct iovec *iov,
struct interface *ifp, int fd, int flags,
}
int
-if_carrier_os(struct interface *ifp)
+if_carrier(struct interface *ifp)
{
kstat_ctl_t *kcp;
kstat_t *ksp;
kstat_named_t *knp;
link_state_t linkstate;
+ if (if_getflags(ifp) == -1)
+ return LINK_UNKNOWN;
+
kcp = kstat_open();
if (kcp == NULL)
goto err;
}
int
-if_carrier(struct interface *ifp)
+if_getflags(struct interface *ifp)
{
- int r;
- struct ifreq ifr;
-#ifdef SIOCGIFMEDIA
- struct ifmediareq ifmr;
-#endif
+ struct ifreq ifr = { .ifr_flags = 0 };
- memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
- r = ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr);
- if (r != -1)
- ifp->flags = (unsigned int)ifr.ifr_flags;
-
-#ifdef __sun
- return if_carrier_os(ifp);
-#else
- if (r == -1)
- return LINK_UNKNOWN;
-
-#ifdef SIOCGIFMEDIA
- memset(&ifmr, 0, sizeof(ifmr));
- 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)
- {
- ifp->media_valid = true;
- r = (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN;
- } else {
- ifp->media_valid = false;
- r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_UNKNOWN;
- }
-#else
- r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN;
-#endif
-#endif /* __sun */
- return r;
+ if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1)
+ return -1;
+ ifp->flags = (unsigned int)ifr.ifr_flags;
+ return 0;
}
int
if_setflag(struct interface *ifp, short flag)
{
- struct ifreq ifr;
- int r;
+ struct ifreq ifr = { .ifr_flags = 0 };
+ short f;
+
+ if (if_getflags(ifp) == -1)
+ return -1;
+
+ f = (short)ifp->flags;
+ if ((f & flag) == flag)
+ return 0;
- memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
- r = -1;
- 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(ifp->ctx->pf_inet_fd, SIOCSIFFLAGS, &ifr) ==0)
- r = 0;
- }
- ifp->flags = (unsigned int)ifr.ifr_flags;
- }
- return r;
+ ifr.ifr_flags = f | flag;
+ if (ioctl(ifp->ctx->pf_inet_fd, SIOCSIFFLAGS, &ifr) == -1)
+ return -1;
+
+ ifp->flags = (unsigned int)ifr.ifr_flags;
+ return 0;
}
static int
#define getifaddrs if_getifaddrs
#endif
+int if_getflags(struct interface *ifp);
int if_setflag(struct interface *ifp, short flag);
#define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING))
bool if_valid_hwaddr(const uint8_t *, size_t);
int if_makealias(char *, size_t, const char *, int);
#endif
-int if_carrier_os(struct interface *);
int if_mtu_os(const struct interface *);
/*