415 lines
11 KiB
C
415 lines
11 KiB
C
#include <linux/module.h>
|
||
#include <linux/netlink.h>
|
||
#include <linux/netfilter.h>
|
||
#include <linux/ip.h>
|
||
#include <uapi/linux/netfilter_ipv4.h>
|
||
#include <uapi/linux/ip.h>
|
||
#include <net/netlink.h>
|
||
#include <net/net_namespace.h>
|
||
#include <net/netfilter/nf_conntrack_acct.h>
|
||
#include <linux/inet.h>
|
||
|
||
#include "../netlink_api/libnetlink_k.h"
|
||
#include "../../../Common/commuapinl.h"
|
||
//#include "pdeliverynl_kinit.h"
|
||
#include "../conntrack_api/api/conntrack_api.h"
|
||
|
||
//int nf_nlmsg_multicast(struct netlinkk_cfg *g_nlcfg, struct sk_buff *skb);
|
||
unsigned int pdelivery_hook_func(void *priv,
|
||
struct sk_buff *skb,
|
||
const struct nf_hook_state *state);
|
||
//int debugfs_pkt_num_stati(struct netlinkk_cfg *g_nlcfg, struct nlmsghdr *nlh);
|
||
|
||
int pdeliv_unicast(struct sk_buff *skb, u32 portid);
|
||
int pde_pkt_control(struct sk_buff *skb, struct netlinkk_cfg *g_nlcfg);
|
||
|
||
|
||
struct netlinkk_cfg g_nlcfg = {0};
|
||
|
||
|
||
static struct nf_hook_ops upm_nfho = {
|
||
.hook = pdelivery_hook_func,
|
||
.hooknum = 1, /* should be NF_IP_FORWARD,use NF_IP_LOCAL_IN=1 for test */
|
||
.pf = PF_INET,
|
||
.priority = NF_IP_PRI_FILTER,
|
||
};
|
||
|
||
struct commnl_msgtype_process pdelivnl_msg_handlers[NLMGS_PDELIVERY_MAX_TYPE];
|
||
|
||
|
||
int pdeliv_rcv_stat(struct sk_buff *skb, struct nlmsghdr *nlh,struct netlink_ext_ack * ext_ack)
|
||
{
|
||
int ret = 0;
|
||
|
||
/**************************************************************************************************************/
|
||
|
||
switch(nlh->nlmsg_type)
|
||
{
|
||
//case COMMNMSG_POLICYCONF:/**/
|
||
case NLMSG_PDELIV_DEBUGFS:
|
||
|
||
#ifdef NLDEBUG_ACK_COOKIES
|
||
ret = debugfs_pkt_num_stati(&g_nlcfg, nlh, ext_ack);
|
||
#else
|
||
ret = debugfs_pkt_num_stati_witisend(&g_nlcfg, nlh,pdelivnl_msg_handlers);
|
||
#endif
|
||
NETLINK_DEBUG(g_nlcfg.debugfs_prk_enable, "*****************biduichengong********%d*******\n", nlh->nlmsg_type);
|
||
return ret;
|
||
break;
|
||
case NK_DEBUGFS_PRK_ONOFF:
|
||
ret = debugfs_prk_onoff(&g_nlcfg, nlh, ext_ack);
|
||
return ret;
|
||
break;
|
||
|
||
case PKT_PDE_THR:
|
||
ret = set_pde_pkt_num(&g_nlcfg, nlh, ext_ack);
|
||
return ret;
|
||
break;
|
||
|
||
|
||
default:
|
||
NETLINK_DEBUG(g_nlcfg.debugfs_prk_enable, "libnetlink Unknow msgtype recieved!\n");
|
||
return 0;
|
||
}
|
||
/**************************************************************************************************************/
|
||
|
||
return 0;
|
||
}
|
||
|
||
int nl_pdeliv_data_ready(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack)
|
||
{
|
||
int ret = 0;
|
||
|
||
NETLINK_DEBUG(g_nlcfg.debugfs_prk_enable, "nl_pdeliv_data_ready() nlmsg_type = %d begin.\n",nlh->nlmsg_type);
|
||
g_nlcfg.dfs.rev_total++;
|
||
|
||
if(NULL != pdelivnl_msg_handlers[nlh->nlmsg_type].doit)
|
||
{
|
||
pdelivnl_msg_handlers[nlh->nlmsg_type].dfs.rev_total++;
|
||
ret = pdelivnl_msg_handlers[nlh->nlmsg_type].doit(skb, nlh,extack);
|
||
if(ret >= 0)
|
||
{
|
||
g_nlcfg.dfs.rev_cb_sucess++;
|
||
pdelivnl_msg_handlers[nlh->nlmsg_type].dfs.rev_cb_sucess++;
|
||
}
|
||
else
|
||
{
|
||
g_nlcfg.dfs.rev_cb_fail++;
|
||
pdelivnl_msg_handlers[nlh->nlmsg_type].dfs.rev_cb_fail++;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
pdelivnl_msg_handlers[nlh->nlmsg_type].dfs.rev_drop_total++;
|
||
pdelivnl_msg_handlers[nlh->nlmsg_type].dfs.rev_drop_nodoit++;
|
||
g_nlcfg.dfs.rev_drop_total++;
|
||
g_nlcfg.dfs.rev_drop_nodoit++;
|
||
|
||
NETLINK_DEBUG(g_nlcfg.debugfs_prk_enable, "no doit fun register with nlmsg_type = %d .\n",nlh->nlmsg_type);
|
||
}
|
||
|
||
NETLINK_DEBUG(g_nlcfg.debugfs_prk_enable, "nl_pdeliv_data_ready() nlmsg_type = %d end.\n",nlh->nlmsg_type);
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
static void libpdelivnl_rcv(struct sk_buff *skb)
|
||
{
|
||
NETLINK_DEBUG(g_nlcfg.debugfs_prk_enable, "libpdelivnl_rcv:\n");
|
||
|
||
netlink_rcv_skb(skb, &nl_pdeliv_data_ready);
|
||
|
||
}
|
||
|
||
int pdeliv_msgtype_register( int msgtype,commnl_doit_func doit,
|
||
commnl_dumpit_func dumpit,commnl_calcit_func calcit)
|
||
{
|
||
if(msgtype >= NLMGS_PDELIVERY_MAX_TYPE )
|
||
{
|
||
printk(KERN_ERR"netlink.ko-msgtype register invalid msgtype %d,protocl pdeliv.\r\n",msgtype);
|
||
return -1;
|
||
}
|
||
|
||
commnl_register(pdelivnl_msg_handlers, msgtype,doit, dumpit,calcit);
|
||
|
||
printk(KERN_INFO"netlink.ko-msgtype register sucess msgtype %d,protocl comcfg.\r\n",msgtype);
|
||
|
||
return 0;
|
||
}
|
||
|
||
int pdeliv_msgtype_unregister(int msgtype)
|
||
{
|
||
if(msgtype >= NETLINK_PDELIVERY )
|
||
{
|
||
printk(KERN_ERR"commnl_unregister invalid msgtype %d,protocl conncfg.\r\n",msgtype);
|
||
return -1;
|
||
}
|
||
|
||
commnl_unregister(pdelivnl_msg_handlers,msgtype);
|
||
|
||
printk(KERN_DEBUG"commnl_unregister sucess msgtype %d,protocl pdeliv.\r\n",msgtype);
|
||
|
||
return 0;
|
||
}
|
||
|
||
int __init pdelivery_init(void)
|
||
{
|
||
int ret = -1;
|
||
|
||
printk(KERN_CRIT "pdeliv initialed!\n");
|
||
|
||
g_nlcfg.msg_processer = &(pdelivnl_msg_handlers[0]);
|
||
g_nlcfg.msg_processer_num = NLMGS_PDELIVERY_MAX_TYPE;
|
||
|
||
/*init for pdelivery module*/
|
||
g_nlcfg.groups = PDELIVERY_NLGRP_MAX;
|
||
g_nlcfg.subscriptions = NETLINK_PDELIVERY;
|
||
g_nlcfg.cfg.input = libpdelivnl_rcv;
|
||
|
||
|
||
ret = libnetlinkk_init_byproto(&g_nlcfg);
|
||
if(ret < 0)
|
||
{
|
||
printk (KERN_CRIT "pdelivery_init netlink init fail!.\n");
|
||
return ret;
|
||
}
|
||
|
||
/*init the netfilter hook for upm*/
|
||
printk (KERN_INFO "pdeliv register netfilter module.\n");
|
||
nf_register_net_hook (&init_net,&upm_nfho);
|
||
|
||
/*do msg process register*/
|
||
pdeliv_msgtype_register(PDNLGRP_REQUEST,pdeliv_rcv_stat,NULL,NULL);
|
||
pdeliv_msgtype_register(NLMSG_PDELIV_DEBUGFS,pdeliv_rcv_stat,NULL,NULL);
|
||
pdeliv_msgtype_register(NK_DEBUGFS_PRK_ONOFF,pdeliv_rcv_stat,NULL,NULL);
|
||
pdeliv_msgtype_register(PKT_PDE_THR,pdeliv_rcv_stat,NULL,NULL);
|
||
|
||
|
||
return 0;
|
||
}
|
||
|
||
void __exit pdelivery_exit(void)
|
||
{
|
||
printk(KERN_CRIT "pdeliv exit\n");
|
||
libnetlinkk_exit(&g_nlcfg);
|
||
|
||
/*init the netfilter hook for upm*/
|
||
printk (KERN_INFO "pdeliv unregister netfilter module.\n");
|
||
nf_unregister_net_hook (&init_net,&upm_nfho);
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
/****************************************************************/
|
||
/*函数功能:pdelivery模块注册的netfilter钩子回调函数,用于从 */
|
||
/*netfilter框架接收到报文,然后调用netlink发送接口将报文上送到*/
|
||
/*用户态。报文内容从链路层头开始。 */
|
||
/*输入参数:priv:优先级;skb 报文;state:netfilter钩子状态。 */
|
||
/*输出参数: 无*/
|
||
/*返回值:固定返回NF_ACCEPT表示放行报文。 */
|
||
/****************************************************************/
|
||
unsigned int pdelivery_hook_func(void *priv,
|
||
struct sk_buff *skb,
|
||
const struct nf_hook_state *state)
|
||
{
|
||
void *payload;
|
||
struct sk_buff *out_skb;
|
||
void *out_payload;
|
||
struct nlmsghdr *out_nlh;
|
||
int payload_len; // with padding, but ok for echo
|
||
//struct iphdr *iph;
|
||
int ret = -1;
|
||
|
||
#if 0
|
||
iph = ip_hdr(skb);
|
||
printk(KERN_INFO "pdelivery_hook_func:pktlen=%d,mac_header = %d IP:",skb->len,skb->mac_len);
|
||
printk_ipaddress(iph->saddr);
|
||
printk(KERN_INFO "-->");
|
||
printk_ipaddress(iph->daddr);
|
||
#endif
|
||
|
||
ret = pde_pkt_control(skb, &g_nlcfg);
|
||
if(ret == PDE_TO_ACCEPT)
|
||
return NF_ACCEPT;
|
||
|
||
if(!netlink_has_listeners(g_nlcfg.sk, PDNLGRP_ALLRAW))
|
||
{
|
||
goto out;
|
||
}
|
||
|
||
//printk("***************************************in_pde_dpi****************************\n");
|
||
payload = skb_mac_header(skb);
|
||
payload_len = skb->len + skb->mac_len;/**/
|
||
|
||
|
||
out_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); //分配足以存放默认大小的sk_buff
|
||
if (!out_skb)
|
||
{
|
||
goto failure;
|
||
}
|
||
|
||
out_nlh = nlmsg_put(out_skb, 0, 0, NLMSG_RECV_RAW_PKT, payload_len, 0); //payload_len is the user data total len填充协议头数据
|
||
if (!out_nlh)
|
||
{
|
||
goto failure;
|
||
}
|
||
|
||
out_payload = nlmsg_data(out_nlh);
|
||
memcpy(out_payload, payload,payload_len);/**/
|
||
|
||
/*example:use nla_put to add other attr here. ***********************************/
|
||
/*int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data);*/
|
||
/********************************************************************************/
|
||
|
||
#if 0
|
||
printk(KERN_DEBUG "%02x %02x %02x %02x %02x %02x %02x %02x\r\n",
|
||
*((char*)out_payload),*((char*)out_payload+1),
|
||
*((char*)out_payload+2),*((char*)out_payload+3),
|
||
*((char*)out_payload+4),*((char*)out_payload+5),
|
||
*((char*)out_payload+6),*((char*)out_payload+7));
|
||
#endif
|
||
|
||
ret = nf_nlmsg_multicast(&g_nlcfg, out_skb);
|
||
if(ret < 0)
|
||
{
|
||
g_nlcfg.dfs.send_fail_reason = ret;
|
||
goto out;
|
||
}
|
||
|
||
//printk(KERN_INFO "pdelivery_hook_func() end.\n");
|
||
g_nlcfg.dfs.send_succ ++;
|
||
g_nlcfg.msg_processer[NLMSG_RECV_RAW_PKT].dfs.send_succ++;
|
||
|
||
return NF_ACCEPT;/*must return a value*/
|
||
|
||
failure:
|
||
if(out_skb != NULL)
|
||
{
|
||
kfree_skb(out_skb);
|
||
}
|
||
out:
|
||
|
||
//printk(KERN_INFO " failed in pdelivery_hook_func!\n");
|
||
g_nlcfg.dfs.send_fail ++;
|
||
g_nlcfg.msg_processer[NLMSG_RECV_RAW_PKT].dfs.send_fail++;
|
||
|
||
return NF_ACCEPT;/*must return a value*/
|
||
}
|
||
|
||
|
||
int pdeliv_unicast(struct sk_buff *skb, u32 portid)
|
||
{
|
||
int ret = -1;
|
||
struct nlmsghdr *nlh = NULL;
|
||
int msgtype = 0;
|
||
|
||
ret = commnl_unicast(g_nlcfg.sk, skb, portid);
|
||
/*
|
||
if(ret < 0)
|
||
{
|
||
g_nlcfg.dfs.send_fail++;
|
||
g_nlcfg.dfs.send_fail_reason = ret;
|
||
}
|
||
else
|
||
{
|
||
g_nlcfg.dfs.send_succ++;
|
||
}
|
||
|
||
|
||
nlh = (struct nlmsghdr *)skb->head;
|
||
msgtype = nlh->nlmsg_type;
|
||
if((msgtype > NLMGS_PDELIVERY_MAX_TYPE ) || (msgtype <= PDNL_BASE))
|
||
{
|
||
printk(KERN_ERR "pdeliv_unicast:msg type invalid.\r\n");
|
||
}
|
||
else
|
||
{
|
||
//printk(KERN_DEBUG "pdeliv_unicast:msg type %d.\r\n",msgtype);
|
||
if(ret < 0)
|
||
{
|
||
pdelivnl_msg_handlers[msgtype].dfs.send_fail++;
|
||
}
|
||
else
|
||
{
|
||
pdelivnl_msg_handlers[msgtype].dfs.send_succ++;
|
||
}
|
||
}
|
||
*/
|
||
|
||
return(ret);
|
||
}
|
||
|
||
int pde_pkt_control(struct sk_buff *skb, struct netlinkk_cfg *g_nlcfg)
|
||
{
|
||
u_int32_t action;
|
||
int ret=0;
|
||
enum ip_conntrack_info ctinfo = {0};
|
||
struct nf_conn *ct = NULL;
|
||
struct nf_conn_acct *acct = NULL;
|
||
long long pd_num_original;
|
||
long long pd_num_reply;
|
||
long long num_max;
|
||
long long total_pkt;
|
||
|
||
ret = cmhi_get_conntrack_u32(skb, &action, ACTION);
|
||
if(ret)
|
||
{
|
||
printk("***********cmhi_get_conntrack_u32-error***************\n");
|
||
}
|
||
|
||
if(action != CONNTRACK_PDE_DPI)
|
||
{
|
||
return PDE_TO_ACCEPT;
|
||
}
|
||
|
||
if(g_nlcfg->pde_pkt_num == 0)
|
||
num_max = 50;
|
||
else
|
||
num_max = g_nlcfg->pde_pkt_num;
|
||
|
||
ct = nf_ct_get(skb, &ctinfo);
|
||
acct = nf_conn_acct_find(ct);
|
||
if(acct)
|
||
{
|
||
struct nf_conn_counter *counter = acct->counter;
|
||
pd_num_original = atomic64_read(&counter[IP_CT_DIR_ORIGINAL].packets);
|
||
pd_num_reply = atomic64_read(&counter[IP_CT_DIR_REPLY].packets);
|
||
total_pkt = pd_num_original + pd_num_reply;
|
||
}
|
||
|
||
if((action == CONNTRACK_PDE_DPI) && (total_pkt > num_max))
|
||
{
|
||
return PDE_TO_ACCEPT;
|
||
}
|
||
|
||
return PDE_TO_DPI;
|
||
}
|
||
|
||
|
||
EXPORT_SYMBOL_GPL(pdeliv_msgtype_register);
|
||
EXPORT_SYMBOL_GPL(pdeliv_msgtype_unregister);
|
||
EXPORT_SYMBOL_GPL(pdeliv_unicast);
|
||
|
||
|
||
module_init(pdelivery_init);
|
||
module_exit(pdelivery_exit);
|
||
|
||
MODULE_LICENSE("GPL");
|
||
MODULE_DESCRIPTION("a simple example for upm(user policy manage) netlink protocal family");
|
||
MODULE_AUTHOR("RSLjdkt");
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|