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