- 论坛徽章:
- 0
|
static int link_netlink_receive_peer(unsigned char type, void *msg, unsigned int len)
{
int ret = 0;
switch (type) {
case 1:
printk("***************recv successful***********************\n");
break;
default:
printk("link-netlink: Unknown message type\n");
ret = -EINVAL;
break;
}
return ret;
}
static struct sk_buff* link_netlink_build_msg(int type, void *data, int len)
{
unsigned char *old_tail;
size_t size = 0;
struct sk_buff *skb;
struct nlmsghdr *nlh;
void *m;
size = NLMSG_SPACE(len);
skb = alloc_skb(size, GFP_ATOMIC);
if (!skb)
goto nlmsg_failure;
old_tail = skb_tail_pointer(skb);
nlh = NLMSG_PUT(skb, 0, 0, type, size - sizeof(*nlh));
m = NLMSG_DATA(nlh);
memcpy(m, data, len);
nlh->nlmsg_len = skb_tail_pointer(skb) - old_tail;
NETLINK_CB(skb).pid = 0; /*from kernel*/
NETLINK_CB(skb).dst_group = ASNTGRP_LINK_IF;
return skb;
nlmsg_failure:
if(skb)
kfree_skb(skb);
printk("link: error creating rt timeout message\n");
return NULL;
}
void link_netlink_send_rt_msg(int type, __u32 src, __u32 dest)
{
//printk("*******Start send_rt_msg sucessful !*********\n");
struct sk_buff *skb = NULL;
struct link_rt_msg m;
int ret = 0;
memset(&m, 0, sizeof(m));
m.src = src;
m.dest = dest;
skb = link_netlink_build_msg(type, &m, sizeof(struct link_rt_msg));
//printk("Send_rt_msg : *******build_msg sucessful !********* peer_pid === %d\n",peer_pid);
if (skb == NULL)
{
printk("link_netlink: skb = NULL\n");
return;
}
/*netlink_unicast(linknl, skb, peer_pid, MSG_DOWNWAIT)*/
ret = netlink_broadcast(linknl, skb, 0, ASNTGRP_LINK_IF, GFP_KERNEL);
printk("ret === %d\n",ret);
}
#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
static inline void link_netlink_rcv_skb(struct sk_buff *skb)
{
int status, type, pid, flags, nlmsglen, skblen;
struct nlmsghdr *nlh;
//printk("*******Start link_netlink_rcv_skb sucessful !********* %d\n",nlmsglen);
skblen = skb->len;
if (skblen < sizeof(struct nlmsghdr)) {
printk("skblen to small\n");
return;
}
nlh = (struct nlmsghdr *)skb->data;
nlmsglen = nlh->nlmsg_len;
if (nlmsglen < sizeof(struct nlmsghdr) || skblen < nlmsglen) {
printk("nlsmsg=%d skblen=%d to small\n", nlmsglen, skblen);
return;
}
pid = nlh->nlmsg_pid;
flags = nlh->nlmsg_flags;
if (pid <= 0 || !(flags & NLM_F_REQUEST) || flags & NLM_F_MULTI)
RCV_SKB_FAIL(-EINVAL);
if (flags & MSG_TRUNC)
RCV_SKB_FAIL(-ECOMM);
type = nlh->nlmsg_type;
//printk("***************Type = %d*********************\n",type);
if (peer_pid) {
if (peer_pid != pid) {
//write_unlock_bh(&queue_lock);
RCV_SKB_FAIL(-EBUSY);
}
} else
peer_pid = pid;
//printk("***************Send sucessful!********************\n"); //write_unlock_bh(&queue_lock);
status = link_netlink_receive_peer(type, NLMSG_DATA(nlh),
skblen - NLMSG_LENGTH(0));
if (status < 0)
printk("RCV_SKB_FAIL(status)\n");
if (flags & NLM_F_ACK)
netlink_ack(skb, nlh, 0);
link_netlink_send_rt_msg(MSG_1,1,2);
return;
}
int link_netlink_init(void)
{
linknl = netlink_kernel_create(&init_net, NETLINK_LINK, 0, link_netlink_rcv_skb, NULL, THIS_MODULE);
printk("*******linknl create sucessful !*********\n");
if (linknl == NULL)
{
printk(KERN_ERR "link_netlink: failed to create netlink socket\n");
return -1;
}
return 0;
} |
|