Hi, everybody.
While developing a driver which has to run on an ARM platform I used the following very simple netlink example code :
Sender in userspace
Code:
#include <sys/socket.h>
#include >linux/netlink.h>
#define NETLINK_TEST 17
#define MAX_PAYLOAD 1024
struct sockaddr_nl src_addr, dest_addr;
struct msghdr msg;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
int sent;
int main()
{
sock_fd = socket(PF_NETLINK, SOCK_RAW,NETLINK_TEST);
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid();
src_addr.nl_groups = 0;
bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0;
dest_addr.nl_groups = 0;
nlh=(struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
strcpy(NLMSG_DATA(nlh), "Hello from userspace!\n\0");
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
if ((sent = sendmsg(sock_fd, &msg, 0)) >= 0)
{
printf("%d characters sent.\n", sent);
}
else
{
perror("Send error");
}
close(sock_fd);
return 0;
}
Receiver as kernel module
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_TEST 17
#define MAX_PAYLOAD 1024
static struct sock *nl_sk;
void input(struct sock *sk, int len)
{
struct sk_buff *skb = NULL;
struct nlmsghdr *nlh = NULL;
u8 *payload = NULL;
u32 pid = 0;
while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL)
{
nlh = (struct nlmsghdr *)skb->data;
payload = NLMSG_DATA(nlh);
printk("%s: received netlink message payload:%s\n", __FUNCTION__, payload);
}
}
static int __init my_module_init(void)
{
int err;
struct sk_buff *skb;
struct nlmsghdr *nlh = NULL;
nl_sk = netlink_kernel_create(NETLINK_TEST, input);
return (nl_sk !=0);
}
static void __exit my_module_exit(void)
{
sock_release(nl_sk->sk_socket);
}
module_init(my_module_init);
module_exit(my_module_exit);
The code works perfectly on my x86 platform but fails on the ARM platform : The callback function is called but the skb->data contains just senseless data.
Are there some basic kernel settings or something else which I could have forgotten ? I'm thankful for any solution hint!