diff options
Diffstat (limited to 'accel-pppd/ppp/lcp_opt_accomp.c')
-rw-r--r-- | accel-pppd/ppp/lcp_opt_accomp.c | 142 |
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 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); |