Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-netlink-generic.c
blobf34a0736fa36b9734269ef111f502ef5fe114846
1 /* packet-netlink-generic.c
2 * Dissector for Linux Generic Netlink.
4 * Copyright (c) 2017, Peter Wu <peter@lekensteyn.nl>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 #include <epan/packet.h>
16 #include <wsutil/array.h>
17 #include "packet-netlink.h"
20 * Documentation:
21 * https://wiki.linuxfoundation.org/networking/generic_netlink_howto#message-format
22 * include/uapi/linux/netlink.h
23 * include/uapi/linux/genetlink.h
25 * For the meaning of fields in genlmsghdr, see genlmsg_put in
26 * net/netlink/genetlink.c, note that it has no user-specific message header
27 * (genl_ctrl.hdr_size==0).
30 void proto_register_netlink_generic(void);
31 void proto_reg_handoff_netlink_generic(void);
33 typedef struct {
34 /* Values parsed from the attributes (only valid in this packet). */
35 uint16_t family_id;
36 const uint8_t *family_name;
37 } genl_ctrl_info_t;
39 /* from include/uapi/linux/genetlink.h */
40 enum {
41 WS_CTRL_CMD_UNSPEC,
42 WS_CTRL_CMD_NEWFAMILY,
43 WS_CTRL_CMD_DELFAMILY,
44 WS_CTRL_CMD_GETFAMILY,
45 WS_CTRL_CMD_NEWOPS,
46 WS_CTRL_CMD_DELOPS,
47 WS_CTRL_CMD_GETOPS,
48 WS_CTRL_CMD_NEWMCAST_GRP,
49 WS_CTRL_CMD_DELMCAST_GRP,
50 WS_CTRL_CMD_GETMCAST_GRP,
51 WS_CTRL_CMD_GETPOLICY,
54 enum ws_genl_ctrl_attr {
55 WS_CTRL_ATTR_UNSPEC,
56 WS_CTRL_ATTR_FAMILY_ID,
57 WS_CTRL_ATTR_FAMILY_NAME,
58 WS_CTRL_ATTR_VERSION,
59 WS_CTRL_ATTR_HDRSIZE,
60 WS_CTRL_ATTR_MAXATTR,
61 WS_CTRL_ATTR_OPS,
62 WS_CTRL_ATTR_MCAST_GROUPS,
63 WS_CTRL_ATTR_POLICY,
64 WS_CTRL_ATTR_OP_POLICY,
65 WS_CTRL_ATTR_OP,
68 enum ws_genl_ctrl_op_attr {
69 WS_CTRL_ATTR_OP_UNSPEC,
70 WS_CTRL_ATTR_OP_ID,
71 WS_CTRL_ATTR_OP_FLAGS,
74 enum ws_genl_ctrl_group_attr {
75 WS_CTRL_ATTR_MCAST_GRP_UNSPEC,
76 WS_CTRL_ATTR_MCAST_GRP_NAME,
77 WS_CTRL_ATTR_MCAST_GRP_ID,
80 #define WS_GENL_ID_CTRL 0x10
81 #define GENL_CTRL_NAME "nlctrl"
83 static const value_string genl_ctrl_cmds[] = {
84 { WS_CTRL_CMD_UNSPEC, "CTRL_CMD_UNSPEC" },
85 { WS_CTRL_CMD_NEWFAMILY, "CTRL_CMD_NEWFAMILY" },
86 { WS_CTRL_CMD_DELFAMILY, "CTRL_CMD_DELFAMILY" },
87 { WS_CTRL_CMD_GETFAMILY, "CTRL_CMD_GETFAMILY" },
88 { WS_CTRL_CMD_NEWOPS, "CTRL_CMD_NEWOPS" },
89 { WS_CTRL_CMD_DELOPS, "CTRL_CMD_DELOPS" },
90 { WS_CTRL_CMD_GETOPS, "CTRL_CMD_GETOPS" },
91 { WS_CTRL_CMD_NEWMCAST_GRP, "CTRL_CMD_NEWMCAST_GRP" },
92 { WS_CTRL_CMD_DELMCAST_GRP, "CTRL_CMD_DELMCAST_GRP" },
93 { WS_CTRL_CMD_GETMCAST_GRP, "CTRL_CMD_GETMCAST_GRP" },
94 { WS_CTRL_CMD_GETPOLICY, "CTRL_CMD_GETPOLICY" },
95 { 0, NULL }
98 static const value_string genl_ctrl_attr_vals[] = {
99 { WS_CTRL_ATTR_UNSPEC, "CTRL_ATTR_UNSPEC" },
100 { WS_CTRL_ATTR_FAMILY_ID, "CTRL_ATTR_FAMILY_ID" },
101 { WS_CTRL_ATTR_FAMILY_NAME, "CTRL_ATTR_FAMILY_NAME" },
102 { WS_CTRL_ATTR_VERSION, "CTRL_ATTR_VERSION" },
103 { WS_CTRL_ATTR_HDRSIZE, "CTRL_ATTR_HDRSIZE" },
104 { WS_CTRL_ATTR_MAXATTR, "CTRL_ATTR_MAXATTR" },
105 { WS_CTRL_ATTR_OPS, "CTRL_ATTR_OPS" },
106 { WS_CTRL_ATTR_MCAST_GROUPS, "CTRL_ATTR_MCAST_GROUPS" },
107 { WS_CTRL_ATTR_POLICY, "CTRL_ATTR_POLICY" },
108 { WS_CTRL_ATTR_OP_POLICY, "CTRL_ATTR_OP_POLICY" },
109 { WS_CTRL_ATTR_OP, "CTRL_ATTR_OP" },
110 { 0, NULL }
113 static const value_string genl_ctrl_op_attr_vals[] = {
114 { WS_CTRL_ATTR_OP_UNSPEC, "CTRL_ATTR_OP_UNSPEC" },
115 { WS_CTRL_ATTR_OP_ID, "CTRL_ATTR_OP_ID" },
116 { WS_CTRL_ATTR_OP_FLAGS, "CTRL_ATTR_OP_FLAGS" },
117 { 0, NULL }
120 static const value_string genl_ctrl_group_attr_vals[] = {
121 { WS_CTRL_ATTR_MCAST_GRP_UNSPEC, "CTRL_ATTR_MCAST_GRP_UNSPEC" },
122 { WS_CTRL_ATTR_MCAST_GRP_NAME, "CTRL_ATTR_MCAST_GRP_NAME" },
123 { WS_CTRL_ATTR_MCAST_GRP_ID, "CTRL_ATTR_MCAST_GRP_ID" },
124 { 0, NULL }
127 static dissector_handle_t netlink_generic;
128 static dissector_handle_t netlink_generic_ctrl;
129 static dissector_table_t genl_dissector_table;
131 static int proto_netlink_generic;
133 static int hf_genl_cmd;
134 static int hf_genl_ctrl_attr;
135 static int hf_genl_ctrl_cmd;
136 static int hf_genl_ctrl_family_id;
137 static int hf_genl_ctrl_family_name;
138 static int hf_genl_ctrl_group_id;
139 static int hf_genl_ctrl_group_name;
140 static int hf_genl_ctrl_groups_attr;
141 static int hf_genl_ctrl_hdrsize;
142 static int hf_genl_ctrl_maxattr;
143 static int hf_genl_ctrl_op_flags;
144 static int hf_genl_ctrl_op_flags_admin_perm;
145 static int hf_genl_ctrl_op_flags_cmd_cap_do;
146 static int hf_genl_ctrl_op_flags_cmd_cap_dump;
147 static int hf_genl_ctrl_op_flags_cmd_cap_haspol;
148 static int hf_genl_ctrl_op_flags_uns_admin_perm;
149 static int hf_genl_ctrl_op_id;
150 static int hf_genl_ctrl_ops_attr;
151 static int hf_genl_ctrl_version;
152 static int hf_genl_family_id;
153 static int hf_genl_reserved;
154 static int hf_genl_version;
156 static int ett_netlink_generic;
157 static int ett_genl_ctrl_attr;
158 static int ett_genl_ctrl_ops;
159 static int ett_genl_ctrl_ops_attr;
160 static int ett_genl_ctrl_op_flags;
161 static int ett_genl_ctrl_groups;
162 static int ett_genl_ctrl_groups_attr;
163 static int ett_genl_nested_attr;
166 * Maps family IDs (integers) to family names (strings) within a capture file.
168 static wmem_map_t *genl_family_map;
170 static int * const genl_ctrl_op_flags_fields[] = {
171 &hf_genl_ctrl_op_flags_admin_perm,
172 &hf_genl_ctrl_op_flags_cmd_cap_do,
173 &hf_genl_ctrl_op_flags_cmd_cap_dump,
174 &hf_genl_ctrl_op_flags_cmd_cap_haspol,
175 &hf_genl_ctrl_op_flags_uns_admin_perm,
176 NULL
179 static int
180 dissect_genl_ctrl_ops_attrs(tvbuff_t *tvb, void *data _U_, struct packet_netlink_data *nl_data, proto_tree *tree, int nla_type, int offset, int len)
182 enum ws_genl_ctrl_op_attr type = (enum ws_genl_ctrl_op_attr) nla_type;
183 proto_tree *ptree = proto_tree_get_parent_tree(tree);
184 uint32_t value;
186 switch (type) {
187 case WS_CTRL_ATTR_OP_UNSPEC:
188 break;
189 case WS_CTRL_ATTR_OP_ID:
190 if (len == 4) {
191 proto_tree_add_item_ret_uint(tree, hf_genl_ctrl_op_id, tvb, offset, 4, nl_data->encoding, &value);
192 proto_item_append_text(tree, ": %u", value);
193 proto_item_append_text(ptree, ", id=%u", value);
194 offset += 4;
196 break;
197 case WS_CTRL_ATTR_OP_FLAGS:
198 if (len == 4) {
199 uint64_t op_flags;
200 /* XXX it would be nice if the flag names are appended to the tree */
201 proto_tree_add_bitmask_with_flags_ret_uint64(tree, tvb, offset, hf_genl_ctrl_op_flags,
202 ett_genl_ctrl_op_flags, genl_ctrl_op_flags_fields, nl_data->encoding, BMT_NO_FALSE, &op_flags);
203 proto_item_append_text(tree, ": 0x%08x", (uint32_t)op_flags);
204 proto_item_append_text(ptree, ", flags=0x%08x", (uint32_t)op_flags);
205 offset += 4;
207 break;
210 return offset;
213 static int
214 dissect_genl_ctrl_groups_attrs(tvbuff_t *tvb, void *data _U_, struct packet_netlink_data *nl_data, proto_tree *tree, int nla_type, int offset, int len)
216 enum ws_genl_ctrl_group_attr type = (enum ws_genl_ctrl_group_attr) nla_type;
217 proto_tree *ptree = proto_tree_get_parent_tree(tree);
218 uint32_t value;
219 const uint8_t *strval;
221 switch (type) {
222 case WS_CTRL_ATTR_MCAST_GRP_UNSPEC:
223 break;
224 case WS_CTRL_ATTR_MCAST_GRP_NAME:
225 proto_tree_add_item_ret_string(tree, hf_genl_ctrl_group_name, tvb, offset, len, ENC_ASCII, wmem_packet_scope(), &strval);
226 proto_item_append_text(tree, ": %s", strval);
227 proto_item_append_text(ptree, ", name=%s", strval);
228 offset += len;
229 break;
230 case WS_CTRL_ATTR_MCAST_GRP_ID:
231 if (len == 4) {
232 proto_tree_add_item_ret_uint(tree, hf_genl_ctrl_group_id, tvb, offset, 4, nl_data->encoding, &value);
233 proto_item_append_text(tree, ": %u", value);
234 proto_item_append_text(ptree, ", id=%u", value);
235 offset += 4;
237 break;
240 return offset;
243 static int
244 dissect_genl_ctrl_attrs(tvbuff_t *tvb, void *data, struct packet_netlink_data *nl_data, proto_tree *tree, int nla_type, int offset, int len)
246 enum ws_genl_ctrl_attr type = (enum ws_genl_ctrl_attr) nla_type;
247 genl_ctrl_info_t *info = (genl_ctrl_info_t *) data;
248 uint32_t value;
250 switch (type) {
251 case WS_CTRL_CMD_UNSPEC:
252 break;
253 case WS_CTRL_ATTR_FAMILY_ID:
254 if (len == 2) {
255 proto_tree_add_item_ret_uint(tree, hf_genl_ctrl_family_id, tvb, offset, 2, nl_data->encoding, &value);
256 proto_item_append_text(tree, ": %#x", value);
257 info->family_id = value;
258 offset += 2;
260 break;
261 case WS_CTRL_ATTR_FAMILY_NAME:
262 proto_tree_add_item_ret_string(tree, hf_genl_ctrl_family_name, tvb, offset, len, ENC_ASCII, wmem_packet_scope(), &info->family_name);
263 proto_item_append_text(tree, ": %s", info->family_name);
264 offset += len;
265 break;
266 case WS_CTRL_ATTR_VERSION:
267 if (len == 4) {
268 proto_tree_add_item_ret_uint(tree, hf_genl_ctrl_version, tvb, offset, 4, nl_data->encoding, &value);
269 proto_item_append_text(tree, ": %u", value);
270 offset += 4;
272 break;
273 case WS_CTRL_ATTR_HDRSIZE:
274 if (len == 4) {
275 proto_tree_add_item_ret_uint(tree, hf_genl_ctrl_hdrsize, tvb, offset, 4, nl_data->encoding, &value);
276 proto_item_append_text(tree, ": %u", value);
277 offset += 4;
279 break;
280 case WS_CTRL_ATTR_MAXATTR:
281 if (len == 4) {
282 proto_tree_add_item_ret_uint(tree, hf_genl_ctrl_maxattr, tvb, offset, 4, nl_data->encoding, &value);
283 proto_item_append_text(tree, ": %u", value);
284 offset += 4;
286 break;
287 case WS_CTRL_ATTR_OPS:
288 offset = dissect_netlink_attributes_array(tvb, hf_genl_ctrl_ops_attr, ett_genl_ctrl_ops, ett_genl_ctrl_ops_attr, info, nl_data, tree, offset, len, dissect_genl_ctrl_ops_attrs);
289 break;
290 case WS_CTRL_ATTR_MCAST_GROUPS:
291 offset = dissect_netlink_attributes_array(tvb, hf_genl_ctrl_groups_attr, ett_genl_ctrl_groups, ett_genl_ctrl_groups_attr, info, nl_data, tree, offset, len, dissect_genl_ctrl_groups_attrs);
292 break;
293 case WS_CTRL_ATTR_POLICY:
294 case WS_CTRL_ATTR_OP_POLICY:
295 case WS_CTRL_ATTR_OP:
296 break;
299 return offset;
302 static int
303 dissect_genl_ctrl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree _U_, void *data)
305 genl_info_t *genl_info = (genl_info_t *) data;
306 genl_ctrl_info_t info;
307 int offset;
309 if (!genl_info) {
310 return 0;
313 info.family_id = 0;
314 info.family_name = NULL;
316 offset = dissect_genl_header(tvb, genl_info, genl_info->nl_data, hf_genl_ctrl_cmd);
318 /* Return if command has no payload */
319 if (!tvb_reported_length_remaining(tvb, offset))
320 return offset;
322 dissect_netlink_attributes_to_end(tvb, hf_genl_ctrl_attr, ett_genl_ctrl_attr, &info, genl_info->nl_data, genl_info->genl_tree, offset, dissect_genl_ctrl_attrs);
325 * Remember association of dynamic ID with the family name such that
326 * future packets can be linked to a protocol.
327 * Do not allow overwriting our control protocol.
329 if (info.family_id && info.family_id != WS_GENL_ID_CTRL && info.family_name) {
330 wmem_map_insert(genl_family_map, GUINT_TO_POINTER(info.family_id), wmem_strdup(wmem_file_scope(), info.family_name));
333 return tvb_captured_length(tvb);
336 int dissect_genl_header(tvbuff_t *tvb, genl_info_t *genl_info, struct packet_netlink_data *nl_data, int hf_cmd)
338 int offset = 0;
340 if (hf_cmd <= 0) {
341 hf_cmd = hf_genl_cmd;
343 proto_tree_add_item(genl_info->genl_tree, hf_cmd, tvb, offset, 1, ENC_NA);
344 offset++;
345 /* XXX Family dissectors may want to know this */
346 proto_tree_add_item(genl_info->genl_tree, hf_genl_version, tvb, offset, 1, ENC_NA);
347 offset++;
348 proto_tree_add_item(genl_info->genl_tree, hf_genl_reserved, tvb, offset, 2, nl_data->encoding);
349 offset += 2;
350 return offset;
353 static int
354 dissect_netlink_generic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
356 struct packet_netlink_data *nl_data = (struct packet_netlink_data *) data;
357 genl_info_t info;
358 proto_tree *nlmsg_tree;
359 proto_item *pi, *pi_type;
360 const char *family_name;
361 tvbuff_t *next_tvb;
362 int offset = 0;
364 DISSECTOR_ASSERT(nl_data && nl_data->magic == PACKET_NETLINK_MAGIC);
366 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Netlink generic");
367 col_clear(pinfo->cinfo, COL_INFO);
369 pi = proto_tree_add_item(tree, proto_netlink_generic, tvb, 0, -1, ENC_NA);
370 nlmsg_tree = proto_item_add_subtree(pi, ett_netlink_generic);
372 /* Netlink message header (nlmsghdr) */
373 offset = dissect_netlink_header(tvb, nlmsg_tree, offset, nl_data->encoding, hf_genl_family_id, &pi_type);
374 family_name = (const char *)wmem_map_lookup(genl_family_map, GUINT_TO_POINTER(nl_data->type));
375 proto_item_append_text(pi_type, " (%s)", family_name ? family_name : "Unknown");
377 /* Populate info from Generic Netlink message header (genlmsghdr) */
378 info.nl_data = nl_data;
379 info.genl_tree = nlmsg_tree;
380 info.cmd = tvb_get_uint8(tvb, offset);
382 /* Optional user-specific message header and optional message payload. */
383 next_tvb = tvb_new_subset_remaining(tvb, offset);
384 if (family_name) {
385 int ret;
386 /* Invoke subdissector with genlmsghdr present. */
387 ret = dissector_try_string_with_data(genl_dissector_table, family_name, next_tvb, pinfo, tree, true, &info);
388 if (ret) {
389 return ret;
393 /* No subdissector added the genl header, do it now. */
394 offset = dissect_genl_header(next_tvb, &info, nl_data, -1);
395 if (tvb_reported_length_remaining(tvb, offset)) {
396 next_tvb = tvb_new_subset_remaining(tvb, offset);
397 call_data_dissector(next_tvb, pinfo, tree);
400 return offset;
403 static void
404 genl_init(void)
406 /* Add fixed family entry (0x10 maps to "nlctrl"). */
407 wmem_map_insert(genl_family_map, GUINT_TO_POINTER(WS_GENL_ID_CTRL), GENL_CTRL_NAME);
410 void
411 proto_register_netlink_generic(void)
413 static hf_register_info hf[] = {
414 { &hf_genl_ctrl_op_id,
415 { "Operation ID", "genl.ctrl.op_id",
416 FT_UINT32, BASE_DEC, NULL, 0x00,
417 NULL, HFILL }
419 { &hf_genl_ctrl_op_flags,
420 { "Operation Flags", "genl.ctrl.op_flags",
421 FT_UINT32, BASE_HEX, NULL, 0x00,
422 NULL, HFILL }
424 { &hf_genl_ctrl_op_flags_admin_perm,
425 { "GENL_ADMIN_PERM", "genl.ctrl.op_flags.admin_perm",
426 FT_BOOLEAN, 32, NULL, 0x00000001,
427 NULL, HFILL }
429 { &hf_genl_ctrl_op_flags_cmd_cap_do,
430 { "GENL_CMD_CAP_DO", "genl.ctrl.op_flags.cmd_cap_do",
431 FT_BOOLEAN, 32, NULL, 0x00000002,
432 NULL, HFILL }
434 { &hf_genl_ctrl_op_flags_cmd_cap_dump,
435 { "GENL_CMD_CAP_DUMP", "genl.ctrl.op_flags.cmd_cap_dump",
436 FT_BOOLEAN, 32, NULL, 0x00000004,
437 NULL, HFILL }
439 { &hf_genl_ctrl_op_flags_cmd_cap_haspol,
440 { "GENL_CMD_CAP_HASPOL", "genl.ctrl.op_flags.cmd_cap_haspol",
441 FT_BOOLEAN, 32, NULL, 0x00000008,
442 NULL, HFILL }
444 { &hf_genl_ctrl_op_flags_uns_admin_perm,
445 { "GENL_UNS_ADMIN_PERM", "genl.ctrl.op_flags.uns_admin_perm",
446 FT_BOOLEAN, 32, NULL, 0x00000010,
447 NULL, HFILL }
449 { &hf_genl_ctrl_group_name,
450 { "Group Name", "genl.ctrl.group_name",
451 FT_STRINGZ, BASE_NONE, NULL, 0x0,
452 NULL, HFILL }
454 { &hf_genl_ctrl_group_id,
455 { "Group ID", "genl.ctrl.group_id",
456 FT_UINT32, BASE_HEX, NULL, 0x0,
457 NULL, HFILL }
459 { &hf_genl_ctrl_family_id,
460 { "Family ID", "genl.ctrl.family_id",
461 FT_UINT16, BASE_HEX, NULL, 0x0,
462 NULL, HFILL }
464 { &hf_genl_ctrl_family_name,
465 { "Family Name", "genl.ctrl.family_name",
466 FT_STRINGZ, BASE_NONE, NULL, 0x0,
467 NULL, HFILL }
469 { &hf_genl_ctrl_version,
470 { "Version", "genl.ctrl.version",
471 FT_UINT32, BASE_DEC, NULL, 0x0,
472 "Family-specific version number", HFILL }
474 { &hf_genl_ctrl_hdrsize,
475 { "Header Size", "genl.ctrl.hdrsize",
476 FT_UINT32, BASE_DEC, NULL, 0x0,
477 "Size of family-specific header", HFILL }
479 { &hf_genl_ctrl_maxattr,
480 { "Maximum Attributes", "genl.ctrl.maxattr",
481 FT_UINT32, BASE_DEC, NULL, 0x0,
482 "Maximum number of attributes", HFILL }
484 { &hf_genl_ctrl_ops_attr,
485 { "Type", "genl.ctrl.ops_attr",
486 FT_UINT16, BASE_DEC, VALS(genl_ctrl_op_attr_vals), NLA_TYPE_MASK,
487 NULL, HFILL }
489 { &hf_genl_ctrl_groups_attr,
490 { "Type", "genl.ctrl.groups_attr",
491 FT_UINT16, BASE_DEC, VALS(genl_ctrl_group_attr_vals), NLA_TYPE_MASK,
492 NULL, HFILL }
494 { &hf_genl_ctrl_cmd,
495 { "Command", "genl.ctrl.cmd",
496 FT_UINT8, BASE_DEC, VALS(genl_ctrl_cmds), 0x0,
497 "Generic Netlink command", HFILL }
499 { &hf_genl_ctrl_attr,
500 { "Type", "genl.ctrl_attr",
501 FT_UINT16, BASE_DEC, VALS(genl_ctrl_attr_vals), NLA_TYPE_MASK,
502 NULL, HFILL }
504 { &hf_genl_family_id,
505 { "Family ID", "genl.family_id",
506 FT_UINT8, BASE_HEX, NULL, 0x00,
507 NULL, HFILL }
509 { &hf_genl_cmd,
510 { "Command", "genl.cmd",
511 FT_UINT8, BASE_DEC, NULL, 0x00,
512 "Generic Netlink command", HFILL }
514 { &hf_genl_version,
515 { "Family Version", "genl.version",
516 FT_UINT8, BASE_DEC, NULL, 0x00,
517 "Family-specific version", HFILL }
519 { &hf_genl_reserved,
520 { "Reserved", "genl.reserved",
521 FT_NONE, BASE_NONE, NULL, 0x00,
522 NULL, HFILL }
526 static int *ett[] = {
527 &ett_netlink_generic,
528 &ett_genl_ctrl_attr,
529 &ett_genl_ctrl_ops,
530 &ett_genl_ctrl_ops_attr,
531 &ett_genl_ctrl_op_flags,
532 &ett_genl_ctrl_groups,
533 &ett_genl_ctrl_groups_attr,
534 &ett_genl_nested_attr,
537 proto_netlink_generic = proto_register_protocol("Linux Generic Netlink protocol", "genl", "genl");
538 proto_register_field_array(proto_netlink_generic, hf, array_length(hf));
539 proto_register_subtree_array(ett, array_length(ett));
541 netlink_generic = register_dissector("genl", dissect_netlink_generic, proto_netlink_generic);
542 netlink_generic_ctrl = register_dissector("genl_ctrl", dissect_genl_ctrl, proto_netlink_generic);
543 genl_dissector_table = register_dissector_table(
544 "genl.family",
545 "Linux Generic Netlink family name",
546 proto_netlink_generic, FT_STRING,
547 STRING_CASE_SENSITIVE
550 genl_family_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal);
552 register_init_routine(genl_init);
555 void
556 proto_reg_handoff_netlink_generic(void)
558 dissector_add_string("genl.family", GENL_CTRL_NAME, netlink_generic_ctrl);
559 dissector_add_uint("netlink.protocol", WS_NETLINK_GENERIC, netlink_generic);
563 * Editor modelines - https://www.wireshark.org/tools/modelines.html
565 * Local variables:
566 * c-basic-offset: 8
567 * tab-width: 8
568 * indent-tabs-mode: t
569 * End:
571 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
572 * :indentSize=8:tabSize=8:noTabs=false: