]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-tftp.c
Partially revert r273382, to reduce diffs against upstream. This was a
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-tftp.c
1 /*
2  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * Format and print trivial file transfer protocol packets.
22  */
23
24 #define NETDISSECT_REWORKED
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <tcpdump-stdinc.h>
30
31 #include <string.h>
32
33 #include "interface.h"
34 #include "extract.h"
35
36 /*
37  * Trivial File Transfer Protocol (IEN-133)
38  */
39
40 /*
41  * Packet types.
42  */
43 #define RRQ     01                      /* read request */
44 #define WRQ     02                      /* write request */
45 #define DATA    03                      /* data packet */
46 #define ACK     04                      /* acknowledgement */
47 #define TFTP_ERROR      05                      /* error code */
48 #define OACK    06                      /* option acknowledgement */
49
50 struct  tftphdr {
51         unsigned short  th_opcode;              /* packet type */
52         union {
53                 unsigned short  tu_block;       /* block # */
54                 unsigned short  tu_code;        /* error code */
55                 char    tu_stuff[1];    /* request packet stuff */
56         } th_u;
57         char    th_data[1];             /* data or error string */
58 };
59
60 #define th_block        th_u.tu_block
61 #define th_code         th_u.tu_code
62 #define th_stuff        th_u.tu_stuff
63 #define th_msg          th_data
64
65 /*
66  * Error codes.
67  */
68 #define EUNDEF          0               /* not defined */
69 #define ENOTFOUND       1               /* file not found */
70 #define EACCESS         2               /* access violation */
71 #define ENOSPACE        3               /* disk full or allocation exceeded */
72 #define EBADOP          4               /* illegal TFTP operation */
73 #define EBADID          5               /* unknown transfer ID */
74 #define EEXISTS         6               /* file already exists */
75 #define ENOUSER         7               /* no such user */
76
77 static const char tstr[] = " [|tftp]";
78
79 /* op code to string mapping */
80 static const struct tok op2str[] = {
81         { RRQ,          "RRQ" },        /* read request */
82         { WRQ,          "WRQ" },        /* write request */
83         { DATA,         "DATA" },       /* data packet */
84         { ACK,          "ACK" },        /* acknowledgement */
85         { TFTP_ERROR,   "ERROR" },      /* error code */
86         { OACK,         "OACK" },       /* option acknowledgement */
87         { 0,            NULL }
88 };
89
90 /* error code to string mapping */
91 static const struct tok err2str[] = {
92         { EUNDEF,       "EUNDEF" },     /* not defined */
93         { ENOTFOUND,    "ENOTFOUND" },  /* file not found */
94         { EACCESS,      "EACCESS" },    /* access violation */
95         { ENOSPACE,     "ENOSPACE" },   /* disk full or allocation exceeded */
96         { EBADOP,       "EBADOP" },     /* illegal TFTP operation */
97         { EBADID,       "EBADID" },     /* unknown transfer ID */
98         { EEXISTS,      "EEXISTS" },    /* file already exists */
99         { ENOUSER,      "ENOUSER" },    /* no such user */
100         { 0,            NULL }
101 };
102
103 /*
104  * Print trivial file transfer program requests
105  */
106 void
107 tftp_print(netdissect_options *ndo,
108            register const u_char *bp, u_int length)
109 {
110         register const struct tftphdr *tp;
111         register const char *cp;
112         register const u_char *p;
113         register int opcode, i;
114
115         tp = (const struct tftphdr *)bp;
116
117         /* Print length */
118         ND_PRINT((ndo, " %d", length));
119
120         /* Print tftp request type */
121         ND_TCHECK(tp->th_opcode);
122         opcode = EXTRACT_16BITS(&tp->th_opcode);
123         cp = tok2str(op2str, "tftp-#%d", opcode);
124         ND_PRINT((ndo, " %s", cp));
125         /* Bail if bogus opcode */
126         if (*cp == 't')
127                 return;
128
129         switch (opcode) {
130
131         case RRQ:
132         case WRQ:
133         case OACK:
134                 p = (u_char *)tp->th_stuff;
135                 ND_PRINT((ndo, " "));
136                 /* Print filename or first option */
137                 if (opcode != OACK)
138                         ND_PRINT((ndo, "\""));
139                 i = fn_print(ndo, p, ndo->ndo_snapend);
140                 if (opcode != OACK)
141                         ND_PRINT((ndo, "\""));
142
143                 /* Print the mode (RRQ and WRQ only) and any options */
144                 while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) {
145                         if (length <= (u_int)(p - (const u_char *)&tp->th_block))
146                                 break;
147                         p++;
148                         if (*p != '\0') {
149                                 ND_PRINT((ndo, " "));
150                                 fn_print(ndo, p, ndo->ndo_snapend);
151                         }
152                 }
153
154                 if (i)
155                         goto trunc;
156                 break;
157
158         case ACK:
159         case DATA:
160                 ND_TCHECK(tp->th_block);
161                 ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block)));
162                 break;
163
164         case TFTP_ERROR:
165                 /* Print error code string */
166                 ND_TCHECK(tp->th_code);
167                 ND_PRINT((ndo, " %s \"", tok2str(err2str, "tftp-err-#%d \"",
168                                        EXTRACT_16BITS(&tp->th_code))));
169                 /* Print error message string */
170                 i = fn_print(ndo, (const u_char *)tp->th_data, ndo->ndo_snapend);
171                 ND_PRINT((ndo, "\""));
172                 if (i)
173                         goto trunc;
174                 break;
175
176         default:
177                 /* We shouldn't get here */
178                 ND_PRINT((ndo, "(unknown #%d)", opcode));
179                 break;
180         }
181         return;
182 trunc:
183         ND_PRINT((ndo, "%s", tstr));
184         return;
185 }