linux netlink套接字学习资料

理论:

http://blog.csdn.net/unbutun/article/details/3394061

进一步深入:

http://edsionte.com/techblog/archives/4134

http://edsionte.com/techblog/archives/4140

http://edsionte.com/techblog/archives/4134

实践:

http://bbs.chinaunix.net/thread-3766684-1-1.html


附录代码:

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <unistd.h>  
  4. #include <string.h>  
  5. #include <fcntl.h>  
  6. #include <errno.h>  
  7. #include <string.h>  
  8. #include <asm/types.h>  
  9. #include <sys/socket.h>  
  10. #include <linux/netlink.h>  
  11. #include <linux/inet_diag.h>  
  12. #include <netinet/tcp.h>  
  13.   
  14. #define NETLINK_TEST 18  
  15. #define MAX_PAYLOAD 1024  
  16. struct req {  
  17.     struct nlmsghdr nlh;  
  18.     char [MAX_PAYLOAD];  
  19. };  
  20.   
  21. void eprint(int err_no, char *str, int line)  
  22. {  
  23.     printf("Error %d in line %d:%s() with %s\n", err_no, line, str, strerror(errno));  
  24. }  
  25. int main()  
  26. {  
  27. int sock_fd;  
  28. sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);  
  29. if (sock_fd < 0) {  
  30.     eprint(errno, "socket", __LINE__);  
  31.     return errno;  
  32. }  
  33. //将本地套接字与源地址绑定  
  34. struct sockaddr_nl src_addr;  
  35. memset(&src_addr, 0, sizeof(src_addr));  
  36. src_addr.nl_family = AF_NETLINK;  
  37. src_addr.nl_pid = getpid();                 //nl_pid字段指明发送消息一方的pid  
  38. src_addr.nl_groups = 0;                     //nl_groups表示多播组的掩码  这里我们并没有涉及多播,因此默认为0  
  39.   
  40. if (bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr)) < 0) {  
  41.     eprint(errno, "bind", __LINE__);  
  42.     return errno;  
  43. }  
  44.   
  45. //绑定了套接字之后,用户进程最终发送的是msghdr结构的消息,因此必须对这个结构进行初始化,  
  46. //而msghdr结构又与  
  47. //初始化msghdr结构 sockaddr_nl,iovec和nlmsghdr三个结构相关,因此必须依次对这些数据结构进行初始化  
  48. /* 
  49. struct msghdr { 
  50.     void    *   msg_name;   // Socket name           
  51.     int     msg_namelen;    //Length of name         
  52.     struct iovec *  msg_iov;    // Data blocks           
  53.     __kernel_size_t msg_iovlen; // Number of blocks      
  54.     void    *   msg_control;    // Per protocol magic (eg BSD file descriptor passing)  
  55.     __kernel_size_t msg_controllen; // Length of cmsg list  
  56.     unsigned    msg_flags; 
  57. };*/  
  58. /* 
  59. struct sockaddr_nl { 
  60.     __kernel_sa_family_t    nl_family;  // AF_NETLINK    
  61.     unsigned short  nl_pad;     //zero       
  62.     __u32       nl_pid;     // port ID   
  63.         __u32       nl_groups;  // multicast groups mask  
  64. };*/  
  65.   
  66. struct sockaddr_nl dest_addr;  
  67. memset(&dest_addr, 0, sizeof(dest_addr));  
  68. dest_addr.nl_family = AF_NETLINK;  
  69. dest_addr.nl_pid = 0;   //即nl_pid必须为0,表示接收方为内核。                   
  70. dest_addr.nl_groups = 0;                   
  71. //req类型的数据报进行初始化,即依次对其封装的两个数据结构初始化:  
  72.   
  73. struct req r;//自定义协议数据结构  使用netlink进行用户进程和内核的数据交互时 用到  
  74. r.nlh.nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);             /*这里的nlmsg_len为为sizeof(structnlmsghdr)+MAX_PAYLOAD的总和。宏NLMSG_SPACE会自动将两者的长度相加 
  75. #define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN) 
  76. #define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len)) */  
  77.   
  78. r.nlh.nlmsg_pid = getpid();  
  79. r.nlh.nlmsg_flags = 0;  
  80. memset(r.buf, 0, MAX_PAYLOAD);  
  81. strcpy(NLMSG_DATA(&(r.nlh)), "hello, I am edsionte!");  //#define NLMSG_DATA(nlh)  ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))  
  82.   
  83. //接下来对缓冲区向量iov进行初始化,让iov_base字段指向数据报结构,而iov_len为数据报长度。  
  84. struct iovec iov;  
  85. iov.iov_base = (void *)&r;  
  86. iov.iov_len = sizeof(r);  
  87.   
  88. //一切就绪后,将目的套接字地址与当前要发送的消息msg绑定,即将目的套接字地址复制给msg_name。再将要发送的数据iov与msg_iov绑定,如果一次///性要发送多个数据包,则创建一个iovec类型的数组。  
  89. struct msghdr msg;  
  90. msg.msg_name = (void *)&dest_addr;  
  91. msg.msg_namelen = sizeof(dest_addr);  
  92. msg.msg_iov = &iov;  
  93. msg.msg_iovlen = 1;  
  94.   
  95. //.向内核发送消息  
  96. if (sendmsg(sock_fd, &msg, 0) < 0) {  
  97.     eprint(errno, "sendmsg", __LINE__);  
  98.     return errno;  
  99. }  
  100.   
  101. //接收内核发来的消息  
  102. memset(&r.nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));  
  103. if (recvmsg(sock_fd, &msg, 0) < 0) {  
  104.         eprint(errno, "recvmsg", __LINE__);  
  105.         return errno;  
  106. }  
  107. printf("Received message payload:%s\n", (char *)NLMSG_DATA(r.nlh));  
  108. close(sock_fd);  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值