用户空间
用户态应用使用标准的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等函数调用
- static int skfd;
- skfd = socket(PF_NETLINK, SOCK_RAW, NL_IMP2);
- if(skfd < 0)
- {
-
printf("can not create a netlink socket\n");
-
exit(0);
- }
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,表示调用者不加入任何多播组:
- struct sockaddr_nl local;
- memset(&local, 0, sizeof(local));
- local.nl_family = AF_NETLINK;
- local.nl_pid = getpid(); /设置pid为自己的pid值/
- local.nl_groups = 0;
- /绑定套接字/
- if(bind(skfd, (struct sockaddr*)&local, sizeof(local)) != 0)
- {
- printf(“bind() error\n”);
-
return -1;
- }
用户空间可以调用send函数簇向内核发送消息,如sendto、sendmsg等,同样地,也可以使用struct sockaddr_nl来描述一个对端地址,以待send函数来调用,与本地地址稍不同的是,因为对端为内核,所以nl_pid成员需要设置为0:
- struct sockaddr_nl kpeer;
- memset(&kpeer, 0, sizeof(kpeer));
- kpeer.nl_family = AF_NETLINK;
- kpeer.nl_pid = 0;
- kpeer.nl_groups = 0;
另一个问题就是发内核发送的消息的组成,使用我们发送一个IP网络数据包的话,则数据包结构为“IP包头+IP数据”,同样地,netlink的消息结构是“netlink消息头部+数据”。Netlink消息头部使用struct nlmsghdr结构来描述:
- struct nlmsghdr
- {
- __u32 nlmsg_len; /* Length of message */
- __u16 nlmsg_type; /* Message type*/
- __u16 nlmsg_flags; /* Additional flags */
- __u32 nlmsg_seq; /* Sequence number */
- __u32 nlmsg_pid; /* Sending process PID */
- };
字段 nlmsg_len 指定消息的总长度,包括紧跟该结构的数据部分长度以及该结构的大小,一般地,我们使用netlink提供的宏NLMSG_LENGTH来计算这个长度,仅需向NLMSG_LENGTH宏提供要发送的数据的长度,它会自动计算对齐后的总长度:
- /计算包含报头的数据报长度/
- #define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(sizeof(struct nlmsghdr)))
- /字节对齐/
- #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。
-
struct msg_to_kernel /自定义消息首部,它仅包含了netlink的消息首部/
-
{
-
struct nlmsghdr hdr; //这个必须包含
-
//以下是自定义的消息内容,以我代码为例
-
char flag; //a,d,s:分别代表增,删,查
int time; //定时器,功能用于内核自己实现每多长时间将ip删除
char data[MSG_LEN]; //存储ip地址 -
};
-
struct msg_to_kernel 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);
}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);
} -
这样,有了本地地址、对端地址和发送的数据,就可以调用发送函数将消息发送给内核了:
-
/发送一个请求/
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);