diff options
| author | Roy Marples <roy@marples.name> | 2008-09-04 11:30:11 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2008-09-04 11:30:11 +0000 |
| commit | 96d0673a2cd58d50f0e4c8e0c60b332a7fff92a8 (patch) | |
| tree | 1ca3996de4d29132abaca0a485c47b3e6509a47c /if-bsd.c | |
| parent | 4570862e65882adb2b2b60e45b6ba7e6dec21229 (diff) | |
| download | dhcpcd-96d0673a2cd58d50f0e4c8e0c60b332a7fff92a8.tar.xz | |
When OS reports new and removed interfaces, dhcpcd sees this and either starts or stops watching them. BSD only, Linux to follow.
Diffstat (limited to 'if-bsd.c')
| -rw-r--r-- | if-bsd.c | 45 |
1 files changed, 35 insertions, 10 deletions
@@ -187,23 +187,29 @@ open_link_socket(void) 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; @@ -216,12 +222,31 @@ link_changed(int fd, const struct interface *ifaces) 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; + } } } } |
