Add an additional "title" attribute for UAT fields; that's what's
[obnox/wireshark/wip.git] / epan / dissectors / packet-user_encap.c
1 /* packet-user_encap.c
2  * Allow users to specify the dissectors for DLTs
3  * Luis E. Garcia Ontanon <luis@ontanon.org>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998
10  *
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  *  of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <string.h>
32 #include <glib.h>
33 #include <epan/packet.h>
34 #include <epan/expert.h>
35 #include <epan/prefs.h>
36 #include <epan/uat.h>
37 #include <epan/emem.h>
38
39 #ifdef _MSC_VER
40 /* disable: warning C4090: 'XY' : different 'const' qualifiers */
41 #pragma warning(disable:4090)
42 #endif
43
44 typedef struct _user_encap_t {
45         guint encap;
46         char* payload_proto_name;
47         dissector_handle_t payload_proto;
48         char* header_proto_name;
49         dissector_handle_t header_proto;
50         char* trailer_proto_name;
51         dissector_handle_t trailer_proto;
52         guint header_size;
53         guint trailer_size;
54 } user_encap_t;
55
56 #define ENCAP0_STR "User 0 (DLT=147)"
57 static const value_string user_dlts[] = {
58         { WTAP_ENCAP_USER0, ENCAP0_STR},
59         { WTAP_ENCAP_USER1, "User 1 (DLT=148)"},
60         { WTAP_ENCAP_USER2, "User 2 (DLT=149)"},
61         { WTAP_ENCAP_USER3, "User 3 (DLT=150)"},
62         { WTAP_ENCAP_USER4, "User 4 (DLT=151)"},
63         { WTAP_ENCAP_USER5, "User 5 (DLT=152)"},
64         { WTAP_ENCAP_USER6, "User 6 (DLT=153)"},
65         { WTAP_ENCAP_USER7, "User 7 (DLT=154)"},
66         { WTAP_ENCAP_USER8, "User 8 (DLT=155)"},
67         { WTAP_ENCAP_USER9, "User 9 (DLT=156)"},
68         { WTAP_ENCAP_USER10, "User 10 (DLT=157)"},
69         { WTAP_ENCAP_USER11, "User 11 (DLT=158)"},
70         { WTAP_ENCAP_USER12, "User 12 (DLT=159)"},
71         { WTAP_ENCAP_USER13, "User 13 (DLT=160)"},
72         { WTAP_ENCAP_USER14, "User 14 (DLT=161)"},
73         { WTAP_ENCAP_USER15, "User 15 (DLT=162)"},
74         { 0, NULL }
75 };
76 static int proto_user_encap = -1;
77
78 static user_encap_t* encaps = NULL;
79 static guint num_encaps = 0;
80 static uat_t* encaps_uat;
81 static dissector_handle_t data_handle;
82
83 static void dissect_user(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree) {
84         user_encap_t* encap = NULL;
85         tvbuff_t* payload_tvb;
86         int offset = 0;
87         int len;
88         guint i;
89         
90         for (i = 0; i < num_encaps; i++) {
91                 if (encaps[i].encap == pinfo->match_port) {
92                         encap = &(encaps[i]);
93                         break;
94                 }
95         }
96         
97         if (!encap) {
98                 char* msg = ep_strdup_printf("User encapsulation not handled: DLT=%d, check your Preferences->Protocols->DLT_USER",
99                                                                          pinfo->match_port + 147 - WTAP_ENCAP_USER0);
100                 proto_item* item = proto_tree_add_text(tree, tvb, 0, 0, "%s", msg);
101                 
102                 expert_add_info_format(pinfo, item, PI_UNDECODED, PI_WARN, "%s", msg);
103                 
104                 call_dissector(data_handle, tvb, pinfo, tree);
105                 return;
106         } else {
107                 proto_item* item = proto_tree_add_item(tree,proto_user_encap,tvb,0,0,FALSE);
108                 proto_item_set_text(item,"DLT: %d",pinfo->match_port + 147 - WTAP_ENCAP_USER0);
109         }
110
111         len = tvb_reported_length(tvb) - (encap->header_size + encap->trailer_size);
112         
113         if (encap->header_size) {
114                 tvbuff_t* hdr_tvb = tvb_new_subset(tvb, 0, encap->header_size, encap->header_size);
115                 call_dissector(encap->header_proto, hdr_tvb, pinfo, tree);
116                 offset = encap->header_size;
117         }
118         
119         payload_tvb = tvb_new_subset(tvb, encap->header_size, len, len);
120         call_dissector(encap->payload_proto, payload_tvb, pinfo, tree);
121
122         if (encap->trailer_size) {
123                 tvbuff_t* trailer_tvb = tvb_new_subset(tvb, encap->header_size + len, encap->trailer_size, encap->trailer_size);
124                 call_dissector(encap->trailer_proto, trailer_tvb, pinfo, tree);
125                 offset = encap->trailer_size;
126         }
127 }
128
129 static void user_update_cb(void* r _U_, const char** err _U_) {
130 }
131
132 UAT_VS_DEF(user_encap, encap, user_encap_t, WTAP_ENCAP_USER0, ENCAP0_STR)
133 UAT_PROTO_DEF(user_encap, payload_proto, payload_proto, payload_proto_name, user_encap_t)
134 UAT_DEC_CB_DEF(user_encap, header_size, user_encap_t)
135 UAT_DEC_CB_DEF(user_encap, trailer_size, user_encap_t)
136 UAT_PROTO_DEF(user_encap, header_proto, header_proto, header_proto_name, user_encap_t)
137 UAT_PROTO_DEF(user_encap, trailer_proto, trailer_proto, trailer_proto_name, user_encap_t)
138
139 void proto_reg_handoff_user_encap(void)
140 {
141         dissector_handle_t user_encap_handle;
142         guint i;
143         
144         user_encap_handle = find_dissector("user_dlt");
145         data_handle = find_dissector("data");
146         
147         for (i = WTAP_ENCAP_USER0 ; i <= WTAP_ENCAP_USER15; i++)
148                 dissector_add("wtap_encap", i, user_encap_handle);
149
150 }
151
152
153 void proto_register_user_encap(void)
154 {
155         module_t *module;
156
157         static uat_field_t user_flds[] = {
158                 UAT_FLD_VS(user_encap,encap,"DLT",user_dlts,"The DLT"),
159                 UAT_FLD_PROTO(user_encap,payload_proto,"Payload protocol","Protocol to be used for the payload of this DLT"),
160                 UAT_FLD_DEC(user_encap,header_size,"Header size","Size of an eventual header that precedes the actual payload, 0 means none"),
161                 UAT_FLD_PROTO(user_encap,header_proto,"Header protocol","Protocol to be used for the header (empty = data)"),
162                 UAT_FLD_DEC(user_encap,trailer_size,"Trailer size","Size of an eventual trailer that follows the actual payload, 0 means none"),
163                 UAT_FLD_PROTO(user_encap,trailer_proto,"Trailer protocol","Protocol to be used for the trailer (empty = data)"),
164                 UAT_END_FIELDS
165         };
166         
167         
168         proto_user_encap = proto_register_protocol("DLT User","DLT_USER","user_dlt");
169         
170         module = prefs_register_protocol(proto_user_encap, NULL);
171         
172         encaps_uat = uat_new("User DLTs Table",
173                                                  sizeof(user_encap_t),
174                                                  "user_dlts",
175                                                  TRUE,
176                                                  (void**) &encaps,
177                                                  &num_encaps,
178                                                  UAT_CAT_FFMT,
179                                                  "ChUserDLTsSection",
180                                                  NULL,
181                                                  user_update_cb,
182                                                  NULL,
183                                                  user_flds );
184         
185         prefs_register_uat_preference(module,
186                                       "encaps_table",
187                                       "Encapsulations Table",
188                                       "A table that enumerates the various protocols to be used against a certain user DLT",
189                                       encaps_uat);
190         
191         
192         register_dissector("user_dlt",dissect_user,proto_user_encap);
193
194         /*
195         prefs_register_protocol_obsolete(proto_register_protocol("DLT User A","DLT_USER_A","user_dlt_a"));
196         prefs_register_protocol_obsolete(proto_register_protocol("DLT User B","DLT_USER_B","user_dlt_b"));
197         prefs_register_protocol_obsolete(proto_register_protocol("DLT User C","DLT_USER_C","user_dlt_c"));
198         prefs_register_protocol_obsolete(proto_register_protocol("DLT User D","DLT_USER_D","user_dlt_d"));
199         */
200 }