1 /* protobuf-helper.h
2  *
3  * C Wrapper Layer of Protocol Buffers Language library.
4  * Copyright 2019, Huang Qiangxiong <qiangxiong.huang@qq.com>
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12 
13 /* The packet-protobuf dissector needs get information from *.proto files for dissecting
14  * protobuf packet correctly. The information includes:
15  *   - The names of MESSAGE, ENUM, FIELD, ENUM_VALUE;
16  *   - The data type of FIELD which assuring the value of protobuf field of packet can be dissected correctly.
17  *
18  * At present, we use C Protocol Buffers Language Parser which generated by protobuf_lang_parser.lemon and protobuf_lang_scanner.l.
19  * Because wireshark is mainly implemented in plain ANSI C but the offical protobuf library is implemented in C++ language.
20  *
21  * One day, if C++ library is allowd, we can create a protobuf-helper.cpp file, that invoking offical protobuf C++ library directly,
22  * to replace protobuf-helper.c. The packet-protobuf.c can keep unchanged.
23  */
24 
25 #ifndef __PROTOBUF_HELPER_H__
26 #define __PROTOBUF_HELPER_H__
27 
28 #include <epan/value_string.h>
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif /* __cplusplus */
33 
34 /* Protobuf field type. Must be kept in sync with FieldType of protobuf wire_format_lite.h */
35 #define protobuf_field_type_VALUE_STRING_LIST(XXX)    \
36     XXX(PROTOBUF_TYPE_NONE, 0, "") \
37     XXX(PROTOBUF_TYPE_DOUBLE, 1, "double")  \
38     XXX(PROTOBUF_TYPE_FLOAT, 2, "float")   \
39     XXX(PROTOBUF_TYPE_INT64, 3, "int64") \
40     XXX(PROTOBUF_TYPE_UINT64, 4, "uint64") \
41     XXX(PROTOBUF_TYPE_INT32, 5, "int32") \
42     XXX(PROTOBUF_TYPE_FIXED64, 6, "fixed64") \
43     XXX(PROTOBUF_TYPE_FIXED32, 7, "fixed32")  \
44     XXX(PROTOBUF_TYPE_BOOL, 8, "bool")  \
45     XXX(PROTOBUF_TYPE_STRING, 9, "string")  \
46     XXX(PROTOBUF_TYPE_GROUP, 10, "group")  \
47     XXX(PROTOBUF_TYPE_MESSAGE, 11, "message")  \
48     XXX(PROTOBUF_TYPE_BYTES, 12, "bytes")  \
49     XXX(PROTOBUF_TYPE_UINT32, 13, "uint32")  \
50     XXX(PROTOBUF_TYPE_ENUM, 14, "enum")  \
51     XXX(PROTOBUF_TYPE_SFIXED32, 15, "sfixed32")  \
52     XXX(PROTOBUF_TYPE_SFIXED64, 16, "sfixed64")  \
53     XXX(PROTOBUF_TYPE_SINT32, 17, "sint32")  \
54     XXX(PROTOBUF_TYPE_SINT64, 18, "sint64")
55 
56 #define PROTOBUF_MAX_FIELD_TYPE 18
57 
58 VALUE_STRING_ENUM(protobuf_field_type);
59 VALUE_STRING_ARRAY_GLOBAL_DCL(protobuf_field_type);
60 
61 /* like google::protobuf::DescriptorPool of protobuf cpp library */
62 typedef struct PbwDescriptorPool PbwDescriptorPool;
63 /* like google::protobuf::MethodDescriptor of protobuf cpp library */
64 typedef struct PbwMethodDescriptor PbwMethodDescriptor;
65 /* like google::protobuf::Descriptor of protobuf cpp library */
66 typedef struct PbwDescriptor PbwDescriptor;
67 /* like google::protobuf::FieldDescriptor of protobuf cpp library */
68 typedef struct PbwFieldDescriptor PbwFieldDescriptor;
69 /* like google::protobuf::EnumDescriptor of protobuf cpp library */
70 typedef struct PbwEnumDescriptor PbwEnumDescriptor;
71 /* like google::protobuf::EnumValueDescriptor of protobuf cpp library */
72 typedef struct PbwEnumValueDescriptor PbwEnumValueDescriptor;
73 
74 typedef void(*pbw_report_error_cb_t)(const char *msg_format, ...);
75 
76 /**
77  Reinitialize PbwDescriptorPool according to proto files directories.
78  @param pool  The output DescriptorPool will be created. If *pool is not NULL, it will free it first.
79  @param directories  The root directories containing proto files. Must end with NULL element.
80  @param error_cb The error reporter callback function. */
81 void
82 pbw_reinit_DescriptorPool(PbwDescriptorPool** pool, const char** directories, pbw_report_error_cb_t error_cb);
83 
84 /* load a proto file, return 0 if successed */
85 int
86 pbw_load_proto_file(PbwDescriptorPool* pool, const char* filename);
87 
88 /* like DescriptorPool::FindMethodByName */
89 const PbwMethodDescriptor*
90 pbw_DescriptorPool_FindMethodByName(const PbwDescriptorPool* pool, const char* name);
91 
92 /* like MethodDescriptor::name() */
93 const char*
94 pbw_MethodDescriptor_name(const PbwMethodDescriptor* method);
95 
96 /* like MethodDescriptor::full_name() */
97 const char*
98 pbw_MethodDescriptor_full_name(const PbwMethodDescriptor* method);
99 
100 /* like MethodDescriptor::input_type() */
101 const PbwDescriptor*
102 pbw_MethodDescriptor_input_type(const PbwMethodDescriptor* method);
103 
104 /* like MethodDescriptor::output_type() */
105 const PbwDescriptor*
106 pbw_MethodDescriptor_output_type(const PbwMethodDescriptor* method);
107 
108 /* like DescriptorPool::FindMessageTypeByName() */
109 const PbwDescriptor*
110 pbw_DescriptorPool_FindMessageTypeByName(const PbwDescriptorPool* pool, const char* name);
111 
112 /* like Descriptor::name() */
113 const char*
114 pbw_Descriptor_name(const PbwDescriptor* message);
115 
116 /* like Descriptor::full_name() */
117 const char*
118 pbw_Descriptor_full_name(const PbwDescriptor* message);
119 
120 /* like Descriptor::field_count() */
121 int
122 pbw_Descriptor_field_count(const PbwDescriptor* message);
123 
124 /* like Descriptor::field() */
125 const PbwFieldDescriptor*
126 pbw_Descriptor_field(const PbwDescriptor* message, int field_index);
127 
128 /* like Descriptor::FindFieldByNumber() */
129 const PbwFieldDescriptor*
130 pbw_Descriptor_FindFieldByNumber(const PbwDescriptor* message, int number);
131 
132 /* like Descriptor::FindFieldByName() */
133 const PbwFieldDescriptor*
134 pbw_Descriptor_FindFieldByName(const PbwDescriptor* message, const char* name);
135 
136 /* like FieldDescriptor::full_name() */
137 const char*
138 pbw_FieldDescriptor_full_name(const PbwFieldDescriptor* field);
139 
140 /* like FieldDescriptor::name() */
141 const char*
142 pbw_FieldDescriptor_name(const PbwFieldDescriptor* field);
143 
144 /* like FieldDescriptor::number() */
145 int
146 pbw_FieldDescriptor_number(const PbwFieldDescriptor* field);
147 
148 /* like FieldDescriptor::type() */
149 int
150 pbw_FieldDescriptor_type(const PbwFieldDescriptor* field);
151 
152 /* like FieldDescriptor::is_repeated() */
153 int
154 pbw_FieldDescriptor_is_repeated(const PbwFieldDescriptor* field);
155 
156 /* like FieldDescriptor::is_packed() */
157 int
158 pbw_FieldDescriptor_is_packed(const PbwFieldDescriptor* field);
159 
160 /* like FieldDescriptor::typeName() */
161 const char*
162 pbw_FieldDescriptor_typeName(int field_type);
163 
164 /* like FieldDescriptor::message_type() */
165 const PbwDescriptor*
166 pbw_FieldDescriptor_message_type(const PbwFieldDescriptor* field);
167 
168 /* like FieldDescriptor::enum_type() */
169 const PbwEnumDescriptor*
170 pbw_FieldDescriptor_enum_type(const PbwFieldDescriptor* field);
171 
172 /* like FieldDescriptor::is_required() */
173 gboolean
174 pbw_FieldDescriptor_is_required(const PbwFieldDescriptor* field);
175 
176 /* like FieldDescriptor::has_default_value().
177  * Does this field have an explicitly-declared default value? */
178 gboolean
179 pbw_FieldDescriptor_has_default_value(const PbwFieldDescriptor* field);
180 
181 /* like FieldDescriptor::default_value_int32() */
182 gint32
183 pbw_FieldDescriptor_default_value_int32(const PbwFieldDescriptor* field);
184 
185 /* like FieldDescriptor::default_value_int64() */
186 gint64
187 pbw_FieldDescriptor_default_value_int64(const PbwFieldDescriptor* field);
188 
189 /* like FieldDescriptor::default_value_uint32() */
190 guint32
191 pbw_FieldDescriptor_default_value_uint32(const PbwFieldDescriptor* field);
192 
193 /* like FieldDescriptor::default_value_uint64() */
194 guint64
195 pbw_FieldDescriptor_default_value_uint64(const PbwFieldDescriptor* field);
196 
197 /* like FieldDescriptor::default_value_float() */
198 gfloat
199 pbw_FieldDescriptor_default_value_float(const PbwFieldDescriptor* field);
200 
201 /* like FieldDescriptor::default_value_double() */
202 gdouble
203 pbw_FieldDescriptor_default_value_double(const PbwFieldDescriptor* field);
204 
205 /* like FieldDescriptor::default_value_bool() */
206 gboolean
207 pbw_FieldDescriptor_default_value_bool(const PbwFieldDescriptor* field);
208 
209 /* like FieldDescriptor::default_value_string() */
210 const gchar*
211 pbw_FieldDescriptor_default_value_string(const PbwFieldDescriptor* field, int* size);
212 
213 /* like FieldDescriptor::default_value_enum() */
214 const PbwEnumValueDescriptor*
215 pbw_FieldDescriptor_default_value_enum(const PbwFieldDescriptor* field);
216 
217 /* like EnumDescriptor::name() */
218 const char*
219 pbw_EnumDescriptor_name(const PbwEnumDescriptor* anEnum);
220 
221 /* like EnumDescriptor::full_name() */
222 const char*
223 pbw_EnumDescriptor_full_name(const PbwEnumDescriptor* anEnum);
224 
225 /* like EnumDescriptor::value_count() */
226 int
227 pbw_EnumDescriptor_value_count(const PbwEnumDescriptor* anEnum);
228 
229 /* like EnumDescriptor::value() */
230 const PbwEnumValueDescriptor*
231 pbw_EnumDescriptor_value(const PbwEnumDescriptor* anEnum, int value_index);
232 
233 /* like EnumDescriptor::FindValueByNumber() */
234 const PbwEnumValueDescriptor*
235 pbw_EnumDescriptor_FindValueByNumber(const PbwEnumDescriptor* anEnum, int number);
236 
237 /* like EnumDescriptor::FindValueByName() */
238 const PbwEnumValueDescriptor*
239 pbw_EnumDescriptor_FindValueByName(const PbwEnumDescriptor* anEnum, const gchar* name);
240 
241 /* like EnumValueDescriptor::name() */
242 const char*
243 pbw_EnumValueDescriptor_name(const PbwEnumValueDescriptor* enumValue);
244 
245 /* like EnumValueDescriptor::full_name() */
246 const char*
247 pbw_EnumValueDescriptor_full_name(const PbwEnumValueDescriptor* enumValue);
248 
249 /* like EnumValueDescriptor::number() */
250 int
251 pbw_EnumValueDescriptor_number(const PbwEnumValueDescriptor* enumValue);
252 
253 /* visit all messages of this pool */
254 void
255 pbw_foreach_message(const PbwDescriptorPool* pool, void (*cb)(const PbwDescriptor* message, void* userdata), void* userdata);
256 
257 #ifdef __cplusplus
258 }
259 #endif /* __cplusplus */
260 
261 #endif /* __PROTOBUF_HELPER_H__ */
262 
263 /*
264  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
265  *
266  * Local variables:
267  * c-basic-offset: 4
268  * tab-width: 8
269  * indent-tabs-mode: nil
270  * End:
271  *
272  * vi: set shiftwidth=4 tabstop=8 expandtab:
273  * :indentSize=4:tabSize=8:noTabs=true:
274  */
275