]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-bootp.c
IPv6: Print the protocol name before any test
[tcpdump] / print-bootp.c
index 8ffaf409dade05109385c295feb1a755f22105d0..52b1238199fd5f3a77def44ec7150970bbf855ae 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <string.h>
 
+#define ND_LONGJMP_FROM_TCHECK
 #include "netdissect.h"
 #include "addrtoname.h"
 #include "extract.h"
@@ -193,9 +194,11 @@ struct bootp {
 /* 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)
-/* ftp://ftp.isi.edu/.../assignments/bootp-dhcp-extensions */
+/* https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml */
 #define        TAG_SLP_NAMING_AUTH     ((uint8_t)  80)
 #define        TAG_CLIENT_FQDN         ((uint8_t)  81)
 #define        TAG_AGENT_CIRCUIT       ((uint8_t)  82)
@@ -203,15 +206,15 @@ struct bootp {
 #define        TAG_TZ_STRING           ((uint8_t)  88)
 #define        TAG_FQDN_OPTION         ((uint8_t)  89)
 #define        TAG_AUTH                ((uint8_t)  90)
-#define        TAG_VINES_SERVERS       ((uint8_t)  91)
-#define        TAG_SERVER_RANK         ((uint8_t)  92)
+#define        TAG_CLIENT_LAST_TRANSACTION_TIME        ((uint8_t)  91)
+#define        TAG_ASSOCIATED_IP                       ((uint8_t)  92)
 #define        TAG_CLIENT_ARCH         ((uint8_t)  93)
 #define        TAG_CLIENT_NDI          ((uint8_t)  94)
 #define        TAG_CLIENT_GUID         ((uint8_t)  97)
 #define        TAG_LDAP_URL            ((uint8_t)  95)
 /* RFC 4833, TZ codes */
-#define        TAG_TZ_PCODE            ((uint8_t) 100)
-#define        TAG_TZ_TCODE            ((uint8_t) 101)
+#define        TAG_TZ_PCODE            ((uint8_t) 100)
+#define        TAG_TZ_TCODE            ((uint8_t) 101)
 #define        TAG_NETINFO_PARENT      ((uint8_t) 112)
 #define        TAG_NETINFO_PARENT_TAG  ((uint8_t) 113)
 #define        TAG_URL                 ((uint8_t) 114)
@@ -226,6 +229,12 @@ struct bootp {
 #define DHCPNAK                6
 #define DHCPRELEASE    7
 #define DHCPINFORM     8
+/* Defined in RFC4388 */
+#define DHCPLEASEQUERY       10
+#define DHCPLEASEUNASSIGNED  11
+#define DHCPLEASEUNKNOWN     12
+#define DHCPLEASEACTIVE      13
+
 
 /*
  * "vendor" data permitted for CMU bootp clients.
@@ -254,9 +263,16 @@ struct cmu_vend {
 #define CLIENT_FQDN_FLAGS_N    0x08
 /* end of original bootp.h */
 
+static const struct tok fqdn_flags_bm[] = {
+       { CLIENT_FQDN_FLAGS_S, "S" },
+       { CLIENT_FQDN_FLAGS_O, "O" },
+       { CLIENT_FQDN_FLAGS_E, "E" },
+       { CLIENT_FQDN_FLAGS_N, "N" },
+       { 0, NULL }
+};
+
 static void rfc1048_print(netdissect_options *, const u_char *);
 static void cmu_print(netdissect_options *, const u_char *);
-static char *client_fqdn_flags(u_int flags);
 
 static const struct tok bootp_flag_values[] = {
        { 0x8000,       "Broadcast" },
@@ -289,9 +305,8 @@ bootp_print(netdissect_options *ndo,
 
        bp_htype = GET_U_1(bp->bp_htype);
        bp_hlen = GET_U_1(bp->bp_hlen);
-       if (bp_htype == 1 && bp_hlen == 6 && bp_op == BOOTPREQUEST) {
-               ND_TCHECK_6(bp->bp_chaddr);
-               ND_PRINT(" from %s", GET_ETHERADDR_STRING(bp->bp_chaddr));
+       if (bp_htype == 1 && bp_hlen == MAC48_LEN && bp_op == BOOTPREQUEST) {
+               ND_PRINT(" from %s", GET_MAC48_STRING(bp->bp_chaddr));
        }
 
        ND_PRINT(", length %u", length);
@@ -306,7 +321,7 @@ bootp_print(netdissect_options *ndo,
                ND_PRINT(", htype %u", bp_htype);
 
        /* The usual length for 10Mb Ethernet address is 6 bytes */
-       if (bp_htype != 1 || bp_hlen != 6)
+       if (bp_htype != 1 || bp_hlen != MAC48_LEN)
                ND_PRINT(", hlen %u", bp_hlen);
 
        /* Only print interesting fields */
@@ -323,48 +338,43 @@ bootp_print(netdissect_options *ndo,
                ND_PRINT(" (0x%04x)", GET_BE_U_2(bp->bp_flags));
 
        /* Client's ip address */
-       ND_TCHECK_4(bp->bp_ciaddr);
        if (GET_IPV4_TO_NETWORK_ORDER(bp->bp_ciaddr))
                ND_PRINT("\n\t  Client-IP %s", GET_IPADDR_STRING(bp->bp_ciaddr));
 
        /* 'your' ip address (bootp client) */
-       ND_TCHECK_4(bp->bp_yiaddr);
        if (GET_IPV4_TO_NETWORK_ORDER(bp->bp_yiaddr))
                ND_PRINT("\n\t  Your-IP %s", GET_IPADDR_STRING(bp->bp_yiaddr));
 
        /* Server's ip address */
-       ND_TCHECK_4(bp->bp_siaddr);
        if (GET_IPV4_TO_NETWORK_ORDER(bp->bp_siaddr))
                ND_PRINT("\n\t  Server-IP %s", GET_IPADDR_STRING(bp->bp_siaddr));
 
        /* Gateway's ip address */
-       ND_TCHECK_4(bp->bp_giaddr);
        if (GET_IPV4_TO_NETWORK_ORDER(bp->bp_giaddr))
                ND_PRINT("\n\t  Gateway-IP %s", GET_IPADDR_STRING(bp->bp_giaddr));
 
        /* Client's Ethernet address */
-       if (bp_htype == 1 && bp_hlen == 6) {
-               ND_TCHECK_6(bp->bp_chaddr);
-               ND_PRINT("\n\t  Client-Ethernet-Address %s", GET_ETHERADDR_STRING(bp->bp_chaddr));
+       if (bp_htype == 1 && bp_hlen == MAC48_LEN) {
+               ND_PRINT("\n\t  Client-Ethernet-Address %s", GET_MAC48_STRING(bp->bp_chaddr));
        }
 
        if (GET_U_1(bp->bp_sname)) {    /* get first char only */
                ND_PRINT("\n\t  sname \"");
                if (nd_printztn(ndo, bp->bp_sname, (u_int)sizeof(bp->bp_sname),
-                               ndo->ndo_snapend) == 0) {
+                               NULL) == 0) {
+                       /* Within the buffer, but not NUL-terminated. */
                        ND_PRINT("\"");
-                       nd_print_trunc(ndo);
-                       return;
+                       goto invalid;
                }
                ND_PRINT("\"");
        }
        if (GET_U_1(bp->bp_file)) {     /* get first char only */
                ND_PRINT("\n\t  file \"");
                if (nd_printztn(ndo, bp->bp_file, (u_int)sizeof(bp->bp_file),
-                               ndo->ndo_snapend) == 0) {
+                               NULL) == 0) {
+                       /* Ditto. */
                        ND_PRINT("\"");
-                       nd_print_trunc(ndo);
-                       return;
+                       goto invalid;
                }
                ND_PRINT("\"");
        }
@@ -384,10 +394,9 @@ bootp_print(netdissect_options *ndo,
                if (ul != 0)
                        ND_PRINT("\n\t  Vendor-#0x%x", ul);
        }
-
        return;
-trunc:
-       nd_print_trunc(ndo);
+invalid:
+       nd_print_invalid(ndo);
 }
 
 /*
@@ -499,6 +508,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 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 */
@@ -509,14 +520,14 @@ static const struct tok tag2str[] = {
        { TAG_TZ_STRING,        "aTZSTR" },
        { TAG_FQDN_OPTION,      "bFQDNS" },     /* XXX 'b' */
        { TAG_AUTH,             "bAUTH" },      /* XXX 'b' */
-       { TAG_VINES_SERVERS,    "iVINES" },
-       { TAG_SERVER_RANK,      "sRANK" },
+       { TAG_CLIENT_LAST_TRANSACTION_TIME, "LLast-Transaction-Time" },
+       { TAG_ASSOCIATED_IP,    "iAssociated-IP" },
        { TAG_CLIENT_ARCH,      "sARCH" },
        { TAG_CLIENT_NDI,       "bNDI" },       /* XXX 'b' */
        { TAG_CLIENT_GUID,      "bGUID" },      /* XXX 'b' */
        { TAG_LDAP_URL,         "aLDAP" },
-       { TAG_TZ_PCODE,         "aPOSIX-TZ" },
-       { TAG_TZ_TCODE,         "aTZ-Name" },
+       { TAG_TZ_PCODE,         "aPOSIX-TZ" },
+       { TAG_TZ_TCODE,         "aTZ-Name" },
        { TAG_NETINFO_PARENT,   "iNI" },
        { TAG_NETINFO_PARENT_TAG, "aNITAG" },
        { TAG_URL,              "aURL" },
@@ -553,14 +564,18 @@ static const struct tok arp2str[] = {
 };
 
 static const struct tok dhcp_msg_values[] = {
-       { DHCPDISCOVER, "Discover" },
-       { DHCPOFFER,    "Offer" },
-       { DHCPREQUEST,  "Request" },
-       { DHCPDECLINE,  "Decline" },
-       { DHCPACK,      "ACK" },
-       { DHCPNAK,      "NACK" },
-       { DHCPRELEASE,  "Release" },
-       { DHCPINFORM,   "Inform" },
+       { DHCPDISCOVER,        "Discover" },
+       { DHCPOFFER,           "Offer" },
+       { DHCPREQUEST,         "Request" },
+       { DHCPDECLINE,         "Decline" },
+       { DHCPACK,             "ACK" },
+       { DHCPNAK,             "NACK" },
+       { DHCPRELEASE,         "Release" },
+       { DHCPINFORM,          "Inform" },
+       { DHCPLEASEQUERY,      "LeaseQuery" },
+       { DHCPLEASEUNASSIGNED, "LeaseUnassigned" },
+       { DHCPLEASEUNKNOWN,    "LeaseUnknown" },
+       { DHCPLEASEACTIVE,     "LeaseActive" },
        { 0, NULL }
 };
 
@@ -667,10 +682,7 @@ rfc1048_print(netdissect_options *ndo,
                case 'a':
                        /* ASCII strings */
                        ND_PRINT("\"");
-                       if (nd_printn(ndo, bp, len, ndo->ndo_snapend)) {
-                               ND_PRINT("\"");
-                               goto trunc;
-                       }
+                       nd_printjn(ndo, bp, len);
                        ND_PRINT("\"");
                        bp += len;
                        len = 0;
@@ -807,17 +819,14 @@ rfc1048_print(netdissect_options *ndo,
                                }
                                if (GET_U_1(bp) & 0x0f)
                                        ND_PRINT("[%s] ",
-                                                client_fqdn_flags(GET_U_1(bp)));
+                                                bittok2str_nosep(fqdn_flags_bm, "", (GET_U_1(bp))));
                                bp++;
                                if (GET_U_1(bp) || GET_U_1(bp + 1))
                                        ND_PRINT("%u/%u ", GET_U_1(bp),
                                                 GET_U_1(bp + 1));
                                bp += 2;
                                ND_PRINT("\"");
-                               if (nd_printn(ndo, bp, len - 3, ndo->ndo_snapend)) {
-                                       ND_PRINT("\"");
-                                       goto trunc;
-                               }
+                               nd_printjn(ndo, bp, len - 3);
                                ND_PRINT("\"");
                                bp += len - 3;
                                len = 0;
@@ -837,10 +846,7 @@ rfc1048_print(netdissect_options *ndo,
                                len--;
                                if (type == 0) {
                                        ND_PRINT("\"");
-                                       if (nd_printn(ndo, bp, len, ndo->ndo_snapend)) {
-                                               ND_PRINT("\"");
-                                               goto trunc;
-                                       }
+                                       nd_printjn(ndo, bp, len);
                                        ND_PRINT("\"");
                                        bp += len;
                                        len = 0;
@@ -883,8 +889,7 @@ rfc1048_print(netdissect_options *ndo,
                                        case AGENT_SUBOPTION_CIRCUIT_ID: /* fall through */
                                        case AGENT_SUBOPTION_REMOTE_ID:
                                        case AGENT_SUBOPTION_SUBSCRIBER_ID:
-                                               if (nd_printn(ndo, bp, suboptlen, ndo->ndo_snapend))
-                                                       goto trunc;
+                                               nd_printjn(ndo, bp, suboptlen);
                                                break;
 
                                        default:
@@ -982,10 +987,7 @@ rfc1048_print(netdissect_options *ndo,
                                                break;
                                        }
                                        ND_PRINT("\"");
-                                       if (nd_printn(ndo, bp, suboptlen, ndo->ndo_snapend)) {
-                                               ND_PRINT("\"");
-                                               goto trunc;
-                                       }
+                                       nd_printjn(ndo, bp, suboptlen);
                                        ND_PRINT("\"");
                                        ND_PRINT(", length %u", suboptlen);
                                        suboptnumber++;
@@ -995,6 +997,39 @@ rfc1048_print(netdissect_options *ndo,
                                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);
@@ -1010,9 +1045,6 @@ rfc1048_print(netdissect_options *ndo,
                        bp += len;
                }
        }
-       return;
-trunc:
-       nd_print_trunc(ndo);
 }
 
 #define PRINTCMUADDR(m, s) { ND_TCHECK_4(cmu->m); \
@@ -1042,29 +1074,6 @@ cmu_print(netdissect_options *ndo,
        PRINTCMUADDR(v_ins2, "IEN2");
        PRINTCMUADDR(v_ts1, "TS1");
        PRINTCMUADDR(v_ts2, "TS2");
-       return;
-
-trunc:
-       nd_print_trunc(ndo);
 }
 
 #undef PRINTCMUADDR
-
-static char *
-client_fqdn_flags(u_int flags)
-{
-       static char buf[8+1];
-       int i = 0;
-
-       if (flags & CLIENT_FQDN_FLAGS_S)
-               buf[i++] = 'S';
-       if (flags & CLIENT_FQDN_FLAGS_O)
-               buf[i++] = 'O';
-       if (flags & CLIENT_FQDN_FLAGS_E)
-               buf[i++] = 'E';
-       if (flags & CLIENT_FQDN_FLAGS_N)
-               buf[i++] = 'N';
-       buf[i] = '\0';
-
-       return buf;
-}