summaryrefslogtreecommitdiff
path: root/accel-pptpd/ppp.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pptpd/ppp.c')
-rw-r--r--accel-pptpd/ppp.c368
1 files changed, 280 insertions, 88 deletions
diff --git a/accel-pptpd/ppp.c b/accel-pptpd/ppp.c
index b032b064..58f99dc9 100644
--- a/accel-pptpd/ppp.c
+++ b/accel-pptpd/ppp.c
@@ -17,21 +17,33 @@
#include "log.h"
#include "events.h"
-static void ppp_read(struct triton_md_handler_t*);
-static void ppp_write(struct triton_md_handler_t*);
-static void ppp_timeout(struct triton_md_handler_t*);
+static LIST_HEAD(layers);
-struct ppp_t *alloc_ppp(void)
+struct layer_node_t
+{
+ struct list_head entry;
+ int order;
+ struct list_head items;
+};
+
+static void ppp_chan_read(struct triton_md_handler_t*);
+static void ppp_unit_read(struct triton_md_handler_t*);
+static void init_layers(struct ppp_t *);
+static void start_first_layer(struct ppp_t *);
+
+struct ppp_t *init_ppp(void)
{
struct ppp_t *ppp=malloc(sizeof(*ppp));
memset(ppp,0,sizeof(*ppp));
- ppp->out_buf=malloc(PPP_MTU+PPP_HDRLEN);
- ppp->in_buf=malloc(PPP_MRU+PPP_HDRLEN);
- ppp->mtu=PPP_MTU;
- ppp->mru=PPP_MRU;
return ppp;
}
+static void free_ppp(struct ppp_t *ppp)
+{
+ free(ppp->chan_buf);
+ free(ppp->unit_buf);
+}
+
int establish_ppp(struct ppp_t *ppp)
{
/* Open an instance of /dev/ppp and connect the channel to it */
@@ -65,42 +77,75 @@ int establish_ppp(struct ppp_t *ppp)
if (ioctl(ppp->unit_fd, PPPIOCNEWUNIT, &ppp->unit_idx)<0)
{
log_error("Couldn't create new ppp unit\n");
- goto exit_clodse_unit;
+ goto exit_close_unit;
}
if (ioctl(ppp->chan_fd, PPPIOCCONNECT, &ppp->unit_idx)<0)
{
log_error("Couldn't attach to PPP unit %d\n", ppp->unit_idx);
- goto exit_clodse_unit;
+ goto exit_close_unit;
}
log_info("connect: ppp%i <--> pptp(%s)\n",ppp->unit_idx,ppp->chan_name);
+
+ ppp->chan_buf=malloc(PPP_MRU);
+ ppp->unit_buf=malloc(PPP_MRU);
- ppp->h=malloc(sizeof(*ppp->h));
- memset(ppp->h,0,sizeof(*ppp->h));
- ppp->h->pd=ppp;
- ppp->h->fd=ppp->chan_fd;
- ppp->h->read=ppp_read;
- ppp->h->write=ppp_write;
- ppp->h->timeout=ppp_timeout;
- ppp->h->twait=-1;
- triton_md_register_handler(ppp->h);
- triton_md_enable_handler(ppp->h,MD_MODE_READ);
- INIT_LIST_HEAD(&ppp->handlers);
-
- ppp->cur_layer=PPP_LAYER_LCP;
+ INIT_LIST_HEAD(&ppp->chan_handlers);
+ INIT_LIST_HEAD(&ppp->unit_handlers);
- lcp_start(ppp);
+ init_layers(ppp);
+
+ if (list_empty(&ppp->layers))
+ {
+ log_error("no layers to start\n");
+ goto exit_close_unit;
+ }
+
+ ppp->chan_hnd.fd=ppp->chan_fd;
+ ppp->chan_hnd.read=ppp_chan_read;
+ ppp->chan_hnd.twait=-1;
+ ppp->unit_hnd.fd=ppp->unit_fd;
+ ppp->unit_hnd.read=ppp_unit_read;
+ ppp->unit_hnd.twait=-1;
+ triton_md_register_handler(&ppp->chan_hnd);
+ triton_md_register_handler(&ppp->unit_hnd);
+
+ triton_md_enable_handler(&ppp->chan_hnd,MD_MODE_READ);
+ triton_md_enable_handler(&ppp->unit_hnd,MD_MODE_READ);
+
+ log_debug("ppp established\n");
+
+ start_first_layer(ppp);
return 0;
-exit_clodse_unit:
+exit_close_unit:
close(ppp->unit_fd);
exit_close_chan:
close(ppp->chan_fd);
+
+ free_ppp(ppp);
+
return -1;
}
+void destablish_ppp(struct ppp_t *ppp)
+{
+ triton_md_unregister_handler(&ppp->chan_hnd);
+ triton_md_unregister_handler(&ppp->unit_hnd);
+
+ close(ppp->unit_fd);
+ close(ppp->chan_fd);
+
+ free(ppp->unit_buf);
+ free(ppp->chan_buf);
+
+ log_debug("ppp destablished\n");
+
+ if (ppp->events.finished) ppp->events.finished(ppp);
+}
+
void print_buf(uint8_t *buf,int size)
{
int i;
@@ -109,41 +154,51 @@ void print_buf(uint8_t *buf,int size)
printf("\n");
}
-int ppp_send(struct ppp_t *ppp, void *data, int size)
+int ppp_chan_send(struct ppp_t *ppp, void *data, int size)
{
int n;
- if (ppp->out_buf_size) return -1;
- if (size>PPP_MTU+PPP_HDRLEN) return -1;
+ printf("ppp_chan_send: ");
+ print_buf((uint8_t*)data,size);
+
+ n=write(ppp->chan_fd,data,size);
+ if (n<size)
+ log_error("ppp_chan_send: short write %i, excpected %i\n",n,size);
+ return n;
+}
- printf("ppp: send: ");
+int 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>=0)
- {
- if (n!=ppp->out_buf_size-ppp->out_buf_pos)
- {
- ppp->out_buf_pos+=n;
- triton_md_enable_handler(ppp->h,MD_MODE_WRITE);
- }
- }*/
+ if (n<size)
+ log_error("ppp_unit_send: short write %i, excpected %i\n",n,size);
return n;
}
-static void ppp_read(struct triton_md_handler_t*h)
+static void ppp_chan_read(struct triton_md_handler_t*h)
{
- struct ppp_t *ppp=(struct ppp_t *)h->pd;
- struct ppp_handler_t *ppp_h=NULL;
+ struct ppp_t *ppp=container_of(h,typeof(*ppp),chan_hnd);
+ struct ppp_handler_t *ppp_h;
uint16_t proto;
- ppp->in_buf_size=read(h->fd,ppp->in_buf,PPP_MRU+PPP_HDRLEN);
+ ppp->chan_buf_size=read(h->fd,ppp->chan_buf,PPP_MRU);
+
+ printf("ppp_chan_read: ");
+ print_buf(ppp->chan_buf,ppp->chan_buf_size);
- printf("ppp: recv: ");
- print_buf(ppp->in_buf,ppp->in_buf_size);
+ if (ppp->chan_buf_size<2)
+ {
+ log_error("ppp_chan_read: short read %i\n",ppp->chan_buf_size);
+ return;
+ }
- proto=ntohs(*(uint16_t*)ppp->in_buf);
- list_for_each_entry(ppp_h,&ppp->handlers,entry)
+ proto=ntohs(*(uint16_t*)ppp->chan_buf);
+ list_for_each_entry(ppp_h,&ppp->chan_handlers,entry)
{
if (ppp_h->proto==proto)
{
@@ -152,75 +207,212 @@ static void ppp_read(struct triton_md_handler_t*h)
}
}
- log_warn("discarding unknown packet %x\n",proto);
+ log_warn("ppp_chan_read: discarding unknown packet %x\n",proto);
}
-static void ppp_write(struct triton_md_handler_t*h)
+
+static void ppp_unit_read(struct triton_md_handler_t*h)
{
- struct ppp_t *ppp=(struct ppp_t *)h->pd;
+ struct ppp_t *ppp=container_of(h,typeof(*ppp),unit_hnd);
+ struct ppp_handler_t *ppp_h;
+ uint16_t proto;
- int n=write(ppp->unit_fd,ppp->out_buf+ppp->out_buf_pos,ppp->out_buf_size-ppp->out_buf_pos);
- if (n>=0)
+ ppp->unit_buf_size=read(h->fd,ppp->unit_buf,PPP_MRU);
+
+ printf("ppp_unit_read: ");
+ print_buf(ppp->unit_buf,ppp->unit_buf_size);
+
+ if (ppp->unit_buf_size<2)
{
- ppp->out_buf_pos+=n;
- if (ppp->out_buf_pos==ppp->out_buf_size)
+ log_error("ppp_chan_read: short read %i\n",ppp->unit_buf_size);
+ return;
+ }
+
+ proto=ntohs(*(uint16_t*)ppp->unit_buf);
+ list_for_each_entry(ppp_h,&ppp->unit_handlers,entry)
+ {
+ if (ppp_h->proto==proto)
{
- triton_md_disable_handler(ppp->h,MD_MODE_WRITE);
- ppp->out_buf_pos=0;
- ppp->out_buf_size=0;
+ ppp_h->recv(ppp_h);
+ return;
}
}
+
+ log_warn("ppp_chan_read: discarding unknown packet %x\n",proto);
}
-static void ppp_timeout(struct triton_md_handler_t*h)
+
+void ppp_layer_started(struct ppp_t *ppp, struct ppp_layer_data_t *d)
{
+ struct layer_node_t *n=d->node;
+
+ d->started=1;
+
+ list_for_each_entry(d,&n->items,entry)
+ if (!d->started) return;
+ if (n->entry.next==&ppp->layers)
+ {
+ if (ppp->events.started) ppp->events.started(ppp);
+ }else
+ {
+ n=list_entry(n->entry.next,typeof(*n),entry);
+ list_for_each_entry(d,&n->items,entry)
+ d->layer->start(d);
+ }
}
-void ppp_layer_started(struct ppp_t *ppp)
+void ppp_layer_finished(struct ppp_t *ppp, struct ppp_layer_data_t *d)
{
- switch(ppp->cur_layer)
+ struct layer_node_t *n=d->node;
+
+ d->started=0;
+
+ list_for_each_entry(d,&n->items,entry)
+ if (d->started) return;
+
+ if (n->entry.prev==&ppp->layers) destablish_ppp(ppp);
+ else
{
- case PPP_LAYER_LCP:
- ppp->cur_layer++;
- if (auth_start(ppp))
- break;
- case PPP_LAYER_AUTH:
- ppp->cur_layer++;
- if (ccp_start(ppp))
- break;
- case PPP_LAYER_CCP:
- ppp->cur_layer++;
- if (ipcp_start(ppp))
- break;
- case PPP_LAYER_IPCP:
- break;
+ n=list_entry(n->entry.prev,typeof(*n),entry);
+ list_for_each_entry(d,&n->items,entry)
+ if (d->started) d->layer->finish(d);
}
}
+
void ppp_terminate(struct ppp_t *ppp)
{
- switch(ppp->cur_layer)
+ struct layer_node_t *n;
+ struct list_head *p;
+ struct ppp_layer_data_t *d;
+ int s=0;
+
+ log_debug("ppp_terminate\n");
+
+ list_for_each_prev(p,&ppp->layers)
{
- case PPP_LAYER_IPCP:
- ppp->cur_layer--;
- ipcp_finish(ppp);
- case PPP_LAYER_CCP:
- ppp->cur_layer--;
- ccp_finish(ppp);
- case PPP_LAYER_AUTH:
- ppp->cur_layer--;
- auth_finish(ppp);
- case PPP_LAYER_LCP:
- ppp->cur_layer--;
- lcp_finish(ppp);
+ list_for_each_entry(d,&n->items,entry)
+ {
+ if (d->started)
+ {
+ s=1;
+ d->layer->finish(d);
+ }
+ }
+ if (s) return;
}
+ destablish_ppp(ppp);
}
-
-void ppp_register_handler(struct ppp_t *ppp,struct ppp_handler_t *h)
+void ppp_register_chan_handler(struct ppp_t *ppp,struct ppp_handler_t *h)
+{
+ list_add_tail(&h->entry,&ppp->chan_handlers);
+}
+void ppp_register_unit_handler(struct ppp_t *ppp,struct ppp_handler_t *h)
{
- list_add_tail(&h->entry,&ppp->handlers);
+ list_add_tail(&h->entry,&ppp->unit_handlers);
}
void 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,"ipcp")) return 2;
+ if (!strcmp(name,"ccp")) return 2;
+ return -1;
+}
+
+int 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 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;
+
+ INIT_LIST_HEAD(&ppp->layers);
+
+ list_for_each_entry(n,&layers,entry)
+ {
+ n1=(struct layer_node_t*)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 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->layer->start(d);
+}
+
+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;
+}