Linux Kernel Version checking

For compatibility between new and old distributions of linux.
This commit is contained in:
Valeska 2014-02-14 16:12:55 -08:00
parent 9b8df0cd35
commit cf72a5ec59

View File

@ -9,7 +9,7 @@
*/ */
/* (C) 1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See /* (C) 1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
* COPYING for details). * COPYING for details).
* (C) 2000-2004 by the Netfilter Core Team <coreteam@netfilter.org> * (C) 2000-2004 by the Netfilter Core Team <coreteam@netfilter.org>
* *
* 2003-Jun-20: Harald Welte <laforge@netfilter.org>: * 2003-Jun-20: Harald Welte <laforge@netfilter.org>:
@ -17,7 +17,7 @@
* 2003-Jun-23: Harald Welte <laforge@netfilter.org>: * 2003-Jun-23: Harald Welte <laforge@netfilter.org>:
* - performance optimization, sponsored by Astaro AG (http://www.astaro.com/) * - performance optimization, sponsored by Astaro AG (http://www.astaro.com/)
* don't rebuild the chain cache after every operation, instead fix it * don't rebuild the chain cache after every operation, instead fix it
* up after a ruleset change. * up after a ruleset change.
* 2004-Aug-18: Harald Welte <laforge@netfilter.org>: * 2004-Aug-18: Harald Welte <laforge@netfilter.org>:
* - futher performance work: total reimplementation of libiptc. * - futher performance work: total reimplementation of libiptc.
* - libiptc now has a real internal (linked-list) represntation of the * - libiptc now has a real internal (linked-list) represntation of the
@ -27,6 +27,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <linux/version.h>
#include "linux_list.h" #include "linux_list.h"
//#define IPTC_DEBUG2 1 //#define IPTC_DEBUG2 1
@ -44,6 +46,7 @@
#define IPT_LIB_DIR "/usr/local/lib/iptables" #define IPT_LIB_DIR "/usr/local/lib/iptables"
#endif #endif
static int sockfd = -1; static int sockfd = -1;
static int sockfd_use = 0; static int sockfd_use = 0;
static void *iptc_fn = NULL; static void *iptc_fn = NULL;
@ -130,7 +133,7 @@ STRUCT_TC_HANDLE
int changed; /* Have changes been made? */ int changed; /* Have changes been made? */
struct list_head chains; struct list_head chains;
struct chain_head *chain_iterator_cur; struct chain_head *chain_iterator_cur;
struct rule_head *rule_iterator_cur; struct rule_head *rule_iterator_cur;
@ -370,14 +373,14 @@ static int __iptcc_p_del_policy(TC_HANDLE_T h, unsigned int num)
h->chain_iterator_cur->rules.prev; h->chain_iterator_cur->rules.prev;
/* save verdict */ /* save verdict */
h->chain_iterator_cur->verdict = h->chain_iterator_cur->verdict =
*(int *)GET_TARGET(pr->entry)->data; *(int *)GET_TARGET(pr->entry)->data;
/* save counter and counter_map information */ /* save counter and counter_map information */
h->chain_iterator_cur->counter_map.maptype = h->chain_iterator_cur->counter_map.maptype =
COUNTER_MAP_NORMAL_MAP; COUNTER_MAP_NORMAL_MAP;
h->chain_iterator_cur->counter_map.mappos = num-1; h->chain_iterator_cur->counter_map.mappos = num-1;
memcpy(&h->chain_iterator_cur->counters, &pr->entry->counters, memcpy(&h->chain_iterator_cur->counters, &pr->entry->counters,
sizeof(h->chain_iterator_cur->counters)); sizeof(h->chain_iterator_cur->counters));
/* foot_offset points to verdict rule */ /* foot_offset points to verdict rule */
@ -423,13 +426,13 @@ static void __iptcc_p_add_chain(TC_HANDLE_T h, struct chain_head *c,
c->index = *num; c->index = *num;
iptc_insert_chain(h, c); iptc_insert_chain(h, c);
h->chain_iterator_cur = c; h->chain_iterator_cur = c;
} }
/* main parser function: add an entry from the blob to the cache */ /* main parser function: add an entry from the blob to the cache */
static int cache_add_entry(STRUCT_ENTRY *e, static int cache_add_entry(STRUCT_ENTRY *e,
TC_HANDLE_T h, TC_HANDLE_T h,
STRUCT_ENTRY **prev, STRUCT_ENTRY **prev,
unsigned int *num) unsigned int *num)
{ {
@ -453,9 +456,9 @@ static int cache_add_entry(STRUCT_ENTRY *e,
* target, or a hook entry point */ * target, or a hook entry point */
if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) { if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) {
struct chain_head *c = struct chain_head *c =
iptcc_alloc_chain_head((const char *)GET_TARGET(e)->data, 0); iptcc_alloc_chain_head((const char *)GET_TARGET(e)->data, 0);
DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset, DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset,
(char *)c->name, c); (char *)c->name, c);
if (!c) { if (!c) {
errno = -ENOMEM; errno = -ENOMEM;
@ -466,9 +469,9 @@ static int cache_add_entry(STRUCT_ENTRY *e,
} else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) { } else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) {
struct chain_head *c = struct chain_head *c =
iptcc_alloc_chain_head((char *)hooknames[builtin-1], iptcc_alloc_chain_head((char *)hooknames[builtin-1],
builtin); builtin);
DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n", DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n",
*num, offset, c, &c->rules); *num, offset, c, &c->rules);
if (!c) { if (!c) {
errno = -ENOMEM; errno = -ENOMEM;
@ -486,7 +489,7 @@ static int cache_add_entry(STRUCT_ENTRY *e,
struct rule_head *r; struct rule_head *r;
new_rule: new_rule:
if (!(r = iptcc_alloc_rule(h->chain_iterator_cur, if (!(r = iptcc_alloc_rule(h->chain_iterator_cur,
e->next_offset))) { e->next_offset))) {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
@ -619,7 +622,7 @@ static inline int iptcc_compile_rule (TC_HANDLE_T h, STRUCT_REPLACE *repl, struc
t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry);
t->verdict = r->offset + r->size; t->verdict = r->offset + r->size;
} }
/* copy entry from cache to blob */ /* copy entry from cache to blob */
memcpy((char *)repl->entries+r->offset, r->entry, r->size); memcpy((char *)repl->entries+r->offset, r->entry, r->size);
@ -634,6 +637,25 @@ static int iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE *repl, struct chain
struct iptcb_chain_start *head; struct iptcb_chain_start *head;
struct iptcb_chain_foot *foot; struct iptcb_chain_foot *foot;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 7, 0)
/* only user-defined chains have heaer */
if (!iptcc_is_builtin(c)) {
/* put chain header in place */
head = (void *)repl->entries + c->head_offset;
head->e.target_offset = sizeof(STRUCT_ENTRY);
head->e.next_offset = IPTCB_CHAIN_START_SIZE;
strcpy(head->name.t.u.user.name, ERROR_TARGET);
head->name.t.u.target_size =
ALIGN(sizeof(struct ipt_error_target));
strcpy(head->name.error, c->name);
} else {
repl->hook_entry[c->hooknum-1] = c->head_offset;
repl->underflow[c->hooknum-1] = c->foot_offset;
}
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
/* only user-defined chains have heaer */ /* only user-defined chains have heaer */
if (!iptcc_is_builtin(c)) { if (!iptcc_is_builtin(c)) {
/* put chain header in place */ /* put chain header in place */
@ -641,13 +663,14 @@ static int iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE *repl, struct chain
head->e.target_offset = sizeof(STRUCT_ENTRY); head->e.target_offset = sizeof(STRUCT_ENTRY);
head->e.next_offset = IPTCB_CHAIN_START_SIZE; head->e.next_offset = IPTCB_CHAIN_START_SIZE;
strcpy(head->name.target.u.user.name, ERROR_TARGET); strcpy(head->name.target.u.user.name, ERROR_TARGET);
head->name.target.u.target_size = head->name.target.u.target_size =
ALIGN(sizeof(struct ipt_error_target)); ALIGN(sizeof(struct ipt_error_target));
strcpy(head->name.errorname, c->name); strcpy(head->name.error, c->name);
} else { } else {
repl->hook_entry[c->hooknum-1] = c->head_offset; repl->hook_entry[c->hooknum-1] = c->head_offset;
repl->underflow[c->hooknum-1] = c->foot_offset; repl->underflow[c->hooknum-1] = c->foot_offset;
} }
#endif
/* iterate over rules */ /* iterate over rules */
list_for_each_entry(r, &c->rules, list) { list_for_each_entry(r, &c->rules, list) {
@ -685,7 +708,7 @@ static int iptcc_compile_chain_offsets(TC_HANDLE_T h, struct chain_head *c,
if (!iptcc_is_builtin(c)) { if (!iptcc_is_builtin(c)) {
/* Chain has header */ /* Chain has header */
*offset += sizeof(STRUCT_ENTRY) *offset += sizeof(STRUCT_ENTRY)
+ ALIGN(sizeof(struct ipt_error_target)); + ALIGN(sizeof(struct ipt_error_target));
(*num)++; (*num)++;
} }
@ -698,7 +721,7 @@ static int iptcc_compile_chain_offsets(TC_HANDLE_T h, struct chain_head *c,
(*num)++; (*num)++;
} }
DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num, DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num,
*offset, *num); *offset, *num);
c->foot_offset = *offset; c->foot_offset = *offset;
c->foot_index = *num; c->foot_index = *num;
@ -744,16 +767,27 @@ static int iptcc_compile_table(TC_HANDLE_T h, STRUCT_REPLACE *repl)
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 7, 0)
/* Append error rule at end of chain */ /* Append error rule at end of chain */
error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE; error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE;
error->entry.target_offset = sizeof(STRUCT_ENTRY); error->entry.target_offset = sizeof(STRUCT_ENTRY);
error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE; error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE;
error->target.target.u.user.target_size = error->target.t.u.user.target_size =
ALIGN(sizeof(struct ipt_error_target)); ALIGN(sizeof(struct ipt_error_target));
strcpy((char *)&error->target.target.u.user.name, ERROR_TARGET); strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET);
strcpy((char *)&error->target.errorname, "ERROR"); strcpy((char *)&error->target.error, "ERROR");
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
/* Append error rule at end of chain */
error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE;
error->entry.target_offset = sizeof(STRUCT_ENTRY);
error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE;
error->target.target.u.user.target_size =
ALIGN(sizeof(struct ipt_error_target));
strcpy((char *)&error->target.target.u.user.name, ERROR_TARGET);
strcpy((char *)&error->target.errorname, "ERROR");
#endif
return 1; return 1;
} }
@ -809,7 +843,7 @@ TC_INIT(const char *tablename)
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
if (sockfd_use == 0) { if (sockfd_use == 0) {
sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW);
if (sockfd < 0) if (sockfd < 0)
@ -853,7 +887,7 @@ TC_INIT(const char *tablename)
#ifdef IPTC_DEBUG2 #ifdef IPTC_DEBUG2
{ {
int fd = open("/tmp/libiptc-so_get_entries.blob", int fd = open("/tmp/libiptc-so_get_entries.blob",
O_CREAT|O_WRONLY); O_CREAT|O_WRONLY);
if (fd >= 0) { if (fd >= 0) {
write(fd, h->entries, tmp); write(fd, h->entries, tmp);
@ -911,7 +945,7 @@ print_match(const STRUCT_ENTRY_MATCH *m)
} }
/*static int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle);*/ /*static int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle);*/
void void
TC_DUMP_ENTRIES(const TC_HANDLE_T handle) TC_DUMP_ENTRIES(const TC_HANDLE_T handle)
{ {
@ -953,7 +987,7 @@ static void iptcc_chain_iterator_advance(TC_HANDLE_T handle)
if (c->list.next == &handle->chains) if (c->list.next == &handle->chains)
handle->chain_iterator_cur = NULL; handle->chain_iterator_cur = NULL;
else else
handle->chain_iterator_cur = handle->chain_iterator_cur =
list_entry(c->list.next, struct chain_head, list); list_entry(c->list.next, struct chain_head, list);
} }
@ -993,7 +1027,7 @@ TC_NEXT_CHAIN(TC_HANDLE_T *handle)
} }
iptcc_chain_iterator_advance(*handle); iptcc_chain_iterator_advance(*handle);
DEBUGP(": returning `%s'\n", c->name); DEBUGP(": returning `%s'\n", c->name);
return c->name; return c->name;
} }
@ -1041,13 +1075,13 @@ TC_NEXT_RULE(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle)
DEBUGP_C("returning NULL\n"); DEBUGP_C("returning NULL\n");
return NULL; return NULL;
} }
r = list_entry((*handle)->rule_iterator_cur->list.next, r = list_entry((*handle)->rule_iterator_cur->list.next,
struct rule_head, list); struct rule_head, list);
iptc_fn = TC_NEXT_RULE; iptc_fn = TC_NEXT_RULE;
DEBUGP_C("next=%p, head=%p...", &r->list, DEBUGP_C("next=%p, head=%p...", &r->list,
&(*handle)->rule_iterator_cur->chain->rules); &(*handle)->rule_iterator_cur->chain->rules);
if (&r->list == &(*handle)->rule_iterator_cur->chain->rules) { if (&r->list == &(*handle)->rule_iterator_cur->chain->rules) {
@ -1076,7 +1110,7 @@ TC_NUM_RULES(const char *chain, TC_HANDLE_T *handle)
errno = ENOENT; errno = ENOENT;
return (unsigned int)-1; return (unsigned int)-1;
} }
return c->num_rules; return c->num_rules;
} }
@ -1086,7 +1120,7 @@ const STRUCT_ENTRY *TC_GET_RULE(const char *chain,
{ {
struct chain_head *c; struct chain_head *c;
struct rule_head *r; struct rule_head *r;
iptc_fn = TC_GET_RULE; iptc_fn = TC_GET_RULE;
CHECK(*handle); CHECK(*handle);
@ -1163,7 +1197,7 @@ int
TC_BUILTIN(const char *chain, const TC_HANDLE_T handle) TC_BUILTIN(const char *chain, const TC_HANDLE_T handle)
{ {
struct chain_head *c; struct chain_head *c;
iptc_fn = TC_BUILTIN; iptc_fn = TC_BUILTIN;
c = iptcc_find_label(chain, handle); c = iptcc_find_label(chain, handle);
@ -1537,7 +1571,7 @@ TC_DELETE_ENTRY(const IPT_CHAINLABEL chain,
* current iterator, move rule iterator back. next * current iterator, move rule iterator back. next
* pointer will then point to real next node */ * pointer will then point to real next node */
if (i == (*handle)->rule_iterator_cur) { if (i == (*handle)->rule_iterator_cur) {
(*handle)->rule_iterator_cur = (*handle)->rule_iterator_cur =
list_entry((*handle)->rule_iterator_cur->list.prev, list_entry((*handle)->rule_iterator_cur->list.prev,
struct rule_head, list); struct rule_head, list);
} }
@ -1588,7 +1622,7 @@ TC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain,
* iterator, move rule iterator back. next pointer will then * iterator, move rule iterator back. next pointer will then
* point to real next node */ * point to real next node */
if (r == (*handle)->rule_iterator_cur) { if (r == (*handle)->rule_iterator_cur) {
(*handle)->rule_iterator_cur = (*handle)->rule_iterator_cur =
list_entry((*handle)->rule_iterator_cur->list.prev, list_entry((*handle)->rule_iterator_cur->list.prev,
struct rule_head, list); struct rule_head, list);
} }
@ -1691,7 +1725,7 @@ TC_ZERO_COUNTER(const IPT_CHAINLABEL chain,
{ {
struct chain_head *c; struct chain_head *c;
struct rule_head *r; struct rule_head *r;
iptc_fn = TC_ZERO_COUNTER; iptc_fn = TC_ZERO_COUNTER;
CHECK(*handle); CHECK(*handle);
@ -1713,7 +1747,7 @@ TC_ZERO_COUNTER(const IPT_CHAINLABEL chain,
return 1; return 1;
} }
int int
TC_SET_COUNTER(const IPT_CHAINLABEL chain, TC_SET_COUNTER(const IPT_CHAINLABEL chain,
unsigned int rulenum, unsigned int rulenum,
STRUCT_COUNTERS *counters, STRUCT_COUNTERS *counters,
@ -1892,7 +1926,7 @@ int TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname,
} }
strncpy(c->name, newname, sizeof(IPT_CHAINLABEL)); strncpy(c->name, newname, sizeof(IPT_CHAINLABEL));
set_changed(*handle); set_changed(*handle);
return 1; return 1;
@ -2092,7 +2126,7 @@ TC_COMMIT(TC_HANDLE_T *handle)
#ifdef IPTC_DEBUG2 #ifdef IPTC_DEBUG2
{ {
int fd = open("/tmp/libiptc-so_set_replace.blob", int fd = open("/tmp/libiptc-so_set_replace.blob",
O_CREAT|O_WRONLY); O_CREAT|O_WRONLY);
if (fd >= 0) { if (fd >= 0) {
write(fd, repl, sizeof(*repl) + repl->size); write(fd, repl, sizeof(*repl) + repl->size);
@ -2125,12 +2159,12 @@ TC_COMMIT(TC_HANDLE_T *handle)
break; break;
case COUNTER_MAP_NORMAL_MAP: case COUNTER_MAP_NORMAL_MAP:
counters_normal_map(newcounters, repl, counters_normal_map(newcounters, repl,
c->foot_index, c->foot_index,
c->counter_map.mappos); c->counter_map.mappos);
break; break;
case COUNTER_MAP_ZEROED: case COUNTER_MAP_ZEROED:
counters_map_zeroed(newcounters, repl, counters_map_zeroed(newcounters, repl,
c->foot_index, c->foot_index,
c->counter_map.mappos, c->counter_map.mappos,
&c->counters); &c->counters);
break; break;
@ -2150,7 +2184,7 @@ TC_COMMIT(TC_HANDLE_T *handle)
case COUNTER_MAP_NORMAL_MAP: case COUNTER_MAP_NORMAL_MAP:
counters_normal_map(newcounters, repl, counters_normal_map(newcounters, repl,
r->index, r->index,
r->counter_map.mappos); r->counter_map.mappos);
break; break;
@ -2187,7 +2221,7 @@ TC_COMMIT(TC_HANDLE_T *handle)
#ifdef IPTC_DEBUG2 #ifdef IPTC_DEBUG2
{ {
int fd = open("/tmp/libiptc-so_set_add_counters.blob", int fd = open("/tmp/libiptc-so_set_add_counters.blob",
O_CREAT|O_WRONLY); O_CREAT|O_WRONLY);
if (fd >= 0) { if (fd >= 0) {
write(fd, newcounters, counterlen); write(fd, newcounters, counterlen);
@ -2232,7 +2266,7 @@ TC_STRERROR(int err)
} table [] = } table [] =
{ { TC_INIT, EPERM, "Permission denied (you must be root)" }, { { TC_INIT, EPERM, "Permission denied (you must be root)" },
{ TC_INIT, EINVAL, "Module is wrong version" }, { TC_INIT, EINVAL, "Module is wrong version" },
{ TC_INIT, ENOENT, { TC_INIT, ENOENT,
"Table does not exist (do you need to insmod?)" }, "Table does not exist (do you need to insmod?)" },
{ TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" },
{ TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" },