内核态
1、初始化
首先当然是调用netlink_kernel_create函数,具体参数参考前一篇文章。
#define NETLINK_ETRAINF 17
struct sock * g_etraInfSock = NULL;
g_etraInfSock = netlink_kernel_create(&init_net, NETLINK_ETRAINF,\
0, EtraInfRecv, NULL, THIS_MODULE);
其中
g_etraInfSock
定义成全局变量,因为这个返回值还要作为其它函数的参数,稍后将会讲到。
2、接收
接收函数实现:
void EtraInfRecv(struct sk_buff *pSkb)
{
struct nlmsghdr *pNlHdr = NULL;
int iLen = 0;//NLMSG_OK四字节对齐
int iSecTimesFlag = 0;
int iMarkFlag = 0;
if (NULL == pSkb){
STAT_INC(RECV_SKB_NULL);
return;
}
pNlHdr = nlmsg_hdr(pSkb); /*(struct nlmsghdr *)skb->data*/
iLen = pSkb->len;
EF_INFO("[INFO:] recv sk_buff's length is %d\r\n",iLen);
while (NULL != pNlHdr && NLMSG_OK(pNlHdr, iLen)){
if (1 == iSecTimesFlag && 0 == iMarkFlag){
//g_etraInfKernErrStat.iRecvOneBuffHaveMultiPack++;
STAT_INC(RECV_MULTI_PACK);
iSecTimesFlag = 0;
iMarkFlag = 1;
}
STAT_INC(RECV_PACK);//接收计数+1
EF_HANDLE_RECV(EF_TYPE_TO_ENTRY(pNlHdr->nlmsg_type),pNlHdr);//根据type类型来选择对应的处理函数
pNlHdr = NLMSG_NEXT(pNlHdr, iLen);
iSecTimesFlag = 1;
}
return;
}
内核态的接收函数一般流程是这样的
net->genl_sock = netlink_kernel_create(net, NETLINK_GENERIC, 0,
genl_rcv, &genl_mutex,
THIS_MODULE);
static void genl_rcv(struct sk_buff *skb)
{
genl_lock();
netlink_rcv_skb(skb, &genl_rcv_msg);
genl_unlock();
}
genl_rcv_msg函数用来解析接收来的数据
3、发送int EtraInfSendMsg(MSG_NODE *pMsg)
{
//int iUdcLen = sizeof(APP_MSG);
char *p = (char *)pMsg->pUdcMsg;
int iRet = ETERROR;
int iUdcLen = sizeof(APP_MSG);