summaryrefslogtreecommitdiff
path: root/src/ra.c
diff options
context:
space:
mode:
authorSteven Barth <steven@midlink.org>2014-10-08 11:57:07 +0200
committerSteven Barth <steven@midlink.org>2014-10-08 11:57:07 +0200
commit6373af63310f32e1408a81f4e4e069a5f0d3e59e (patch)
treeebb228f245de9c341acd785f8f82cdfc181e36bf /src/ra.c
parentd6fe99f6d03873e7a670c9b6f26fa03b219422f5 (diff)
downloadodhcp6c-6373af63310f32e1408a81f4e4e069a5f0d3e59e.tar.gz
Ensure signal-safety of signal handlers
Diffstat (limited to 'src/ra.c')
-rw-r--r--src/ra.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/src/ra.c b/src/ra.c
index baaee9b..9c5eb22 100644
--- a/src/ra.c
+++ b/src/ra.c
@@ -26,7 +26,6 @@
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
-#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
@@ -56,6 +55,15 @@ static char if_name[IF_NAMESIZE] = {0};
static volatile int rs_attempt = 0;
static struct in6_addr lladdr = IN6ADDR_ANY_INIT;
+struct {
+ struct icmp6_hdr hdr;
+ struct icmpv6_opt lladdr;
+} rs = {
+ .hdr = {ND_ROUTER_SOLICIT, 0, 0, {{0}}},
+ .lladdr = {ND_OPT_SOURCE_LINKADDR, 1, {0}},
+};
+
+
static void ra_send_rs(int signal __attribute__((unused)));
int ra_init(const char *ifname, const struct in6_addr *ifid)
@@ -93,6 +101,7 @@ int ra_init(const char *ifname, const struct in6_addr *ifid)
.ifi = {.ifi_index = if_index}
};
send(rtnl, &req, sizeof(req), 0);
+ ra_link_up();
// Filter ICMPv6 package types
struct icmp6_filter filt;
@@ -133,22 +142,12 @@ int ra_init(const char *ifname, const struct in6_addr *ifid)
static void ra_send_rs(int signal __attribute__((unused)))
{
- struct {
- struct icmp6_hdr hdr;
- struct icmpv6_opt lladdr;
- } rs = {
- .hdr = {ND_ROUTER_SOLICIT, 0, 0, {{0}}},
- .lladdr = {ND_OPT_SOURCE_LINKADDR, 1, {0}},
- };
const struct sockaddr_in6 dest = {AF_INET6, 0, 0, ALL_IPV6_ROUTERS, if_index};
- size_t len = sizeof(rs);
-
- struct ifreq ifr;
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
- if ((rs_attempt % 2 == 0) && !ioctl(sock, SIOCGIFHWADDR, &ifr)
- && memcmp(rs.lladdr.data, ifr.ifr_hwaddr.sa_data, 6))
- memcpy(rs.lladdr.data, ifr.ifr_hwaddr.sa_data, 6);
+ const struct icmpv6_opt llnull = {ND_OPT_SOURCE_LINKADDR, 1, {0}};
+ size_t len;
+
+ if ((rs_attempt % 2 == 0) && memcmp(&rs.lladdr, &llnull, sizeof(llnull)))
+ len = sizeof(rs);
else
len = sizeof(struct icmp6_hdr);
@@ -197,6 +196,14 @@ bool ra_link_up(void)
resp.msg.ifi_index != if_index)
continue;
+ ssize_t alen = NLMSG_PAYLOAD(&resp.hdr, sizeof(resp.msg));
+ for (struct rtattr *rta = (struct rtattr*)(resp.pad);
+ RTA_OK(rta, alen); rta = RTA_NEXT(rta, alen)) {
+ if (rta->rta_type == IFLA_ADDRESS &&
+ RTA_PAYLOAD(rta) >= sizeof(rs.lladdr.data))
+ memcpy(rs.lladdr.data, RTA_DATA(rta), sizeof(rs.lladdr.data));
+ }
+
bool hascarrier = resp.msg.ifi_flags & IFF_LOWER_UP;
if (!firstcall && nocarrier != !hascarrier)
ret = true;