summaryrefslogtreecommitdiff
path: root/accel-pptpd/ppp
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pptpd/ppp')
-rw-r--r--accel-pptpd/ppp/ccp_mppe.c214
-rw-r--r--accel-pptpd/ppp/ipcp_opt_dns.c3
-rw-r--r--accel-pptpd/ppp/ipcp_opt_ipaddr.c3
-rw-r--r--accel-pptpd/ppp/lcp_opt_accomp.c8
-rw-r--r--accel-pptpd/ppp/lcp_opt_magic.c7
-rw-r--r--accel-pptpd/ppp/lcp_opt_mru.c7
-rw-r--r--accel-pptpd/ppp/lcp_opt_pcomp.c8
-rw-r--r--accel-pptpd/ppp/ppp.c2
-rw-r--r--accel-pptpd/ppp/ppp_ccp.c168
-rw-r--r--accel-pptpd/ppp/ppp_ccp.h9
10 files changed, 362 insertions, 67 deletions
diff --git a/accel-pptpd/ppp/ccp_mppe.c b/accel-pptpd/ppp/ccp_mppe.c
new file mode 100644
index 00000000..8958b520
--- /dev/null
+++ b/accel-pptpd/ppp/ccp_mppe.c
@@ -0,0 +1,214 @@
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <linux/if_ppp.h>
+#include <net/if.h>
+
+#include "ppp.h"
+#include "ppp_ccp.h"
+#include "log.h"
+#include "events.h"
+
+#include "memdebug.h"
+
+#define MPPE_H (1 << 24)
+#define MPPE_M (1 << 7)
+#define MPPE_S (1 << 6)
+#define MPPE_L (1 << 5)
+#define MPPE_D (1 << 4)
+#define MPPE_C (1 << 0)
+
+#define MPPE_PAD 4
+
+static struct ccp_option_t *mppe_init(struct ppp_ccp_t *ccp);
+static void mppe_free(struct ppp_ccp_t *ccp, struct ccp_option_t *opt);
+static int mppe_send_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr);
+static int mppe_recv_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr);
+static void mppe_print(void (*print)(const char *fmt,...),struct ccp_option_t*, uint8_t *ptr);
+
+struct mppe_option_t
+{
+ struct ccp_option_t opt;
+ int mppe;
+ uint8_t recv_key[16];
+ uint8_t send_key[16];
+ int policy; // 1 - allowed, 2 - required
+};
+
+static struct ccp_option_handler_t mppe_opt_hnd = {
+ .init = mppe_init,
+ .send_conf_req = mppe_send_conf_req,
+ .send_conf_nak = mppe_send_conf_req,
+ .recv_conf_req = mppe_recv_conf_req,
+ .free = mppe_free,
+ .print = mppe_print,
+};
+
+static struct ccp_option_t *mppe_init(struct ppp_ccp_t *ccp)
+{
+ struct mppe_option_t *mppe_opt = _malloc(sizeof(*mppe_opt));
+ memset(mppe_opt, 0, sizeof(*mppe_opt));
+ mppe_opt->mppe = -1;
+ mppe_opt->opt.id = CI_MPPE;
+ mppe_opt->opt.len = 6;
+
+ return &mppe_opt->opt;
+}
+
+static void mppe_free(struct ppp_ccp_t *ccp, struct ccp_option_t *opt)
+{
+ struct mppe_option_t *mppe_opt = container_of(opt, typeof(*mppe_opt), opt);
+
+ _free(mppe_opt);
+}
+
+static int setup_mppe_key(int fd, int transmit, uint8_t *key)
+{
+ struct ppp_option_data data;
+ uint8_t buf[6 + 16];
+
+ memset(buf, 0, sizeof(buf));
+ buf[0] = CI_MPPE;
+ buf[1] = 6;
+ *(uint32_t*)(buf + 2) = htonl(MPPE_S | MPPE_H);
+ if (key)
+ memcpy(buf + 6, key, 16);
+
+ memset(&data, 0, sizeof(data));
+ data.ptr = buf;
+ data.length = sizeof(buf);
+ data.transmit = transmit;
+
+ if (ioctl(fd, PPPIOCSCOMPRESS, &data)) {
+ log_ppp_warn("mppe: MPPE requested but not supported by kernel\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int decrease_mtu(struct ppp_t *ppp)
+{
+ struct ifreq ifr;
+
+ strcpy(ifr.ifr_name, ppp->ifname);
+
+ if (ioctl(sock_fd, SIOCGIFMTU, &ifr)) {
+ log_ppp_error("mppe: failed to get MTU: %s\n", strerror(errno));
+ return -1;
+ }
+
+ ifr.ifr_mtu -= MPPE_PAD;
+
+ if (ioctl(sock_fd, SIOCSIFMTU, &ifr)) {
+ log_ppp_error("mppe: failed to set MTU: %s\n", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int mppe_send_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr)
+{
+ struct mppe_option_t *mppe_opt = container_of(opt,typeof(*mppe_opt),opt);
+ struct ccp_opt32_t *opt32 = (struct ccp_opt32_t*)ptr;
+
+ if (mppe_opt->policy == 2 || mppe_opt->mppe != -1) {
+ opt32->hdr.id = CI_MPPE;
+ opt32->hdr.len = 6;
+ opt32->val = mppe_opt->mppe ? htonl(MPPE_S | MPPE_H) : 0;
+
+ if (mppe_opt->mppe && setup_mppe_key(ccp->ppp->unit_fd, 0, mppe_opt->recv_key))
+ return 0;
+
+ return 6;
+ }
+ return 0;
+}
+
+static int mppe_recv_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr)
+{
+ struct mppe_option_t *mppe_opt = container_of(opt, typeof(*mppe_opt), opt);
+ struct ccp_opt32_t *opt32 = (struct ccp_opt32_t *)ptr;
+
+ /*if (!ptr) {
+ if (mppe_opt->policy == 2)
+ return CCP_OPT_NAK;
+ return CCP_OPT_ACK;
+ }*/
+
+ if (opt32->hdr.len != 6)
+ return CCP_OPT_REJ;
+
+ if (mppe_opt->policy == 2) {
+ if (ntohl(opt32->val) != (MPPE_S | MPPE_H))
+ return CCP_OPT_NAK;
+ } else if (mppe_opt->policy == 1) {
+ if (ntohl(opt32->val) == (MPPE_S | MPPE_H))
+ mppe_opt->mppe = 1;
+ else if ((ntohl(opt32->val) & (MPPE_S | MPPE_H)) == (MPPE_S | MPPE_H)) {
+ mppe_opt->mppe = 1;
+ return CCP_OPT_NAK;
+ } else if (opt32->val) {
+ mppe_opt->mppe = 0;
+ return CCP_OPT_NAK;
+ } else
+ mppe_opt->mppe = 0;
+ }
+
+ if (setup_mppe_key(ccp->ppp->unit_fd, 1, mppe_opt->send_key))
+ return CCP_OPT_REJ;
+
+ decrease_mtu(ccp->ppp);
+
+ return CCP_OPT_ACK;
+}
+
+static void mppe_print(void (*print)(const char *fmt,...),struct ccp_option_t *opt, uint8_t *ptr)
+{
+ struct mppe_option_t *mppe_opt = container_of(opt, typeof(*mppe_opt), opt);
+ struct ccp_opt32_t *opt32 = (struct ccp_opt32_t *)ptr;
+ uint32_t bits;
+
+ if (ptr)
+ bits = ntohl(opt32->val);
+ else
+ if (mppe_opt->mppe)
+ bits = MPPE_S | MPPE_H;
+ else
+ bits = 0;
+
+ print("<mppe %sH %sM %sS %sL %sD %sC>",
+ bits & MPPE_H ? "+" : "-",
+ bits & MPPE_M ? "+" : "-",
+ bits & MPPE_S ? "+" : "-",
+ bits & MPPE_L ? "+" : "-",
+ bits & MPPE_D ? "+" : "-",
+ bits & MPPE_C ? "+" : "-"
+ );
+}
+
+static void ev_mppe_keys(struct ev_mppe_keys_t *ev)
+{
+ struct mppe_option_t *mppe_opt = container_of(ccp_find_option(ev->ppp, &mppe_opt_hnd), typeof(*mppe_opt), opt);
+
+ if ((ev->type & 0x02) == 0) {
+ log_ppp_warn("mppe: 128-bit session keys not allowed, disabling mppe ...\n");
+ return;
+ }
+
+ memcpy(mppe_opt->recv_key, ev->recv_key, 16);
+ memcpy(mppe_opt->send_key, ev->send_key, 16);
+ mppe_opt->policy = ev->policy;
+
+ if (ev->policy == 2)
+ mppe_opt->mppe = 1;
+}
+
+static void __init mppe_opt_init()
+{
+ ccp_option_register(&mppe_opt_hnd);
+ triton_event_register_handler(EV_MPPE_KEYS, (triton_event_func)ev_mppe_keys);
+}
+
diff --git a/accel-pptpd/ppp/ipcp_opt_dns.c b/accel-pptpd/ppp/ipcp_opt_dns.c
index b0365da2..4c48fd4c 100644
--- a/accel-pptpd/ppp/ipcp_opt_dns.c
+++ b/accel-pptpd/ppp/ipcp_opt_dns.c
@@ -101,6 +101,9 @@ static int dns_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt,
struct dns_option_t *dns_opt=container_of(opt,typeof(*dns_opt),opt);
struct ipcp_opt32_t *opt32=(struct ipcp_opt32_t*)ptr;
+ if (opt32->hdr.len != 6)
+ return IPCP_OPT_REJ;
+
if (!dns_opt->addr)
{
if (dns_opt->opt.id == CI_DNS1 && conf_dns1) dns_opt->addr=conf_dns1;
diff --git a/accel-pptpd/ppp/ipcp_opt_ipaddr.c b/accel-pptpd/ppp/ipcp_opt_ipaddr.c
index 963d4736..108e350c 100644
--- a/accel-pptpd/ppp/ipcp_opt_ipaddr.c
+++ b/accel-pptpd/ppp/ipcp_opt_ipaddr.c
@@ -104,6 +104,9 @@ static int ipaddr_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *o
struct sockaddr_in addr;
struct npioctl np;
+ if (opt32->hdr.len != 6)
+ return IPCP_OPT_REJ;
+
if (ipaddr_opt->ip->peer_addr == opt32->val)
goto ack;
diff --git a/accel-pptpd/ppp/lcp_opt_accomp.c b/accel-pptpd/ppp/lcp_opt_accomp.c
index 94fa1281..241b0e06 100644
--- a/accel-pptpd/ppp/lcp_opt_accomp.c
+++ b/accel-pptpd/ppp/lcp_opt_accomp.c
@@ -75,13 +75,17 @@ static int accomp_send_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt,
static int accomp_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
{
struct accomp_option_t *accomp_opt=container_of(opt,typeof(*accomp_opt),opt);
+ struct lcp_opt_hdr_t *opt0=(struct lcp_opt_hdr_t*)ptr;
- if (!ptr) {
+ /*if (!ptr) {
if (accomp_opt->require)
return LCP_OPT_NAK;
accomp_opt->accomp=0;
return LCP_OPT_ACK;
- }
+ }*/
+
+ if (opt0->len != 2)
+ return LCP_OPT_REJ;
if (accomp_opt->accomp>0)
{
diff --git a/accel-pptpd/ppp/lcp_opt_magic.c b/accel-pptpd/ppp/lcp_opt_magic.c
index 166c85c4..4a61ef91 100644
--- a/accel-pptpd/ppp/lcp_opt_magic.c
+++ b/accel-pptpd/ppp/lcp_opt_magic.c
@@ -64,8 +64,11 @@ static int magic_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt,
struct magic_option_t *magic_opt=container_of(opt,typeof(*magic_opt),opt);
struct lcp_opt32_t *opt32=(struct lcp_opt32_t*)ptr;
- if (!ptr)
- return LCP_OPT_NAK;
+ /*if (!ptr)
+ return LCP_OPT_NAK;*/
+
+ if (opt32->hdr.len != 6)
+ return LCP_OPT_REJ;
if (magic_opt->magic==ntohl(opt32->val))
{
diff --git a/accel-pptpd/ppp/lcp_opt_mru.c b/accel-pptpd/ppp/lcp_opt_mru.c
index 096c0d58..9bf7af67 100644
--- a/accel-pptpd/ppp/lcp_opt_mru.c
+++ b/accel-pptpd/ppp/lcp_opt_mru.c
@@ -86,8 +86,11 @@ static int mru_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, ui
struct mru_option_t *mru_opt = container_of(opt,typeof(*mru_opt),opt);
struct lcp_opt16_t *opt16 = (struct lcp_opt16_t*)ptr;
- if (!ptr)
- return LCP_OPT_NAK;
+ /*if (!ptr)
+ return LCP_OPT_NAK;*/
+
+ if (opt16->hdr.len != 4)
+ return LCP_OPT_REJ;
if (ntohs(opt16->val) < conf_min_mtu || ntohs(opt16->val) > lcp->ppp->ctrl->max_mtu)
return LCP_OPT_NAK;
diff --git a/accel-pptpd/ppp/lcp_opt_pcomp.c b/accel-pptpd/ppp/lcp_opt_pcomp.c
index a1ceb8e8..1f8532bb 100644
--- a/accel-pptpd/ppp/lcp_opt_pcomp.c
+++ b/accel-pptpd/ppp/lcp_opt_pcomp.c
@@ -75,13 +75,17 @@ static int pcomp_send_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt,
static int pcomp_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
{
struct pcomp_option_t *pcomp_opt=container_of(opt,typeof(*pcomp_opt),opt);
+ struct lcp_opt_hdr_t *opt0=(struct lcp_opt_hdr_t*)ptr;
- if (!ptr) {
+ /*if (!ptr) {
if (pcomp_opt->require)
return LCP_OPT_NAK;
pcomp_opt->pcomp=0;
return LCP_OPT_ACK;
- }
+ }*/
+
+ if (opt0->len != 2)
+ return LCP_OPT_REJ;
if (pcomp_opt->pcomp>0)
{
diff --git a/accel-pptpd/ppp/ppp.c b/accel-pptpd/ppp/ppp.c
index 94919779..ee7e13cc 100644
--- a/accel-pptpd/ppp/ppp.c
+++ b/accel-pptpd/ppp/ppp.c
@@ -424,8 +424,8 @@ 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;
+ if (!strcmp(name,"ipcp")) return 3;
return -1;
}
diff --git a/accel-pptpd/ppp/ppp_ccp.c b/accel-pptpd/ppp/ppp_ccp.c
index 6deaeb18..36db6f9a 100644
--- a/accel-pptpd/ppp/ppp_ccp.c
+++ b/accel-pptpd/ppp/ppp_ccp.c
@@ -1,8 +1,9 @@
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include <linux/ppp_defs.h>
#include <linux/if_ppp.h>
-#include <arpa/inet.h>
+#include <sys/ioctl.h>
#include "triton.h"
@@ -22,6 +23,7 @@ struct recv_opt_t
struct ccp_option_t *lopt;
};
+static struct ppp_layer_t ccp_layer;
static LIST_HEAD(option_handlers);
static void ccp_layer_up(struct ppp_fsm_t*);
@@ -65,6 +67,26 @@ static void ccp_options_free(struct ppp_ccp_t *ccp)
}
}
+static int ccp_set_flags(int fd, int isopen, int isup)
+{
+ int flags;
+
+ if (ioctl(fd, PPPIOCGFLAGS, &flags)) {
+ log_ppp_error("ccp: failed to get flags: %s\n", strerror(errno));
+ return -1;
+ }
+
+ flags &= ~(SC_CCP_OPEN | SC_CCP_UP);
+ flags |= (isopen ? SC_CCP_OPEN : 0) | (isup ? SC_CCP_UP : 0);
+
+ if (ioctl(fd, PPPIOCSFLAGS, &flags)) {
+ log_ppp_error("ccp: failed to set flags: %s\n", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
static struct ppp_layer_data_t *ccp_layer_init(struct ppp_t *ppp)
{
struct ppp_ccp_t *ccp=_malloc(sizeof(*ccp));
@@ -80,6 +102,11 @@ static struct ppp_layer_data_t *ccp_layer_init(struct ppp_t *ppp)
ppp_register_unit_handler(ppp,&ccp->hnd);
+ INIT_LIST_HEAD(&ccp->options);
+ ccp_options_init(ccp);
+
+ ccp->passive = 1;
+
ccp->fsm.proto = PPP_CCP;
ppp_fsm_init(&ccp->fsm);
@@ -92,7 +119,6 @@ static struct ppp_layer_data_t *ccp_layer_init(struct ppp_t *ppp)
ccp->fsm.send_term_req=send_term_req;
ccp->fsm.send_term_ack=send_term_ack;
- INIT_LIST_HEAD(&ccp->options);
INIT_LIST_HEAD(&ccp->ropt_list);
return &ccp->ld;
@@ -104,8 +130,6 @@ int ccp_layer_start(struct ppp_layer_data_t *ld)
log_ppp_debug("ccp_layer_start\n");
- ccp_options_init(ccp);
-
if (list_empty(&ccp->options)) {
ppp_layer_started(ccp->ppp, &ccp->ld);
return 0;
@@ -115,6 +139,11 @@ int ccp_layer_start(struct ppp_layer_data_t *ld)
if (ppp_fsm_open(&ccp->fsm))
return -1;
+ if (ccp_set_flags(ccp->ppp->unit_fd, 1, 0)) {
+ ppp_fsm_close(&ccp->fsm);
+ return -1;
+ }
+
return 0;
}
@@ -123,6 +152,8 @@ void ccp_layer_finish(struct ppp_layer_data_t *ld)
struct ppp_ccp_t *ccp=container_of(ld,typeof(*ccp),ld);
log_ppp_debug("ccp_layer_finish\n");
+
+ ccp_set_flags(ccp->ppp->unit_fd, 0, 0);
ccp->fsm.fsm_state = FSM_Closed;
ppp_layer_finished(ccp->ppp,&ccp->ld);
@@ -146,6 +177,10 @@ static void ccp_layer_up(struct ppp_fsm_t *fsm)
struct ppp_ccp_t *ccp=container_of(fsm,typeof(*ccp),fsm);
log_ppp_debug("ccp_layer_started\n");
ccp->started = 1;
+ if (ccp_set_flags(ccp->ppp->unit_fd, 1, 1)) {
+ ppp_terminate(ccp->ppp, 0);
+ return;
+ }
ppp_layer_started(ccp->ppp,&ccp->ld);
}
@@ -174,38 +209,45 @@ static void print_ropt(struct recv_opt_t *ropt)
static int send_conf_req(struct ppp_fsm_t *fsm)
{
- struct ppp_ccp_t *ccp=container_of(fsm,typeof(*ccp),fsm);
- uint8_t *buf=_malloc(ccp->conf_req_len), *ptr=buf;
- struct ccp_hdr_t *ccp_hdr=(struct ccp_hdr_t*)ptr;
+ struct ppp_ccp_t *ccp = container_of(fsm, typeof(*ccp), fsm);
+ uint8_t *buf, *ptr;
+ struct ccp_hdr_t *ccp_hdr;
struct ccp_option_t *lopt;
int n;
- log_ppp_debug("send [CCP ConfReq");
- ccp_hdr->proto=htons(PPP_CCP);
- ccp_hdr->code=CONFREQ;
- ccp_hdr->id=++ccp->fsm.id;
- ccp_hdr->len=0;
- log_ppp_debug(" id=%x",ccp_hdr->id);
+ ccp->need_req = 0;
+
+ if (ccp->passive)
+ return 0;
+
+ buf = _malloc(ccp->conf_req_len);
+ ccp_hdr = (struct ccp_hdr_t*)buf;
+
+ ccp_hdr->proto = htons(PPP_CCP);
+ ccp_hdr->code = CONFREQ;
+ ccp_hdr->id = ++ccp->fsm.id;
+ ccp_hdr->len = 0;
- ptr+=sizeof(*ccp_hdr);
+ ptr = (uint8_t*)(ccp_hdr + 1);
- list_for_each_entry(lopt,&ccp->options,entry)
- {
- n=lopt->h->send_conf_req(ccp,lopt,ptr);
+ log_ppp_debug("send [CCP ConfReq id=%x", ccp_hdr->id);
+
+ list_for_each_entry(lopt,&ccp->options,entry) {
+ n = lopt->h->send_conf_req(ccp,lopt,ptr);
if (n < 0)
return -1;
- if (n)
- {
+ if (n) {
log_ppp_debug(" ");
- lopt->h->print(log_ppp_debug,lopt,NULL);
- ptr+=n;
+ lopt->h->print(log_ppp_debug, lopt, NULL);
+ lopt->state = CCP_OPT_ACK;
}
+ ptr += n;
}
log_ppp_debug("]\n");
-
- ccp_hdr->len=htons((ptr-buf)-2);
- ppp_unit_send(ccp->ppp,ccp_hdr,ptr-buf);
+
+ ccp_hdr->len = htons((ptr-buf)-2);
+ ppp_unit_send(ccp->ppp, ccp_hdr, ptr-buf);
_free(buf);
@@ -298,9 +340,10 @@ static int ccp_recv_conf_req(struct ppp_ccp_t *ccp,uint8_t *data,int size)
struct ccp_opt_hdr_t *hdr;
struct recv_opt_t *ropt;
struct ccp_option_t *lopt;
- int r,ret=1,ack=0;
+ int r, ret = 1, ack = 0;
- ccp->ropt_len=size;
+ ccp->need_req = 0;
+ ccp->ropt_len = size;
while(size>0)
{
@@ -318,41 +361,37 @@ static int ccp_recv_conf_req(struct ppp_ccp_t *ccp,uint8_t *data,int size)
size-=ropt->len;
}
- list_for_each_entry(lopt,&ccp->options,entry)
- lopt->state=CCP_OPT_NONE;
-
- log_ppp_debug("recv [CCP ConfReq id=%x",ccp->fsm.recv_id);
- list_for_each_entry(ropt,&ccp->ropt_list,entry)
+ log_ppp_debug("recv [CCP ConfReq id=%x", ccp->fsm.recv_id);
+ list_for_each_entry(ropt, &ccp->ropt_list, entry)
{
- list_for_each_entry(lopt,&ccp->options,entry)
+ list_for_each_entry(lopt, &ccp->options, entry)
{
- if (lopt->id==ropt->hdr->id)
- {
+ if (lopt->id == ropt->hdr->id) {
log_ppp_debug(" ");
- lopt->h->print(log_ppp_debug,lopt,(uint8_t*)ropt->hdr);
- r=lopt->h->recv_conf_req(ccp,lopt,(uint8_t*)ropt->hdr);
- if (ack)
- {
- lopt->state=CCP_OPT_REJ;
- ropt->state=CCP_OPT_REJ;
- }else
- {
- lopt->state=r;
- ropt->state=r;
+ lopt->h->print(log_ppp_debug, lopt, (uint8_t*)ropt->hdr);
+ r = lopt->h->recv_conf_req(ccp, lopt, (uint8_t*)ropt->hdr);
+ if (ack) {
+ lopt->state = CCP_OPT_REJ;
+ ropt->state = CCP_OPT_REJ;
+ } else {
+ if (lopt->state == CCP_OPT_NAK && r == CCP_OPT_ACK)
+ ccp->need_req = 1;
+ lopt->state = r;
+ ropt->state = r;
}
- ropt->lopt=lopt;
- if (r<ret) ret=r;
+ ropt->lopt = lopt;
+ if (r < ret)
+ ret = r;
break;
}
}
- if (ropt->state==CCP_OPT_ACK || ropt->state==CCP_OPT_NAK)
- ack=1;
- else if (!ropt->lopt)
- {
+ if (ropt->state == CCP_OPT_ACK || ropt->state == CCP_OPT_NAK)
+ ack = 1;
+ else if (!ropt->lopt) {
log_ppp_debug(" ");
print_ropt(ropt);
- ropt->state=CCP_OPT_REJ;
- ret=CCP_OPT_REJ;
+ ropt->state = CCP_OPT_REJ;
+ ret = CCP_OPT_REJ;
}
}
log_ppp_debug("]\n");
@@ -570,14 +609,22 @@ static void ccp_recv(struct ppp_handler_t*h)
break;
}
ccp_free_conf_req(ccp);
- if (r==CCP_OPT_FAIL)
+
+ if (r == CCP_OPT_ACK && ccp->passive) {
+ ccp->passive = 0;
+ send_conf_req(&ccp->fsm);
+ }
+ if (r == CCP_OPT_FAIL)
ppp_terminate(ccp->ppp, 0);
break;
case CONFACK:
if (ccp_recv_conf_ack(ccp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN))
ppp_terminate(ccp->ppp, 0);
- else
+ else {
ppp_fsm_recv_conf_ack(&ccp->fsm);
+ if (ccp->need_req)
+ send_conf_req(&ccp->fsm);
+ }
break;
case CONFNAK:
ccp_recv_conf_nak(ccp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN);
@@ -625,6 +672,19 @@ int ccp_option_register(struct ccp_option_handler_t *h)
return 0;
}
+struct ccp_option_t *ccp_find_option(struct ppp_t *ppp, struct ccp_option_handler_t *h)
+{
+ struct ppp_ccp_t *ccp = container_of(ppp_find_layer_data(ppp, &ccp_layer), typeof(*ccp), ld);
+ struct ccp_option_t *opt;
+
+ list_for_each_entry(opt, &ccp->options, entry)
+ if (opt->h == h)
+ return opt;
+
+ log_emerg("ccp: BUG: option not found\n");
+ abort();
+}
+
static struct ppp_layer_t ccp_layer=
{
.init=ccp_layer_init,
diff --git a/accel-pptpd/ppp/ppp_ccp.h b/accel-pptpd/ppp/ppp_ccp.h
index 23f44f0f..27b303e6 100644
--- a/accel-pptpd/ppp/ppp_ccp.h
+++ b/accel-pptpd/ppp/ppp_ccp.h
@@ -8,10 +8,8 @@
/*
* Options.
*/
-#define CI_COMP 2 /* IP-Compress-Protocol */
-#define CI_ADDR 3 /* IP-Address */
-#define CI_DNS1 129 /* Primary-DNS-Address */
-#define CI_DNS2 131 /* Secondary-DNS-Address */
+
+#define CI_MPPE 18 /* MPPE */
struct ccp_hdr_t
{
@@ -87,9 +85,12 @@ struct ppp_ccp_t
int conf_req_len;
int started:1;
+ int passive:1;
+ int need_req:1;
};
int ccp_option_register(struct ccp_option_handler_t *h);
+struct ccp_option_t *ccp_find_option(struct ppp_t *ppp, struct ccp_option_handler_t *h);
#endif