summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladislav Grishenko <themiron@mail.ru>2014-09-01 16:05:39 +0600
committerDmitry Kozlov <xeb@mail.ru>2014-09-13 11:02:18 +0400
commit9a7418b7cf4b46d48896c0b0be22e8f5a3893eed (patch)
treeef02d31580016978f2daf577a34d82ba9eeb6ddb
parent0d9a9b35c355fa5273055d9cf21630d07adda40f (diff)
downloadaccel-ppp-9a7418b7cf4b46d48896c0b0be22e8f5a3893eed.tar.gz
accel-ppp-9a7418b7cf4b46d48896c0b0be22e8f5a3893eed.zip
ppp: implement address/control and protocol field compression
-rw-r--r--accel-pppd/accel-ppp.conf2
-rw-r--r--accel-pppd/accel-ppp.conf.518
-rw-r--r--accel-pppd/ppp/lcp_opt_accomp.c142
-rw-r--r--accel-pppd/ppp/lcp_opt_pcomp.c144
4 files changed, 217 insertions, 89 deletions
diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf
index af8967ff..49d1fa9c 100644
--- a/accel-pppd/accel-ppp.conf
+++ b/accel-pppd/accel-ppp.conf
@@ -43,6 +43,8 @@ verbose=1
min-mtu=1280
mtu=1400
mru=1400
+#accomp=deny
+#pcomp=deny
#ccp=0
#check-ip=0
#mppe=require
diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5
index ced42acb..06a1d3fd 100644
--- a/accel-pppd/accel-ppp.conf.5
+++ b/accel-pppd/accel-ppp.conf.5
@@ -95,6 +95,24 @@ MTU which will be negotiated if client's MRU will be not acceptable.
.BI "mru=" n
Prefered MRU.
.TP
+.BI "accomp=" allow|deny|n
+Address/Control compression negotiation.
+.br
+.B allow
+- prefere in send and don't deny in receive directions
+.br
+.B deny
+- disable in both directions, default behavior
+.TP
+.BI "pcomp=" allow|deny|n
+Protocol field compression negotiation.
+.br
+.B allow
+- prefere in send and don't deny in receive directions
+.br
+.B deny
+- disable in both directions, default behavior
+.TP
.BI "ccp=" n
Disable CCP negotiation if this parameter is zero.
.TP
diff --git a/accel-pppd/ppp/lcp_opt_accomp.c b/accel-pppd/ppp/lcp_opt_accomp.c
index 33347d88..7e605826 100644
--- a/accel-pppd/ppp/lcp_opt_accomp.c
+++ b/accel-pppd/ppp/lcp_opt_accomp.c
@@ -1,107 +1,161 @@
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include "linux_ppp.h"
#include "ppp.h"
#include "ppp_lcp.h"
#include "log.h"
+#include "events.h"
#include "memdebug.h"
+static int conf_accomp = 0;
+
static struct lcp_option_t *accomp_init(struct ppp_lcp_t *lcp);
static void accomp_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt);
static int accomp_send_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
-static int accomp_send_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
static int accomp_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
-static void accomp_print(void (*print)(const char *fmt,...),struct lcp_option_t*, uint8_t *ptr);
+static int accomp_recv_conf_rej(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
+static int accomp_recv_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
+static int accomp_recv_conf_ack(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
+static void accomp_print(void (*print)(const char *fmt, ...), struct lcp_option_t *opt, uint8_t *ptr);
struct accomp_option_t
{
struct lcp_option_t opt;
int accomp; // 0 - disabled, 1 - enabled, 2 - allow,disabled, 3 - allow,enabled
- int require;
};
-static struct lcp_option_handler_t accomp_opt_hnd=
+static struct lcp_option_handler_t accomp_opt_hnd =
{
- .init=accomp_init,
- .send_conf_req=accomp_send_conf_req,
- .send_conf_nak=accomp_send_conf_nak,
- .recv_conf_req=accomp_recv_conf_req,
- .free=accomp_free,
- .print=accomp_print,
+ .init = accomp_init,
+ .send_conf_req = accomp_send_conf_req,
+ .recv_conf_req = accomp_recv_conf_req,
+ .recv_conf_rej = accomp_recv_conf_rej,
+ .recv_conf_nak = accomp_recv_conf_nak,
+ .recv_conf_ack = accomp_recv_conf_ack,
+ .free = accomp_free,
+ .print = accomp_print,
};
static struct lcp_option_t *accomp_init(struct ppp_lcp_t *lcp)
{
- struct accomp_option_t *accomp_opt=_malloc(sizeof(*accomp_opt));
- memset(accomp_opt,0,sizeof(*accomp_opt));
- accomp_opt->accomp=0;
- accomp_opt->opt.id=CI_ACCOMP;
- accomp_opt->opt.len=2;
+ struct accomp_option_t *accomp_opt = _malloc(sizeof(*accomp_opt));
+
+ memset(accomp_opt, 0, sizeof(*accomp_opt));
+ accomp_opt->accomp = conf_accomp;
+ accomp_opt->opt.id = CI_ACCOMP;
+ accomp_opt->opt.len = 2;
return &accomp_opt->opt;
}
static void accomp_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt)
{
- struct accomp_option_t *accomp_opt=container_of(opt,typeof(*accomp_opt),opt);
+ struct accomp_option_t *accomp_opt = container_of(opt, typeof(*accomp_opt), opt);
_free(accomp_opt);
}
static int accomp_send_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 (accomp_opt->accomp==1 || accomp_opt->accomp==3)
- {
- opt0->id=CI_ACCOMP;
- opt0->len=2;
+ 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 (accomp_opt->accomp & 1) {
+ opt0->id = CI_ACCOMP;
+ opt0->len = 2;
return 2;
}
return 0;
}
-static int accomp_send_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
+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;
- opt0->id=CI_ACCOMP;
- opt0->len=2;
- return 2;
+ 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 (opt0->len != 2)
+ return LCP_OPT_REJ;
+
+ if (accomp_opt->accomp & 2)
+ return LCP_OPT_ACK;
+ else
+ return LCP_OPT_REJ;
}
-static int accomp_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
+static int accomp_recv_conf_rej(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;
+ struct accomp_option_t *accomp_opt = container_of(opt, typeof(*accomp_opt), opt);
- /*if (!ptr) {
- if (accomp_opt->require)
- return LCP_OPT_NAK;
- accomp_opt->accomp=0;
- return LCP_OPT_ACK;
- }*/
+ accomp_opt->accomp &= ~1;
+ return 0;
+}
+
+static int accomp_recv_conf_nak(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 (opt0->len != 2)
- return LCP_OPT_REJ;
+ return -1;
- if (accomp_opt->accomp>0)
- {
- accomp_opt->accomp=1;
- return LCP_OPT_ACK;
- }else return LCP_OPT_REJ;
+ /* treat as reject */
+ return accomp_recv_conf_rej(lcp, opt, ptr);
+}
+
+static int accomp_recv_conf_ack(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);
+ int flags;
+
+ if (ioctl(lcp->ppp->chan_fd, PPPIOCGFLAGS, &flags))
+ goto err;
+
+ flags &= ~SC_COMP_AC;
+ if (accomp_opt->accomp & 1)
+ flags |= SC_COMP_AC;
+
+ if (ioctl(lcp->ppp->chan_fd, PPPIOCSFLAGS, &flags))
+ goto err;
+
+ return 0;
+
+err:
+ if (errno != EIO)
+ log_ppp_error("lcp:accomp: failed to set channel ACCOMP: %s\n", strerror(errno));
+ return -1;
}
-static void accomp_print(void (*print)(const char *fmt,...),struct lcp_option_t *opt, uint8_t *ptr)
+static void accomp_print(void (*print)(const char *fmt, ...), struct lcp_option_t *opt, uint8_t *ptr)
{
print("<accomp>");
}
+static void load_config(void)
+{
+ char *opt;
+
+ opt = conf_get_opt("ppp", "accomp");
+ if (opt) {
+ if (!strcmp(opt, "deny"))
+ conf_accomp = 0;
+ else if (!strcmp(opt, "allow"))
+ conf_accomp = 1 | 2;
+ else
+ conf_accomp = atoi(opt);
+ }
+}
+
static void accomp_opt_init()
{
lcp_option_register(&accomp_opt_hnd);
+
+ load_config();
+ triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config);
}
DEFINE_INIT(4, accomp_opt_init);
diff --git a/accel-pppd/ppp/lcp_opt_pcomp.c b/accel-pppd/ppp/lcp_opt_pcomp.c
index fec5e7b8..e034622e 100644
--- a/accel-pppd/ppp/lcp_opt_pcomp.c
+++ b/accel-pppd/ppp/lcp_opt_pcomp.c
@@ -1,107 +1,161 @@
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include "linux_ppp.h"
#include "ppp.h"
#include "ppp_lcp.h"
#include "log.h"
+#include "events.h"
#include "memdebug.h"
+static int conf_pcomp = 0;
+
static struct lcp_option_t *pcomp_init(struct ppp_lcp_t *lcp);
static void pcomp_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt);
static int pcomp_send_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
-static int pcomp_send_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
static int pcomp_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
-static void pcomp_print(void (*print)(const char *fmt,...),struct lcp_option_t*, uint8_t *ptr);
+static int pcomp_recv_conf_rej(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
+static int pcomp_recv_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
+static int pcomp_recv_conf_ack(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
+static void pcomp_print(void (*print)(const char *fmt, ...), struct lcp_option_t *opt, uint8_t *ptr);
struct pcomp_option_t
{
struct lcp_option_t opt;
int pcomp; // 0 - disabled, 1 - enabled, 2 - allow,disabled, 3 - allow,enabled
- int require;
};
-static struct lcp_option_handler_t pcomp_opt_hnd=
+static struct lcp_option_handler_t pcomp_opt_hnd =
{
- .init=pcomp_init,
- .send_conf_req=pcomp_send_conf_req,
- .send_conf_nak=pcomp_send_conf_nak,
- .recv_conf_req=pcomp_recv_conf_req,
- .free=pcomp_free,
- .print=pcomp_print,
+ .init = pcomp_init,
+ .send_conf_req = pcomp_send_conf_req,
+ .recv_conf_req = pcomp_recv_conf_req,
+ .recv_conf_rej = pcomp_recv_conf_rej,
+ .recv_conf_nak = pcomp_recv_conf_nak,
+ .recv_conf_ack = pcomp_recv_conf_ack,
+ .free = pcomp_free,
+ .print = pcomp_print,
};
static struct lcp_option_t *pcomp_init(struct ppp_lcp_t *lcp)
{
- struct pcomp_option_t *pcomp_opt=_malloc(sizeof(*pcomp_opt));
- memset(pcomp_opt,0,sizeof(*pcomp_opt));
- pcomp_opt->pcomp=0;
- pcomp_opt->opt.id=CI_PCOMP;
- pcomp_opt->opt.len=2;
+ struct pcomp_option_t *pcomp_opt = _malloc(sizeof(*pcomp_opt));
+
+ memset(pcomp_opt, 0, sizeof(*pcomp_opt));
+ pcomp_opt->pcomp = conf_pcomp;
+ pcomp_opt->opt.id = CI_PCOMP;
+ pcomp_opt->opt.len = 2;
return &pcomp_opt->opt;
}
static void pcomp_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt)
{
- struct pcomp_option_t *pcomp_opt=container_of(opt,typeof(*pcomp_opt),opt);
+ struct pcomp_option_t *pcomp_opt = container_of(opt, typeof(*pcomp_opt), opt);
_free(pcomp_opt);
}
static int pcomp_send_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 (pcomp_opt->pcomp==1 || pcomp_opt->pcomp==3)
- {
- opt0->id=CI_PCOMP;
- opt0->len=2;
+ 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 (pcomp_opt->pcomp & 1) {
+ opt0->id = CI_PCOMP;
+ opt0->len = 2;
return 2;
}
return 0;
}
-static int pcomp_send_conf_nak(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;
- opt0->id=CI_PCOMP;
- opt0->len=2;
- return 2;
-}
-
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;
+ 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 (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)
- {
- pcomp_opt->pcomp=1;
+ if (pcomp_opt->pcomp & 2)
return LCP_OPT_ACK;
- }else return LCP_OPT_REJ;
+ else
+ return LCP_OPT_REJ;
}
-static void pcomp_print(void (*print)(const char *fmt,...),struct lcp_option_t *opt, uint8_t *ptr)
+static int pcomp_recv_conf_rej(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);
+
+ pcomp_opt->pcomp &= ~1;
+ return 0;
+}
+
+static int pcomp_recv_conf_nak(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 (opt0->len != 2)
+ return -1;
+
+ /* treat as reject */
+ return pcomp_recv_conf_rej(lcp, opt, ptr);
+}
+
+static int pcomp_recv_conf_ack(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);
+ int flags;
+
+ if (ioctl(lcp->ppp->chan_fd, PPPIOCGFLAGS, &flags))
+ goto err;
+
+ flags &= ~SC_COMP_AC;
+ if (pcomp_opt->pcomp & 1)
+ flags |= SC_COMP_AC;
+
+ if (ioctl(lcp->ppp->chan_fd, PPPIOCSFLAGS, &flags))
+ goto err;
+
+ return 0;
+
+err:
+ if (errno != EIO)
+ log_ppp_error("lcp:pcomp: failed to set channel ACCOMP: %s\n", strerror(errno));
+ return -1;
+}
+
+static void pcomp_print(void (*print)(const char *fmt, ...), struct lcp_option_t *opt, uint8_t *ptr)
{
print("<pcomp>");
}
+static void load_config(void)
+{
+ char *opt;
+
+ opt = conf_get_opt("ppp", "pcomp");
+ if (opt) {
+ if (!strcmp(opt, "deny"))
+ conf_pcomp = 0;
+ else if (!strcmp(opt, "allow"))
+ conf_pcomp = 1 | 2;
+ else
+ conf_pcomp = atoi(opt);
+ }
+}
+
static void pcomp_opt_init()
{
lcp_option_register(&pcomp_opt_hnd);
+
+ load_config();
+ triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config);
}
DEFINE_INIT(4, pcomp_opt_init);