//imp2.h
#ifndef __IMP2_H__
#define __IMP2_H__
#define IMP2_U_PID 0
#define IMP2_K_MSG 1
#define IMP2_CLOSE 2
#define NL_IMP2 31
struct packet_info
{
__u32 src;
__u32 dest;
};
#endif
//内核态程序imp2_k_my.c
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/netfilter.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/netfilter_ipv4.h>
#include <linux/inet.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/netlink.h>
#include <linux/spinlock.h>
#include <net/sock.h>
#include "imp2.h"
MODULE_LICENSE("Dual BSD/GPL");
#define IMP2_K_MY "imp2_k_my:"
//#define printk(arg) //printkk(KERN_ALERT IMP2_K_MY arg)
DECLARE_MUTEX(receive_sem);
static struct sock *mysock;
struct
{
__u32 pid;
rwlock_t lock;
} user_proc;
static int send_to_user(struct packet_info *info)
{
int ret = 0;
int size;
//unsigned char *old_tail;
sk_buff_data_t old_tail;
struct sk_buff *skb;
struct nlmsghdr *nlh;
struct packet_info *packet;
printk("%s, begin !!! \n", __func__);
size = NLMSG_SPACE(sizeof(*info));
skb = alloc_skb(size, GFP_ATOMIC);
old_tail = skb->tail;
nlh = NLMSG_PUT(skb, 0, 0, IMP2_K_MSG, size - sizeof(*nlh));
packet = NLMSG_DATA(nlh);
memset(packet, 0, sizeof(struct packet_info));
packet->src = info->src;
packet->dest = info->dest;
nlh->nlmsg_len = (__u32)(skb->tail - old_tail);
NETLINK_CB(skb).dst_group = 0;
read_lock_bh(&user_proc.lock);
ret = netlink_unicast(mysock, skb, user_proc.pid, MSG_DONTWAIT);
read_unlock_bh(&user_proc.lock);
printk("%s, end !!! \n", __func__);
return ret;
nlmsg_failure:
if(skb)
kfree_skb(skb);
return -1;
}
static unsigned int icmp_hook_func(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct iphdr *iph = ip_hdr(skb);
struct packet_info info;
//printk("%s, begin !!! \n", __func__);
if (iph->protocol == IPPROTO_ICMP) {
read_lock_bh(&user_proc.lock);
if (user_proc.pid != 0) {
info.src = iph->saddr;
info.dest = iph->daddr;
printk("%s, src=%u.%u.%u.%u, dst=%u.%u.%u.%u\n", __func__,
NIPQUAD(info.src), NIPQUAD(info.dest));
send_to_user(&info);
} else {
printk("%s, no user process running..!\n", __func__);
}
read_unlock_bh(&user_proc.lock);
}
//printk("%s, end !!! \n", __func__);
return NF_ACCEPT;
}
#define NF_IP_PRE_ROUTING 0
static struct nf_hook_ops my_icmp_hook = {
.hook = icmp_hook_func,
.pf = PF_INET,
.hooknum = NF_IP_PRE_ROUTING,
.owner = THIS_MODULE,
.priority = NF_IP_PRI_FILTER - 1,
};
static void my_receive(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
int len;
printk("%s, begin !!!!!\n", __func__);
nlh = nlmsg_hdr(skb);
len = skb->len;
while (NLMSG_OK(nlh, len)) {
printk("%s, skb_len = %d!!!!!\n", __func__, len);
if (nlh->nlmsg_type == IMP2_U_PID) {
write_lock_bh(&user_proc.lock);
user_proc.pid = nlh->nlmsg_pid;
write_unlock_bh(&user_proc.lock);
} else if (nlh->nlmsg_type == IMP2_CLOSE)
{
write_lock_bh(&user_proc.lock);
if(nlh->nlmsg_pid == user_proc.pid)
user_proc.pid = 0;
write_unlock_bh(&user_proc.lock);
}
netlink_ack(skb, nlh, 0);
nlh = NLMSG_NEXT(nlh, len);
}
printk("%s, end !!!!!\n", __func__);
}
static int __init imp2_k_my_init(void)
{
printk("%s, begin !!!!!\n", __func__);
rwlock_init(&user_proc.lock);
mysock = netlink_kernel_create(&init_net, NL_IMP2, 0, my_receive,
NULL, THIS_MODULE);
if (!mysock) {
printk("%s, netlink_kernel_create fail.. !!!!!\n", __func__);
return -1;
}
printk("%s, end !!!!!\n", __func__);
return nf_register_hook(&my_icmp_hook);
}
static void __exit imp2_k_my_exit(void)
{
printk("%s, begin !!!!!\n", __func__);
netlink_kernel_release(mysock);
nf_unregister_hook(&my_icmp_hook);
printk("%s, end !!!!!\n", __func__);
}
module_init(imp2_k_my_init);
module_exit(imp2_k_my_exit);
//用户态程序imp2_u_my.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <error.h>
#include <linux/types.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <signal.h>
#include "imp2.h"
struct msg_to_kernel
{
struct nlmsghdr hdr;
};
struct u_packet_info
{
struct nlmsghdr hdr;
struct packet_info icmp_info;
};
static int skfd;
static void sig_int(int signo)
{
struct sockaddr_nl kpeer;
struct msg_to_kernel message;
memset(&kpeer, 0, sizeof(kpeer));
kpeer.nl_family = AF_NETLINK;
kpeer.nl_pid = 0;
kpeer.nl_groups = 0;
memset(&message, 0, sizeof(message));
message.hdr.nlmsg_len = NLMSG_LENGTH(0);
message.hdr.nlmsg_flags = 0;
message.hdr.nlmsg_type = IMP2_CLOSE;
message.hdr.nlmsg_pid = getpid();
sendto(skfd, &message, message.hdr.nlmsg_len, 0, (struct sockaddr *)(&kpeer),
sizeof(kpeer));
close(skfd);
exit(0);
}
int main(void)
{
struct sockaddr_nl local;
struct sockaddr_nl kpeer;
int kpeerlen;
struct msg_to_kernel message;
struct u_packet_info info;
int sendlen = 0;
int rcvlen = 0;
struct in_addr addr;
skfd = socket(PF_NETLINK, SOCK_RAW, NL_IMP2);
if(skfd < 0) {
printf("can not create a netlink socket\n");
exit(0);
}
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;
}
signal(SIGINT, sig_int);
memset(&kpeer, 0, sizeof(kpeer));
kpeer.nl_family = AF_NETLINK;
kpeer.nl_pid = 0;
kpeer.nl_groups = 0;
memset(&message, 0, sizeof(message));
message.hdr.nlmsg_len = NLMSG_LENGTH(0);
message.hdr.nlmsg_flags = 0;
message.hdr.nlmsg_type = IMP2_U_PID;
message.hdr.nlmsg_pid = local.nl_pid;
sendto(skfd, &message, message.hdr.nlmsg_len, 0,
(struct sockaddr*)&kpeer, sizeof(kpeer));
while(1) {
kpeerlen = sizeof(struct sockaddr_nl);
rcvlen = recvfrom(skfd, &info, sizeof(struct u_packet_info),
0, (struct sockaddr*)&kpeer, &kpeerlen);
addr.s_addr = info.icmp_info.src;
printf("src: %s, ", inet_ntoa(addr));
addr.s_addr = info.icmp_info.dest;
printf("dest: %s\n", inet_ntoa(addr));
}
return 0;
}