return subnets;
}
-static struct geoip_info *
+static struct geoip_country_user *
load_geoip_cc(u_int16_t cc)
{
- static struct geoip_info *ginfo;
- ginfo = malloc(sizeof(struct geoip_info));
+ struct geoip_country_user *ginfo;
+ ginfo = malloc(sizeof(struct geoip_country_user));
if (!ginfo)
return NULL;
/* Based on libipt_multiport.c parsing code. */
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;
u_int8_t i, count = 0;
if (next) *next++ = '\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,
"geoip: insufficient memory available");
cc[count-1] = cctmp;
MODULE_DESCRIPTION("xtables module for geoip match");
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 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;
+ if (copy_from_user(&umem, umem_ptr, sizeof(umem)) != 0)
+ return NULL;
+
+ p = kmalloc(sizeof(struct geoip_country_kernel), GFP_KERNEL);
if (p == 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));
if (s == NULL)
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;
spin_lock_bh(&geoip_lock);
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);
if (!atomic_dec_and_test((atomic_t *)&p->ref)) {
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);
while (p) {
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
{
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);
uint32_t ip, i;
spin_lock_bh(&geoip_lock);
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",
COUNTRY(info->cc[i]));
const struct xt_match *match, void *matchinfo, unsigned int hook_mask)
{
struct xt_geoip_match_info *info = matchinfo;
- struct geoip_info *node;
+ struct geoip_country_kernel *node;
u_int8_t i;
for (i = 0; i < info->count; i++) {
node = find_node(info->cc[i]);
if (node == NULL)
- if ((node = add_node(info->mem[i])) == NULL) {
+ if ((node = geoip_add_node(info->mem[i].user)) == NULL) {
printk(KERN_ERR
"xt_geoip: unable to load '%c%c' into memory\n",
COUNTRY(info->cc[i]));
* This avoids searching for a node in the match() and
* destroy() functions.
*/
- info->mem[i] = node;
+ info->mem[i].kernel = node;
}
return 1;
static void xt_geoip_mt_destroy(const struct xt_match *match, void *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;
/* This entry has been removed from the table so
*/
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
* anymore. */
geoip_try_remove_node(node);
u_int32_t end;
};
-struct geoip_info {
+struct geoip_country_user {
struct geoip_subnet *subnets;
u_int32_t count;
- u_int32_t ref;
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 {
u_int16_t cc[XT_GEOIP_MAX];
/* 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)