Reference to the source code of the SS
and NetLink related information: http://blog.csdn.net/scdxmoe/article/details/27711205
The implementation results are:
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 paper does not implement how to get the window value of TCP CWnd and RTT values, in the SS source I saw him using the/proc.
file to achieve the acquisition window and RTT value, how to use NetLink socket implementation? Also ask you to advise
Source:
#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; __s16 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; RQ int, Wq; int timer; RQ int, Wq; int timer; int timeout; int retrs; UnsigneD ino; int probes; unsigned uid; int refcnt; unsigned long long SK; int RTO, ATO, Qack, CWnd, Ssthresh;}; enum {ss_unknown, ss_established, Ss_syn_sent, Ss_syn_recv, Ss_fin_wait1, Ss_fi N_wait2, Ss_time_wait, Ss_close, ss_close_wait, Ss_last_ack, Ss_listen, Ss_closi NG, ss_max};static const char *sstate_name[] = {"UNKNOWN", [ss_established] = "Estab", [Ss_sy N_sent] = "Syn-sent", [ss_syn_recv] = "Syn-recv", [ss_fin_wait1] = "Fin-wait-1", [ss_fin_wait2] = "FI N-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 informationShown by netstat./* Base info structure. It contains socket identity (addrs/ports/cookie) * And, alas, the information shown by Netstat. struct NLMSGHDR {__u32 nlmsg_len; Length of message including header __u16 Nlmsg_type; Message content __u16 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 257static 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 (0xffff)) {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->ad Dr.bytelen = = Len && memcmp (n->addr.data, addr, len) = = 0) return n-& Gt;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) {CAs E 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,}}; memcpy (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 IP address char buf2[1024]; const char *AP2 = buf2;//holds 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.family = r->idiag_family; if (s.local.family = = af_inet) {//here print S.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%-*s%-*s%-*s%-*s%-*s\n", Ten, "state", "Family", "l.addr", Ten, "L.port", "r.addr", Ten, "R.rport" "); printf ("%-*s", ten, Sstate_name[s.state]); printf ("%-*s", Ten, "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", p, 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", AP2); printf ("%-*d\n", 10,s.rport); 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, si Zeof (DEST_ADDR));d est_addr.nl_family = Af_netlink;memset (&dest_addr, 0, sizeof (DEST_ADDR));d est_addr.nl_family = Af_netlink;dest_addr.nl_pid = 0;dest_addr.nl_groups = 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 error\n"); return-1;} printf ("\n%-*s%-*s%-*s%-*s%-*s%-*s\n", Ten, "State", Ten, "FamilY "," l.addr "," L.port "," 0 "," r.addr "," R.rport ") memset (buf,, 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 (Status < 0) {if (errno = = eintr) CO Ntinue; 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 inet_diag_msg *pkg = NULL; /* struct INET_diag_msg *pkg = NULL; /* struct INET_DIAG_MSG {__u8 idiag_family; __u8 idiag_state; __u8 Idiag_timer; __u8 Idiag_retrans; struct Inet_diag_sockid ID; __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 = = nlmsg_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%-*s%-*s%-*s%-*s%-*s\n", Ten, "state", "family", ten, "l.addr", Ten, "L.port", Ten, "r.addr", Ten, "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 NLM sghdr*) (((char*) (NLH)) + nlmsg_align ((NLH)->nlmsg_len))//#define NLMSG_ALIGN (len) ((len) +nlmsg_align TO-1) & ~ (nlmsg_alignto-1))}//while}//whileclose (FD); return 0;}