diff options
author | Kozlov Dmitry <dima@server> | 2010-10-06 16:43:14 +0400 |
---|---|---|
committer | Kozlov Dmitry <dima@server> | 2010-10-06 16:43:14 +0400 |
commit | b6a1268714671904e96a49b88680dc3ff07aaa1c (patch) | |
tree | 60424372b94312710b9f583b1bcc641de4020316 /accel-pptpd/extra | |
parent | 5cf93f33f2350ed3b92f73ead1d2829a6883810a (diff) | |
download | accel-ppp-b6a1268714671904e96a49b88680dc3ff07aaa1c.tar.gz accel-ppp-b6a1268714671904e96a49b88680dc3ff07aaa1c.zip |
project cleanup and prepare to release
Diffstat (limited to 'accel-pptpd/extra')
-rw-r--r-- | accel-pptpd/extra/CMakeLists.txt | 6 | ||||
-rw-r--r-- | accel-pptpd/extra/ippool.c | 208 | ||||
-rw-r--r-- | accel-pptpd/extra/pppd_compat.c | 10 | ||||
-rw-r--r-- | accel-pptpd/extra/sigchld.c | 117 | ||||
-rw-r--r-- | accel-pptpd/extra/sigchld.h | 21 |
5 files changed, 357 insertions, 5 deletions
diff --git a/accel-pptpd/extra/CMakeLists.txt b/accel-pptpd/extra/CMakeLists.txt index 7b4b69b6..a14a5a3b 100644 --- a/accel-pptpd/extra/CMakeLists.txt +++ b/accel-pptpd/extra/CMakeLists.txt @@ -1,2 +1,8 @@ ADD_LIBRARY(pppd_compat SHARED pppd_compat.c) +ADD_LIBRARY(ippool SHARED ippool.c) +ADD_LIBRARY(sigchld SHARED sigchld.c) + +INSTALL(TARGETS pppd_compat ippool sigchld + LIBRARY DESTINATION usr/lib/accel-pptp +) diff --git a/accel-pptpd/extra/ippool.c b/accel-pptpd/extra/ippool.c new file mode 100644 index 00000000..5f90fe8a --- /dev/null +++ b/accel-pptpd/extra/ippool.c @@ -0,0 +1,208 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> +#include <arpa/inet.h> + +#include "ipdb.h" +#include "list.h" +#include "spinlock.h" + +#include "memdebug.h" + +struct ippool_item_t +{ + struct list_head entry; + struct ipdb_item_t it; +}; + +struct ipaddr_t +{ + struct list_head entry; + in_addr_t addr; +}; + +static LIST_HEAD(gw_list); +static LIST_HEAD(tunnel_list); +static LIST_HEAD(ippool); +static spinlock_t pool_lock = SPINLOCK_INITIALIZER; +static struct ipdb_t ipdb; + +static in_addr_t conf_gw_ip_address; +static int cnt; + +static void parse_gw_ip_address(const char *val) +{ + if (!val) + return; + + conf_gw_ip_address = inet_addr(val); +} + +//parses ranges like x.x.x.x/mask +static int parse1(const char *str, uint32_t *begin, uint32_t *end) +{ + int n, f1, f2, f3, f4, m, mask = 0; + + n = sscanf(str, "%u.%u.%u.%u/%u",&f1, &f2, &f3, &f4, &m); + if (n != 5) + return -1; + if (f1 > 255) + return -1; + if (f1 > 255) + return -1; + if (f1 > 255) + return -1; + if (f1 > 255) + return -1; + if (m == 0 || m > 32) + return -1; + + for (n = 0; n < m ; n++) + mask |= 1 << n; + + *begin = (f4 << 24) | (f3 << 16) | (f2 << 8) | f1; + *end = *begin | ~mask; + + return 0; +} + +//parses ranges like x.x.x.x-y +static int parse2(const char *str, uint32_t *begin, uint32_t *end) +{ + int n, f1, f2, f3, f4, m; + + n = sscanf(str, "%u.%u.%u.%u-%u",&f1, &f2, &f3, &f4, &m); + if (n != 5) + return -1; + if (f1 > 255) + return -1; + if (f2 > 255) + return -1; + if (f3 > 255) + return -1; + if (f4 > 255) + return -1; + if (m < f4 || m > 255) + return -1; + + *begin = (f4 << 24) | (f3 << 16) | (f2 << 8) | f1; + *end = (m << 24) | (f3 << 16) | (f2 << 8) | f1; + + return 0; +} + +static void add_range(struct list_head *list, const char *name) +{ + uint32_t i,startip, endip; + struct ipaddr_t *ip; + + if (parse1(name, &startip, &endip)) + if (parse2(name, &startip, &endip)) { + fprintf(stderr, "ippool: cann't parse '%s'\n", name); + _exit(EXIT_FAILURE); + } + + for (i = ntohl(startip); i <= ntohl(endip); i++) { + ip = malloc(sizeof(*ip)); + ip->addr = htonl(i); + list_add_tail(&ip->entry, list); + cnt++; + } +} + +static void generate_pool(void) +{ + struct ippool_item_t *it; + struct ipaddr_t *addr = NULL; + struct ipaddr_t *peer_addr; + + while (1) { + if (list_empty(&tunnel_list)) + break; + else { + peer_addr = list_entry(tunnel_list.next, typeof(*peer_addr), entry); + list_del(&peer_addr->entry); + } + + if (!conf_gw_ip_address) { + if (list_empty(&gw_list)) + break; + else { + addr = list_entry(gw_list.next, typeof(*addr), entry); + list_del(&addr->entry); + } + } + + it = malloc(sizeof(*it)); + if (!it) { + fprintf(stderr, "ippool: out of memory\n"); + break; + } + + it->it.owner = &ipdb; + if (conf_gw_ip_address) + it->it.addr = conf_gw_ip_address; + else + it->it.addr = addr->addr; + + it->it.peer_addr = peer_addr->addr; + + list_add_tail(&it->entry, &ippool); + } +} + +static struct ipdb_item_t *get_ip(struct ppp_t *ppp) +{ + struct ippool_item_t *it; + + spin_lock(&pool_lock); + if (!list_empty(&ippool)) { + it = list_entry(ippool.next, typeof(*it), entry); + list_del(&it->entry); + } else + it = NULL; + spin_unlock(&pool_lock); + + return it ? &it->it : NULL; +} + +static void put_ip(struct ppp_t *ppp, struct ipdb_item_t *it) +{ + struct ippool_item_t *pit = container_of(it, typeof(*pit), it); + + spin_lock(&pool_lock); + list_add_tail(&pit->entry, &ippool); + spin_unlock(&pool_lock); +} + +static struct ipdb_t ipdb = { + .get = get_ip, + .put = put_ip, +}; + +static void __init ipool_init(void) +{ + struct conf_sect_t *s = conf_get_section("ip-pool"); + struct conf_option_t *opt; + + if (!s) + return; + + list_for_each_entry(opt, &s->items, entry) { + if (!strcmp(opt->name, "gw-ip-address")) + parse_gw_ip_address(opt->val); + else if (!strcmp(opt->name, "gw")) + add_range(&gw_list, opt->val); + else if (!strcmp(opt->name, "tunnel")) + add_range(&tunnel_list, opt->val); + else if (!opt->val) + add_range(&tunnel_list, opt->name); + } + + generate_pool(); + + ipdb_register(&ipdb); +} + diff --git a/accel-pptpd/extra/pppd_compat.c b/accel-pptpd/extra/pppd_compat.c index e45d609a..8dd35028 100644 --- a/accel-pptpd/extra/pppd_compat.c +++ b/accel-pptpd/extra/pppd_compat.c @@ -48,7 +48,7 @@ static void ip_up_handler(struct sigchld_handler_t *h, int status) struct pppd_compat_pd_t *pd = container_of(h, typeof(*pd), ip_up_hnd); if (conf_verbose) { log_switch(NULL, pd->ppp); - log_ppp_debug("pppd_compat: ip-up finished (%i)\n", status); + log_ppp_info("pppd_compat: ip-up finished (%i)\n", status); } } @@ -57,7 +57,7 @@ static void ip_down_handler(struct sigchld_handler_t *h, int status) struct pppd_compat_pd_t *pd = container_of(h, typeof(*pd), ip_down_hnd); if (conf_verbose) { log_switch(NULL, pd->ppp); - log_ppp_debug("pppd_compat: ip-down finished (%i)\n", status); + log_ppp_info("pppd_compat: ip-down finished (%i)\n", status); } sched_yield(); triton_context_wakeup(pd->ppp->ctrl->ctx); @@ -68,7 +68,7 @@ static void ip_change_handler(struct sigchld_handler_t *h, int status) struct pppd_compat_pd_t *pd = container_of(h, typeof(*pd), ip_change_hnd); if (conf_verbose) { log_switch(NULL, pd->ppp); - log_ppp_debug("pppd_compat: ip-change finished (%i)\n", status); + log_ppp_info("pppd_compat: ip-change finished (%i)\n", status); } sched_yield(); pd->ip_change_res = status; @@ -113,7 +113,7 @@ static void ev_ppp_started(struct ppp_t *ppp) pd->ip_up_hnd.pid = pid; sigchld_register_handler(&pd->ip_up_hnd); if (conf_verbose) - log_ppp_debug("pppd_compat: ip-up started (pid %i)\n", pid); + log_ppp_info("pppd_compat: ip-up started (pid %i)\n", pid); sigchld_unlock(); } else if (pid == 0) { execv(conf_ip_up, argv); @@ -156,7 +156,7 @@ static void ev_ppp_finished(struct ppp_t *ppp) pd->ip_down_hnd.pid = pid; sigchld_register_handler(&pd->ip_down_hnd); if (conf_verbose) - log_ppp_debug("pppd_compat: ip-down started (pid %i)\n", pid); + log_ppp_info("pppd_compat: ip-down started (pid %i)\n", pid); sigchld_unlock(); triton_context_schedule(pd->ppp->ctrl->ctx); pthread_mutex_lock(&pd->ip_down_hnd.lock); diff --git a/accel-pptpd/extra/sigchld.c b/accel-pptpd/extra/sigchld.c new file mode 100644 index 00000000..49bcfd43 --- /dev/null +++ b/accel-pptpd/extra/sigchld.c @@ -0,0 +1,117 @@ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <signal.h> +#include <sys/signalfd.h> +#include <sys/wait.h> + +#include "triton.h" +#include "spinlock.h" +#include "log.h" + +#include "sigchld.h" + +#include "memdebug.h" + +static LIST_HEAD(handlers); +static int lock_refs; +static pthread_mutex_t handlers_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t refs_cond = PTHREAD_COND_INITIALIZER; +static pthread_t sigchld_thr; + +static void* sigchld_thread(void *arg) +{ + sigset_t set; + struct sigchld_handler_t *h, *h0; + pid_t pid; + int status, sig; + + sigfillset(&set); + sigdelset(&set, SIGKILL); + sigdelset(&set, SIGSTOP); + pthread_sigmask(SIG_BLOCK, &set, NULL); + + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + sigaddset(&set, SIGQUIT); + + while (1) { + pid = waitpid(0, &status, 0); + if (pid < 0) { + if (errno == EINTR) + continue; + if (errno == ECHILD) { + sigwait(&set, &sig); + if (sig == SIGQUIT) + break; + continue; + } + log_error("sigchld: waitpid: %s\n", strerror(errno)); + continue; + } + + pthread_mutex_lock(&handlers_lock); + while (lock_refs) + pthread_cond_wait(&refs_cond, &handlers_lock); + + h0 = NULL; + list_for_each_entry(h, &handlers, entry) { + if (h->pid == pid) { + h0 = h; + pthread_mutex_lock(&h0->lock); + break; + } + } + pthread_mutex_unlock(&handlers_lock); + if (h0) { + list_del(&h0->entry); + h0->handler(h0, WEXITSTATUS(status)); + h0->pid = 0; + pthread_mutex_unlock(&h0->lock); + } + } + + return NULL; +} + +void __export sigchld_register_handler(struct sigchld_handler_t *h) +{ + pthread_mutex_init(&h->lock, NULL); + + pthread_mutex_lock(&handlers_lock); + list_add_tail(&h->entry, &handlers); + pthread_mutex_unlock(&handlers_lock); +} + +void __export sigchld_unregister_handler(struct sigchld_handler_t *h) +{ + pthread_mutex_lock(&handlers_lock); + pthread_mutex_lock(&h->lock); + if (h->pid) { + list_del(&h->entry); + h->pid = 0; + } + pthread_mutex_unlock(&h->lock); + pthread_mutex_unlock(&handlers_lock); +} + +void __export sigchld_lock() +{ + pthread_mutex_lock(&handlers_lock); + ++lock_refs; + pthread_mutex_unlock(&handlers_lock); +} + +void __export sigchld_unlock() +{ + pthread_mutex_lock(&handlers_lock); + if (--lock_refs == 0) + pthread_cond_signal(&refs_cond); + pthread_mutex_unlock(&handlers_lock); +} + +static void __init init(void) +{ + if (pthread_create(&sigchld_thr, NULL, sigchld_thread, NULL)) + log_emerg("sigchld: pthread_create: %s\n", strerror(errno)); +} diff --git a/accel-pptpd/extra/sigchld.h b/accel-pptpd/extra/sigchld.h new file mode 100644 index 00000000..27d1adf4 --- /dev/null +++ b/accel-pptpd/extra/sigchld.h @@ -0,0 +1,21 @@ +#ifndef __SIGCHLD_H +#define __SIGCHLD_H + +#include <pthread.h> +#include "list.h" + +struct sigchld_handler_t +{ + struct list_head entry; + pthread_mutex_t lock; + pid_t pid; + void (*handler)(struct sigchld_handler_t *, int status); +}; + +void sigchld_register_handler(struct sigchld_handler_t *); +void sigchld_unregister_handler(struct sigchld_handler_t *); +void sigchld_lock(); +void sigchld_unlock(); + +#endif + |