vendor/TCPDUMP: Import libpcap 4.99.1
[dragonfly.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
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
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 }