summaryrefslogtreecommitdiffstats
path: root/if-bsd.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2014-05-02 23:54:29 +0000
committerRoy Marples <roy@marples.name>2014-05-02 23:54:29 +0000
commit68e672702b8683e64e6c93d2687bd8f47f74c760 (patch)
tree792ab89786b036a4d44ee9e5df5ef39b2948024f /if-bsd.c
parent94cb985a8e37779af588a3c70b64b91a3b391547 (diff)
downloaddhcpcd-68e672702b8683e64e6c93d2687bd8f47f74c760.tar.xz
Change the readrawsocket API a little so that we know when EOF is reached.
This allows us to remove the non blocking option from our sockets due to the way BPF works.
Diffstat (limited to 'if-bsd.c')
-rw-r--r--if-bsd.c268
1 files changed, 124 insertions, 144 deletions
diff --git a/if-bsd.c b/if-bsd.c
index b36ccfd9..474ec038 100644
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -114,7 +114,7 @@ if_openlinksocket(void)
{
#ifdef SOCK_CLOEXEC
- return socket(PF_ROUTE, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
+ return socket(PF_ROUTE, SOCK_RAW | SOCK_CLOEXEC, 0);
#else
int s, flags;
@@ -126,12 +126,6 @@ if_openlinksocket(void)
close(s);
return -1;
}
- if ((flags = fcntl(s, F_GETFL, 0)) == -1 ||
- fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
- {
- close(s);
- return -1;
- }
return s;
#endif
}
@@ -228,14 +222,14 @@ if_openrawsocket(struct interface *ifp, int protocol)
int flags;
#endif
#ifdef _PATH_BPF
- fd = open(_PATH_BPF, O_RDWR | O_CLOEXEC | O_NONBLOCK);
+ fd = open(_PATH_BPF, O_RDWR | O_CLOEXEC);
#else
char device[32];
int n = 0;
do {
snprintf(device, sizeof(device), "/dev/bpf%d", n++);
- fd = open(device, O_RDWR | O_CLOEXEC | O_NONBLOCK);
+ fd = open(device, O_RDWR | O_CLOEXEC);
} while (fd == -1 && errno == EBUSY);
#endif
@@ -289,13 +283,6 @@ if_openrawsocket(struct interface *ifp, int protocol)
if (ioctl(fd, BIOCSETF, &pf) == -1)
goto eexit;
-#ifdef __OpenBSD__
- /* For some reason OpenBSD fails to open the fd as non blocking */
- if ((flags = fcntl(fd, F_GETFL, 0)) == -1 ||
- fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
- goto eexit;
-#endif
-
return fd;
eexit:
@@ -333,9 +320,9 @@ if_sendrawpacket(const struct interface *ifp, int protocol,
* So we pass the buffer in the API so we can loop on >1 packet. */
ssize_t
if_readrawpacket(struct interface *ifp, int protocol,
- void *data, size_t len, int *partialcsum)
+ void *data, size_t len, int *flags)
{
- int fd = -1;
+ int fd;
struct bpf_hdr packet;
ssize_t bytes;
const unsigned char *payload;
@@ -347,16 +334,14 @@ if_readrawpacket(struct interface *ifp, int protocol,
else
fd = state->raw_fd;
- if (partialcsum != NULL)
- *partialcsum = 0; /* Not supported on BSD */
+ if (flags != NULL)
+ *flags = 0; /* Not supported on BSD */
for (;;) {
if (state->buffer_len == 0) {
bytes = read(fd, state->buffer, state->buffer_size);
- if (bytes == -1)
- return errno == EAGAIN ? 0 : -1;
- else if ((size_t)bytes < sizeof(packet))
- return -1;
+ if (bytes == -1 || bytes == 0)
+ return bytes;
state->buffer_len = (size_t)bytes;
state->buffer_pos = 0;
}
@@ -377,8 +362,10 @@ if_readrawpacket(struct interface *ifp, int protocol,
next:
state->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen +
packet.bh_caplen);
- if (state->buffer_pos >= state->buffer_len)
+ if (state->buffer_pos >= state->buffer_len) {
state->buffer_len = state->buffer_pos = 0;
+ *flags |= RAW_EOF;
+ }
if (bytes != -1)
return bytes;
}
@@ -774,143 +761,136 @@ if_managelink(struct dhcpcd_ctx *ctx)
int ifa_flags;
#endif
- for (;;) {
- bytes = read(ctx->link_fd, msg, sizeof(msg));
- if (bytes == -1) {
- if (errno == EAGAIN)
- return 0;
- if (errno == EINTR)
- continue;
- return -1;
- }
- e = msg + bytes;
- for (p = msg; p < e; p += rtm->rtm_msglen) {
- rtm = (struct rt_msghdr *)(void *)p;
- // Ignore messages generated by us
- if (rtm->rtm_pid == getpid())
- break;
- switch(rtm->rtm_type) {
+ bytes = read(ctx->link_fd, msg, sizeof(msg));
+ if (bytes == -1 || bytes == 0)
+ return bytes;
+ e = msg + bytes;
+ for (p = msg; p < e; p += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)(void *)p;
+ // Ignore messages generated by us
+ if (rtm->rtm_pid == getpid())
+ break;
+ switch(rtm->rtm_type) {
#ifdef RTM_IFANNOUNCE
- case RTM_IFANNOUNCE:
- ifan = (struct if_announcemsghdr *)(void *)p;
- switch(ifan->ifan_what) {
- case IFAN_ARRIVAL:
- dhcpcd_handleinterface(ctx, 1,
- ifan->ifan_name);
- break;
- case IFAN_DEPARTURE:
- dhcpcd_handleinterface(ctx, -1,
- ifan->ifan_name);
- break;
- }
+ case RTM_IFANNOUNCE:
+ ifan = (struct if_announcemsghdr *)(void *)p;
+ switch(ifan->ifan_what) {
+ case IFAN_ARRIVAL:
+ dhcpcd_handleinterface(ctx, 1,
+ ifan->ifan_name);
break;
+ case IFAN_DEPARTURE:
+ dhcpcd_handleinterface(ctx, -1,
+ ifan->ifan_name);
+ break;
+ }
+ break;
#endif
- case RTM_IFINFO:
- ifm = (struct if_msghdr *)(void *)p;
- memset(ifname, 0, sizeof(ifname));
- if (!(if_indextoname(ifm->ifm_index, ifname)))
- break;
- switch (ifm->ifm_data.ifi_link_state) {
- case LINK_STATE_DOWN:
- len = LINK_DOWN;
- break;
- case LINK_STATE_UP:
- len = LINK_UP;
- break;
- default:
- /* handle_carrier will re-load
- * the interface flags and check for
- * IFF_RUNNING as some drivers that
- * don't handle link state also don't
- * set IFF_RUNNING when this routing
- * message is generated.
- * As such, it is a race ...*/
- len = LINK_UNKNOWN;
- break;
- }
- dhcpcd_handlecarrier(ctx, len,
- (unsigned int)ifm->ifm_flags, ifname);
+ case RTM_IFINFO:
+ ifm = (struct if_msghdr *)(void *)p;
+ memset(ifname, 0, sizeof(ifname));
+ if (!(if_indextoname(ifm->ifm_index, ifname)))
+ break;
+ switch (ifm->ifm_data.ifi_link_state) {
+ case LINK_STATE_DOWN:
+ len = LINK_DOWN;
+ break;
+ case LINK_STATE_UP:
+ len = LINK_UP;
+ break;
+ default:
+ /* handle_carrier will re-load
+ * the interface flags and check for
+ * IFF_RUNNING as some drivers that
+ * don't handle link state also don't
+ * set IFF_RUNNING when this routing
+ * message is generated.
+ * As such, it is a race ...*/
+ len = LINK_UNKNOWN;
+ break;
+ }
+ dhcpcd_handlecarrier(ctx, len,
+ (unsigned int)ifm->ifm_flags, ifname);
+ break;
+ case RTM_DELETE:
+ if (~rtm->rtm_addrs &
+ (RTA_DST | RTA_GATEWAY | RTA_NETMASK))
+ break;
+ cp = (char *)(void *)(rtm + 1);
+ sa = (struct sockaddr *)(void *)cp;
+ if (sa->sa_family != AF_INET)
break;
- case RTM_DELETE:
- if (~rtm->rtm_addrs &
- (RTA_DST | RTA_GATEWAY | RTA_NETMASK))
- break;
- cp = (char *)(void *)(rtm + 1);
- sa = (struct sockaddr *)(void *)cp;
- if (sa->sa_family != AF_INET)
- break;
#ifdef INET
- get_addrs(rtm->rtm_addrs, cp, rti_info);
- memset(&rt, 0, sizeof(rt));
- rt.iface = NULL;
- COPYOUT(rt.dest, rti_info[RTAX_DST]);
- COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
- COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]);
- ipv4_routedeleted(ctx, &rt);
+ get_addrs(rtm->rtm_addrs, cp, rti_info);
+ memset(&rt, 0, sizeof(rt));
+ rt.iface = NULL;
+ COPYOUT(rt.dest, rti_info[RTAX_DST]);
+ COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
+ COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]);
+ ipv4_routedeleted(ctx, &rt);
#endif
- break;
+ break;
#ifdef RTM_CHGADDR
- case RTM_CHGADDR: /* FALLTHROUGH */
+ case RTM_CHGADDR: /* FALLTHROUGH */
#endif
- case RTM_DELADDR: /* FALLTHROUGH */
- case RTM_NEWADDR:
- ifam = (struct ifa_msghdr *)(void *)p;
- if (!if_indextoname(ifam->ifam_index, ifname))
- break;
- cp = (char *)(void *)(ifam + 1);
- get_addrs(ifam->ifam_addrs, cp, rti_info);
- if (rti_info[RTAX_IFA] == NULL)
- break;
- switch (rti_info[RTAX_IFA]->sa_family) {
- case AF_LINK:
+ case RTM_DELADDR: /* FALLTHROUGH */
+ case RTM_NEWADDR:
+ ifam = (struct ifa_msghdr *)(void *)p;
+ if (!if_indextoname(ifam->ifam_index, ifname))
+ break;
+ cp = (char *)(void *)(ifam + 1);
+ get_addrs(ifam->ifam_addrs, cp, rti_info);
+ if (rti_info[RTAX_IFA] == NULL)
+ break;
+ switch (rti_info[RTAX_IFA]->sa_family) {
+ case AF_LINK:
#ifdef RTM_CHGADDR
- if (rtm->rtm_type != RTM_CHGADDR)
- break;
+ if (rtm->rtm_type != RTM_CHGADDR)
+ break;
#else
- if (rtm->rtm_type != RTM_NEWADDR)
- break;
-#endif
- memcpy(&sdl, rti_info[RTAX_IFA],
- rti_info[RTAX_IFA]->sa_len);
- dhcpcd_handlehwaddr(ctx, ifname,
- (const unsigned char*)CLLADDR(&sdl),
- sdl.sdl_alen);
+ if (rtm->rtm_type != RTM_NEWADDR)
break;
+#endif
+ memcpy(&sdl, rti_info[RTAX_IFA],
+ rti_info[RTAX_IFA]->sa_len);
+ dhcpcd_handlehwaddr(ctx, ifname,
+ (const unsigned char*)CLLADDR(&sdl),
+ sdl.sdl_alen);
+ break;
#ifdef INET
- case AF_INET:
- case 255: /* FIXME: Why 255? */
- COPYOUT(rt.dest, rti_info[RTAX_IFA]);
- COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
- COPYOUT(rt.gate, rti_info[RTAX_BRD]);
- ipv4_handleifa(ctx, rtm->rtm_type,
- NULL, ifname,
- &rt.dest, &rt.net, &rt.gate);
- break;
+ case AF_INET:
+ case 255: /* FIXME: Why 255? */
+ COPYOUT(rt.dest, rti_info[RTAX_IFA]);
+ COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
+ COPYOUT(rt.gate, rti_info[RTAX_BRD]);
+ ipv4_handleifa(ctx, rtm->rtm_type,
+ NULL, ifname,
+ &rt.dest, &rt.net, &rt.gate);
+ break;
#endif
#ifdef INET6
- case AF_INET6:
- sin6 = (struct sockaddr_in6*)(void *)
- rti_info[RTAX_IFA];
- memcpy(ia6.s6_addr,
- sin6->sin6_addr.s6_addr,
- sizeof(ia6.s6_addr));
- if (rtm->rtm_type == RTM_NEWADDR) {
- ifa_flags = if_addrflags6(
- ifname,
- &ia6);
- if (ifa_flags == -1)
- break;
- } else
- ifa_flags = 0;
- ipv6_handleifa(ctx, rtm->rtm_type, NULL,
- ifname, &ia6, ifa_flags);
- break;
-#endif
- }
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6*)(void *)
+ rti_info[RTAX_IFA];
+ memcpy(ia6.s6_addr,
+ sin6->sin6_addr.s6_addr,
+ sizeof(ia6.s6_addr));
+ if (rtm->rtm_type == RTM_NEWADDR) {
+ ifa_flags = if_addrflags6(ifname, &ia6);
+ if (ifa_flags == -1)
+ break;
+ } else
+ ifa_flags = 0;
+ ipv6_handleifa(ctx, rtm->rtm_type, NULL,
+ ifname, &ia6, ifa_flags);
break;
+#endif
}
+ break;
}
}
+
+ return 0;
}
#ifndef SYS_NMLN /* OSX */