summaryrefslogtreecommitdiff
path: root/accel-pppd/ppp/lcp_opt_accomp.c
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 /accel-pppd/ppp/lcp_opt_accomp.c
parent0d9a9b35c355fa5273055d9cf21630d07adda40f (diff)
downloadaccel-ppp-xebd-9a7418b7cf4b46d48896c0b0be22e8f5a3893eed.tar.gz
accel-ppp-xebd-9a7418b7cf4b46d48896c0b0be22e8f5a3893eed.zip
ppp: implement address/control and protocol field compression
Diffstat (limited to 'accel-pppd/ppp/lcp_opt_accomp.c')
-rw-r--r--accel-pppd/ppp/lcp_opt_accomp.c142
1 files changed, 98 insertions, 44 deletions
diff --git a/accel-pppd/ppp/lcp_opt_accomp.c b/accel-pppd/ppp/lcp_opt_accomp.c
index 33347d8..7e60582 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);