diff options
author | Steven Barth <steven@midlink.org> | 2013-06-18 14:44:43 +0200 |
---|---|---|
committer | Steven Barth <steven@midlink.org> | 2013-06-18 14:44:43 +0200 |
commit | eaf3a11cad8a5dd389d5f52cc76e424e0242074b (patch) | |
tree | 419a2a520499abd9412a5a6e88efbeed340d3f99 /src | |
parent | 83114b179091cb080f09cf4142ee1c9949ea4e30 (diff) | |
download | odhcp6c-eaf3a11cad8a5dd389d5f52cc76e424e0242074b.tar.gz |
Allow overriding the interface-identifier for public addresses
Diffstat (limited to 'src')
-rw-r--r-- | src/odhcp6c.c | 12 | ||||
-rw-r--r-- | src/ra.c | 23 | ||||
-rw-r--r-- | src/ra.h | 2 |
3 files changed, 24 insertions, 13 deletions
diff --git a/src/odhcp6c.c b/src/odhcp6c.c index 4fefcd7..df89eb9 100644 --- a/src/odhcp6c.c +++ b/src/odhcp6c.c @@ -27,6 +27,7 @@ #include <net/if.h> #include <sys/wait.h> #include <sys/syscall.h> +#include <arpa/inet.h> #include "odhcp6c.h" #include "ra.h" @@ -55,11 +56,12 @@ int main(_unused int argc, char* const argv[]) char *optpos; uint16_t opttype; enum odhcp6c_ia_mode ia_na_mode = IA_MODE_TRY; + static struct in6_addr ifid = IN6ADDR_ANY_INIT; bool help = false, daemonize = false; int logopt = LOG_PID; int c, request_pd = 0; - while ((c = getopt(argc, argv, "S::N:P:c:r:s:khedp:")) != -1) { + while ((c = getopt(argc, argv, "S::N:P:c:i:r:s:khedp:")) != -1) { switch (c) { case 'S': allow_slaac_only = (optarg) ? atoi(optarg) : -1; @@ -98,6 +100,11 @@ int main(_unused int argc, char* const argv[]) } break; + case 'i': + if (inet_pton(AF_INET6, optarg, &ifid) != 1) + help = true; + break; + case 'r': optpos = optarg; while (optpos[0]) { @@ -151,7 +158,7 @@ int main(_unused int argc, char* const argv[]) signal(SIGUSR2, sighandler); if ((urandom_fd = open("/dev/urandom", O_CLOEXEC | O_RDONLY)) < 0 || - init_dhcpv6(ifname, request_pd) || ra_init(ifname) || + init_dhcpv6(ifname, request_pd) || ra_init(ifname, &ifid) || script_init(script, ifname)) { syslog(LOG_ERR, "failed to initialize: %s", strerror(errno)); return 3; @@ -314,6 +321,7 @@ static int usage(void) " -N <mode> Mode for requesting addresses [try|force|none]\n" " -P <length> Request IPv6-Prefix (0 = auto)\n" " -c <clientid> Override client-ID (base-16 encoded)\n" + " -i <iface-id> Use a custom interface identifier for RA handling\n" " -r <options> Options to be requested (comma-separated)\n" " -s <script> Status update script (/usr/sbin/odhcp6c-update)\n" " -k Don't send a RELEASE when stopping\n" @@ -42,11 +42,12 @@ static struct in6_addr lladdr = IN6ADDR_ANY_INIT; static void ra_send_rs(int signal __attribute__((unused))); -int ra_init(const char *ifname) +int ra_init(const char *ifname, const struct in6_addr *ifid) { sock = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6); if_index = if_nametoindex(ifname); strncpy(if_name, ifname, sizeof(if_name) - 1); + lladdr = *ifid; // Filter ICMPv6 package types struct icmp6_filter filt; @@ -74,17 +75,19 @@ int ra_init(const char *ifname) fcntl(sock, F_SETOWN, ourpid); fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_ASYNC); - // Get LL-addr - FILE *fp = fopen("/proc/net/if_inet6", "r"); - if (fp) { - char addrbuf[33], ifbuf[16]; - while (fscanf(fp, "%32s %*x %*x %*x %*x %15s", addrbuf, ifbuf) == 2) { - if (!strcmp(ifbuf, if_name)) { - script_unhexlify((uint8_t*)&lladdr, sizeof(lladdr), addrbuf); - break; + if (IN6_IS_ADDR_UNSPECIFIED(&lladdr)) { + // Autodetect interface-id if not specified + FILE *fp = fopen("/proc/net/if_inet6", "r"); + if (fp) { + char addrbuf[33], ifbuf[16]; + while (fscanf(fp, "%32s %*x %*x %*x %*x %15s", addrbuf, ifbuf) == 2) { + if (!strcmp(ifbuf, if_name)) { + script_unhexlify((uint8_t*)&lladdr, sizeof(lladdr), addrbuf); + break; + } } + fclose(fp); } - fclose(fp); } // Open rtnetlink socket @@ -34,6 +34,6 @@ struct icmpv6_opt { (void*)(opt + opt->len) <= (void*)(end); opt += opt->len) -int ra_init(const char *ifname); +int ra_init(const char *ifname, const struct in6_addr *ifid); bool ra_process(void); bool ra_rtnl_process(void); |