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