LinuxQuestions.org
Register a domain and help support LQ
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices

Reply
 
Search this Thread
Old 12-26-2008, 07:13 AM   #1
alfrag
LQ Newbie
 
Registered: Dec 2008
Posts: 3

Rep: Reputation: 0
A question about netlink sockets


Hi all,
i'm trying to use netlink sockets to send messages from user to kernel space. I've found on the net the following code:

User space:

/******************************************************************/
/** @file netlink-u2k.c
*
* @author marco corvi <marco_corvi@geocities.com>
* @date feb 2005
*
* @brief test program for user to kernel netlink communication
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h> // socket, getpid, bind
#include <sys/socket.h> // socket, bind
#include <unistd.h> // getpid
#include <asm/types.h>
#include <linux/netlink.h>

// this value is not used in knetlink.c
#define KNETLINK 17

#define PAYLOAD_SIZE 1024

int main( int argc, char ** argv )
{
int sock;
int i, j;
unsigned char payload[PAYLOAD_SIZE]; // payload

unsigned char rpayload[PAYLOAD_SIZE]; // payload

struct msghdr msg; // message-header
struct sockaddr_nl addr; // my netlink address
struct sockaddr_nl peer; // peer address
struct nlmsghdr nlh; // netlink message header
struct iovec iov[2]; // iovec array

sock = socket( AF_NETLINK, SOCK_DGRAM, KNETLINK /* NETLINK_ARPD */ );
if ( sock < 0 ) {
perror("Socket error");
exit(1);
}

memset( &addr, 0, sizeof(addr) );
addr.nl_family = AF_NETLINK;
addr.nl_pad = 0;
addr.nl_pid = getpid();
addr.nl_groups = 0;

{ //**************** sender *****************************
printf("Sender: my pid %d\n", getpid() );
memset( &peer, 0, sizeof(peer) );

peer.nl_family = AF_NETLINK;
peer.nl_pad = 0;
peer.nl_pid = 0; // peer is the kernel
peer.nl_groups = 0; // unicast

printf("server pid %d\n", peer.nl_pid);

nlh.nlmsg_len = sizeof(nlh) + PAYLOAD_SIZE;
nlh.nlmsg_type = 5;
nlh.nlmsg_flags = 0;
nlh.nlmsg_seq = 1;
nlh.nlmsg_pid = getpid();

iov[0].iov_base = (void *)&nlh;
iov[0].iov_len = sizeof(nlh);

iov[1].iov_base = (void *)payload;
iov[1].iov_len = PAYLOAD_SIZE;

for (i=0; i<PAYLOAD_SIZE; ++i) payload[i] = i % 0xff;

msg.msg_name = (void *)&(peer);
msg.msg_namelen = sizeof(peer);
msg.msg_iov = iov;
msg.msg_iovlen = 2;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0; // flags are not used by sendmsg

if ( sendmsg( sock, &msg, 0 ) < 0 ) {
perror("Sendmsg error");
exit(1);
}

// receive the kernel reply
// memset( rpayload, 0, PAYLOAD_SIZE );
// memset( &nlh, 0, sizeof(nlh) );

iov[0].iov_base = (void *)&nlh;
iov[0].iov_len = sizeof(nlh);
iov[1].iov_base = (void *)rpayload;
iov[1].iov_len = PAYLOAD_SIZE;

memset( &msg, 0, sizeof(msg) );
msg.msg_name = (void *)&peer;
msg.msg_namelen = sizeof(peer);
msg.msg_iov = iov;
msg.msg_iovlen = 2;

if ( recvmsg( sock, &msg, 0 ) < 0 ) {
perror("Recvmsg error");
exit(1);
}
printf("recv iov %d %p\n", msg.msg_iovlen, (void *)&(msg.msg_iov) );
printf(" peer:len %d, family %d, pid %d\n",
msg.msg_namelen, peer.nl_family, peer.nl_pid );
printf(" iov size [0] %d [1] %d\n", iov[0].iov_len, iov[1].iov_len);
printf(" nl: len %d, type %d, flags %d, seq %d, pid %d\n",
nlh.nlmsg_len, nlh.nlmsg_type, nlh.nlmsg_flags,
nlh.nlmsg_seq, nlh.nlmsg_pid );

for ( i=0; i<PAYLOAD_SIZE; ++i)
if ( rpayload[i] != 0xff - (i % 0xff) ) break;
if (i == PAYLOAD_SIZE) {
printf("payload is ok \n");
} else {
printf("payload is broken at %d \n", i );
for ( j=0; j<i+5 && j<PAYLOAD_SIZE; ++j )
printf("%02x ", rpayload[j] );
}


}
close(sock);
return 0;
}
/******************************************************************/

and in kernel space:

/******************************************************************/

/** @file knetlink.c
*
* @author marco corvi <marco_corvi@geocities.com>
* @date feb 2005
*
* @brief netlink kernel module
*
* inspired and heavily taken from the article
* K. Kaichuan He, "Why and how to use netlink socket"
* Linux Journal, Feb 2005
*
*/
#ifndef __KERNEL__
# define __KERNEL__
#endif

#define __NO_VERSION__ /* don't define kernel_verion in module.h */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/net.h>
#include <net/sock.h>
#include <linux/socket.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>


#define KNETLINK_UNIT 17


static struct sock * knetlink_sk = NULL;


/** process a netlink message
* @param skb socket buffer containing the netlink message
*
* The netlink message is in skb-> data
* This function does some printout, modifies the bytes of the payload,
* and send a reply message back to the sender user process.
*/
void knetlink_process( struct sk_buff * skb )
{
int k;
struct nlmsghdr * nlh = NULL;
u8 * payload = NULL;
int payload_size;
int length;
int seq;
pid_t pid;
struct sk_buff * rskb;

/* process netlink message pointed by skb->data */
nlh = (struct nlmsghdr *)skb->data;
pid = nlh->nlmsg_pid;
length = nlh->nlmsg_len;
seq = nlh->nlmsg_seq;

printk("knetlink_process: nlmsg len %d type %d pid %d seq %d\n",
length, nlh->nlmsg_type, pid, seq );

/* process the payload */
payload_size = nlh->nlmsg_len - NLMSG_LENGTH(0);
if ( payload_size > 0 ) {
payload = NLMSG_DATA( nlh );

printk("knetlink_process: process payload ");

for (k=0; k<10; k++) printk("%02x ", payload[k]);
printk("...\n");

for ( k=0; k<payload_size; ++k)
payload[k] = 0xff - payload[k];
/* ... */
}
// reply
rskb = alloc_skb( nlh->nlmsg_len, GFP_KERNEL );

if ( rskb ) {
memcpy( rskb->data, skb->data, length );
skb_put( rskb, length );
kfree_skb( skb );
} else {
printk("knetlink_process: replies with the same socket_buffer\n");
rskb = skb;
}
nlh = (struct nlmsghdr *) rskb->data;
nlh->nlmsg_len=length;
nlh->nlmsg_pid=0; /* from kernel */
nlh->nlmsg_flags=0;
nlh->nlmsg_type=2;
nlh->nlmsg_seq=seq+1;

//NETLINK_CB(rskb).group=0;
NETLINK_CB(rskb).pid= 0;
NETLINK_CB(rskb).dst_group = 0;

//NETLINK_CB(rskb).dst_pid= pid;
payload = NLMSG_DATA( nlh );


printk("knetlink_process: reply nlmsg len %d type %d pid %d\n",
nlh->nlmsg_len, nlh->nlmsg_type, nlh->nlmsg_pid );
printk("knetlink_process: payload ");

for (k=0; k<10; k++) printk("%02x ", payload[k]);
printk("...\n");

netlink_unicast( knetlink_sk, rskb, pid, MSG_DONTWAIT );

}


/** input function
* @param sk sock (namely knetlink_sk)
* @param len length of the data on the sock
*
* Either it calls the knetlink_process (no-thread model)
* or it wakes the knetlink thread up.
*/
void knetlink_input( struct sock *sk, int len )
{
printk("knetlink_input: sock %p, len %d\n", (void*)sk, len);

if ( knetlink_sk != sk ) {
printk("knetlink_input: wrong sock %p instead of %p\n",(void *)sk, (void *)knetlink_sk );
return;
}


struct sk_buff * skb;
while ( (skb = skb_dequeue( &sk->sk_receive_queue ) ) != NULL ) {
knetlink_process(skb);
}

}

/** module init
* @return 0 on success
*
* It creates the netlink, and (in the thread model) the * knetlink thread
*/
int knetlink_init( void )
{
if ( knetlink_sk != NULL ) {
printk("knetlink_init: sock already present\n");
return 1;
}

// knetlink_sk = netlink_kernel_create( KNETLINK_UNIT, knetlink_input);

knetlink_sk=netlink_kernel_create(&init_net,KNETLINK_UNIT,1,(void*)
knetlink_input,NULL,THIS_MODULE);

if ( knetlink_sk == NULL ) {
printk("knetlink_init: sock fail\n");
return 1;
}


printk("knetlink_init: sock %p\n", (void*)knetlink_sk );
return 0;
}

/** module exit
*
* In the thread model it stops the thread,
* then it releases the knetlink sock.
*/
void knetlink_exit( void )
{

if ( knetlink_sk != NULL ) {
printk("knetlink_exit: release sock %p\n", (void*)knetlink_sk);
sock_release( knetlink_sk->sk_socket );
} else {
printk("knetlink_exit: warning sock is NULL\n");
}

}

module_init( knetlink_init );
module_exit( knetlink_exit );

MODULE_LICENSE("GPL");
MODULE_AUTHOR("marco corvi");
MODULE_DESCRIPTION("Netlink example");
/***************************************************************/


When i try these modules cat /proc/net/netlink shows:

de2ec600 17 7458 00000000 0 0 00000000 2
dea46a00 17 0 00000000 0 0 00000000 2

meaning that there are two sockets opened; one in kernel space and one in user space.

But, kernel module refuses to accept the data saying:

knetlink_input: wrong sock dea753c0 instead of dea46a00

For some reason, the user space process send data to the kernel in a wrong socket.

Any ideas?

Many thanks in advance,

Alexandros
 
Old 12-26-2008, 08:48 AM   #2
onebuck
Moderator
 
Registered: Jan 2005
Location: Midwest USA, Central Illinois
Distribution: SlackwareŽ
Posts: 11,044
Blog Entries: 1

Rep: Reputation: 1370Reputation: 1370Reputation: 1370Reputation: 1370Reputation: 1370Reputation: 1370Reputation: 1370Reputation: 1370Reputation: 1370Reputation: 1370
Hi,

Welcome to LQ!

You should use the vbcode tags to post long data lists like you have provided in the OP. You will find them at the top of the reply window. The '#' is for code (long lists) and the Quote balloon to the left is for 'quoting'.

What about the error message that you got, is that complete?
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Netlink sockets usage to communicate b/w user and kernel space. vinodkr83 Linux - Newbie 1 07-03-2009 03:22 AM
Kernel module using netlink sockets arunka Programming 1 03-31-2005 07:42 AM
Netlink Sockets Problem gio123 Programming 3 01-23-2005 06:17 PM
Adding Routes using Netlink Sockets mpls_linux Linux - Networking 0 05-22-2004 09:14 PM
comments and opinions on linux netlink routing sockets tutorial infamous41md Programming 3 11-20-2003 05:54 PM


All times are GMT -5. The time now is 11:10 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration