int master = 0;
int pidfd = -1;
+static char **ifv = NULL;
+static int ifc = 0;
static int linkfd = -1;
static char cffile[PATH_MAX];
static char pidfile[PATH_MAX] = { '\0' };
{
struct interface *ifp, *ifl = NULL;
+ logger(LOG_ERR, "%s: removing interface", iface->name);
drop_config(iface, "STOP");
close_sockets(iface);
delete_timeout(NULL, iface);
}
free(dhcp);
if (r == -1) {
- logger(LOG_ERR, "%s: removing interface from dhcpcd",
- iface->name);
stop_interface(iface);
} else {
if (callback)
}
static void
-handle_link(_unused void *arg)
+handle_carrier(struct interface *iface)
{
- struct interface *iface;
- int retval;
-
- retval = link_changed(linkfd, ifaces);
- if (retval == -1) {
- logger(LOG_ERR, "link_changed: %s", strerror(errno));
+ if (!(iface->state->options->options & DHCPCD_LINK))
return;
- }
- if (retval == 0)
- return;
- for (iface = ifaces; iface; iface = iface->next) {
- if (iface->state->options->options & DHCPCD_LINK) {
- switch (carrier_status(iface->name)) {
- case -1:
- logger(LOG_ERR, "carrier_status: %s",
- strerror(errno));
- break;
- case 0:
- if (iface->state->carrier != LINK_DOWN) {
- iface->state->carrier = LINK_DOWN;
- logger(LOG_INFO, "%s: carrier lost",
- iface->name);
- close_sockets(iface);
- delete_timeouts(iface, start_expire, NULL);
- }
- break;
- default:
- if (iface->state->carrier != LINK_UP) {
- iface->state->carrier = LINK_UP;
- logger(LOG_INFO, "%s: carrier acquired",
- iface->name);
- start_interface(iface);
- }
- break;
- }
+ switch (carrier_status(iface->name)) {
+ case -1:
+ logger(LOG_ERR, "carrier_status: %s", strerror(errno));
+ break;
+ case 0:
+ if (iface->state->carrier != LINK_DOWN) {
+ iface->state->carrier = LINK_DOWN;
+ logger(LOG_INFO, "%s: carrier lost", iface->name);
+ close_sockets(iface);
+ delete_timeouts(iface, start_expire, NULL);
+ }
+ break;
+ default:
+ if (iface->state->carrier != LINK_UP) {
+ iface->state->carrier = LINK_UP;
+ logger(LOG_INFO, "%s: carrier acquired", iface->name);
+ start_interface(iface);
}
+ break;
}
}
start_interface(iface);
}
+static void
+handle_new_interface(const char *name)
+{
+ struct interface *ifs, *ifp;
+ const char * const argv[] = { "dhcpcd", name };
+ int i;
+
+ /* If running off an interface list, check it's in it. */
+ if (ifc) {
+ for (i = 0; i < ifc; i++)
+ if (strcmp(ifv[i], name) == 0)
+ break;
+ if (i >= ifc)
+ return;
+ }
+
+ if ((ifs = discover_interfaces(2, UNCONST(argv)))) {
+ for (ifp = ifs; ifp; ifp = ifp->next)
+ init_state(ifp, 2, UNCONST(argv));
+ if (ifaces) {
+ ifp = ifaces;
+ while (ifp->next)
+ ifp = ifp->next;
+ ifp->next = ifs;
+ } else
+ ifaces = ifs;
+ }
+}
+
+static void
+handle_link(_unused void *arg)
+{
+ if (manage_link(linkfd, ifaces, handle_carrier,
+ handle_new_interface, stop_interface) == -1)
+ logger(LOG_ERR, "manage_link: %s", strerror(errno));
+}
+
static void
handle_signal(_unused void *arg)
{
}
free_options(ifo);
- argc -= optind;
- argv += optind;
- ifaces = discover_interfaces(argc, argv);
- argc += optind;
- argv -= optind;
+ ifc = argc - optind;
+ ifv = argv + optind;
+ ifaces = discover_interfaces(ifc, ifv);
for (iface = ifaces; iface; iface = iface->next)
init_state(iface, argc, argv);
+ if (!ifaces && ifc == 1) {
+ logger(LOG_ERR, "interface `%s' does not exist", ifv[0]);
+ exit(EXIT_FAILURE);
+ }
start_eloop();
/* NOTREACHED */
}
int fd;
fd = socket(PF_ROUTE, SOCK_RAW, 0);
- if (fd != -1)
+ if (fd != -1) {
set_cloexec(fd);
+ set_nonblock(fd);
+ }
return fd;
}
#define BUFFER_LEN 2048
int
-link_changed(int fd, const struct interface *ifaces)
+manage_link(int fd, struct interface *ifaces,
+ void (*if_carrier)(struct interface *),
+ void (*if_add)(const char *),
+ void (*if_remove)(struct interface *))
{
char buffer[2048], *p;
ssize_t bytes;
struct rt_msghdr *rtm;
+ struct if_announcemsghdr *ifa;
struct if_msghdr *ifm;
- const struct interface *iface;
+ struct interface *iface;
for (;;) {
- bytes = recv(fd, buffer, BUFFER_LEN, MSG_DONTWAIT);
+ bytes = read(fd, buffer, BUFFER_LEN);
if (bytes == -1) {
if (errno == EAGAIN)
return 0;
p += ((struct rt_msghdr *)p)->rtm_msglen)
{
rtm = (struct rt_msghdr *)p;
- if (rtm->rtm_type != RTM_IFINFO)
- continue;
- ifm = (struct if_msghdr *)p;
- for (iface = ifaces; iface; iface = iface->next)
- if (ifm->ifm_index == if_nametoindex(iface->name))
- return 1;
+ switch(rtm->rtm_type) {
+ case RTM_IFANNOUNCE:
+ ifa = (struct if_announcemsghdr *)p;
+ switch(ifa->ifan_what) {
+ case IFAN_ARRIVAL:
+ if_add(ifa->ifan_name);
+ break;
+ case IFAN_DEPARTURE:
+ for (iface = ifaces; iface; iface = iface->next)
+ if (strcmp(ifa->ifan_name, iface->name) == 0) {
+ if_remove(iface);
+ break;
+ }
+ break;
+ }
+ break;
+ case RTM_IFINFO:
+ ifm = (struct if_msghdr *)p;
+ for (iface = ifaces; iface; iface = iface->next)
+ if (ifm->ifm_index == if_nametoindex(iface->name)) {
+ if_carrier(iface);
+ break;
+ }
+ break;
+ }
}
}
}