内核代码:

#include
#include
#include
#include
#include
#include
#define NETLINK_TEST 17
struct
{

 __u32 pid;

} user_process;
int send_to_user (char *info);
static struct nf_hook_ops nfho_marker1;
unsigned int hook_mark1(unsigned int hooknum, struct sk_buff *skb,
                       const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))
{
if(user_process.pid == 0)
       return;

send_to_user("this message is from kernel\n");
return NF_ACCEPT;
}

static struct sock *netlinkfd = NULL;

int
send_to_user (char *info)       //发送到用户空间
{

 int size;

 struct sk_buff *skb;

 unsigned char *old_tail;

 struct nlmsghdr *nlh;         //报文头

 int retval;

 size = NLMSG_SPACE (strlen (info));   //报文大小

  skb = alloc_skb (size, GFP_ATOMIC);  //分配一个新的套接字缓存,使用GFP_ATOMIC标志进程不>会被置>为睡眠

 nlh =
   nlmsg_put (skb, 0, 0, 0,
              NLMSG_SPACE (strlen (info)) - sizeof (struct nlmsghdr), 0);

 old_tail = skb->tail;

 memcpy (NLMSG_DATA (nlh), info, strlen (info));       //填充数据区

 nlh->nlmsg_len = skb->tail - old_tail;        //设置消息长度

NETLINK_CB (skb).pid = 0;

 NETLINK_CB (skb).dst_group = 0;


// printk (KERN_DEBUG "[kernel space] skb->data:%s\n",
         //(char *) NLMSG_DATA ((struct nlmsghdr *) skb->data));

 //发送数据
 retval = netlink_unicast (netlinkfd, skb, user_process.pid, MSG_DONTWAIT);
 printk(KERN_ALERT "retval = %d\n",retval);

 return 0;

}

/*通过此函数获取用户发的数据包,得到用户进程的pid,内核才能与应用程序通信*/

void
kernel_receive (struct sk_buff *__skb)  //内核从用户空间接收数据
{

 struct sk_buff *skb;

 struct nlmsghdr *nlh = NULL;

 char *data = "This is eric's test message from kernel";

 printk (KERN_DEBUG "[kernel space] begin kernel_receive\n");

skb = skb_get (__skb);

 if (skb->len >= sizeof (struct nlmsghdr))
   {

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

     if ((nlh->nlmsg_len >= sizeof (struct nlmsghdr))
         && (__skb->len >= nlh->nlmsg_len))
       {

         user_process.pid = nlh->nlmsg_pid;

         printk (KERN_ALERT
                 "[kernel space] data receive from user are:%s\n",
                 (char *) NLMSG_DATA (nlh));

         printk (KERN_ALERT "[kernel space] user_pid:%d\n",
                 user_process.pid);

         send_to_user (data);

       }

   }
 else
   {

printk (KERN_DEBUG "[kernel space] data receive from user are:%s\n",
             (char *) NLMSG_DATA (nlmsg_hdr (__skb)));

     send_to_user (data);

   }

 kfree_skb (skb);

}

int __init
test_netlink_init (void)
{
user_process.pid=0;
nfho_marker1.hook=hook_mark1;
   nfho_marker1.hooknum=NF_INET_PRE_ROUTING;
   nfho_marker1.pf=PF_INET;
   nfho_marker1.priority=11;
   nf_register_hook(&nfho_marker1);

 netlinkfd =
   netlink_kernel_create (&init_net, NETLINK_TEST, 0, kernel_receive, NULL,
                          THIS_MODULE);

 if (!netlinkfd)
   {

printk (KERN_ERR "can not create a netlink socket\n");

     return -1;

   }


 return 0;

}

void __exit
test_netlink_exit (void)
{

 sock_release (netlinkfd->sk_socket);
 nf_unregister_hook(&nfho_marker1);

 printk (KERN_DEBUG "test_netlink_exit!!\n");

}

module_init (test_netlink_init);

module_exit (test_netlink_exit);

MODULE_LICENSE ("GPL");


makefile:

obj-m:=netlink.o
KERNELDIR = /lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
default:
       $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
       $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean



应用代码:

#include

#include

#include

#include

#include

#define MAX_PAYLOAD 1024

#define NETLINK_TEST 17

#define MSG_LEN 100


struct msg_to_kernel
{

 struct nlmsghdr hdr;

 char data[MSG_LEN];

};

struct u_packet_info

{

 struct nlmsghdr hdr;

 char msg[MSG_LEN];

};


int
main (int argc, char *argv[])
{

 char *data = "This message is from eric's space";

 //初始化

 struct sockaddr_nl local;

 struct sockaddr_nl kpeer;

 int skfd, ret, kpeerlen = sizeof (struct sockaddr_nl);

 struct nlmsghdr *message;

 struct u_packet_info info;
 struct sockaddr_nl src_addr, dest_addr;

struct iovec iov;
   struct msghdr msg;
 char *retval;
 struct nlmsghdr *nlh = NULL;
 FILE *logfile_p;
 message = (struct nlmsghdr *) malloc (1);
  nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));


 skfd = socket (PF_NETLINK, SOCK_RAW, NETLINK_TEST);

 if (skfd < 0)
   {
     printf ("can not create a netlink socket\n");

     return -1;

   }

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

 local.nl_family = AF_NETLINK;

 local.nl_pid = getpid ();

 local.nl_groups = 0;

if (bind (skfd, (struct sockaddr *) &local, sizeof (local)) != 0)
   {

     printf ("bind() error\n");

     return -1;

   }

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

 kpeer.nl_family = AF_NETLINK;

 kpeer.nl_pid = 0;

 kpeer.nl_groups = 0;


 memset (message, '\0', sizeof (struct nlmsghdr));

 message->nlmsg_len = NLMSG_SPACE (strlen (data));

 message->nlmsg_flags = 0;

 message->nlmsg_type = 0;

 message->nlmsg_seq = 0;

message->nlmsg_pid = local.nl_pid;


 retval = memcpy (NLMSG_DATA (message), data, strlen (data));


 printf ("message sendto kernel are:%s, len:%d\n",
         (char *) NLMSG_DATA (message), message->nlmsg_len);
 ret =
   sendto (skfd, message, message->nlmsg_len, 0, (struct sockaddr *) &kpeer,
           sizeof (kpeer));

 if (!ret)
   {

     perror ("send pid:");

     exit (-1);

   }
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
   iov.iov_base = (void *)nlh;
  iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);

  memset(&msg, 0, sizeof(msg));
   memset(&kpeer, 0, sizeof(kpeer));

msg.msg_name = (void *)&kpeer;
   msg.msg_namelen = sizeof(kpeer);
   msg.msg_iov = &iov;
   msg.msg_iovlen = 1;
   logfile_p = fopen("/var/log/accsess","a+");
   if(logfile_p==NULL)
       printf("open errpr\n");

while(1)
{
recvmsg(skfd, &msg, 0);
//        printf("Received message: %s\n", NLMSG_DATA(nlh));
fputs(NLMSG_DATA(nlh),logfile_p);

};




 close (skfd);

 return 0;

}