您的位置:首页 > 其它

netlink机制使用实例

2014-06-18 16:02 120 查看
(一)客户端:

1./*创建NETLINK_ID客户端套接字

netlink _id = open_socket_for_netlink();

int open_socket_for_netlink()

{

int sock = -1;

int bindsock = -1;

struct sockaddr_nl nlskaddr;

sock = socket(AF_NETLINK,SOCK_RAW,NETLINK_ID);

if (sock > 0)

{

memset ( &nlskaddr, 0 , sizeof( nlskaddr ) );

nlskaddr.nl_family = (sa_family_t)AF_NETLINK;

nlskaddr.nl_pid = 0; //getpid();

nlskaddr.nl_groups = TRAPTYPE_GROUP;

}

else

return -1;

bindsock = bind (sock,(struct sockaddr *)&nlskaddr,sizeof(nlskaddr));

if (bindsock != 0)

{

perror("bind failure!\n");

return -1;

}

{

int on = nlskaddr.nl_groups;

//setsockopt(sock, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &on, sizeof(on));

setsockopt(sock, 270, 1,&on, sizeof(on));

}

return sock;

}

2.通过套接子集操作来调用消息接受处理

if(FD_ISSET(netlink_id, &readfds))

{

receive_netlink_do();

FD_CLR(netlink_id, &readfds);

}

void receive_netlink_do()

{

struct nlmsghdr hdr; //从结构体中可以得到netlink消息的总长度

int read_len = -1;

memset(&hdr, 0, sizeof(hdr));

read_len = recvfrom(netlink_id,

&hdr, sizeof(hdr),
MSG_PEEK, NULL, NULL);

if (read_len <=0 || read_len != sizeof(hdr))

return;

struct nlmsg_netlink message;

memset(&message, 0, sizeof(message));

read_len = recvfrom(netlink_cgi_id, &message, sizeof(message),MSG_DONTWAIT, NULL, NULL);

if (read_len <=0 || read_len != hdr.nlmsg_len)

return;

……..

}

3. 主动发送消息给服务端:

send_nlhdr = ( struct nlmsghdr * ) malloc ( NLMSG_SPACE ( MAX_MSGSIZE ) );

void send_msg_to_server_kernel ( int msg_type, char *message, unsigned short int msg_len )

{

user_mgs *pmsg;

struct sockaddr_nl daddr;

struct nlmsghdr *nlhdr = NULL;

struct msghdr msg;

struct iovec iov;

int ret;

int *mess;

send_nlhdr->nlmsg_len = NLMSG_SPACE ( MAX_MSGSIZE );

send_nlhdr->nlmsg_pid = getpid(); /* self pid */

send_nlhdr->nlmsg_flags = 0;

/* 填写用户消息*/

pmsg = ( USER_MSG * ) NLMSG_DATA ( send_nlhdr );

pmsg->msg_id = msg_type;

pmsg->datalen = msg_len*4;

memcpy ( pmsg->data, message, 4*msg_len );

mess= ( int * ) message;

memset ( &daddr, 0, sizeof ( daddr ) );

daddr.nl_family = AF_NETLINK;

daddr.nl_pid = 0; /* For Linux Kernel */

daddr.nl_groups = 0; /* unicast */

memset ( &msg, 0 ,sizeof ( struct msghdr ) );

iov.iov_base = ( void * ) send_nlhdr;

iov.iov_len = send_nlhdr->nlmsg_len;

msg.msg_name = ( void * ) &daddr;

msg.msg_namelen = sizeof ( daddr );

msg.msg_iov = &iov;

msg.msg_iovlen = 1;

ret = sendmsg
( netlink_sk, &msg, 0 );

if ( ret == -1 )

{

perror ( "sendmsg error" );

}

}

(二)服务端:

1.服务器注册NETLINK_ID 的netlink_sk

netlink_sk=netlink_kernel_create(&init_net,NETLINK_ID, 0,
recv_msg_from_user, NULL,THIS_MODULE);

2.netlink发送函数处理

int server_netlink_send_msg_portal ( struct sock *netlink_sk, u_int8_t *msg, int len )

{

int ret = -1;

int size;

unsigned char *old_tail;

struct sk_buff *skb;

struct nlmsghdr *nlh;

char *pos = NULL;

size = NLMSG_SPACE ( len );

skb = dev_alloc_skb ( size );

if ( skb == NULL )

{

goto out;

}

old_tail = skb->tail;

/*填写数据报相关信息*/

nlh = NLMSG_PUT ( skb, 0, 0, AUTH_GROUP, size - sizeof ( struct nlmsghdr ) );

pos = NLMSG_DATA ( nlh );

memset ( pos, 0, len );

memcpy ( pos, msg, len );/*传输到用户空间的数据*/

nlh->nlmsg_len = skb->tail - old_tail;/*计算经过字节对其后的数据实际长度*/

NETLINK_CB ( skb ).dst_group =
TRAPTYPE_GROUP;

if ( netlink_sk )

netlink_broadcast ( netlink_sk, skb, 0,TRAPTYPE_GROUP, GFP_ATOMIC );

else

goto out;

ret = 0;

out:

return ret;

nlmsg_failure: /*NLMSG_PUT 失败,则撤销套接字缓存*/

kfree_skb ( skb );

goto out;

}

3. 处理用户空间传递的消息:

void recv_msg_from_user (struct sk_buff *skb)

{

struct nlmsghdr *nlh = NULL;

u8 *payload = NULL;

skb = skb_clone(skb, GFP_KERNEL);

//while ( (skb = skb_dequeue( &sk->sk_receive_queue)) != NULL )

if (skb)

{

/* process netlink message pointed by skb->data */

nlh = (struct nlmsghdr *)skb->data;

/* process netlink message with header pointed by

* nlh and payload pointed by payload

*/

payload = NLMSG_DATA(nlh);

deal_msg_from_user( payload );

//if(skb) kfree_skb(skb);

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: