]> The Tcpdump Group git mirrors - tcpdump/blob - print-tftp.c
Move the printer summaries from INSTALL.txt to each printer
[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 /* \summary: Trivial File Transfer Protocol (TFTP) printer */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <netdissect-stdinc.h>
31
32 #include <string.h>
33
34 #include "netdissect.h"
35 #include "extract.h"
36
37 /*
38 * Trivial File Transfer Protocol (IEN-133)
39 */
40
41 /*
42 * Packet types.
43 */
44 #define RRQ 01 /* read request */
45 #define WRQ 02 /* write request */
46 #define DATA 03 /* data packet */
47 #define ACK 04 /* acknowledgement */
48 #define TFTP_ERROR 05 /* error code */
49 #define OACK 06 /* option acknowledgement */
50
51 struct tftphdr {
52 unsigned short th_opcode; /* packet type */
53 union {
54 unsigned short tu_block; /* block # */
55 unsigned short tu_code; /* error code */
56 char tu_stuff[1]; /* request packet stuff */
57 } th_u;
58 char th_data[1]; /* data or error string */
59 };
60
61 #define th_block th_u.tu_block
62 #define th_code th_u.tu_code
63 #define th_stuff th_u.tu_stuff
64 #define th_msg th_data
65
66 /*
67 * Error codes.
68 */
69 #define EUNDEF 0 /* not defined */
70 #define ENOTFOUND 1 /* file not found */
71 #define EACCESS 2 /* access violation */
72 #define ENOSPACE 3 /* disk full or allocation exceeded */
73 #define EBADOP 4 /* illegal TFTP operation */
74 #define EBADID 5 /* unknown transfer ID */
75 #define EEXISTS 6 /* file already exists */
76 #define ENOUSER 7 /* no such user */
77
78 static const char tstr[] = " [|tftp]";
79
80 /* op code to string mapping */
81 static const struct tok op2str[] = {
82 { RRQ, "RRQ" }, /* read request */
83 { WRQ, "WRQ" }, /* write request */
84 { DATA, "DATA" }, /* data packet */
85 { ACK, "ACK" }, /* acknowledgement */
86 { TFTP_ERROR, "ERROR" }, /* error code */
87 { OACK, "OACK" }, /* option acknowledgement */
88 { 0, NULL }
89 };
90
91 /* error code to string mapping */
92 static const struct tok err2str[] = {
93 { EUNDEF, "EUNDEF" }, /* not defined */
94 { ENOTFOUND, "ENOTFOUND" }, /* file not found */
95 { EACCESS, "EACCESS" }, /* access violation */
96 { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */
97 { EBADOP, "EBADOP" }, /* illegal TFTP operation */
98 { EBADID, "EBADID" }, /* unknown transfer ID */
99 { EEXISTS, "EEXISTS" }, /* file already exists */
100 { ENOUSER, "ENOUSER" }, /* no such user */
101 { 0, NULL }
102 };
103
104 /*
105 * Print trivial file transfer program requests
106 */
107 void
108 tftp_print(netdissect_options *ndo,
109 register const u_char *bp, u_int length)
110 {
111 register const struct tftphdr *tp;
112 register const char *cp;
113 register const u_char *p;
114 register int opcode, i;
115
116 tp = (const struct tftphdr *)bp;
117
118 /* Print length */
119 ND_PRINT((ndo, " %d", length));
120
121 /* Print tftp request type */
122 ND_TCHECK(tp->th_opcode);
123 opcode = EXTRACT_16BITS(&tp->th_opcode);
124 cp = tok2str(op2str, "tftp-#%d", opcode);
125 ND_PRINT((ndo, " %s", cp));
126 /* Bail if bogus opcode */
127 if (*cp == 't')
128 return;
129
130 switch (opcode) {
131
132 case RRQ:
133 case WRQ:
134 case OACK:
135 p = (const u_char *)tp->th_stuff;
136 ND_PRINT((ndo, " "));
137 /* Print filename or first option */
138 if (opcode != OACK)
139 ND_PRINT((ndo, "\""));
140 i = fn_print(ndo, p, ndo->ndo_snapend);
141 if (opcode != OACK)
142 ND_PRINT((ndo, "\""));
143
144 /* Print the mode (RRQ and WRQ only) and any options */
145 while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) {
146 if (length <= (u_int)(p - (const u_char *)&tp->th_block))
147 break;
148 p++;
149 if (*p != '\0') {
150 ND_PRINT((ndo, " "));
151 fn_print(ndo, p, ndo->ndo_snapend);
152 }
153 }
154
155 if (i)
156 goto trunc;
157 break;
158
159 case ACK:
160 case DATA:
161 ND_TCHECK(tp->th_block);
162 ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block)));
163 break;
164
165 case TFTP_ERROR:
166 /* Print error code string */
167 ND_TCHECK(tp->th_code);
168 ND_PRINT((ndo, " %s \"", tok2str(err2str, "tftp-err-#%d \"",
169 EXTRACT_16BITS(&tp->th_code))));
170 /* Print error message string */
171 i = fn_print(ndo, (const u_char *)tp->th_data, ndo->ndo_snapend);
172 ND_PRINT((ndo, "\""));
173 if (i)
174 goto trunc;
175 break;
176
177 default:
178 /* We shouldn't get here */
179 ND_PRINT((ndo, "(unknown #%d)", opcode));
180 break;
181 }
182 return;
183 trunc:
184 ND_PRINT((ndo, "%s", tstr));
185 return;
186 }