Linux NetLink sockets implement similar SS commands, statistics sockets, and TCP information

Source: Internet
Author: User
Tags sendmsg socket error

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-&GT;ID.IDIAG_SRC, S.local.bytelen);                memcpy (S.remote.data, R-&GT;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 (&AMP;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;}




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.