增加地域白名单
This commit is contained in:
parent
706299cd4c
commit
b8bd3f3afe
10
Makefile
10
Makefile
@ -2,12 +2,20 @@ CROSS_COMPILE ?=
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
CFLAGS += -Os -g -Wall
|
||||
LIB += -lcurl -lip4tc
|
||||
|
||||
IPTC_CFLAGS += -DHAVE_CONFIG_H -I./libiptc -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D_REENTRANT
|
||||
|
||||
OBG = rhost
|
||||
|
||||
all: conf.o rhost.o libiptc.o
|
||||
$(CC) $(CFLAGS) $^ -o $(OBG) $(LIB)
|
||||
chmod +x $(OBG)
|
||||
|
||||
|
||||
static: conf.o rhost.o libiptc.o
|
||||
$(CC) $(IPTC_CFLAGS) -c libiptc/libip4tc.c -o libiptc/libip4tc.o
|
||||
ar crs libiptc/libip4tc.a libiptc/libip4tc.o
|
||||
$(CC) $(CFLAGS) $^ -o $(OBG) libiptc/libip4tc.o -lcurl
|
||||
|
||||
clean:
|
||||
rm -rf *.o
|
||||
rm $(OBG)
|
||||
|
20
conf.c
20
conf.c
@ -168,6 +168,17 @@ static void parse_global_module(char *content, conf * conf)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (strcasecmp(var, "REGION") == 0) {
|
||||
val_begin_len = val_end - val_begin;
|
||||
conf->REGION = atoi(val_begin);
|
||||
}
|
||||
|
||||
if (strcasecmp(var, "REGION_LIST") == 0) {
|
||||
val_begin_len = val_end - val_begin;
|
||||
if (copy_new_mem(val_begin, val_begin_len, &conf->REGION_LIST) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
content = strchr(lineEnd + 1, '\n');
|
||||
@ -248,6 +259,9 @@ void free_conf(conf * conf)
|
||||
if (conf->IPV4_WHITE_LIST)
|
||||
free(conf->IPV4_WHITE_LIST);
|
||||
|
||||
if (conf->REGION_LIST)
|
||||
free(conf->REGION_LIST);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -272,8 +286,14 @@ void ptintf_conf(conf * conf)
|
||||
printf("%s\n", conf->RECV_MAIL);
|
||||
if (conf->PUBLIC_IP)
|
||||
printf("%s\n", conf->PUBLIC_IP);
|
||||
|
||||
printf("%d\n", conf->IPV4_RESTRICTION);
|
||||
if (conf->IPV4_WHITE_LIST)
|
||||
printf("%s\n", conf->IPV4_WHITE_LIST);
|
||||
|
||||
printf("%d\n", conf->REGION);
|
||||
if (conf->REGION_LIST)
|
||||
printf("%s\n", conf->REGION_LIST);
|
||||
}
|
||||
|
||||
void split_string(char string[], char delims[], char (*whitelist_ip)[WHITELIST_IP_NUM])
|
||||
|
4
conf.h
4
conf.h
@ -18,6 +18,10 @@ typedef struct CONF {
|
||||
|
||||
// 获取公网IP Url地址
|
||||
char *PUBLIC_IP;
|
||||
|
||||
// 地域白名单
|
||||
int REGION;
|
||||
char *REGION_LIST;
|
||||
|
||||
// IPV4 白名单
|
||||
int IPV4_RESTRICTION;
|
||||
|
@ -34,7 +34,7 @@ function run()
|
||||
netstat -tnulp &>> ${LOG_FILE}
|
||||
|
||||
echo "System SSH authorization information:" &>> ${LOG_FILE}
|
||||
/root/denyhosts/rhost | awk '{a[$1]+=1;} END {for(i in a){print a[i]" "i;}}' &>> ${LOG_FILE}
|
||||
/root/denyhosts/rhost | grep -E "^[0-9]" | awk '{a[$1]+=1;} END {for(i in a){print a[i]" "i;}}' &>> ${LOG_FILE}
|
||||
|
||||
$IPTABLES_SAVE > /root/ipv4tables
|
||||
|
||||
|
BIN
libiptc/libip4tc.a
Normal file
BIN
libiptc/libip4tc.a
Normal file
Binary file not shown.
311
libiptc/libip4tc.c
Normal file
311
libiptc/libip4tc.c
Normal file
@ -0,0 +1,311 @@
|
||||
/* Library which manipulates firewall rules. Version 0.1. */
|
||||
|
||||
/* Architecture of firewall rules is as follows:
|
||||
*
|
||||
* Chains go INPUT, FORWARD, OUTPUT then user chains.
|
||||
* Each user chain starts with an ERROR node.
|
||||
* Every chain ends with an unconditional jump: a RETURN for user chains,
|
||||
* and a POLICY for built-ins.
|
||||
*/
|
||||
|
||||
/* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
|
||||
COPYING for details). */
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef DEBUG_CONNTRACK
|
||||
#define inline
|
||||
#endif
|
||||
|
||||
#if !defined(__BIONIC__) && (!defined(__GLIBC__) || (__GLIBC__ < 2))
|
||||
typedef unsigned int socklen_t;
|
||||
#endif
|
||||
|
||||
#include "libiptc/libiptc.h"
|
||||
|
||||
#define IP_VERSION 4
|
||||
#define IP_OFFSET 0x1FFF
|
||||
|
||||
#define HOOK_PRE_ROUTING NF_IP_PRE_ROUTING
|
||||
#define HOOK_LOCAL_IN NF_IP_LOCAL_IN
|
||||
#define HOOK_FORWARD NF_IP_FORWARD
|
||||
#define HOOK_LOCAL_OUT NF_IP_LOCAL_OUT
|
||||
#define HOOK_POST_ROUTING NF_IP_POST_ROUTING
|
||||
|
||||
#define STRUCT_ENTRY_TARGET struct xt_entry_target
|
||||
#define STRUCT_ENTRY struct ipt_entry
|
||||
#define STRUCT_ENTRY_MATCH struct xt_entry_match
|
||||
#define STRUCT_GETINFO struct ipt_getinfo
|
||||
#define STRUCT_GET_ENTRIES struct ipt_get_entries
|
||||
#define STRUCT_COUNTERS struct xt_counters
|
||||
#define STRUCT_COUNTERS_INFO struct xt_counters_info
|
||||
#define STRUCT_STANDARD_TARGET struct xt_standard_target
|
||||
#define STRUCT_REPLACE struct ipt_replace
|
||||
|
||||
#define ENTRY_ITERATE IPT_ENTRY_ITERATE
|
||||
#define TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
|
||||
#define FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
|
||||
|
||||
#define GET_TARGET ipt_get_target
|
||||
|
||||
#define ERROR_TARGET XT_ERROR_TARGET
|
||||
#define NUMHOOKS NF_IP_NUMHOOKS
|
||||
|
||||
#define IPT_CHAINLABEL xt_chainlabel
|
||||
|
||||
#define TC_DUMP_ENTRIES dump_entries
|
||||
#define TC_IS_CHAIN iptc_is_chain
|
||||
#define TC_FIRST_CHAIN iptc_first_chain
|
||||
#define TC_NEXT_CHAIN iptc_next_chain
|
||||
#define TC_FIRST_RULE iptc_first_rule
|
||||
#define TC_NEXT_RULE iptc_next_rule
|
||||
#define TC_GET_TARGET iptc_get_target
|
||||
#define TC_BUILTIN iptc_builtin
|
||||
#define TC_GET_POLICY iptc_get_policy
|
||||
#define TC_INSERT_ENTRY iptc_insert_entry
|
||||
#define TC_REPLACE_ENTRY iptc_replace_entry
|
||||
#define TC_APPEND_ENTRY iptc_append_entry
|
||||
#define TC_CHECK_ENTRY iptc_check_entry
|
||||
#define TC_DELETE_ENTRY iptc_delete_entry
|
||||
#define TC_DELETE_NUM_ENTRY iptc_delete_num_entry
|
||||
#define TC_FLUSH_ENTRIES iptc_flush_entries
|
||||
#define TC_ZERO_ENTRIES iptc_zero_entries
|
||||
#define TC_READ_COUNTER iptc_read_counter
|
||||
#define TC_ZERO_COUNTER iptc_zero_counter
|
||||
#define TC_SET_COUNTER iptc_set_counter
|
||||
#define TC_CREATE_CHAIN iptc_create_chain
|
||||
#define TC_GET_REFERENCES iptc_get_references
|
||||
#define TC_DELETE_CHAIN iptc_delete_chain
|
||||
#define TC_RENAME_CHAIN iptc_rename_chain
|
||||
#define TC_SET_POLICY iptc_set_policy
|
||||
#define TC_GET_RAW_SOCKET iptc_get_raw_socket
|
||||
#define TC_INIT iptc_init
|
||||
#define TC_FREE iptc_free
|
||||
#define TC_COMMIT iptc_commit
|
||||
#define TC_STRERROR iptc_strerror
|
||||
#define TC_NUM_RULES iptc_num_rules
|
||||
#define TC_GET_RULE iptc_get_rule
|
||||
#define TC_OPS iptc_ops
|
||||
|
||||
#define TC_AF AF_INET
|
||||
#define TC_IPPROTO IPPROTO_IP
|
||||
|
||||
#define SO_SET_REPLACE IPT_SO_SET_REPLACE
|
||||
#define SO_SET_ADD_COUNTERS IPT_SO_SET_ADD_COUNTERS
|
||||
#define SO_GET_INFO IPT_SO_GET_INFO
|
||||
#define SO_GET_ENTRIES IPT_SO_GET_ENTRIES
|
||||
#define SO_GET_VERSION IPT_SO_GET_VERSION
|
||||
|
||||
#define STANDARD_TARGET XT_STANDARD_TARGET
|
||||
#define LABEL_RETURN IPTC_LABEL_RETURN
|
||||
#define LABEL_ACCEPT IPTC_LABEL_ACCEPT
|
||||
#define LABEL_DROP IPTC_LABEL_DROP
|
||||
#define LABEL_QUEUE IPTC_LABEL_QUEUE
|
||||
|
||||
#define ALIGN XT_ALIGN
|
||||
#define RETURN XT_RETURN
|
||||
|
||||
#include "libiptc.c"
|
||||
|
||||
#define IP_PARTS_NATIVE(n) \
|
||||
(unsigned int)((n)>>24)&0xFF, \
|
||||
(unsigned int)((n)>>16)&0xFF, \
|
||||
(unsigned int)((n)>>8)&0xFF, \
|
||||
(unsigned int)((n)&0xFF)
|
||||
|
||||
#define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n))
|
||||
|
||||
static int
|
||||
dump_entry(struct ipt_entry *e, struct xtc_handle *const handle)
|
||||
{
|
||||
size_t i;
|
||||
STRUCT_ENTRY_TARGET *t;
|
||||
|
||||
printf("Entry %u (%lu):\n", iptcb_entry2index(handle, e),
|
||||
iptcb_entry2offset(handle, e));
|
||||
printf("SRC IP: %u.%u.%u.%u/%u.%u.%u.%u\n",
|
||||
IP_PARTS(e->ip.src.s_addr),IP_PARTS(e->ip.smsk.s_addr));
|
||||
printf("DST IP: %u.%u.%u.%u/%u.%u.%u.%u\n",
|
||||
IP_PARTS(e->ip.dst.s_addr),IP_PARTS(e->ip.dmsk.s_addr));
|
||||
printf("Interface: `%s'/", e->ip.iniface);
|
||||
for (i = 0; i < IFNAMSIZ; i++)
|
||||
printf("%c", e->ip.iniface_mask[i] ? 'X' : '.');
|
||||
printf("to `%s'/", e->ip.outiface);
|
||||
for (i = 0; i < IFNAMSIZ; i++)
|
||||
printf("%c", e->ip.outiface_mask[i] ? 'X' : '.');
|
||||
printf("\nProtocol: %u\n", e->ip.proto);
|
||||
printf("Flags: %02X\n", e->ip.flags);
|
||||
printf("Invflags: %02X\n", e->ip.invflags);
|
||||
printf("Counters: %llu packets, %llu bytes\n",
|
||||
(unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
|
||||
printf("Cache: %08X\n", e->nfcache);
|
||||
|
||||
IPT_MATCH_ITERATE(e, print_match);
|
||||
|
||||
t = GET_TARGET(e);
|
||||
printf("Target name: `%s' [%u]\n", t->u.user.name, t->u.target_size);
|
||||
if (strcmp(t->u.user.name, STANDARD_TARGET) == 0) {
|
||||
const unsigned char *data = t->data;
|
||||
int pos = *(const int *)data;
|
||||
if (pos < 0)
|
||||
printf("verdict=%s\n",
|
||||
pos == -NF_ACCEPT-1 ? "NF_ACCEPT"
|
||||
: pos == -NF_DROP-1 ? "NF_DROP"
|
||||
: pos == -NF_QUEUE-1 ? "NF_QUEUE"
|
||||
: pos == RETURN ? "RETURN"
|
||||
: "UNKNOWN");
|
||||
else
|
||||
printf("verdict=%u\n", pos);
|
||||
} else if (strcmp(t->u.user.name, XT_ERROR_TARGET) == 0)
|
||||
printf("error=`%s'\n", t->data);
|
||||
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b, unsigned char *matchmask)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned char *mptr;
|
||||
|
||||
/* Always compare head structures: ignore mask here. */
|
||||
if (a->ip.src.s_addr != b->ip.src.s_addr
|
||||
|| a->ip.dst.s_addr != b->ip.dst.s_addr
|
||||
|| a->ip.smsk.s_addr != b->ip.smsk.s_addr
|
||||
|| a->ip.dmsk.s_addr != b->ip.dmsk.s_addr
|
||||
|| a->ip.proto != b->ip.proto
|
||||
|| a->ip.flags != b->ip.flags
|
||||
|| a->ip.invflags != b->ip.invflags)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < IFNAMSIZ; i++) {
|
||||
if (a->ip.iniface_mask[i] != b->ip.iniface_mask[i])
|
||||
return NULL;
|
||||
if ((a->ip.iniface[i] & a->ip.iniface_mask[i])
|
||||
!= (b->ip.iniface[i] & b->ip.iniface_mask[i]))
|
||||
return NULL;
|
||||
if (a->ip.outiface_mask[i] != b->ip.outiface_mask[i])
|
||||
return NULL;
|
||||
if ((a->ip.outiface[i] & a->ip.outiface_mask[i])
|
||||
!= (b->ip.outiface[i] & b->ip.outiface_mask[i]))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (a->target_offset != b->target_offset
|
||||
|| a->next_offset != b->next_offset)
|
||||
return NULL;
|
||||
|
||||
mptr = matchmask + sizeof(STRUCT_ENTRY);
|
||||
if (IPT_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr))
|
||||
return NULL;
|
||||
mptr += XT_ALIGN(sizeof(struct xt_entry_target));
|
||||
|
||||
return mptr;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/***************************** DEBUGGING ********************************/
|
||||
static inline int
|
||||
unconditional(const struct ipt_ip *ip)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < sizeof(*ip)/sizeof(uint32_t); i++)
|
||||
if (((uint32_t *)ip)[i])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
check_match(const STRUCT_ENTRY_MATCH *m, unsigned int *off)
|
||||
{
|
||||
assert(m->u.match_size >= sizeof(STRUCT_ENTRY_MATCH));
|
||||
assert(ALIGN(m->u.match_size) == m->u.match_size);
|
||||
|
||||
(*off) += m->u.match_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
check_entry(const STRUCT_ENTRY *e, unsigned int *i, unsigned int *off,
|
||||
unsigned int user_offset, int *was_return,
|
||||
struct xtc_handle *h)
|
||||
{
|
||||
unsigned int toff;
|
||||
STRUCT_STANDARD_TARGET *t;
|
||||
|
||||
assert(e->target_offset >= sizeof(STRUCT_ENTRY));
|
||||
assert(e->next_offset >= e->target_offset
|
||||
+ sizeof(STRUCT_ENTRY_TARGET));
|
||||
toff = sizeof(STRUCT_ENTRY);
|
||||
IPT_MATCH_ITERATE(e, check_match, &toff);
|
||||
|
||||
assert(toff == e->target_offset);
|
||||
|
||||
t = (STRUCT_STANDARD_TARGET *)
|
||||
GET_TARGET((STRUCT_ENTRY *)e);
|
||||
/* next_offset will have to be multiple of entry alignment. */
|
||||
assert(e->next_offset == ALIGN(e->next_offset));
|
||||
assert(e->target_offset == ALIGN(e->target_offset));
|
||||
assert(t->target.u.target_size == ALIGN(t->target.u.target_size));
|
||||
assert(!TC_IS_CHAIN(t->target.u.user.name, h));
|
||||
|
||||
if (strcmp(t->target.u.user.name, STANDARD_TARGET) == 0) {
|
||||
assert(t->target.u.target_size
|
||||
== ALIGN(sizeof(STRUCT_STANDARD_TARGET)));
|
||||
|
||||
assert(t->verdict == -NF_DROP-1
|
||||
|| t->verdict == -NF_ACCEPT-1
|
||||
|| t->verdict == RETURN
|
||||
|| t->verdict < (int)h->entries->size);
|
||||
|
||||
if (t->verdict >= 0) {
|
||||
STRUCT_ENTRY *te = get_entry(h, t->verdict);
|
||||
int idx;
|
||||
|
||||
idx = iptcb_entry2index(h, te);
|
||||
assert(strcmp(GET_TARGET(te)->u.user.name,
|
||||
XT_ERROR_TARGET)
|
||||
!= 0);
|
||||
assert(te != e);
|
||||
|
||||
/* Prior node must be error node, or this node. */
|
||||
assert(t->verdict == iptcb_entry2offset(h, e)+e->next_offset
|
||||
|| strcmp(GET_TARGET(index2entry(h, idx-1))
|
||||
->u.user.name, XT_ERROR_TARGET)
|
||||
== 0);
|
||||
}
|
||||
|
||||
if (t->verdict == RETURN
|
||||
&& unconditional(&e->ip)
|
||||
&& e->target_offset == sizeof(*e))
|
||||
*was_return = 1;
|
||||
else
|
||||
*was_return = 0;
|
||||
} else if (strcmp(t->target.u.user.name, XT_ERROR_TARGET) == 0) {
|
||||
assert(t->target.u.target_size
|
||||
== ALIGN(sizeof(struct ipt_error_target)));
|
||||
|
||||
/* If this is in user area, previous must have been return */
|
||||
if (*off > user_offset)
|
||||
assert(*was_return);
|
||||
|
||||
*was_return = 0;
|
||||
}
|
||||
else *was_return = 0;
|
||||
|
||||
if (*off == user_offset)
|
||||
assert(strcmp(t->target.u.user.name, XT_ERROR_TARGET) == 0);
|
||||
|
||||
(*off) += e->next_offset;
|
||||
(*i)++;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
BIN
libiptc/libip4tc.o
Normal file
BIN
libiptc/libip4tc.o
Normal file
Binary file not shown.
2751
libiptc/libiptc.c
Normal file
2751
libiptc/libiptc.c
Normal file
File diff suppressed because it is too large
Load Diff
723
libiptc/linux_list.h
Normal file
723
libiptc/linux_list.h
Normal file
@ -0,0 +1,723 @@
|
||||
#ifndef _LINUX_LIST_H
|
||||
#define _LINUX_LIST_H
|
||||
|
||||
#undef offsetof
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||
|
||||
/**
|
||||
* container_of - cast a member of a structure out to the containing structure
|
||||
*
|
||||
* @ptr: the pointer to the member.
|
||||
* @type: the type of the container struct this is embedded in.
|
||||
* @member: the name of the member within the struct.
|
||||
*
|
||||
*/
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||
|
||||
/*
|
||||
* Check at compile time that something is of a particular type.
|
||||
* Always evaluates to 1 so you may use it easily in comparisons.
|
||||
*/
|
||||
#define typecheck(type,x) \
|
||||
({ type __dummy; \
|
||||
typeof(x) __dummy2; \
|
||||
(void)(&__dummy == &__dummy2); \
|
||||
1; \
|
||||
})
|
||||
|
||||
#define prefetch(x) ((void)0)
|
||||
|
||||
/* empty define to make this work in userspace -HW */
|
||||
#define smp_wmb()
|
||||
|
||||
/*
|
||||
* These are non-NULL pointers that will result in page faults
|
||||
* under normal circumstances, used to verify that nobody uses
|
||||
* non-initialized list entries.
|
||||
*/
|
||||
#define LIST_POISON1 ((void *) 0x00100100)
|
||||
#define LIST_POISON2 ((void *) 0x00200200)
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#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 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 inline void __list_add_rcu(struct list_head * new,
|
||||
struct list_head * prev, struct list_head * next)
|
||||
{
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
smp_wmb();
|
||||
next->prev = new;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_rcu - add a new entry to rcu-protected list
|
||||
* @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.
|
||||
*
|
||||
* The caller must take whatever precautions are necessary
|
||||
* (such as holding appropriate locks) to avoid racing
|
||||
* with another list-mutation primitive, such as list_add_rcu()
|
||||
* or list_del_rcu(), running on this same list.
|
||||
* However, it is perfectly legal to run concurrently with
|
||||
* the _rcu list-traversal primitives, such as
|
||||
* list_for_each_entry_rcu().
|
||||
*/
|
||||
static inline void list_add_rcu(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add_rcu(new, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_tail_rcu - add a new entry to rcu-protected list
|
||||
* @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.
|
||||
*
|
||||
* The caller must take whatever precautions are necessary
|
||||
* (such as holding appropriate locks) to avoid racing
|
||||
* with another list-mutation primitive, such as list_add_tail_rcu()
|
||||
* or list_del_rcu(), running on this same list.
|
||||
* However, it is perfectly legal to run concurrently with
|
||||
* the _rcu list-traversal primitives, such as
|
||||
* list_for_each_entry_rcu().
|
||||
*/
|
||||
static inline void list_add_tail_rcu(struct list_head *new,
|
||||
struct list_head *head)
|
||||
{
|
||||
__list_add_rcu(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 = LIST_POISON1;
|
||||
entry->prev = LIST_POISON2;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_rcu - deletes entry from list without re-initialization
|
||||
* @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. It is useful for RCU based
|
||||
* lockfree traversal.
|
||||
*
|
||||
* In particular, it means that we can not poison the forward
|
||||
* pointers that may still be used for walking the list.
|
||||
*
|
||||
* The caller must take whatever precautions are necessary
|
||||
* (such as holding appropriate locks) to avoid racing
|
||||
* with another list-mutation primitive, such as list_del_rcu()
|
||||
* or list_add_rcu(), running on this same list.
|
||||
* However, it is perfectly legal to run concurrently with
|
||||
* the _rcu list-traversal primitives, such as
|
||||
* list_for_each_entry_rcu().
|
||||
*
|
||||
* Note that the caller is not permitted to immediately free
|
||||
* the newly deleted entry. Instead, either synchronize_kernel()
|
||||
* or call_rcu() must be used to defer freeing until an RCU
|
||||
* grace period has elapsed.
|
||||
*/
|
||||
static inline void list_del_rcu(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
entry->prev = LIST_POISON2;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty_careful - tests whether a list is
|
||||
* empty _and_ checks that no other CPU might be
|
||||
* in the process of still modifying either member
|
||||
*
|
||||
* NOTE: using list_empty_careful() without synchronization
|
||||
* can only be safe if the only activity that can happen
|
||||
* to the list entry is list_del_init(). Eg. it cannot be used
|
||||
* if another CPU could re-list_add() it.
|
||||
*
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty_careful(const struct list_head *head)
|
||||
{
|
||||
struct list_head *next = head->next;
|
||||
return (next == head) && (next == head->prev);
|
||||
}
|
||||
|
||||
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_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
container_of(ptr, type, member)
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next, prefetch(pos->next); pos != (head); \
|
||||
pos = pos->next, prefetch(pos->next))
|
||||
|
||||
/**
|
||||
* __list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*
|
||||
* This variant differs from list_for_each() in that it's the
|
||||
* simplest possible list iteration code, no prefetching is done.
|
||||
* Use this for code that knows the list to be very short (empty
|
||||
* or 1 entry) most of the time.
|
||||
*/
|
||||
#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 counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
|
||||
pos = pos->prev, prefetch(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 counter.
|
||||
* @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_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_reverse - iterate backwards over list of given type.
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_reverse(pos, head, member) \
|
||||
for (pos = list_entry((head)->prev, typeof(*pos), member), \
|
||||
prefetch(pos->member.prev); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.prev, typeof(*pos), member), \
|
||||
prefetch(pos->member.prev))
|
||||
|
||||
/**
|
||||
* list_prepare_entry - prepare a pos entry for use as a start point 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_struct within the struct.
|
||||
*/
|
||||
#define list_prepare_entry(pos, head, member) \
|
||||
((pos) ? : list_entry(head, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_continue - iterate over list of given type
|
||||
* continuing after existing point
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_continue(pos, head, member) \
|
||||
for (pos = list_entry(pos->member.next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next))
|
||||
|
||||
/**
|
||||
* 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 counter.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||
|
||||
/**
|
||||
* list_for_each_rcu - iterate over an rcu-protected list
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*
|
||||
* This list-traversal primitive may safely run concurrently with
|
||||
* the _rcu list-mutation primitives such as list_add_rcu()
|
||||
* as long as the traversal is guarded by rcu_read_lock().
|
||||
*/
|
||||
#define list_for_each_rcu(pos, head) \
|
||||
for (pos = (head)->next, prefetch(pos->next); pos != (head); \
|
||||
pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next))
|
||||
|
||||
#define __list_for_each_rcu(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); \
|
||||
pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
|
||||
|
||||
/**
|
||||
* list_for_each_safe_rcu - iterate over an rcu-protected list safe
|
||||
* against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*
|
||||
* This list-traversal primitive may safely run concurrently with
|
||||
* the _rcu list-mutation primitives such as list_add_rcu()
|
||||
* as long as the traversal is guarded by rcu_read_lock().
|
||||
*/
|
||||
#define list_for_each_safe_rcu(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_entry_rcu - iterate over rcu list of given type
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* This list-traversal primitive may safely run concurrently with
|
||||
* the _rcu list-mutation primitives such as list_add_rcu()
|
||||
* as long as the traversal is guarded by rcu_read_lock().
|
||||
*/
|
||||
#define list_for_each_entry_rcu(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member), \
|
||||
({ smp_read_barrier_depends(); 0;}), \
|
||||
prefetch(pos->member.next))
|
||||
|
||||
|
||||
/**
|
||||
* list_for_each_continue_rcu - iterate over an rcu-protected list
|
||||
* continuing after existing point.
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*
|
||||
* This list-traversal primitive may safely run concurrently with
|
||||
* the _rcu list-mutation primitives such as list_add_rcu()
|
||||
* as long as the traversal is guarded by rcu_read_lock().
|
||||
*/
|
||||
#define list_for_each_continue_rcu(pos, head) \
|
||||
for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
|
||||
(pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next))
|
||||
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
|
||||
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)
|
||||
#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->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 !h->first;
|
||||
}
|
||||
|
||||
static inline void __hlist_del(struct hlist_node *n)
|
||||
{
|
||||
struct hlist_node *next = n->next;
|
||||
struct hlist_node **pprev = n->pprev;
|
||||
*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;
|
||||
}
|
||||
|
||||
/**
|
||||
* hlist_del_rcu - deletes entry from hash list without re-initialization
|
||||
* @n: the element to delete from the hash list.
|
||||
*
|
||||
* Note: list_unhashed() on entry does not return true after this,
|
||||
* the entry is in an undefined state. It is useful for RCU based
|
||||
* lockfree traversal.
|
||||
*
|
||||
* In particular, it means that we can not poison the forward
|
||||
* pointers that may still be used for walking the hash list.
|
||||
*
|
||||
* The caller must take whatever precautions are necessary
|
||||
* (such as holding appropriate locks) to avoid racing
|
||||
* with another list-mutation primitive, such as hlist_add_head_rcu()
|
||||
* or hlist_del_rcu(), running on this same list.
|
||||
* However, it is perfectly legal to run concurrently with
|
||||
* the _rcu list-traversal primitives, such as
|
||||
* hlist_for_each_entry().
|
||||
*/
|
||||
static inline void hlist_del_rcu(struct hlist_node *n)
|
||||
{
|
||||
__hlist_del(n);
|
||||
n->pprev = LIST_POISON2;
|
||||
}
|
||||
|
||||
static inline void hlist_del_init(struct hlist_node *n)
|
||||
{
|
||||
if (n->pprev) {
|
||||
__hlist_del(n);
|
||||
INIT_HLIST_NODE(n);
|
||||
}
|
||||
}
|
||||
|
||||
#define hlist_del_rcu_init hlist_del_init
|
||||
|
||||
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;
|
||||
h->first = n;
|
||||
n->pprev = &h->first;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hlist_add_head_rcu - adds the specified element to the specified hlist,
|
||||
* while permitting racing traversals.
|
||||
* @n: the element to add to the hash list.
|
||||
* @h: the list to add to.
|
||||
*
|
||||
* The caller must take whatever precautions are necessary
|
||||
* (such as holding appropriate locks) to avoid racing
|
||||
* with another list-mutation primitive, such as hlist_add_head_rcu()
|
||||
* or hlist_del_rcu(), running on this same list.
|
||||
* However, it is perfectly legal to run concurrently with
|
||||
* the _rcu list-traversal primitives, such as
|
||||
* hlist_for_each_entry(), but only if smp_read_barrier_depends()
|
||||
* is used to prevent memory-consistency problems on Alpha CPUs.
|
||||
* Regardless of the type of CPU, the list-traversal primitive
|
||||
* must be guarded by rcu_read_lock().
|
||||
*
|
||||
* OK, so why don't we have an hlist_for_each_entry_rcu()???
|
||||
*/
|
||||
static inline void hlist_add_head_rcu(struct hlist_node *n,
|
||||
struct hlist_head *h)
|
||||
{
|
||||
struct hlist_node *first = h->first;
|
||||
n->next = first;
|
||||
n->pprev = &h->first;
|
||||
smp_wmb();
|
||||
if (first)
|
||||
first->pprev = &n->next;
|
||||
h->first = n;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
*(n->pprev) = n;
|
||||
}
|
||||
|
||||
static inline void hlist_add_after(struct hlist_node *n,
|
||||
struct hlist_node *next)
|
||||
{
|
||||
next->next = n->next;
|
||||
n->next = next;
|
||||
next->pprev = &n->next;
|
||||
|
||||
if(next->next)
|
||||
next->next->pprev = &next->next;
|
||||
}
|
||||
|
||||
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
|
||||
|
||||
#define hlist_for_each(pos, head) \
|
||||
for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
|
||||
pos = pos->next)
|
||||
|
||||
#define hlist_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
|
||||
pos = n)
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry - iterate over list of given type
|
||||
* @tpos: the type * to use as a loop counter.
|
||||
* @pos: the &struct hlist_node to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry(tpos, pos, head, member) \
|
||||
for (pos = (head)->first; \
|
||||
pos && ({ prefetch(pos->next); 1;}) && \
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry_continue - iterate over a hlist continuing after existing point
|
||||
* @tpos: the type * to use as a loop counter.
|
||||
* @pos: the &struct hlist_node to use as a loop counter.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry_continue(tpos, pos, member) \
|
||||
for (pos = (pos)->next; \
|
||||
pos && ({ prefetch(pos->next); 1;}) && \
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry_from - iterate over a hlist continuing from existing point
|
||||
* @tpos: the type * to use as a loop counter.
|
||||
* @pos: the &struct hlist_node to use as a loop counter.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry_from(tpos, pos, member) \
|
||||
for (; pos && ({ prefetch(pos->next); 1;}) && \
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @tpos: the type * to use as a loop counter.
|
||||
* @pos: the &struct hlist_node to use as a loop counter.
|
||||
* @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(tpos, pos, n, head, member) \
|
||||
for (pos = (head)->first; \
|
||||
pos && ({ n = pos->next; 1; }) && \
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||
pos = n)
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry_rcu - iterate over rcu list of given type
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @pos: the &struct hlist_node to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*
|
||||
* This list-traversal primitive may safely run concurrently with
|
||||
* the _rcu list-mutation primitives such as hlist_add_rcu()
|
||||
* as long as the traversal is guarded by rcu_read_lock().
|
||||
*/
|
||||
#define hlist_for_each_entry_rcu(tpos, pos, head, member) \
|
||||
for (pos = (head)->first; \
|
||||
pos && ({ prefetch(pos->next); 1;}) && \
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||
pos = pos->next, ({ smp_read_barrier_depends(); 0; }) )
|
||||
|
||||
#endif
|
2
libiptc/xtables-version.h
Normal file
2
libiptc/xtables-version.h
Normal file
@ -0,0 +1,2 @@
|
||||
#define XTABLES_VERSION "libxtables.so.12"
|
||||
#define XTABLES_VERSION_CODE 12
|
674
libiptc/xtables.h
Normal file
674
libiptc/xtables.h
Normal file
@ -0,0 +1,674 @@
|
||||
#ifndef _XTABLES_H
|
||||
#define _XTABLES_H
|
||||
|
||||
/*
|
||||
* Changing any structs/functions may incur a needed change
|
||||
* in libxtables_vcurrent/vage too.
|
||||
*/
|
||||
|
||||
#include <sys/socket.h> /* PF_* */
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
|
||||
#ifndef IPPROTO_SCTP
|
||||
#define IPPROTO_SCTP 132
|
||||
#endif
|
||||
#ifndef IPPROTO_DCCP
|
||||
#define IPPROTO_DCCP 33
|
||||
#endif
|
||||
#ifndef IPPROTO_MH
|
||||
# define IPPROTO_MH 135
|
||||
#endif
|
||||
#ifndef IPPROTO_UDPLITE
|
||||
#define IPPROTO_UDPLITE 136
|
||||
#endif
|
||||
|
||||
#include <xtables-version.h>
|
||||
|
||||
struct in_addr;
|
||||
|
||||
/*
|
||||
* .size is here so that there is a somewhat reasonable check
|
||||
* against the chosen .type.
|
||||
*/
|
||||
#define XTOPT_POINTER(stype, member) \
|
||||
.ptroff = offsetof(stype, member), \
|
||||
.size = sizeof(((stype *)NULL)->member)
|
||||
#define XTOPT_TABLEEND {.name = NULL}
|
||||
|
||||
/**
|
||||
* Select the format the input has to conform to, as well as the target type
|
||||
* (area pointed to with XTOPT_POINTER). Note that the storing is not always
|
||||
* uniform. @cb->val will be populated with as much as there is space, i.e.
|
||||
* exactly 2 items for ranges, but the target area can receive more values
|
||||
* (e.g. in case of ranges), or less values (e.g. %XTTYPE_HOSTMASK).
|
||||
*
|
||||
* %XTTYPE_NONE: option takes no argument
|
||||
* %XTTYPE_UINT*: standard integer
|
||||
* %XTTYPE_UINT*RC: colon-separated range of standard integers
|
||||
* %XTTYPE_DOUBLE: double-precision floating point number
|
||||
* %XTTYPE_STRING: arbitrary string
|
||||
* %XTTYPE_TOSMASK: 8-bit TOS value with optional mask
|
||||
* %XTTYPE_MARKMASK32: 32-bit mark with optional mask
|
||||
* %XTTYPE_SYSLOGLEVEL: syslog level by name or number
|
||||
* %XTTYPE_HOST: one host or address (ptr: union nf_inet_addr)
|
||||
* %XTTYPE_HOSTMASK: one host or address, with an optional prefix length
|
||||
* (ptr: union nf_inet_addr; only host portion is stored)
|
||||
* %XTTYPE_PROTOCOL: protocol number/name from /etc/protocols (ptr: uint8_t)
|
||||
* %XTTYPE_PORT: 16-bit port name or number (supports %XTOPT_NBO)
|
||||
* %XTTYPE_PORTRC: colon-separated port range (names acceptable),
|
||||
* (supports %XTOPT_NBO)
|
||||
* %XTTYPE_PLEN: prefix length
|
||||
* %XTTYPE_PLENMASK: prefix length (ptr: union nf_inet_addr)
|
||||
* %XTTYPE_ETHERMAC: Ethernet MAC address in hex form
|
||||
*/
|
||||
enum xt_option_type {
|
||||
XTTYPE_NONE,
|
||||
XTTYPE_UINT8,
|
||||
XTTYPE_UINT16,
|
||||
XTTYPE_UINT32,
|
||||
XTTYPE_UINT64,
|
||||
XTTYPE_UINT8RC,
|
||||
XTTYPE_UINT16RC,
|
||||
XTTYPE_UINT32RC,
|
||||
XTTYPE_UINT64RC,
|
||||
XTTYPE_DOUBLE,
|
||||
XTTYPE_STRING,
|
||||
XTTYPE_TOSMASK,
|
||||
XTTYPE_MARKMASK32,
|
||||
XTTYPE_SYSLOGLEVEL,
|
||||
XTTYPE_HOST,
|
||||
XTTYPE_HOSTMASK,
|
||||
XTTYPE_PROTOCOL,
|
||||
XTTYPE_PORT,
|
||||
XTTYPE_PORTRC,
|
||||
XTTYPE_PLEN,
|
||||
XTTYPE_PLENMASK,
|
||||
XTTYPE_ETHERMAC,
|
||||
};
|
||||
|
||||
/**
|
||||
* %XTOPT_INVERT: option is invertible (usable with !)
|
||||
* %XTOPT_MAND: option is mandatory
|
||||
* %XTOPT_MULTI: option may be specified multiple times
|
||||
* %XTOPT_PUT: store value into memory at @ptroff
|
||||
* %XTOPT_NBO: store value in network-byte order
|
||||
* (only certain XTTYPEs recognize this)
|
||||
*/
|
||||
enum xt_option_flags {
|
||||
XTOPT_INVERT = 1 << 0,
|
||||
XTOPT_MAND = 1 << 1,
|
||||
XTOPT_MULTI = 1 << 2,
|
||||
XTOPT_PUT = 1 << 3,
|
||||
XTOPT_NBO = 1 << 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* @name: name of option
|
||||
* @type: type of input and validation method, see %XTTYPE_*
|
||||
* @id: unique number (within extension) for option, 0-31
|
||||
* @excl: bitmask of flags that cannot be used with this option
|
||||
* @also: bitmask of flags that must be used with this option
|
||||
* @flags: bitmask of option flags, see %XTOPT_*
|
||||
* @ptroff: offset into private structure for member
|
||||
* @size: size of the item pointed to by @ptroff; this is a safeguard
|
||||
* @min: lowest allowed value (for singular integral types)
|
||||
* @max: highest allowed value (for singular integral types)
|
||||
*/
|
||||
struct xt_option_entry {
|
||||
const char *name;
|
||||
enum xt_option_type type;
|
||||
unsigned int id, excl, also, flags;
|
||||
unsigned int ptroff;
|
||||
size_t size;
|
||||
unsigned int min, max;
|
||||
};
|
||||
|
||||
/**
|
||||
* @arg: input from command line
|
||||
* @ext_name: name of extension currently being processed
|
||||
* @entry: current option being processed
|
||||
* @data: per-extension kernel data block
|
||||
* @xflags: options of the extension that have been used
|
||||
* @invert: whether option was used with !
|
||||
* @nvals: number of results in uXX_multi
|
||||
* @val: parsed result
|
||||
* @udata: per-extension private scratch area
|
||||
* (cf. xtables_{match,target}->udata_size)
|
||||
*/
|
||||
struct xt_option_call {
|
||||
const char *arg, *ext_name;
|
||||
const struct xt_option_entry *entry;
|
||||
void *data;
|
||||
unsigned int xflags;
|
||||
bool invert;
|
||||
uint8_t nvals;
|
||||
union {
|
||||
uint8_t u8, u8_range[2], syslog_level, protocol;
|
||||
uint16_t u16, u16_range[2], port, port_range[2];
|
||||
uint32_t u32, u32_range[2];
|
||||
uint64_t u64, u64_range[2];
|
||||
double dbl;
|
||||
struct {
|
||||
union nf_inet_addr haddr, hmask;
|
||||
uint8_t hlen;
|
||||
};
|
||||
struct {
|
||||
uint8_t tos_value, tos_mask;
|
||||
};
|
||||
struct {
|
||||
uint32_t mark, mask;
|
||||
};
|
||||
uint8_t ethermac[6];
|
||||
} val;
|
||||
/* Wished for a world where the ones below were gone: */
|
||||
union {
|
||||
struct xt_entry_match **match;
|
||||
struct xt_entry_target **target;
|
||||
};
|
||||
void *xt_entry;
|
||||
void *udata;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ext_name: name of extension currently being processed
|
||||
* @data: per-extension (kernel) data block
|
||||
* @udata: per-extension private scratch area
|
||||
* (cf. xtables_{match,target}->udata_size)
|
||||
* @xflags: options of the extension that have been used
|
||||
*/
|
||||
struct xt_fcheck_call {
|
||||
const char *ext_name;
|
||||
void *data, *udata;
|
||||
unsigned int xflags;
|
||||
};
|
||||
|
||||
/**
|
||||
* A "linear"/linked-list based name<->id map, for files similar to
|
||||
* /etc/iproute2/.
|
||||
*/
|
||||
struct xtables_lmap {
|
||||
char *name;
|
||||
int id;
|
||||
struct xtables_lmap *next;
|
||||
};
|
||||
|
||||
enum xtables_ext_flags {
|
||||
XTABLES_EXT_ALIAS = 1 << 0,
|
||||
};
|
||||
|
||||
struct xt_xlate;
|
||||
|
||||
struct xt_xlate_mt_params {
|
||||
const void *ip;
|
||||
const struct xt_entry_match *match;
|
||||
int numeric;
|
||||
bool escape_quotes;
|
||||
};
|
||||
|
||||
struct xt_xlate_tg_params {
|
||||
const void *ip;
|
||||
const struct xt_entry_target *target;
|
||||
int numeric;
|
||||
bool escape_quotes;
|
||||
};
|
||||
|
||||
/* Include file for additions: new matches and targets. */
|
||||
struct xtables_match {
|
||||
/*
|
||||
* ABI/API version this module requires. Must be first member,
|
||||
* as the rest of this struct may be subject to ABI changes.
|
||||
*/
|
||||
const char *version;
|
||||
|
||||
struct xtables_match *next;
|
||||
|
||||
const char *name;
|
||||
const char *real_name;
|
||||
|
||||
/* Revision of match (0 by default). */
|
||||
uint8_t revision;
|
||||
|
||||
/* Extension flags */
|
||||
uint8_t ext_flags;
|
||||
|
||||
uint16_t family;
|
||||
|
||||
/* Size of match data. */
|
||||
size_t size;
|
||||
|
||||
/* Size of match data relevant for userspace comparison purposes */
|
||||
size_t userspacesize;
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
void (*help)(void);
|
||||
|
||||
/* Initialize the match. */
|
||||
void (*init)(struct xt_entry_match *m);
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
/* entry is struct ipt_entry for example */
|
||||
int (*parse)(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry,
|
||||
struct xt_entry_match **match);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*final_check)(unsigned int flags);
|
||||
|
||||
/* Prints out the match iff non-NULL: put space at end */
|
||||
/* ip is struct ipt_ip * for example */
|
||||
void (*print)(const void *ip,
|
||||
const struct xt_entry_match *match, int numeric);
|
||||
|
||||
/* Saves the match info in parsable form to stdout. */
|
||||
/* ip is struct ipt_ip * for example */
|
||||
void (*save)(const void *ip, const struct xt_entry_match *match);
|
||||
|
||||
/* Print match name or alias */
|
||||
const char *(*alias)(const struct xt_entry_match *match);
|
||||
|
||||
/* Pointer to list of extra command-line options */
|
||||
const struct option *extra_opts;
|
||||
|
||||
/* New parser */
|
||||
void (*x6_parse)(struct xt_option_call *);
|
||||
void (*x6_fcheck)(struct xt_fcheck_call *);
|
||||
const struct xt_option_entry *x6_options;
|
||||
|
||||
/* Translate iptables to nft */
|
||||
int (*xlate)(struct xt_xlate *xl,
|
||||
const struct xt_xlate_mt_params *params);
|
||||
|
||||
/* Size of per-extension instance extra "global" scratch space */
|
||||
size_t udata_size;
|
||||
|
||||
/* Ignore these men behind the curtain: */
|
||||
void *udata;
|
||||
unsigned int option_offset;
|
||||
struct xt_entry_match *m;
|
||||
unsigned int mflags;
|
||||
unsigned int loaded; /* simulate loading so options are merged properly */
|
||||
};
|
||||
|
||||
struct xtables_target {
|
||||
/*
|
||||
* ABI/API version this module requires. Must be first member,
|
||||
* as the rest of this struct may be subject to ABI changes.
|
||||
*/
|
||||
const char *version;
|
||||
|
||||
struct xtables_target *next;
|
||||
|
||||
|
||||
const char *name;
|
||||
|
||||
/* Real target behind this, if any. */
|
||||
const char *real_name;
|
||||
|
||||
/* Revision of target (0 by default). */
|
||||
uint8_t revision;
|
||||
|
||||
/* Extension flags */
|
||||
uint8_t ext_flags;
|
||||
|
||||
uint16_t family;
|
||||
|
||||
|
||||
/* Size of target data. */
|
||||
size_t size;
|
||||
|
||||
/* Size of target data relevant for userspace comparison purposes */
|
||||
size_t userspacesize;
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
void (*help)(void);
|
||||
|
||||
/* Initialize the target. */
|
||||
void (*init)(struct xt_entry_target *t);
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
/* entry is struct ipt_entry for example */
|
||||
int (*parse)(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry,
|
||||
struct xt_entry_target **targetinfo);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*final_check)(unsigned int flags);
|
||||
|
||||
/* Prints out the target iff non-NULL: put space at end */
|
||||
void (*print)(const void *ip,
|
||||
const struct xt_entry_target *target, int numeric);
|
||||
|
||||
/* Saves the targinfo in parsable form to stdout. */
|
||||
void (*save)(const void *ip,
|
||||
const struct xt_entry_target *target);
|
||||
|
||||
/* Print target name or alias */
|
||||
const char *(*alias)(const struct xt_entry_target *target);
|
||||
|
||||
/* Pointer to list of extra command-line options */
|
||||
const struct option *extra_opts;
|
||||
|
||||
/* New parser */
|
||||
void (*x6_parse)(struct xt_option_call *);
|
||||
void (*x6_fcheck)(struct xt_fcheck_call *);
|
||||
const struct xt_option_entry *x6_options;
|
||||
|
||||
/* Translate iptables to nft */
|
||||
int (*xlate)(struct xt_xlate *xl,
|
||||
const struct xt_xlate_tg_params *params);
|
||||
|
||||
size_t udata_size;
|
||||
|
||||
/* Ignore these men behind the curtain: */
|
||||
void *udata;
|
||||
unsigned int option_offset;
|
||||
struct xt_entry_target *t;
|
||||
unsigned int tflags;
|
||||
unsigned int used;
|
||||
unsigned int loaded; /* simulate loading so options are merged properly */
|
||||
};
|
||||
|
||||
struct xtables_rule_match {
|
||||
struct xtables_rule_match *next;
|
||||
struct xtables_match *match;
|
||||
/* Multiple matches of the same type: the ones before
|
||||
the current one are completed from parsing point of view */
|
||||
bool completed;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct xtables_pprot -
|
||||
*
|
||||
* A few hardcoded protocols for 'all' and in case the user has no
|
||||
* /etc/protocols.
|
||||
*/
|
||||
struct xtables_pprot {
|
||||
const char *name;
|
||||
uint8_t num;
|
||||
};
|
||||
|
||||
enum xtables_tryload {
|
||||
XTF_DONT_LOAD,
|
||||
XTF_DURING_LOAD,
|
||||
XTF_TRY_LOAD,
|
||||
XTF_LOAD_MUST_SUCCEED,
|
||||
};
|
||||
|
||||
enum xtables_exittype {
|
||||
OTHER_PROBLEM = 1,
|
||||
PARAMETER_PROBLEM,
|
||||
VERSION_PROBLEM,
|
||||
RESOURCE_PROBLEM,
|
||||
XTF_ONLY_ONCE,
|
||||
XTF_NO_INVERT,
|
||||
XTF_BAD_VALUE,
|
||||
XTF_ONE_ACTION,
|
||||
};
|
||||
|
||||
struct xtables_globals
|
||||
{
|
||||
unsigned int option_offset;
|
||||
const char *program_name, *program_version;
|
||||
struct option *orig_opts;
|
||||
struct option *opts;
|
||||
void (*exit_err)(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
|
||||
int (*compat_rev)(const char *name, uint8_t rev, int opt);
|
||||
};
|
||||
|
||||
#define XT_GETOPT_TABLEEND {.name = NULL, .has_arg = false}
|
||||
|
||||
/*
|
||||
* enum op-
|
||||
*
|
||||
* For writing clean nftables translations code
|
||||
*/
|
||||
enum xt_op {
|
||||
XT_OP_EQ,
|
||||
XT_OP_NEQ,
|
||||
XT_OP_MAX,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const char *xtables_modprobe_program;
|
||||
extern struct xtables_match *xtables_matches;
|
||||
extern struct xtables_target *xtables_targets;
|
||||
|
||||
extern void xtables_init(void);
|
||||
extern void xtables_fini(void);
|
||||
extern void xtables_set_nfproto(uint8_t);
|
||||
extern void *xtables_calloc(size_t, size_t);
|
||||
extern void *xtables_malloc(size_t);
|
||||
extern void *xtables_realloc(void *, size_t);
|
||||
char *xtables_strdup(const char *);
|
||||
|
||||
extern int xtables_insmod(const char *, const char *, bool);
|
||||
extern int xtables_load_ko(const char *, bool);
|
||||
extern int xtables_set_params(struct xtables_globals *xtp);
|
||||
extern void xtables_free_opts(int reset_offset);
|
||||
extern struct option *xtables_merge_options(struct option *origopts,
|
||||
struct option *oldopts, const struct option *newopts,
|
||||
unsigned int *option_offset);
|
||||
|
||||
extern int xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto);
|
||||
extern struct xtables_match *xtables_find_match(const char *name,
|
||||
enum xtables_tryload, struct xtables_rule_match **match);
|
||||
extern struct xtables_match *xtables_find_match_revision(const char *name,
|
||||
enum xtables_tryload tryload, struct xtables_match *match,
|
||||
int revision);
|
||||
extern struct xtables_target *xtables_find_target(const char *name,
|
||||
enum xtables_tryload);
|
||||
struct xtables_target *xtables_find_target_revision(const char *name,
|
||||
enum xtables_tryload tryload, struct xtables_target *target,
|
||||
int revision);
|
||||
extern int xtables_compatible_revision(const char *name, uint8_t revision,
|
||||
int opt);
|
||||
|
||||
extern void xtables_rule_matches_free(struct xtables_rule_match **matches);
|
||||
|
||||
/* Your shared library should call one of these. */
|
||||
extern void xtables_register_match(struct xtables_match *me);
|
||||
extern void xtables_register_matches(struct xtables_match *, unsigned int);
|
||||
extern void xtables_register_target(struct xtables_target *me);
|
||||
extern void xtables_register_targets(struct xtables_target *, unsigned int);
|
||||
|
||||
extern bool xtables_strtoul(const char *, char **, uintmax_t *,
|
||||
uintmax_t, uintmax_t);
|
||||
extern bool xtables_strtoui(const char *, char **, unsigned int *,
|
||||
unsigned int, unsigned int);
|
||||
extern int xtables_service_to_port(const char *name, const char *proto);
|
||||
extern uint16_t xtables_parse_port(const char *port, const char *proto);
|
||||
extern void
|
||||
xtables_parse_interface(const char *arg, char *vianame, unsigned char *mask);
|
||||
|
||||
/* this is a special 64bit data type that is 8-byte aligned */
|
||||
#define aligned_u64 uint64_t __attribute__((aligned(8)))
|
||||
|
||||
extern struct xtables_globals *xt_params;
|
||||
#define xtables_error (xt_params->exit_err)
|
||||
|
||||
extern void xtables_param_act(unsigned int, const char *, ...);
|
||||
|
||||
extern const char *xtables_ipaddr_to_numeric(const struct in_addr *);
|
||||
extern const char *xtables_ipaddr_to_anyname(const struct in_addr *);
|
||||
extern const char *xtables_ipmask_to_numeric(const struct in_addr *);
|
||||
extern struct in_addr *xtables_numeric_to_ipaddr(const char *);
|
||||
extern struct in_addr *xtables_numeric_to_ipmask(const char *);
|
||||
extern int xtables_ipmask_to_cidr(const struct in_addr *);
|
||||
extern void xtables_ipparse_any(const char *, struct in_addr **,
|
||||
struct in_addr *, unsigned int *);
|
||||
extern void xtables_ipparse_multiple(const char *, struct in_addr **,
|
||||
struct in_addr **, unsigned int *);
|
||||
|
||||
extern struct in6_addr *xtables_numeric_to_ip6addr(const char *);
|
||||
extern const char *xtables_ip6addr_to_numeric(const struct in6_addr *);
|
||||
extern const char *xtables_ip6addr_to_anyname(const struct in6_addr *);
|
||||
extern const char *xtables_ip6mask_to_numeric(const struct in6_addr *);
|
||||
extern int xtables_ip6mask_to_cidr(const struct in6_addr *);
|
||||
extern void xtables_ip6parse_any(const char *, struct in6_addr **,
|
||||
struct in6_addr *, unsigned int *);
|
||||
extern void xtables_ip6parse_multiple(const char *, struct in6_addr **,
|
||||
struct in6_addr **, unsigned int *);
|
||||
|
||||
/* Absolute file name for network data base files. */
|
||||
#define XT_PATH_ETHERTYPES "/etc/ethertypes"
|
||||
|
||||
struct xt_ethertypeent {
|
||||
char *e_name; /* Official ethernet type name. */
|
||||
char **e_aliases; /* Alias list. */
|
||||
int e_ethertype; /* Ethernet type number. */
|
||||
};
|
||||
|
||||
extern struct xt_ethertypeent *xtables_getethertypebyname(const char *name);
|
||||
extern struct xt_ethertypeent *xtables_getethertypebynumber(int ethertype);
|
||||
|
||||
/**
|
||||
* Print the specified value to standard output, quoting dangerous
|
||||
* characters if required.
|
||||
*/
|
||||
extern void xtables_save_string(const char *value);
|
||||
|
||||
#define FMT_NUMERIC 0x0001
|
||||
#define FMT_NOCOUNTS 0x0002
|
||||
#define FMT_KILOMEGAGIGA 0x0004
|
||||
#define FMT_OPTIONS 0x0008
|
||||
#define FMT_NOTABLE 0x0010
|
||||
#define FMT_NOTARGET 0x0020
|
||||
#define FMT_VIA 0x0040
|
||||
#define FMT_NONEWLINE 0x0080
|
||||
#define FMT_LINENUMBERS 0x0100
|
||||
#define FMT_EBT_SAVE 0x0200
|
||||
#define FMT_C_COUNTS 0x0400
|
||||
|
||||
#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \
|
||||
| FMT_NUMERIC | FMT_NOTABLE)
|
||||
#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
|
||||
|
||||
extern void xtables_print_num(uint64_t number, unsigned int format);
|
||||
extern int xtables_parse_mac_and_mask(const char *from, void *to, void *mask);
|
||||
extern int xtables_print_well_known_mac_and_mask(const void *mac,
|
||||
const void *mask);
|
||||
extern void xtables_print_mac(const unsigned char *macaddress);
|
||||
extern void xtables_print_mac_and_mask(const unsigned char *mac,
|
||||
const unsigned char *mask);
|
||||
|
||||
extern void xtables_parse_val_mask(struct xt_option_call *cb,
|
||||
unsigned int *val, unsigned int *mask,
|
||||
const struct xtables_lmap *lmap);
|
||||
|
||||
static inline void xtables_parse_mark_mask(struct xt_option_call *cb,
|
||||
unsigned int *mark,
|
||||
unsigned int *mask)
|
||||
{
|
||||
xtables_parse_val_mask(cb, mark, mask, NULL);
|
||||
}
|
||||
|
||||
extern void xtables_print_val_mask(unsigned int val, unsigned int mask,
|
||||
const struct xtables_lmap *lmap);
|
||||
|
||||
static inline void xtables_print_mark_mask(unsigned int mark,
|
||||
unsigned int mask)
|
||||
{
|
||||
xtables_print_val_mask(mark, mask, NULL);
|
||||
}
|
||||
|
||||
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
|
||||
# ifdef _INIT
|
||||
# undef _init
|
||||
# define _init _INIT
|
||||
# endif
|
||||
extern void init_extensions(void);
|
||||
extern void init_extensions4(void);
|
||||
extern void init_extensions6(void);
|
||||
extern void init_extensionsa(void);
|
||||
extern void init_extensionsb(void);
|
||||
#else
|
||||
# define _init __attribute__((constructor)) _INIT
|
||||
# define EMPTY_FUNC_DEF(x) static inline void x(void) {}
|
||||
EMPTY_FUNC_DEF(init_extensions)
|
||||
EMPTY_FUNC_DEF(init_extensions4)
|
||||
EMPTY_FUNC_DEF(init_extensions6)
|
||||
EMPTY_FUNC_DEF(init_extensionsa)
|
||||
EMPTY_FUNC_DEF(init_extensionsb)
|
||||
# undef EMPTY_FUNC_DEF
|
||||
#endif
|
||||
|
||||
extern const struct xtables_pprot xtables_chain_protos[];
|
||||
extern uint16_t xtables_parse_protocol(const char *s);
|
||||
|
||||
/* kernel revision handling */
|
||||
extern int kernel_version;
|
||||
extern void get_kernel_version(void);
|
||||
#define LINUX_VERSION(x,y,z) (0x10000*(x) + 0x100*(y) + z)
|
||||
#define LINUX_VERSION_MAJOR(x) (((x)>>16) & 0xFF)
|
||||
#define LINUX_VERSION_MINOR(x) (((x)>> 8) & 0xFF)
|
||||
#define LINUX_VERSION_PATCH(x) ( (x) & 0xFF)
|
||||
|
||||
/* xtoptions.c */
|
||||
extern void xtables_option_metavalidate(const char *,
|
||||
const struct xt_option_entry *);
|
||||
extern struct option *xtables_options_xfrm(struct option *, struct option *,
|
||||
const struct xt_option_entry *,
|
||||
unsigned int *);
|
||||
extern void xtables_option_parse(struct xt_option_call *);
|
||||
extern void xtables_option_tpcall(unsigned int, char **, bool,
|
||||
struct xtables_target *, void *);
|
||||
extern void xtables_option_mpcall(unsigned int, char **, bool,
|
||||
struct xtables_match *, void *);
|
||||
extern void xtables_option_tfcall(struct xtables_target *);
|
||||
extern void xtables_option_mfcall(struct xtables_match *);
|
||||
extern void xtables_options_fcheck(const char *, unsigned int,
|
||||
const struct xt_option_entry *);
|
||||
|
||||
extern struct xtables_lmap *xtables_lmap_init(const char *);
|
||||
extern void xtables_lmap_free(struct xtables_lmap *);
|
||||
extern int xtables_lmap_name2id(const struct xtables_lmap *, const char *);
|
||||
extern const char *xtables_lmap_id2name(const struct xtables_lmap *, int);
|
||||
|
||||
/* xlate infrastructure */
|
||||
struct xt_xlate *xt_xlate_alloc(int size);
|
||||
void xt_xlate_free(struct xt_xlate *xl);
|
||||
void xt_xlate_add(struct xt_xlate *xl, const char *fmt, ...) __attribute__((format(printf,2,3)));
|
||||
#define xt_xlate_rule_add xt_xlate_add
|
||||
void xt_xlate_set_add(struct xt_xlate *xl, const char *fmt, ...) __attribute__((format(printf,2,3)));
|
||||
void xt_xlate_add_comment(struct xt_xlate *xl, const char *comment);
|
||||
const char *xt_xlate_get_comment(struct xt_xlate *xl);
|
||||
void xl_xlate_set_family(struct xt_xlate *xl, uint8_t family);
|
||||
uint8_t xt_xlate_get_family(struct xt_xlate *xl);
|
||||
const char *xt_xlate_get(struct xt_xlate *xl);
|
||||
#define xt_xlate_rule_get xt_xlate_get
|
||||
const char *xt_xlate_set_get(struct xt_xlate *xl);
|
||||
|
||||
/* informed target lookups */
|
||||
void xtables_announce_chain(const char *name);
|
||||
|
||||
#ifdef XTABLES_INTERNAL
|
||||
|
||||
/* Shipped modules rely on this... */
|
||||
|
||||
# ifndef ARRAY_SIZE
|
||||
# define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
||||
# endif
|
||||
|
||||
extern void _init(void);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _XTABLES_H */
|
83
rhost.c
83
rhost.c
@ -213,6 +213,30 @@ int whitelist(char *client_ip, char (*whitelist_ip)[WHITELIST_IP_NUM])
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 地域段白名单对比
|
||||
int isregion(char *str, char (*region_list)[WHITELIST_IP_NUM])
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
for (i = 1; i < WHITELIST_IP_NUM - 1; i++) {
|
||||
if (strcmp(region_list[i], "\0") == 0) { // 如果字符串为空就跳出循环
|
||||
break;
|
||||
}
|
||||
|
||||
// 在str中查找region_list[i]
|
||||
p = strstr(str, region_list[i]);
|
||||
if (p != NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 去除空格
|
||||
char *remove_space(const char *str)
|
||||
{
|
||||
unsigned int uLen = strlen(str);
|
||||
@ -243,6 +267,8 @@ int rule(conf * conf)
|
||||
{
|
||||
int i;
|
||||
char whitelist_ip[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } };
|
||||
char region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } };
|
||||
|
||||
char p[2], splice_command[LONG_BUFFER], command[LONG_BUFFER], *temp, buffer[BUFFER], awk[BUFFER];
|
||||
FILE *fp, *fc;
|
||||
time_t timep;
|
||||
@ -299,6 +325,7 @@ int rule(conf * conf)
|
||||
strcat(splice_command, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s", splice_command); // 打印所有非法IP
|
||||
|
||||
|
||||
@ -320,16 +347,31 @@ int rule(conf * conf)
|
||||
|
||||
|
||||
split_string(conf->IPV4_WHITE_LIST, " ", whitelist_ip);
|
||||
split_string(conf->REGION_LIST, " ", region_list);
|
||||
|
||||
|
||||
|
||||
// 打印配置
|
||||
for (i = 1; i <= WHITELIST_IP_NUM - 1; i++) {
|
||||
if (*whitelist_ip[i] != '\0') ;
|
||||
if (*whitelist_ip[i] != '\0') {
|
||||
;
|
||||
//printf("%s\n", whitelist_ip[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (conf->IPV4_RESTRICTION == 1) { // 是否启用百名单
|
||||
for (i = 1; i <= WHITELIST_IP_NUM - 1; i++) {
|
||||
if (*region_list[i] != '\0') {
|
||||
;
|
||||
//printf("%s\n", region_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (conf->IPV4_RESTRICTION == 1) { // 是否启用白名单
|
||||
if (whitelist(buffer, whitelist_ip) == 1) {
|
||||
;
|
||||
//printf("白名单IPV4:%s\n", buffer);
|
||||
printf("白名单IPV4:%s\n", buffer);
|
||||
|
||||
continue;
|
||||
}
|
||||
@ -350,22 +392,18 @@ int rule(conf * conf)
|
||||
if (NULL == location_json)
|
||||
{
|
||||
printf("获取IP位置错误!\n");
|
||||
|
||||
goto BLOCKED;
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("%s\n", location_json);
|
||||
|
||||
char temp[BUFFER];
|
||||
memset(temp, 0, BUFFER);
|
||||
|
||||
char *p = strstr(location_json, "\"location\"");
|
||||
char *p1 = strstr(p, "\",");
|
||||
|
||||
|
||||
memcpy(temp, p+12, p1-p-12);
|
||||
|
||||
location = remove_space(temp);
|
||||
|
||||
memset(temp, 0, BUFFER);
|
||||
memcpy(temp, p+12, p1-p-12);
|
||||
location = remove_space(temp);
|
||||
}
|
||||
|
||||
memset(iplocation, 0, BUFFER);
|
||||
@ -373,7 +411,24 @@ int rule(conf * conf)
|
||||
strcat(iplocation, "(");
|
||||
strcat(iplocation, location);
|
||||
strcat(iplocation, ")");
|
||||
//printf("%s\n", iplocation);
|
||||
|
||||
|
||||
|
||||
// 地域白名单
|
||||
if (conf->REGION == 1)
|
||||
{
|
||||
if (isregion(iplocation, region_list) == 1)
|
||||
{
|
||||
;
|
||||
printf("地域白名单: %s\n", iplocation);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (conf->IS_DING_WEBHOOK == 1) // 钉钉告警
|
||||
{
|
||||
@ -393,7 +448,7 @@ int rule(conf * conf)
|
||||
sleep(3);
|
||||
}
|
||||
|
||||
|
||||
BLOCKED:
|
||||
// 是否封禁攻击IP
|
||||
if (conf->IS_BLOCKED == 1) {
|
||||
// libiptc 库插入规则 iptables -t filter -A INPUT -p tcp -m tcp -s xxxx -j DROP
|
||||
|
@ -7,11 +7,16 @@ global {
|
||||
|
||||
|
||||
IPV4_RESTRICTION = 1; // 是否启用百名单
|
||||
IPV4_WHITE_LIST = "1.193.37.156 117.158.215.217"; // IP白名单
|
||||
IPV4_WHITE_LIST = "1.1.1.1 "; // IP白名单
|
||||
|
||||
|
||||
REGION = 1; // 是否启用地域白名单
|
||||
REGION_LIST = "河南 郑州"; // 地域列表
|
||||
|
||||
|
||||
|
||||
IS_BLOCKED = 1; // 是否封禁攻击IP
|
||||
REFUSE_NUMBER = 5; // 拒绝攻击次数
|
||||
REFUSE_NUMBER = 3; // 拒绝攻击次数
|
||||
|
||||
|
||||
IS_MAIL = 0; // 开启邮件告警
|
||||
|
Loading…
Reference in New Issue
Block a user