]> The Tcpdump Group git mirrors - tcpdump/commitdiff
bootp/dhcp6: DHCPv4/v6 ZTP and SZTP option support
authorEamon Doyle <[email protected]>
Thu, 14 Apr 2022 07:53:54 +0000 (08:53 +0100)
committerFrancois-Xavier Le Bail <[email protected]>
Thu, 12 Oct 2023 17:22:30 +0000 (19:22 +0200)
DHCPv4: RFC8572 specifies the SZTP redirect tag.

DHCPv6: RFC5970 specifies the boot file URL, used for ZTP,
 and RFC8572 specifies the SZTP redirect tag
 The base DHCPv6 RFC3315 specifies the user class option.

(cherry picked from commit 9c37f53ddedfd335c5b16b240ec5730dff522c7b)

print-bootp.c
print-dhcp6.c
tests/TESTLIST
tests/dhcpv4v6-rfc5970-rfc8572.out [new file with mode: 0644]
tests/dhcpv4v6-rfc5970-rfc8572.pcap [new file with mode: 0644]

index d230a24cbf836f957e8a3ba6b2f52e30d592eeec..f6c6e995c4fdfa85dd0ad2bad9985b962f353814 100644 (file)
@@ -193,6 +193,8 @@ struct bootp {
 /* RFC 3442 */
 #define TAG_CLASSLESS_STATIC_RT        ((uint8_t) 121)
 #define TAG_CLASSLESS_STA_RT_MS        ((uint8_t) 249)
 /* RFC 3442 */
 #define TAG_CLASSLESS_STATIC_RT        ((uint8_t) 121)
 #define TAG_CLASSLESS_STA_RT_MS        ((uint8_t) 249)
+/* RFC8572 */
+#define TAG_SZTP_REDIRECT      ((uint8_t) 143)
 /* RFC 5859 - TFTP Server Address Option for DHCPv4 */
 #define        TAG_TFTP_SERVER_ADDRESS ((uint8_t) 150)
 /* https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml */
 /* RFC 5859 - TFTP Server Address Option for DHCPv4 */
 #define        TAG_TFTP_SERVER_ADDRESS ((uint8_t) 150)
 /* https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml */
@@ -499,6 +501,8 @@ static const struct tok tag2str[] = {
 /* RFC 3442 */
        { TAG_CLASSLESS_STATIC_RT, "$Classless-Static-Route" },
        { TAG_CLASSLESS_STA_RT_MS, "$Classless-Static-Route-Microsoft" },
 /* RFC 3442 */
        { TAG_CLASSLESS_STATIC_RT, "$Classless-Static-Route" },
        { TAG_CLASSLESS_STA_RT_MS, "$Classless-Static-Route-Microsoft" },
+/* RFC 8572 */
+       { TAG_SZTP_REDIRECT,    "$SZTP-Redirect" },
 /* RFC 5859 - TFTP Server Address Option for DHCPv4 */
        { TAG_TFTP_SERVER_ADDRESS, "iTFTP-Server-Address" },
 /* https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml#options */
 /* RFC 5859 - TFTP Server Address Option for DHCPv4 */
        { TAG_TFTP_SERVER_ADDRESS, "iTFTP-Server-Address" },
 /* https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml#options */
@@ -999,6 +1003,39 @@ rfc1048_print(netdissect_options *ndo,
                                break;
                            }
 
                                break;
                            }
 
+
+                       case TAG_SZTP_REDIRECT:
+                               /* as per https://datatracker.ietf.org/doc/html/rfc8572#section-8.3
+                                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+
+                                |        uri-length             |          URI                  |
+                                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+
+
+                                * uri-length: 2 octets long; specifies the length of the URI data.
+                                * URI: URI of the SZTP bootstrap server.
+                                */
+                               while (len >= 2) {
+                                       suboptlen = GET_BE_U_2(bp);
+                                       bp += 2;
+                                       len -= 2;
+                                       ND_PRINT("\n\t      ");
+                                       ND_PRINT("length %u: ", suboptlen);
+                                       if (len < suboptlen) {
+                                               ND_PRINT("length goes past end of option");
+                                               bp += len;
+                                               len = 0;
+                                               break;
+                                       }
+                                       ND_PRINT("\"");
+                                       nd_printjn(ndo, bp, suboptlen);
+                                       ND_PRINT("\"");
+                                       len -= suboptlen;
+                                       bp += suboptlen;
+                               }
+                               if (len != 0) {
+                                       ND_PRINT("[ERROR: length < 2 bytes]");
+                               }
+                               break;
+
                        default:
                                ND_PRINT("[unknown special tag %u, size %u]",
                                          tag, len);
                        default:
                                ND_PRINT("[unknown special tag %u, size %u]",
                                          tag, len);
index 6b0dc21335d31c432c3e97ccf77d5a72b695a155..7e7d1246fc0a2f970a41e0cb1023b1ce8e0335ef 100644 (file)
@@ -188,8 +188,10 @@ struct dhcp6_relay {
 #  define DH6OPT_NTP_SUBOPTION_SRV_ADDR 1
 #  define DH6OPT_NTP_SUBOPTION_MC_ADDR 2
 #  define DH6OPT_NTP_SUBOPTION_SRV_FQDN 3
 #  define DH6OPT_NTP_SUBOPTION_SRV_ADDR 1
 #  define DH6OPT_NTP_SUBOPTION_MC_ADDR 2
 #  define DH6OPT_NTP_SUBOPTION_SRV_FQDN 3
+#define DH6OPT_BOOTFILE_URL 59    /* RFC5970 */
 #define DH6OPT_AFTR_NAME 64
 #define DH6OPT_MUDURL 112
 #define DH6OPT_AFTR_NAME 64
 #define DH6OPT_MUDURL 112
+#define DH6OPT_SZTP_REDIRECT 136  /* RFC8572 */
 
 static const struct tok dh6opt_str[] = {
        { DH6OPT_CLIENTID,           "client-ID"            },
 
 static const struct tok dh6opt_str[] = {
        { DH6OPT_CLIENTID,           "client-ID"            },
@@ -239,8 +241,10 @@ static const struct tok dh6opt_str[] = {
        { DH6OPT_LQ_RELAY_DATA,      "LQ-relay-data"        },
        { DH6OPT_LQ_CLIENT_LINK,     "LQ-client-link"       },
        { DH6OPT_NTP_SERVER,         "NTP-server"           },
        { DH6OPT_LQ_RELAY_DATA,      "LQ-relay-data"        },
        { DH6OPT_LQ_CLIENT_LINK,     "LQ-client-link"       },
        { DH6OPT_NTP_SERVER,         "NTP-server"           },
+       { DH6OPT_BOOTFILE_URL,       "Bootfile-URL"         },
        { DH6OPT_AFTR_NAME,          "AFTR-Name"            },
        { DH6OPT_MUDURL,             "MUD-URL"              },
        { DH6OPT_AFTR_NAME,          "AFTR-Name"            },
        { DH6OPT_MUDURL,             "MUD-URL"              },
+       { DH6OPT_SZTP_REDIRECT,      "SZTP-redirect"        },
        { 0, NULL }
 };
 
        { 0, NULL }
 };
 
@@ -290,6 +294,8 @@ dhcp6opt_print(netdissect_options *ndo,
        uint16_t subopt_len;
        uint8_t dh6_reconf_type;
        uint8_t dh6_lq_query_type;
        uint16_t subopt_len;
        uint8_t dh6_reconf_type;
        uint8_t dh6_lq_query_type;
+       u_int first_list_value;
+       uint16_t remainder_len;
 
        if (cp == ep)
                return;
 
        if (cp == ep)
                return;
@@ -784,6 +790,39 @@ dhcp6opt_print(netdissect_options *ndo,
                        ND_PRINT(")");
                        break;
 
                        ND_PRINT(")");
                        break;
 
+               case DH6OPT_BOOTFILE_URL:
+                       tp = (const u_char *)(dh6o + 1);
+                       ND_PRINT(" ");
+                       nd_printjn(ndo, tp, optlen);
+                       ND_PRINT(")");
+                       break;
+
+               case DH6OPT_SZTP_REDIRECT:
+               case DH6OPT_USER_CLASS:
+                       ND_PRINT(" ");
+                       tp = (const u_char *)(dh6o + 1);
+                       first_list_value = TRUE;
+                       remainder_len = optlen;
+                       while (remainder_len >= 2) {
+                               if (first_list_value == FALSE) {
+                                       ND_PRINT(",");
+                               }
+                               first_list_value = FALSE;
+                               subopt_len = GET_BE_U_2(tp);
+                               if (subopt_len > remainder_len-2) {
+                                       break;
+                               }
+                               tp += 2;
+                               nd_printjn(ndo, tp, subopt_len);
+                               tp += subopt_len;
+                               remainder_len -= (subopt_len+2);
+                       }
+                       if (remainder_len != 0 ) {
+                               ND_PRINT(" ?");
+                       }
+                       ND_PRINT(")");
+                       break;
+
                default:
                        ND_PRINT(")");
                        break;
                default:
                        ND_PRINT(")");
                        break;
index d74405d084d86a2fd628f5f376f6c9ab7c4bab4a..c189d1c1636be0759e00c54d5b99881166383521 100644 (file)
@@ -850,6 +850,9 @@ lsp-ping-timestamp  lsp-ping-timestamp.pcap         lsp-ping-timestamp.out  -vv
 # lwres with "extra" bytes
 lwres_with_extra lwres_with_extra.pcap lwres_with_extra.out
 
 # lwres with "extra" bytes
 lwres_with_extra lwres_with_extra.pcap lwres_with_extra.out
 
+# DHCP ZTP(RFC5970) and SZTP(RFC8572) tests
+dhcpv4v6-rfc5970-rfc8572 dhcpv4v6-rfc5970-rfc8572.pcap dhcpv4v6-rfc5970-rfc8572.out -vv
+
 # Undefined behavior tests
 ip-snmp-leftshift-unsigned ip-snmp-leftshift-unsigned.pcap ip-snmp-leftshift-unsigned.out
 ip6-snmp-oid-unsigned ip6-snmp-oid-unsigned.pcap ip6-snmp-oid-unsigned.out
 # Undefined behavior tests
 ip-snmp-leftshift-unsigned ip-snmp-leftshift-unsigned.pcap ip-snmp-leftshift-unsigned.out
 ip6-snmp-oid-unsigned ip6-snmp-oid-unsigned.pcap ip6-snmp-oid-unsigned.out
diff --git a/tests/dhcpv4v6-rfc5970-rfc8572.out b/tests/dhcpv4v6-rfc5970-rfc8572.out
new file mode 100644 (file)
index 0000000..bc0e8c6
--- /dev/null
@@ -0,0 +1,76 @@
+    1  13:35:23.334910 IP6 (flowlabel 0x03f85, hlim 1, next-header UDP (17) payload length: 80) fe80::200:1ff:fe01:0.546 > ff02::1:2.547: [udp sum ok] dhcp6 solicit (xid=6aebe6 (vendor-specific-info) (client-ID hwaddr/time type 1 time 701530515 000001010000) (option-request SZTP-redirect DNS-search-list DNS-server) (elapsed-time 703) (IA_NA IAID:16842752 T1:3600 T2:5400))
+    2  13:35:45.614434 IP6 (flowlabel 0x03f85, hlim 1, next-header UDP (17) payload length: 80) fe80::200:1ff:fe01:0.546 > ff02::1:2.547: [udp sum ok] dhcp6 solicit (xid=aca407 (vendor-specific-info) (client-ID hwaddr/time type 1 time 701530515 000001010000) (option-request SZTP-redirect DNS-search-list DNS-server) (elapsed-time 0) (IA_NA IAID:16842752 T1:3600 T2:5400))
+    3  13:35:45.618584 IP6 (flowlabel 0xe612c, hlim 64, next-header UDP (17) payload length: 281) fe80::cc0d:b4ff:fe8a:3384.547 > fe80::200:1ff:fe01:0.546: [udp sum ok] dhcp6 advertise (xid=aca407 (IA_NA IAID:16842752 T1:0 T2:0 (IA_ADDR 1234:5678::4 pltime:18000 vltime:28800)) (client-ID hwaddr/time type 1 time 701530515 000001010000) (server-ID hwaddr/time type 1 time 701530524 ce0db48a3384) (SZTP-redirect https://sztp1.download.com,https://sztp2.download.com:8080,https://10.10.0.0,https://10.10.0.0:8000,https://[2001:4860:4860::8888]:8080) (DNS-search-list aristanetworks.com.) (DNS-server 1234:5678::2))
+    4  13:35:46.635774 IP6 (flowlabel 0x03f85, hlim 1, next-header UDP (17) payload length: 126) fe80::200:1ff:fe01:0.546 > ff02::1:2.547: [udp sum ok] dhcp6 request (xid=5f98e6 (vendor-specific-info) (client-ID hwaddr/time type 1 time 701530515 000001010000) (server-ID hwaddr/time type 1 time 701530524 ce0db48a3384) (option-request SZTP-redirect DNS-search-list DNS-server) (elapsed-time 0) (IA_NA IAID:16842752 T1:3600 T2:5400 (IA_ADDR 1234:5678::4 pltime:7200 vltime:7500)))
+    5  13:35:46.638223 IP6 (flowlabel 0xe612c, hlim 64, next-header UDP (17) payload length: 281) fe80::cc0d:b4ff:fe8a:3384.547 > fe80::200:1ff:fe01:0.546: [udp sum ok] dhcp6 reply (xid=5f98e6 (IA_NA IAID:16842752 T1:0 T2:0 (IA_ADDR 1234:5678::4 pltime:7200 vltime:28800)) (client-ID hwaddr/time type 1 time 701530515 000001010000) (server-ID hwaddr/time type 1 time 701530524 ce0db48a3384) (SZTP-redirect https://sztp1.download.com,https://sztp2.download.com:8080,https://10.10.0.0,https://10.10.0.0:8000,https://[2001:4860:4860::8888]:8080) (DNS-search-list aristanetworks.com.) (DNS-server 1234:5678::2))
+    6  13:56:39.000073 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328)
+    0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request from 00:00:44:01:00:00, length 300, xid 0x796a827d, Flags [none] (0x0000)
+         Client-Ethernet-Address 00:00:44:01:00:00
+         Vendor-rfc1048 Extensions
+           Magic Cookie 0x63825363
+           DHCP-Message (53), length 1: Discover
+           Parameter-Request (55), length 10: 
+             MTU (26), Subnet-Mask (1), BR (28), Default-Gateway (3)
+             Domain-Name (15), Domain-Name-Server (6), LOG (7), Hostname (12)
+             SZTP-Redirect (143), Classless-Static-Route (121)
+           Vendor-Class (60), length 6: "Arista"
+           Client-ID (61), length 6: "^@D^A^@^@"
+    7  13:56:40.003200 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 469)
+    10.10.0.2.67 > 10.10.0.4.68: [udp sum ok] BOOTP/DHCP, Reply, length 441, xid 0x796a827d, Flags [none] (0x0000)
+         Your-IP 10.10.0.4
+         Client-Ethernet-Address 00:00:44:01:00:00
+         Vendor-rfc1048 Extensions
+           Magic Cookie 0x63825363
+           DHCP-Message (53), length 1: Offer
+           Server-ID (54), length 4: 10.10.0.2
+           Lease-Time (51), length 4: 28800
+           MTU (26), length 2: 1500
+           Subnet-Mask (1), length 4: 255.255.0.0
+           Default-Gateway (3), length 4: 10.10.0.1
+           Domain-Name (15), length 18: "aristanetworks.com"
+           Domain-Name-Server (6), length 4: 10.10.0.1
+           SZTP-Redirect (143), length 141: 
+                   length 26: "https://sztp1.download.com"
+                   length 31: "https://sztp2.download.com:8080"
+                   length 17: "https://10.10.0.0"
+                   length 22: "https://10.10.0.0:8000"
+                   length 35: "https://[2001:4860:4860::8888]:8080"
+    8  13:56:40.003500 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328)
+    0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request from 00:00:44:01:00:00, length 300, xid 0x796a827d, Flags [none] (0x0000)
+         Client-Ethernet-Address 00:00:44:01:00:00
+         Vendor-rfc1048 Extensions
+           Magic Cookie 0x63825363
+           DHCP-Message (53), length 1: Request
+           Server-ID (54), length 4: 10.10.0.2
+           Requested-IP (50), length 4: 10.10.0.4
+           Parameter-Request (55), length 10: 
+             MTU (26), Subnet-Mask (1), BR (28), Default-Gateway (3)
+             Domain-Name (15), Domain-Name-Server (6), LOG (7), Hostname (12)
+             SZTP-Redirect (143), Classless-Static-Route (121)
+           Vendor-Class (60), length 6: "Arista"
+           Client-ID (61), length 6: "^@D^A^@^@"
+    9  13:56:40.005894 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 469)
+    10.10.0.2.67 > 10.10.0.4.68: [udp sum ok] BOOTP/DHCP, Reply, length 441, xid 0x796a827d, Flags [none] (0x0000)
+         Your-IP 10.10.0.4
+         Client-Ethernet-Address 00:00:44:01:00:00
+         Vendor-rfc1048 Extensions
+           Magic Cookie 0x63825363
+           DHCP-Message (53), length 1: ACK
+           Server-ID (54), length 4: 10.10.0.2
+           Lease-Time (51), length 4: 28800
+           MTU (26), length 2: 1500
+           Subnet-Mask (1), length 4: 255.255.0.0
+           Default-Gateway (3), length 4: 10.10.0.1
+           Domain-Name (15), length 18: "aristanetworks.com"
+           Domain-Name-Server (6), length 4: 10.10.0.1
+           SZTP-Redirect (143), length 141: 
+                   length 26: "https://sztp1.download.com"
+                   length 31: "https://sztp2.download.com:8080"
+                   length 17: "https://10.10.0.0"
+                   length 22: "https://10.10.0.0:8000"
+                   length 35: "https://[2001:4860:4860::8888]:8080"
+   10  14:15:10.112658 IP6 (flowlabel 0x03f85, hlim 1, next-header UDP (17) payload length: 80) fe80::200:1ff:fe01:0.546 > ff02::1:2.547: [udp sum ok] dhcp6 solicit (xid=28792a (vendor-specific-info) (client-ID hwaddr/time type 1 time 701792102 000001010000) (option-request Bootfile-URL DNS-search-list DNS-server) (elapsed-time 754) (IA_NA IAID:16842752 T1:3600 T2:5400))
+   11  14:15:33.148466 IP6 (flowlabel 0x1570c, hlim 64, next-header UDP (17) payload length: 157) fe80::40d3:61ff:fe62:3810.547 > fe80::200:1ff:fe01:0.546: [udp sum ok] dhcp6 advertise (xid=654242 (IA_NA IAID:16842752 T1:0 T2:0 (IA_ADDR 1234:5678::4 pltime:18000 vltime:28800)) (client-ID hwaddr/time type 1 time 701792102 000001010000) (server-ID hwaddr/time type 1 time 701792110 42d361623810) (Bootfile-URL my-startup-config) (DNS-search-list aristanetworks.com.) (DNS-server 1234:5678::2))
+   12  14:15:34.152941 IP6 (flowlabel 0x03f85, hlim 1, next-header UDP (17) payload length: 126) fe80::200:1ff:fe01:0.546 > ff02::1:2.547: [udp sum ok] dhcp6 request (xid=becafa (vendor-specific-info) (client-ID hwaddr/time type 1 time 701792102 000001010000) (server-ID hwaddr/time type 1 time 701792110 42d361623810) (option-request Bootfile-URL DNS-search-list DNS-server) (elapsed-time 0) (IA_NA IAID:16842752 T1:3600 T2:5400 (IA_ADDR 1234:5678::4 pltime:7200 vltime:7500)))
+   13  14:15:34.156427 IP6 (flowlabel 0x1570c, hlim 64, next-header UDP (17) payload length: 157) fe80::40d3:61ff:fe62:3810.547 > fe80::200:1ff:fe01:0.546: [udp sum ok] dhcp6 reply (xid=becafa (IA_NA IAID:16842752 T1:0 T2:0 (IA_ADDR 1234:5678::4 pltime:7200 vltime:28800)) (client-ID hwaddr/time type 1 time 701792102 000001010000) (server-ID hwaddr/time type 1 time 701792110 42d361623810) (Bootfile-URL my-startup-config) (DNS-search-list aristanetworks.com.) (DNS-server 1234:5678::2))
+   14  08:08:32.009292 IP6 (flowlabel 0x09903, hlim 1, next-header UDP (17) payload length: 138) fe80::200:44ff:fe01:0.546 > ff02::1:2.547: [udp sum ok] dhcp6 inf-req (xid=b5fcf (vendor-specific-info) (client-ID hwaddr type 1 000044010000) (option-request Bootfile-URL DNS-search-list DNS-server) (elapsed-time 331) (user-class Arista;Test-Dhcpv6Discover;4.21.XX))
diff --git a/tests/dhcpv4v6-rfc5970-rfc8572.pcap b/tests/dhcpv4v6-rfc5970-rfc8572.pcap
new file mode 100644 (file)
index 0000000..e4937d0
Binary files /dev/null and b/tests/dhcpv4v6-rfc5970-rfc8572.pcap differ