Linux netlink socket Implements similar ss commands to count socket and TCP information

Source: Internet
Author: User

Refer to the source code of ss

And netlink related information: http://blog.csdn.net/scdxmoe/article/details/27711205


Implementation result:

Gcc netlink_dig_530_7.c-o netlink_dig_530_7
./Netlink_dig_530_7

State family l. addr l. port r. addr r. rport
LISTEN AF_INET localhost 53 0.0.0.0 0
LISTEN AF_INET (null) 21 0.0.0.0 0
LISTEN AF_INET (null) 22 0.0.0.0 0
LISTEN AF_INET (null) 22 0.0.0.0 0
LISTEN AF_INET localhost 631 0.0.0.0 0
LISTEN AF_INET (null) 12865 0.0.0.0 0
ESTAB AF_INET ubuntu. local 59208 91.189.89.134 80
ESTAB AF_INET ubuntu. local 22 192.168.0.248 9689
ESTAB AF_INET ubuntu. local 22 192.168.0.248 9295
ESTAB AF_INET ubuntu. local 35531 91.189.94.25 80
ESTAB AF_INET ubuntu. local 22 192.168.0.248 9691

The experiment in this article does not implement how to obtain the TCP Window values cwnd and RTT values. In the ss source code, I saw that he used/proc.

File to obtain the window and RTT value, how to use netlink socket to implement it? For more information, see
Source code:

# Include <stdio. h> # include <stdlib. h> # include <unistd. h> # include <string. h> # include <fcntl. h> # include <errno. h> # include <string. h> # include <asm/types. h> # include <sys/socket. h> # include <linux/netlink. h> # include <linux/inet_diag.h> # include <netinet/tcp. h> # include <netdb. h> # include <arpa/inet. h> struct sk_req {struct nlmsghdr nlh; struct inet_diag_req r ;}; typedef struct {_ u8 family; _ u8 bytelen; _ s1 6 bitlen; _ u32 flags; _ u32 data [8];} inet_prefix;/* struct namerec {struct namerec * next; const char * name; inet_prefix addr ;}; */struct tcpstat {inet_prefix local; inet_prefix remote; int lport; int rport; int state; int rq, wq; int timer; int rq, wq; int timer; int timeout; int retrs; unsigned ino; int probes; unsigned uid; int refcnt; unsigned long sk; int rto, ato, qack, cwnd, ssthresh ;}; Enum {SS_UNKNOWN, cosine, SS_SYN_SENT, SS_SYN_RECV, SS_FIN_WAIT1, SS_FIN_WAIT2, SS_TIME_WAIT, SS_CLOSE, cosine, cosine, SS_LISTEN, SS_CLOSING, SS_MAX }; static const char * sstate_name [] = {"UNKNOWN", [SS_ESTABLISHED] = "ESTAB", [SS_SYN_SENT] = "SYN-SENT", [SS_SYN_RECV] = "SYN-RECV ", [SS_FIN_WAIT1] = "FIN-WAIT-1", [SS_FIN_WAIT2] = "FIN-WAIT-2", [SS_TIME_WAIT] = "TIME-WAIT", [SS _ CLOSE] = "UNCONN", [SS_CLOSE_WAIT] = "CLOSE-WAIT", [SS_LAST_ACK] = "LAST-ACK", [SS_LISTEN] = "LISTEN ", [SS_CLOSING] = "CLOSING",};/* Base info structure. it contains socket identity (addrs/ports/cookie) * and, alas, the information shown by netstat. /* Base info structure. it contains socket identity (addrs/ports/cookie) * and, alas, the information shown by netstat. struct nlmsghdr {_ u32 nlmsg_l En; // Length of message including header _ XHTML nlmsg_type; // Message content _ XHTML nlmsg_flags; // Additional flags _ u32 nlmsg_seq; // Sequence number _ u32 nlmsg_pid; // Sending process port ID}; * // # ifdef RESOLVE_HOSTNAMESstruct namerec {struct namerec * next; const char * name; inet_prefix addr;}; # define NHASH 257 static struct namerec * nht [NHASH]; static const char * resolve_address (const void * Addr, int len, int af) {struct namerec * n; struct hostent * h_ent; unsigned hash; static int notfirst; if (af = AF_INET6 & (_ u32 *) addr) [0] = 0 & (_ u32 *) addr) [1] = 0 & (_ u32 *) addr) [2] = htonl (0 xffff) {af = AF_INET; addr + = 12; len = 4;} hash = * (_ u32 *) (addr + len-4) % NHASH; for (n = nht [hash]; n; n = n-> next) {if (n-> addr. family = af & n-> addr. bytelen = len & memcmp (n-> addr. Data, addr, len) = 0) return n-> name; memcmp (n-> addr. data, addr, len) = 0) return n-> name;} if (n = malloc (sizeof (* n) = NULL) return NULL; n-> addr. family = af; n-> addr. bytelen = len; n-> name = NULL; memcpy (n-> addr. data, addr, len); n-> next = nht [hash]; nht [hash] = n; if (++ notfirst = 1) sethostent (1 ); fflush (stdout); if (h_ent = gethostbyaddr (addr, len, af ))! = NULL) n-> name = strdup (h_ent-> h_name);/* Even if we fail, "negative" entry is remembered. */return n-> name;} // # endifconst char * rt_addr_n2a (int af, int len, const void * addr, char * buf, int buflen) {switch (af) {case AF_INET: case AF_INET6: return inet_ntop (af, addr, buf, buflen);/* case AF_IPX: return ipx_ntop (af, addr, buf, buflen); case AF_DECnet: {struct dn_naddr dna = {2, {0, 0, }}; me Mcpy (dna. a_addr, addr, 2); return dnet_ntop (af, & dna, buf, buflen);} */default: return "??? ";}} Void print_info (struct inet_diag_msg * pkg, struct nlmsghdr * h) {struct tcpstat s; char buf [1024]; const char * ap = buf; // store the IP address char buf2 [1024]; const char * ap2 = buf2; // store the IP address struct inet_diag_msg * r = NLMSG_DATA (h); s. state = r-> idiag_state; s. local. family = s. remote. family = r-> idiag_family; s. lport = ntohs (r-> id. idiag_sport); s. rport = ntohs (r-> id. idiag_dport); s. local. family = s. remote. fam Ily = r-> idiag_family; if (s. local. family = AF_INET) {// print s here. local. bytelen = s. remote. bytelen = 4;} else {s. local. bytelen = s. remote. bytelen = 16;} memcpy (s. local. data, r-> id. idiag_src, s. local. bytelen); memcpy (s. remote. data, r-> id. idiag_dst, s. local. bytelen); // printf ("\ n %-* s \ n", 10, "state", 10, "family", 10, "l. addr ", 10," l. port ", 10," r. addr ", 10," r. rport "); printf (" % -* S ", 10, sstate_name [s. state]); printf ("%-* s", 10, "AF_INET"); // printf ("\ n ------------ \ n "); const inet_prefix * a = & s. remote; const void * addr = a-> data; ap = resolve_address (& s. local. data, 4, AF_INET); printf ("%-* s", 15, ap); printf ("%-* d", 10, s. lport); // ap2 = resolve_address (& s. remote. data, 4, AF_INET); ap2 = rt_addr_n2a (AF_INET, 4, addr, buf2, sizeof (buf2); printf ("%-* s", 15, ap2 ); printf ("%-* d \ n", 10, s. rp Ort); // printf ("L. port: %-* d R. prot: %-* d \ n ", 10, s. lport, 10, s. rport); // printf ("idiag_state: % d \ n", pkg-> idiag_state); // printf ("idiag_state: % d \ n ", pkg-> idiag_state); // printf ("Family: % s \ n", pkg-> idiag_family = AF_INET? "AF_INET": "AF_INET6"); // printf ("dport: % d, sprot: % d \ n", ntohs (pkg-> id. idiag_sport), ntohs (pkg-> id. idiag_sport); // printf ("idiag_state: % d \ n", pkg-> idiag_state);} int main (int argc, char ** argv) {int fd; struct sk_req req; struct sockaddr_nl dest_addr; struct msghdr msg; char buf [8192]; char src_ip [20]; char dest_ip [20]; struct iovec iov; if (fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG )) <0) {// eprint (_ LINE __, errno, "socket"); printf ("socket error \ n"); return-1;} req. nlh. nlmsg_len = sizeof (req); req. nlh. nlmsg_type = TCPDIAG_GETSOCK; req. nlh. nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; req. nlh. nlmsg_pid = 0; memset (& req. r, 0, sizeof (req. r); req. r. idiag_family = AF_INET; req. r. idiag_states = (1 <TCP_CLOSING + 1)-1); iov. iov_base = & req; iov. iov_len = sizeof (req); memset (& dest_addr, 0, sizeof (dest_addr); Memory = AF_NETLINK; memset (& dest_addr, 0, sizeof (dest_addr); dest_addr.nl_family = AF_NETLINK; latency = 0; latency = 0; memset (& msg, 0, sizeof (msg); msg. msg_name = (void *) & dest_addr; msg. msg_namelen = sizeof (dest_addr); msg. msg_iov = & iov; msg. msg_iovlen = 1; if (sendmsg (fd, & msg, 0) <0) {// eprint (_ LINE __, errno, "sendmsg"); printf ("socket erro R \ n "); return-1 ;} printf ("\ n %-* s \ n", 10, "state ", 10, "family", 10, "l. addr ", 10," l. port ", 10," r. addr ", 10," r. rport "); memset (buf, 0, sizeof (buf); iov. iov_base = buf; iov. iov_len = sizeof (buf); while (1) {int status; struct nlmsghdr * h; msg = (struct msghdr) {(void *) & dest_addr, sizeof (dest_addr ), & iov, 1, NULL, 0, 0}; status = recvmsg (fd, & msg, 0); // the return value of the recvmsg function is the number of bytes read, if (stat Us <0) {if (errno = EINTR) continue; // eprint (_ LINE __, errno, "recvmsg"); printf ("socket error \ n "); continue;} if (status = 0) {printf ("EOF on netlink \ n"); close (fd); return 0 ;}h = (struct nlmsghdr *) buf; // # define NLMSG_ OK (nlh, len) (len)> = (int) sizeof (struct nlmsghdr) & \ (nlh)-> nlmsg_len> = sizeof (struct nlmsghdr) & \ (nlh)-> nlmsg_len <= (len) while (NLMSG_ OK (h, status) {struct I Net_diag_msg * pkg = NULL;/* struct inet_diag_msg * pkg = NULL;/* struct detail {_ u8 idiag_family; _ u8 idiag_state; _ u8 idiag_timer; _ u8 break; struct inet_diag_sockid; _ u32 idiag_expires; _ u32 idiag_rqueue; _ u32 idiag_wqueue; _ u32 idiag_uid; _ u32 idiag_inode ;}; */if (h-> nlmsg_type = NLMSG_DONE) {close (fd); printf ("NLMSG_DONE \ n"); return 0;} if (h-> nlmsg_type = NLM SG_ERROR) {struct nlmsgerr * err; err = (struct nlmsgerr *) NLMSG_DATA (h); fprintf (stderr, "% d Error % d: % s \ n ", _ LINE __,-(err-> error), strerror (-(err-> error); close (fd); printf ("NLMSG_ERROR \ n "); return 0;} pkg = (struct inet_diag_msg *) NLMSG_DATA (h); // print_skinfo (pkg ); // printf ("\ n %-* s \ n", 10, "state", 10, "family", 10, "l. addr ", 10," l. port ", 10," r. addr ", 10," r. rport "); print _ Info (pkg, h); // get_tcp_state (pkg-> idiag_state); h = NLMSG_NEXT (h, status); // # define NLMSG_NEXT (nlh, len) (len) -= NLMSG_ALIGN (nlh)-> nlmsg_len), \ (struct nlmsghdr *) (char *) (nlh) + NLMSG_ALIGN (nlh)-> nlmsg_len ))) // # define NLMSG_ALIGN (len) + NLMSG_ALIGNTO-1 )&~ (NLMSG_ALIGNTO-1)} // while // whileclose (fd); return 0 ;}




Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.