diff options
Diffstat (limited to 'accel-pppd/iprange.c')
-rw-r--r-- | accel-pppd/iprange.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/accel-pppd/iprange.c b/accel-pppd/iprange.c new file mode 100644 index 00000000..411dcb76 --- /dev/null +++ b/accel-pppd/iprange.c @@ -0,0 +1,146 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> + +#include "triton.h" +#include "list.h" +#include "log.h" + +#include "iprange.h" + +#include "memdebug.h" + +struct iprange_t +{ + struct list_head entry; + uint32_t begin; + uint32_t end; +}; + +static int conf_disable = 0; + +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; + int mask; + + 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 == 0 || m > 32) + return NULL; + + r = _malloc(sizeof(*r)); + r->begin = (f4 << 24) | (f3 << 16) | (f2 << 8) | f1; + + mask = htonl(~((1 << (32 - m)) - 1)); + r->end = ntohl(r->begin | ~mask); + r->begin = ntohl(r->begin); + + 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->begin = ntohl((f4 << 24) | (f3 << 16) | (f2 << 8) | f1); + r->end = ntohl((m << 24) | (f3 << 16) | (f2 << 8) | f1); + + 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) { + log_emerg("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) { + if (!strcmp(opt->name, "disable")) { + conf_disable = 1; + log_emerg("iprange: iprange module disabled so improper ip address assigning may cause kernel soft lockup!\n"); + continue; + } + r = parse1(opt->name); + if (!r) + r = parse2(opt->name); + if (!r) { + log_emerg("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; + uint32_t a = ntohl(ipaddr); + + list_for_each_entry(r, list, entry) { + if (a >= r->begin && a <= r->end) + return 0; + } + + return -1; +} + +int __export iprange_client_check(in_addr_t ipaddr) +{ + if (conf_disable) + return 0; + + return check_range(&client_ranges, ipaddr); +} +int __export iprange_tunnel_check(in_addr_t ipaddr) +{ + if (conf_disable) + return 0; + + return !check_range(&client_ranges, ipaddr); +} + +static void __init iprange_init(void) +{ + load_ranges(&client_ranges, "client-ip-range"); + //load_ranges(&tunnel_ranges, "tunnel-ip-range"); +} + |