#include #include #include #include #include #include #include // see #define TCP_ALL ((1 << (TCP_CLOSING + 1)) - 1) /** * report `netstat -nat` or `ss -an` data using netlink method with libnl library * author: Elan Ruusamäe * */ int main() { struct nl_handle *nl = nl_handle_alloc(); if (nl_connect(nl, NETLINK_INET_DIAG) < 0) { fprintf(stderr, "Couldn't connect to netlink: %s", nl_geterror()); return -1; } struct inet_diag_req req = { .idiag_states = TCP_ALL, }; struct nl_msg *nm = nlmsg_alloc_simple(TCPDIAG_GETSOCK, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST); nlmsg_append(nm, &req, sizeof(struct inet_diag_req), 0); if (nl_send_auto_complete(nl, nm) < 0) { fprintf(stderr, "nl_send(): %s", nl_geterror()); return -1; } nl_msg_dump(nm, stderr); nlmsg_free(nm); struct sockaddr_nl peer; unsigned char *buf = NULL; int len; while (1) { if ((len = nl_recv(nl, &peer, &buf, NULL)) <= 0) { fprintf(stderr, "nl_recv(): %s", nl_geterror()); return -1; } struct nlmsghdr *h = (struct nlmsghdr*)buf; while (nlmsg_ok(h, len)) { if (h->nlmsg_type == NLMSG_DONE) { return 0; } struct inet_diag_msg *r = nlmsg_data(h); struct nl_addr *src = nl_addr_build(r->idiag_family, r->id.idiag_src, r->idiag_family == AF_INET ? 4 : 6); struct nl_addr *dst = nl_addr_build(r->idiag_family, r->id.idiag_dst, r->idiag_family == AF_INET ? 4 : 6); char saddr[64], daddr[64]; nl_addr2str(src, saddr, sizeof(saddr)); nl_addr2str(dst, daddr, sizeof(daddr)); printf("%16s:%d\t%16s:%d\n", saddr, ntohs(r->id.idiag_sport), daddr, ntohs(r->id.idiag_dport)); h = nlmsg_next(h, &len); } free(buf); } nl_handle_destroy(nl); }