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