diff options
author | Jakub Zawadzki <darkjames-ws@darkjames.pl> | 2013-12-08 19:30:33 +0000 |
---|---|---|
committer | Jakub Zawadzki <darkjames-ws@darkjames.pl> | 2013-12-08 19:30:33 +0000 |
commit | 64456261b9214f7b8bd520f74cbaee26d95b5f3e (patch) | |
tree | f1451d7171551cf4ae7c6a5aa4dfccbdc6237d67 /epan | |
parent | fab9e520551ed2b92d85a7676ed67caf64f41f6b (diff) |
Improve netlink dissection:
- add standard message types
- add dissection for WS_RTM_*NEIGH
- add BASE_CUSTOM functions to print bitfields
svn path=/trunk/; revision=53864
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-netlink-route.c | 251 | ||||
-rw-r--r-- | epan/dissectors/packet-netlink.c | 13 | ||||
-rw-r--r-- | epan/dissectors/packet-netlink.h | 7 |
3 files changed, 219 insertions, 52 deletions
diff --git a/epan/dissectors/packet-netlink-route.c b/epan/dissectors/packet-netlink-route.c index d073809ce2..7d2ac45d21 100644 --- a/epan/dissectors/packet-netlink-route.c +++ b/epan/dissectors/packet-netlink-route.c @@ -188,10 +188,10 @@ enum { /* values for rtmsg.rtm_scope from <linux/rtnetlink.h> */ enum { WS_RT_SCOPE_UNIVERSE = 0, -/* user defined */ - WS_RT_SCOPE_SITE = 200, - WS_RT_SCOPE_LINK = 253, - WS_RT_SCOPE_HOST = 254, +/* ... user defined (/etc/iproute2/rt_scopes) ... */ + WS_RT_SCOPE_SITE = 200, + WS_RT_SCOPE_LINK = 253, + WS_RT_SCOPE_HOST = 254, WS_RT_SCOPE_NOWHERE = 255 }; @@ -234,6 +234,31 @@ enum { WS_IFF_ECHO = 0x40000, }; +/* values for ifaddrmsg.ifa_flags <linux/if_addr.h> */ +enum { + WS_IFA_F_SECONDARY = 0x01, + WS_IFA_F_NODAD = 0x02, + WS_IFA_F_OPTIMISTIC = 0x04, + WS_IFA_F_DADFAILED = 0x08, + WS_IFA_F_HOMEADDRESS = 0x10, + WS_IFA_F_DEPRECATED = 0x20, + WS_IFA_F_TENTATIVE = 0x40, + WS_IFA_F_PERMANENT = 0x80 +}; + +/* values for ndmsg.ndm_state <linux/neighbour.h> */ +enum { + WS_NUD_INCOMPLETE = 0x01, + WS_NUD_REACHABLE = 0x02, + WS_NUD_STALE = 0x04, + WS_NUD_DELAY = 0x08, + WS_NUD_PROBE = 0x10, + WS_NUD_FAILED = 0x20, +/* Dummy states */ + WS_NUD_NOARP = 0x40, + WS_NUD_PERMANENT = 0x80 +}; + static dissector_handle_t netlink_route_handle; static header_field_info *hfi_netlink_route = NULL; @@ -287,6 +312,33 @@ static gint ett_netlink_route_if_flags = -1; typedef int netlink_route_attributes_cb_t(tvbuff_t *, struct netlink_route_info *, proto_tree *, int rta_type, int offset, int len); +static void +_fill_label_value_string_bitmask(char *label, guint32 value, const value_string *vals) +{ + char tmp[16]; + + label[0] = '\0'; + + while (vals->strptr) { + if (value & vals->value) { + value &= ~(vals->value); + if (label[0]) + g_strlcat(label, ", ", ITEM_LABEL_LENGTH); + + g_strlcat(label, vals->strptr, ITEM_LABEL_LENGTH); + } + + vals++; + } + + if (value) { + if (label[0]) + g_strlcat(label, ", ", ITEM_LABEL_LENGTH); + g_snprintf(tmp, sizeof(tmp), "0x%x", value); + g_strlcat(label, tmp, ITEM_LABEL_LENGTH); + } +} + static int dissect_netlink_route_attributes(tvbuff_t *tvb, header_field_info *hfi_type, struct netlink_route_info *info, proto_tree *tree, int offset, netlink_route_attributes_cb_t cb) { @@ -348,9 +400,43 @@ static header_field_info hfi_netlink_route_ifi_index NETLINK_ROUTE_HFI_INIT = { "Interface index", "netlink-route.ifi_index", FT_INT32, BASE_DEC, NULL, 0x00, NULL, HFILL }; +static void +hfi_netlink_route_ifi_flags_label(char *label, guint32 value) +{ + static const value_string iff_vals[] = { + { WS_IFF_UP, "UP" }, + { WS_IFF_BROADCAST, "BROADCAST" }, + { WS_IFF_DEBUG, "DEBUG" }, + { WS_IFF_LOOPBACK, "LOOPBACK" }, + { WS_IFF_POINTOPOINT, "POINTOPOINT" }, + { WS_IFF_NOTRAILERS, "NOTRAILERS" }, + { WS_IFF_RUNNING, "RUNNING" }, + { WS_IFF_NOARP, "NOARP" }, + { WS_IFF_PROMISC, "PROMISC" }, + { WS_IFF_ALLMULTI, "ALLMULTI" }, + { WS_IFF_MASTER, "MASTER" }, + { WS_IFF_SLAVE, "SLAVE" }, + { WS_IFF_MULTICAST, "MULTICAST" }, + { WS_IFF_PORTSEL, "PORTSEL" }, + { WS_IFF_AUTOMEDIA, "AUTOMEDIA" }, + { WS_IFF_DYNAMIC, "DYNAMIC" }, + { WS_IFF_LOWER_UP, "LOWER_UP" }, + { WS_IFF_DORMANT, "DORMANT" }, + { WS_IFF_ECHO, "ECHO" }, + { 0x00, NULL } + }; + + char tmp[16]; + + _fill_label_value_string_bitmask(label, value, iff_vals); + + g_snprintf(tmp, sizeof(tmp), " (0x%.8x)", value); + g_strlcat(label, tmp, ITEM_LABEL_LENGTH); +} + static header_field_info hfi_netlink_route_ifi_flags NETLINK_ROUTE_HFI_INIT = - { "Device flags", "netlink-route.ifi_flags", FT_UINT32, BASE_HEX, - NULL, 0x00, NULL, HFILL }; + { "Device flags", "netlink-route.ifi_flags", FT_UINT32, BASE_CUSTOM, + &hfi_netlink_route_ifi_flags_label, 0x00, NULL, HFILL }; static const true_false_string hfi_netlink_route_ifi_flags_iff_up_tfs = { "Up", "Down" }; @@ -388,47 +474,6 @@ dissect_netlink_route_ifinfomsg(tvbuff_t *tvb, struct netlink_route_info *info, if_flags_tree = proto_item_add_subtree(ti, ett_netlink_route_if_flags); if (if_flags_tree) { - guint32 if_flags = tvb_get_letohl(tvb, offset); - - if (if_flags & WS_IFF_UP) - proto_item_append_text(ti, " UP"); - if (if_flags & WS_IFF_BROADCAST) - proto_item_append_text(ti, " BROADCAST"); - if (if_flags & WS_IFF_DEBUG) - proto_item_append_text(ti, " DEBUG"); - if (if_flags & WS_IFF_LOOPBACK) - proto_item_append_text(ti, " LOOPBACK"); - if (if_flags & WS_IFF_POINTOPOINT) - proto_item_append_text(ti, " POINTOPOINT"); - if (if_flags & WS_IFF_NOTRAILERS) - proto_item_append_text(ti, " NOTRAILERS"); - if (if_flags & WS_IFF_RUNNING) - proto_item_append_text(ti, " RUNNING"); - if (if_flags & WS_IFF_NOARP) - proto_item_append_text(ti, " NOARP"); - if (if_flags & WS_IFF_PROMISC) - proto_item_append_text(ti, " PROMISC"); - if (if_flags & WS_IFF_ALLMULTI) - proto_item_append_text(ti, " ALLMULTI"); - if (if_flags & WS_IFF_MASTER) - proto_item_append_text(ti, " MASTER"); - if (if_flags & WS_IFF_SLAVE) - proto_item_append_text(ti, " SLAVE"); - if (if_flags & WS_IFF_MULTICAST) - proto_item_append_text(ti, " MULTICAST"); - if (if_flags & WS_IFF_PORTSEL) - proto_item_append_text(ti, " PORTSEL"); - if (if_flags & WS_IFF_AUTOMEDIA) - proto_item_append_text(ti, " AUTOMEDIA"); - if (if_flags & WS_IFF_DYNAMIC) - proto_item_append_text(ti, " DYNAMIC"); - if (if_flags & WS_IFF_LOWER_UP) - proto_item_append_text(ti, " LOWER_UP"); - if (if_flags & WS_IFF_DORMANT) - proto_item_append_text(ti, " DORMANT"); - if (if_flags & WS_IFF_ECHO) - proto_item_append_text(ti, " ECHO"); - proto_tree_add_item(if_flags_tree, &hfi_netlink_route_ifi_flags_iff_up, tvb, offset, 4, info->encoding); proto_tree_add_item(if_flags_tree, &hfi_netlink_route_ifi_flags_iff_broadcast, tvb, offset, 4, info->encoding); /* XXX */ @@ -477,11 +522,13 @@ dissect_netlink_route_ifla_attrs(tvbuff_t *tvb, struct netlink_route_info *info, switch (type) { case WS_IFLA_IFNAME: + proto_item_append_text(tree, ": %s", tvb_get_string_enc(wmem_packet_scope(), tvb, offset, len, ENC_ASCII | ENC_NA)); proto_tree_add_item(tree, &hfi_netlink_route_ifla_ifname, tvb, offset, len, ENC_ASCII | ENC_NA); return 1; case WS_IFLA_MTU: if (len == 4) { + proto_item_append_text(tree, ": %u", tvb_get_letohl(tvb, offset)); proto_tree_add_item(tree, &hfi_netlink_route_ifla_mtu, tvb, offset, len, info->encoding); return 1; } @@ -501,9 +548,32 @@ static header_field_info hfi_netlink_route_ifa_prefixlen NETLINK_ROUTE_HFI_INIT { "Address prefixlength", "netlink-route.ifa_prefixlen", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }; +static void +hfi_netlink_route_ifa_flags_label(char *label, guint32 value) +{ + static const value_string iff_vals[] = { + { WS_IFA_F_SECONDARY, "secondary/temporary" }, + { WS_IFA_F_NODAD, "nodad" }, + { WS_IFA_F_OPTIMISTIC, "optimistic" }, + { WS_IFA_F_DADFAILED, "dadfailed" }, + { WS_IFA_F_HOMEADDRESS, "homeaddress" }, + { WS_IFA_F_DEPRECATED, "deprecated" }, + { WS_IFA_F_TENTATIVE, "tentative" }, + { WS_IFA_F_PERMANENT, "permanent" }, + { 0x00, NULL } + }; + + char tmp[16]; + + _fill_label_value_string_bitmask(label, value, iff_vals); + + g_snprintf(tmp, sizeof(tmp), " (0x%.8x)", value); + g_strlcat(label, tmp, ITEM_LABEL_LENGTH); +} + static header_field_info hfi_netlink_route_ifa_flags NETLINK_ROUTE_HFI_INIT = - { "Address flags", "netlink-route.ifa_flags", FT_UINT8, BASE_HEX, - NULL, 0x00, NULL, HFILL }; + { "Address flags", "netlink-route.ifa_flags", FT_UINT8, BASE_CUSTOM, + &hfi_netlink_route_ifa_flags_label, 0x00, NULL, HFILL }; static header_field_info hfi_netlink_route_ifa_scope NETLINK_ROUTE_HFI_INIT = { "Address scope", "netlink-route.ifa_scope", FT_UINT8, BASE_DEC, @@ -563,6 +633,7 @@ dissect_netlink_route_ifa_attrs(tvbuff_t *tvb, struct netlink_route_info *info _ switch (type) { case WS_IFA_LABEL: + proto_item_append_text(tree, ": %s", tvb_get_string_enc(wmem_packet_scope(), tvb, offset, len, ENC_ASCII | ENC_NA)); proto_tree_add_item(tree, &hfi_netlink_route_ifa_label, tvb, offset, len, ENC_ASCII | ENC_NA); return 1; @@ -718,6 +789,7 @@ dissect_netlink_route_route_attrs(tvbuff_t *tvb, struct netlink_route_info *info switch (type) { case WS_RTA_IIF: if (len == 4) { + proto_item_append_text(tree, ": %u", tvb_get_letohl(tvb, offset)); proto_tree_add_item(tree, &hfi_netlink_route_rta_iif, tvb, offset, 4, info->encoding); return 1; } @@ -725,6 +797,7 @@ dissect_netlink_route_route_attrs(tvbuff_t *tvb, struct netlink_route_info *info case WS_RTA_OIF: if (len == 4) { + proto_item_append_text(tree, ": %u", tvb_get_letohl(tvb, offset)); proto_tree_add_item(tree, &hfi_netlink_route_rta_oif, tvb, offset, 4, info->encoding); return 1; } @@ -735,6 +808,73 @@ dissect_netlink_route_route_attrs(tvbuff_t *tvb, struct netlink_route_info *info } } +static header_field_info hfi_netlink_route_nd_family NETLINK_ROUTE_HFI_INIT = + { "Family", "netlink-route.nd_family", FT_UINT8, BASE_DEC | BASE_EXT_STRING, + &linux_af_vals_ext, 0x00, NULL, HFILL }; + +static header_field_info hfi_netlink_route_nd_index NETLINK_ROUTE_HFI_INIT = + { "Interface index", "netlink-route.nd_index", FT_INT32, BASE_DEC, + NULL, 0x00, NULL, HFILL }; + +static void +hfi_netlink_route_nd_states_label(char *label, guint32 value) +{ + static const value_string flags_vals[] = { + { WS_NUD_INCOMPLETE, "INCOMPLETE" }, + { WS_NUD_REACHABLE, "REACHABLE" }, + { WS_NUD_STALE, "STALE" }, + { WS_NUD_DELAY, "DELAY" }, + { WS_NUD_PROBE, "PROBE" }, + { WS_NUD_FAILED, "FAILED" }, + { WS_NUD_NOARP, "NOARP" }, + { WS_NUD_PERMANENT, "PERMAMENT" }, + { 0x00, NULL } + }; + + char tmp[16]; + + _fill_label_value_string_bitmask(label, value, flags_vals); + + g_snprintf(tmp, sizeof(tmp), " (0x%.4x)", value); + g_strlcat(label, tmp, ITEM_LABEL_LENGTH); +} + +static header_field_info hfi_netlink_route_nd_state NETLINK_ROUTE_HFI_INIT = + { "State", "netlink-route.nd_state", FT_UINT16, BASE_CUSTOM, + &hfi_netlink_route_nd_states_label, 0x00, NULL, HFILL }; + +static header_field_info hfi_netlink_route_nd_flags NETLINK_ROUTE_HFI_INIT = + { "Flags", "netlink-route.nd_flags", FT_UINT8, BASE_HEX, + NULL, 0x00, NULL, HFILL }; + +static header_field_info hfi_netlink_route_nd_type NETLINK_ROUTE_HFI_INIT = + { "Type", "netlink-route.nd_type", FT_UINT8, BASE_HEX, + NULL, 0x00, NULL, HFILL }; + +static int +dissect_netlink_route_ndmsg(tvbuff_t *tvb, struct netlink_route_info *info, proto_tree *tree, int offset) +{ + proto_tree_add_item(tree, &hfi_netlink_route_nd_family, tvb, offset, 1, ENC_NA); + offset += 1; + + /* XXX, 3B padding */ + offset += 3; + + proto_tree_add_item(tree, &hfi_netlink_route_nd_index, tvb, offset, 4, info->encoding); + offset += 4; + + proto_tree_add_item(tree, &hfi_netlink_route_nd_state, tvb, offset, 2, info->encoding); + offset += 2; + + proto_tree_add_item(tree, &hfi_netlink_route_nd_flags, tvb, offset, 1, ENC_NA); + offset += 1; + + proto_tree_add_item(tree, &hfi_netlink_route_nd_type, tvb, offset, 1, ENC_NA); + offset += 1; + + return offset; +} + static int dissect_netlink_route(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *_data) { @@ -791,6 +931,12 @@ dissect_netlink_route(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void /* Optional attributes */ offset = dissect_netlink_route_attributes(tvb, &hfi_netlink_route_rta_attr_type, &info, tree, offset, dissect_netlink_route_route_attrs); break; + + case WS_RTM_NEWNEIGH: + case WS_RTM_DELNEIGH: + case WS_RTM_GETNEIGH: + offset = dissect_netlink_route_ndmsg(tvb, &info, tree, offset); + break; } return offset; @@ -840,6 +986,13 @@ proto_register_netlink_route(void) &hfi_netlink_route_rta_attr_type, &hfi_netlink_route_rta_iif, &hfi_netlink_route_rta_oif, + + /* Neighbor */ + &hfi_netlink_route_nd_family, + &hfi_netlink_route_nd_index, + &hfi_netlink_route_nd_state, + &hfi_netlink_route_nd_flags, + &hfi_netlink_route_nd_type, }; #endif diff --git a/epan/dissectors/packet-netlink.c b/epan/dissectors/packet-netlink.c index 51fe73cf67..5b11b4110c 100644 --- a/epan/dissectors/packet-netlink.c +++ b/epan/dissectors/packet-netlink.c @@ -40,7 +40,7 @@ */ #define SLL_HEADER_SIZE 16 /* total header length */ -static const value_string ltype_vals[] = { +static const value_string family_vals[] = { { WS_NETLINK_ROUTE, "Route" }, { WS_NETLINK_UNUSED, "Unused" }, { WS_NETLINK_USERSOCK, "user-mode" }, @@ -65,6 +65,13 @@ static const value_string ltype_vals[] = { { 0, NULL } }; +static const value_string type_vals[] = { + { WS_NLMSG_NOOP, "nothing" }, + { WS_NLMSG_ERROR, "error" }, + { WS_NLMSG_DONE, "end of a dump" }, + { WS_NLMSG_OVERRUN, "data lost" }, + { 0, NULL } +}; static dissector_handle_t netlink_handle; @@ -79,7 +86,7 @@ static header_field_info hfi_netlink_hatype NETLINK_HFI_INIT = /* Linux netlink protocol type */ static header_field_info hfi_netlink_family NETLINK_HFI_INIT = { "Family", "netlink.family", FT_UINT16, BASE_HEX, - VALS(ltype_vals), 0x00, NULL, HFILL }; + VALS(family_vals), 0x00, NULL, HFILL }; static header_field_info hfi_netlink_hdr_len NETLINK_HFI_INIT = @@ -88,7 +95,7 @@ static header_field_info hfi_netlink_hdr_len NETLINK_HFI_INIT = static header_field_info hfi_netlink_hdr_type NETLINK_HFI_INIT = { "Type", "netlink.hdr_type", FT_UINT16, BASE_HEX, - NULL, 0x00, NULL, HFILL }; + VALS(type_vals), 0x00, NULL, HFILL }; static header_field_info hfi_netlink_hdr_flags NETLINK_HFI_INIT = { "Flags", "netlink.hdr_flags", FT_UINT16, BASE_HEX, diff --git a/epan/dissectors/packet-netlink.h b/epan/dissectors/packet-netlink.h index 2708462413..fbe858db05 100644 --- a/epan/dissectors/packet-netlink.h +++ b/epan/dissectors/packet-netlink.h @@ -50,6 +50,13 @@ enum { WS_NETLINK_CRYPTO = 21 }; +enum { + WS_NLMSG_NOOP = 0x01, + WS_NLMSG_ERROR = 0x02, + WS_NLMSG_DONE = 0x03, + WS_NLMSG_OVERRUN = 0x04 +}; + #define PACKET_NETLINK_MAGIC 0x4A5ACCCE struct packet_netlink_data { |