- 论坛徽章:
- 0
|
我现在遇到一个非常奇怪的问题,应用程序向内核发送消息时,内核能够正确获取到消息,记录下应用程序的pid。之后,内核在特定情况下,需要向应用层发包时,应用层却始终收不到包(应用层的recvmsg没有任何响应)。奇怪的是,如果手动起应用程序,就能够正确收到内核发来的数据包。有谁遇到过类似的问题吗?请教了!
#include <linux/init.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/time.h>
#include <linux/delay.h>
#include <linux/types.h>
#include <net/sock.h>
#include <linux/skbuff.h>
#include <linux/autoconf.h>
#include <linux/ip.h>
#include <net/netlink.h>
#include <linux/netfilter_ipv4/ip_hash.h>
#include <uapi/linux/internet_ctrl_netlink.h>
#define DEBUG_IP_HASH 1
#if DEBUG_IP_HASH
#define DEBUG_PRINT(fmt, argx...) printk(fmt, ##argx)
#else
#define DEBUG_PRINT(fmt, argx...)
#endif
#define ip_hash_key(ipaddr) ((ipaddr & 0xffu) ^ ((ipaddr >> 8u) & 0xffu))
#define IP_HASH_TIMEOUT_INTERVAL 60*HZ
u_int phicommUsrPid = 0;
static struct sock *nl_sk = NULL;
IPHashNode *ip_hash_table[MAX_IP_HASH_TABLE];
static struct timer_list ip_hash_timer;
static void ip_hash_timeout(u_long param);
static void ip_hash_poll_init(void);
static int NlSend(char *data, u_int dataLen, u_int dpid, u_int dgrp)
{
struct sk_buff *skb;
struct nlmsghdr *nlh;
int err = 0;
DEBUG_PRINT("#######func:%s,line:%d phicommUsrPid=%u#####\n",__func__,__LINE__,phicommUsrPid);
#if 0
int nlLen = NLMSG_SPACE(dataLen);
skb = alloc_skb(nlLen,GFP_ATOMIC);
#else
skb = nlmsg_new(dataLen, GFP_ATOMIC);
#endif
if(skb)
{
nlh = nlmsg_put(skb,0,0,0,dataLen,0);
NETLINK_CB(skb).dst_group = dgrp;
memcpy(NLMSG_DATA(nlh), data, dataLen);
if(dgrp != 0)
{
netlink_broadcast(nl_sk, skb, 0, dgrp, GFP_ATOMIC);
}
else
{
err = netlink_unicast(nl_sk,skb,dpid,MSG_DONTWAIT);
DEBUG_PRINT("#######func:%s,line:%d err=%d####\n",__func__,__LINE__,err);
}
}
else
{
err = -1;
}
return err;
}
static void netlinkSendToUser(IPHashNode *ipHashNode,NetlinkConfType confType)
{
NlMsg nlData;
nlData.msgHead.nlType = INTERNET_CTRL_INFO;
nlData.confType = confType;
memcpy(nlData.mac, ipHashNode->conf.userStats.mac, ETH_ALEN);
nlData.ip = ipHashNode->ip;
DEBUG_PRINT("#######func:%s,line:%d phicommUsrPid=%u#####\n",__func__,__LINE__,phicommUsrPid);
if (phicommUsrPid > 0) {
NlSend((char *)&nlData, sizeof(nlData), phicommUsrPid, 0);
}
}
static void ip_hash_timeout(u_long param)
{
int i = 0;
IPHashNode **hashBufPP = NULL;
IPHashNode *hashBufP = NULL;
for (i = 0; i < MAX_IP_HASH_TABLE; i++) {
hashBufPP = &(ip_hash_table[i]);
while (*hashBufPP != NULL) {
if ((*hashBufPP)->status == 0) {
DEBUG_PRINT("%s %08x:timeout hash %08x\n", __func__, __LINE__, (*hashBufPP)->ip);
hashBufP = *hashBufPP;
/*ip hash节点超时时,向应用层发送离线消息*/
netlinkSendToUser(*hashBufPP,IP_OFFLINE);
*hashBufPP = hashBufP->next;
kfree(hashBufP);
} else {
(*hashBufPP)->status = 0;
hashBufPP = &((*hashBufPP)->next);
}
}
}
mod_timer(&ip_hash_timer, jiffies + IP_HASH_TIMEOUT_INTERVAL);
}
static void ip_hash_poll_init(void)
{
init_timer(&ip_hash_timer);
ip_hash_timer.expires = jiffies + IP_HASH_TIMEOUT_INTERVAL;
ip_hash_timer.data = 0;
ip_hash_timer.function = ip_hash_timeout;
add_timer(&ip_hash_timer);
}
IPHashNode *get_ip_hash_node (u_long ipaddr, int isCreat, struct sk_buff *skb)
{
u_int key;
struct timespec uptime;
IPHashNode **hashBufPP;
struct ethhdr *eth;
key = ip_hash_key(ntohl(ipaddr));
hashBufPP = &(ip_hash_table[key]);
//DEBUG_PRINT("%s %d:hash key %d\n", __func__, __LINE__, key);
while (*hashBufPP != NULL) {
if ((*hashBufPP)->ip == ipaddr) {
if(isCreat == 1) {
isCreat = 0;
(*hashBufPP)->status = 1;
}
//DEBUG_PRINT("%s %d:find ok hash %pI4, key %d\n", __func__, __LINE__, &ipaddr,key);
break;
}
hashBufPP = &((*hashBufPP)->next);
}
if (isCreat == 1) {
*hashBufPP = (IPHashNode*) kzalloc(sizeof(IPHashNode), GFP_ATOMIC);
if (*hashBufPP != NULL) {
(*hashBufPP)->status = 1;
(*hashBufPP)->ip = ipaddr;
(*hashBufPP)->conf.iif = -1;
do_posix_clock_monotonic_gettime(&uptime);
monotonic_to_bootbased(&uptime);
(*hashBufPP)->conf.userStats.stTime = (u_long)( uptime.tv_sec);
(*hashBufPP)->conf.userStats.realtimeflowS.lastClrJiffies = jiffies;
//DEBUG_PRINT("%s %d:new hash %pI4, key %d\n", __func__, __LINE__, &ipaddr,key);
eth = eth_hdr(skb);
if (((unsigned char *)eth) + ETH_HLEN <= skb->data) {
DEBUG_PRINT("eth get right!\n");
memcpy((*hashBufPP)->conf.userStats.mac, eth->h_source, ETH_ALEN);
/*ip hash结点建立时,向应用层发送消息*/
netlinkSendToUser(*hashBufPP,IP_ONLINE);
} else {
DEBUG_PRINT("eth get error!\n");
memset((*hashBufPP)->conf.userStats.mac, 0, ETH_ALEN);
}
}
}
return *hashBufPP;
}
void ip_hash_traverse (void (*processFun)(IPHashNode* buf))
{
int i = 0;
IPHashNode *hashBufP = NULL;
for(i = 0; i < MAX_IP_HASH_TABLE; i++) {
hashBufP = ip_hash_table[i];
while (hashBufP != NULL) {
processFun(hashBufP);
hashBufP = hashBufP->next;
}
}
}
void internet_ctrl_conf (struct nlmsghdr *nlh)
{
NlMsg *nlData;
nlData = (NlMsg *)NLMSG_DATA(nlh);
IPHashNode *hashBufP = NULL;
int i = 0;
DEBUG_PRINT("%d in %s of %s\n", __LINE__, __func__, __FILE__);
switch (nlData->confType) {
case INIT_UNICAST_PID:
phicommUsrPid = nlh->nlmsg_pid;
DEBUG_PRINT("#######%d in %s of %s, phicommUsrPid=%d#######\n", __LINE__, __func__, __FILE__,phicommUsrPid);
break;
default:
break;
}
}
static int phicomm_user_rcv_msg (struct sk_buff *skb, struct nlmsghdr *nlh)
{
NetlinkMsgHead *msgHead = NULL;
DEBUG_PRINT("%d in %s of %s\n", __LINE__, __func__, __FILE__);
if (skb->len < sizeof(*nlh)) {
return 1;
}
msgHead = (NetlinkMsgHead*)NLMSG_DATA(nlh);
DEBUG_PRINT("%d in %s of %s, Message receive\n", __LINE__, __func__, __FILE__);
switch(msgHead->nlType)
{
case INTERNET_CTRL_INFO:
internet_ctrl_conf(nlh);
break;
default:
break;
}
return 0;
}
static DEFINE_MUTEX(phicomm_cfg_mutex);
static void phicomm_netlink_rcv(struct sk_buff *skb)
{
DEBUG_PRINT("%d in %s of %s\n", __LINE__, __func__, __FILE__);
mutex_lock(&phicomm_cfg_mutex);
netlink_rcv_skb(skb, &phicomm_user_rcv_msg);
mutex_unlock(&phicomm_cfg_mutex);
}
static void internet_ctrl_init(void)
{
struct netlink_kernel_cfg cfg = {
.input = phicomm_netlink_rcv,
};
DEBUG_PRINT("***********%d in %s of %s**************\n", __LINE__, __func__, __FILE__);
nl_sk = netlink_kernel_create(&init_net, NETLINK_INTERNET_CONTROLE, &cfg);
if(!nl_sk){
DEBUG_PRINT("internet_ctrl_init create netlink socket error.\n");
}
}
static int __init ip_hash_init(void)
{
ip_hash_poll_init();
internet_ctrl_init();
return 0;
}
module_init(ip_hash_init);
EXPORT_SYMBOL(phicommUsrPid);
以上是内核代码
_____________________________________________________________________________
|
|