diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2011-01-05 15:18:59 +0300 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2011-01-05 15:18:59 +0300 |
commit | f28cb1b0a926f1ea98700b7871537ad1793511fd (patch) | |
tree | baf35570bc6b38b6fab5b6524e8f19f58f71e57f /accel-pptpd/ppp/ppp.c | |
parent | 2fdf3586c13a72c36f9530084962e29d57dc0329 (diff) | |
download | accel-ppp-f28cb1b0a926f1ea98700b7871537ad1793511fd.tar.gz accel-ppp-f28cb1b0a926f1ea98700b7871537ad1793511fd.zip |
rename accel-pptp to accel-ppp
Diffstat (limited to 'accel-pptpd/ppp/ppp.c')
-rw-r--r-- | accel-pptpd/ppp/ppp.c | 681 |
1 files changed, 0 insertions, 681 deletions
diff --git a/accel-pptpd/ppp/ppp.c b/accel-pptpd/ppp/ppp.c deleted file mode 100644 index 6cf1c72..0000000 --- a/accel-pptpd/ppp/ppp.c +++ /dev/null @@ -1,681 +0,0 @@ -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <arpa/inet.h> -#include <features.h> -#include <signal.h> -#include "linux_ppp.h" - -#include <openssl/md5.h> - -#include "triton.h" - -#include "events.h" -#include "ppp.h" -#include "ppp_fsm.h" -#include "log.h" -#include "spinlock.h" - -#include "memdebug.h" - -int __export conf_ppp_verbose; -static int conf_sid_ucase; - -pthread_rwlock_t __export ppp_lock = PTHREAD_RWLOCK_INITIALIZER; -__export LIST_HEAD(ppp_list); - -static LIST_HEAD(layers); -int __export sock_fd; - -int __export ppp_shutdown; - -static unsigned long long seq; -#if __WORDSIZE == 32 -static spinlock_t seq_lock; -#endif - - -struct ppp_stat_t ppp_stat; - -struct layer_node_t -{ - struct list_head entry; - int order; - struct list_head items; -}; - -static int ppp_chan_read(struct triton_md_handler_t*); -static int ppp_unit_read(struct triton_md_handler_t*); -static void init_layers(struct ppp_t *); -static void _free_layers(struct ppp_t *); -static void start_first_layer(struct ppp_t *); - -void __export ppp_init(struct ppp_t *ppp) -{ - memset(ppp,0,sizeof(*ppp)); - INIT_LIST_HEAD(&ppp->layers); - INIT_LIST_HEAD(&ppp->chan_handlers); - INIT_LIST_HEAD(&ppp->unit_handlers); - INIT_LIST_HEAD(&ppp->pd_list); -} - -static void _free_ppp(struct ppp_t *ppp) -{ - if (ppp->chan_buf) - free(ppp->chan_buf); - if (ppp->unit_buf) - _free(ppp->unit_buf); - if (ppp->username) - _free(ppp->username); -} - -static void generate_sessionid(struct ppp_t *ppp) -{ - unsigned long long sid; - -#if __WORDSIZE == 32 - spin_lock(&seq_lock); - sid = ++seq; - spin_unlock(&seq_lock); -#else - sid = __sync_add_and_fetch(&seq, 1); -#endif - - if (conf_sid_ucase) - sprintf(ppp->sessionid, "%016llX", sid); - else - sprintf(ppp->sessionid, "%016llx", sid); -} - -int __export establish_ppp(struct ppp_t *ppp) -{ - /* Open an instance of /dev/ppp and connect the channel to it */ - if (ioctl(ppp->fd, PPPIOCGCHAN, &ppp->chan_idx) == -1) { - log_ppp_error("ioctl(PPPIOCGCHAN): %s\n", strerror(errno)); - return -1; - } - - ppp->chan_fd = open("/dev/ppp", O_RDWR); - if (ppp->chan_fd < 0) { - log_ppp_error("open(chan) /dev/ppp: %s\n", strerror(errno)); - return -1; - } - - if (ioctl(ppp->chan_fd, PPPIOCATTCHAN, &ppp->chan_idx) < 0) { - log_ppp_error("ioctl(PPPIOCATTCHAN): %s\n", strerror(errno)); - goto exit_close_chan; - } - - ppp->unit_fd = open("/dev/ppp", O_RDWR); - if (ppp->unit_fd < 0) { - log_ppp_error("open(unit) /dev/ppp: %s\n", strerror(errno)); - goto exit_close_chan; - } - - ppp->unit_idx = -1; - if (ioctl(ppp->unit_fd, PPPIOCNEWUNIT, &ppp->unit_idx) < 0) { - log_ppp_error("ioctl(PPPIOCNEWUNIT): %s\n", strerror(errno)); - goto exit_close_unit; - } - - if (ioctl(ppp->chan_fd, PPPIOCCONNECT, &ppp->unit_idx) < 0) { - log_ppp_error("ioctl(PPPIOCCONNECT): %s\n", strerror(errno)); - goto exit_close_unit; - } - - if (fcntl(ppp->chan_fd, F_SETFL, O_NONBLOCK)) { - log_ppp_error("ppp: cann't to set nonblocking mode: %s\n", strerror(errno)); - goto exit_close_unit; - } - - if (fcntl(ppp->unit_fd, F_SETFL, O_NONBLOCK)) { - log_ppp_error("ppp: cann't to set nonblocking mode: %s\n", strerror(errno)); - goto exit_close_unit; - } - - ppp->start_time = time(NULL); - generate_sessionid(ppp); - sprintf(ppp->ifname, "ppp%i", ppp->unit_idx); - - log_ppp_info1("connect: %s <--> %s(%s)\n", ppp->ifname, ppp->ctrl->name, ppp->chan_name); - - init_layers(ppp); - - if (list_empty(&ppp->layers)) { - log_ppp_error("no layers to start\n"); - goto exit_close_unit; - } - - ppp->chan_buf = _malloc(PPP_MRU); - ppp->unit_buf = _malloc(PPP_MRU); - - ppp->chan_hnd.fd = ppp->chan_fd; - ppp->chan_hnd.read = ppp_chan_read; - ppp->unit_hnd.fd = ppp->unit_fd; - ppp->unit_hnd.read = ppp_unit_read; - triton_md_register_handler(ppp->ctrl->ctx, &ppp->chan_hnd); - triton_md_register_handler(ppp->ctrl->ctx, &ppp->unit_hnd); - - triton_md_enable_handler(&ppp->chan_hnd, MD_MODE_READ); - triton_md_enable_handler(&ppp->unit_hnd, MD_MODE_READ); - - ppp->state = PPP_STATE_STARTING; - __sync_add_and_fetch(&ppp_stat.starting, 1); - - pthread_rwlock_wrlock(&ppp_lock); - list_add_tail(&ppp->entry, &ppp_list); - pthread_rwlock_unlock(&ppp_lock); - - log_ppp_debug("ppp established\n"); - - triton_event_fire(EV_PPP_STARTING, ppp); - - start_first_layer(ppp); - - return 0; - -exit_close_unit: - close(ppp->unit_fd); -exit_close_chan: - close(ppp->chan_fd); - - _free_ppp(ppp); - - return -1; -} - -static void destablish_ppp(struct ppp_t *ppp) -{ - pthread_rwlock_wrlock(&ppp_lock); - list_del(&ppp->entry); - pthread_rwlock_unlock(&ppp_lock); - - switch (ppp->state) { - case PPP_STATE_ACTIVE: - __sync_sub_and_fetch(&ppp_stat.active, 1); - break; - case PPP_STATE_STARTING: - __sync_sub_and_fetch(&ppp_stat.starting, 1); - break; - case PPP_STATE_FINISHING: - __sync_sub_and_fetch(&ppp_stat.finishing, 1); - break; - } - - triton_md_unregister_handler(&ppp->chan_hnd); - triton_md_unregister_handler(&ppp->unit_hnd); - - close(ppp->unit_fd); - close(ppp->chan_fd); - close(ppp->fd); - - ppp->unit_fd = -1; - ppp->chan_fd = -1; - ppp->fd = -1; - - _free(ppp->unit_buf); - _free(ppp->chan_buf); - - _free_layers(ppp); - - ppp->terminated = 1; - - log_ppp_debug("ppp destablished\n"); - - triton_event_fire(EV_PPP_FINISHED, ppp); - ppp->ctrl->finished(ppp); - - if (ppp->username) { - _free(ppp->username); - ppp->username = NULL; - } - - if (ppp_shutdown && !ppp_stat.starting && !ppp_stat.active && !ppp_stat.finishing) - kill(getpid(), SIGTERM); -} - -/*void print_buf(uint8_t *buf, int size) -{ - int i; - for(i=0;i<size;i++) - printf("%x ",buf[i]); - printf("\n"); -}*/ - -int __export ppp_chan_send(struct ppp_t *ppp, void *data, int size) -{ - int n; - - //printf("ppp_chan_send: "); - //print_buf((uint8_t*)data,size); - - n = write(ppp->chan_fd,data,size); - if (n < size) - log_ppp_error("ppp_chan_send: short write %i, excpected %i\n", n, size); - return n; -} - -int __export ppp_unit_send(struct ppp_t *ppp, void *data, int size) -{ - int n; - - //printf("ppp_unit_send: "); - //print_buf((uint8_t*)data,size); - - n=write(ppp->unit_fd, data, size); - if (n < size) - log_ppp_error("ppp_unit_send: short write %i, excpected %i\n",n,size); - return n; -} - -static int ppp_chan_read(struct triton_md_handler_t *h) -{ - struct ppp_t *ppp = container_of(h, typeof(*ppp), chan_hnd); - struct ppp_handler_t *ppp_h; - uint16_t proto; - - while(1) { -cont: - ppp->chan_buf_size = read(h->fd, ppp->chan_buf, PPP_MRU); - if (ppp->chan_buf_size < 0) { - if (errno == EAGAIN) - return 0; - log_ppp_error("ppp_chan_read: %s\n", strerror(errno)); - return 0; - } - - //printf("ppp_chan_read: "); - //print_buf(ppp->chan_buf,ppp->chan_buf_size); - if (ppp->chan_buf_size == 0) { - ppp_terminate(ppp, 1, TERM_NAS_ERROR); - return 1; - } - - if (ppp->chan_buf_size < 2) { - log_ppp_error("ppp_chan_read: short read %i\n", ppp->chan_buf_size); - continue; - } - - proto = ntohs(*(uint16_t*)ppp->chan_buf); - list_for_each_entry(ppp_h, &ppp->chan_handlers, entry) { - if (ppp_h->proto == proto) { - ppp_h->recv(ppp_h); - if (ppp->chan_fd == -1) { - ppp->ctrl->finished(ppp); - return 1; - } - goto cont; - } - } - - lcp_send_proto_rej(ppp, proto); - //log_ppp_warn("ppp_chan_read: discarding unknown packet %x\n", proto); - } -} - -static int ppp_unit_read(struct triton_md_handler_t *h) -{ - struct ppp_t *ppp = container_of(h, typeof(*ppp), unit_hnd); - struct ppp_handler_t *ppp_h; - uint16_t proto; - - while (1) { -cont: - ppp->unit_buf_size = read(h->fd, ppp->unit_buf, PPP_MRU); - if (ppp->unit_buf_size < 0) { - if (errno == EAGAIN) - return 0; - log_ppp_error("ppp_unit_read: %s\n",strerror(errno)); - return 0; - } - - md_check(ppp->unit_buf); - //printf("ppp_unit_read: "); - //print_buf(ppp->unit_buf,ppp->unit_buf_size); - - if (ppp->unit_buf_size == 0) { - ppp_terminate(ppp, 1, TERM_NAS_ERROR); - return 1; - } - - if (ppp->unit_buf_size < 2) { - log_ppp_error("ppp_unit_read: short read %i\n", ppp->unit_buf_size); - continue; - } - - proto=ntohs(*(uint16_t*)ppp->unit_buf); - list_for_each_entry(ppp_h, &ppp->unit_handlers, entry) { - if (ppp_h->proto == proto) { - ppp_h->recv(ppp_h); - if (ppp->unit_fd == -1) { - ppp->ctrl->finished(ppp); - return 1; - } - goto cont; - } - } - lcp_send_proto_rej(ppp, proto); - //log_ppp_warn("ppp_unit_read: discarding unknown packet %x\n", proto); - } -} - -void ppp_recv_proto_rej(struct ppp_t *ppp, uint16_t proto) -{ - struct ppp_handler_t *ppp_h; - - list_for_each_entry(ppp_h, &ppp->chan_handlers, entry) { - if (ppp_h->proto == proto) { - if (ppp_h->recv_proto_rej) - ppp_h->recv_proto_rej(ppp_h); - return; - } - } - - list_for_each_entry(ppp_h, &ppp->unit_handlers, entry) { - if (ppp_h->proto == proto) { - if (ppp_h->recv_proto_rej) - ppp_h->recv_proto_rej(ppp_h); - return; - } - } -} - -void __export ppp_layer_started(struct ppp_t *ppp, struct ppp_layer_data_t *d) -{ - struct layer_node_t *n = d->node; - - if (d->started) - return; - - d->started = 1; - - list_for_each_entry(d, &n->items, entry) - if (!d->started) return; - - if (n->entry.next == &ppp->layers) { - ppp->state = PPP_STATE_ACTIVE; - __sync_sub_and_fetch(&ppp_stat.starting, 1); - __sync_add_and_fetch(&ppp_stat.active, 1); - ppp->ctrl->started(ppp); - triton_event_fire(EV_PPP_STARTED, ppp); - } else { - n = list_entry(n->entry.next, typeof(*n), entry); - list_for_each_entry(d, &n->items, entry) { - d->starting = 1; - if (d->layer->start(d)) { - ppp_terminate(ppp, TERM_NAS_ERROR, 0); - return; - } - } - } -} - -void __export ppp_layer_finished(struct ppp_t *ppp, struct ppp_layer_data_t *d) -{ - struct layer_node_t *n = d->node; - - d->finished = 1; - d->starting = 0; - - list_for_each_entry(n, &ppp->layers, entry) { - list_for_each_entry(d, &n->items, entry) { - if (d->starting && !d->finished) - return; - } - } - - destablish_ppp(ppp); -} - -void __export ppp_terminate(struct ppp_t *ppp, int cause, int hard) -{ - struct layer_node_t *n; - struct ppp_layer_data_t *d; - int s = 0; - - if (ppp->terminated) - return; - - if (!ppp->stop_time) - time(&ppp->stop_time); - - if (!ppp->terminate_cause) - ppp->terminate_cause = cause; - - if (ppp->terminating) { - if (hard) - destablish_ppp(ppp); - return; - } - - ppp->terminating = 1; - if (ppp->state == PPP_STATE_ACTIVE) - __sync_sub_and_fetch(&ppp_stat.active, 1); - else - __sync_sub_and_fetch(&ppp_stat.starting, 1); - __sync_add_and_fetch(&ppp_stat.finishing, 1); - ppp->state = PPP_STATE_FINISHING; - - log_ppp_debug("ppp_terminate\n"); - - triton_event_fire(EV_PPP_FINISHING, ppp); - - if (hard) { - destablish_ppp(ppp); - return; - } - - list_for_each_entry(n,&ppp->layers,entry) { - list_for_each_entry(d,&n->items,entry) { - if (d->starting) { - s = 1; - d->layer->finish(d); - } - } - } - if (s) - return; - destablish_ppp(ppp); -} - -void __export ppp_register_chan_handler(struct ppp_t *ppp,struct ppp_handler_t *h) -{ - list_add_tail(&h->entry,&ppp->chan_handlers); -} -void __export ppp_register_unit_handler(struct ppp_t *ppp,struct ppp_handler_t *h) -{ - list_add_tail(&h->entry,&ppp->unit_handlers); -} -void __export ppp_unregister_handler(struct ppp_t *ppp,struct ppp_handler_t *h) -{ - list_del(&h->entry); -} - -static int get_layer_order(const char *name) -{ - if (!strcmp(name,"lcp")) return 0; - if (!strcmp(name,"auth")) return 1; - if (!strcmp(name,"ccp")) return 2; - if (!strcmp(name,"ipcp")) return 2; - return -1; -} - -int __export ppp_register_layer(const char *name, struct ppp_layer_t *layer) -{ - int order; - struct layer_node_t *n,*n1; - - order = get_layer_order(name); - - if (order < 0) - return order; - - list_for_each_entry(n, &layers, entry) { - if (order > n->order) - continue; - if (order < n->order) { - n1 = _malloc(sizeof(*n1)); - memset(n1, 0, sizeof(*n1)); - n1->order = order; - INIT_LIST_HEAD(&n1->items); - list_add_tail(&n1->entry, &n->entry); - n = n1; - } - goto insert; - } - n1 = _malloc(sizeof(*n1)); - memset(n1, 0, sizeof(*n1)); - n1->order = order; - INIT_LIST_HEAD(&n1->items); - list_add_tail(&n1->entry, &layers); - n = n1; -insert: - list_add_tail(&layer->entry, &n->items); - - return 0; -} -void __export ppp_unregister_layer(struct ppp_layer_t *layer) -{ - list_del(&layer->entry); -} - -static void init_layers(struct ppp_t *ppp) -{ - struct layer_node_t *n, *n1; - struct ppp_layer_t *l; - struct ppp_layer_data_t *d; - - list_for_each_entry(n,&layers,entry) { - n1 = _malloc(sizeof(*n1)); - memset(n1, 0, sizeof(*n1)); - INIT_LIST_HEAD(&n1->items); - list_add_tail(&n1->entry, &ppp->layers); - list_for_each_entry(l, &n->items, entry) { - d = l->init(ppp); - d->layer = l; - d->started = 0; - d->node = n1; - list_add_tail(&d->entry, &n1->items); - } - } -} - -static void _free_layers(struct ppp_t *ppp) -{ - struct layer_node_t *n; - struct ppp_layer_data_t *d; - - while (!list_empty(&ppp->layers)) { - n = list_entry(ppp->layers.next, typeof(*n), entry); - while (!list_empty(&n->items)) { - d = list_entry(n->items.next, typeof(*d), entry); - list_del(&d->entry); - d->layer->free(d); - } - list_del(&n->entry); - _free(n); - } -} - -static void start_first_layer(struct ppp_t *ppp) -{ - struct layer_node_t *n; - struct ppp_layer_data_t *d; - - n = list_entry(ppp->layers.next, typeof(*n), entry); - list_for_each_entry(d, &n->items, entry) { - d->starting = 1; - if (d->layer->start(d)) { - ppp_terminate(ppp, TERM_NAS_ERROR, 0); - return; - } - } -} - -struct ppp_layer_data_t *ppp_find_layer_data(struct ppp_t *ppp, struct ppp_layer_t *layer) -{ - struct layer_node_t *n; - struct ppp_layer_data_t *d; - - list_for_each_entry(n,&ppp->layers,entry) { - list_for_each_entry(d,&n->items,entry) { - if (d->layer == layer) - return d; - } - } - - return NULL; -} - -void ppp_shutdown_soft(void) -{ - ppp_shutdown = 1; - - if (!ppp_stat.starting && !ppp_stat.active && !ppp_stat.finishing) - kill(getpid(), SIGTERM); -} - -static void save_seq(void) -{ - FILE *f; - char *opt = conf_get_opt("ppp", "seq-file"); - if (!opt) - opt = "/var/run/accel-pptp/seq"; - - f = fopen(opt, "w"); - if (f) { - fprintf(f, "%llu", seq); - fclose(f); - } -} - -static void load_config(void) -{ - char *opt; - - opt = conf_get_opt("ppp", "verbose"); - if (opt && atoi(opt) > 0) - conf_ppp_verbose = 1; - - opt = conf_get_opt("ppp", "sid-case"); - if (opt) { - if (!strcmp(opt, "upper")) - conf_sid_ucase = 1; - else if (strcmp(opt, "lower")) - log_emerg("ppp: sid-case: invalid format\n"); - } -} - -static void __init init(void) -{ - char *opt; - FILE *f; - - sock_fd = socket(AF_INET, SOCK_DGRAM, 0); - if (sock_fd < 0) { - perror("socket"); - _exit(EXIT_FAILURE); - } - - opt = conf_get_opt("ppp", "seq-file"); - if (!opt) - opt = "/var/run/accel-pptp/seq"; - - f = fopen(opt, "r"); - if (f) { - fscanf(f, "%llu", &seq); - fclose(f); - } else - seq = (unsigned long long)random() * (unsigned long long)random(); - - load_config(); - triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); - - atexit(save_seq); -} - |