diff options
author | Vladislav Grishenko <themiron@mail.ru> | 2014-09-01 16:05:39 +0600 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2014-09-13 11:02:18 +0400 |
commit | 9a7418b7cf4b46d48896c0b0be22e8f5a3893eed (patch) | |
tree | ef02d31580016978f2daf577a34d82ba9eeb6ddb | |
parent | 0d9a9b35c355fa5273055d9cf21630d07adda40f (diff) | |
download | accel-ppp-9a7418b7cf4b46d48896c0b0be22e8f5a3893eed.tar.gz accel-ppp-9a7418b7cf4b46d48896c0b0be22e8f5a3893eed.zip |
ppp: implement address/control and protocol field compression
-rw-r--r-- | accel-pppd/accel-ppp.conf | 2 | ||||
-rw-r--r-- | accel-pppd/accel-ppp.conf.5 | 18 | ||||
-rw-r--r-- | accel-pppd/ppp/lcp_opt_accomp.c | 142 | ||||
-rw-r--r-- | accel-pppd/ppp/lcp_opt_pcomp.c | 144 |
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); |