netlink通信 用户态与内核态使用netlink通信编程

用户空间

用户态应用使用标准的socket与内核通讯,标准的socket API 的函数, socket(), bind(), sendmsg(), recvmsg() 和 close()很容易地应用到 netlink socket。
为了创建一个 netlink socket,用户需要使用如下参数调用 socket():
socket(AF_NETLINK, SOCK_RAW, netlink_type)
netlink对应的协议簇是 AF_NETLINK,第二个参数必须是SOCK_RAW或SOCK_DGRAM, 第三个参数指定netlink协议类型,它可以是一个自定义的类型,也可以使用内核预定义的类型

同样地,socket函数返回的套接字,可以交给bing等函数调用

  1. static int skfd;
  2. skfd = socket(PF_NETLINK, SOCK_RAW, NL_IMP2);
  3. if(skfd < 0)
  4. {
  5.   printf("can not create a netlink socket\n");
    
  6.   exit(0);
    
  7. }

bind函数需要绑定协议地址,netlink的socket地址使用struct sockaddr_nl结构描述:
8. struct sockaddr_nl
9. {
10. sa_family_t nl_family;
11. unsigned short nl_pad;
12. __u32 nl_pid;
13. __u32 nl_groups;
14. };
15.
员 nl_family为协议簇 AF_NETLINK,成员 nl_pad 当前没有使用,因此要总是设置为 0,成员 nl_pid 为接收或发送消息的进程的 ID,如果希望内核处理消息或多播消息,就把该字段设置为 0,否则设置为处理消息的进程 ID。成员 nl_groups 用于指定多播组,bind 函数用于把调用进程加入到该字段指定的多播组,如果设置为 0,表示调用者不加入任何多播组:

  1. struct sockaddr_nl local;
  2. memset(&local, 0, sizeof(local));
  3. local.nl_family = AF_NETLINK;
  4. local.nl_pid = getpid(); /设置pid为自己的pid值/
  5. local.nl_groups = 0;
  6. /绑定套接字/
  7. if(bind(skfd, (struct sockaddr*)&local, sizeof(local)) != 0)
  8. {
  9. printf(“bind() error\n”);
  10.  return -1;
    
  11. }

用户空间可以调用send函数簇向内核发送消息,如sendto、sendmsg等,同样地,也可以使用struct sockaddr_nl来描述一个对端地址,以待send函数来调用,与本地地址稍不同的是,因为对端为内核,所以nl_pid成员需要设置为0:

  1. struct sockaddr_nl kpeer;
  2. memset(&kpeer, 0, sizeof(kpeer));
  3. kpeer.nl_family = AF_NETLINK;
  4. kpeer.nl_pid = 0;
  5. kpeer.nl_groups = 0;

另一个问题就是发内核发送的消息的组成,使用我们发送一个IP网络数据包的话,则数据包结构为“IP包头+IP数据”,同样地,netlink的消息结构是“netlink消息头部+数据”。Netlink消息头部使用struct nlmsghdr结构来描述:

  1. struct nlmsghdr
  2. {
  3. __u32 nlmsg_len; /* Length of message */
  4. __u16 nlmsg_type; /* Message type*/
  5. __u16 nlmsg_flags; /* Additional flags */
  6. __u32 nlmsg_seq; /* Sequence number */
  7. __u32 nlmsg_pid; /* Sending process PID */
  8. };

字段 nlmsg_len 指定消息的总长度,包括紧跟该结构的数据部分长度以及该结构的大小,一般地,我们使用netlink提供的宏NLMSG_LENGTH来计算这个长度,仅需向NLMSG_LENGTH宏提供要发送的数据的长度,它会自动计算对齐后的总长度:

  1. /计算包含报头的数据报长度/
  2. #define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(sizeof(struct nlmsghdr)))
  3. /字节对齐/
  4. #define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )

后面还可以看到很多netlink提供的宏,这些宏可以为我们编写netlink宏提供很大的方便。

字段 nlmsg_type 用于应用内部定义消息的类型,它对 netlink 内核实现是透明的,因此大部分情况下设置为 0,字段 nlmsg_flags 用于设置消息标志,对于一般的使用,用户把它设置为 0 就可以,只是一些高级应用(如 netfilter 和路由 daemon 需要它进行一些复杂的操作),字段 nlmsg_seq 和 nlmsg_pid 用于应用追踪消息,前者表示顺序号,后者为消息来源进程 ID。

  1. struct msg_to_kernel /自定义消息首部,它仅包含了netlink的消息首部/

  2. {

  3. struct nlmsghdr hdr; //这个必须包含

  4. //以下是自定义的消息内容,以我代码为例

  5. char flag; //a,d,s:分别代表增,删,查
    int time; //定时器,功能用于内核自己实现每多长时间将ip删除
    char data[MSG_LEN]; //存储ip地址

  6. };

  7. struct msg_to_kernel message;

  8. //以下是初始化消息
    struct msg_to_kernel message;
    char send_ip[BUF_LEN]={’\0’};
    char send_fuction;
    int time_clock;

    memset(&message.hdr,0, sizeof(struct nlmsghdr));
    message.hdr.nlmsg_len = NLMSG_SPACE(MSG_LEN)+1;
    message.hdr.nlmsg_flags = 0;
    message.hdr.nlmsg_type = 0;
    message.hdr.nlmsg_seq = 0;
    message.hdr.nlmsg_pid = local.nl_pid;
    printf(“input the ip: “);
    fgets(send_ip, BUF_LEN, stdin);
    printf(“input the fuction: “);
    scanf(”%c”,&send_fuction);
    getchar();
    if(send_fuction==‘a’)
    {
    printf(“input the time_clock:”);
    scanf(”%d”,&time_clock);
    }

    memcpy(message.data,send_ip,strlen(send_ip));
    message.flag=send_fuction;
    message.time=time_clock;

    if(send_fuction==‘a’)
    {
    printf(“send to kernel: %s, send_id: %d ,send_fuction: %c ,send_time:%d,send_len: %d\n”,message.data,local.nl_pid,message.flag,message.time,strlen(send_ip)+2);
    }
    else
    {
    printf(“send to kernel: %s, send_id: %d ,send_fuction: %c send_len: %d\n”,message.data,local.nl_pid,message.flag,strlen(send_ip)+1);
    }

  9. 这样,有了本地地址、对端地址和发送的数据,就可以调用发送函数将消息发送给内核了:

  10. /发送一个请求/
    sendto(skfd, &message1, message1.hdr.nlmsg_len, 0,(struct sockaddr*)&kpeer, sizeof(kpeer));

当发送完请求后,就可以调用recv函数簇从内核接收数据了,接收到的数据包含了netlink消息首部和要传输的数据:
13. /接收的数据包含了netlink消息首部和自定义数据结构/
14. struct u_packet_info
15. {
16. struct nlmsghdr hdr;
17. struct packet_info icmp_info;
18. };
19. struct u_packet_info info;
20. while(1)
21. {
22. kpeerlen = sizeof(struct sockaddr_nl);
23. /接收内核空间返回的数据/
24. rcvlen = recvfrom(skfd, &info, sizeof(struct u_packet_info),
25. 0, (struct sockaddr*)&kpeer, &kpeerlen);
26.
27. /处理接收到的数据/
28. ……
29. }
我的代码:
printf(“wating message from kernel!\n”);
while(1)
{
memset(&u_info,0,sizeof(u_info));
int len=sizeof(struct sockaddr_nl);
int ret;
ret=recvfrom(skfd,&u_info,sizeof(user_msg_info),0,(struct sockaddr *)&kpeer,&len);
if(!ret)
{
perror(“recv from kernel error\n”);
close(skfd);
exit(-1);
}
printf(“recv from kernel:%s\n”,u_info.msg);

}

上面的netlink介绍不详细,可以自己搜下相关资料,网上关于用户态传输的数据大部分都是一个请求,我传输的是ip地址+功能(a,d,s)以及一个定时功能,可以查看下我下面附的代码,有关收发数据如何发送接收

内核空间:

static void kernel_receive(struct sock *sk, int len)
{
int config=0;
struct nlmsghdr *nlh=NULL;
struct sk_buff *skb;
skb=skb_get(sk);
int clock;
//char *recv_data=NULL;
char flag;
if(skb->len>=nlmsg_total_size(0))
{
nlh=nlmsg_hdr(skb); //获取用户态发送的消息
Node *node=NULL;
node=NLMSG_DATA(nlh); //获取用户态发送的自定义消息
if(node)
{
printk(“recv_function:%c\n”,node->flag);
printk(“recv_time_clock:%d\n”,node->time);
printk(“recv_ip:%s\n”,node->data);
printk(“recv_ip_len:%d\n”,strlen(node->data));
}
clock=node->time; //获取定时时间
char buffer[strlen(node->data)];
memcpy(buffer,node->data,strlen(node->data)-1);
buffer[strlen(node->data)-1]=’\0’; //以上获取Ip

	flag=node->flag; //获取用户态所发送的ip对应的功能

}
用户态发送的所对应的功能:a,d,s
即在内核态收到ip进行对ip地址做hash表,冲突采用链地址法,即相当于单链表,增加新ip使用尾插法;

hash表的类型:

typedef struct ip_info
{
unsigned int ip;
unsigned int flag; //用于判断hash数组每一个对应的下标值是否存在,存在为1;若要删除,则浪费该空间,将该空间当做单链表头结点
int year;
int month;
int day;
int hour;
int minute;
int sec;
struct ip_info *next;
}ip_info;

ip_info black_list[black_list_len]={0,0,NULL};

内核态处理数据碰到的问题(我所碰到的)

1:ip地址转换成unsigned int

由于kernel没有提供inet_addr()和inet_ntoa()函数的功能,查了下这两个函数的定义,自己编写原理:
inet_addr():
unsigned int ip_str_to_num(const char *buf)

{
unsigned int tmpip[4] = {0};
unsigned int tmpip32 = 0;
sscanf(buf, “%d.%d.%d.%d”, &tmpip[0], &tmpip[1], &tmpip[2], &tmpip[3]);
tmpip32 = (tmpip[3]<<24) | (tmpip[2]<<16) | (tmpip[1]<<8) | tmpip[0];
return tmpip32;
}

inet_ntoa():
#define IP_LEN 17
static inline void ip_num_to_str(unsigned int ip_num)
{
unsigned char ip_str[17]={’\0’};
unsigned char * uip = (unsigned char *)&ip_num;
snprintf(ip_str, IP_LEN , “%d.%d.%d.%d”, uip[0], uip[1], uip[2], uip[3]);
printf("%s\n",ip_str);
}

2:定时器问题:

由于考虑到在新增1个黑名单的ip,设置每过多长时间该ip自动删除
我没有使用在内核开线程或者队列的方法,因为这需要不断的对当前时间与hash表所存储的时间(当多长时间删除)做比较,浪费资源,所以在hook函数中,当每次有外面的主机访问该台机器,再进行时间上的判断.
struct timex txc;
struct rtc_time tm;
do_gettimeofday(&(txc.time));
rtc_time_to_tm(txc.time.tv_sec+3600*8,&tm);
//printk(“UTC time:%d-%d-%d %d:%d:%d\n”,tm.tm_year+1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec);

这里mon需要+1 ,它是从0~11,年代需要加上1900;

第一次写,是为了记录下我当前所做的项目,刚入行,为了以后复习,哈哈.
以下代码能够在linux ubuntu kernel4.4.15环境下运行.

附代码:kernel4.4.15

user.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <linux/netlink.h>
#include <signal.h>

#define MSG_LEN         60
#define BUF_LEN         125 
#define TIME            210
#define NL_IMP2 30
#define MAX_PAYLOAD 1024
struct sockaddr_nl local;
struct sockaddr_nl kpeer;
static int skfd;

struct msg_to_kernel
{
    struct nlmsghdr hdr;
    char flag;
	int time;
    char data[MSG_LEN];
};

typedef struct u_packet_info
{
    struct nlmsghdr hdr;
    char msg[MSG_LEN];
}user_msg_info;



struct msg_to_kernel init_message()
{
	struct msg_to_kernel message;
    char send_ip[BUF_LEN]={'\0'};
    char send_fuction;
	int time_clock;
    
    memset(&message.hdr,0, sizeof(struct nlmsghdr));
    message.hdr.nlmsg_len = NLMSG_SPACE(MSG_LEN)+1;
    message.hdr.nlmsg_flags = 0;
    message.hdr.nlmsg_type = 0;
    message.hdr.nlmsg_seq = 0;
    message.hdr.nlmsg_pid = local.nl_pid;    
    
    printf("input  the  ip: ");
    fgets(send_ip, BUF_LEN, stdin);
    printf("input  the  fuction: ");
    scanf("%c",&send_fuction);
	getchar();
	if(send_fuction=='a')
	{
		printf("input the time_clock:");
		scanf("%d",&time_clock);
	}
	printf("2\n");
    
    //sprintf(NLMSG_DATA(message),"%s%c\n",send_ip,send_fuction);
    //sprintf(message.data,"%s",send_ip);
    //sprintf(message.flag,"%c",send_fuction);
	memcpy(message.data,send_ip,strlen(send_ip));
	message.flag=send_fuction;
	message.time=time_clock;
	//printf("1\n");
	if(send_fuction=='a')
	{
		printf("send  to  kernel: %s,  send_id: %d  ,send_fuction: %c ,send_time:%d,send_len: %d\n",message.data,local.nl_pid,message.flag,message.time,strlen(send_ip)+2);
	}
	else
	{
		printf("send  to  kernel: %s,  send_id: %d  ,send_fuction: %c send_len: %d\n",message.data,local.nl_pid,message.flag,strlen(send_ip)+1);
	}
    //printf("send  to  kernel: %s,  send_id: %d  , send_len: %d\n",message.data,local.nl_pid,strlen(send_ip)+1);


    return message;
	
}
int main()
{
  struct nlmsghdr *nlh=NULL;
  user_msg_info u_info;
  int kpeerlen;
  struct msg_to_kernel message1,message2,message3,message4,message5,message6;
  int sendlen = 0;
  int rcvlen = 0;
  
  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;
  }
  message1=init_message();
  //message2=init_message();
  //message3=init_message();
  //message4=init_message();
  //message5=init_message();
  //message6=init_message();
  memset(&kpeer, 0, sizeof(kpeer));
  kpeer.nl_family = AF_NETLINK;
  kpeer.nl_pid = 0;
  kpeer.nl_groups = 0;

  sendto(skfd, &message1, message1.hdr.nlmsg_len, 0,(struct sockaddr*)&kpeer, sizeof(kpeer));
  //sendto(skfd, &message2, message2.hdr.nlmsg_len, 0,(struct sockaddr*)&kpeer, sizeof(kpeer));
  //sendto(skfd, &message3, message3.hdr.nlmsg_len, 0,(struct sockaddr*)&kpeer, sizeof(kpeer));
  //sendto(skfd, &message4, message4.hdr.nlmsg_len, 0,(struct sockaddr*)&kpeer, sizeof(kpeer));
  //sendto(skfd, &message5, message5.hdr.nlmsg_len, 0,(struct sockaddr*)&kpeer, sizeof(kpeer));
  //sendto(skfd, &message6, message6.hdr.nlmsg_len, 0,(struct sockaddr*)&kpeer, sizeof(kpeer));

  printf("wating message from kernel!\n");
  while(1)
  {
	memset(&u_info,0,sizeof(u_info));
	int len=sizeof(struct sockaddr_nl);
	int ret;
	ret=recvfrom(skfd,&u_info,sizeof(user_msg_info),0,(struct sockaddr *)&kpeer,&len);
	 if(!ret)
	 {
		 perror("recv from kernel error\n");
		 close(skfd);
		 exit(-1);
	 }
	 printf("recv from kernel:%s\n",u_info.msg);

  }
  close(skfd);
  free((void *)nlh);
  return 0;
}

kernel.c

#ifndef __KERNEL__
#define __KERNEL__
#endif

#ifndef MODULE
#define MODULE
#endif

#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 <linux/semaphore.h>
#include <net/sock.h>
#include <linux/rtc.h>

#define IP_LEN 17
#define NETLINK_TEST 30
DEFINE_SEMAPHORE(receive_sem);
#define MAX_MSGSIZE 1024
#define black_list_len 2048
static struct sock *nlfd;
extern struct net init_net;
typedef struct ip_info
{
	unsigned int ip;
	unsigned int flag;
	int year;
	int month;
	int day;
	int hour;
	int minute;
	int sec;
	struct ip_info *next;
}ip_info;

ip_info black_list[black_list_len]={0,0,NULL};
typedef struct node
{
	char flag;
	int time;
	char data[60];
}Node;

int module=0;

void sendmsg_to_usr(char *buff,int dstPID)
{
	struct sk_buff *skb;
	struct nlmsghdr *nlh;
	int len=strlen(buff);
	skb=nlmsg_new(len,GFP_ATOMIC);
	if(!skb)
	{
		printk("netlink alloc failure\n");
		return -1;
	}
	nlh=nlmsg_put(skb,0,0,NETLINK_TEST,len,0);
	if(nlh==NULL)
	{
		printk("nlmsg_put failure\n");
		nlmsg_free(skb);
		return -1;
	}
	memcpy(nlmsg_data(nlh),buff,len);
	netlink_unicast(nlfd,skb,dstPID,MSG_DONTWAIT);

	return;

}

ip_info init_new_data(char *buffer)
{
	ip_info ptf;
	//ptf.ip=inet_addr(buffer);
	unsigned int tmpip[4]={0};
	unsigned int tmpip32=0;
	sscanf(buffer,"%d.%d.%d.%d",&tmpip[0],&tmpip[1],&tmpip[2],&tmpip[3]);
	tmpip32=(tmpip[3]<<24)|(tmpip[2]<<16)|(tmpip[1]<<8)|tmpip[0];
	ptf.ip=tmpip32;
	ptf.flag=1;
	ptf.next=NULL;
	return ptf;
}

unsigned int MOD(ip_info *ptf)
{
	//unsigned int index=ptf->ip % (black_list_len-1);
	unsigned int index=ptf->ip % (black_list_len);
	printk("%u\n",ptf->ip);
	printk("%u\n",index);
	return index;
}


int add_black_ip_list(ip_info Node,unsigned int index,int dstPID)
{
	printk("Node.ip:%u,Node.flag:%d\n",Node.ip,Node.flag);
	printk("flag:%d\n",black_list[index].flag);
	int config=0;
	if(black_list[index].flag==0)
	{
		black_list[index].ip=Node.ip;
		black_list[index].flag=Node.flag;
		black_list[index].year=Node.year;
		black_list[index].month=Node.month;
		black_list[index].day=Node.day;
		black_list[index].hour=Node.hour;
		black_list[index].minute=Node.minute;
		black_list[index].sec=Node.sec;
		black_list[index].next=Node.next;
		config=1;
		unsigned char *uip=(unsigned char *)&Node.ip;
		unsigned char ip_str[18]={'\0'};
		snprintf(ip_str,IP_LEN,"%d.%d.%d.%d",uip[0],uip[1],uip[2],uip[3]);
		printk("add_success: ip:%s,len:%u\n",ip_str,strlen(ip_str));
		printk("black_list[index].ip:%u\n",black_list[index].ip);

			/*struct timex txc;
			struct rtc_time tm;
			do_gettimeofday(&(txc.time));
			rtc_time_to_tm(txc.time.tv_sec+3600*8+clock*60,&tm);
			printk("UTC time:%d-%d-%d %d:%d:%d\n",tm.tm_year+1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec);*/

		return config;
	}
	else
	{
		ip_info *s=&black_list[index];
		if(s->ip==Node.ip)
		{
				config=0;
				printk("%d\n",config);
			printk("add:black_list:the data is exist,add error\n");
			sendmsg_to_usr("the ip is exist,add error",dstPID);
			return config;
		}
		while(NULL!=s->next)
		{
			s=s->next;
			if(s->ip==Node.ip)
			{
				config=0;
				printk("%d\n",config);
				printk("add:black_list:the data is exist,add error\n");
				sendmsg_to_usr("the ip is exist,add error",dstPID);
				return config;
			}
		}
		ip_info *nd=NULL;
		nd=(ip_info *)kmalloc(sizeof(ip_info),GFP_KERNEL);
		nd->ip=Node.ip;
		nd->flag=Node.flag;
		nd->year=Node.year;
		nd->month=Node.month;
		nd->day=Node.day;
		nd->hour=Node.hour;
		nd->minute=Node.minute;
		nd->sec=Node.sec;
		s->next=nd;
		nd->next=NULL;
		config=1;
		unsigned char *uip=(unsigned char *)&Node.ip;
		unsigned char ip_str[18]={'\0'};
		snprintf(ip_str,IP_LEN,"%d.%d.%d.%d",uip[0],uip[1],uip[2],uip[3]);
		printk("add_success: ip:%s,len:%u\n",ip_str,strlen(ip_str));
		printk("blgack_list[index].ip:%u\n",s->ip);
	}
	return config;
}

int delete_black_ip_list(ip_info ptf,unsigned int index,int dstPID)
{
	int config=0;
	if(black_list[index].flag==0)
	{
		printk("delete:black_list:the data you want to delete is not exist\n");
		if(dstPID=0)
		{
			sendmsg_to_usr("the ip is not exist,delete error",dstPID);
		}
		//sendmsg_to_usr("the ip is not exist,delete error",dstPID);
		return config;
	}
	ip_info *ls=&black_list[index];
	ip_info *s=black_list[index].next;
	if(ls->ip==ptf.ip)
	{
		ls->ip=0;
		ls->next=s;
		config=1;
		printk("delete:black_list:success for delete one data\n");
		return config;
	}
	while(s!=NULL)
	{
		if(s->ip==ptf.ip)
		{
			ls->next=s->next;
			config=1;
			s=NULL;
			kfree(s);
			printk("delete:black_list:success for delete one data\n");
			return config;
		}
		ls=ls->next;
		s=s->next;
		/*if(nd==NULL)
		{
			sendmsg_to_usr("the ip is not exist,delete error",dstPID);
			printk("delete:black_list:the data you want to delete is not exist\n");
			return config;
		}*/

	}
	if(s==NULL)
	{
		if(dstPID!=0)
		{
			sendmsg_to_usr("the ip is not exist,delete error",dstPID);
		}
		//sendmsg_to_usr("the ip is not exist,delete error",dstPID);
		printk("delete:black_list:the data you want to delete is not exist\n");
		return config;
	}
	return config;
}

int search_black_ip_list(ip_info ptf,unsigned int index,int dstPID)
{
	int config=0;
	if(black_list[index].flag==0)
	{
		sendmsg_to_usr("the ip is not exist,search error",dstPID);
		printk("search:black_list:the data that you want to search in is not exist\n");
		return config;
	}
	ip_info *s=&black_list[index];
	while(1)
	{
		if(s->ip==ptf.ip)
		{
			config=1;
			unsigned char *uip=(unsigned char *)&ptf.ip;
			unsigned char ip_str[18]={'\0'};
			snprintf(ip_str,IP_LEN,"%d.%d.%d.%d",uip[0],uip[1],uip[2],uip[3]);
			printk("ip_str_len:%d\n",strlen(ip_str));
			printk("search:black_list:%s\n",ip_str);
			return config;
		}
		s=s->next;
		if(s==NULL)
		{
			sendmsg_to_usr("the ip is not exist,search error",dstPID);
			printk("search:black_list:the data that you want to search is not exist\n");
			return config;
		}
	}
	return config;
}

void sendnlmsg(char *message,int dstPID,char *buffer)
{
	char buff[200];
	sprintf(buff,"%s:%s\n",message,buffer);
	struct sk_buff *skb;
	struct nlmsghdr *nlh;
	int len=strlen(buff);
	skb=nlmsg_new(len,GFP_ATOMIC);
	if(!skb)
	{
		printk("netlink alloc failure\n");
		return;
	}
	nlh=nlmsg_put(skb,0,0,NETLINK_TEST,len,0);
	if(nlh==NULL)
	{
		printk("nlmsg_put failure\n");
		nlmsg_free(skb);
		return;
	}
	memcpy(nlmsg_data(nlh),buff,len);
	netlink_unicast(nlfd,skb,dstPID,MSG_DONTWAIT);

	return;
}


static void kernel_receive(struct sock *sk, int len)
{
	int config=0;
	struct nlmsghdr *nlh=NULL;
	struct sk_buff *skb;
	skb=skb_get(sk);
	int clock;
	//char *recv_data=NULL;
	char flag;
	if(skb->len>=nlmsg_total_size(0))
	{
		nlh=nlmsg_hdr(skb);
		Node *node=NULL;
		node=NLMSG_DATA(nlh);
		if(node)
		{
			printk("recv_function:%c\n",node->flag);
			printk("recv_time_clock:%d\n",node->time);
			printk("recv_ip:%s\n",node->data);
			printk("recv_ip_len:%d\n",strlen(node->data));
		}
		clock=node->time;
		char buffer[strlen(node->data)];
		memcpy(buffer,node->data,strlen(node->data)-1);
		buffer[strlen(node->data)-1]='\0';
		//printk("%s\n",buffer);
		//printk("%d\n",strlen(buffer));
		flag=node->flag;
		if(flag=='a')
		{
			ip_info ptf=init_new_data(buffer);
			struct timex txc;
			struct rtc_time tm;
			do_gettimeofday(&(txc.time));
			rtc_time_to_tm(txc.time.tv_sec+3600*8+clock*60,&tm);
			//printk("UTC time:%d-%d-%d %d:%d:%d\n",tm.tm_year+1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec);

			ptf.year=tm.tm_year+1900;
			ptf.month=tm.tm_mon+1;
			ptf.day=tm.tm_mday;
			ptf.hour=tm.tm_hour;
			ptf.minute=tm.tm_min;
			ptf.sec=tm.tm_sec;
			unsigned int index=MOD(&ptf);
			config=add_black_ip_list(ptf,index,nlh->nlmsg_pid);
			if(config==1)
			{
				sendnlmsg("Success for add one ip:",nlh->nlmsg_pid,buffer);
			}
			else
			{
				sendnlmsg("Failure for add one ip:",nlh->nlmsg_pid,buffer);
			}
		}
		else if(flag=='d')
		{
			ip_info ptf=init_new_data(buffer);
			unsigned int index=MOD(&ptf);
			config=delete_black_ip_list(ptf,index,nlh->nlmsg_pid);
			printk("%d\n",config);
			if(config==1)
			{
				sendnlmsg("Success for delete one ip:",nlh->nlmsg_pid,buffer);
			}
			else
			{
				sendnlmsg("Failure for delete one ip:",nlh->nlmsg_pid,buffer);
			}
		}
		else if(flag=='s')
		{
			ip_info ptf=init_new_data(buffer);
			unsigned int index=MOD(&ptf);
			config=search_black_ip_list(ptf,index,nlh->nlmsg_pid);
			printk("%d\n",config);
			if(config==1)
			{
				sendnlmsg("Success for search one ip:",nlh->nlmsg_pid,buffer);
			}
			else
			{
				sendnlmsg("Failure for search one ip:",nlh->nlmsg_pid,buffer);
			}
		}
		else
		{
			printk("the fuction is error\n");
		}
	}
		
		//write_unlock_bh(recv_data);
	return 0; 
}

static unsigned int get_icmp(unsigned int hook,
			     struct sk_buff *skb,
			     const struct net_device *in,
			     const struct net_device *out,
			     int (*okfn)(struct sk_buff *))
{
	
		struct iphdr *ip_hdr = (struct iphdr *)skb_network_header(skb);
		printk("hook:%u\n",ip_hdr->saddr);
	    //printk ("%u.%u.%u.%u\n",((unsigned char *)&ip_hdr->saddr)[0],((unsigned char *)&ip_hdr->saddr)[1],((unsigned char *)&ip_hdr->saddr)[2],((unsigned char *)&ip_hdr->saddr)[3]);
		ip_info *pwd=NULL;
		unsigned int number=ip_hdr->saddr%2048;
		pwd=&black_list[number];
			struct timex txc;
			struct rtc_time tm;
			do_gettimeofday(&(txc.time));
			rtc_time_to_tm(txc.time.tv_sec+3600*8,&tm);
		while(pwd!=NULL)
		{
			if(pwd->flag==0)
			{
				break;
			}
			if(pwd->ip==ip_hdr->saddr)
			{
				printk("REJECT\n");
				printk("pwd:%d-%d-%d,%d:%d:%d\n",pwd->year,pwd->month,pwd->day,pwd->hour,pwd->minute,pwd->sec);
				printk("now:%d-%d-%d,%d:%d:%d\n",tm.tm_year+1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec);

				if(pwd->year>tm.tm_year+1900)
				{
			        return NF_DROP; 
                }
		        else if(pwd->year==tm.tm_year+1900)
		        {
					if(pwd->month>tm.tm_mon+1)
					{
						return NF_DROP;
					}
					else if(pwd->month==tm.tm_mon+1)
					{
						if(pwd->day>tm.tm_mday)
						{
							return NF_DROP;
						}
						else if(pwd->day==tm.tm_mday)
						{
							if(pwd->hour>tm.tm_hour)
							{
								return NF_DROP;
							}
							else if(pwd->hour==tm.tm_hour)
							{
								if(pwd->minute>tm.tm_min)
								{
									printk("first\n");
									return NF_DROP;
								}
								else if(pwd->minute==tm.tm_min)
								{
									if(pwd->sec>tm.tm_sec)
									{
										return NF_DROP;
									}
									else if(pwd->sec==tm.tm_sec)
									{
										return NF_ACCEPT;
									}
									else
									{
										ip_info ptf;
										ptf.ip=pwd->ip;
										ptf.flag=1;
										unsigned int index=MOD(&ptf);
										delete_black_ip_list(ptf,index,0);
										return NF_ACCEPT;
									}
								}
								else
								{
									ip_info ptf;
									ptf.ip=pwd->ip;
									ptf.flag=1;
									unsigned int index=MOD(&ptf);
									delete_black_ip_list(ptf,index,0);
									return NF_ACCEPT;
								}
							}
							else
							{
								ip_info ptf;
								ptf.ip=pwd->ip;
								ptf.flag=1;
								unsigned int index=MOD(&ptf);
								delete_black_ip_list(ptf,index,0);
								return NF_ACCEPT;
							}
						}
						else
						{
							ip_info ptf;
							ptf.ip=pwd->ip;
							ptf.flag=1;
							unsigned int index=MOD(&ptf);
							delete_black_ip_list(ptf,index,0);
							return NF_ACCEPT;
						}
					}
					else
					{
						ip_info ptf;
						ptf.ip=pwd->ip;
						ptf.flag=1;
						unsigned int index=MOD(&ptf);
						delete_black_ip_list(ptf,index,0);
						return NF_ACCEPT;
					}
				}
				else
				{
					ip_info ptf;
					ptf.ip=pwd->ip;
					ptf.flag=1;
					unsigned int index=MOD(&ptf);
					delete_black_ip_list(ptf,index,0);
					return NF_ACCEPT;
				}
			}
			pwd=pwd->next;
		}

  return NF_ACCEPT;
}


static struct nf_hook_ops imp2_ops =
{
  .hook = get_icmp,
  .pf = PF_INET,
  //.hooknum = NF_IP_PRE_ROUTING,
  .hooknum = NF_INET_PRE_ROUTING,
  .priority = NF_IP_PRI_FILTER -1,
};
struct netlink_kernel_cfg cfg={
	.input = kernel_receive,
};


static int __init init(void)
{
	nlfd = (struct sock *)netlink_kernel_create(&init_net,NETLINK_TEST,&cfg);
    if(!nlfd)
    {
      printk("can not create a netlink socket\n");
      return -1;
    }
    printk("__init_netlink\n");
	nf_register_hook(&imp2_ops);
}

static void __exit fini(void)
{
	if(nlfd)
    {
      sock_release(nlfd->sk_socket);
    }
    nf_unregister_hook(&imp2_ops);
}

module_init(init);
module_exit(fini);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值