#include #include #include #include #include #include #include #include #include #include #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);