mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-08 13:44:56 +02:00
geoip: split user/kernel-visible parts of struct geoip_info
This commit is contained in:
@@ -122,11 +122,11 @@ get_country_subnets(u_int16_t cc, u_int32_t *count)
|
|||||||
return subnets;
|
return subnets;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct geoip_info *
|
static struct geoip_country_user *
|
||||||
load_geoip_cc(u_int16_t cc)
|
load_geoip_cc(u_int16_t cc)
|
||||||
{
|
{
|
||||||
static struct geoip_info *ginfo;
|
struct geoip_country_user *ginfo;
|
||||||
ginfo = malloc(sizeof(struct geoip_info));
|
ginfo = malloc(sizeof(struct geoip_country_user));
|
||||||
|
|
||||||
if (!ginfo)
|
if (!ginfo)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -175,7 +175,7 @@ check_geoip_cc(char *cc, u_int16_t cc_used[], u_int8_t count)
|
|||||||
|
|
||||||
/* Based on libipt_multiport.c parsing code. */
|
/* Based on libipt_multiport.c parsing code. */
|
||||||
static u_int8_t
|
static u_int8_t
|
||||||
parse_geoip_cc(const char *ccstr, u_int16_t *cc, struct geoip_info **mem)
|
parse_geoip_cc(const char *ccstr, u_int16_t *cc, union geoip_country_group *mem)
|
||||||
{
|
{
|
||||||
char *buffer, *cp, *next;
|
char *buffer, *cp, *next;
|
||||||
u_int8_t i, count = 0;
|
u_int8_t i, count = 0;
|
||||||
@@ -192,7 +192,7 @@ parse_geoip_cc(const char *ccstr, u_int16_t *cc, struct geoip_info **mem)
|
|||||||
if (next) *next++ = '\0';
|
if (next) *next++ = '\0';
|
||||||
|
|
||||||
if ((cctmp = check_geoip_cc(cp, cc, count)) != 0) {
|
if ((cctmp = check_geoip_cc(cp, cc, count)) != 0) {
|
||||||
if ((mem[count++] = load_geoip_cc(cctmp)) == NULL)
|
if ((mem[count++].user = load_geoip_cc(cctmp)) == NULL)
|
||||||
exit_error(OTHER_PROBLEM,
|
exit_error(OTHER_PROBLEM,
|
||||||
"geoip: insufficient memory available");
|
"geoip: insufficient memory available");
|
||||||
cc[count-1] = cctmp;
|
cc[count-1] = cctmp;
|
||||||
|
@@ -27,24 +27,39 @@ MODULE_AUTHOR("Samuel Jean");
|
|||||||
MODULE_DESCRIPTION("xtables module for geoip match");
|
MODULE_DESCRIPTION("xtables module for geoip match");
|
||||||
MODULE_ALIAS("ipt_geoip");
|
MODULE_ALIAS("ipt_geoip");
|
||||||
|
|
||||||
struct geoip_info *head = NULL;
|
struct geoip_country_kernel {
|
||||||
|
struct geoip_subnet *subnets;
|
||||||
|
u_int32_t count;
|
||||||
|
u_int32_t ref;
|
||||||
|
u_int16_t cc;
|
||||||
|
struct geoip_country_kernel *next;
|
||||||
|
struct geoip_country_kernel *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct geoip_country_kernel *head = NULL;
|
||||||
static spinlock_t geoip_lock = SPIN_LOCK_UNLOCKED;
|
static spinlock_t geoip_lock = SPIN_LOCK_UNLOCKED;
|
||||||
|
|
||||||
static struct geoip_info *add_node(struct geoip_info *memcpy)
|
static struct geoip_country_kernel *
|
||||||
|
geoip_add_node(const struct geoip_country_user __user *umem_ptr)
|
||||||
{
|
{
|
||||||
struct geoip_info *p = kmalloc(sizeof(struct geoip_info), GFP_KERNEL);
|
struct geoip_country_user umem;
|
||||||
|
struct geoip_country_kernel *p;
|
||||||
struct geoip_subnet *s;
|
struct geoip_subnet *s;
|
||||||
|
|
||||||
|
if (copy_from_user(&umem, umem_ptr, sizeof(umem)) != 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
p = kmalloc(sizeof(struct geoip_country_kernel), GFP_KERNEL);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (copy_from_user(p, memcpy, sizeof(struct geoip_info)) != 0)
|
|
||||||
goto free_p;
|
p->count = umem.count;
|
||||||
|
p->cc = umem.cc;
|
||||||
|
|
||||||
s = vmalloc(p->count * sizeof(struct geoip_subnet));
|
s = vmalloc(p->count * sizeof(struct geoip_subnet));
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
goto free_p;
|
goto free_p;
|
||||||
if (copy_from_user(s, p->subnets, p->count * sizeof(struct geoip_subnet)) != 0)
|
if (copy_from_user(s, umem.subnets, p->count * sizeof(struct geoip_subnet)) != 0)
|
||||||
goto free_s;
|
goto free_s;
|
||||||
|
|
||||||
spin_lock_bh(&geoip_lock);
|
spin_lock_bh(&geoip_lock);
|
||||||
@@ -66,7 +81,7 @@ static struct geoip_info *add_node(struct geoip_info *memcpy)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void geoip_try_remove_node(struct geoip_info *p)
|
static void geoip_try_remove_node(struct geoip_country_kernel *p)
|
||||||
{
|
{
|
||||||
spin_lock_bh(&geoip_lock);
|
spin_lock_bh(&geoip_lock);
|
||||||
if (!atomic_dec_and_test((atomic_t *)&p->ref)) {
|
if (!atomic_dec_and_test((atomic_t *)&p->ref)) {
|
||||||
@@ -95,9 +110,9 @@ static void geoip_try_remove_node(struct geoip_info *p)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct geoip_info *find_node(u_int16_t cc)
|
static struct geoip_country_kernel *find_node(u_int16_t cc)
|
||||||
{
|
{
|
||||||
struct geoip_info *p = head;
|
struct geoip_country_kernel *p = head;
|
||||||
spin_lock_bh(&geoip_lock);
|
spin_lock_bh(&geoip_lock);
|
||||||
|
|
||||||
while (p) {
|
while (p) {
|
||||||
@@ -136,7 +151,7 @@ static bool xt_geoip_mt(const struct sk_buff *skb, const struct net_device *in,
|
|||||||
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
|
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
|
||||||
{
|
{
|
||||||
const struct xt_geoip_match_info *info = matchinfo;
|
const struct xt_geoip_match_info *info = matchinfo;
|
||||||
const struct geoip_info *node; /* This keeps the code sexy */
|
const struct geoip_country_kernel *node;
|
||||||
const struct iphdr *iph = ip_hdr(skb);
|
const struct iphdr *iph = ip_hdr(skb);
|
||||||
uint32_t ip, i;
|
uint32_t ip, i;
|
||||||
|
|
||||||
@@ -147,7 +162,7 @@ static bool xt_geoip_mt(const struct sk_buff *skb, const struct net_device *in,
|
|||||||
|
|
||||||
spin_lock_bh(&geoip_lock);
|
spin_lock_bh(&geoip_lock);
|
||||||
for (i = 0; i < info->count; i++) {
|
for (i = 0; i < info->count; i++) {
|
||||||
if ((node = info->mem[i]) == NULL) {
|
if ((node = info->mem[i].kernel) == NULL) {
|
||||||
printk(KERN_ERR "xt_geoip: what the hell ?? '%c%c' isn't loaded into memory... skip it!\n",
|
printk(KERN_ERR "xt_geoip: what the hell ?? '%c%c' isn't loaded into memory... skip it!\n",
|
||||||
COUNTRY(info->cc[i]));
|
COUNTRY(info->cc[i]));
|
||||||
|
|
||||||
@@ -168,13 +183,13 @@ static bool xt_geoip_mt_checkentry(const char *table, const void *entry,
|
|||||||
const struct xt_match *match, void *matchinfo, unsigned int hook_mask)
|
const struct xt_match *match, void *matchinfo, unsigned int hook_mask)
|
||||||
{
|
{
|
||||||
struct xt_geoip_match_info *info = matchinfo;
|
struct xt_geoip_match_info *info = matchinfo;
|
||||||
struct geoip_info *node;
|
struct geoip_country_kernel *node;
|
||||||
u_int8_t i;
|
u_int8_t i;
|
||||||
|
|
||||||
for (i = 0; i < info->count; i++) {
|
for (i = 0; i < info->count; i++) {
|
||||||
node = find_node(info->cc[i]);
|
node = find_node(info->cc[i]);
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
if ((node = add_node(info->mem[i])) == NULL) {
|
if ((node = geoip_add_node(info->mem[i].user)) == NULL) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"xt_geoip: unable to load '%c%c' into memory\n",
|
"xt_geoip: unable to load '%c%c' into memory\n",
|
||||||
COUNTRY(info->cc[i]));
|
COUNTRY(info->cc[i]));
|
||||||
@@ -186,7 +201,7 @@ static bool xt_geoip_mt_checkentry(const char *table, const void *entry,
|
|||||||
* This avoids searching for a node in the match() and
|
* This avoids searching for a node in the match() and
|
||||||
* destroy() functions.
|
* destroy() functions.
|
||||||
*/
|
*/
|
||||||
info->mem[i] = node;
|
info->mem[i].kernel = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -195,7 +210,7 @@ static bool xt_geoip_mt_checkentry(const char *table, const void *entry,
|
|||||||
static void xt_geoip_mt_destroy(const struct xt_match *match, void *matchinfo)
|
static void xt_geoip_mt_destroy(const struct xt_match *match, void *matchinfo)
|
||||||
{
|
{
|
||||||
struct xt_geoip_match_info *info = matchinfo;
|
struct xt_geoip_match_info *info = matchinfo;
|
||||||
struct geoip_info *node; /* this keeps the code sexy */
|
struct geoip_country_kernel *node;
|
||||||
u_int8_t i;
|
u_int8_t i;
|
||||||
|
|
||||||
/* This entry has been removed from the table so
|
/* This entry has been removed from the table so
|
||||||
@@ -204,7 +219,7 @@ static void xt_geoip_mt_destroy(const struct xt_match *match, void *matchinfo)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
for (i = 0; i < info->count; i++)
|
for (i = 0; i < info->count; i++)
|
||||||
if ((node = info->mem[i]) != NULL) {
|
if ((node = info->mem[i].kernel) != NULL) {
|
||||||
/* Free up some memory if that node isn't used
|
/* Free up some memory if that node isn't used
|
||||||
* anymore. */
|
* anymore. */
|
||||||
geoip_try_remove_node(node);
|
geoip_try_remove_node(node);
|
||||||
|
@@ -24,13 +24,17 @@ struct geoip_subnet {
|
|||||||
u_int32_t end;
|
u_int32_t end;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct geoip_info {
|
struct geoip_country_user {
|
||||||
struct geoip_subnet *subnets;
|
struct geoip_subnet *subnets;
|
||||||
u_int32_t count;
|
u_int32_t count;
|
||||||
u_int32_t ref;
|
|
||||||
u_int16_t cc;
|
u_int16_t cc;
|
||||||
struct geoip_info *next;
|
};
|
||||||
struct geoip_info *prev;
|
|
||||||
|
struct geoip_country_kernel;
|
||||||
|
|
||||||
|
union geoip_country_group {
|
||||||
|
struct geoip_country_user *user;
|
||||||
|
struct geoip_country_kernel *kernel;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xt_geoip_match_info {
|
struct xt_geoip_match_info {
|
||||||
@@ -39,7 +43,7 @@ struct xt_geoip_match_info {
|
|||||||
u_int16_t cc[XT_GEOIP_MAX];
|
u_int16_t cc[XT_GEOIP_MAX];
|
||||||
|
|
||||||
/* Used internally by the kernel */
|
/* Used internally by the kernel */
|
||||||
struct geoip_info *mem[XT_GEOIP_MAX];
|
union geoip_country_group mem[XT_GEOIP_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define COUNTRY(cc) (cc >> 8), (cc & 0x00FF)
|
#define COUNTRY(cc) (cc >> 8), (cc & 0x00FF)
|
||||||
|
Reference in New Issue
Block a user