I hope no one just committed something on this.
[metze/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.6 1999/11/14 10:32:26 deniel Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@unicom.net>
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 #define RRQ     1
49 #define WRQ     2
50 #define DATA    3
51 #define ACK     4
52 #define ERROR   5
53
54 char *tftp_opcodes[8] = {
55   "Unknown Request",
56   "Read Request",
57   "Write Request",
58   "Data Packet",
59   "Acknowledgement",
60   "Error Code",
61   "Unknown Request",
62   "Unknown Request"
63 };
64
65 char *tftp_errors[8] = {
66   "Not defined",
67   "File not found",
68   "Access violation",
69   "Disk full or allocation exceeded",
70   "Illegal TFTP Operation",
71   "Unknown transfer ID",
72   "File already exists",
73   "No such user"
74 };
75
76 void
77 dissect_tftp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
78 {
79         proto_tree      *tftp_tree;
80         proto_item      *ti;
81         u_int           i1;
82
83         if (check_col(fd, COL_PROTOCOL))
84                 col_add_str(fd, COL_PROTOCOL, "TFTP");
85
86         if (check_col(fd, COL_INFO)) {
87
88           i1 = pntohs(&pd[offset]);
89           col_add_fstr(fd, COL_INFO, "TFTP %s", i1 <= ERROR ? tftp_opcodes[i1 % 8] : "Unknown Request");
90
91         }
92
93         if (tree) {
94
95           ti = proto_tree_add_item(tree, proto_tftp, offset, END_OF_FRAME, NULL);
96           tftp_tree = proto_item_add_subtree(ti, ETT_TFTP);
97
98           i1 = pntohs(pd+offset);
99           proto_tree_add_item_hidden(tftp_tree, hf_tftp_type, offset, 2, i1);
100             
101           switch (i1) {
102           case RRQ:
103             proto_tree_add_text(tftp_tree, offset, 2, "Read Request");
104             offset += 2;
105             i1 = strlen(pd+offset);
106             proto_tree_add_text(tftp_tree, offset, i1+1, "Source File: %s", pd+offset);
107             offset += i1 + 1;
108             proto_tree_add_text(tftp_tree, offset, END_OF_FRAME, "Type: %s",pd+offset);
109             break;
110           case WRQ:
111             proto_tree_add_text(tftp_tree, offset, 2, "Write Request");
112             offset += 2;
113             i1 = strlen(pd+offset);
114             proto_tree_add_text(tftp_tree, offset, i1+1, "Destination File: %s", pd+offset);
115             offset += i1 + 1;
116             proto_tree_add_text(tftp_tree, offset+2, END_OF_FRAME, "Type: %s",pd+offset);
117             break;
118           case DATA:
119             proto_tree_add_text(tftp_tree, offset, 2, "Data Packet");
120             offset += 2;
121             i1 = pntohs(pd+offset);
122             proto_tree_add_text(tftp_tree, offset, 2, "Block = %u", i1);
123             offset += 2;
124             proto_tree_add_text(tftp_tree, offset, END_OF_FRAME,
125                 "Data (%d bytes)", END_OF_FRAME);
126             break;
127           case ACK:
128             proto_tree_add_text(tftp_tree, offset, 2, "Acknowledgement");
129             offset += 2;
130             i1 = pntohs(pd+offset);
131             proto_tree_add_text(tftp_tree, offset, END_OF_FRAME, "Block = %u", i1);
132             break;
133           case ERROR:
134             proto_tree_add_text(tftp_tree, offset, 2, "Error Code");
135             offset += 2;
136             i1 = pntohs(pd+offset);
137             proto_tree_add_item_hidden(tftp_tree, hf_tftp_error_code, offset, 2, i1);
138             proto_tree_add_text(tftp_tree, offset, 2, "Code = %s", tftp_errors[i1 % 8]);
139             offset += 2;
140             proto_tree_add_text(tftp_tree, offset, END_OF_FRAME, "Error Message: %s", pd + offset);
141             break;
142           default:
143             proto_tree_add_text(tftp_tree, offset, 2, "Unknown TFTP Request: %0X.", i1);
144             offset += 2;
145             proto_tree_add_text(tftp_tree, offset, END_OF_FRAME,
146                 "Data (%d bytes)", END_OF_FRAME);
147             break;
148           }
149
150         }
151 }
152
153 void
154 proto_register_tftp(void)
155 {
156
157   static hf_register_info hf[] = {
158     { &hf_tftp_type,
159       { "Type",               "tftp.type",
160         FT_UINT16, BASE_DEC, NULL, 0x0,
161         "TFTP message type" }},
162
163     { &hf_tftp_error_code,
164       { "Error code",         "tftp.error.code",
165         FT_UINT16, BASE_DEC, NULL, 0x0,
166         "Error code in case of TFTP error message" }}
167   };
168
169   proto_tftp = proto_register_protocol("Trivial File Transfer Protocol", "tftp");
170   proto_register_field_array(proto_tftp, hf, array_length(hf));
171 }