当前位置:网站首页>Implementation process of tcpdump packet capturing
Implementation process of tcpdump packet capturing
2022-06-24 08:56:00 【To maintain world peace_】
Catalog
Kernel according to ptype_all Find the bag capturing point ( important )
Filter packet capture point netfilter( important )
The application layer implements the key program of capturing packets
tcpdump Packet capture source code analysis
application layer
Protocol family AF_PACKET
socket(AF_PACKET, SOCK_RAW, ETH_P_ALL)Protocol family and address family relationship : Each protocol family has a corresponding address family .IPV4 Protocol family of PF_INET, Address family is AF_INET, One-to-one correspondence , The value is exactly the same , Mix it up a lot .
socket Kernel Implementation
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
{
return __sys_socket(family, type, protocol);
}
int __sys_socket(int family, int type, int protocol)
{
retval = sock_create(family, type, protocol, &sock);
}
int __sock_create(struct net *net, int family, int type, int protocol,
struct socket **res, int kern)
{
pf = rcu_dereference(net_families[family]);
err = pf->create(net, sock, protocol, kern);
}from net_families Get the specified protocol in , And call create Method creation
static const struct net_proto_family packet_family_ops = {
.family = PF_PACKET,
.create = packet_create,
.owner = THIS_MODULE,
};
static int __init packet_init(void)
{
rc = sock_register(&packet_family_ops);
}
// register packet_family_ops To net_families in
int sock_register(const struct net_proto_family *ops)
{
rcu_assign_pointer(net_families[ops->family], ops);
}
//pf->create Namely packet_create
static int packet_create(struct net *net, struct socket *sock, int protocol,
int kern)
{
// State at creation
sock->state = SS_UNCONNECTED;
sk = sk_alloc(net, PF_PACKET, GFP_KERNEL, &packet_proto, kern);
sock->ops = &packet_ops;
po = pkt_sk(sk);
// Congestion control
init_completion(&po->skb_completion);
sk->sk_family = PF_PACKET;
po->xmit = dev_queue_xmit;
//fun The callback function registered on is packet_rcv
po->prot_hook.func = packet_rcv;
if (proto) {
po->prot_hook.type = proto;
__register_prot_hook(sk);
}
}
static void __register_prot_hook(struct sock *sk)
{
struct packet_sock *po = pkt_sk(sk);
dev_add_pack(&po->prot_hook);// register
}
void dev_add_pack(struct packet_type *pt)
{
struct list_head *head = ptype_head(pt);
list_add_rcu(&pt->list, head);
}
//ptype_head
static inline struct list_head *ptype_head(const struct packet_type *pt)
{
if (pt->type == htons(ETH_P_ALL))
return pt->dev ? &pt->dev->ptype_all : &ptype_all;
else
return pt->dev ? &pt->dev->ptype_specific :
&ptype_base[ntohs(pt->type) & PTYPE_HASH_MASK];
}dev_add_pack In fact, in the end hook Function added to ptype_all In the , The code is as follows .
Kernel according to ptype_all Find the bag capturing point ( important )
static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
{
......
// Traverse ptype_all (tcpdump Hang up the virtual protocol here )
list_for_each_entry_rcu(ptype, &ptype_all, list) {
if (pt_prev)
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
}
}
static inline int deliver_skb(struct sk_buff *skb,
struct packet_type *pt_prev,
struct net_device *orig_dev)
{
// This callback function is registered packet_rcv
return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
}
// take skb Add to sk_receive_queue in
static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
{
__skb_queue_tail(&sk->sk_receive_queue, skb);
}
so packet_rcv Take what you have received skb Put it in the current packet socket In the receiving queue . call recvfrom You can get the caught bag when you get it
Filter packet capture point netfilter( important )
The Internet Reception does not go through netfilter
The Internet Contract process netfilter
Contract awarding IP Various layers netfilter Rule filtering
int __ip_local_out(struct sk_buff *skb)
{
......
return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, skb, NULL,
skb_dst(skb)->dev, dst_output);
}
struct sk_buff *dev_hard_start_xmit(struct sk_buff *first, struct net_device *dev,
struct netdev_queue *txq, int *ret)
{
while (skb) {
rc = xmit_one(skb, dev, txq, next != NULL);
}
}
//xmit_one->dev_queue_xmit_nit
void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
{
list_for_each_entry_rcu(ptype, ptype_list, list) {
if (ptype->ignore_outgoing)
continue;
if (pt_prev) {
deliver_skb(skb2, pt_prev, skb->dev);
pt_prev = ptype;
continue;
}
}static inline int deliver_skb(struct sk_buff *skb,
struct packet_type *pt_prev,
struct net_device *orig_dev)
{
return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
}
stay dev_queue_xmit_nit Middle traversal ptype_all The agreement in , And call... In turn deliver_skb. This will be implemented to tcpdump The virtual protocol hanging on it .
summary
- tcpdump It's through socket system call ,
- register packet_rcv Callback function to ptype_all In line
- Network receiving and contracting , It will traverse the network device layer ptype_all The agreement in , And execute the callback .
- Data packets go through the network device layer before they reach the protocol layer n,etfilter stay tcpdump There is no filtering function in the packet receiving process ; During the contract awarding process IP Layers enter various netfilter Rule filtering works .
The application layer implements the key program of capturing packets
Implement packet capturing at the application layer The type is set to PF_PACKET
//PF_PACKET
int main(int argc, char *argv[])
{
if( (sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0 ){
printf("Create socket error.\n");
exit(0);
}
while(1){
len = recvfrom(sock, buffer, BUFFER_MAX, 0, NULL, NULL);
if (len < 46) {
printf("Catch packet length error.\n" );
close(sock);
exit(0);
}
}
}
Reference resources
https://course.0voice.com/v1/course/intro?courseId=2&agentId=0
边栏推荐
- Database migration from PostgreSQL to MySQL
- 原生小程序用画布制作海报,等比例缩放,和uniapp差不多就是写法有点不同
- ZUCC_ Principles of compiling language and compilation_ Experiment 0607 grammar analysis ll analysis
- 【LeetCode】415. 字符串相加
- 项目部署相关
- [MySQL from introduction to mastery] [advanced part] (I) character set modification and underlying principle
- xargs使用技巧 —— 筑梦之路
- 2138. splitting a string into groups of length k
- 【牛客】HJ1 字符串最后一个单词的长度
- 2021-05-20computed和watch应用与区别
猜你喜欢

MySQL | store notes of Master Kong MySQL from introduction to advanced

Detailed explanation of Base64 coding and its variants (to solve the problem that the plus sign changes into a space in the URL)

JS to find and update the specified value in the object through the key

rpiplay实现树莓派AirPlay投屏器

“不平凡的代理初始值设定不受支持”,出现的原因及解决方法

Pymysql inserts data into MySQL and reports an error for no reason

【NOI模拟赛】给国与时光鸡(构造)

One article explains in detail | those things about growth

疫情、失业,2022,我们高喊着摆烂和躺平!

MySQL | view notes on Master Kong MySQL from introduction to advanced
随机推荐
pm2 部署 nuxt3.js 项目
every()、map()、forEarch()方法。数组里面有对象的情况
【PyTorch基础教程30】DSSM双塔模型代码解析
leetcode 1268. Search suggestions system
Database migration from PostgreSQL to MySQL
原生小程序用画布制作海报,等比例缩放,和uniapp差不多就是写法有点不同
所说的Get post:请求的区别,你真的知道了吗??????
Double pointer analog
216. 组合总和 III-枚举法
数据中台:国内大厂中台建设架构集锦
Analyze the meaning of Internet advertising terms CPM, CPC, CPA, CPS, CPL and CPR
从华为WeAutomate数字机器人论坛,看政企领域的“政务新智理”
Earthly 容器镜像构建工具 —— 筑梦之路
用VNC Viewer的方式远程连接无需显示屏的树莓派
The form image uploaded in chorme cannot view the binary image information of the request body
小程序wx.show
leetcode——错误的集合
Telnet port login method with user name for liunx server
ZUCC_ Principles of compiling language and compilation_ Experiment 0607 grammar analysis ll analysis
Background management of uniapp hot update