dhcp6_handleifa(int cmd, struct ipv6_addr *ia)
{
struct dhcp6_state *state;
+ struct interface *ifp = ia->iface;
/* If not running in master mode, listen to this address */
if (cmd == RTM_NEWADDR &&
!(ia->addr_flags & IN6_IFF_NOTUSEABLE) &&
- ia->iface->active == IF_ACTIVE_USER &&
- !(ia->iface->ctx->options & DHCPCD_MASTER) &&
+ ifp->active == IF_ACTIVE_USER &&
+ !(ifp->ctx->options & DHCPCD_MASTER) &&
+ ifp->options->options & DHCPCD_DHCP6 &&
ia->dhcp6_fd == -1)
dhcp6_listen(ia->iface->ctx, ia);
- if ((state = D6_STATE(ia->iface)) != NULL)
+ if ((state = D6_STATE(ifp)) != NULL)
ipv6_handleifa_addrs(cmd, &state->addrs, ia);
}
dhcpcd_handleinterface(void *arg, int action, const char *ifname)
{
struct dhcpcd_ctx *ctx;
+ struct ifaddrs *ifaddrs;
struct if_head *ifs;
struct interface *ifp, *iff, *ifn;
const char * const argv[] = { ifname };
}
i = -1;
- ifs = if_discover(ctx, -1, UNCONST(argv));
+ ifs = if_discover(ctx, &ifaddrs, -1, UNCONST(argv));
if (ifs == NULL) {
logerr(__func__);
return -1;
dhcpcd_prestartinterface(iff);
}
+ if_learnaddrs(ctx, ifs, &ifaddrs);
+
+ /* Now we have learned addresses, start the interface */
+ TAILQ_FOREACH_SAFE(ifp, ifs, next, ifn) {
+ if (strcmp(ifp->name, ifname) != 0)
+ continue;
+ iff = if_find(ctx->ifaces, ifp->name);
+ if (action > 0 && iff->active)
+ dhcpcd_prestartinterface(iff);
+ }
+
/* Free our discovered list */
while ((ifp = TAILQ_FIRST(ifs))) {
TAILQ_REMOVE(ifs, ifp, next);
main(int argc, char **argv)
{
struct dhcpcd_ctx ctx;
+ struct ifaddrs *ifaddrs = NULL;
struct if_options *ifo;
struct interface *ifp;
uint16_t family = 0;
if (optind != argc) {
/* We need to try and find the interface so we can load
* the hardware address to compare automated IAID */
- ctx.ifaces = if_discover(&ctx,
+ ctx.ifaces = if_discover(&ctx, &ifaddrs,
argc - optind, argv + optind);
} else {
if ((ctx.ifaces = malloc(sizeof(*ctx.ifaces))) != NULL)
(DHCPCD_MASTER | DHCPCD_DEV))
dev_start(&ctx);
- ctx.ifaces = if_discover(&ctx, ctx.ifc, ctx.ifv);
+ ctx.ifaces = if_discover(&ctx, &ifaddrs, ctx.ifc, ctx.ifv);
if (ctx.ifaces == NULL) {
logerr("%s: if_discover", __func__);
goto exit_failure;
if (ifp->active)
dhcpcd_initstate1(ifp, argc, argv, 0);
}
+ if_learnaddrs(&ctx, ctx.ifaces, &ifaddrs);
if (ctx.options & DHCPCD_BACKGROUND && dhcpcd_daemonise(&ctx))
goto exit_success;
i = EXIT_FAILURE;
exit1:
+ if (ifaddrs != NULL)
+ freeifaddrs(ifaddrs);
if (control_stop(&ctx) == -1)
logerr("%s: control_stop", __func__);
/* Free memory and close fd's */
return 0;
}
-static void if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs,
- struct ifaddrs *ifaddrs)
+void
+if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs,
+ struct ifaddrs **ifaddrs)
{
struct ifaddrs *ifa;
struct interface *ifp;
#endif
int addrflags;
- for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
+ for (ifa = *ifaddrs; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
continue;
if ((ifp = if_find(ifs, ifa->ifa_name)) == NULL)
#endif
}
}
+
+ freeifaddrs(*ifaddrs);
+ *ifaddrs = NULL;
}
bool
}
struct if_head *
-if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
+if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
+ int argc, char * const *argv)
{
- struct ifaddrs *ifaddrs, *ifa;
+ struct ifaddrs *ifa;
int i;
unsigned int active;
struct if_head *ifs;
const struct sockaddr_ll *sll;
#endif
- if (getifaddrs(&ifaddrs) == -1)
+ if ((ifs = malloc(sizeof(*ifs))) == NULL) {
+ logerr(__func__);
return NULL;
-
- if ((ifs = malloc(sizeof(*ifs))) == NULL)
- goto failed;
+ }
TAILQ_INIT(ifs);
+ if (getifaddrs(ifaddrs) == -1) {
+ logerr(__func__);
+ goto out;
+ }
- for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
+ for (ifa = *ifaddrs; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_addr != NULL) {
#ifdef AF_LINK
if (ifa->ifa_addr->sa_family != AF_LINK)
TAILQ_INSERT_TAIL(ifs, ifp, next);
}
- if_learnaddrs(ctx, ifs, ifaddrs);
-failed:
- freeifaddrs(ifaddrs);
+out:
return ifs;
}
#include <netinet/in_var.h> /* for IN_IFF_TENTATIVE et all */
#endif
+#include <ifaddrs.h>
+
/* Some systems have in-built IPv4 DAD.
* However, we need them to do DAD at carrier up as well. */
#ifdef IN_IFF_TENTATIVE
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);
-struct if_head *if_discover(struct dhcpcd_ctx *, int, char * const *);
+struct if_head *if_discover(struct dhcpcd_ctx *, struct ifaddrs **,
+ int, char * const *);
+void if_learnaddrs(struct dhcpcd_ctx *, struct if_head *, struct ifaddrs **);
struct interface *if_find(struct if_head *, const char *);
struct interface *if_findindex(struct if_head *, unsigned int);
struct interface *if_loopback(struct dhcpcd_ctx *);