Netfilter 之 钩子函数调用
本篇主要从三层协议栈调用函数NF_HOOK说起,不断深入,分析某个钩子点中所有钩子函数的调用流程,但是本文不包含规则介绍和核心的规则匹配流程,后续文章将继续分析;
NF_HOOK函数先调用了nf_hook继续执行调用钩子函数处理,处理之后,如果接受,则调用输入的回调函数okfn,继续数据包的下一步处理;
static inline int
NF_HOOK(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb,
struct net_device *in, struct net_device *out,
int (*okfn)(struct net *, struct sock *, struct sk_buff *))
{
/* 先执行钩子函数 */
int ret = nf_hook(pf, hook, net, sk, skb, in, out, okfn); /* 返回成功,则继续执行成功回调 */
if (ret == )
ret = okfn(net, sk, skb);
return ret;
}
NF_HOOK_COND增加了一个输入掉价cond,当不满足条件的时候,直接调用okfn,满足条件的时候,才会继续调用nf_hook进行后续的钩子函数调用流程,如果nf_hook返回1,则调用okfn;
static inline int
NF_HOOK_COND(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk,
struct sk_buff *skb, struct net_device *in, struct net_device *out,
int (*okfn)(struct net *, struct sock *, struct sk_buff *),
bool cond)
{
int ret; if (!cond ||
((ret = nf_hook(pf, hook, net, sk, skb, in, out, okfn)) == ))
ret = okfn(net, sk, skb);
return ret;
}
nf_hook函数首先找到钩子点函数入口,如果有钩子函数,则进一步初始化nf_hook_state结构,然后调用nf_hook_slow进入钩子函数调用流程;
static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net,
struct sock *sk, struct sk_buff *skb,
struct net_device *indev, struct net_device *outdev,
int (*okfn)(struct net *, struct sock *, struct sk_buff *))
{
struct nf_hook_entry *hook_head;
int ret = ; #ifdef HAVE_JUMP_LABEL
if (__builtin_constant_p(pf) &&
__builtin_constant_p(hook) &&
!static_key_false(&nf_hooks_needed[pf][hook]))
return ;
#endif rcu_read_lock();
/* 找到钩子点 */
hook_head = rcu_dereference(net->nf.hooks[pf][hook]);
if (hook_head) {
struct nf_hook_state state; /* 初始化nf_hook_state结构 */
nf_hook_state_init(&state, hook, pf, indev, outdev,
sk, net, okfn); /* 执行钩子函数 */
ret = nf_hook_slow(skb, &state, hook_head);
}
rcu_read_unlock(); return ret;
}
在分析nf_hook_slow之前,我们先看下该函数中涉及到的钩子函数执行结果的返回值字段的含义;
/* Responses from hook functions. */
#define NF_DROP 0 /* 丢包,不再传输 */
#define NF_ACCEPT 1 /* 接受数据包,继续正常传输 */
#define NF_STOLEN 2 /* 数据包已经被接管,回调函数处理该包,NF不再处理 */
#define NF_QUEUE 3 /* 将数据包交给用户空间的进程处理 */
#define NF_REPEAT 4 /* 再次调用钩子函数 */
#define NF_STOP 5 /* Deprecated, for userspace nf_queue compatibility. */
#define NF_MAX_VERDICT NF_STOP
nf_hook_slow会遍历当前钩子点上的钩子函数,通过函数nf_hook_entry_hookfn调用钩子函数,并根据返回值判断如何进行下一步处理;
int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
struct nf_hook_entry *entry)
{
unsigned int verdict;
int ret; do {
/* 调用钩子函数 */
verdict = nf_hook_entry_hookfn(entry, skb, state);
switch (verdict & NF_VERDICT_MASK) {
case NF_ACCEPT:
/* 获取下一个钩子函数 */
entry = rcu_dereference(entry->next);
break;
case NF_DROP:
/* 丢包 */
kfree_skb(skb);
ret = NF_DROP_GETERR(verdict);
if (ret == )
ret = -EPERM;
return ret;
case NF_QUEUE:
/* 通过netfilter_queue交给应用层nf_queue处理 */
ret = nf_queue(skb, state, &entry, verdict);
if (ret == && entry)
continue;
return ret;
default:
/* Implicit handling for NF_STOLEN, as well as any other
* non conventional verdicts.
*/
return ;
} /* 继续执行下一个钩子函数 */
} while (entry); return ;
}
nf_hook_entry_hookfn函数调用当前钩子函数结构entry中的钩子函数hook,返回执行结果;
static inline int
nf_hook_entry_hookfn(const struct nf_hook_entry *entry, struct sk_buff *skb,
struct nf_hook_state *state)
{
return entry->hook(entry->priv, skb, state);
}
我们暂且看一下filter表的钩子函数,可见,其核心流程为ipt_do_table,也就是进入filter表的规则匹配流程,ipt_do_table函数后续文章我们单独分析;
static unsigned int
iptable_filter_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
/* LOCAL_OUT && (数据长度不足ip头 || 实际ip头部长度不足最小ip头),在使用raw socket */
if (state->hook == NF_INET_LOCAL_OUT &&
(skb->len < sizeof(struct iphdr) ||
ip_hdrlen(skb) < sizeof(struct iphdr)))
/* root is playing with raw sockets. */
return NF_ACCEPT; /* 核心规则匹配流程 */
return ipt_do_table(skb, state, state->net->ipv4.iptable_filter);
}
Netfilter 之 钩子函数调用的更多相关文章
- netfilter的钩子——数据包在内核态得捕获、修改和转发
转发:http://blog.csdn.net/stonesharp/article/details/27091391 数据包在内核态得捕获.修改和转发(基于 netfilter) 忙活了好几天 ...
- Linux Netfilter注册钩子点
注册钩子点首先要包含响应的头文件,因为这应该已经属于对kernel的编程了. #include <linux/module.h> #include <linux/kernel.h&g ...
- Netfilter 之 钩子函数与钩子点关系图
概述 通过钩子点和优先级的代码追溯,得到如下对应关系图,图中横坐标为钩子点,纵坐标为优先级,每个钩子点上的钩子函数按照优先级排布: 详细分析 5个钩子点如下所示,在这个五个钩子点上的钩子函数按照上面的 ...
- Netfilter 之 钩子函数注册
通过注册流程代码的分析,能够明确钩子函数的注册流程,理解存储钩子函数的数据结构,如下图(点击图片可查看原图): 废话不多说,开始分析: nf_hook_ops是注册的钩子函数的核心结构,字段含义如下所 ...
- Netfilter的使用和实现
本文主要内容:Netfilter的原理和实现浅析,以及示例模块. 内核版本:2.6.37 Author:zhangskd @ csdn blog 概述 Netfilter为多种网络协议(IPv4.IP ...
- Linux内核project导论——网络:Netfilter概览
简单介绍 最早的内核包过滤机制是ipfwadm.后来是ipchains.再后来就是iptables/netfilter了. 再往后,也就是如今是nftables. 只是nftables与iptable ...
- Netfilter/iptables防火墙
http://os.51cto.com/art/201107/273443.htm [51CTO独家特稿]Linux系统管理员们都接触过Netfilter/iptables,这是Linux系统自带的免 ...
- c#调用钩子
1 概述 在c++中有钩子程序,但是在C#还没有对其进行封装,所以需要自己根据实际情况调用钩子.钩子在我的理解下是,通过初始化钩子与系统中消息映射建立某种关系,当点击鼠标或者键盘,就会通过钩子中的回调 ...
- Pytest权威教程19-编写钩子(Hooks)方法函数
目录 编写钩子(Hooks)函数 钩子函数验证和执行 firstresult: 遇到第一个有效(非None)结果返回 hookwrapper:在其他钩子函数周围执行 钩子(Hooks)函数排序/调用示 ...
随机推荐
- mysql5.7 密码字段名更改
由password更改为authentication_string update user set authentication_string=password("123456") ...
- 解决微信小程序Date.parse()获取时间戳IOS显示为NaN
ios系统不支持2018-03-29这样格式的时间导致出现的这个问题, IOS只识别2018/03/09这样的格式. 上正则 //之前的var data = '2018-03-09 12:00:00' ...
- 复选框已经有checked,但是页面没有选中效果(解决)
原代码: $("#checked").click(function(){ $(".input[name="checked"]").attr( ...
- Spring Cloud(十)高可用的分布式配置中心 Spring Cloud Config 中使用 Refresh
上一篇文章讲了SpringCloudConfig 集成Git仓库,配和 Eureka 注册中心一起使用,但是我们会发现,修改了Git仓库的配置后,需要重启服务,才可以得到最新的配置,这一篇我们尝试使用 ...
- Spring OAuth2 Could not decode JSON for additional information: BaseClientDetails
错误消息: 2019-10-08 14:48:16.703 WARN o.s.s.o.p.c.JdbcClientDetailsService : Could not decode JSON for ...
- MySQL安装步骤及环境变量配置
MySQL安装 MySQL下载地址:http://dev.mysql.com/downloads/installer/1:首先进入的是安装引导界面2:然后进入的是类型选择界面,这里有3个类型:Typi ...
- 在springmvc框架中,通过ajax请求,响应至前端的中文显示是?
今天遇到的一个问题,我通过ajax请求去访问控制器,然后通过控制器给我响应了一段json数据,但是里面的中文 在浏览上显示是??,我在web.xml 文件中是设置了编码过滤器的,但是估计这个编码过滤器 ...
- onload;readystatechange;DOMContentLoaded事件
当文档的 readyState 属性发生改变时,会触发 readystatechange 事件. onload 事件会在页面或图像加载完成后立即发生 当纯HTML被完全加载以及解析时,DOMConte ...
- 详解mpstat等性能监测命令的使用
mpstat是Multiprocessor Statistics的缩写,是实时监控工具,报告与cpu的一些统计信息这些信息都存在/proc/stat文件中,在多CPU系统里,其不但能查看所有的CPU的 ...
- JavaScript教程——数据类型概述
简介 JavaScript 语言的每一个值,都属于某一种数据类型.JavaScript 的数据类型,共有六种.(ES6 又新增了第七种 Symbol 类型的值,本教程不涉及.) 数值(number): ...