12f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin#include "defs.h" 22f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin#include <netinet/in.h> 32f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin#include <sys/socket.h> 42f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin#include <arpa/inet.h> 52f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin#include <linux/netlink.h> 62f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin#include <linux/sock_diag.h> 72f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin#include <linux/inet_diag.h> 8120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO#include <linux/unix_diag.h> 9120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO#include <linux/rtnetlink.h> 10120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO 11d9f7e7a4392a5fb38b3c60825fedddb28f30572fDmitry V. Levin#if !defined NETLINK_SOCK_DIAG && defined NETLINK_INET_DIAG 12d9f7e7a4392a5fb38b3c60825fedddb28f30572fDmitry V. Levin# define NETLINK_SOCK_DIAG NETLINK_INET_DIAG 13d9f7e7a4392a5fb38b3c60825fedddb28f30572fDmitry V. Levin#endif 14d9f7e7a4392a5fb38b3c60825fedddb28f30572fDmitry V. Levin 15120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO#include <sys/un.h> 16120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO#ifndef UNIX_PATH_MAX 17120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO# define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) 0)->sun_path) 18120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO#endif 192f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 202f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levinstatic bool 21120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATOinet_send_query(const int fd, const int family, const int proto) 222f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin{ 23af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin struct sockaddr_nl nladdr = { 24af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin .nl_family = AF_NETLINK 25af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin }; 262f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin struct { 272f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin struct nlmsghdr nlh; 282f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin struct inet_diag_req_v2 idr; 29af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin } req = { 30af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin .nlh = { 31af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin .nlmsg_len = sizeof(req), 32af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin .nlmsg_type = SOCK_DIAG_BY_FAMILY, 33af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin .nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST 34af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin }, 35af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin .idr = { 36af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin .sdiag_family = family, 37af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin .sdiag_protocol = proto, 38af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin .idiag_states = -1 39af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin } 40af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin }; 412f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin struct iovec iov = { 422f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin .iov_base = &req, 432f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin .iov_len = sizeof(req) 442f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin }; 452f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin struct msghdr msg = { 462f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin .msg_name = (void*)&nladdr, 472f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin .msg_namelen = sizeof(nladdr), 482f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin .msg_iov = &iov, 492f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin .msg_iovlen = 1 502f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin }; 512f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 522f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin for (;;) { 532f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin if (sendmsg(fd, &msg, 0) < 0) { 542f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin if (errno == EINTR) 552f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin continue; 562f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin return false; 572f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin } 582f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin return true; 592f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin } 602f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin} 612f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 622f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levinstatic bool 63959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levininet_parse_response(const char *proto_name, const void *data, int data_len, 64959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin const unsigned long inode) 652f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin{ 66120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO const struct inet_diag_msg *diag_msg = data; 672f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin static const char zero_addr[sizeof(struct in6_addr)]; 682f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin socklen_t addr_size, text_size; 692f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 702f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin if (diag_msg->idiag_inode != inode) 712f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin return false; 722f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 732f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin switch(diag_msg->idiag_family) { 742f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin case AF_INET: 752f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin addr_size = sizeof(struct in_addr); 762f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin text_size = INET_ADDRSTRLEN; 772f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin break; 782f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin case AF_INET6: 792f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin addr_size = sizeof(struct in6_addr); 802f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin text_size = INET6_ADDRSTRLEN; 812f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin break; 822f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin default: 832f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin return false; 842f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin } 852f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 862f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin char src_buf[text_size]; 872f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 882f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin if (!inet_ntop(diag_msg->idiag_family, diag_msg->id.idiag_src, 892f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin src_buf, text_size)) 902f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin return false; 912f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 922f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin if (diag_msg->id.idiag_dport || 932f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin memcmp(zero_addr, diag_msg->id.idiag_dst, addr_size)) { 942f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin char dst_buf[text_size]; 952f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 962f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin if (!inet_ntop(diag_msg->idiag_family, diag_msg->id.idiag_dst, 972f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin dst_buf, text_size)) 982f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin return false; 992f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 100959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin tprintf("%s:[%s:%u->%s:%u]", 101959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin proto_name, 1022f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin src_buf, ntohs(diag_msg->id.idiag_sport), 1032f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin dst_buf, ntohs(diag_msg->id.idiag_dport)); 1042f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin } else { 105959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin tprintf("%s:[%s:%u]", proto_name, src_buf, 106959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin ntohs(diag_msg->id.idiag_sport)); 1072f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin } 1082f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 1092f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin return true; 1102f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin} 1112f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 1122f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levinstatic bool 113120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATOreceive_responses(const int fd, const unsigned long inode, 114959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin const char *proto_name, 115959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin bool (* parser) (const char *, const void *, int, const unsigned long)) 1162f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin{ 117301c65cbf0b9c999e24ff6b3518abe3dca63b229Dmitry V. Levin static long buf[8192 / sizeof(long)]; 118af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin struct sockaddr_nl nladdr = { 119af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin .nl_family = AF_NETLINK 120af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin }; 1212f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin struct iovec iov = { 1222f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin .iov_base = buf, 1232f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin .iov_len = sizeof(buf) 1242f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin }; 1252f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 1262f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin for (;;) { 1272f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin ssize_t ret; 1282f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin struct nlmsghdr *h; 1292f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin struct msghdr msg = { 1302f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin .msg_name = (void*)&nladdr, 1312f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin .msg_namelen = sizeof(nladdr), 1322f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin .msg_iov = &iov, 133af534b8d7a28ce6b2aaa6a0be1b5da20dbfe7b45Dmitry V. Levin .msg_iovlen = 1 1342f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin }; 1352f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 1362f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin ret = recvmsg(fd, &msg, 0); 1372f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin if (ret < 0) { 1382f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin if (errno == EINTR) 1392f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin continue; 1402f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin return false; 1412f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin } 1422f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin if (!ret) 1432f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin return false; 1442f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin for (h = (struct nlmsghdr*)buf; 1452f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin NLMSG_OK(h, ret); 1462f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin h = NLMSG_NEXT(h, ret)) { 1472f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin switch (h->nlmsg_type) { 1482f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin case NLMSG_DONE: 1492f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin case NLMSG_ERROR: 1502f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin return false; 1512f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin } 152959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin if (parser(proto_name, NLMSG_DATA(h), h->nlmsg_len, inode)) 1532f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin return true; 1542f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin } 1552f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin } 1562f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin} 1572f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 158f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATOstatic bool 159959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levininet_print(const int fd, const int family, const int protocol, 160959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin const unsigned long inode, const char *proto_name) 161f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATO{ 162120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO return inet_send_query(fd, family, protocol) 163959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin && receive_responses(fd, inode, proto_name, inet_parse_response); 164120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO} 165120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO 166120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATOstatic bool 167120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATOunix_send_query(const int fd, const unsigned long inode) 168120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO{ 169120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO struct sockaddr_nl nladdr = { 170120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .nl_family = AF_NETLINK 171120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO }; 172120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO struct { 173120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO struct nlmsghdr nlh; 174120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO struct unix_diag_req udr; 175120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO } req = { 176120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .nlh = { 177120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .nlmsg_len = sizeof(req), 178120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .nlmsg_type = SOCK_DIAG_BY_FAMILY, 179120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST 180120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO }, 181120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .udr = { 182120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .sdiag_family = AF_UNIX, 183120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .udiag_ino = inode, 184120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .udiag_states = -1, 185120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER 186120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO } 187120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO }; 188120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO struct iovec iov = { 189120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .iov_base = &req, 190120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .iov_len = sizeof(req) 191120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO }; 192120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO struct msghdr msg = { 193120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .msg_name = (void*)&nladdr, 194120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .msg_namelen = sizeof(nladdr), 195120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .msg_iov = &iov, 196120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO .msg_iovlen = 1 197120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO }; 198120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO 199120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO for (;;) { 200120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO if (sendmsg(fd, &msg, 0) < 0) { 201120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO if (errno == EINTR) 202120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO continue; 203120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO return false; 204120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO } 205120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO return true; 206120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO } 207120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO} 208120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO 209120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATOstatic bool 210959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levinunix_parse_response(const char *proto_name, const void *data, int data_len, 211959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin const unsigned long inode) 212120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO{ 213120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO const struct unix_diag_msg *diag_msg = data; 214120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO struct rtattr *attr; 215120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO int rta_len = data_len - NLMSG_LENGTH(sizeof(*diag_msg)); 216120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO uint32_t peer = 0; 217120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO size_t path_len = 0; 218120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO char path[UNIX_PATH_MAX + 1]; 219120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO 220120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO if (diag_msg->udiag_ino != inode) 221120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO return false; 222120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO if (diag_msg->udiag_family != AF_UNIX) 223120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO return false; 224120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO 225120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO for (attr = (struct rtattr *) (diag_msg + 1); 226120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO RTA_OK(attr, rta_len); 227120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO attr = RTA_NEXT(attr, rta_len)) { 228120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO switch (attr->rta_type) { 229120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO case UNIX_DIAG_NAME: 230120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO if (!path_len) { 231120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO path_len = RTA_PAYLOAD(attr); 232120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO if (path_len > UNIX_PATH_MAX) 233120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO path_len = UNIX_PATH_MAX; 234120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO memcpy(path, RTA_DATA(attr), path_len); 235120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO path[path_len] = '\0'; 236120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO } 237120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO break; 238120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO case UNIX_DIAG_PEER: 239120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO if (RTA_PAYLOAD(attr) >= 4) 240120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO peer = *(uint32_t *)RTA_DATA(attr); 241120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO break; 242120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO } 243120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO } 244120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO 245120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO /* 246120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO * print obtained information in the following format: 247120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO * "UNIX:[" SELF_INODE [ "->" PEER_INODE ][ "," SOCKET_FILE ] "]" 248120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO */ 249120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO if (peer || path_len) { 250959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin tprintf("%s:[%lu", proto_name, inode); 251120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO if (peer) 252120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO tprintf("->%u", peer); 253120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO if (path_len) { 254120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO if (path[0] == '\0') { 255513e96eb94841734274c0607aae2c9f212411eeeDmitry V. Levin tprints(",@"); 256513e96eb94841734274c0607aae2c9f212411eeeDmitry V. Levin print_quoted_string(path + 1, path_len, 257513e96eb94841734274c0607aae2c9f212411eeeDmitry V. Levin QUOTE_0_TERMINATED); 258120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO } else { 259513e96eb94841734274c0607aae2c9f212411eeeDmitry V. Levin tprints(","); 260513e96eb94841734274c0607aae2c9f212411eeeDmitry V. Levin print_quoted_string(path, path_len + 1, 261513e96eb94841734274c0607aae2c9f212411eeeDmitry V. Levin QUOTE_0_TERMINATED); 262120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO } 263120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO } 264120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO tprints("]"); 265120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO return true; 266120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO } 267120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO else 268120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO return false; 269120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO} 270120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO 271120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATOstatic bool 272120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATOunix_print(int fd, const unsigned long inode) 273120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO{ 274120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO return unix_send_query(fd, inode) 275959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin && receive_responses(fd, inode, "UNIX", unix_parse_response); 276f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATO} 277f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATO 2782f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin/* Given an inode number of a socket, print out the details 2792f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin * of the ip address and port. */ 2802f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levinbool 281f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATOprint_sockaddr_by_inode(const unsigned long inode, const char *proto_name) 2822f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin{ 2832f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin int fd; 284f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATO bool r = false; 2852f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 286120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG); 2872f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin if (fd < 0) 2882f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin return false; 2892f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin 290f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATO if (proto_name) { 291f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATO if (strcmp(proto_name, "TCP") == 0) 292959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin r = inet_print(fd, AF_INET, IPPROTO_TCP, inode, "TCP"); 293f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATO else if (strcmp(proto_name, "UDP") == 0) 294959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin r = inet_print(fd, AF_INET, IPPROTO_UDP, inode, "UDP"); 295f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATO else if (strcmp(proto_name, "TCPv6") == 0) 296959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin r = inet_print(fd, AF_INET6, IPPROTO_TCP, inode, "TCPv6"); 297f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATO else if (strcmp(proto_name, "UDPv6") == 0) 298959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin r = inet_print(fd, AF_INET6, IPPROTO_UDP, inode, "UDPv6"); 299120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO else if (strcmp(proto_name, "UNIX") == 0) 300120e5dbcac4fa6a8f642ffab06c5e206fca214d3Masatake YAMATO r = unix_print(fd, inode); 301f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATO } else { 302959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin const struct { 303959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin const int family; 304959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin const int protocol; 305959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin const char *name; 306959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin } protocols[] = { 307959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin { AF_INET, IPPROTO_TCP, "TCP" }, 308959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin { AF_INET, IPPROTO_UDP, "UDP" }, 309959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin { AF_INET6, IPPROTO_TCP, "TCPv6" }, 310959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin { AF_INET6, IPPROTO_UDP, "UDPv6" } 311959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin }; 312959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin size_t i; 313f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATO 314959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin for (i = 0; i < ARRAY_SIZE(protocols); ++i) { 315959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin if ((r = inet_print(fd, protocols[i].family, 316959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin protocols[i].protocol, inode, 317959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin protocols[i].name))) 318959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin break; 3192f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin } 3202f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin } 321959205c2a8a7c559b40204a1d33336d6800d1f1eDmitry V. Levin 3222f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin close(fd); 323f605e92365c7479d59ccfac3a294089f89359715Masatake YAMATO return r; 3242f6510c8a6a358ec00f56a491318181bc068a1fcDmitry V. Levin} 325