OCT commit rpdb
This commit is contained in:
parent
c80692156c
commit
1962e94d4c
|
@ -0,0 +1,296 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
|
||||
|
||||
/*
|
||||
* 三元组超时时间设置为120s
|
||||
*/
|
||||
int dpi_cache_node_timeout = 120;
|
||||
|
||||
/*
|
||||
* 三元组数据结构
|
||||
*/
|
||||
struct dpi_cache_node {
|
||||
struct list_head list;
|
||||
|
||||
union {
|
||||
struct in6_addr ip6;
|
||||
struct in_addr ip4;
|
||||
|
||||
}ip;
|
||||
|
||||
__u16 proto;
|
||||
__u16 port;
|
||||
__u32 appid;
|
||||
uint64_t uptime;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 初始化cache链表
|
||||
*/
|
||||
#define TRIPLE_CAHCE_HASH_SIZE (2048)
|
||||
struct list_head dpi_cache_head[TRIPLE_CAHCE_HASH_SIZE] = {0};
|
||||
|
||||
typedef struct pkt_info{
|
||||
unsigned int srcip;
|
||||
unsigned short sport;
|
||||
unsigned int dstip;
|
||||
unsigned short dport;
|
||||
unsigned short proto;
|
||||
}pkt_info_t;
|
||||
|
||||
#define POLY 0x01101 // CRC20生成多项式x^20+x^12+x^8+1即:01101 CRC32:04C11DB7L
|
||||
static unsigned int crc_table[256] = {0};
|
||||
|
||||
unsigned int get_sum_poly(unsigned char data)
|
||||
{
|
||||
unsigned int sum_poly = data;
|
||||
int j;
|
||||
sum_poly <<= 24;
|
||||
for(j = 0; j < 8; j++)
|
||||
{
|
||||
int hi = sum_poly&0x80000000; // 取得reg的最高位
|
||||
sum_poly <<= 1;
|
||||
if(hi) sum_poly = sum_poly^POLY;
|
||||
}
|
||||
return sum_poly;
|
||||
}
|
||||
|
||||
void create_crc_table(void) //在使用CRC20_key函数应该先建立crc表
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 256; i++)
|
||||
{
|
||||
crc_table[i] = get_sum_poly(i&0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int CRC20_key(unsigned char* data, int len)
|
||||
{
|
||||
int i;
|
||||
unsigned int reg = 0xFFFFFFFF;// 0xFFFFFFFF,见后面解释
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
reg = (reg<<8) ^ crc_table[((reg>>24)&0xFF) ^ data[i]];
|
||||
}
|
||||
return (reg&0XFFFFF);//得到的reg取后20作为key值
|
||||
}
|
||||
|
||||
/*
|
||||
* 初始化dpi三元组hash链表
|
||||
*/
|
||||
void dpi_cache_list_init(void)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < TRIPLE_CAHCE_HASH_SIZE; i++){
|
||||
INIT_LIST_HEAD(&dpi_cache_head[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 三元组hash值计算
|
||||
*/
|
||||
int dpi_cache_node_hash(struct dpi_cache_node node)
|
||||
{
|
||||
int i = 0;
|
||||
int dip = 0;
|
||||
|
||||
pkt_info_t info;
|
||||
info.dport = node.port;
|
||||
info.sport = 0;
|
||||
info.srcip = 0;
|
||||
info.proto = node.proto;
|
||||
if (node.ip.ip4.s_addr !=0 ) {
|
||||
info.dstip = node.ip.ip4.s_addr;
|
||||
} else {
|
||||
for (i = 0; i < 4; ++i) {
|
||||
dip ^= node.ip.ip6.s6_addr32[i];
|
||||
}
|
||||
info.dstip = dip;
|
||||
}
|
||||
|
||||
return CRC20_key((unsigned char *)&info, sizeof(pkt_info_t))&(TRIPLE_CAHCE_HASH_SIZE - 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* src 和dst比较,并更新dst的appid,update_appid=true,update
|
||||
*/
|
||||
bool dpi_cache_node_compare(struct dpi_cache_node src,struct dpi_cache_node dst,bool update_appid)
|
||||
{
|
||||
int i = 0;
|
||||
if (src.port != dst.port){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (src.proto != dst.proto){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(src.ip.ip4.s_addr != 0){
|
||||
if(src.ip.ip4.s_addr != dst.ip.ip4.s_addr){
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
for (i = 0; i < 4; i++){
|
||||
if (src.ip.ip6.s6_addr32[i] != dst.ip.ip6.s6_addr32[i]){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (update_appid){
|
||||
dst.appid = src.appid;
|
||||
dst.uptime = get_jiffies_64();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*遍历hash链表,查找node
|
||||
*/
|
||||
bool dpi_cache_node_search(struct dpi_cache_node node,int flag)
|
||||
{
|
||||
struct list_head * pList;
|
||||
struct dpi_cache_node *pNode;
|
||||
int hash = dpi_cache_node_hash(node);
|
||||
list_for_each(pList,&dpi_cache_head[hash]){
|
||||
pNode = list_entry(pList,struct dpi_cache_node,list);
|
||||
if (dpi_cache_node_compare(node,*pNode,flag)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DPI 信息记录,外部接口调用
|
||||
*/
|
||||
bool dpi_cache_node_add(struct dpi_cache_node node)
|
||||
{
|
||||
int hash = 0;
|
||||
struct dpi_cache_node *pNode =NULL;
|
||||
|
||||
if (dpi_cache_node_search(node,true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
pNode = kmalloc(sizeof(struct dpi_cache_node), GFP_KERNEL);
|
||||
if (NULL == pNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hash = dpi_cache_node_hash(node);
|
||||
pNode->uptime = get_jiffies_64();
|
||||
pNode->appid = node.appid;
|
||||
list_add_tail(&pNode->list,&dpi_cache_head[hash]);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 释放hash链表上所有node节点
|
||||
*/
|
||||
void dpi_cache_list_release(void)
|
||||
{
|
||||
struct list_head * pList = NULL;
|
||||
struct dpi_cache_node *pNode = NULL;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < TRIPLE_CAHCE_HASH_SIZE; i++){
|
||||
list_for_each(pList,&dpi_cache_head[i]){
|
||||
pNode = list_entry(pList,struct dpi_cache_node,list);
|
||||
if(pNode){
|
||||
list_del(&pNode->list);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*定时器超时,删除超时的节点
|
||||
*/
|
||||
void dpi_cache_node_timeout_func(void)
|
||||
{
|
||||
struct list_head * pList = NULL;
|
||||
struct dpi_cache_node *pNode = NULL;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < TRIPLE_CAHCE_HASH_SIZE; i++){
|
||||
list_for_each(pList,&dpi_cache_head[i]){
|
||||
pNode = list_entry(pList,struct dpi_cache_node,list);
|
||||
if(pNode&&
|
||||
(get_jiffies_64() - pNode->uptime >= dpi_cache_node_timeout)){
|
||||
list_del(&pNode->list);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 定时器操作
|
||||
*/
|
||||
struct timer_list gTimer;
|
||||
|
||||
void dpi_cache_timer_handler(unsigned long data) {
|
||||
printk(KERN_INFO"timer pending:%d\n", timer_pending(&gTimer));
|
||||
dpi_cache_node_timeout_func();
|
||||
mod_timer(&gTimer, jiffies+msecs_to_jiffies(dpi_cache_node_timeout*1000));
|
||||
|
||||
}
|
||||
|
||||
int dpi_cache_timer_init(void) {
|
||||
printk(KERN_INFO"%s jiffies:%ld\n", __func__, jiffies);
|
||||
printk(KERN_INFO"ji:%d,HZ:%d\n", jiffies_to_msecs(250), HZ);
|
||||
init_timer(&gTimer);
|
||||
gTimer.expires = jiffies + dpi_cache_node_timeout*HZ;
|
||||
gTimer.function = dpi_cache_timer_handler;
|
||||
add_timer(&gTimer);
|
||||
printk(KERN_INFO"timer pending:%d\n", timer_pending(&gTimer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dpi_cache_timer_exit(void) {
|
||||
printk(KERN_INFO"%s jiffies:%ld\n", __func__, jiffies);
|
||||
del_timer(&gTimer);
|
||||
}
|
||||
|
||||
int dpi_cahce_module_init(void)
|
||||
{
|
||||
dpi_cache_timer_init();
|
||||
dpi_cache_list_init();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dpi_cache_module_exit(void)
|
||||
{
|
||||
dpi_cache_timer_exit();
|
||||
dpi_cache_list_release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
module_init(dpi_cahce_module_init);
|
||||
module_exit(dpi_cache_timer_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
|
@ -0,0 +1,641 @@
|
|||
#ifndef _LINUX_LIST_H
|
||||
#define _LINUX_LIST_H
|
||||
|
||||
#define container_of(ptr,type,member) ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
|
||||
|
||||
|
||||
//#if defined(__KERNEL__) || defined(_LVM_H_INCLUDE)
|
||||
|
||||
//#include <linux/prefetch.h>
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
typedef struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
} list_t;
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
#define INIT_LIST_HEAD(ptr) do { \
|
||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
|
||||
static void inline prefetch(void *p){}
|
||||
|
||||
static inline void __list_add(struct list_head *new,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head->prev, head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_del(struct list_head *prev, struct list_head *next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
|
||||
*/
|
||||
static inline void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
entry->next = (void *) 0;
|
||||
entry->prev = (void *) 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_replace - replace old entry by new one
|
||||
* @old : the element to be replaced
|
||||
* @new : the new element to insert
|
||||
*
|
||||
* If @old was empty, it will be overwritten.
|
||||
*/
|
||||
static inline void list_replace(struct list_head *old,
|
||||
struct list_head *new)
|
||||
{
|
||||
new->next = old->next;
|
||||
new->next->prev = new;
|
||||
new->prev = old->prev;
|
||||
new->prev->next = new;
|
||||
}
|
||||
|
||||
static inline void list_replace_init(struct list_head *old,
|
||||
struct list_head *new)
|
||||
{
|
||||
list_replace(old, new);
|
||||
INIT_LIST_HEAD(old);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
static inline void list_del_init(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move - delete from one list and add as another's head
|
||||
* @list: the entry to move
|
||||
* @head: the head that will precede our entry
|
||||
*/
|
||||
static inline void list_move(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move_tail - delete from one list and add as another's tail
|
||||
* @list: the entry to move
|
||||
* @head: the head that will follow our entry
|
||||
*/
|
||||
static inline void list_move_tail(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add_tail(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty(const struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
static inline void __list_splice(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
struct list_head *last = list->prev;
|
||||
struct list_head *at = head->next;
|
||||
|
||||
first->prev = head;
|
||||
head->next = first;
|
||||
|
||||
last->next = at;
|
||||
at->prev = last;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice - join two lists
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
static inline void list_splice(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list))
|
||||
__list_splice(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice_init - join two lists and reinitialise the emptied list.
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*
|
||||
* The list at @list is reinitialised
|
||||
*/
|
||||
static inline void list_splice_init(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list)) {
|
||||
__list_splice(list, head);
|
||||
INIT_LIST_HEAD(list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_head within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
container_of(ptr, type, member)
|
||||
|
||||
/**
|
||||
* list_first_entry - get the first element from a list
|
||||
* @ptr: the list head to take the element from.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_head within the struct.
|
||||
*
|
||||
* Note, that list is expected to be not empty.
|
||||
*/
|
||||
#define list_first_entry(ptr, type, member) \
|
||||
list_entry((ptr)->next, type, member)
|
||||
|
||||
/**
|
||||
* list_last_entry - get the last element from a list
|
||||
* @ptr: the list head to take the element from.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_head within the struct.
|
||||
*
|
||||
* Note, that list is expected to be not empty.
|
||||
*/
|
||||
#define list_last_entry(ptr, type, member) \
|
||||
list_entry((ptr)->prev, type, member)
|
||||
|
||||
/**
|
||||
* list_first_entry_or_null - get the first element from a list
|
||||
* @ptr: the list head to take the element from.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_head within the struct.
|
||||
*
|
||||
* Note that if the list is empty, it returns NULL.
|
||||
*/
|
||||
#define list_first_entry_or_null(ptr, type, member) \
|
||||
(!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
|
||||
|
||||
/**
|
||||
* list_next_entry - get the next element in list
|
||||
* @pos: the type * to cursor
|
||||
* @member: the name of the list_head within the struct.
|
||||
*/
|
||||
#define list_next_entry(pos, member) \
|
||||
list_entry((pos)->member.next, typeof(*(pos)), member)
|
||||
|
||||
/**
|
||||
* list_prev_entry - get the prev element in list
|
||||
* @pos: the type * to cursor
|
||||
* @member: the name of the list_head within the struct.
|
||||
*/
|
||||
#define list_prev_entry(pos, member) \
|
||||
list_entry((pos)->member.prev, typeof(*(pos)), member)
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_prev - iterate over a list backwards
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev; pos != (head); pos = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev_safe(pos, n, head) \
|
||||
for (pos = (head)->prev, n = pos->prev; \
|
||||
pos != (head); \
|
||||
pos = n, n = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_head within the struct.
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_first_entry(head, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_next_entry(pos, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_reverse - iterate backwards over list of given type.
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_head within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_reverse(pos, head, member) \
|
||||
for (pos = list_last_entry(head, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_prev_entry(pos, member))
|
||||
|
||||
/**
|
||||
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
|
||||
* @pos: the type * to use as a start point
|
||||
* @head: the head of the list
|
||||
* @member: the name of the list_head within the struct.
|
||||
*
|
||||
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
|
||||
*/
|
||||
#define list_prepare_entry(pos, head, member) \
|
||||
((pos) ? : list_entry(head, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_continue - continue iteration over list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_head within the struct.
|
||||
*
|
||||
* Continue to iterate over list of given type, continuing after
|
||||
* the current position.
|
||||
*/
|
||||
#define list_for_each_entry_continue(pos, head, member) \
|
||||
for (pos = list_next_entry(pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_next_entry(pos, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_continue_reverse - iterate backwards from the given point
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_head within the struct.
|
||||
*
|
||||
* Start to iterate over list of given type backwards, continuing after
|
||||
* the current position.
|
||||
*/
|
||||
#define list_for_each_entry_continue_reverse(pos, head, member) \
|
||||
for (pos = list_prev_entry(pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_prev_entry(pos, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_from - iterate over list of given type from the current point
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_head within the struct.
|
||||
*
|
||||
* Iterate over list of given type, continuing from current position.
|
||||
*/
|
||||
#define list_for_each_entry_from(pos, head, member) \
|
||||
for (; &pos->member != (head); \
|
||||
pos = list_next_entry(pos, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_head within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = list_first_entry(head, typeof(*pos), member), \
|
||||
n = list_next_entry(pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_next_entry(n, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe_continue - continue list iteration safe against removal
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_head within the struct.
|
||||
*
|
||||
* Iterate over list of given type, continuing after current point,
|
||||
* safe against removal of list entry.
|
||||
*/
|
||||
#define list_for_each_entry_safe_continue(pos, n, head, member) \
|
||||
for (pos = list_next_entry(pos, member), \
|
||||
n = list_next_entry(pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_next_entry(n, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe_from - iterate over list from current point safe against removal
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_head within the struct.
|
||||
*
|
||||
* Iterate over list of given type from current point, safe against
|
||||
* removal of list entry.
|
||||
*/
|
||||
#define list_for_each_entry_safe_from(pos, n, head, member) \
|
||||
for (n = list_next_entry(pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_next_entry(n, member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_head within the struct.
|
||||
*
|
||||
* Iterate backwards over list of given type, safe against removal
|
||||
* of list entry.
|
||||
*/
|
||||
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
|
||||
for (pos = list_last_entry(head, typeof(*pos), member), \
|
||||
n = list_prev_entry(pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_prev_entry(n, member))
|
||||
|
||||
/**
|
||||
* list_safe_reset_next - reset a stale list_for_each_entry_safe loop
|
||||
* @pos: the loop cursor used in the list_for_each_entry_safe loop
|
||||
* @n: temporary storage used in list_for_each_entry_safe
|
||||
* @member: the name of the list_head within the struct.
|
||||
*
|
||||
* list_safe_reset_next is not safe to use in general if the list may be
|
||||
* modified concurrently (eg. the lock is dropped in the loop body). An
|
||||
* exception to this is if the cursor element (pos) is pinned in the list,
|
||||
* and list_safe_reset_next is called after re-taking the lock and before
|
||||
* completing the current iteration of the loop body.
|
||||
*/
|
||||
#define list_safe_reset_next(pos, n, member) \
|
||||
n = list_next_entry(pos, member)
|
||||
|
||||
|
||||
/*
|
||||
* Double linked lists with a single pointer list head.
|
||||
* Mostly useful for hash tables where the two pointer list head is
|
||||
* too wasteful.
|
||||
* You lose the ability to access the tail in O(1).
|
||||
*/
|
||||
#define LIST_POISON1 NULL
|
||||
#define LIST_POISON2 NULL
|
||||
|
||||
#define READ_ONCE(x) (x)
|
||||
#define WRITE_ONCE(x, val) x=(val)
|
||||
|
||||
|
||||
struct hlist_head {
|
||||
struct hlist_node *first;
|
||||
};
|
||||
|
||||
struct hlist_node {
|
||||
struct hlist_node *next, **pprev;
|
||||
};
|
||||
|
||||
#define HLIST_HEAD_INIT { .first = NULL }
|
||||
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
|
||||
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
|
||||
static inline void INIT_HLIST_NODE(struct hlist_node *h)
|
||||
{
|
||||
h->next = NULL;
|
||||
h->pprev = NULL;
|
||||
}
|
||||
|
||||
static inline int hlist_unhashed(const struct hlist_node *h)
|
||||
{
|
||||
return !h->pprev;
|
||||
}
|
||||
|
||||
static inline int hlist_empty(const struct hlist_head *h)
|
||||
{
|
||||
return !READ_ONCE(h->first);
|
||||
}
|
||||
|
||||
static inline void __hlist_del(struct hlist_node *n)
|
||||
{
|
||||
struct hlist_node *next = n->next;
|
||||
struct hlist_node **pprev = n->pprev;
|
||||
|
||||
WRITE_ONCE(*pprev, next);
|
||||
if (next)
|
||||
next->pprev = pprev;
|
||||
}
|
||||
|
||||
static inline void hlist_del(struct hlist_node *n)
|
||||
{
|
||||
__hlist_del(n);
|
||||
n->next = LIST_POISON1;
|
||||
n->pprev = LIST_POISON2;
|
||||
}
|
||||
|
||||
static inline void hlist_del_init(struct hlist_node *n)
|
||||
{
|
||||
if (!hlist_unhashed(n)) {
|
||||
__hlist_del(n);
|
||||
INIT_HLIST_NODE(n);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
|
||||
{
|
||||
struct hlist_node *first = h->first;
|
||||
n->next = first;
|
||||
if (first)
|
||||
first->pprev = &n->next;
|
||||
WRITE_ONCE(h->first, n);
|
||||
n->pprev = &h->first;
|
||||
}
|
||||
|
||||
/* next must be != NULL */
|
||||
static inline void hlist_add_before(struct hlist_node *n,
|
||||
struct hlist_node *next)
|
||||
{
|
||||
n->pprev = next->pprev;
|
||||
n->next = next;
|
||||
next->pprev = &n->next;
|
||||
WRITE_ONCE(*(n->pprev), n);
|
||||
}
|
||||
|
||||
static inline void hlist_add_behind(struct hlist_node *n,
|
||||
struct hlist_node *prev)
|
||||
{
|
||||
n->next = prev->next;
|
||||
WRITE_ONCE(prev->next, n);
|
||||
n->pprev = &prev->next;
|
||||
|
||||
if (n->next)
|
||||
n->next->pprev = &n->next;
|
||||
}
|
||||
|
||||
/* after that we'll appear to be on some hlist and hlist_del will work */
|
||||
static inline void hlist_add_fake(struct hlist_node *n)
|
||||
{
|
||||
n->pprev = &n->next;
|
||||
}
|
||||
|
||||
static inline int hlist_fake(struct hlist_node *h)
|
||||
{
|
||||
return h->pprev == &h->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the node is the only node of the head without
|
||||
* accessing head:
|
||||
*/
|
||||
static inline int
|
||||
hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h)
|
||||
{
|
||||
return !n->next && n->pprev == &h->first;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move a list from one list head to another. Fixup the pprev
|
||||
* reference of the first entry if it exists.
|
||||
*/
|
||||
static inline void hlist_move_list(struct hlist_head *old,
|
||||
struct hlist_head *new)
|
||||
{
|
||||
new->first = old->first;
|
||||
if (new->first)
|
||||
new->first->pprev = &new->first;
|
||||
old->first = NULL;
|
||||
}
|
||||
|
||||
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
|
||||
|
||||
#define hlist_for_each(pos, head) \
|
||||
for (pos = (head)->first; pos ; pos = pos->next)
|
||||
|
||||
#define hlist_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
|
||||
pos = n)
|
||||
|
||||
#define hlist_entry_safe(ptr, type, member) \
|
||||
({ typeof(ptr) ____ptr = (ptr); \
|
||||
____ptr ? hlist_entry(____ptr, type, member) : NULL; \
|
||||
})
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry(pos, head, member) \
|
||||
for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
|
||||
pos; \
|
||||
pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry_continue(pos, member) \
|
||||
for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);\
|
||||
pos; \
|
||||
pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry_from(pos, member) \
|
||||
for (; pos; \
|
||||
pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another &struct hlist_node to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\
|
||||
pos && ({ n = pos->member.next; 1; }); \
|
||||
pos = hlist_entry_safe(n, typeof(*pos), member))
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,468 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "list.h"
|
||||
|
||||
|
||||
|
||||
struct rpdb_mark {
|
||||
struct list_head list;
|
||||
union {
|
||||
struct in6_addr ip6;
|
||||
struct in_addr ip4;
|
||||
|
||||
}ip;
|
||||
|
||||
int mark;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
char rt_table[11][128]= {
|
||||
"# reserved values",
|
||||
"#",
|
||||
"255 local",
|
||||
"254 main",
|
||||
"253 default",
|
||||
"0 unspe",
|
||||
"#",
|
||||
"# local",
|
||||
"#",
|
||||
"#1 inr.ruhep"
|
||||
};
|
||||
|
||||
|
||||
#define RT_TABLES_PATH ("/etc/iproute2/rt_tables")
|
||||
#define IPV4_PATTERN "^([0-9]|[1-9][0-9]|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]).([0-9]|[1-9][0-9]|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]).([0-9]|[1-9][0-9]|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]).([0-9]|[1-9][0-9]|1[0-9]{1,2}|2[0-4][0-9]|25[0-5])$"
|
||||
#define IPV6_PATTERN "^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$"
|
||||
|
||||
#define RPDP_MARK_HASH_DEPTH (1024)
|
||||
static int gRpdbMark = 0;
|
||||
|
||||
/*
|
||||
* mark hash list,save mark
|
||||
*/
|
||||
struct list_head gRpdbMarkList[RPDP_MARK_HASH_DEPTH] = {0};
|
||||
|
||||
|
||||
/*
|
||||
popen
|
||||
*/
|
||||
|
||||
|
||||
void
|
||||
print_result(FILE *fp)
|
||||
{
|
||||
char buf[100];
|
||||
|
||||
if(!fp) {
|
||||
return;
|
||||
}
|
||||
printf("\n>>>\n");
|
||||
memset(buf, 0, sizeof(buf));
|
||||
fgets(buf, sizeof(buf) - 1, fp) ;
|
||||
|
||||
|
||||
printf("%s", buf);
|
||||
|
||||
|
||||
printf("\n<<<\n");
|
||||
}
|
||||
|
||||
int rpdb_popen(char *cmd)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
|
||||
|
||||
fp = NULL;
|
||||
fp = popen(cmd, "r");
|
||||
if(!fp)
|
||||
{
|
||||
perror("popen");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
print_result(fp);
|
||||
pclose(fp);
|
||||
sleep(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* rpdb 初始化接口
|
||||
*/
|
||||
bool rpdb_init_route()
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
int i = 0;
|
||||
|
||||
system("echo > /etc/iproute2/rt_tables");
|
||||
fp = fopen(RT_TABLES_PATH,"w");
|
||||
if (fp)
|
||||
{
|
||||
for (i = 0; i < 11; i++)
|
||||
{
|
||||
fprintf(fp,"%s\n",rt_table[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
|
||||
/*
|
||||
初始化链表
|
||||
*/
|
||||
for (i = 0; i < RPDP_MARK_HASH_DEPTH; i++)
|
||||
{
|
||||
INIT_LIST_HEAD(&gRpdbMarkList[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int gRpdbTableIndex = 1; /* 1 - 252 */
|
||||
#define RPDB_TABLE_ADD (0)
|
||||
#define RPDB_TABLE_DEL (1)
|
||||
bool rpdb_add_delete_table(const char* gateway,const char *tbl_name,int op)
|
||||
{
|
||||
char table_name[128] = {0};
|
||||
char line_cnt[1024] = {0};
|
||||
FILE *fp = NULL;
|
||||
FILE *fp_tmp = NULL;
|
||||
bool ret = false;
|
||||
int i = 0;
|
||||
int cn_num = 0;
|
||||
if (tbl_name == NULL)
|
||||
{
|
||||
memset(table_name,0,sizeof(table_name));
|
||||
sprintf(table_name,"table_%s",gateway);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(tbl_name) < 1) /* 检查name的合法性*/
|
||||
{
|
||||
memset(table_name,0,sizeof(table_name));
|
||||
sprintf(table_name,"%s",tbl_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fp = fopen(RT_TABLES_PATH,"ra+");
|
||||
if (NULL == fp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(!feof(fp)) /* 遍历文件每一行,查找 路由表是否存在 */
|
||||
{
|
||||
memset(line_cnt,0,1024);
|
||||
fgets(line_cnt,1024,fp);
|
||||
if(strstr(line_cnt,table_name))
|
||||
{
|
||||
if (op == RPDB_TABLE_ADD)
|
||||
{
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
向文件最后一行添加 路由表项
|
||||
*/
|
||||
if (op == RPDB_TABLE_ADD)
|
||||
{
|
||||
if (gRpdbTableIndex > 252)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(line_cnt,0,1024);
|
||||
sprintf(line_cnt,"%d %s",gRpdbTableIndex,table_name);
|
||||
printf("RPDB_TABLE_ADD:%s\n",line_cnt);
|
||||
fprintf(fp,"%s\n",line_cnt);
|
||||
fclose(fp);
|
||||
gRpdbTableIndex++;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (op == RPDB_TABLE_DEL)
|
||||
{
|
||||
fp = fopen(RT_TABLES_PATH,"r+");
|
||||
if (NULL == fp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fp_tmp = fopen("/tmp/rt_tables","w");
|
||||
if (fp_tmp == NULL) return false;
|
||||
while(!feof(fp)) /* 遍历文件每一行,查找 路由表是否存在 */
|
||||
{
|
||||
memset(line_cnt,0,1024);
|
||||
fgets(line_cnt,1024,fp);
|
||||
if(!strstr(line_cnt,table_name))
|
||||
{
|
||||
fprintf(fp_tmp,"%s",line_cnt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
fclose(fp_tmp);
|
||||
system("cp -fr /tmp/rt_tables /etc/iproute2/rt_tables");
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* 判断ip地址是否合法
|
||||
*/
|
||||
|
||||
int rpdb_ipaddr_match(char *ip_addr,int flag)
|
||||
{
|
||||
regex_t reg;
|
||||
regmatch_t match[1];
|
||||
int retval = 0;
|
||||
|
||||
if (flag == 1)
|
||||
{
|
||||
retval = regcomp(®, IPV4_PATTERN, REG_EXTENDED | REG_NEWLINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = regcomp(®, IPV6_PATTERN, REG_EXTENDED | REG_NEWLINE);
|
||||
}
|
||||
|
||||
retval = regexec(®,ip_addr, sizeof match / sizeof match[0], match, 0);
|
||||
printf("%s is %s\n", ip_addr, retval == 0 ? "legal" : "illegal");
|
||||
regfree(®);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
int rpdb_ip_hash(struct rpdb_mark node)
|
||||
{
|
||||
int ip_value = 0;
|
||||
int hash = 0;
|
||||
int i = 0;
|
||||
if (node.ip.ip4.s_addr !=0 )
|
||||
{
|
||||
ip_value = node.ip.ip4.s_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
ip_value += node.ip.ip6.s6_addr32[i];
|
||||
}
|
||||
}
|
||||
hash = (ip_value&0xF) + ((ip_value >> 8)&0xF) + ((ip_value >> 16)&0xF) + ((ip_value >> 24)&0xF);
|
||||
hash = hash&(1024-1);
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* node比较
|
||||
*/
|
||||
|
||||
bool rpdb_mark_node_compare(struct rpdb_mark node1,struct rpdb_mark node2)
|
||||
{
|
||||
if (node1.ip.ip4.s_addr == node2.ip.ip4.s_addr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* mark 查找,返回链上的node节点
|
||||
*/
|
||||
struct rpdb_mark * rpdb_mark_search(struct rpdb_mark node)
|
||||
{
|
||||
struct list_head * pList;
|
||||
struct rpdb_mark *pNode;
|
||||
int hash = rpdb_ip_hash(node);
|
||||
|
||||
list_for_each(pList,&gRpdbMarkList[hash]) {
|
||||
pNode = list_entry(pList,struct rpdb_mark,list);
|
||||
printf("%s,%d,%d,%d\n",__FUNCTION__,__LINE__,pNode->ip.ip4.s_addr,pNode->mark);
|
||||
if (rpdb_mark_node_compare(node,*pNode)){
|
||||
printf("%s,%d,mark = %d\n",__FUNCTION__,__LINE__,pNode->mark);
|
||||
return pNode;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* mark
|
||||
*/
|
||||
int rpdb_mark_hash_add(struct rpdb_mark node)
|
||||
{
|
||||
|
||||
struct rpdb_mark *pNode = NULL;
|
||||
int hash = 0;
|
||||
|
||||
pNode = rpdb_mark_search(node);
|
||||
if (pNode != NULL)
|
||||
{
|
||||
return pNode->mark;
|
||||
}
|
||||
|
||||
pNode = (struct rpdb_mark*)malloc(sizeof(struct rpdb_mark));
|
||||
if (NULL == pNode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
hash = rpdb_ip_hash(node);
|
||||
node.mark = ++gRpdbMark;
|
||||
memcpy((char*)pNode,(char*)&node,sizeof(struct rpdb_mark));
|
||||
|
||||
printf("%s,%d,%d,%d\n",__FUNCTION__,__LINE__,pNode->ip.ip4.s_addr,pNode->mark);
|
||||
/*
|
||||
节点添加到链尾部
|
||||
*/
|
||||
list_add_tail(&pNode->list,&gRpdbMarkList[hash]);
|
||||
|
||||
return gRpdbMark;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 根据下一跳地址生成mark
|
||||
*/
|
||||
int rpdb_gen_mark(const char* gateway)
|
||||
{
|
||||
in_addr_t addr;
|
||||
if (NULL == gateway)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr = inet_addr(gateway);
|
||||
struct rpdb_mark node;
|
||||
node.ip.ip4.s_addr = addr;
|
||||
return rpdb_mark_hash_add(node);
|
||||
}
|
||||
|
||||
/*
|
||||
* 路由添加接口
|
||||
*/
|
||||
bool rpdb_add_route(const char* gateway,const char *tbl_name)
|
||||
{
|
||||
char cmd[256] = {0};
|
||||
int status = 0;
|
||||
char table_name[128] = {0};
|
||||
int mark = 0;
|
||||
if (tbl_name == NULL)
|
||||
{
|
||||
memset(table_name,0,sizeof(table_name));
|
||||
sprintf(table_name,"table_%s",gateway);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(tbl_name) < 1) /* 检查name的合法性*/
|
||||
{
|
||||
memset(table_name,0,sizeof(table_name));
|
||||
sprintf(table_name,"%s",tbl_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (rpdb_add_delete_table(gateway,tbl_name,RPDB_TABLE_ADD) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strstr(":",gateway))
|
||||
{
|
||||
sprintf(cmd,"ip -6 route add default via %s table %s",gateway,table_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(cmd,"ip route add default via %s table %s",gateway,table_name);
|
||||
}
|
||||
|
||||
printf("%s\n",cmd);
|
||||
rpdb_popen(cmd);
|
||||
|
||||
mark = rpdb_gen_mark(gateway);
|
||||
memset(cmd,0,sizeof(cmd));
|
||||
sprintf(cmd,"ip rule add fwmark %d table %s",mark,table_name);
|
||||
printf("%s\n",cmd);
|
||||
rpdb_popen(cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
//ipaddr_match("192.168.1.1",1);
|
||||
|
||||
//ipaddr_match("192.168.1.300",1);
|
||||
|
||||
//ipaddr_match("2000:0:0:0:0:0:0:1 ",2);
|
||||
//ipaddr_match("fe80:0000:0000:0000:0204:61ff:fe9d:ffffff15",2);
|
||||
struct rpdb_mark mark_value;
|
||||
struct rpdb_mark mark_value1;
|
||||
in_addr_t addr;
|
||||
rpdb_init_route();
|
||||
rpdb_add_delete_table("1.1.2.1",NULL,RPDB_TABLE_ADD);
|
||||
rpdb_add_delete_table("1.1.2.1",NULL,RPDB_TABLE_ADD);
|
||||
rpdb_add_delete_table("1.2.2.1",NULL,RPDB_TABLE_ADD);
|
||||
rpdb_add_delete_table("2.1.2.1",NULL,RPDB_TABLE_ADD);
|
||||
|
||||
rpdb_add_delete_table("2.1.2.1",NULL,RPDB_TABLE_DEL);
|
||||
//rpdb_add_delete_table("2.1.2.1",NULL,RPDB_TABLE_DEL);
|
||||
//rpdb_add_delete_table("1.1.2.1",NULL,RPDB_TABLE_DEL);
|
||||
addr = inet_addr("2006.6.6.6");
|
||||
mark_value.ip.ip4.s_addr = addr;
|
||||
rpdb_mark_hash_add(mark_value);
|
||||
rpdb_mark_hash_add(mark_value);
|
||||
rpdb_mark_hash_add(mark_value);
|
||||
rpdb_mark_hash_add(mark_value);
|
||||
|
||||
addr = inet_addr("7.7.7.7");
|
||||
mark_value1.ip.ip4.s_addr = addr;
|
||||
rpdb_mark_hash_add(mark_value1);
|
||||
rpdb_mark_hash_add(mark_value1);
|
||||
|
||||
|
||||
|
||||
rpdb_add_route("1.2.3.3",NULL);
|
||||
rpdb_add_route("2.2.4.3",NULL);
|
||||
rpdb_add_route("3.2.4.3",NULL);
|
||||
rpdb_add_route("4.2.4.3",NULL);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue