diff options
author | Vladislav Grishenko <themiron@mail.ru> | 2012-11-12 16:36:46 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2012-11-12 16:36:46 +0400 |
commit | 28749c59a24b277ca3f6e1bdf262c54155126f2a (patch) | |
tree | b51991afa16d80c51d9e0186c7a231b076db5c62 | |
parent | ce56e6c72c0363cd02a77cd7c7b37f9f0b50d8a4 (diff) | |
download | accel-ppp-28749c59a24b277ca3f6e1bdf262c54155126f2a.tar.gz accel-ppp-28749c59a24b277ca3f6e1bdf262c54155126f2a.zip |
ppp: add NBNS (WINS) support
-rw-r--r-- | accel-pppd/CMakeLists.txt | 1 | ||||
-rw-r--r-- | accel-pppd/accel-ppp.conf | 4 | ||||
-rw-r--r-- | accel-pppd/accel-ppp.conf.5 | 8 | ||||
-rw-r--r-- | accel-pppd/include/events.h | 8 | ||||
-rw-r--r-- | accel-pppd/ppp/CMakeLists.txt | 1 | ||||
-rw-r--r-- | accel-pppd/ppp/ipcp_opt_wins.c | 203 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp_ipcp.h | 2 | ||||
-rw-r--r-- | accel-pppd/radius/radius.c | 12 |
8 files changed, 238 insertions, 1 deletions
diff --git a/accel-pppd/CMakeLists.txt b/accel-pppd/CMakeLists.txt index 11df04fc..0f7ab089 100644 --- a/accel-pppd/CMakeLists.txt +++ b/accel-pppd/CMakeLists.txt @@ -54,6 +54,7 @@ ADD_EXECUTABLE(accel-pppd ppp/ppp_ipcp.c ppp/ipcp_opt_ipaddr.c ppp/ipcp_opt_dns.c + ppp/ipcp_opt_wins.c ppp/ipv6cp_opt_intfid.c ppp/ppp_ipv6cp.c ppp/ppp_ccp.c diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf index 28e8ed0c..8487ce9f 100644 --- a/accel-pppd/accel-ppp.conf +++ b/accel-pppd/accel-ppp.conf @@ -95,6 +95,10 @@ verbose=1 #dns1=172.16.0.1 #dns2=172.16.1.1 +[wins] +#wins1=172.16.0.1 +#wins2=172.16.1.1 + [radius] #dictionary=/usr/local/share/accel-ppp/radius/dictionary nas-identifier=accel-ppp diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5 index b3e72653..69b27a5d 100644 --- a/accel-pppd/accel-ppp.conf.5 +++ b/accel-pppd/accel-ppp.conf.5 @@ -206,6 +206,14 @@ You have to explicitly specify range of ip address from which clients can connec .B x.x.x.x-y (for example 10.0.0.1-254) .TP +.SH [wins] +.TP +.BI "wins1=" x.x.x.x +Specifies primary NBNS to be sent to peer. +.TP +.BI "wins2=" x.x.x.x +Specifies secondary NBNS to be sent to peer. +.TP .SH [pptp] .br Configuration of PPTP module. diff --git a/accel-pppd/include/events.h b/accel-pppd/include/events.h index 5d6fea7e..0d8f1fc3 100644 --- a/accel-pppd/include/events.h +++ b/accel-pppd/include/events.h @@ -21,6 +21,7 @@ #define EV_SHAPER 101 #define EV_MPPE_KEYS 102 #define EV_DNS 103 +#define EV_WINS 104 #define EV_RADIUS_ACCESS_ACCEPT 200 #define EV_RADIUS_COA 201 @@ -56,5 +57,10 @@ struct ev_dns_t in_addr_t dns2; }; +struct ev_wins_t +{ + struct ppp_t *ppp; + in_addr_t wins1; + in_addr_t wins2; +}; #endif - diff --git a/accel-pppd/ppp/CMakeLists.txt b/accel-pppd/ppp/CMakeLists.txt index f4c0f04a..560f7759 100644 --- a/accel-pppd/ppp/CMakeLists.txt +++ b/accel-pppd/ppp/CMakeLists.txt @@ -11,6 +11,7 @@ SET(sources_c ppp_ipcp.c ipcp_opt_ipaddr.c ipcp_opt_dns.c + ipcp_opt_wins.c ppp_ccp.c ) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/accel-pppd/ppp/ipcp_opt_wins.c b/accel-pppd/ppp/ipcp_opt_wins.c new file mode 100644 index 00000000..d549722a --- /dev/null +++ b/accel-pppd/ppp/ipcp_opt_wins.c @@ -0,0 +1,203 @@ +#include <stdlib.h> +#include <string.h> +#include <arpa/inet.h> + +#include "ppp.h" +#include "ppp_ipcp.h" +#include "log.h" +#include "ipdb.h" +#include "events.h" + +#include "memdebug.h" + +static in_addr_t conf_wins1; +static in_addr_t conf_wins2; + +static struct ipcp_option_t *wins1_init(struct ppp_ipcp_t *ipcp); +static struct ipcp_option_t *wins2_init(struct ppp_ipcp_t *ipcp); +static void wins_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt); +static int wins_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr); +static int wins_send_conf_nak(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr); +static int wins_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr); +static int wins_recv_conf_rej(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr); +static void wins1_print(void (*print)(const char *fmt,...), struct ipcp_option_t*, uint8_t *ptr); +static void wins2_print(void (*print)(const char *fmt,...), struct ipcp_option_t*, uint8_t *ptr); + +struct wins_option_t +{ + struct ipcp_option_t opt; + in_addr_t addr; + int rejected; +}; + +static struct ipcp_option_handler_t wins1_opt_hnd = { + .init = wins1_init, + .send_conf_req = wins_send_conf_req, + .send_conf_nak = wins_send_conf_nak, + .recv_conf_req = wins_recv_conf_req, + .recv_conf_rej = wins_recv_conf_rej, + .free = wins_free, + .print = wins1_print, +}; + +static struct ipcp_option_handler_t wins2_opt_hnd = { + .init = wins2_init, + .send_conf_req = wins_send_conf_req, + .send_conf_nak = wins_send_conf_nak, + .recv_conf_req = wins_recv_conf_req, + .recv_conf_rej = wins_recv_conf_rej, + .free = wins_free, + .print = wins2_print, +}; + +static struct ipcp_option_t *wins1_init(struct ppp_ipcp_t *ipcp) +{ + struct wins_option_t *wins_opt = _malloc(sizeof(*wins_opt)); + memset(wins_opt, 0, sizeof(*wins_opt)); + wins_opt->opt.id = CI_WINS1; + wins_opt->opt.len = 6; + + return &wins_opt->opt; +} + +static struct ipcp_option_t *wins2_init(struct ppp_ipcp_t *ipcp) +{ + struct wins_option_t *wins_opt = _malloc(sizeof(*wins_opt)); + memset(wins_opt, 0, sizeof(*wins_opt)); + wins_opt->opt.id = CI_WINS2; + wins_opt->opt.len = 6; + + return &wins_opt->opt; +} + +static void wins_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt) +{ + struct wins_option_t *wins_opt=container_of(opt,typeof(*wins_opt),opt); + + _free(wins_opt); +} + +static int wins_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr) +{ + struct wins_option_t *wins_opt = container_of(opt, typeof(*wins_opt), opt); + struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t *)ptr; + + if (!wins_opt->addr || wins_opt->rejected) + return 0; + + opt32->hdr.id = wins_opt->opt.id; + opt32->hdr.len = 6; + opt32->val = 0; + + return 6; +} + +static int wins_send_conf_nak(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr) +{ + struct wins_option_t *wins_opt = container_of(opt, typeof(*wins_opt), opt); + struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t *)ptr; + opt32->hdr.id = wins_opt->opt.id; + opt32->hdr.len = 6; + opt32->val = wins_opt->addr; + return 6; +} + +static int wins_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr) +{ + struct wins_option_t *wins_opt = container_of(opt, typeof(*wins_opt), opt); + struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t*)ptr; + + if (opt32->hdr.len != 6) + return IPCP_OPT_REJ; + + if (!wins_opt->addr) { + if (wins_opt->opt.id == CI_WINS1 && conf_wins1) + wins_opt->addr=conf_wins1; + else if (wins_opt->opt.id == CI_WINS2 && conf_wins2) + wins_opt->addr=conf_wins2; + + if (!wins_opt->addr) { + wins_opt->addr = opt32->val; + return IPCP_OPT_ACK; + } + } + + if (wins_opt->addr == opt32->val) + return IPCP_OPT_ACK; + + return IPCP_OPT_NAK; +} + +static int wins_recv_conf_rej(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr) +{ + struct wins_option_t *wins_opt = container_of(opt, typeof(*wins_opt), opt); + + wins_opt->rejected = 1; + + return 0; +} + +static void wins1_print(void (*print)(const char *fmt,...), struct ipcp_option_t *opt, uint8_t *ptr) +{ + struct wins_option_t *wins_opt = container_of(opt, typeof(*wins_opt), opt); + struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t *)ptr; + struct in_addr in; + + if (ptr) + in.s_addr = opt32->val; + else + in.s_addr = wins_opt->addr; + + print("<wins1 %s>", inet_ntoa(in)); +} + +static void wins2_print(void (*print)(const char *fmt,...), struct ipcp_option_t *opt, uint8_t *ptr) +{ + struct wins_option_t *wins_opt = container_of(opt, typeof(*wins_opt), opt); + struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t *)ptr; + struct in_addr in; + + if (ptr) + in.s_addr = opt32->val; + else + in.s_addr = wins_opt->addr; + + print("<wins2 %s>", inet_ntoa(in)); +} + +static void ev_wins(struct ev_wins_t *ev) +{ + struct wins_option_t *wins_opt; + + wins_opt = container_of(ipcp_find_option(ev->ppp, &wins1_opt_hnd), typeof(*wins_opt), opt); + wins_opt->addr = ev->wins1; + + wins_opt = container_of(ipcp_find_option(ev->ppp, &wins2_opt_hnd), typeof(*wins_opt), opt); + wins_opt->addr = ev->wins2; +} + +static void load_config(void) +{ + char *opt; + + opt = conf_get_opt("wins", "wins1"); + if (opt) + conf_wins1 = inet_addr(opt); + + opt = conf_get_opt("wins", "wins2"); + if (opt) + conf_wins2 = inet_addr(opt); +} + +static void wins_opt_init() +{ + ipcp_option_register(&wins1_opt_hnd); + ipcp_option_register(&wins2_opt_hnd); + + load_config(); + triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); + + triton_event_register_handler(EV_WINS, (triton_event_func)ev_wins); +} + +DEFINE_INIT(4, wins_opt_init); diff --git a/accel-pppd/ppp/ppp_ipcp.h b/accel-pppd/ppp/ppp_ipcp.h index 301bdcec..74127020 100644 --- a/accel-pppd/ppp/ppp_ipcp.h +++ b/accel-pppd/ppp/ppp_ipcp.h @@ -12,6 +12,8 @@ #define CI_ADDR 3 /* IP-Address */ #define CI_DNS1 129 /* Primary-DNS-Address */ #define CI_DNS2 131 /* Secondary-DNS-Address */ +#define CI_WINS1 130 /* Primary-NBNS-Address */ +#define CI_WINS2 132 /* Secondary-NBNS-Address */ struct ipcp_hdr_t { diff --git a/accel-pppd/radius/radius.c b/accel-pppd/radius/radius.c index 8f17fcc9..b6a0b5f5 100644 --- a/accel-pppd/radius/radius.c +++ b/accel-pppd/radius/radius.c @@ -58,9 +58,11 @@ int rad_proc_attrs(struct rad_req_t *req) struct rad_attr_t *attr; struct ipv6db_addr_t *a; struct ev_dns_t dns; + struct ev_wins_t wins; int res = 0; dns.ppp = NULL; + wins.ppp = NULL; req->rpd->acct_interim_interval = conf_acct_interim_interval; list_for_each_entry(attr, &req->reply->attrs, entry) { @@ -74,6 +76,14 @@ int rad_proc_attrs(struct rad_req_t *req) dns.ppp = req->rpd->ppp; dns.dns2 = attr->val.ipaddr; break; + case MS_Primary_NBNS_Server: + wins.ppp = req->rpd->ppp; + wins.wins1 = attr->val.ipaddr; + break; + case MS_Secondary_NBNS_Server: + wins.ppp = req->rpd->ppp; + wins.wins2 = attr->val.ipaddr; + break; } continue; } else if (attr->vendor) @@ -134,6 +144,8 @@ int rad_proc_attrs(struct rad_req_t *req) if (dns.ppp) triton_event_fire(EV_DNS, &dns); + if (wins.ppp) + triton_event_fire(EV_WINS, &wins); return res; } |