内核模块
#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发到应用层.然后写一段信息到文件里去