#include #include #include #include #include #include #include #include #include "usercfg_kinit.h" #include "../../../../../Common/commuapinl.h" #include #define NLMSG_TAIL(nmsg) \ ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len)) #define RTA_ALIGNTO 4U #define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) ) struct netlinkk_cfg g_upmnlcfg; struct commnl_msgtype_process cfgnl_msg_handlers[COMMCFG_NLMSG_MAX_TYPE]; /*全局变量,存放免认证规则信息,目前只考虑放一条免认证规则,以结构体形式存放,后期考虑链表存放 */ freeauth_configure_t * kfreeauth; /*全局变量,存放配置的用户老化时间 */ int *kaging_time = NULL; int nl_cfg_data_ready(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) { int ret = 0; printk(KERN_DEBUG "nl_cfg_data_ready() nlmsg_type = %d begin.\n",nlh->nlmsg_type); g_upmnlcfg.dfs.rev_total++; if(NULL != cfgnl_msg_handlers[nlh->nlmsg_type].doit) { cfgnl_msg_handlers[nlh->nlmsg_type].dfs.rev_total++; ret = cfgnl_msg_handlers[nlh->nlmsg_type].doit(skb, nlh,extack); if(ret >= 0) { g_upmnlcfg.dfs.rev_cb_sucess++; cfgnl_msg_handlers[nlh->nlmsg_type].dfs.rev_cb_sucess++; } else { g_upmnlcfg.dfs.rev_cb_fail++; cfgnl_msg_handlers[nlh->nlmsg_type].dfs.rev_cb_fail++; } } else { cfgnl_msg_handlers[nlh->nlmsg_type].dfs.rev_drop_total++; cfgnl_msg_handlers[nlh->nlmsg_type].dfs.rev_drop_nodoit++; g_upmnlcfg.dfs.rev_drop_total++; g_upmnlcfg.dfs.rev_drop_nodoit++; printk(KERN_WARNING "no doit fun register with nlmsg_type = %d .\n",nlh->nlmsg_type); } printk(KERN_DEBUG "nl_cfg_data_ready() nlmsg_type = %d end.\n",nlh->nlmsg_type); return ret; } static void libcfgnl_rcv(struct sk_buff *skb) { printk(KERN_DEBUG "libcfgnl_rcv:\n"); netlink_rcv_skb(skb, &nl_cfg_data_ready); } /*单播,内核态发送给用户态 */ int cfgnl_unicast(struct sk_buff *skb, u32 portid) { int ret = -1; struct nlmsghdr *nlh = NULL; int msgtype = 0; /** * nlmsg_unicast - unicast a netlink message * @sk: netlink socket to spread message to * @skb: netlink message as socket buffer * @portid: netlink portid of the destination socket */ ret = commnl_unicast(g_upmnlcfg.sk, skb, portid); if(ret < 0) { g_upmnlcfg.dfs.send_fail++; g_upmnlcfg.dfs.send_fail_reason = ret; } else { g_upmnlcfg.dfs.send_succ++; } nlh = (struct nlmsghdr *)skb->head; msgtype = nlh->nlmsg_type; if(msgtype > COMMCFG_NLMSG_MAX_TYPE) { printk(KERN_ERR "cfg_unicast:msg type invalid.\r\n"); } else { printk(KERN_DEBUG "cfg_unicast:msg type %d.\r\n",msgtype); if(ret < 0) { cfgnl_msg_handlers[msgtype].dfs.send_fail++; } else { cfgnl_msg_handlers[msgtype].dfs.send_succ++; } } return(ret); } /*免认证规则配置的功能函数,解析出配置信息,存全局变量*/ int usercfg_freeauth(struct sk_buff *skb, struct nlmsghdr *nlh,struct netlink_ext_ack *extack) { char *pload; struct nlattr *rta; char *load; /** * nlmsg_data - head of message payload * @nlh: netlink message header */ pload = nlmsg_data(nlh); rta = (struct nlattr *)pload; load = RTA_DATA(rta); kfreeauth = (freeauth_configure_t *)load; printk("name:%s sip:%d\n", kfreeauth->name, kfreeauth->sip); printk("dip:%d dport:%d\n", kfreeauth->dip, kfreeauth->dport); return 0; } /*用户老化时间配置的功能函数,解析出配置信息,存全局变量 */ int usercfg_agingtime(struct sk_buff *skb, struct nlmsghdr *nlh,struct netlink_ext_ack *extack) { char *pload; struct nlattr *rta; char *load; pload = nlmsg_data(nlh); rta = (struct nlattr *)pload; load = RTA_DATA(rta); kaging_time = (int *)load; printk("agingtime: %d\n", *kaging_time); return 0; } int cfg_msgtype_register( int msgtype,commnl_doit_func doit, commnl_dumpit_func dumpit,commnl_calcit_func calcit) { if(msgtype >= COMMCFG_NLMSG_MAX_TYPE ) { printk(KERN_ERR"netlink.ko-msgtype register invalid msgtype %d,protocl comcfg.\r\n",msgtype); return -1; } /*函数功能:注册内核态配置接收消息处理函数。 */ /*输入参数: */ /*msgtype:注册的消息类型。*/ /*doit:对应的消息接收处理函数;*/ /*dumpit,calcit:框架预留接口,暂未使用。填NULL.*/ /*输出参数: WU */ /*返回值:0注册成功;< 0,失败*/ commnl_register(cfgnl_msg_handlers, msgtype, doit, dumpit, calcit); printk(KERN_INFO"netlink.ko-msgtype register sucess msgtype %d,protocl comcfg.\r\n",msgtype); return 0; } /*commcfgmsgtype:FREEAUTH_CFG = 0x13, 用户态发送给内核态的免认证规则消息*/ /*AGINGTIME_CFG = 0x14, 用户态发送给内核态的用户老化时间消息 */ int __init usercfgrcv_init(void) { int ret = -1; printk(KERN_INFO "usercfgrcv.ko-initialed\n"); g_upmnlcfg.msg_processer = &(cfgnl_msg_handlers[0]); g_upmnlcfg.msg_processer_num = COMMCFG_NLMSG_MAX_TYPE; /*init for usercfg module */ g_upmnlcfg.groups = 0; g_upmnlcfg.subscriptions = NETLINK_COMMCFG; /*创建配置处理通道 */ g_upmnlcfg.cfg.input = libcfgnl_rcv; /*函数功能:在内核态创建报文上送通道,上送的 */ /*报文内容从链路层头开始。一个netlink协议号只能创建一个通道。 */ /*输入参数:g_nlcfg */ /*输出参数: wu */ /*返回值:0通道创建成果;< 0,失败 */ ret = libnetlinkk_init_byproto(&g_upmnlcfg); if(ret < 0) { return ret; } /*do msg process register */ ret = cfg_msgtype_register(FREEAUTH_CFG, usercfg_freeauth, NULL, NULL); ret = cfg_msgtype_register(AGINGTIME_CFG, usercfg_agingtime, NULL, NULL); return ret; } void __exit usercfgrcv_exit(void) { printk(KERN_CRIT "nl_upm existing...\n"); libnetlinkk_exit(&g_upmnlcfg); } EXPORT_SYMBOL_GPL(cfgnl_unicast); EXPORT_SYMBOL_GPL(cfg_msgtype_register); module_init(usercfgrcv_init); module_exit(usercfgrcv_exit);