summaryrefslogtreecommitdiff
path: root/accel-pptpd/ppp/ppp.c
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2011-01-05 15:18:59 +0300
committerDmitry Kozlov <xeb@mail.ru>2011-01-05 15:18:59 +0300
commitf28cb1b0a926f1ea98700b7871537ad1793511fd (patch)
treebaf35570bc6b38b6fab5b6524e8f19f58f71e57f /accel-pptpd/ppp/ppp.c
parent2fdf3586c13a72c36f9530084962e29d57dc0329 (diff)
downloadaccel-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.c681
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);
-}
-