diff options
Diffstat (limited to 'accel-pppd/ctrl/pptp')
| -rw-r--r-- | accel-pppd/ctrl/pptp/pptp.c | 168 | ||||
| -rw-r--r-- | accel-pppd/ctrl/pptp/pptp.h | 7 | ||||
| -rw-r--r-- | accel-pppd/ctrl/pptp/pptp_prot.h | 1 |
3 files changed, 124 insertions, 52 deletions
diff --git a/accel-pppd/ctrl/pptp/pptp.c b/accel-pppd/ctrl/pptp/pptp.c index a95fe8ae..dac7c041 100644 --- a/accel-pppd/ctrl/pptp/pptp.c +++ b/accel-pppd/ctrl/pptp/pptp.c @@ -11,7 +11,7 @@ #include <netinet/in.h> #include <sys/socket.h> -#include "if_pppox.h" +#include <linux/if_pppox.h> #include "events.h" #include "list.h" @@ -25,6 +25,7 @@ #include "cli.h" #include "connlimit.h" +#include "pptp.h" #include "memdebug.h" @@ -55,6 +56,19 @@ struct pptp_conn_t struct ppp_t ppp; }; +struct pptp_stat_t +{ + unsigned int starting; + unsigned int active; +}; + +struct pptp_serv_t +{ + struct triton_context_t ctx; + struct triton_md_handler_t hnd; + struct pptp_stat_t stat; +}; + static int conf_ppp_max_mtu = PPTP_MAX_MTU; static int conf_timeout = 5; static int conf_echo_interval = 0; @@ -69,14 +83,53 @@ static const char *conf_ifname; static mempool_t conn_pool; -static unsigned int stat_starting; -static unsigned int stat_active; - static int pptp_read(struct triton_md_handler_t *h); static int pptp_write(struct triton_md_handler_t *h); static void pptp_timeout(struct triton_timer_t *); static void ppp_started(struct ap_session *); static void ppp_finished(struct ap_session *); +static void pptp_ctx_switch(struct triton_context_t *ctx, void *arg); +static int pptp_connect(struct triton_md_handler_t *h); +static void pptp_serv_close(struct triton_context_t *ctx); + +static struct pptp_serv_t serv = +{ + .hnd.read = pptp_connect, + .ctx.close = pptp_serv_close, + .ctx.before_switch = pptp_ctx_switch, +}; + +static void pptp_stat_inc(unsigned int *stat) +{ + __atomic_add_fetch(stat, 1, __ATOMIC_RELAXED); +} + +static void pptp_stat_dec(unsigned int *stat) +{ + __atomic_sub_fetch(stat, 1, __ATOMIC_RELAXED); +} + +static void pptp_stat_move(unsigned int *from, unsigned int *to) +{ + pptp_stat_dec(from); + pptp_stat_inc(to); +} + +static void pptp_stat_get(struct pptp_stat_t *stat) +{ + stat->starting = __atomic_load_n(&serv.stat.starting, __ATOMIC_RELAXED); + stat->active = __atomic_load_n(&serv.stat.active, __ATOMIC_RELAXED); +} + +unsigned int __export pptp_stat_starting(void) +{ + return __atomic_load_n(&serv.stat.starting, __ATOMIC_RELAXED); +} + +unsigned int __export pptp_stat_active(void) +{ + return __atomic_load_n(&serv.stat.active, __ATOMIC_RELAXED); +} static void pptp_ctx_switch(struct triton_context_t *ctx, void *arg) { @@ -101,11 +154,11 @@ static void disconnect(struct pptp_conn_t *conn) triton_timer_del(&conn->echo_timer); if (conn->state == STATE_PPP) { - __sync_sub_and_fetch(&stat_active, 1); + pptp_stat_dec(&serv.stat.active); conn->state = STATE_CLOSE; ap_session_terminate(&conn->ppp.ses, TERM_LOST_CARRIER, 1); } else if (conn->state != STATE_CLOSE) - __sync_sub_and_fetch(&stat_starting, 1); + pptp_stat_dec(&serv.stat.starting); triton_event_fire(EV_CTRL_FINISHED, &conn->ppp.ses); @@ -142,13 +195,14 @@ again: if (errno != EPIPE) { if (conf_verbose) log_ppp_info2("pptp: write: %s\n", strerror(errno)); - return -1; } + return -1; } } if ( n<size ) { memcpy(conn->out_buf, (uint8_t *)buf + n, size - n); + conn->out_size = size - n; triton_md_enable_handler(&conn->hnd, MD_MODE_WRITE); } @@ -306,7 +360,10 @@ static int pptp_out_call_rqst(struct pptp_conn_t *conn) 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); + if (getsockname(conn->hnd.fd, (struct sockaddr*)&addr, &addrlen)) { + log_ppp_error("pptp: getsockname: %s\n", strerror(errno)); + return -1; + } src_addr.sa_addr.pptp.sin_addr = addr.sin_addr; memset(&dst_addr, 0, sizeof(dst_addr)); @@ -314,7 +371,10 @@ static int pptp_out_call_rqst(struct pptp_conn_t *conn) 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); + if (getpeername(conn->hnd.fd, (struct sockaddr*)&addr, &addrlen)) { + log_ppp_error("pptp: getpeername: %s\n", strerror(errno)); + return -1; + } dst_addr.sa_addr.pptp.sin_addr = addr.sin_addr; pptp_sock = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_PPTP); @@ -331,7 +391,11 @@ static int pptp_out_call_rqst(struct pptp_conn_t *conn) return -1; } addrlen = sizeof(src_addr); - getsockname(pptp_sock, (struct sockaddr*)&src_addr, &addrlen); + if (getsockname(pptp_sock, (struct sockaddr*)&src_addr, &addrlen)) { + log_ppp_error("pptp: getsockname: %s\n", strerror(errno)); + close(pptp_sock); + return -1; + } if (connect(pptp_sock, (struct sockaddr*)&dst_addr, sizeof(dst_addr))) { log_ppp_error("failed to connect PPTP socket (%s)\n", strerror(errno)); @@ -339,11 +403,13 @@ static int pptp_out_call_rqst(struct pptp_conn_t *conn) 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)) { + close(pptp_sock); return -1; + } conn->call_id = src_addr.sa_addr.pptp.call_id; - conn->peer_call_id = msg->call_id; + conn->peer_call_id = ntohs(msg->call_id); conn->ppp.fd = pptp_sock; conn->ppp.ses.chan_name = _strdup(inet_ntoa(dst_addr.sa_addr.pptp.sin_addr)); @@ -356,8 +422,7 @@ static int pptp_out_call_rqst(struct pptp_conn_t *conn) return -1; } conn->state = STATE_PPP; - __sync_sub_and_fetch(&stat_starting, 1); - __sync_add_and_fetch(&stat_active, 1); + pptp_stat_move(&serv.stat.starting, &serv.stat.active); if (conn->timeout_timer.tpd) triton_timer_del(&conn->timeout_timer); @@ -397,7 +462,7 @@ static int pptp_call_clear_rqst(struct pptp_conn_t *conn) triton_timer_del(&conn->echo_timer); if (conn->state == STATE_PPP) { - __sync_sub_and_fetch(&stat_active, 1); + pptp_stat_dec(&serv.stat.active); conn->state = STATE_CLOSE; ap_session_terminate(&conn->ppp.ses, TERM_USER_REQUEST, 1); } @@ -443,7 +508,7 @@ static void pptp_send_echo(struct triton_timer_t *t) .header = PPTP_HEADER_CTRL(PPTP_ECHO_RQST), }; - if (++conn->echo_sent == conf_echo_failure) { + if (conf_echo_failure && ++conn->echo_sent >= conf_echo_failure) { log_ppp_warn("pptp: no echo reply\n"); disconnect(conn); return; @@ -514,6 +579,10 @@ static int pptp_read(struct triton_md_handler_t *h) log_ppp_error("pptp: invalid magic\n"); goto drop; } + if (ntohs(hdr->length) < sizeof(*hdr)) { + log_ppp_error("pptp: message is too short\n"); + goto drop; + } if (ntohs(hdr->length) >= PPTP_CTRL_SIZE_MAX) { log_ppp_error("pptp: message is too long\n"); goto drop; @@ -578,7 +647,7 @@ static void pptp_close(struct triton_context_t *ctx) { struct pptp_conn_t *conn = container_of(ctx, typeof(*conn), ctx); if (conn->state == STATE_PPP) { - __sync_sub_and_fetch(&stat_active, 1); + pptp_stat_dec(&serv.stat.active); conn->state = STATE_CLOSE; ap_session_terminate(&conn->ppp.ses, TERM_ADMIN_RESET, 1); if (send_pptp_call_disconnect_notify(conn, 3)) { @@ -609,7 +678,7 @@ static void ppp_finished(struct ap_session *ses) if (conn->state != STATE_CLOSE) { log_ppp_debug("pptp: ppp finished\n"); conn->state = STATE_CLOSE; - __sync_sub_and_fetch(&stat_active, 1); + pptp_stat_dec(&serv.stat.active); if (send_pptp_call_disconnect_notify(conn, 3)) triton_context_call(&conn->ctx, (void (*)(void*))disconnect, conn); @@ -626,20 +695,15 @@ static void ppp_finished(struct ap_session *ses) //================================== -struct pptp_serv_t -{ - struct triton_context_t ctx; - struct triton_md_handler_t hnd; -}; - static int pptp_connect(struct triton_md_handler_t *h) { - struct sockaddr_in addr; - socklen_t size = sizeof(addr); + struct sockaddr_in addr, laddr; + socklen_t size; int sock; struct pptp_conn_t *conn; while(1) { + size = sizeof(addr); sock = accept(h->fd, (struct sockaddr *)&addr, &size); if (sock < 0) { if (errno == EAGAIN) @@ -653,12 +717,12 @@ static int pptp_connect(struct triton_md_handler_t *h) continue; } - if (conf_max_starting && ap_session_stat.starting >= conf_max_starting) { + if (conf_max_starting && ap_session_stat_starting() >= conf_max_starting) { close(sock); continue; } - if (conf_max_sessions && ap_session_stat.active + ap_session_stat.starting >= conf_max_sessions) { + if (conf_max_sessions && ap_session_stat_active() + ap_session_stat_starting() >= conf_max_sessions) { close(sock); continue; } @@ -676,6 +740,13 @@ static int pptp_connect(struct triton_md_handler_t *h) continue; } + size = sizeof(laddr); + if (getsockname(sock, (struct sockaddr *)&laddr, &size)) { + log_error("pptp: getsockname: %s, closing connection...\n", strerror(errno)); + close(sock); + continue; + } + if (fcntl(sock, F_SETFL, O_NONBLOCK)) { log_error("pptp: failed to set nonblocking mode: %s, closing connection...\n", strerror(errno)); close(sock); @@ -708,8 +779,7 @@ static int pptp_connect(struct triton_md_handler_t *h) conn->ctrl.calling_station_id = _malloc(17); conn->ctrl.called_station_id = _malloc(17); u_inet_ntoa(addr.sin_addr.s_addr, conn->ctrl.calling_station_id); - getsockname(sock, &addr, &size); - u_inet_ntoa(addr.sin_addr.s_addr, conn->ctrl.called_station_id); + u_inet_ntoa(laddr.sin_addr.s_addr, conn->ctrl.called_station_id); ppp_init(&conn->ppp); conn->ppp.ses.ctrl = &conn->ctrl; @@ -733,7 +803,7 @@ static int pptp_connect(struct triton_md_handler_t *h) triton_event_fire(EV_CTRL_STARTING, &conn->ppp.ses); - __sync_add_and_fetch(&stat_starting, 1); + pptp_stat_inc(&serv.stat.starting); } return 0; } @@ -744,28 +814,19 @@ static void pptp_serv_close(struct triton_context_t *ctx) triton_context_unregister(ctx); } -static struct pptp_serv_t serv= -{ - .hnd.read = pptp_connect, - .ctx.close = pptp_serv_close, - .ctx.before_switch = pptp_ctx_switch, -}; - static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, void *client) { + struct pptp_stat_t stat; + + pptp_stat_get(&stat); + cli_send(client, "pptp:\r\n"); - cli_sendv(client," starting: %u\r\n", stat_starting); - cli_sendv(client," active: %u\r\n", stat_active); + cli_sendv(client," starting: %u\r\n", stat.starting); + cli_sendv(client," active: %u\r\n", stat.active); return CLI_CMD_OK; } -void __export pptp_get_stat(unsigned int **starting, unsigned int **active) -{ - *starting = &stat_starting; - *active = &stat_active; -} - static void load_config(void) { char *opt; @@ -834,7 +895,7 @@ static void pptp_init(void) { struct sockaddr_in addr; char *opt; - int fd; + int fd, f = 1; fd = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_PPTP); if (fd >= 0) @@ -850,12 +911,17 @@ static void pptp_init(void) fcntl(serv.hnd.fd, F_SETFD, fcntl(serv.hnd.fd, F_GETFD) | FD_CLOEXEC); + memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; opt = conf_get_opt("pptp", "bind"); - if (opt) - addr.sin_addr.s_addr = inet_addr(opt); - else + if (opt) { + if (!inet_aton(opt, &addr.sin_addr)) { + log_emerg("pptp: failed to parse bind address '%s'\n", opt); + close(serv.hnd.fd); + return; + } + } else addr.sin_addr.s_addr = htonl(INADDR_ANY); opt = conf_get_opt("pptp", "port"); @@ -864,7 +930,7 @@ static void pptp_init(void) else addr.sin_port = htons(PPTP_PORT); - setsockopt(serv.hnd.fd, SOL_SOCKET, SO_REUSEADDR, &serv.hnd.fd, 4); + setsockopt(serv.hnd.fd, SOL_SOCKET, SO_REUSEADDR, &f, sizeof(f)); if (bind (serv.hnd.fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) { log_emerg("pptp: failed to bind socket: %s\n", strerror(errno)); close(serv.hnd.fd); diff --git a/accel-pppd/ctrl/pptp/pptp.h b/accel-pppd/ctrl/pptp/pptp.h new file mode 100644 index 00000000..29f24ca2 --- /dev/null +++ b/accel-pppd/ctrl/pptp/pptp.h @@ -0,0 +1,7 @@ +#ifndef __PPTP_H +#define __PPTP_H + +unsigned int pptp_stat_starting(void); +unsigned int pptp_stat_active(void); + +#endif diff --git a/accel-pppd/ctrl/pptp/pptp_prot.h b/accel-pppd/ctrl/pptp/pptp_prot.h index ee8cb341..3726334a 100644 --- a/accel-pppd/ctrl/pptp/pptp_prot.h +++ b/accel-pppd/ctrl/pptp/pptp_prot.h @@ -281,7 +281,6 @@ struct pptp_set_link_info /* for control message type 15 */ (type==PPTP_WAN_ERR_NTFY )?sizeof(struct pptp_wan_err_ntfy): \ (type==PPTP_SET_LINK_INFO )?sizeof(struct pptp_set_link_info): \ 0) -#define max(a,b) (((a)>(b))?(a):(b)) #define PPTP_CTRL_SIZE_MAX ( \ max(sizeof(struct pptp_start_ctrl_conn), \ max(sizeof(struct pptp_echo_rqst), \ |
