149 lines
3.6 KiB
C
149 lines
3.6 KiB
C
#include <linux/kernel.h>
|
||
#include <linux/skbuff.h>
|
||
#include <linux/module.h>
|
||
#include <linux/if.h>
|
||
#include <linux/netdevice.h>
|
||
#include <linux/inetdevice.h>
|
||
#include <linux/rcupdate.h>
|
||
#include <net/net_namespace.h>
|
||
#include <linux/list.h>
|
||
#include <linux/netdevice.h>
|
||
#include "lkh_hook.h"
|
||
|
||
|
||
#define LKH_VERDICT_MASK 0x000000ff
|
||
#define LKH_VERDICT_QBITS 16
|
||
|
||
static inline int LKH_DROP_GETERR(int verdict)
|
||
{
|
||
return -(verdict >> LKH_VERDICT_QBITS);
|
||
}
|
||
|
||
static inline int lkh_hook_entry_hookfn(const struct lkh_hook_entry *entry, struct sk_buff *skb, struct lkh_hook_state *state)
|
||
{
|
||
return entry->hook(entry->priv, skb, state);
|
||
}
|
||
|
||
static inline void lkh_hook_state_init(struct lkh_hook_state *p,
|
||
unsigned int hook,
|
||
u_int8_t pf,
|
||
struct net_device *indev,
|
||
struct net_device *outdev,
|
||
struct sock *sk,
|
||
struct net *net)
|
||
{
|
||
p->hook_stage = hook;
|
||
p->pf = pf;
|
||
p->in = indev;
|
||
p->out = outdev;
|
||
p->sk = sk;
|
||
p->net = net;
|
||
}
|
||
|
||
int lkh_hook_slow(struct sk_buff *skb, struct lkh_hook_state *state,
|
||
const struct lkh_hook_entries *e, unsigned int s)
|
||
{
|
||
unsigned int verdict;
|
||
int ret;
|
||
|
||
for (; s < e->num_hook_entries; s++)
|
||
{
|
||
verdict = lkh_hook_entry_hookfn(&e->hooks[s], skb, state);
|
||
|
||
switch (verdict & LKH_VERDICT_MASK)
|
||
{
|
||
case LKH_ACCEPT:
|
||
break;
|
||
case LKH_DROP:
|
||
kfree_skb(skb);
|
||
ret = LKH_DROP_GETERR(verdict);
|
||
if (ret == 0)
|
||
{
|
||
ret = -EPERM;
|
||
}
|
||
return ret;
|
||
default:
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
/*********************************************************************************
|
||
* Description:
|
||
* 转发流程调用钩子函数的处理报文的入口函数
|
||
* Input:
|
||
* pf - 优先级
|
||
* hook_stage - 钩子函数调用阶段
|
||
* sk - socket
|
||
* skb - 报文描述符
|
||
* indev - 入设备信息
|
||
* outdev - 出设备信息
|
||
* Output:
|
||
* 无
|
||
* Return:
|
||
* 无
|
||
* Others:
|
||
* 入口参数的定义和使用方法同netfilter一样
|
||
**********************************************************************************/
|
||
int lkh_hook(u_int8_t pf,
|
||
unsigned int hook_stage,
|
||
struct net *net,
|
||
struct sock *sk,
|
||
struct sk_buff *skb,
|
||
struct net_device *indev,
|
||
struct net_device *outdev)
|
||
{
|
||
struct lkh_hook_entries * hook_entrise;
|
||
int ret = 1;
|
||
bool find_flag = false;
|
||
struct lkh_hook * hook_head;
|
||
|
||
/* 查找对应网络空间的hook结构 */
|
||
list_for_each_entry(hook_head, &g_lkh_hook_handle.list, list)
|
||
{
|
||
if (hook_head->net_ptr == net)
|
||
{
|
||
find_flag = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!find_flag)
|
||
{
|
||
return ret;
|
||
}
|
||
|
||
rcu_read_lock();
|
||
|
||
switch (pf)
|
||
{
|
||
case LKH_PROTO_IPV4:
|
||
hook_entrise = rcu_dereference(hook_head->hooks_ipv4[hook_stage]);
|
||
break;
|
||
case LKH_PROTO_IPV6:
|
||
hook_entrise = rcu_dereference(hook_head->hooks_ipv6[hook_stage]);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (hook_entrise != NULL)
|
||
{
|
||
struct lkh_hook_state state;
|
||
|
||
lkh_hook_state_init(&state, hook_stage, pf, indev, outdev, sk, net);
|
||
|
||
ret = lkh_hook_slow(skb, &state, hook_entrise, 0);
|
||
}
|
||
|
||
rcu_read_unlock();
|
||
|
||
return ret;
|
||
}
|
||
|
||
EXPORT_SYMBOL(lkh_hook);
|
||
|
||
|