mirror of
https://github.com/rsmarples/dhcpcd.git
synced 2024-11-27 12:03:45 +08:00
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.
This commit is contained in:
parent
94cb985a8e
commit
68e672702b
12
arp.c
12
arp.c
@ -134,14 +134,20 @@ arp_packet(void *arg)
|
||||
const char *hwaddr;
|
||||
struct in_addr ina;
|
||||
char hwbuf[HWADDR_LEN * 3];
|
||||
int flags;
|
||||
|
||||
state = D_STATE(ifp);
|
||||
state->fail.s_addr = 0;
|
||||
for(;;) {
|
||||
flags = 0;
|
||||
while (!(flags & RAW_EOF)) {
|
||||
bytes = if_readrawpacket(ifp, ETHERTYPE_ARP,
|
||||
arp_buffer, sizeof(arp_buffer), NULL);
|
||||
if (bytes == 0 || bytes == -1)
|
||||
arp_buffer, sizeof(arp_buffer), &flags);
|
||||
if (bytes == 0 || bytes == -1) {
|
||||
syslog(LOG_ERR, "%s: arp if_readrawpacket: %m",
|
||||
ifp->name);
|
||||
dhcp_close(ifp);
|
||||
return;
|
||||
}
|
||||
/* We must have a full ARP header */
|
||||
if ((size_t)bytes < sizeof(ar))
|
||||
continue;
|
||||
|
55
dhcp.c
55
dhcp.c
@ -2557,55 +2557,58 @@ valid_udp_packet(const uint8_t *data, size_t data_len, struct in_addr *from,
|
||||
static void
|
||||
dhcp_handlepacket(void *arg)
|
||||
{
|
||||
struct interface *iface = arg;
|
||||
struct interface *ifp = arg;
|
||||
struct dhcp_message *dhcp = NULL;
|
||||
const uint8_t *pp;
|
||||
size_t bytes;
|
||||
struct in_addr from;
|
||||
int i, partialcsum = 0;
|
||||
const struct dhcp_state *state = D_CSTATE(iface);
|
||||
int i, flags;
|
||||
const struct dhcp_state *state = D_CSTATE(ifp);
|
||||
|
||||
/* We loop through until our buffer is empty.
|
||||
* The benefit is that if we get >1 DHCP packet in our buffer and
|
||||
* the first one fails for any reason, we can use the next. */
|
||||
for(;;) {
|
||||
bytes = (size_t)if_readrawpacket(iface, ETHERTYPE_IP,
|
||||
iface->ctx->packet, udp_dhcp_len, &partialcsum);
|
||||
if (bytes == 0 || (ssize_t)bytes == -1)
|
||||
/* Need this API due to BPF */
|
||||
flags = 0;
|
||||
while (!(flags & RAW_EOF)) {
|
||||
bytes = (size_t)if_readrawpacket(ifp, ETHERTYPE_IP,
|
||||
ifp->ctx->packet, udp_dhcp_len, &flags);
|
||||
if (bytes == 0 || (ssize_t)bytes == -1) {
|
||||
syslog(LOG_ERR, "%s: dhcp if_readrawpacket: %m",
|
||||
ifp->name);
|
||||
dhcp_close(ifp);
|
||||
break;
|
||||
if (valid_udp_packet(iface->ctx->packet, bytes,
|
||||
&from, partialcsum) == -1)
|
||||
}
|
||||
if (valid_udp_packet(ifp->ctx->packet, bytes,
|
||||
&from, flags & RAW_PARTIALCSUM) == -1)
|
||||
{
|
||||
syslog(LOG_ERR, "%s: invalid UDP packet from %s",
|
||||
iface->name, inet_ntoa(from));
|
||||
ifp->name, inet_ntoa(from));
|
||||
continue;
|
||||
}
|
||||
i = whitelisted_ip(iface->options, from.s_addr);
|
||||
i = whitelisted_ip(ifp->options, from.s_addr);
|
||||
if (i == 0) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s: non whitelisted DHCP packet from %s",
|
||||
iface->name, inet_ntoa(from));
|
||||
ifp->name, inet_ntoa(from));
|
||||
continue;
|
||||
} else if (i != 1 &&
|
||||
blacklisted_ip(iface->options, from.s_addr) == 1)
|
||||
blacklisted_ip(ifp->options, from.s_addr) == 1)
|
||||
{
|
||||
syslog(LOG_WARNING,
|
||||
"%s: blacklisted DHCP packet from %s",
|
||||
iface->name, inet_ntoa(from));
|
||||
ifp->name, inet_ntoa(from));
|
||||
continue;
|
||||
}
|
||||
if (iface->flags & IFF_POINTOPOINT &&
|
||||
if (ifp->flags & IFF_POINTOPOINT &&
|
||||
state->dst.s_addr != from.s_addr)
|
||||
{
|
||||
syslog(LOG_WARNING,
|
||||
"%s: server %s is not destination",
|
||||
iface->name, inet_ntoa(from));
|
||||
ifp->name, inet_ntoa(from));
|
||||
}
|
||||
bytes = get_udp_data(&pp, iface->ctx->packet);
|
||||
bytes = get_udp_data(&pp, ifp->ctx->packet);
|
||||
if (bytes > sizeof(*dhcp)) {
|
||||
syslog(LOG_ERR,
|
||||
"%s: packet greater than DHCP size from %s",
|
||||
iface->name, inet_ntoa(from));
|
||||
ifp->name, inet_ntoa(from));
|
||||
continue;
|
||||
}
|
||||
if (dhcp == NULL) {
|
||||
@ -2618,22 +2621,22 @@ dhcp_handlepacket(void *arg)
|
||||
memcpy(dhcp, pp, bytes);
|
||||
if (dhcp->cookie != htonl(MAGIC_COOKIE)) {
|
||||
syslog(LOG_DEBUG, "%s: bogus cookie from %s",
|
||||
iface->name, inet_ntoa(from));
|
||||
ifp->name, inet_ntoa(from));
|
||||
continue;
|
||||
}
|
||||
/* Ensure packet is for us */
|
||||
if (iface->hwlen <= sizeof(dhcp->chaddr) &&
|
||||
memcmp(dhcp->chaddr, iface->hwaddr, iface->hwlen))
|
||||
if (ifp->hwlen <= sizeof(dhcp->chaddr) &&
|
||||
memcmp(dhcp->chaddr, ifp->hwaddr, ifp->hwlen))
|
||||
{
|
||||
char buf[sizeof(dhcp->chaddr) * 3];
|
||||
|
||||
syslog(LOG_DEBUG, "%s: xid 0x%x is not for hwaddr %s",
|
||||
iface->name, ntohl(dhcp->xid),
|
||||
ifp->name, ntohl(dhcp->xid),
|
||||
hwaddr_ntoa(dhcp->chaddr, sizeof(dhcp->chaddr),
|
||||
buf, sizeof(buf)));
|
||||
continue;
|
||||
}
|
||||
dhcp_handledhcp(iface, &dhcp, &from);
|
||||
dhcp_handledhcp(ifp, &dhcp, &from);
|
||||
if (state->raw_fd == -1)
|
||||
break;
|
||||
}
|
||||
|
5
dhcp6.c
5
dhcp6.c
@ -2036,8 +2036,11 @@ dhcp6_handledata(void *arg)
|
||||
ctx = dhcpcd_ctx->ipv6;
|
||||
ctx->rcvhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
|
||||
bytes = recvmsg(ctx->dhcp_fd, &ctx->rcvhdr, 0);
|
||||
if (bytes == -1) {
|
||||
if (bytes == -1 || bytes == 0) {
|
||||
syslog(LOG_ERR, "recvmsg: %m");
|
||||
close(ctx->dhcp_fd);
|
||||
eloop_event_delete(dhcpcd_ctx->eloop, ctx->dhcp_fd);
|
||||
ctx->dhcp_fd = -1;
|
||||
return;
|
||||
}
|
||||
len = (size_t)bytes;
|
||||
|
6
dhcpcd.c
6
dhcpcd.c
@ -641,8 +641,12 @@ handle_link(void *arg)
|
||||
struct dhcpcd_ctx *ctx;
|
||||
|
||||
ctx = arg;
|
||||
if (if_managelink(ctx) == -1 && errno != ENXIO && errno != ENODEV)
|
||||
if (if_managelink(ctx) == -1) {
|
||||
syslog(LOG_ERR, "if_managelink: %m");
|
||||
eloop_event_delete(ctx->eloop, ctx->link_fd);
|
||||
close(ctx->link_fd);
|
||||
ctx->link_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
4
eloop.c
4
eloop.c
@ -386,7 +386,7 @@ eloop_start(struct dhcpcd_ctx *dctx)
|
||||
n = poll(ctx->fds, ctx->events_len, timeout);
|
||||
#endif
|
||||
if (n == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
syslog(LOG_ERR, "poll: %m");
|
||||
break;
|
||||
@ -395,7 +395,7 @@ eloop_start(struct dhcpcd_ctx *dctx)
|
||||
/* Process any triggered events. */
|
||||
if (n > 0) {
|
||||
TAILQ_FOREACH(e, &ctx->events, next) {
|
||||
if (e->pollfd->revents & (POLLIN | POLLHUP)) {
|
||||
if (e->pollfd->revents & (POLLIN)) {
|
||||
e->callback(e->arg);
|
||||
/* We need to break here as the
|
||||
* callback could destroy the next
|
||||
|
292
if-bsd.c
292
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;
|
||||
#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);
|
||||
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);
|
||||
#endif
|
||||
break;
|
||||
#ifdef RTM_CHGADDR
|
||||
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:
|
||||
#ifdef RTM_CHGADDR
|
||||
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);
|
||||
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;
|
||||
#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 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);
|
||||
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);
|
||||
#endif
|
||||
break;
|
||||
#ifdef RTM_CHGADDR
|
||||
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:
|
||||
#ifdef RTM_CHGADDR
|
||||
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);
|
||||
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;
|
||||
#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
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef SYS_NMLN /* OSX */
|
||||
|
39
if-linux.c
39
if-linux.c
@ -272,15 +272,9 @@ get_netlink(struct dhcpcd_ctx *ctx, int fd, int flags,
|
||||
for (;;) {
|
||||
bytes = recv(fd, NULL, 0,
|
||||
flags | MSG_PEEK | MSG_DONTWAIT | MSG_TRUNC);
|
||||
if (bytes == -1) {
|
||||
if (errno == EAGAIN) {
|
||||
r = 0;
|
||||
goto eexit;
|
||||
}
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (bytes == -1 || bytes == 0)
|
||||
goto eexit;
|
||||
} else if ((size_t)bytes == buflen) {
|
||||
if ((size_t)bytes == buflen) {
|
||||
/* Support kernels older than 2.6.22 */
|
||||
if (bytes == 0)
|
||||
bytes = 512;
|
||||
@ -297,15 +291,8 @@ get_netlink(struct dhcpcd_ctx *ctx, int fd, int flags,
|
||||
}
|
||||
bytes = recvfrom(fd, buf, buflen, flags,
|
||||
(struct sockaddr *)&nladdr, &nladdr_len);
|
||||
if (bytes == -1) {
|
||||
if (errno == EAGAIN) {
|
||||
r = 0;
|
||||
goto eexit;
|
||||
}
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (bytes == -1 || bytes == 0)
|
||||
goto eexit;
|
||||
}
|
||||
|
||||
/* Check sender */
|
||||
if (nladdr_len != sizeof(nladdr)) {
|
||||
@ -752,7 +739,7 @@ if_openrawsocket(struct interface *ifp, int protocol)
|
||||
#endif
|
||||
|
||||
#ifdef SOCK_CLOEXEC
|
||||
if ((s = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
|
||||
if ((s = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC,
|
||||
htons(protocol))) == -1)
|
||||
return -1;
|
||||
#else
|
||||
@ -766,12 +753,6 @@ if_openrawsocket(struct interface *ifp, int protocol)
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
if ((flags = fcntl(s, F_GETFL, 0)) == -1 ||
|
||||
fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
{
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
/* Install the DHCP filter */
|
||||
memset(&pf, 0, sizeof(pf));
|
||||
@ -839,7 +820,7 @@ if_sendrawpacket(const struct interface *ifp, int protocol,
|
||||
|
||||
ssize_t
|
||||
if_readrawpacket(struct interface *ifp, int protocol,
|
||||
void *data, size_t len, int *partialcsum)
|
||||
void *data, size_t len, int *flags)
|
||||
{
|
||||
struct iovec iov = {
|
||||
.iov_base = data,
|
||||
@ -871,9 +852,9 @@ if_readrawpacket(struct interface *ifp, int protocol,
|
||||
fd = state->raw_fd;
|
||||
bytes = recvmsg(fd, &msg, 0);
|
||||
if (bytes == -1)
|
||||
return errno == EAGAIN ? 0 : -1;
|
||||
if (partialcsum != NULL) {
|
||||
*partialcsum = 0;
|
||||
return -1;
|
||||
if (bytes) {
|
||||
*flags &= ~RAW_PARTIALCSUM;
|
||||
#ifdef PACKET_AUXDATA
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg;
|
||||
@ -882,8 +863,8 @@ if_readrawpacket(struct interface *ifp, int protocol,
|
||||
if (cmsg->cmsg_level == SOL_PACKET &&
|
||||
cmsg->cmsg_type == PACKET_AUXDATA) {
|
||||
aux = (void *)CMSG_DATA(cmsg);
|
||||
*partialcsum = aux->tp_status &
|
||||
TP_STATUS_CSUMNOTREADY;
|
||||
if (aux->tp_status & TP_STATUS_CSUMNOTREADY)
|
||||
*flags |= RAW_PARTIALCSUM;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
3
if.h
3
if.h
@ -80,6 +80,9 @@
|
||||
# define IN_LINKLOCAL(addr) ((addr & IN_CLASSB_NET) == LINKLOCAL_ADDR)
|
||||
#endif
|
||||
|
||||
#define RAW_EOF 1 << 0
|
||||
#define RAW_PARTIALCSUM 2 << 0
|
||||
|
||||
struct if_head *if_discover(struct dhcpcd_ctx *, int, char * const *);
|
||||
struct interface *if_find(struct dhcpcd_ctx *, const char *);
|
||||
void if_free(struct interface *);
|
||||
|
9
ipv6nd.c
9
ipv6nd.c
@ -1166,10 +1166,10 @@ ipv6nd_proberouter(void *arg)
|
||||
pi.ipi6_ifindex = rap->iface->index;
|
||||
memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
|
||||
|
||||
#ifdef DEBUG_NS
|
||||
//#ifdef DEBUG_NS
|
||||
syslog(LOG_INFO, "%s: sending IPv6 NS for %s",
|
||||
rap->iface->name, rap->sfrom);
|
||||
#endif
|
||||
//#endif
|
||||
if (sendmsg(ctx->nd_fd, &ctx->sndhdr, 0) == -1) {
|
||||
syslog(LOG_ERR, "%s: %s: sendmsg: %m",
|
||||
rap->iface->name, __func__);
|
||||
@ -1432,8 +1432,11 @@ ipv6nd_handledata(void *arg)
|
||||
ctx->rcvhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
|
||||
CMSG_SPACE(sizeof(int));
|
||||
len = recvmsg(ctx->nd_fd, &ctx->rcvhdr, 0);
|
||||
if (len == -1) {
|
||||
if (len == -1 || len == 0) {
|
||||
syslog(LOG_ERR, "recvmsg: %m");
|
||||
eloop_event_delete(dhcpcd_ctx->eloop, ctx->nd_fd);
|
||||
close(ctx->nd_fd);
|
||||
ctx->nd_fd = -1;
|
||||
return;
|
||||
}
|
||||
ctx->sfrom = inet_ntop(AF_INET6, &ctx->from.sin6_addr,
|
||||
|
Loading…
Reference in New Issue
Block a user