netlink2.6.32内核实现源码

内核模块

#include <linux/init.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/time.h>
#include <linux/types.h>
#include <net/sock.h>
#include <net/netlink.h> //it include linux/netlink.h

#define NETLINK_TEST 17
#define MAX_MSGSIZE 1024
void sendnlmsg(char *message);
struct sock *nl_sk = NULL;
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 *))
{

sendnlmsg("this message is from kernel");
return NF_ACCEPT;
}

// Get string's length
int stringlength(char *s)
{
   int slen = 0;

   for(; *s; s++){
       slen++;
   }

   return slen;
}

// Send message by netlink
void sendnlmsg(char *message)
{
   struct sk_buff *skb;
   struct nlmsghdr *nlh;

 int len = NLMSG_SPACE(MAX_MSGSIZE);
   int slen = 0;

   if(!message || !nl_sk){
       return;
   }

   // Allocate a new sk_buffer
   skb = alloc_skb(len, GFP_ATOMIC);
   if(!skb){
       printk(KERN_ERR "my_net_link: alloc_skb Error./n");
       return;
   }

   slen = stringlength(message);

   //Initialize the header of netlink message
   nlh = nlmsg_put(skb, 0, 0, 0, MAX_MSGSIZE, 0);

   NETLINK_CB(skb).pid = 0; // from kernel
   NETLINK_CB(skb).dst_group = 1; // multi cast

   memcpy(NLMSG_DATA(nlh), "this is from kernel\n",21);

   printk("my_net_link: send message '%s'./n", (char *)NLMSG_DATA(nlh));

   //send message by multi cast
   netlink_broadcast(nl_sk, skb, 0, 1,GFP_ATOMIC);
   return;
}

// Initialize netlink
int netlink_init(void)

{
   int i = 10;
   struct completion cmpl;
   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);

   nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, 1,
                                 NULL, NULL, THIS_MODULE);

   if(!nl_sk){
       printk(KERN_ERR "my_net_link: create netlink socket error./n");
       return 1;
   }

   printk("my_net_link: create netlink socket ok./n");

   return 0;
}

static void netlink_exit(void)
{
   if(nl_sk != NULL){
       sock_release(nl_sk->sk_socket);
   }
   nf_unregister_hook(&nfho_marker1);
   printk("my_net_link: self module exited/n");
}

module_init(netlink_init);
module_exit(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 <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/socket.h>
#include <errno.h>

#define NETLINK_TEST 17
#define MAX_PAYLOAD 1024  // maximum payload size


int main(int argc, char* argv[])
{
   struct sockaddr_nl src_addr, dest_addr;
   struct nlmsghdr *nlh = NULL;
   struct iovec iov;
   struct msghdr msg;
   int sock_fd, retval;
   int fd;
   FILE *logfile_p;
   unsigned int value;
   // Create a socket
   sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);
   if(sock_fd == -1){
       printf("error getting socket: %s", strerror(errno));
       return -1;
   }

   // To prepare binding
   memset(&src_addr, 0, sizeof(src_addr));
   src_addr.nl_family = PF_NETLINK;
   src_addr.nl_pid = getpid();  // self pid
   src_addr.nl_groups = 1; // multi cast

retval = bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
   if(retval < 0){
       printf("bind failed: %s", strerror(errno));
       close(sock_fd);
       return -1;
   }

   // To prepare recvmsg
   nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
   if(!nlh){
       printf("malloc nlmsghdr error!/n");
       close(sock_fd);
       return -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(&dest_addr, 0, sizeof(dest_addr));
   msg.msg_name = (void *)&dest_addr;
   msg.msg_namelen = sizeof(dest_addr);
   msg.msg_iov = &iov;
   msg.msg_iovlen = 1;
   logfile_p = fopen("/var/log/accsess","a+");
   if(logfile_p==NULL)
       printf("open errpr\n");
   // Read message from kernel
while(1){
       recvmsg(sock_fd, &msg, 0);
       printf("Received message: %s\n", NLMSG_DATA(nlh));
       value = fputs("write log\n",logfile_p);
       printf("value = %u\n",value);

};
   close(sock_fd);


fclose(logfile_p);
   return 0;
}


netfilter每收到一个包就用netlink发到应用层.然后写一段信息到文件里去

你可能感兴趣的:(netlink,linux内核)