Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save danny-source/bf49e95786a71262aa35115ef49b9e7a to your computer and use it in GitHub Desktop.

Select an option

Save danny-source/bf49e95786a71262aa35115ef49b9e7a to your computer and use it in GitHub Desktop.

Revisions

  1. @luohao-brian luohao-brian revised this gist Sep 21, 2018. 2 changed files with 3 additions and 3 deletions.
    3 changes: 3 additions & 0 deletions netlink-enumerate-ipaddrs.c
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,6 @@
    // Netlink 是内核与用户空间进程通信的一种机制,采用与 UDP socket 非常类似的编程风格。(
    // 与 UDP 类似,Netlink 通信也有服务器端和客户端。例如,Linux 内核作为服务器端,已经运行在那里。我们则编写 Netlink 客户端,给内核发消息,并获得我们想要的信息。

    /*
    * Display all IPv4 addresses
    */
    3 changes: 0 additions & 3 deletions netlink-enumerate-netdevs.c
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,3 @@
    // Netlink 是内核与用户空间进程通信的一种机制,采用与 UDP socket 非常类似的编程风格。(
    // 与 UDP 类似,Netlink 通信也有服务器端和客户端。例如,Linux 内核作为服务器端,已经运行在那里。我们则编写 Netlink 客户端,给内核发消息,并获得我们想要的信息。

    /*
    * Display all network interface names
    */
  2. @luohao-brian luohao-brian revised this gist Sep 21, 2018. No changes.
  3. @luohao-brian luohao-brian revised this gist Sep 21, 2018. 2 changed files with 2 additions and 2 deletions.
    1 change: 1 addition & 0 deletions netlink-enumerate-ipaddrs.c
    Original file line number Diff line number Diff line change
    @@ -134,3 +134,4 @@ int main(void)
    close(s);
    return 0;
    }

    3 changes: 1 addition & 2 deletions netlink-enumerate-netdevs.c
    Original file line number Diff line number Diff line change
    @@ -124,5 +124,4 @@ int main(void)

    close(s);
    return 0;
    }

    }
  4. @luohao-brian luohao-brian created this gist Sep 21, 2018.
    136 changes: 136 additions & 0 deletions netlink-enumerate-ipaddrs.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,136 @@
    /*
    * Display all IPv4 addresses
    */

    #include <stdio.h> //printf, perror
    #include <string.h> //memset, strlen
    #include <stdlib.h> //exit
    #include <unistd.h> //close
    #include <sys/socket.h> //msghdr
    #include <arpa/inet.h> //inet_ntop
    #include <linux/netlink.h> //sockaddr_nl
    #include <linux/rtnetlink.h> //rtgenmsg,ifinfomsg

    #define BUFSIZE 8192

    struct nl_req_s {
    struct nlmsghdr hdr;
    struct rtgenmsg gen;
    };

    void die(char *s)
    {
    perror(s);
    exit(1);
    }

    void rtnl_print_addr(struct nlmsghdr * h)
    {
    struct ifaddrmsg * addr;
    struct rtattr * attr;
    int len;

    addr = NLMSG_DATA(h);
    len = RTM_PAYLOAD(h);

    /* loop over all attributes for the NEWLINK message */
    for (attr = IFLA_RTA(addr); RTA_OK(attr, len); attr = RTA_NEXT(attr, len))
    {
    switch (attr->rta_type)
    {
    case IFA_LABEL:
    printf("Interface : %s\n", (char *)RTA_DATA(attr));
    break;
    case IFA_LOCAL:
    {
    int ip = *(int*)RTA_DATA(attr);
    unsigned char bytes[4];
    bytes[0] = ip & 0xFF;
    bytes[1] = (ip >> 8) & 0xFF;
    bytes[2] = (ip >> 16) & 0xFF;
    bytes[3] = (ip >> 24) & 0xFF;
    printf("IP Address : %d.%d.%d.%d\n", bytes[0], bytes[1], bytes[2], bytes[3]);
    break;
    }
    default:
    break;
    }
    }
    }

    int main(void)
    {
    struct sockaddr_nl kernel;
    int s, end=0, len;
    struct msghdr msg;
    struct nl_req_s req;
    struct iovec io;
    char buf[BUFSIZE];

    //build kernel netlink address
    memset(&kernel, 0, sizeof(kernel));
    kernel.nl_family = AF_NETLINK;
    kernel.nl_groups = 0;

    //create a Netlink socket
    if ((s=socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0)
    {
    die("socket");
    }

    //build netlink message
    memset(&req, 0, sizeof(req));
    req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
    req.hdr.nlmsg_type = RTM_GETADDR;
    req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
    req.hdr.nlmsg_seq = 1;
    req.hdr.nlmsg_pid = getpid();
    req.gen.rtgen_family = AF_INET;

    memset(&io, 0, sizeof(io));
    io.iov_base = &req;
    io.iov_len = req.hdr.nlmsg_len;

    memset(&msg, 0, sizeof(msg));
    msg.msg_iov = &io;
    msg.msg_iovlen = 1;
    msg.msg_name = &kernel;
    msg.msg_namelen = sizeof(kernel);

    //send the message
    if (sendmsg(s, &msg, 0) < 0)
    {
    die("sendmsg");
    }

    //parse reply
    while (!end)
    {
    memset(buf, 0, BUFSIZE);
    msg.msg_iov->iov_base = buf;
    msg.msg_iov->iov_len = BUFSIZE;
    if ((len=recvmsg(s, &msg, 0)) < 0)
    {
    die("recvmsg");
    }
    for (struct nlmsghdr * msg_ptr = (struct nlmsghdr *)buf;
    NLMSG_OK(msg_ptr, len); msg_ptr = NLMSG_NEXT(msg_ptr, len))
    {
    switch (msg_ptr->nlmsg_type)
    {
    case NLMSG_DONE:
    end++;
    break;
    case RTM_NEWADDR:
    rtnl_print_addr(msg_ptr);
    break;
    default:
    printf("Ignored msg: type=%d, len=%d\n", msg_ptr->nlmsg_type, msg_ptr->nlmsg_len);
    break;
    }
    }
    }

    close(s);
    return 0;
    }
    128 changes: 128 additions & 0 deletions netlink-enumerate-netdevs.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,128 @@
    // Netlink 是内核与用户空间进程通信的一种机制,采用与 UDP socket 非常类似的编程风格。(
    // 与 UDP 类似,Netlink 通信也有服务器端和客户端。例如,Linux 内核作为服务器端,已经运行在那里。我们则编写 Netlink 客户端,给内核发消息,并获得我们想要的信息。

    /*
    * Display all network interface names
    */
    #include <stdio.h> //printf, perror
    #include <string.h> //memset, strlen
    #include <stdlib.h> //exit
    #include <unistd.h> //close
    #include <sys/socket.h> //msghdr
    #include <arpa/inet.h> //inet_ntop
    #include <linux/netlink.h> //sockaddr_nl
    #include <linux/rtnetlink.h> //rtgenmsg,ifinfomsg

    #define BUFSIZE 8192

    struct nl_req_s {
    struct nlmsghdr hdr;
    struct rtgenmsg gen;
    };

    void die(char *s)
    {
    perror(s);
    exit(1);
    }

    void rtnl_print_link(struct nlmsghdr * h)
    {
    struct ifinfomsg * iface;
    struct rtattr * attr;
    int len;

    iface = NLMSG_DATA(h);
    len = RTM_PAYLOAD(h);

    /* loop over all attributes for the NEWLINK message */
    for (attr = IFLA_RTA(iface); RTA_OK(attr, len); attr = RTA_NEXT(attr, len))
    {
    switch (attr->rta_type)
    {
    case IFLA_IFNAME:
    printf("Interface %d : %s\n", iface->ifi_index, (char *)RTA_DATA(attr));
    break;
    default:
    break;
    }
    }
    }

    int main(void)
    {
    struct sockaddr_nl kernel;
    int s, end=0, len;
    struct msghdr msg;
    struct nl_req_s req;
    struct iovec io;
    char buf[BUFSIZE];

    //build kernel netlink address
    memset(&kernel, 0, sizeof(kernel));
    kernel.nl_family = AF_NETLINK;
    kernel.nl_groups = 0;

    //create a Netlink socket
    if ((s=socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0)
    {
    die("socket");
    }

    //build netlink message
    memset(&req, 0, sizeof(req));
    req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
    req.hdr.nlmsg_type = RTM_GETLINK;
    req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
    req.hdr.nlmsg_seq = 1;
    req.hdr.nlmsg_pid = getpid();
    req.gen.rtgen_family = AF_INET;

    memset(&io, 0, sizeof(io));
    io.iov_base = &req;
    io.iov_len = req.hdr.nlmsg_len;

    memset(&msg, 0, sizeof(msg));
    msg.msg_iov = &io;
    msg.msg_iovlen = 1;
    msg.msg_name = &kernel;
    msg.msg_namelen = sizeof(kernel);

    //send the message
    if (sendmsg(s, &msg, 0) < 0)
    {
    die("sendmsg");
    }

    //parse reply
    while (!end)
    {
    memset(buf, 0, BUFSIZE);
    msg.msg_iov->iov_base = buf;
    msg.msg_iov->iov_len = BUFSIZE;
    if ((len=recvmsg(s, &msg, 0)) < 0)
    {
    die("recvmsg");
    }
    for (struct nlmsghdr * msg_ptr = (struct nlmsghdr *)buf;
    NLMSG_OK(msg_ptr, len); msg_ptr = NLMSG_NEXT(msg_ptr, len))
    {
    switch (msg_ptr->nlmsg_type)
    {
    case NLMSG_DONE:
    end++;
    break;
    case RTM_NEWLINK:
    rtnl_print_link(msg_ptr);
    break;
    default:
    printf("Ignored msg: type=%d, len=%d\n", msg_ptr->nlmsg_type, msg_ptr->nlmsg_len);
    break;
    }
    }
    }

    close(s);
    return 0;
    }