Heikki Vatiainen's patch to add a flag to control whether to interpret
[obnox/wireshark/wip.git] / packet-tftp.c
1 /* packet-tftp.c
2  * Routines for tftp packet dissection
3  *
4  * Richard Sharpe <rsharpe@ns.aus.com>
5  *
6  * $Id: packet-tftp.c,v 1.8 2000/01/07 22:05:41 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@zing.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * Copied from packet-bootp.c
13  * 
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  * 
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
35 #endif
36
37 #ifdef HAVE_NETINET_IN_H
38 # include <netinet/in.h>
39 #endif
40
41 #include <glib.h>
42 #include "packet.h"
43
44 static int proto_tftp = -1;
45 static int hf_tftp_type = -1;
46 static int hf_tftp_error_code = -1;
47
48 static gint ett_tftp = -1;
49
50 #define RRQ     1
51 #define WRQ     2
52 #define DATA    3
53 #define ACK     4
54 #define ERROR   5
55
56 char *tftp_opcodes[8] = {
57   "Unknown Request",
58   "Read Request",
59   "Write Request",
60   "Data Packet",
61   "Acknowledgement",
62   "Error Code",
63   "Unknown Request",
64   "Unknown Request"
65 };
66
67 char *tftp_errors[8] = {
68   "Not defined",
69   "File not found",
70   "Access violation",
71   "Disk full or allocation exceeded",
72   "Illegal TFTP Operation",
73   "Unknown transfer ID",
74   "File already exists",
75   "No such user"
76 };
77
78 void
79 dissect_tftp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
80 {
81         proto_tree      *tftp_tree;
82         proto_item      *ti;
83         u_int           i1;
84
85         if (check_col(fd, COL_PROTOCOL))
86                 col_add_str(fd, COL_PROTOCOL, "TFTP");
87
88         if (check_col(fd, COL_INFO)) {
89
90           i1 = pntohs(&pd[offset]);
91           col_add_fstr(fd, COL_INFO, "TFTP %s", i1 <= ERROR ? tftp_opcodes[i1 % 8] : "Unknown Request");
92
93         }
94
95         if (tree) {
96
97           ti = proto_tree_add_item(tree, proto_tftp, offset, END_OF_FRAME, NULL);
98           tftp_tree = proto_item_add_subtree(ti, ett_tftp);
99
100           i1 = pntohs(pd+offset);
101           proto_tree_add_item_hidden(tftp_tree, hf_tftp_type, offset, 2, i1);
102             
103           switch (i1) {
104           case RRQ:
105             proto_tree_add_text(tftp_tree, offset, 2, "Read Request");
106             offset += 2;
107             i1 = strlen(pd+offset);
108             proto_tree_add_text(tftp_tree, offset, i1+1, "Source File: %s", pd+offset);
109             offset += i1 + 1;
110             proto_tree_add_text(tftp_tree, offset, END_OF_FRAME, "Type: %s",pd+offset);
111             break;
112           case WRQ:
113             proto_tree_add_text(tftp_tree, offset, 2, "Write Request");
114             offset += 2;
115             i1 = strlen(pd+offset);
116             proto_tree_add_text(tftp_tree, offset, i1+1, "Destination File: %s", pd+offset);
117             offset += i1 + 1;
118             proto_tree_add_text(tftp_tree, offset+2, END_OF_FRAME, "Type: %s",pd+offset);
119             break;
120           case DATA:
121             proto_tree_add_text(tftp_tree, offset, 2, "Data Packet");
122             offset += 2;
123             i1 = pntohs(pd+offset);
124             proto_tree_add_text(tftp_tree, offset, 2, "Block = %u", i1);
125             offset += 2;
126             proto_tree_add_text(tftp_tree, offset, END_OF_FRAME,
127                 "Data (%d bytes)", END_OF_FRAME);
128             break;
129           case ACK:
130             proto_tree_add_text(tftp_tree, offset, 2, "Acknowledgement");
131             offset += 2;
132             i1 = pntohs(pd+offset);
133             proto_tree_add_text(tftp_tree, offset, END_OF_FRAME, "Block = %u", i1);
134             break;
135           case ERROR:
136             proto_tree_add_text(tftp_tree, offset, 2, "Error Code");
137             offset += 2;
138             i1 = pntohs(pd+offset);
139             proto_tree_add_item_hidden(tftp_tree, hf_tftp_error_code, offset, 2, i1);
140             proto_tree_add_text(tftp_tree, offset, 2, "Code = %s", tftp_errors[i1 % 8]);
141             offset += 2;
142             proto_tree_add_text(tftp_tree, offset, END_OF_FRAME, "Error Message: %s", pd + offset);
143             break;
144           default:
145             proto_tree_add_text(tftp_tree, offset, 2, "Unknown TFTP Request: %0X.", i1);
146             offset += 2;
147             proto_tree_add_text(tftp_tree, offset, END_OF_FRAME,
148                 "Data (%d bytes)", END_OF_FRAME);
149             break;
150           }
151
152         }
153 }
154
155 void
156 proto_register_tftp(void)
157 {
158
159   static hf_register_info hf[] = {
160     { &hf_tftp_type,
161       { "Type",               "tftp.type",
162         FT_UINT16, BASE_DEC, NULL, 0x0,
163         "TFTP message type" }},
164
165     { &hf_tftp_error_code,
166       { "Error code",         "tftp.error.code",
167         FT_UINT16, BASE_DEC, NULL, 0x0,
168         "Error code in case of TFTP error message" }}
169   };
170   static gint *ett[] = {
171     &ett_tftp,
172   };
173
174   proto_tftp = proto_register_protocol("Trivial File Transfer Protocol", "tftp");
175   proto_register_field_array(proto_tftp, hf, array_length(hf));
176   proto_register_subtree_array(ett, array_length(ett));
177 }