]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: Inroduce DHCP6- send vendor options
authorSusant Sahani <ssahani@vmware.com>
Tue, 26 May 2020 08:46:54 +0000 (10:46 +0200)
committerSusant Sahani <ssahani@vmware.com>
Fri, 29 May 2020 11:37:57 +0000 (13:37 +0200)
network: Inroduce DHCP6- send vendor options

```
 0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |      OPTION_VENDOR_OPTS       |           option-len          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                       enterprise-number                       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      .                                                               .
      .                       vendor-option-data                      .
      .                                                               .
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```

```
  0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |          sub-opt-code         |         sub-option-len        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      .                                                               .
      .                        sub-option-data                        .
      .                                                               .
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                 Figure 31: Vendor-specific Options Format

      sub-opt-code         The code for the sub-option.  A 2-octet
                           field.

      sub-option-len       An unsigned integer giving the length of the
                           sub-option-data field in this sub-option in
                           octets.  A 2-octet field.

      sub-option-data      The data area for the sub-option.  The
                           length, in octets, is specified by
                           sub-option-len.

```

man/systemd.network.xml
src/network/networkd-dhcp-common.c
src/network/networkd-dhcp6.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
test/fuzz/fuzz-network-parser/directives.network

index e8f3f364f1e1fb058777285f672830c5cd3f7607..ae82ae7e02b21759a7f2b616dddbedb00e2820de 100644 (file)
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>SendVendorOption=</varname></term>
+          <listitem>
+            <para>Send an arbitrary vendor option in the DHCPv6 request. Takes an enterprise identifier, DHCP option number,
+            data type, and data separated with a colon
+            (<literal><replaceable>enterprise identifier</replaceable>:<replaceable>option</replaceable>:<replaceable>type</replaceable>:
+            <replaceable>value</replaceable></literal>). Enterprise identifier is an unsigned integer ranges 1..4294967294.
+            The option number must be an integer in the range 1..254. Data type takes one of <literal>uint8</literal>,
+            <literal>uint16</literal>, <literal>uint32</literal>, <literal>ipv4address</literal>, <literal>ipv6address</literal>, or
+            <literal>string</literal>. Special characters in the data string may be escaped using
+            <ulink url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
+            escapes</ulink>. This setting can be specified multiple times. If an empty string is specified,
+            then all options specified earlier are cleared. Defaults to unset.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term><varname>ForceDHCPv6PDOtherInformation=</varname></term>
           <listitem>
index 3d9dab7e3c1abaa5bf31d5240396c90e1fc9cf7f..66dd8ea08e2a0b619c9377a0652189e2d83598ee 100644 (file)
@@ -437,13 +437,13 @@ int config_parse_dhcp_send_option(
 
         _cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *opt4 = NULL, *old4 = NULL;
         _cleanup_(sd_dhcp6_option_unrefp) sd_dhcp6_option *opt6 = NULL, *old6 = NULL;
+        uint32_t uint32_data, enterprise_identifier = 0;
         _cleanup_free_ char *word = NULL, *q = NULL;
         OrderedHashmap **options = data;
+        uint16_t u16, uint16_data;
         union in_addr_union addr;
         DHCPOptionDataType type;
         uint8_t u8, uint8_data;
-        uint16_t u16, uint16_data;
-        uint32_t uint32_data;
         const void *udata;
         const char *p;
         ssize_t sz;
@@ -460,10 +460,29 @@ int config_parse_dhcp_send_option(
         }
 
         p = rvalue;
+        if (ltype == AF_INET6 && streq(lvalue, "SendVendorOption")) {
+                r = extract_first_word(&p, &word, ":", 0);
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r <= 0 || isempty(p)) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Invalid DHCP option, ignoring assignment: %s", rvalue);
+                        return 0;
+                }
+
+                r = safe_atou32(word, &enterprise_identifier);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse DHCPv6 enterprise identifier data, ignoring assignment: %s", p);
+                        return 0;
+                }
+                word = mfree(word);
+        }
+
         r = extract_first_word(&p, &word, ":", 0);
         if (r == -ENOMEM)
                 return log_oom();
-        if (r <= 0) {
+        if (r <= 0 || isempty(p)) {
                 log_syntax(unit, LOG_ERR, filename, line, r,
                            "Invalid DHCP option, ignoring assignment: %s", rvalue);
                 return 0;
@@ -588,7 +607,7 @@ int config_parse_dhcp_send_option(
         }
 
         if (ltype == AF_INET6) {
-                r = sd_dhcp6_option_new(u16, udata, sz, &opt6);
+                r = sd_dhcp6_option_new(u16, udata, sz, enterprise_identifier, &opt6);
                 if (r < 0) {
                         log_syntax(unit, LOG_ERR, filename, line, r,
                                    "Failed to store DHCP option '%s', ignoring assignment: %m", rvalue);
index d0972f3593dcff329f646833d21a39f552a0ec01..a160fd70d984bfe3da5bcd51936b4b84c3facb4b 100644 (file)
@@ -756,6 +756,7 @@ static int dhcp6_set_hostname(sd_dhcp6_client *client, Link *link) {
 
 int dhcp6_configure(Link *link) {
         _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
+        sd_dhcp6_option *vendor_option;
         sd_dhcp6_option *send_option;
         void *request_options;
         const DUID *duid;
@@ -854,6 +855,14 @@ int dhcp6_configure(Link *link) {
                         return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set vendor class: %m");
         }
 
+        ORDERED_HASHMAP_FOREACH(vendor_option, link->network->dhcp6_client_send_vendor_options, i) {
+                r = sd_dhcp6_client_add_vendor_option(client, vendor_option);
+                if (r == -EEXIST)
+                        continue;
+                if (r < 0)
+                        return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set vendor option: %m");
+        }
+
         r = sd_dhcp6_client_set_callback(client, dhcp6_handler, link);
         if (r < 0)
                 return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set callback: %m");
index d318b7d891ddaa9b4d83be68627ea6bb7aced30d..4de2e5e8622aeee4c36174dbdd6d2eb3eb3d15e3 100644 (file)
@@ -198,6 +198,7 @@ DHCPv6.MUDURL,                               config_parse_dhcp6_mud_url,
 DHCPv6.RequestOptions,                       config_parse_dhcp_request_options,                        AF_INET6,                      0
 DHCPv6.UserClass,                            config_parse_dhcp_user_class,                             AF_INET6,                      offsetof(Network, dhcp6_user_class)
 DHCPv6.VendorClass,                          config_parse_dhcp_vendor_class,                           0,                             offsetof(Network, dhcp6_vendor_class)
+DHCPv6.SendVendorOption,                     config_parse_dhcp_send_option,                            AF_INET6,                      offsetof(Network, dhcp6_client_send_vendor_options)
 DHCPv6.ForceDHCPv6PDOtherInformation,        config_parse_bool,                                        0,                             offsetof(Network, dhcp6_force_pd_other_information)
 DHCPv6.AssignAcquiredDelegatedPrefixAddress, config_parse_bool,                                        0,                             offsetof(Network, dhcp6_pd_assign_prefix)
 DHCPv6.PrefixDelegationHint,                 config_parse_dhcp6_pd_hint,                               0,                             0
index ae466a23101d0155ee1bea18e25793aa893a4d0e..c895262a0d774d7ebdf96441cc49763c07c9e1f5 100644 (file)
@@ -749,6 +749,7 @@ static Network *network_free(Network *network) {
         ordered_hashmap_free(network->dhcp_server_send_options);
         ordered_hashmap_free(network->dhcp_server_send_vendor_options);
         ordered_hashmap_free(network->ipv6_tokens);
+        ordered_hashmap_free(network->dhcp6_client_send_vendor_options);
 
         return mfree(network);
 }
index 441bba127326d48405286b4f74393c4532d503c6..0e879be01b7416205ed51f77203cf30af7cbbfa3 100644 (file)
@@ -137,6 +137,7 @@ struct Network {
         char **dhcp6_vendor_class;
         struct in6_addr dhcp6_pd_address;
         OrderedHashmap *dhcp6_client_send_options;
+        OrderedHashmap *dhcp6_client_send_vendor_options;
         Set *dhcp6_request_options;
 
         /* DHCP Server Support */
index a1a6cdd233042038601fc6ff096046b329210405..faa38a1c1e00a52226ae2e28121261727c127ab2 100644 (file)
@@ -120,6 +120,7 @@ RequestOptions=
 UserClass=
 VendorClass=
 AssignAcquiredDelegatedPrefixAddress=
+SendVendorOption=
 [Route]
 Destination=
 Protocol=