#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
-#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
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)
.ifi = {.ifi_index = if_index}
};
send(rtnl, &req, sizeof(req), 0);
+ ra_link_up();
// Filter ICMPv6 package types
struct icmp6_filter filt;
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);
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;
static char *argv[4] = {NULL, NULL, NULL, NULL};
-static volatile char *delayed_call = NULL;
-static bool dont_delay = false;
int script_init(const char *path, const char *ifname)
}
-static void script_call_delayed(int signal __attribute__((unused)))
-{
- if (delayed_call)
- script_call((char*)delayed_call);
-}
-
-
-void script_delay_call(const char *status, int timeout)
-{
- if (dont_delay) {
- script_call(status);
- } else if (!delayed_call) {
- delayed_call = strdup(status);
- signal(SIGALRM, script_call_delayed);
- alarm(timeout);
- }
-}
-
-
void script_call(const char *status)
{
size_t dns_len, search_len, custom_len, sntp_ip_len, ntp_ip_len, ntp_dns_len;
size_t s46_mapt_len, s46_mape_len, s46_lw_len, passthru_len;
odhcp6c_expire();
- if (delayed_call) {
- alarm(0);
- dont_delay = true;
- }
struct in6_addr *addr = odhcp6c_get_state(STATE_SERVER_ADDR, &addr_len);
struct in6_addr *dns = odhcp6c_get_state(STATE_DNS, &dns_len);