diff options
author | Vladislav Grishenko <themiron@mail.ru> | 2021-04-08 01:25:03 +0500 |
---|---|---|
committer | Vladislav Grishenko <themiron@mail.ru> | 2021-04-08 01:25:03 +0500 |
commit | 3b74e1088af7b525880b386136c0330bbed377a0 (patch) | |
tree | d790468d33fcdee96b5e1a5a0007ad585d0e117b /accel-pppd | |
parent | 0ae932e8e39a4cfc88dc2102789791e376fe21cf (diff) | |
download | accel-ppp-3b74e1088af7b525880b386136c0330bbed377a0.tar.gz accel-ppp-3b74e1088af7b525880b386136c0330bbed377a0.zip |
ippool, ipv6pool: fix iterating over circular pools
Diffstat (limited to 'accel-pppd')
-rw-r--r-- | accel-pppd/extra/ippool.c | 51 | ||||
-rw-r--r-- | accel-pppd/extra/ipv6pool.c | 77 |
2 files changed, 63 insertions, 65 deletions
diff --git a/accel-pppd/extra/ippool.c b/accel-pppd/extra/ippool.c index 2b3ef3ff..7a91cf43 100644 --- a/accel-pppd/extra/ippool.c +++ b/accel-pppd/extra/ippool.c @@ -332,38 +332,39 @@ static void generate_pool_net30(struct ippool_t *p) static struct ipv4db_item_t *get_ip(struct ap_session *ses) { struct ippool_item_t *it; - struct ippool_t *p; + struct ippool_t *pool, *start; if (ses->ipv4_pool_name) - p = find_pool(ses->ipv4_pool_name, 0); + pool = find_pool(ses->ipv4_pool_name, 0); else - p = def_pool; + pool = def_pool; - if (!p) + if (!pool) return NULL; -again: - spin_lock(&p->lock); - if (!list_empty(&p->items)) { - it = list_entry(p->items.next, typeof(*it), entry); - list_del(&it->entry); - } else - it = NULL; - spin_unlock(&p->lock); + start = pool; + do { + spin_lock(&pool->lock); + if (!list_empty(&pool->items)) { + it = list_entry(pool->items.next, typeof(*it), entry); + list_del(&it->entry); + } else + it = NULL; + spin_unlock(&pool->lock); - if (it) { - if (ses->ctrl->ppp) - it->it.addr = conf_gw_ip_address; - else - it->it.addr = 0; + if (it) { + if (ses->ctrl->ppp) + it->it.addr = conf_gw_ip_address; + else + it->it.addr = 0; - it->it.mask = 0; + it->it.mask = 0; - return &it->it; - } else if (p->next) { - p = p->next; - goto again; - } + return &it->it; + } + + pool = pool->next; + } while (pool && pool != start); return NULL; } @@ -639,9 +640,7 @@ static void ippool_init2(void) else if (!opt->val || strchr(opt->name, ',')) add_range(pool, &pool->tunnel_list, opt->name, generate); - if (pool == next) - log_warn("ippool: %s: same next pool\n", opt->raw); - else if (next) + if (next) pool->next = next; } } diff --git a/accel-pppd/extra/ipv6pool.c b/accel-pppd/extra/ipv6pool.c index 5ca85f1c..3494a912 100644 --- a/accel-pppd/extra/ipv6pool.c +++ b/accel-pppd/extra/ipv6pool.c @@ -249,7 +249,7 @@ static struct ipv6db_item_t *get_ip(struct ap_session *ses) { struct ippool_item_t *it; struct ipv6db_addr_t *a; - struct ippool_t *pool; + struct ippool_t *pool, *start; if (ses->ipv6_pool_name) pool = find_pool(IPPOOL_ADDRESS, ses->ipv6_pool_name, 0); @@ -259,30 +259,31 @@ static struct ipv6db_item_t *get_ip(struct ap_session *ses) if (!pool) return NULL; -again: - spin_lock(&pool->lock); - if (!list_empty(&pool->items)) { - it = list_entry(pool->items.next, typeof(*it), entry); - list_del(&it->entry); - } else - it = NULL; - spin_unlock(&pool->lock); - - if (it) { - a = list_entry(it->it.addr_list.next, typeof(*a), entry); - if (a->prefix_len == 128) { - memcpy(&it->it.intf_id, conf_gw_addr.s6_addr + 8, 8); - memcpy(&it->it.peer_intf_id, a->addr.s6_addr + 8, 8); - } else { - it->it.intf_id = 0; - it->it.peer_intf_id = 0; + start = pool; + do { + spin_lock(&pool->lock); + if (!list_empty(&pool->items)) { + it = list_entry(pool->items.next, typeof(*it), entry); + list_del(&it->entry); + } else + it = NULL; + spin_unlock(&pool->lock); + + if (it) { + a = list_entry(it->it.addr_list.next, typeof(*a), entry); + if (a->prefix_len == 128) { + memcpy(&it->it.intf_id, conf_gw_addr.s6_addr + 8, 8); + memcpy(&it->it.peer_intf_id, a->addr.s6_addr + 8, 8); + } else { + it->it.intf_id = 0; + it->it.peer_intf_id = 0; + } + + return &it->it; } - return &it->it; - } else if (pool->next) { pool = pool->next; - goto again; - } + } while (pool && pool != start); return NULL; } @@ -299,28 +300,28 @@ static void put_ip(struct ap_session *ses, struct ipv6db_item_t *it) static struct ipv6db_prefix_t *get_dp(struct ap_session *ses) { struct dppool_item_t *it; - struct ippool_t *pool; + struct ippool_t *pool, *start; if (ses->dpv6_pool_name) pool = find_pool(IPPOOL_PREFIX, ses->dpv6_pool_name, 0); else pool = def_dppool; -again: - spin_lock(&pool->lock); - if (!list_empty(&pool->items)) { - it = list_entry(pool->items.next, typeof(*it), entry); - list_del(&it->entry); - } else - it = NULL; - spin_unlock(&pool->lock); + start = pool; + do { + spin_lock(&pool->lock); + if (!list_empty(&pool->items)) { + it = list_entry(pool->items.next, typeof(*it), entry); + list_del(&it->entry); + } else + it = NULL; + spin_unlock(&pool->lock); + + if (it) + return &it->it; - if (it) - return &it->it; - else if (pool->next) { pool = pool->next; - goto again; - } + } while (pool && pool != start); return NULL; } @@ -495,9 +496,7 @@ static void ippool_init2(void) add_prefix(type, pool, val); - if (pool == next) - log_warn("ipv6_pool: %s: same next pool\n", opt->raw); - else if (next) + if (next) pool->next = next; } |