secgateway/Platform/modules/pdelivery/pdeliverynl_kinit.c

415 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 报文statenetfilter钩子状态。 */
/*输出参数: 无*/
/*返回值固定返回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");