summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--proto_nlmsg.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/proto_nlmsg.c b/proto_nlmsg.c
index 9dc9f6b..5018adf 100644
--- a/proto_nlmsg.c
+++ b/proto_nlmsg.c
@@ -30,6 +30,15 @@
#define RTA_UINT32(attr) (*(uint32_t *)RTA_DATA(attr))
#define RTA_STR(attr) ((char *)RTA_DATA(attr))
+#ifndef NDA_RTA
+#define NDA_RTA(r) \
+ ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
+#endif
+
+#ifndef NDA_PAYLOAD
+#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
+#endif
+
#define attr_fmt(attr, fmt, ...) \
tprintf("\tA: "fmt, ##__VA_ARGS__); \
tprintf(", Len %lu\n", RTA_LEN(attr));
@@ -562,6 +571,93 @@ static void rtnl_print_route(struct nlmsghdr *hdr)
}
}
+static struct flag_name neigh_states[] = {
+ { "incomplete", NUD_INCOMPLETE },
+ { "reachable", NUD_REACHABLE },
+ { "stale", NUD_STALE },
+ { "delay", NUD_DELAY },
+ { "probe", NUD_PROBE },
+ { "failed", NUD_FAILED },
+ { "noarp", NUD_NOARP },
+ { "permanent", NUD_PERMANENT },
+ { "none", NUD_NONE },
+ { NULL, 0 },
+};
+
+static struct flag_name neigh_flags[] = {
+ { "use", NTF_USE },
+ { "self", NTF_SELF },
+ { "master", NTF_MASTER },
+ { "proxy", NTF_PROXY },
+#ifdef NTF_EXT_LEARNED
+ { "ext learned", NTF_EXT_LEARNED },
+#endif
+ { "router", NTF_ROUTER },
+ { NULL, 0 },
+};
+
+static void rtnl_print_neigh(struct nlmsghdr *hdr)
+{
+ struct ndmsg *ndm = NLMSG_DATA(hdr);
+ uint32_t attrs_len = NDA_PAYLOAD(hdr);
+ struct rtattr *attr = NDA_RTA(ndm);
+ struct nda_cacheinfo *ci;
+ int hz = get_user_hz();
+ char addr_str[256];
+ char hw_addr[30];
+ char states[256];
+ char flags[256];
+
+ tprintf(" [ Neigh Family %d (%s%s%s)", ndm->ndm_family,
+ colorize_start(bold),
+ addr_family2str(ndm->ndm_family),
+ colorize_end());
+ tprintf(", Link Index %d", ndm->ndm_ifindex);
+ tprintf(", State %d (%s%s%s)", ndm->ndm_state,
+ colorize_start(bold),
+ flags2str(neigh_states, ndm->ndm_state, states,
+ sizeof(states)),
+ colorize_end());
+ tprintf(", Flags %d (%s%s%s)", ndm->ndm_flags,
+ colorize_start(bold),
+ flags2str(neigh_flags, ndm->ndm_flags, flags,
+ sizeof(flags)),
+ colorize_end());
+ tprintf(", Type %d (%s%s%s)", ndm->ndm_type,
+ colorize_start(bold),
+ route_type2str(ndm->ndm_type),
+ colorize_end());
+ tprintf(" ]\n");
+
+ for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
+ switch (attr->rta_type) {
+ case NDA_DST:
+ attr_fmt(attr, "Address %s", addr2str(ndm->ndm_family,
+ RTA_DATA(attr), addr_str,
+ sizeof(addr_str)));
+ break;
+ case NDA_LLADDR:
+ attr_fmt(attr, "HW Address %s",
+ device_addr2str(RTA_DATA(attr),
+ RTA_LEN(attr), 0, hw_addr,
+ sizeof(hw_addr)));
+ break;
+ case NDA_PROBES:
+ attr_fmt(attr, "Probes %d", RTA_UINT32(attr));
+ break;
+ case NDA_CACHEINFO:
+ ci = RTA_DATA(attr);
+ tprintf("\tA: Cache (");
+ tprintf("confirmed(%ds)", ci->ndm_confirmed / hz);
+ tprintf(", used(%ds)", ci->ndm_used / hz);
+ tprintf(", updated(%ds)", ci->ndm_updated / hz);
+ tprintf(", refcnt(%d))", ci->ndm_refcnt);
+ tprintf(", Len %lu\n", RTA_LEN(attr));
+ break;
+ }
+ }
+}
+
static void rtnl_msg_print(struct nlmsghdr *hdr)
{
switch (hdr->nlmsg_type) {
@@ -581,6 +677,11 @@ static void rtnl_msg_print(struct nlmsghdr *hdr)
case RTM_GETROUTE:
rtnl_print_route(hdr);
break;
+ case RTM_NEWNEIGH:
+ case RTM_DELNEIGH:
+ case RTM_GETNEIGH:
+ rtnl_print_neigh(hdr);
+ break;
}
}