diff options
author | Kozlov Dmitry <dima@server> | 2010-09-09 18:26:02 +0400 |
---|---|---|
committer | Kozlov Dmitry <dima@server> | 2010-09-09 18:29:47 +0400 |
commit | 35d38d2c3f3db22216d43604b8750ecb6089e525 (patch) | |
tree | f599fea448c4aacdd96cabf10fee88aa7bdb57aa /accel-pptpd/iprange.c | |
parent | eac0adf4b2b038690c761a126cb3e55a888060df (diff) | |
download | accel-ppp-35d38d2c3f3db22216d43604b8750ecb6089e525.tar.gz accel-ppp-35d38d2c3f3db22216d43604b8750ecb6089e525.zip |
iprange: implemneted modules iprange to validate ip addresses of controlling connection and tunnel
It will check that ip address of tunnel is not in range of clients ip addresses.
This will avoid kernel softlockups due to loopback occured.
Diffstat (limited to 'accel-pptpd/iprange.c')
-rw-r--r-- | accel-pptpd/iprange.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/accel-pptpd/iprange.c b/accel-pptpd/iprange.c new file mode 100644 index 0000000..000e6e6 --- /dev/null +++ b/accel-pptpd/iprange.c @@ -0,0 +1,134 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <unistd.h> + +#include "triton.h" +#include "list.h" + +#include "iprange.h" + +struct iprange_t +{ + struct list_head entry; + uint32_t prefix; + uint32_t mask; + uint32_t end; +}; + +static LIST_HEAD(client_ranges); +//static LIST_HEAD(tunnel_ranges); + +//parses ranges like x.x.x.x/mask +static struct iprange_t *parse1(const char *str) +{ + int n,f1,f2,f3,f4,m; + struct iprange_t *r; + + n = sscanf(str, "%u.%u.%u.%u/%u",&f1, &f2, &f3, &f4, &m); + if (n != 5) + return NULL; + if (f1 > 255) + return NULL; + if (f1 > 255) + return NULL; + if (f1 > 255) + return NULL; + if (f1 > 255) + return NULL; + if (m == 0 || m > 32) + return NULL; + + r = malloc(sizeof(*r)); + r->prefix = (f4 << 24) | (f3 << 16) | (f2 << 8) | f1; + r->mask = 0; + + for (n = 0; n < m ; n++) + r->mask |= 1 << n; + + return r; +} + +//parses ranges like x.x.x.x-y +static struct iprange_t *parse2(const char *str) +{ + int n,f1,f2,f3,f4,m; + struct iprange_t *r; + + n = sscanf(str, "%u.%u.%u.%u-%u",&f1, &f2, &f3, &f4, &m); + if (n != 5) + return NULL; + if (f1 > 255) + return NULL; + if (f2 > 255) + return NULL; + if (f3 > 255) + return NULL; + if (f4 > 255) + return NULL; + if (m < f4 || m > 255) + return NULL; + + r = malloc(sizeof(*r)); + r->prefix = (f4 << 24) | (f3 << 16) | (f2 << 8) | f1; + r->end = (m << 24) | (f2 << 16) | (f3 << 8) | f1; + r->mask = 0; + + return r; +} + +static void load_ranges(struct list_head *list, const char *conf_sect) +{ + struct conf_sect_t *s = conf_get_section(conf_sect); + struct conf_option_t *opt; + struct iprange_t *r; + + if (!s) { + fprintf(stderr, "iprange: section '%s' not found in config file, pptp and l2tp probably will not work...\n", conf_sect); + return; + } + + list_for_each_entry(opt, &s->items, entry) { + r = parse1(opt->name); + if (!r) + r = parse2(opt->name); + if (!r) { + fprintf(stderr, "iprange: cann't parse '%s' in '%s'\n", opt->name, conf_sect); + _exit(EXIT_FAILURE); + } + list_add_tail(&r->entry, list); + } +} + +static int check_range(struct list_head *list, in_addr_t ipaddr) +{ + struct iprange_t *r; + + list_for_each_entry(r, list, entry) { + if (r->mask) { + if ((r->prefix & r->mask) == (ipaddr & r->mask)) + return 0; + } else { + if (ipaddr >= r->prefix && ipaddr <= r->end) + return 0; + } + } + + return -1; +} + +int __export iprange_client_check(in_addr_t ipaddr) +{ + return check_range(&client_ranges, ipaddr); +} +/*int __export iprange_tunnel_check(in_addr_t ipaddr) +{ + return check_range(&tunnel_ranges, ipaddr); +}*/ + +static void __init iprange_init(void) +{ + load_ranges(&client_ranges, "client-ip-range"); + //load_ranges(&tunnel_ranges, "tunnel-ip-range"); +} + |