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