• 采用Netlink进行内核与用户空间交互数据

参考:netlink学习笔记之NETLINK_INET_DIAG获取TCP连接状态(netstat) – 浮生笔记

比如获取连接状态

#if 0
#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>int main(int argc, char **argv)
{int fd;struct sockaddr_nl src_addr, dest_addr;struct{struct nlmsghdr nlh;struct inet_diag_req r;} req;struct inet_diag_msg *pkg;struct msghdr msg;char buf[8192];char src_ip[40];char dest_ip[40];struct iovec iov;if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)return -1;int ret;ret = fcntl(fd, F_SETFL, O_NONBLOCK);if (ret < 0) {fprintf(stderr, "Can't set socket flags");close(fd);return -1;}//src addrmemset(&src_addr, 0, sizeof(struct sockaddr_nl));src_addr.nl_family = AF_NETLINK;src_addr.nl_pid = getpid();src_addr.nl_groups = 0;if (bind(fd, (struct sockaddr *)&src_addr, sizeof(struct sockaddr_nl)) < 0) {fprintf(stderr, "bind socket error %s\n", strerror(errno));}memset(&req, 0, sizeof(req));req.nlh.nlmsg_len = sizeof(req);req.nlh.nlmsg_type = TCPDIAG_GETSOCK;req.nlh.nlmsg_flags = NLM_F_MATCH | NLM_F_REQUEST | NLM_F_ROOT;// req.nlh.nlmsg_flags = NLM_F_REQUEST ;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); //states to dump//send msg to kerneliov.iov_base = &req;iov.iov_len = sizeof(req);//dest addrmemset(&dest_addr, 0, sizeof(struct sockaddr_nl));dest_addr.nl_family = AF_NETLINK;dest_addr.nl_pid = 0;dest_addr.nl_groups = 0;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) {printf("%s\n", strerror(errno));return -1;}//recv msg from kerneliov.iov_base = buf;iov.iov_len = sizeof(buf);while (1) {//printf("while1\n");int status;struct nlmsghdr *h;msg = (struct msghdr){(void *)&dest_addr, sizeof(struct sockaddr_nl),&iov, 1, NULL, 0, 0};//length of recv datastatus = recvmsg(fd, &msg, 0);//status = recv(fd, buf, sizeof(buf), 0);printf("status = %d\n", status);if (status < 0) {if (errno == EINTR) {continue;}printf("errno = %d\n", errno);continue;}if (status == 0) {close(fd);printf("EOF\n");return 0;}h = (struct nlmsghdr *)buf;while (NLMSG_OK(h, status)) {//printf("while2\n");printf("nlmsg_type = %d\n",h->nlmsg_type );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);memset(src_ip, 0, sizeof(src_ip));memset(dest_ip, 0, sizeof(dest_ip));inet_ntop(pkg->idiag_family, pkg->id.idiag_src, src_ip, sizeof(src_ip));inet_ntop(pkg->idiag_family, pkg->id.idiag_dst, dest_ip, sizeof(dest_ip));printf("%-8s %4d %40s:%-6hu %40s:%-6hu\n", pkg->idiag_family == AF_INET ? "AF_INET" : "AF_INET6", pkg->idiag_state, src_ip, ntohs(pkg->id.idiag_sport), dest_ip, ntohs(pkg->id.idiag_dport));// get_tcp_state(pkg->idiag_state);h = NLMSG_NEXT(h, status);//printf("status = %d\n\n", status);}//while}//whileclose(fd);return 0;
}#else
/*** @file NET_LINK_NET_STATE.c* @author dennisthink (https://www.dennisthink.com/)* @brief NETLINK方式获取 网络连接状态* @version 0.1* @date 2020-11-21* * @copyright Copyright (c) 2020* */#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 <arpa/inet.h>/*** @brief 创建NetLinkDiag的socket* * @return int > 0 创建成功*             - 1 创建失败*/
int createNetLinkDiagSocket()
{int fd = 0;if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0){return -1;}    else{return fd;}
}/*** @brief 设置socket为非阻塞模式* * @param fd 被设置的socket描述符* @return int >= 0  -- 成功*             -1 -- 失败*/
int setSocketOpt(int fd)
{int ret = 0;ret = fcntl(fd, F_SETFL, O_NONBLOCK);if (ret < 0){fprintf(stderr, "Can't set socket flags");close(fd);return -1;}else{return ret;}
}/*** @brief 绑定socket到NetLink的地址* * @param fd 待绑定的socket* @return int 0  --- 成功*             -1 --- 失败*/
int bindSocketToNetLink(int fd)
{struct sockaddr_nl src_addr;{//src addrmemset(&src_addr, 0, sizeof(struct sockaddr_nl));src_addr.nl_family = AF_NETLINK;src_addr.nl_pid = getpid();src_addr.nl_groups = 0;}if (bind(fd, (struct sockaddr *)&src_addr, sizeof(struct sockaddr_nl)) >=0 ){return 0;}else{return -1;}
}/*** @brief 发送消息到内核* * @param fd netlink的socket* @return int 0  -- 成功*             -1 -- 失败*/
int sendMsgToNetLink(int fd)
{//4.1 初始化目标地址struct sockaddr_nl dest_addr;{memset(&dest_addr, 0, sizeof(struct sockaddr_nl));dest_addr.nl_family = AF_NETLINK;dest_addr.nl_pid = 0;dest_addr.nl_groups = 0;}//4.2 初始化请求的数据struct{struct nlmsghdr nlh;struct inet_diag_req r;} req;{memset(&req, 0, sizeof(req));req.nlh.nlmsg_len = sizeof(req);req.nlh.nlmsg_type = TCPDIAG_GETSOCK;req.nlh.nlmsg_flags = NLM_F_MATCH | NLM_F_REQUEST | NLM_F_ROOT;// req.nlh.nlmsg_flags = NLM_F_REQUEST ;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); //states to dump}//4.3 将请求数据绑定到消息上//4.3.1 将req数据绑定到iov上//注意:此处要定义一个数组,保存足够的buff,要不会出现 errno=105的错误struct iovec iov[2];char buff[4096]={0};{//send msg to kerneliov[0].iov_base = &req;iov[0].iov_len = sizeof(req);iov[1].iov_base = buff;iov[1].iov_len = sizeof(buff);}struct msghdr msgForSend;//4.3.2 将目标地址和请求数据绑定到msg上{msgForSend.msg_name = (void *)&dest_addr;msgForSend.msg_namelen = sizeof(dest_addr);msgForSend.msg_iov = iov;msgForSend.msg_iovlen = 2;}//4.4 发送消息if (sendmsg(fd, &msgForSend, 0) < 0){return -1;}return 0;
}/*** @brief 解析TCP的状态* * @param nState tcp状态*/
void parseTcpState(const int nState)
{switch(nState){case TCP_ESTABLISHED:{printf("ESTABLISHED");}break;case TCP_SYN_SENT:{printf("SYN_SENT");}break;case TCP_SYN_RECV:{printf("SYN_RECV");}break;case TCP_FIN_WAIT1:{printf("FIN_WAIT1");}break;case TCP_FIN_WAIT2:{printf("FIN_WAIT2");}break;case TCP_TIME_WAIT:{printf("TIME_WAIT");}break;case TCP_CLOSE:{printf("CLOSE");}break;case TCP_CLOSE_WAIT:{printf("CLOSE_WAIT");}break;case TCP_LAST_ACK:{printf("LAST_ACK");}break;case TCP_CLOSING:{printf("CLOSING");}break;case TCP_LISTEN:{printf("LISTEN");}break;default:{printf("DEFAULT");}break;}
}/*** @brief 解析收到的数据* * @param buff 数据起始地址* @param status 数据的长度* @return int 默认返回0*/
int parseRecvMsg(char *buff,int status)
{struct nlmsghdr * h = (struct nlmsghdr *)buff;while (NLMSG_OK(h, status)){if (h->nlmsg_type == NLMSG_DONE){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)));return 0;}struct inet_diag_msg *pkg = (struct inet_diag_msg *)NLMSG_DATA(h);char src_ip[40];char dest_ip[40];memset(src_ip, 0, sizeof(src_ip));memset(dest_ip, 0, sizeof(dest_ip));inet_ntop(pkg->idiag_family, pkg->id.idiag_src, src_ip, sizeof(src_ip));inet_ntop(pkg->idiag_family, pkg->id.idiag_dst, dest_ip, sizeof(dest_ip));printf("%-8s %40s:%-6hu %40s:%-6hu", pkg->idiag_family == AF_INET ? "AF_INET" : "AF_INET6", src_ip, ntohs(pkg->id.idiag_sport), dest_ip, ntohs(pkg->id.idiag_dport));parseTcpState(pkg->idiag_state);printf("\n");h = NLMSG_NEXT(h, status);} //whilereturn 0;
}
/*** @brief 从netlink接收消息* * @param fd netlink套接字* @return int 默认返回0*/
int recvMsgFromNetLink(int fd)
{char buf[8192]={0};//recv msg from kernelstruct iovec iov;iov.iov_base = buf;iov.iov_len = sizeof(buf);struct sockaddr_nl destAddrForRecv;{memset(&destAddrForRecv, 0, sizeof(struct sockaddr_nl));destAddrForRecv.nl_family = AF_NETLINK;destAddrForRecv.nl_pid = 0;destAddrForRecv.nl_groups = 0;}struct msghdr msgForRecv;while (1){msgForRecv.msg_name = (void *)(&destAddrForRecv);msgForRecv.msg_namelen = sizeof(destAddrForRecv);msgForRecv.msg_iov = &iov;msgForRecv.msg_iovlen  = 1;//length of recv dataint status = recvmsg(fd, &msgForRecv, 0);if (status == 0){return 0;}if(status > 0){parseRecvMsg(buf,status);return 0;}usleep(1000);}//whilereturn 0;
}int main(int argc, char **argv)
{//创建socketint fd = createNetLinkDiagSocket();if(fd > 0){printf("Create Socket Succeed\n");}else{printf("Create Socket Failed  ErrNo:%d  ErrMsg:%s\n",errno,strerror(errno));return -1;}//2. 设置socket选项if(setSocketOpt(fd) >= 0){printf("Set socketOpt succeed \n");}else{printf("Set sockOpt faild  ErrNo:%d  ErrMsg:%s\n",errno,strerror(errno));return -1;}//3. 绑定socketif(bindSocketToNetLink(fd) >= 0){printf("bind Socket To NetLink Succeed\n");}else{printf("bind Socket To NetLink faild  ErrNo:%d  ErrMsg:%s\n",errno,strerror(errno));return -1;}//4. 发送消息到内核if(sendMsgToNetLink(fd) >= 0){printf("sendMsgToNetLink Succeed \n");}else{printf("sendMsgToNetLink Failed ErrNo:%d  ErrMsg:%s\n",errno,strerror(errno));return -1;}if(recvMsgFromNetLink(fd)>=0){printf("recvMsgFromNetLink Succeed\n");}else{printf("recvMsgFromNetLink Failed ErrNo:%d  ErrMsg:%s\n",errno,strerror(errno));}close(fd);return 0;
}#endif

Netlink的简单例子相关推荐

  1. webpack入门之简单例子跑起来

    webpack入门之简单例子跑起来 webpack介绍 Webpack是当下最热门的前端资源模块化管理和打包工具,它可以将很多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源,还可以将按需加载 ...

  2. 图片上传(加水印、缩略图、远程保存)的简单例子

    图片上传(加水印.缩略图.远程保存)的简单例子(应用于51aspx.com) 该源码下载地址:http://51aspx.com/CV/ImageUpload 今天看到xiongeee发的文章使用使用 ...

  3. java hashtable import,Hashtable的一个简单例子

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 以下是关于Hashtable的简单例子,谁知道别的遍历Hashtable的方法,请回复! package no1; import java.util.En ...

  4. SAP MM采购定价过程的一个简单例子

    SAP MM采购定价过程的一个简单例子 本文以一个简单的例子阐述了SAP MM模块中采购定价的基本原理.本例中,假定采购订单里输入的是含税采购价,然后系统自动计算出物料最终的采购价格(含税价-税额=采 ...

  5. .net中使用反射的简单例子

    说明:由于工作原因,本人使用反射的机会不是很多,所以没有必要为了炫耀技术而使用这种技术,不过今天有人问到这方面的问题,所以做了一个简单例子,供初学者参考,代码如下: using System; usi ...

  6. linux下Makefile中包含有shared library动态链接库文件时候的简单例子

    如果不知道什么是makefile,可以首先看我的另一篇博客: linux下Makefile的简单例子及解释 http://www.cnblogs.com/lihaozy/archive/2012/08 ...

  7. java 国际化例子_JavaSE 国际化 简单例子

    ①在src下添加两个文件: base_zh_CN.properties Test=\u8fd9\u662f\u4e2d\u6587 base_en_US.properties Test=english ...

  8. 6翻了C语言,《嗨翻C语言》随书练习六 6章 二叉树简单例子

    二叉树简单例子/* <嗨翻C语言>随书练习 6章    2016-12-06 xiousheng@126.com  二叉树例子,警务罪犯判断档案系统,哈哈 书中可以专家系统例子 */ #i ...

  9. QT 信号与槽 最简单例子

    QT  信号与槽 最简单例子 main.cpp 和 my_head.h源码: [cpp] view plaincopy #ifndef MY_HEAD_H #define MY_HEAD_H #inc ...

最新文章

  1. Python 安装selenium
  2. Hibernate中自动生成数据库表的两种方式
  3. 云炬随笔20211002
  4. Qt-5种布局控件详解
  5. c语言判断化学方程式,下列是某同学写的六个化学方程式:①Mg+O2点燃.MgO2②C+O2点燃.CO...
  6. Linux的Makefile简单实例教程
  7. 如何查看和转移 Windows Server 2003 中的 FSMO 角色
  8. OAuth 及 移动端鉴权调研
  9. ztree 使用教程
  10. c语言更改记事本改为大写,记事本里的字母大写转换成小写怎么弄 编写一个汇编程序要...
  11. 2021-2027全球与中国功能性涂层复合材料市场现状及未来发展趋势
  12. Python文件夹压缩
  13. linux串口工具 kermit,Linux下串口工具kermit的安装使用攻略
  14. salesforce 和 salesforce platform 的License的区别
  15. 巨头秀区块链肌肉 原生军机会何在?
  16. 台式计算机如何设置屏幕亮度,怎么调整台式电脑屏幕亮度的方法,如何调整显示器...
  17. 怎么将项目上传到git仓库(gitee)
  18. Qt的QVector类
  19. .Net 垃圾回收机制原理(二)
  20. 打麻将要诀,送给以前常输的你

热门文章

  1. 秒解UTF-8带来的烦恼
  2. EBP与ESP的作用
  3. 【Django】admin.ModelAdmin的源码-20220105
  4. 制造业数字化转型内涵和过程
  5. Linux系统或服务器运行Fastqc
  6. 女孩,既要懂得暧昧,又要懂得拒绝 【20cn 依依】
  7. Expert C Programming 阅读笔记(CH2)
  8. c#自学二之KTV点歌系统
  9. 前端技术栈:后台管理端UI框架
  10. 【Android 11】【WiFi模块】WiFi打开函数调用流程图