Re: Netlink Socket: trouble while using netlink_broadcast

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

it is always the same :'(
I have looked into kernel sources, and there is also somethings
strange: in source code of netlink_kernel_create:
if (group <32)
   group = 32;
This lines were not present in kernel 2.6.9.
I am also wondering if there isn't somethings wrong with listenners:
there are some tests on *has listenners*.

Actually, I get theses errors:
For kernel code: netlink broadcast return -3, No such process.
User code: can't bind: errot -3.

I have put one programs, who works when using unicast instead of
broadcast, GROUP_IB  set to 0, and I fix manually pid of the
user-level program.
When I changed unicast to broadcast, and I set GROUP_IB to an other
value, I get the errors.


Thierry


----------



kernel code:

#include <linux/autoconf.h>
#include <linux/socket.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netlink.h>
#include <net/sock.h>
#include <net/netlink.h>

#define MAX_PAYLOAD 1024
#define NETLINK_IB 24
#define GROUP_IB 1


static struct sock *nl_sk = NULL;

static void nl_ib_data_ready (struct sock *sk, int len)
{
	wake_up_interruptible(sk->sk_sleep);
}

static void netlink_ib_open()
{
	struct sk_buff *skb = NULL;
	struct nlmsghdr *nlh = NULL;
	int err;

	nl_sk = netlink_kernel_create(NETLINK_IB, GROUP_IB, nl_ib_data_ready,
THIS_MODULE);
	if (nl_sk == NULL) {
		printk(KERN_ALERT "Error during netlink_kernel_create");
	}

	skb = alloc_skb(NLMSG_SPACE(MAX_PAYLOAD),GFP_KERNEL);
	nlh = (struct nlmsghdr *)skb->data;
	nlh = skb_put(skb, NLMSG_ALIGN(1024));
	nlh->nlmsg_pid = 0; // Send from kernel
	nlh->nlmsg_flags = 0;

	strcpy(NLMSG_DATA(nlh), "Greeting from kernel!");
	NETLINK_CB(skb).pid = 0;
	NETLINK_CB(skb).dst_pid = 0; //Multicast
	NETLINK_CB(skb).dst_group = GROUP_IB;// 0 if unicast
	
	printk( KERN_ALERT "Sending data...\n");
	//err = netlink_unicast(nl_sk, skb, 6992, GFP_KERNEL);
	err = netlink_broadcast(nl_sk, skb, 0, GROUP_IB, GFP_KERNEL);
	if (err<0) {
		printk(KERN_ALERT "Error during netlink_broadcast: %i\n",err);
		if (err == -3) {
			printk(KERN_ALERT "No such process\n");
		}
	}
	goto out;

nlmsg_failure:
	printk(KERN_ALERT "Erreuuuur nlmsg_failure\n");

out:
	sock_release(nl_sk->sk_socket);
}

static int __init netlink_ib_module_init(void)
{
	printk(KERN_INFO "Init netlink_ib module\n");
	netlink_ib_open();
	return 0;
}

static void __exit netlink_ib_module_exit(void)
{
	printk(KERN_INFO "Unloading netlink_ib module\n");
}

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Kernel/User socket for IB support");
module_init(netlink_ib_module_init);
module_exit(netlink_ib_module_exit);


---------
usercode

#include <sys/socket.h>
#include <sys/types.h>
#include <stdio.h>
#include <linux/netlink.h>
#define NETLINK_IB 24
#define GROUP_IB 1
#define MAX_PAYLOAD 1024
struct sockaddr_nl src_addr, dst_addr;
struct nlmsghdr *nlh = NULL;
struct msghdr msg;
struct iovec iov;
int sock_fd;


int main(int argc, char ** argv)
{
	int err;
	sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_IB);
	if (sock_fd<0) {
	        char s[BUFSIZ];
	        sprintf( s, "%s: can't assign fd for socket", argv[0] );
	        perror(s);
	        return -1;
	}

	//memset(&src_addr, 0, sizeof(src_addr));
	src_addr.nl_family = AF_NETLINK;
	src_addr.nl_pad = 0;
	src_addr.nl_pid = getpid();
	src_addr.nl_groups = GROUP_IB; // Multicast

	err = bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
	if (err<0) {
	        char s[BUFSIZ];
        	sprintf( s, "%s: can't bind socket (%d)", argv[0], sock_fd );
	        perror(s);
	        return -1;
	}

	memset(&dst_addr, 0, sizeof(dst_addr));
	nlh = (struct nlhmsghdr *) malloc(NLMSG_SPACE(MAX_PAYLOAD));
	memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));

	iov.iov_base = (void *)nlh;
	iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
	msg.msg_name = (void *)&dst_addr;
	msg.msg_namelen = sizeof(dst_addr);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;

	printf("Waiting for messages from kernel...\n");
	recvmsg(sock_fd, &msg, 0);
	printf("Message : %s\n", NLMSG_DATA(nlh));
	close(sock_fd);

	return 0;

}



On Thu, Apr 16, 2009 at 5:25 AM, Peter Teoh <htmldeveloper@xxxxxxxxx> wrote:
> not sure if correct or not, dst_group must always be 1 if broadcasting
> is needed.   (and pid=0)
>
> On Thu, Apr 16, 2009 at 11:23 AM, Peter Teoh <htmldeveloper@xxxxxxxxx> wrote:
>> On Wed, Apr 15, 2009 at 8:32 PM, Thierry <chocapiiic.tiery@xxxxxxxxx> wrote:
>>> Hi,
>>>
>>>
>>> I have tried 3 solutions:
>>>
>>> 1. using nlh = (struct nlmsghdr *) skb_put(skb,
>>> NLMSG_SPACE(MAX_PAYLOAD)); instead of  nlh = (struct nlmsghdr
>>> *)skb->data;
>>> No kernel panic, but doesn't work (it is just like before)
>>>
>>> 2. with skb_copy_expand and skb_push like in the second example you
>>> gave me, No kernel panic, but doesn't work (juste like before)
>>>
>>> 3. with the example of wwrap.c (your last idea), doest compile, or kernel panic
>>> But i don't really now what I should put in *message type* argument in
>>>  NLMSG_PUT.
>>> My code for last solution is bellow.
>>>
>>> If never you have others ideas.
>>>
>>> Thierry
>>>
>>>
>>>
>>
>> Have to debug one step at a time.   My first observation is that u did
>> not put the NLMSG_DONE as the type for your netlink message, which is
>> needed for last message.
>>
>> Another hint possibly is due to alignment problem:
>>
>> Yours is:
>>
>> nlh = (struct nlmsghdr *) skb_put(skb, NLMSG_SPACE(MAX_PAYLOAD))
>>
>> but kernel source showed something like this:
>>
>> nlh = (struct nlmsghdr *) skb_put(skb, NLMSG_ALIGN(size))
>>
>> might have to play around with different problem solving.........
>>
>>
>>> ------
>>>
>>>
>>>        struct sk_buff *skb = NULL;
>>>        struct nlmsghdr *nlh = NULL;
>>>        int err;
>>>        int size;
>>>        unsigned char * old_tail;
>>>        char * pos = NULL;
>>>        size = NLMSG_SPACE(MAX_PAYLOAD);
>>>        u32 pid;
>>>
>>>        //Creation de la netlink socket <=> socket()
>>>        nl_sk = netlink_kernel_create(NETLINK_IB, GROUP_IB, nl_ib_data_ready,
>>> THIS_MODULE);
>>>
>>>        skb = alloc_skb(NLMSG_SPACE(MAX_PAYLOAD),GFP_KERNEL);
>>>
>>> if (skb == NULL)
>>> {
>>>        printk(KERN_ALERT "erreur\n");
>>>        return;
>>> }
>>>        old_tail = skb -> tail;
>>>        //nlh = (struct nlmsghdr *)skb->data;
>>>        nlh = NLMSG_PUT(skb, 0, 0, 0, size-sizeof(*nlh));
>>>        int len = sizeof("Message du kernel =(");
>>>        pos = NLMSG_DATA(len);
>>>        memset(pos,0,len);
>>>
>>>        nlh->nlmsg_pid = 0; //Depuis le noyau
>>>        nlh->nlmsg_flags = 0;
>>>
>>>        strcpy(NLMSG_DATA(nlh), "Message du kernel =(");
>>>        NETLINK_CB(skb).pid = 0;
>>>        NETLINK_CB(skb).dst_pid = 0; //Multicast
>>>        NETLINK_CB(skb).dst_group = GROUP_IB;
>>>        nlh->nlmsg_len = skb->tail - old_tail;
>>>
>>>        //Envoi des donnees
>>>        printk( KERN_ALERT "j'envoi els donnees\n");
>>>         err = netlink_broadcast(nl_sk, skb, 0, GROUP_IB, GFP_KERNEL);
>>>
>>>
>>> On Fri, Apr 10, 2009 at 2:29 PM, Peter Teoh <htmldeveloper@xxxxxxxxx> wrote:
>>>> On Fri, Apr 10, 2009 at 4:12 AM, Thierry <chocapiiic.tiery@xxxxxxxxx> wrote:
>>>>> Hi,
>>>>>
>>>>> I have tried to change groupId, with different value, but there should
>>>>> be somethings wrong: the userspace prgm doesn't receive message.
>>>>> I would like to know if there is a plugin for tcpdump or an way of
>>>>> capture trafic on netlink socket, just like usual network socket in
>>>>> order to see were is my problem: in kernel space code or userspace
>>>>> code.
>>>>> My program code is attached, with english commit (sorry for last mail).
>>>>> I have also tried my code on differents kernel (redhat 4.4 with kernel
>>>>> 2.6.9-42.ELsmp, centos52 kernel 2.6.18-92.1.22).
>>>>>
>>>>> If there is other ways to send information from kernel space to user space...
>>>>> My aim is to capture data trafic from infiniband and dump trafic, for
>>>>> example in a netlink socket. Then I will be able with a userspace code
>>>>> to translate informations in .cap files.
>>>>> Thats why I think netlink_broadcast is a good idea.
>>>>>
>>>>> I will be always looking at kernelnewbie mailinglsit for several month,
>>>>>
>>>>> Regards,
>>>>>
>>>>> Thierry
>>>>>
>>>>>
>>>>>
>>>>> --------------
>>>>> kernel-level code
>>>>>
>>>>>
>>>>> #include <linux/config.h>
>>>>> #include <linux/socket.h>
>>>>> #include <linux/kernel.h>
>>>>> #include <linux/module.h>
>>>>> #include <linux/netlink.h>
>>>>> #include <net/sock.h>
>>>>>
>>>>> #define NETLINK_IB 24
>>>>> #define MAX_PAYLOAD 1024
>>>>> #define GROUP_IB 59
>>>>>
>>>>>
>>>>> static struct sock *nl_sk = NULL;
>>>>>
>>>>> static void nl_ib_data_ready (struct sock *sk, int len)
>>>>> {
>>>>>        wake_up_interruptible(sk->sk_sleep);
>>>>> }
>>>>>
>>>>> static void netlink_ib_open()
>>>>> {
>>>>>        struct sk_buff *skb = NULL;
>>>>>        struct nlmsghdr *nlh = NULL;
>>>>>        int err;
>>>>>        u32 pid;
>>>>>
>>>>>        //Socket_create
>>>>>        nl_sk = netlink_kernel_create(NETLINK_IB, GROUP_IB, nl_ib_data_ready,
>>>>> THIS_MODULE);
>>>>>
>>>>>        skb = alloc_skb(NLMSG_SPACE(MAX_PAYLOAD),GFP_KERNEL);
>>>>>        nlh = (struct nlmsghdr *)skb->data;
>>>>>
>>>>>        nlh->nlmsg_len =  NLMSG_SPACE(MAX_PAYLOAD);
>>>>>        nlh->nlmsg_pid = 0; //from kernel
>>>>>        nlh->nlmsg_flags = 0;
>>>>>
>>>>>        strcpy(NLMSG_DATA(nlh), "Message from kernel ");
>>>>>        NETLINK_CB(skb).pid = 0;
>>>>>        NETLINK_CB(skb).dst_pid = 0; //Multicast
>>>>>        NETLINK_CB(skb).dst_group = GROUP_IB;
>>>>>
>>>>>        //data send
>>>>>        printk( KERN_ALERT "data sent\n");
>>>>>        netlink_broadcast(nl_sk, skb, 0, GROUP_IB, GFP_KERNEL);
>>>>>        sock_release(nl_sk->sk_socket);
>>>>> }
>>>>
>>>> check this out:
>>>>
>>>> http://www.linuxjournal.com/article/7356
>>>>
>>>> read the comment, amazingly, someone else HAVE EXACTLY THE SAME
>>>> PROBLEM as yours, and his comment:
>>>>
>>>> ========================
>>>>
>>>> here is missed one importang thing:
>>>>
>>>> before strcpy we should call
>>>>
>>>> skb_put(skb, NLMSG_SPACE(MAX_PAYLOAD))
>>>>
>>>> or change
>>>>
>>>>
>>>> nlh = (struct nlmsghdr *)skb->data;
>>>> nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
>>>> nlh->nlmsg_pid = 0; /* from kernel */
>>>> nlh->nlmsg_flags = 0;
>>>>
>>>> ==========================
>>>>
>>>> and looking into kernel source:
>>>>
>>>>        s = skb_copy_expand(skb, 8, 0, GFP_ATOMIC);
>>>>        skb_push(s, 8);
>>>>        s->data[0] = 'z';
>>>>        s->data[1] = 'y';
>>>>        s->data[2] = 'd';
>>>>        s->data[3] = 'a';
>>>>        s->data[4] = 's';
>>>>        printk("len1=%d, len2=%d", skb->len, s->len);
>>>>        netlink_broadcast(rtnl, s, 0, RTMGRP_LINK, GFP_ATOMIC);
>>>>
>>>>
>>>> and this:
>>>>
>>>>        /*ÌîдÊý¾Ý±¨Ïà¹ØÐÅÏ¢*/
>>>>        nlh = NLMSG_PUT(skb, 0, 0, WAI_K_MSG, size-sizeof(*nlh));
>>>>        pos = NLMSG_DATA(nlh);
>>>>        memset(pos, 0, len);
>>>>
>>>>        /*´«Êäµ½Óû§¿Õ¼äµÄÊý¾Ý*/
>>>>        memcpy(pos, msg,  len);
>>>>        /*¼ÆËã¾­¹ý×Ö½Ú¶ÔÆäºóµÄÊý¾Ýʵ¼Ê³¤¶È*/
>>>>        nlh->nlmsg_len = skb->tail - old_tail;
>>>>        NETLINK_CB(skb).dst_group = COMMTYPE_GROUP;
>>>>        netlink_broadcast(netlink_sk, skb, 0, COMMTYPE_GROUP, GFP_ATOMIC);
>>>>
>>>> all having the same pattern as the comment.
>>>>
>>>> Hopefully this helps.
>>>>
>>>> --
>>>> Regards,
>>>> Peter Teoh
>>>>
>>>
>>
>>
>>
>> --
>> Regards,
>> Peter Teoh
>>
>
>
>
> --
> Regards,
> Peter Teoh
>

--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux