odhcp6c: allow to request specific ipv6 prefix master
authorVladislav Grishenko <themiron@mail.ru>
Thu, 25 Jul 2024 19:51:09 +0000 (00:51 +0500)
committerdedeckeh <dedeckeh@gmail.com>
Wed, 25 Sep 2024 18:33:53 +0000 (20:33 +0200)
Expand -P option with optional exact ipv6 prefix format.
This allows to keep the IPv6 prefix in some cases, for example
if the prefix is issued dynamically on upstream.

Examples:
    -P <length>
    -P <prefix/length>

Based on https://github.com/openwrt/odhcp6c/pull/86

src/dhcpv6.c
src/odhcp6c.c
src/odhcp6c.h

index ca5957e3611c7d08ad0e6a6feba37ffea250dd93..c1603f5bccbc29fa745c6fba8b3facf80a990ddb 100644 (file)
@@ -384,7 +384,8 @@ static void dhcpv6_send(enum dhcpv6_msg type, uint8_t trid[3], uint32_t ecs)
                        struct dhcpv6_ia_prefix pref = {
                                .type = htons(DHCPV6_OPT_IA_PREFIX),
                                .len = htons(sizeof(pref) - 4),
-                               .prefix = request_prefixes[i].length
+                               .prefix = request_prefixes[i].length,
+                               .addr = request_prefixes[i].addr
                        };
                        memcpy(ia_pd + ia_pd_len, &hdr_ia_pd, sizeof(hdr_ia_pd));
                        ia_pd_len += sizeof(hdr_ia_pd);
index 4a6d7bd62579a0570e720b2619722af14000468e..20b4040a17d45b46824bcbd67a06a7028686521a 100644 (file)
@@ -241,17 +241,29 @@ int main(_unused int argc, char* const argv[])
                        if (allow_slaac_only >= 0 && allow_slaac_only < 10)
                                allow_slaac_only = 10;
 
+                       struct odhcp6c_request_prefix prefix = { 0 };
+
+                       optpos = strchr(optarg, '/');
+                       if (optpos) {
+                               strncpy((char *)buf, optarg, optpos - optarg);
+                               buf[optpos - optarg] = '\0';
+                               if (inet_pton(AF_INET6, (char *)buf, &prefix.addr) <= 0) {
+                                       syslog(LOG_ERR, "invalid argument: '%s'", optarg);
+                                       return 1;
+                               }
+                               optpos++;
+                       } else
+                               optpos = optarg;
+
                        char *iaid_begin;
                        int iaid_len = 0;
-                       int prefix_length = strtoul(optarg, &iaid_begin, 10);
+                       prefix.length = strtoul(optpos, &iaid_begin, 10);
 
                        if (*iaid_begin != '\0' && *iaid_begin != ',' && *iaid_begin != ':') {
                                syslog(LOG_ERR, "invalid argument: '%s'", optarg);
                                return 1;
                        }
 
-                       struct odhcp6c_request_prefix prefix = { 0, prefix_length };
-
                        if (*iaid_begin == ',' && (iaid_len = strlen(iaid_begin)) > 1)
                                memcpy(&prefix.iaid, iaid_begin + 1, iaid_len > 4 ? 4 : iaid_len);
                        else if (*iaid_begin == ':')
@@ -614,7 +626,7 @@ static int usage(void)
        "       -S <time>       Wait at least <time> sec for a DHCP-server (0)\n"
        "       -D              Discard advertisements without any address or prefix proposed\n"
        "       -N <mode>       Mode for requesting addresses [try|force|none]\n"
-       "       -P <length>     Request IPv6-Prefix (0 = auto)\n"
+       "       -P <[pfx/]len>  Request IPv6-Prefix (0 = auto)\n"
        "       -F              Force IPv6-Prefix\n"
        "       -V <class>      Set vendor-class option (base-16 encoded)\n"
        "       -u <user-class> Set user-class option string\n"
index 5d9d5e300e21f02945fec69bdb7fd208d43e7e1d..7904946f031cd65dcc5f8a8d78842f72ab9626dc 100644 (file)
@@ -367,7 +367,8 @@ struct odhcp6c_entry {
 
 struct odhcp6c_request_prefix {
        uint32_t iaid;
-       uint16_t length;
+       uint8_t length;
+       struct in6_addr addr;
 };
 
 enum odhcp6c_opt_flags {