]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-tftp.c
CI: Add warning exemptions for Sun C (suncc-5.14) on Solaris 10
[tcpdump] / print-tftp.c
index d996b8cfd69269cd7ef04ee6c4f72a7460111ab5..ec64a5c9dfa97b7c99ede676beafe926cb0c44aa 100644 (file)
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Format and print trivial file transfer protocol packets.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+/* \summary: Trivial File Transfer Protocol (TFTP) printer */
 
-#include <tcpdump-stdinc.h>
+#include <config.h>
 
-#include <string.h>
+#include "netdissect-stdinc.h"
 
-#include "interface.h"
+#include "netdissect.h"
 #include "extract.h"
 
 /*
 #define        TFTP_ERROR      05                      /* error code */
 #define OACK   06                      /* option acknowledgement */
 
-struct tftphdr {
-       unsigned short  th_opcode;              /* packet type */
-       union {
-               unsigned short  tu_block;       /* block # */
-               unsigned short  tu_code;        /* error code */
-               char    tu_stuff[1];    /* request packet stuff */
-       } th_u;
-       char    th_data[1];             /* data or error string */
-};
-
-#define        th_block        th_u.tu_block
-#define        th_code         th_u.tu_code
-#define        th_stuff        th_u.tu_stuff
-#define        th_msg          th_data
-
 /*
  * Error codes.
  */
@@ -73,7 +54,6 @@ struct        tftphdr {
 #define        EEXISTS         6               /* file already exists */
 #define        ENOUSER         7               /* no such user */
 
-static const char tstr[] = " [|tftp]";
 
 /* op code to string mapping */
 static const struct tok op2str[] = {
@@ -104,81 +84,113 @@ static const struct tok err2str[] = {
  */
 void
 tftp_print(netdissect_options *ndo,
-           register const u_char *bp, u_int length)
+           const u_char *bp, u_int length)
 {
-       register const struct tftphdr *tp;
-       register const char *cp;
-       register const u_char *p;
-       register int opcode, i;
+       const char *cp;
+       u_int opcode;
+       u_int ui;
 
-       tp = (const struct tftphdr *)bp;
+       ndo->ndo_protocol = "tftp";
 
+       /* Print protocol */
+       nd_print_protocol_caps(ndo);
        /* Print length */
-       ND_PRINT((ndo, " %d", length));
+       ND_PRINT(", length %u", length);
 
        /* Print tftp request type */
-       ND_TCHECK(tp->th_opcode);
-       opcode = EXTRACT_16BITS(&tp->th_opcode);
-       cp = tok2str(op2str, "tftp-#%d", opcode);
-       ND_PRINT((ndo, " %s", cp));
+       if (length < 2)
+               goto trunc;
+       opcode = GET_BE_U_2(bp);
+       cp = tok2str(op2str, "tftp-#%u", opcode);
+       ND_PRINT(", %s", cp);
        /* Bail if bogus opcode */
        if (*cp == 't')
                return;
+       bp += 2;
+       length -= 2;
 
        switch (opcode) {
 
        case RRQ:
        case WRQ:
-       case OACK:
-               p = (const u_char *)tp->th_stuff;
-               ND_PRINT((ndo, " "));
-               /* Print filename or first option */
-               if (opcode != OACK)
-                       ND_PRINT((ndo, "\""));
-               i = fn_print(ndo, p, ndo->ndo_snapend);
-               if (opcode != OACK)
-                       ND_PRINT((ndo, "\""));
-
-               /* Print the mode (RRQ and WRQ only) and any options */
-               while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) {
-                       if (length <= (u_int)(p - (const u_char *)&tp->th_block))
-                               break;
-                       p++;
-                       if (*p != '\0') {
-                               ND_PRINT((ndo, " "));
-                               fn_print(ndo, p, ndo->ndo_snapend);
-                       }
+               if (length == 0)
+                       goto trunc;
+               ND_PRINT(" ");
+               /* Print filename */
+               ND_PRINT("\"");
+               ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
+               ND_PRINT("\"");
+               if (ui == 0)
+                       goto trunc;
+               bp += ui;
+               length -= ui;
+
+               /* Print the mode - RRQ and WRQ only */
+               if (length == 0)
+                       goto trunc;     /* no mode */
+               ND_PRINT(" ");
+               ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
+               if (ui == 0)
+                       goto trunc;
+               bp += ui;
+               length -= ui;
+
+               /* Print options, if any */
+               while (length != 0) {
+                       if (GET_U_1(bp) != '\0')
+                               ND_PRINT(" ");
+                       ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
+                       if (ui == 0)
+                               goto trunc;
+                       bp += ui;
+                       length -= ui;
                }
+               break;
 
-               if (i)
-                       goto trunc;
+       case OACK:
+               /* Print options */
+               while (length != 0) {
+                       if (GET_U_1(bp) != '\0')
+                               ND_PRINT(" ");
+                       ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
+                       if (ui == 0)
+                               goto trunc;
+                       bp += ui;
+                       length -= ui;
+               }
                break;
 
        case ACK:
        case DATA:
-               ND_TCHECK(tp->th_block);
-               ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block)));
+               if (length < 2)
+                       goto trunc;     /* no block number */
+               ND_PRINT(" block %u", GET_BE_U_2(bp));
                break;
 
        case TFTP_ERROR:
                /* Print error code string */
-               ND_TCHECK(tp->th_code);
-               ND_PRINT((ndo, " %s \"", tok2str(err2str, "tftp-err-#%d \"",
-                                      EXTRACT_16BITS(&tp->th_code))));
+               if (length < 2)
+                       goto trunc;     /* no error code */
+               ND_PRINT(" %s", tok2str(err2str, "tftp-err-#%u \"",
+                                      GET_BE_U_2(bp)));
+               bp += 2;
+               length -= 2;
                /* Print error message string */
-               i = fn_print(ndo, (const u_char *)tp->th_data, ndo->ndo_snapend);
-               ND_PRINT((ndo, "\""));
-               if (i)
+               if (length == 0)
+                       goto trunc;     /* no error message */
+               ND_PRINT(" \"");
+               ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
+               ND_PRINT("\"");
+               if (ui == 0)
                        goto trunc;
                break;
 
        default:
                /* We shouldn't get here */
-               ND_PRINT((ndo, "(unknown #%d)", opcode));
+               ND_PRINT("(unknown #%u)", opcode);
                break;
        }
        return;
 trunc:
-       ND_PRINT((ndo, "%s", tstr));
-       return;
+       nd_print_trunc(ndo);
 }