summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKozlov Dmitry <xeb@mail.ru>2013-06-11 15:47:51 +0400
committerKozlov Dmitry <xeb@mail.ru>2013-06-11 15:47:51 +0400
commitc4e0859d53d9626eb7be3805d3a796011eac1869 (patch)
tree649608449eddda179a61317f5317bccafd287e44
parent462b51dc958f0d710e45b578b03dbf32b5e0d321 (diff)
downloadaccel-ppp-c4e0859d53d9626eb7be3805d3a796011eac1869.tar.gz
accel-ppp-c4e0859d53d9626eb7be3805d3a796011eac1869.zip
ipoe: introduced 'gw-ip-address=x.x.x.x/mask' option to use it as server address and mask if radius can assign only client address
-rw-r--r--accel-pppd/accel-ppp.conf.53
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.c89
2 files changed, 74 insertions, 18 deletions
diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5
index 4aca90fa..ac2abf6f 100644
--- a/accel-pppd/accel-ppp.conf.5
+++ b/accel-pppd/accel-ppp.conf.5
@@ -214,6 +214,9 @@ If specified then if radius rejects access 'ip rule add from ip_addr table l4-re
.B n
seconds.
.TP
+.BI "gw-ip-address="x.x.x.x/mask
+Specifies address to be used as server ip address if radius can assign only client address. In such case if client address is matched network and mask then specified address and mask will be used. You can specify multiple such options.
+.TP
.BI "shared=" 0|1
Specifies default value for per-interface
.B shared
diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c
index b0d52013..18965d86 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.c
+++ b/accel-pppd/ctrl/ipoe/ipoe.c
@@ -69,7 +69,7 @@ static const char *conf_lua_username_func;
#endif
static int conf_offer_timeout = 3;
-static in_addr_t conf_gw_address;
+static LIST_HEAD(conf_gw_addr);
static int conf_netmask = 24;
static int conf_lease_time = 600;
static int conf_lease_timeout = 660;
@@ -83,33 +83,35 @@ static mempool_t ses_pool;
static LIST_HEAD(serv_list);
-struct ifaddr
-{
+struct ifaddr {
struct list_head entry;
in_addr_t addr;
int refs;
};
-struct iplink_arg
-{
+struct iplink_arg {
pcre *re;
const char *opt;
};
-struct unit_cache
-{
+struct unit_cache {
struct list_head entry;
int ifindex;
};
-struct l4_redirect
-{
+struct l4_redirect {
struct list_head entry;
int ifindex;
in_addr_t addr;
time_t timeout;
};
+struct gw_addr {
+ struct list_head entry;
+ in_addr_t addr;
+ int mask;
+};
+
static pthread_mutex_t uc_lock = PTHREAD_MUTEX_INITIALIZER;
static LIST_HEAD(uc_list);
static int uc_size;
@@ -472,6 +474,22 @@ static void ipoe_session_start(struct ipoe_session *ses)
__ipoe_session_start(ses);
}
+static void find_gw_addr(struct ipoe_session *ses)
+{
+ struct gw_addr *a;
+
+ list_for_each_entry(a, &conf_gw_addr, entry) {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ if ((ses->yiaddr & ((1<<a->mask) - 1)) == (a->addr & ((1<<a->mask) - 1))) {
+ ses->siaddr = a->addr;
+ ses->mask = a->mask;
+ return;
+ }
+#else
+#endif
+ }
+}
+
static void __ipoe_session_start(struct ipoe_session *ses)
{
if (!ses->yiaddr) {
@@ -487,9 +505,6 @@ static void __ipoe_session_start(struct ipoe_session *ses)
ses->mask = conf_netmask;
if (ses->ses.ipv4) {
- if (conf_gw_address)
- ses->ses.ipv4->addr = conf_gw_address;
-
if (!ses->mask)
ses->mask = ses->ses.ipv4->mask;
@@ -519,6 +534,9 @@ static void __ipoe_session_start(struct ipoe_session *ses)
if (!ses->siaddr && ses->serv->dhcpv4_relay)
ses->siaddr = ses->serv->dhcpv4_relay->giaddr;
+ if (!ses->siaddr)
+ find_gw_addr(ses);
+
if (!ses->siaddr) {
log_ppp_error("can't determine Server-ID\n");
ap_session_terminate(&ses->ses, TERM_NAS_ERROR, 0);
@@ -1855,6 +1873,46 @@ static void load_local_nets(struct conf_sect_t *sect)
}
}
+static void load_gw_addr(struct conf_sect_t *sect)
+{
+ struct conf_option_t *opt;
+ struct gw_addr *a;
+ char addr[17];
+ char *ptr;
+
+ while (!list_empty(&conf_gw_addr)) {
+ a = list_entry(conf_gw_addr.next, typeof(*a), entry);
+ list_del(&a->entry);
+ _free(a);
+ }
+
+ list_for_each_entry(opt, &sect->items, entry) {
+ if (strcmp(opt->name, "gw-ip-address"))
+ continue;
+ if (!opt->val)
+ continue;
+
+ a = _malloc(sizeof(*a));
+ ptr = strchr(opt->val, '/');
+ if (ptr) {
+ memcpy(addr, opt->val, ptr - opt->val);
+ addr[ptr - opt->val] = 0;
+ a->addr = inet_addr(addr);
+ a->mask = atoi(ptr + 1);
+ } else {
+ a->addr = inet_addr(opt->val);
+ a->mask = 32;
+ }
+
+ if (a->addr == 0xffffffff || a->mask < 1 || a->mask > 32) {
+ log_error("ipoe: failed to parse '%s=%s'\n", opt->name, opt->val);
+ _free(a);
+ continue;
+ }
+ list_add_tail(&a->entry, &conf_gw_addr);
+ }
+}
+
#ifdef RADIUS
static void parse_conf_rad_attr(const char *opt, int *val)
{
@@ -1908,12 +1966,6 @@ static void load_config(void)
log_emerg("ipoe: unknown username value '%s'\n", opt);
}
- opt = conf_get_opt("ipoe", "gw-ip-address");
- if (opt)
- conf_gw_address = inet_addr(opt);
- else
- conf_gw_address = 0;
-
opt = conf_get_opt("ipoe", "netmask");
if (opt) {
conf_netmask = atoi(opt);
@@ -2027,6 +2079,7 @@ static void load_config(void)
load_interfaces(s);
load_local_nets(s);
+ load_gw_addr(s);
}
static struct triton_context_t l4_redirect_ctx = {