Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dfilter / dfilter-translator.c
blob7fa33e85b42acf3728a65117ac8f882b14b94baf
1 /*
2 * Wireshark - Network traffic analyzer
4 * Copyright 1998 Gerald Combs <gerald@wireshark.org>
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
9 // #include "config.h"
10 // #define WS_LOG_DOMAIN LOG_DOMAIN_DFILTER
12 #include <wireshark.h>
14 #include <epan/value_string.h>
16 #include "dfilter.h"
17 #include "dfilter-translator.h"
18 #include "sttype-field.h"
19 #include "sttype-op.h"
21 // name: DFTranslator
22 static GHashTable *registered_translators_;
24 static void cleanup_hash_table_key(gpointer data)
26 g_free(data);
29 bool register_dfilter_translator(const char *translator_name, DFTranslator translator)
31 if (!registered_translators_) {
32 registered_translators_ = g_hash_table_new_full(g_str_hash,
33 g_str_equal,
34 cleanup_hash_table_key,
35 NULL);
37 return g_hash_table_insert(registered_translators_, g_strdup(translator_name), translator);
40 void deregister_dfilter_translator(const char *translator_name)
42 if (!registered_translators_) {
43 return;
45 g_hash_table_remove(registered_translators_, translator_name);
48 char **get_dfilter_translator_list(void)
50 if (!registered_translators_) {
51 return NULL;
54 GList *key_l = g_list_sort(g_hash_table_get_keys(registered_translators_), (GCompareFunc)g_ascii_strcasecmp);
55 size_t key_count = g_list_length(key_l);
56 if (key_count < 1) {
57 g_list_free(key_l);
58 return NULL;
61 char **translator_list = g_malloc(sizeof(char *) * (key_count + 1));
62 size_t idx = 0;
63 for (GList *cur = g_list_first(key_l); cur; cur = g_list_next(cur), idx++) {
64 translator_list[idx] = (char *) cur->data;
66 translator_list[key_count] = NULL;
68 g_list_free(key_l);
69 return translator_list;
72 // XXX We should return an error message for failed translations.
73 const char *translate_dfilter(const char *translator_name, const char *dfilter)
75 if (!registered_translators_ || !translator_name) {
76 return NULL;
79 DFTranslator translator = (DFTranslator) g_hash_table_lookup(registered_translators_, translator_name);
80 if (!translator) {
81 return NULL;
84 stnode_t *root_node = dfilter_get_syntax_tree(dfilter);
85 if (!root_node) {
86 return NULL;
89 GString *translated_filter = g_string_new("");
90 bool res = translator(root_node, translated_filter);
91 stnode_free(root_node);
93 return g_string_free(translated_filter, !res);
97 // pcap filter (BPF) translation
98 // XXX - Fields are spread across all sorts of dissectors; not sure if there is a better place for this.
100 const char *
101 stnode_op_to_pcap_filter(stnode_op_t op) {
102 switch (op) {
103 case STNODE_OP_NOT: return "not";
104 case STNODE_OP_AND: return "&&";
105 case STNODE_OP_OR: return "||";
106 case STNODE_OP_ANY_EQ: return "";
107 // case STNODE_OP_ALL_NE: return "!=";
108 case STNODE_OP_GT: return "greater";
109 // case STNODE_OP_GE: return ">=";
110 case STNODE_OP_LT: return "less";
111 // case STNODE_OP_LE: return "<=";
112 // case STNODE_OP_CONTAINS: return "icontains";
113 case STNODE_OP_UNARY_MINUS: return "-";
114 case STNODE_OP_IN:
115 case STNODE_OP_NOT_IN:
116 default:
117 break;
119 return NULL;
122 // scanner.l in libpcap
123 static const string_string abbrev_to_pcap_filter[] = {
124 { "eth", "ether" },
125 { "eth.addr", "ether host" },
126 { "eth.dst", "ether dst" },
127 { "eth.src", "ether src" },
128 { "ppp", "ppp" },
129 // { "slip", "slip" },
130 { "fddi", "fddi" },
131 { "fddi.addr", "fddi host" },
132 { "fddi.dst", "fddi dst" },
133 { "fddi.src", "fddi src" },
134 { "tr", "tr" },
135 { "tr.addr", "tr host" },
136 { "tr.dst", "tr dst" },
137 { "tr.src", "tr src" },
138 { "wlan", "wlan" },
139 { "wlan.addr", "wlan host" },
140 { "wlan.ra", "wlan ra" },
141 { "wlan.ta", "wlan ta" },
142 // { "wlan.da", "wlan" },
143 // { "wlan", "wlan addr1" },
144 // { "wlan", "wlan addr2" },
145 // { "wlan", "wlan addr3" },
146 // { "wlan", "wlan addr4" },
147 { "arp", "arp" },
148 { "rarp", "rarp" },
149 { "ip", "ip" },
150 { "ip.addr", "ip host" },
151 { "ip.dst", "ip dst" },
152 { "ip.src", "ip src" },
153 { "ip.proto", "ip proto" },
154 { "sctp", "sctp" },
155 { "sctp.port", "sctp port" },
156 { "sctp.dstport", "sctp dst port" },
157 { "sctp.srcport", "sctp src port" },
158 { "tcp", "tcp" },
159 { "tcp.port", "tcp port" },
160 { "tcp.dstport", "tcp dst port" },
161 { "tcp.srcport", "tcp src port" },
162 { "udp", "udp" },
163 { "udp.port", "udp port" },
164 { "udp.dstport", "udp dst port" },
165 { "udp.srcport", "tcp src port" },
166 { "icmp", "icmp" },
167 { "igmp", "igmp" },
168 { "igrp", "igrp" },
169 { "pim", "pim" },
170 { "vrrp", "vrrp" },
171 { "carp", "carp" },
172 // { "", "radio" },
173 { "ipv6", "ip6" },
174 { "ipv6.addr", "ip6 host" },
175 { "ipv6.dst", "ip6 dst" },
176 { "ipv6.src", "ip6 src" },
177 { "icmpv6", "icmp6" },
178 { "ah", "ah" },
179 { "esp", "esp" },
180 // { "", "atalk" },
181 { "aarp", "aarp" },
182 // { "", "decnet" },
183 { "lat", "lat" },
184 // { "", "sca" },
185 // { "", "moprc" },
186 // { "", "mopdl" },
187 // { "", "iso" },
188 { "esis", "esis" },
189 { "isis", "isis" },
190 // { "", "l1" },
191 // { "", "l2" },
192 // { "", "iih" },
193 // { "", "lsp" },
194 // { "", "snp" },
195 // { "", "clnp" },
196 // { "", "psnp" },
197 { "dec_stp", "stp" },
198 { "ipx", "ipx" },
199 { "netbios", "netbeui" },
200 { "vlan", "vlan" },
201 { "mpls", "mpls" },
202 { "pppoed", "pppoed" },
203 { "pppoes", "pppoes" },
204 { "geneve", "geneve" },
205 { "lane", "lane" },
206 { "llc", "llc" },
207 // { "", "metac" },
208 // { "", "bcc" },
209 // { "", "oam" },
210 // { "", "oamf4" },
211 // { "", "oamf4ec" },
212 // { "", "oamf4sc" },
213 // { "", "sc" },
214 // { "", "ilmic" },
215 // { "", "vpi" },
216 // { "", "vci" },
217 // { "", "connectmsg" },
218 // { "", "metaconnect" },
219 { NULL, NULL }
222 // NOLINTNEXTLINE(misc-no-recursion)
223 bool pcap_visit_dfilter_node(stnode_t *node, stnode_op_t parent_bool_op, GString *pcap_filter)
225 stnode_t *left, *right;
227 if (stnode_type_id(node) == STTYPE_TEST) {
228 stnode_op_t op = STNODE_OP_UNINITIALIZED;
229 sttype_oper_get(node, &op, &left, &right);
231 const char *op_str = stnode_op_to_pcap_filter(op);
232 if (!op_str) {
233 return false;
236 if (left && right) {
237 if ((op == STNODE_OP_ANY_EQ || op == STNODE_OP_ALL_NE) && stnode_type_id(right) != STTYPE_FVALUE) {
238 // Don't translate things like "ip.src == ip.dst"
239 return false;
241 bool add_parens = (op == STNODE_OP_AND || op == STNODE_OP_OR) && op != parent_bool_op && parent_bool_op != STNODE_OP_UNINITIALIZED;
242 if (add_parens) {
243 g_string_append_c(pcap_filter, '(');
245 if (!pcap_visit_dfilter_node(left, op, pcap_filter)) {
246 return false;
248 if (strlen(op_str) > 0) {
249 g_string_append_c(pcap_filter, ' ');
251 g_string_append_printf(pcap_filter, "%s ", op_str);
252 if (!pcap_visit_dfilter_node(right, op, pcap_filter)) {
253 return false;
255 if (add_parens) {
256 g_string_append_c(pcap_filter, ')');
259 else if (left) {
260 op = op == STNODE_OP_NOT ? op : parent_bool_op;
261 if (pcap_filter->len > 0) {
262 g_string_append_c(pcap_filter, ' ');
264 g_string_append_printf(pcap_filter, "%s ", op_str);
265 if (!pcap_visit_dfilter_node(left, op, pcap_filter)) {
266 return false;
269 else if (right) {
270 ws_assert_not_reached();
273 else if (stnode_type_id(node) == STTYPE_SET) {
274 return false;
276 else if (stnode_type_id(node) == STTYPE_FUNCTION) {
277 return false;
279 else if (stnode_type_id(node) == STTYPE_FIELD) {
280 header_field_info *hfinfo = sttype_field_hfinfo(node);
281 const char *pcap_fragment = try_str_to_str(hfinfo->abbrev, abbrev_to_pcap_filter);
282 if (!pcap_fragment) {
283 return false;
285 g_string_append_printf(pcap_filter, "%s", pcap_fragment);
287 else if (stnode_type_id(node) == STTYPE_FVALUE) {
288 g_string_append_printf(pcap_filter, "%s", stnode_tostr(node, true));
290 else {
291 g_string_append_printf(pcap_filter, "%s", stnode_type_name(node));
294 return true;
297 bool dfilter_to_pcap_filter(stnode_t *root_node, GString *pcap_filter) {
298 return pcap_visit_dfilter_node(root_node, STNODE_OP_UNINITIALIZED, pcap_filter);
301 void dfilter_translator_init(void)
303 register_dfilter_translator("pcap filter", dfilter_to_pcap_filter);
306 void dfilter_translator_cleanup(void)
308 char **df_translators = get_dfilter_translator_list();
310 if (df_translators == NULL) {
311 return;
314 for (size_t idx = 0; df_translators[idx]; idx++) {
315 deregister_dfilter_translator(df_translators[idx]);
318 g_free(df_translators);
322 * Editor modelines - https://www.wireshark.org/tools/modelines.html
324 * Local variables:
325 * c-basic-offset: 4
326 * tab-width: 8
327 * indent-tabs-mode: nil
328 * End:
330 * vi: set shiftwidth=4 tabstop=8 expandtab:
331 * :indentSize=4:tabSize=8:noTabs=true: