summaryrefslogtreecommitdiff
path: root/accel-pptpd/pptp.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pptpd/pptp.c')
-rw-r--r--accel-pptpd/pptp.c322
1 files changed, 164 insertions, 158 deletions
diff --git a/accel-pptpd/pptp.c b/accel-pptpd/pptp.c
index f932e0b..a8aef87 100644
--- a/accel-pptpd/pptp.c
+++ b/accel-pptpd/pptp.c
@@ -5,6 +5,7 @@
#include <errno.h>
#include <string.h>
#include <fcntl.h>
+#include <time.h>
#include <arpa/inet.h>
#include <netinet/in.h>
@@ -23,7 +24,8 @@
#define STATE_IDLE 0
#define STATE_ESTB 1
#define STATE_PPP 2
-#define STATE_FIN 10
+#define STATE_FIN 3
+#define STATE_CLOSE 4
struct pptp_conn_t
{
@@ -53,220 +55,226 @@ static void disconnect(struct pptp_conn_t *conn)
{
triton_md_unregister_handler(&conn->hnd);
close(conn->hnd.fd);
- conn->hnd.fd=-1;
+
+ if (conn->state == STATE_PPP) {
+ conn->state = STATE_CLOSE;
+ ppp_terminate(&conn->ppp, 1);
+ }
+
triton_unregister_ctx(&conn->ctx);
+
+ free(conn->in_buf);
+ free(conn->out_buf);
+ free(conn);
}
-static int post_msg(struct pptp_conn_t *conn,void *buf,int size)
+static int post_msg(struct pptp_conn_t *conn, void *buf, int size)
{
int n;
- if (conn->out_size)
- {
+ if (conn->out_size) {
log_debug("post_msg: buffer is not empty\n");
return -1;
}
- n=write(conn->hnd.fd,buf,size);
- if (n<0)
- {
- if (errno==EINTR) n=0;
- else
- {
- log_debug("post_msg: failed to write socket %i\n",errno);
+ n=write(conn->hnd.fd, buf, size);
+ if (n < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ n = 0;
+ else {
+ if (errno != EPIPE)
+ log_debug("post_msg: failed to write socket %i\n",errno);
return -1;
}
}
- if (n<size)
- {
- memcpy(conn->out_buf,buf+n,size-n);
- triton_md_enable_handler(&conn->hnd,MD_MODE_WRITE);
+ if ( n<size ) {
+ memcpy(conn->out_buf, buf + n, size - n);
+ triton_md_enable_handler(&conn->hnd, MD_MODE_WRITE);
}
return 0;
}
-static int send_pptp_stop_ctrl_conn_rqst(struct pptp_conn_t *conn,int reason,int err_code)
+static int send_pptp_stop_ctrl_conn_rqst(struct pptp_conn_t *conn, int reason, int err_code)
{
- struct pptp_stop_ctrl_conn msg={
- .header=PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RQST),
- .reason_result=hton8(reason),
- .error_code=hton8(err_code),
+ struct pptp_stop_ctrl_conn msg = {
+ .header = PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RQST),
+ .reason_result = hton8(reason),
+ .error_code = hton8(err_code),
};
- return post_msg(conn,&msg,sizeof(msg));
+ return post_msg(conn, &msg, sizeof(msg));
}
-static int send_pptp_stop_ctrl_conn_rply(struct pptp_conn_t *conn,int reason,int err_code)
+static int send_pptp_stop_ctrl_conn_rply(struct pptp_conn_t *conn, int reason, int err_code)
{
- struct pptp_stop_ctrl_conn msg={
- .header=PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RPLY),
- .reason_result=hton8(reason),
- .error_code=hton8(err_code),
+ struct pptp_stop_ctrl_conn msg = {
+ .header = PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RPLY),
+ .reason_result = hton8(reason),
+ .error_code = hton8(err_code),
};
- return post_msg(conn,&msg,sizeof(msg));
+ return post_msg(conn, &msg, sizeof(msg));
}
static int pptp_stop_ctrl_conn_rqst(struct pptp_conn_t *conn)
{
- struct pptp_stop_ctrl_conn *msg=(struct pptp_stop_ctrl_conn *)conn->in_buf;
- log_info("PPTP_STOP_CTRL_CONN_RQST reason=%i error_code=%i\n",msg->reason_result,msg->error_code);
+ struct pptp_stop_ctrl_conn *msg = (struct pptp_stop_ctrl_conn *)conn->in_buf;
+ log_info("PPTP_STOP_CTRL_CONN_RQST reason=%i error_code=%i\n",msg->reason_result, msg->error_code);
- if (conn->state==STATE_PPP)
- ppp_terminate(&conn->ppp);
+ if (conn->state == STATE_PPP) {
+ conn->state = STATE_FIN;
+ ppp_terminate(&conn->ppp, 0);
+ }
- conn->state=STATE_FIN;
//conn->hnd.twait=1000;
- return send_pptp_stop_ctrl_conn_rply(conn,PPTP_CONN_STOP_OK,0);
+ send_pptp_stop_ctrl_conn_rply(conn, PPTP_CONN_STOP_OK, 0);
+ return -1;
}
-static int send_pptp_start_ctrl_conn_rply(struct pptp_conn_t *conn,int res_code,int err_code)
+static int send_pptp_start_ctrl_conn_rply(struct pptp_conn_t *conn, int res_code, int err_code)
{
- struct pptp_start_ctrl_conn msg={
- .header=PPTP_HEADER_CTRL(PPTP_START_CTRL_CONN_RPLY),
- .version=htons(PPTP_VERSION),
- .result_code=res_code,
- .error_code=err_code,
- .framing_cap=htonl(PPTP_FRAME_SYNC),
- .bearer_cap=htonl(0),
- .max_channels=htons(1),
- .firmware_rev=htons(PPTP_FIRMWARE_VERSION),
+ struct pptp_start_ctrl_conn msg = {
+ .header = PPTP_HEADER_CTRL(PPTP_START_CTRL_CONN_RPLY),
+ .version = htons(PPTP_VERSION),
+ .result_code = res_code,
+ .error_code = err_code,
+ .framing_cap = htonl(PPTP_FRAME_SYNC),
+ .bearer_cap = htonl(0),
+ .max_channels = htons(1),
+ .firmware_rev = htons(PPTP_FIRMWARE_VERSION),
};
- memset(msg.hostname,0,sizeof(msg.hostname));
- strcpy((char*)msg.hostname,PPTP_HOSTNAME);
+ memset(msg.hostname, 0, sizeof(msg.hostname));
+ strcpy((char*)msg.hostname, PPTP_HOSTNAME);
- memset(msg.vendor,0,sizeof(msg.vendor));
- strcpy((char*)msg.vendor,PPTP_VENDOR);
+ memset(msg.vendor, 0, sizeof(msg.vendor));
+ strcpy((char*)msg.vendor, PPTP_VENDOR);
- return post_msg(conn,&msg,sizeof(msg));
+ return post_msg(conn, &msg, sizeof(msg));
}
static int pptp_start_ctrl_conn_rqst(struct pptp_conn_t *conn)
{
- struct pptp_start_ctrl_conn *msg=(struct pptp_start_ctrl_conn *)conn->in_buf;
+ struct pptp_start_ctrl_conn *msg = (struct pptp_start_ctrl_conn *)conn->in_buf;
- if (conn->state!=STATE_IDLE)
- {
+ if (conn->state != STATE_IDLE) {
log_info("unexpected PPTP_START_CTRL_CONN_RQST\n");
- if (send_pptp_start_ctrl_conn_rply(conn,PPTP_CONN_RES_EXISTS,0))
+ if (send_pptp_start_ctrl_conn_rply(conn, PPTP_CONN_RES_EXISTS, 0))
return -1;
return 0;
}
- if (msg->version!=htons(PPTP_VERSION))
- {
- log_info("PPTP version mismatch: expecting %x, received %s\n",PPTP_VERSION,msg->version);
- if (send_pptp_start_ctrl_conn_rply(conn,PPTP_CONN_RES_PROTOCOL,0))
+ if (msg->version != htons(PPTP_VERSION)) {
+ log_info("PPTP version mismatch: expecting %x, received %s\n", PPTP_VERSION, msg->version);
+ if (send_pptp_start_ctrl_conn_rply(conn, PPTP_CONN_RES_PROTOCOL, 0))
return -1;
return 0;
}
- if (!(ntohl(msg->framing_cap)&PPTP_FRAME_SYNC))
- {
+ if (!(ntohl(msg->framing_cap) & PPTP_FRAME_SYNC)) {
log_info("connection does not supports sync mode\n");
- if (send_pptp_start_ctrl_conn_rply(conn,PPTP_CONN_RES_GE,0))
+ if (send_pptp_start_ctrl_conn_rply(conn, PPTP_CONN_RES_GE, 0))
return -1;
return 0;
}
- if (send_pptp_start_ctrl_conn_rply(conn,PPTP_CONN_RES_SUCCESS,0))
+ if (send_pptp_start_ctrl_conn_rply(conn, PPTP_CONN_RES_SUCCESS, 0))
return -1;
- conn->state=STATE_ESTB;
+ conn->state = STATE_ESTB;
return 0;
}
-static int send_pptp_out_call_rply(struct pptp_conn_t *conn,struct pptp_out_call_rqst *rqst,int call_id,int res_code,int err_code)
+static int send_pptp_out_call_rply(struct pptp_conn_t *conn, struct pptp_out_call_rqst *rqst, int call_id, int res_code, int err_code)
{
- struct pptp_out_call_rply msg={
- .header=PPTP_HEADER_CTRL(PPTP_OUT_CALL_RPLY),
- .call_id=htons(call_id),
- .call_id_peer=rqst->call_id,
- .result_code=res_code,
- .error_code=err_code,
- .cause_code=0,
- .speed=rqst->bps_max,
- .recv_size=rqst->recv_size,
- .delay=0,
- .channel=0,
+ struct pptp_out_call_rply msg = {
+ .header = PPTP_HEADER_CTRL(PPTP_OUT_CALL_RPLY),
+ .call_id = htons(call_id),
+ .call_id_peer = rqst->call_id,
+ .result_code = res_code,
+ .error_code = err_code,
+ .cause_code = 0,
+ .speed = rqst->bps_max,
+ .recv_size = rqst->recv_size,
+ .delay = 0,
+ .channel = 0,
};
- return post_msg(conn,&msg,sizeof(msg));
+ return post_msg(conn, &msg, sizeof(msg));
}
static int pptp_out_call_rqst(struct pptp_conn_t *conn)
{
- struct pptp_out_call_rqst *msg=(struct pptp_out_call_rqst *)conn->in_buf;
- struct sockaddr_pppox src_addr,dst_addr;
+ struct pptp_out_call_rqst *msg = (struct pptp_out_call_rqst *)conn->in_buf;
+ struct sockaddr_pppox src_addr, dst_addr;
struct sockaddr_in addr;
socklen_t addrlen;
int pptp_sock;
- if (conn->state!=STATE_ESTB)
- {
+ if (conn->state != STATE_ESTB) {
log_info("unexpected PPTP_OUT_CALL_RQST\n");
- if (send_pptp_out_call_rply(conn,msg,0,PPTP_CALL_RES_GE,PPTP_GE_NOCONN))
+ if (send_pptp_out_call_rply(conn, msg, 0, PPTP_CALL_RES_GE, PPTP_GE_NOCONN))
return -1;
return 0;
}
- src_addr.sa_family=AF_PPPOX;
- src_addr.sa_protocol=PX_PROTO_PPTP;
- src_addr.sa_addr.pptp.call_id=0;
- addrlen=sizeof(addr); getsockname(conn->hnd.fd,(struct sockaddr*)&addr,&addrlen);
- src_addr.sa_addr.pptp.sin_addr=addr.sin_addr;
-
- dst_addr.sa_family=AF_PPPOX;
- dst_addr.sa_protocol=PX_PROTO_PPTP;
- dst_addr.sa_addr.pptp.call_id=htons(msg->call_id);
- addrlen=sizeof(addr); getpeername(conn->hnd.fd,(struct sockaddr*)&addr,&addrlen);
- dst_addr.sa_addr.pptp.sin_addr=addr.sin_addr;
-
- pptp_sock=socket(AF_PPPOX,SOCK_STREAM,PX_PROTO_PPTP);
- if (pptp_sock<0)
- {
- log_error("failed to create PPTP socket (%s)\n",strerror(errno));
+ src_addr.sa_family = AF_PPPOX;
+ src_addr.sa_protocol = PX_PROTO_PPTP;
+ src_addr.sa_addr.pptp.call_id = 0;
+ addrlen = sizeof(addr);
+ getsockname(conn->hnd.fd, (struct sockaddr*)&addr, &addrlen);
+ src_addr.sa_addr.pptp.sin_addr = addr.sin_addr;
+
+ dst_addr.sa_family = AF_PPPOX;
+ dst_addr.sa_protocol = PX_PROTO_PPTP;
+ dst_addr.sa_addr.pptp.call_id = htons(msg->call_id);
+ addrlen = sizeof(addr);
+ getpeername(conn->hnd.fd, (struct sockaddr*)&addr, &addrlen);
+ dst_addr.sa_addr.pptp.sin_addr = addr.sin_addr;
+
+ pptp_sock = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_PPTP);
+ if (pptp_sock < 0) {
+ log_error("failed to create PPTP socket (%s)\n", strerror(errno));
return -1;
}
- if (bind(pptp_sock,(struct sockaddr*)&src_addr,sizeof(src_addr)))
- {
- log_error("failed to bind PPTP socket (%s)\n",strerror(errno));
+ if (bind(pptp_sock, (struct sockaddr*)&src_addr, sizeof(src_addr))) {
+ log_error("failed to bind PPTP socket (%s)\n", strerror(errno));
close(pptp_sock);
return -1;
}
- addrlen=sizeof(src_addr);
- getsockname(pptp_sock,(struct sockaddr*)&src_addr,&addrlen);
+ addrlen = sizeof(src_addr);
+ getsockname(pptp_sock, (struct sockaddr*)&src_addr, &addrlen);
- if (connect(pptp_sock,(struct sockaddr*)&dst_addr,sizeof(dst_addr)))
- {
- log_error("failed to connect PPTP socket (%s)\n",strerror(errno));
+ if (connect(pptp_sock, (struct sockaddr*)&dst_addr, sizeof(dst_addr))) {
+ log_error("failed to connect PPTP socket (%s)\n", strerror(errno));
close(pptp_sock);
return -1;
}
- if (send_pptp_out_call_rply(conn,msg,src_addr.sa_addr.pptp.call_id,PPTP_CALL_RES_OK,0))
+ if (send_pptp_out_call_rply(conn, msg, src_addr.sa_addr.pptp.call_id, PPTP_CALL_RES_OK, 0))
return -1;
- conn->ppp.fd=pptp_sock;
- conn->ppp.chan_name=strdup(inet_ntoa(dst_addr.sa_addr.pptp.sin_addr));
- conn->ppp.ctrl=&conn->ctrl;
- conn->ctrl.ctx=&conn->ctx;
- conn->ctrl.started=ppp_started;
- conn->ctrl.finished=ppp_finished;
- if (establish_ppp(&conn->ppp))
- {
+ conn->ppp.fd = pptp_sock;
+ conn->ppp.chan_name = strdup(inet_ntoa(dst_addr.sa_addr.pptp.sin_addr));
+ conn->ppp.ctrl = &conn->ctrl;
+ conn->ctrl.ctx = &conn->ctx;
+ conn->ctrl.started = ppp_started;
+ conn->ctrl.finished = ppp_finished;
+ if (establish_ppp(&conn->ppp)) {
close(pptp_sock);
- send_pptp_stop_ctrl_conn_rqst(conn,0,0);
- conn->state=STATE_FIN;
+ //if (send_pptp_stop_ctrl_conn_rqst(conn, 0, 0))
+ // return -1;
+ conn->state = STATE_FIN;
//conn->hnd.twait=1000;
- }else conn->state=STATE_PPP;
+ return -1;
+ } else
+ conn->state = STATE_PPP;
return 0;
}
static int process_packet(struct pptp_conn_t *conn)
{
- struct pptp_header *hdr=(struct pptp_header *)conn->in_buf;
+ struct pptp_header *hdr = (struct pptp_header *)conn->in_buf;
switch(ntohs(hdr->ctrl_type))
{
case PPTP_START_CTRL_CONN_RQST:
@@ -287,8 +295,7 @@ static int pptp_read(struct triton_md_handler_t *h)
while(1) {
n = read(h->fd,conn->in_buf,PPTP_CTRL_SIZE_MAX-conn->in_size);
- if (n <= 0)
- {
+ if (n < 0) {
if (errno == EINTR)
continue;
if (errno == EAGAIN)
@@ -296,6 +303,8 @@ static int pptp_read(struct triton_md_handler_t *h)
log_error("pptp: read: %s\n",strerror(errno));
goto drop;
}
+ if (n == 0)
+ goto drop;
conn->in_size += n;
if (conn->in_size >= sizeof(*hdr)) {
if (hdr->magic != htonl(PPTP_MAGIC))
@@ -319,61 +328,61 @@ drop:
}
static int pptp_write(struct triton_md_handler_t *h)
{
- struct pptp_conn_t *conn=container_of(h,typeof(*conn),hnd);
- int n=write(h->fd,conn->out_buf+conn->out_pos,conn->out_size-conn->out_pos);
+ struct pptp_conn_t *conn = container_of(h, typeof(*conn), hnd);
+ int n;
- if (n<0)
- {
- if (errno==EAGAIN) n=0;
- else
- {
- log_debug("post_msg: failed to write socket %i\n",errno);
- disconnect(conn);
- return 1;
+ while (1) {
+ n = write(h->fd, conn->out_buf+conn->out_pos, conn->out_size-conn->out_pos);
+
+ if (n < 0) {
+ if (errno == EINTR)
+ continue;
+ if (errno == EAGAIN)
+ n = 0;
+ else {
+ if (errno != EPIPE)
+ log_error("pptp:post_msg: %s\n", strerror(errno));
+ disconnect(conn);
+ return 1;
+ }
}
- }
- conn->out_pos+=n;
- if (conn->out_pos==conn->out_size)
- {
- conn->out_pos=0;
- conn->out_size=0;
- triton_md_disable_handler(h,MD_MODE_WRITE);
+ conn->out_pos += n;
+ if (conn->out_pos == conn->out_size) {
+ conn->out_pos = 0;
+ conn->out_size = 0;
+ triton_md_disable_handler(h, MD_MODE_WRITE);
+ return 0;
+ }
}
- return 0;
- //h->twait=TIMEOUT;
}
static void pptp_timeout(struct triton_md_handler_t *h)
{
}
static void pptp_close(struct triton_ctx_t *ctx)
{
- struct pptp_conn_t *conn=container_of(ctx,typeof(*conn),ctx);
- if (conn->state==STATE_PPP)
- ppp_terminate(&conn->ppp);
- else
+ struct pptp_conn_t *conn = container_of(ctx, typeof(*conn), ctx);
+ if (conn->state == STATE_PPP) {
+ conn->state = STATE_FIN;
+ ppp_terminate(&conn->ppp, 0);
+ } else
disconnect(conn);
}
-static void pptp_free(struct triton_ctx_t *ctx)
-{
- struct pptp_conn_t *conn=container_of(ctx,typeof(*conn),ctx);
- free(conn->in_buf);
- free(conn->out_buf);
- free(conn);
-}
static void ppp_started(struct ppp_t *ppp)
{
log_msg("ppp_started\n");
}
static void ppp_finished(struct ppp_t *ppp)
{
- struct pptp_conn_t *conn=container_of(ppp,typeof(*conn),ppp);
+ struct pptp_conn_t *conn = container_of(ppp, typeof(*conn), ppp);
log_msg("ppp_finished\n");
close(conn->ppp.fd);
- send_pptp_stop_ctrl_conn_rqst(conn,0,0);
- conn->state=STATE_FIN;
- //conn->hnd.twait=1000;
+ //send_pptp_stop_ctrl_conn_rqst(conn, 0, 0);
+ if (conn->state != STATE_CLOSE) {
+ conn->state = STATE_CLOSE;
+ disconnect(conn);
+ }
}
//==================================
@@ -414,13 +423,11 @@ static int pptp_connect(struct triton_md_handler_t *h)
conn->hnd.read = pptp_read;
conn->hnd.write = pptp_write;
conn->ctx.close = pptp_close;
- conn->ctx.free = pptp_free;
- conn->hnd.ctx = &conn->ctx;
conn->in_buf = malloc(PPTP_CTRL_SIZE_MAX);
conn->out_buf = malloc(PPTP_CTRL_SIZE_MAX);
triton_register_ctx(&conn->ctx);
- triton_md_register_handler(&conn->hnd);
+ triton_md_register_handler(&conn->ctx, &conn->hnd);
triton_md_enable_handler(&conn->hnd,MD_MODE_READ);
}
return 0;
@@ -436,7 +443,6 @@ static struct pptp_serv_t serv=
{
.hnd.read=pptp_connect,
.ctx.close=pptp_serv_close,
- .hnd.ctx=&serv.ctx,
};
void __init pptp_init(void)
@@ -471,7 +477,7 @@ void __init pptp_init(void)
}
triton_register_ctx(&serv.ctx);
- triton_md_register_handler(&serv.hnd);
+ triton_md_register_handler(&serv.ctx, &serv.hnd);
triton_md_enable_handler(&serv.hnd, MD_MODE_READ);
}