mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-10-13 18:12:03 +08:00
Lease a single IPv6.
This commit is contained in:
+212
-177
@@ -27,95 +27,94 @@
|
|||||||
#include <icmp-ping.h>
|
#include <icmp-ping.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
static void bignum_add (uint8_t * num, unsigned size, unsigned step)
|
static void bignum_add(uint8_t * num, unsigned size, unsigned step)
|
||||||
{
|
{
|
||||||
register int i;
|
register int i;
|
||||||
register unsigned tmp, y;
|
register unsigned tmp, y;
|
||||||
|
|
||||||
for (i = size-1; i >= 0; i--)
|
for (i = size - 1; i >= 0; i--) {
|
||||||
{
|
tmp = num[i];
|
||||||
tmp = num[i];
|
|
||||||
|
|
||||||
num[i] += step;
|
|
||||||
if (num[i] < tmp)
|
|
||||||
y = 1;
|
|
||||||
else
|
|
||||||
y = 0;
|
|
||||||
|
|
||||||
if (y == 0)
|
num[i] += step;
|
||||||
break;
|
if (num[i] < tmp)
|
||||||
}
|
y = 1;
|
||||||
|
else
|
||||||
|
y = 0;
|
||||||
|
|
||||||
|
if (y == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ip_lease_deinit(struct ip_lease_db_st *db)
|
||||||
void ip_lease_deinit(struct ip_lease_db_st* db)
|
|
||||||
{
|
{
|
||||||
struct ip_lease_st * cache;
|
struct ip_lease_st *cache;
|
||||||
struct htable_iter iter;
|
struct htable_iter iter;
|
||||||
|
|
||||||
cache = htable_first(&db->ht, &iter);
|
cache = htable_first(&db->ht, &iter);
|
||||||
while(cache != NULL) {
|
while (cache != NULL) {
|
||||||
free(cache);
|
free(cache);
|
||||||
|
|
||||||
cache = htable_next(&db->ht, &iter);
|
cache = htable_next(&db->ht, &iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
htable_clear(&db->ht);
|
htable_clear(&db->ht);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t rehash(const void* _e, void* unused)
|
static size_t rehash(const void *_e, void *unused)
|
||||||
{
|
{
|
||||||
const struct ip_lease_st * e = _e;
|
const struct ip_lease_st *e = _e;
|
||||||
|
|
||||||
return hash_any(&e->rip, e->rip_len, 0);
|
return hash_any(&e->rip, e->rip_len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ip_lease_init(struct ip_lease_db_st* db)
|
void ip_lease_init(struct ip_lease_db_st *db)
|
||||||
{
|
{
|
||||||
htable_init(&db->ht, rehash, NULL);
|
htable_init(&db->ht, rehash, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ip_lease_cmp(const void* _c1, void* _c2)
|
static bool ip_lease_cmp(const void *_c1, void *_c2)
|
||||||
{
|
{
|
||||||
const struct ip_lease_st* c1 = _c1;
|
const struct ip_lease_st *c1 = _c1;
|
||||||
struct ip_lease_st* c2 = _c2;
|
struct ip_lease_st *c2 = _c2;
|
||||||
|
|
||||||
if (c1->rip_len == c2->rip_len &&
|
if (c1->rip_len == c2->rip_len &&
|
||||||
ip_cmp(&c1->rip, &c2->rip, c2->rip_len) == 0)
|
ip_cmp(&c1->rip, &c2->rip, c2->rip_len) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ip_lease_exists(main_server_st* s, struct sockaddr_storage* ip, size_t sockaddrlen)
|
static int ip_lease_exists(main_server_st * s, struct sockaddr_storage *ip,
|
||||||
|
size_t sockaddrlen)
|
||||||
{
|
{
|
||||||
struct ip_lease_st t;
|
struct ip_lease_st t;
|
||||||
|
|
||||||
t.rip_len = sockaddrlen;
|
t.rip_len = sockaddrlen;
|
||||||
memcpy(&t.rip, ip, sizeof(*ip));
|
memcpy(&t.rip, ip, sizeof(*ip));
|
||||||
|
|
||||||
if (htable_get(&s->ip_leases.ht, rehash(&t, NULL), ip_lease_cmp, &t) != 0)
|
if (htable_get(&s->ip_leases.ht, rehash(&t, NULL), ip_lease_cmp, &t) !=
|
||||||
|
0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define MAX_IP_TRIES 16
|
#define MAX_IP_TRIES 16
|
||||||
|
|
||||||
static
|
static
|
||||||
int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
|
int get_ipv4_lease(main_server_st * s, struct proc_st *proc)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct sockaddr_storage tmp, mask, network, rnd;
|
struct sockaddr_storage tmp, mask, network, rnd;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
unsigned max_loops = MAX_IP_TRIES;
|
unsigned max_loops = MAX_IP_TRIES;
|
||||||
int ret;
|
int ret;
|
||||||
const char* c_network, *c_netmask;
|
const char *c_network, *c_netmask;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
|
||||||
if (proc->config.ipv4_network && proc->config.ipv4_netmask) {
|
if (proc->config.ipv4_network && proc->config.ipv4_netmask) {
|
||||||
c_network = proc->config.ipv4_network;
|
c_network = proc->config.ipv4_network;
|
||||||
c_netmask = proc->config.ipv4_netmask;
|
c_netmask = proc->config.ipv4_netmask;
|
||||||
@@ -125,19 +124,19 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (c_network && c_netmask) {
|
if (c_network && c_netmask) {
|
||||||
ret =
|
ret = inet_pton(AF_INET, c_network, SA_IN_P(&network));
|
||||||
inet_pton(AF_INET, c_network, SA_IN_P(&network));
|
|
||||||
|
|
||||||
if (ret != 1) {
|
if (ret != 1) {
|
||||||
mslog(s, NULL, LOG_ERR, "error reading IP: %s", c_network);
|
mslog(s, NULL, LOG_ERR, "error reading IP: %s",
|
||||||
|
c_network);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret =
|
ret = inet_pton(AF_INET, c_netmask, SA_IN_P(&mask));
|
||||||
inet_pton(AF_INET, c_netmask, SA_IN_P(&mask));
|
|
||||||
|
|
||||||
if (ret != 1) {
|
if (ret != 1) {
|
||||||
mslog(s, NULL, LOG_ERR, "error reading mask: %s", c_netmask);
|
mslog(s, NULL, LOG_ERR, "error reading mask: %s",
|
||||||
|
c_netmask);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,96 +145,121 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
|
|||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
|
|
||||||
/* mask the network (just in case it is wrong) */
|
/* mask the network (just in case it is wrong) */
|
||||||
for (i=0;i<sizeof(struct in_addr);i++)
|
for (i = 0; i < sizeof(struct in_addr); i++)
|
||||||
SA_IN_U8_P(&network)[i] &= (SA_IN_U8_P(&mask)[i]);
|
SA_IN_U8_P(&network)[i] &= (SA_IN_U8_P(&mask)[i]);
|
||||||
((struct sockaddr_in*)&network)->sin_family = AF_INET;
|
((struct sockaddr_in *)&network)->sin_family = AF_INET;
|
||||||
((struct sockaddr_in*)&network)->sin_port = 0;
|
((struct sockaddr_in *)&network)->sin_port = 0;
|
||||||
|
|
||||||
memcpy(&tmp, &network, sizeof(tmp));
|
memcpy(&tmp, &network, sizeof(tmp));
|
||||||
((struct sockaddr_in*)&tmp)->sin_family = AF_INET;
|
((struct sockaddr_in *)&tmp)->sin_family = AF_INET;
|
||||||
((struct sockaddr_in*)&tmp)->sin_port = 0;
|
((struct sockaddr_in *)&tmp)->sin_port = 0;
|
||||||
|
|
||||||
memset(&rnd, 0, sizeof(rnd));
|
memset(&rnd, 0, sizeof(rnd));
|
||||||
((struct sockaddr_in*)&rnd)->sin_family = AF_INET;
|
((struct sockaddr_in *)&rnd)->sin_family = AF_INET;
|
||||||
((struct sockaddr_in*)&rnd)->sin_port = 0;
|
((struct sockaddr_in *)&rnd)->sin_port = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (max_loops == 0) {
|
if (max_loops == 0) {
|
||||||
mslog(s, proc, LOG_ERR, "could not figure out a valid IPv4 IP.");
|
mslog(s, proc, LOG_ERR,
|
||||||
|
"could not figure out a valid IPv4 IP.");
|
||||||
ret = ERR_NO_IP;
|
ret = ERR_NO_IP;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (max_loops == MAX_IP_TRIES) {
|
if (max_loops == MAX_IP_TRIES) {
|
||||||
if (proc->seeds_are_set) {
|
if (proc->seeds_are_set) {
|
||||||
memcpy(SA_IN_U8_P(&rnd), proc->ipv4_seed, 4);
|
memcpy(SA_IN_U8_P(&rnd),
|
||||||
|
proc->ipv4_seed, 4);
|
||||||
} else {
|
} else {
|
||||||
uint32_t t = hash_any(proc->username, strlen(proc->username), 0);
|
uint32_t t =
|
||||||
|
hash_any(proc->username,
|
||||||
|
strlen(proc->username), 0);
|
||||||
memcpy(SA_IN_U8_P(&rnd), &t, 4);
|
memcpy(SA_IN_U8_P(&rnd), &t, 4);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
gnutls_rnd(GNUTLS_RND_NONCE, SA_IN_U8_P(&rnd), sizeof(struct in_addr));
|
gnutls_rnd(GNUTLS_RND_NONCE, SA_IN_U8_P(&rnd),
|
||||||
|
sizeof(struct in_addr));
|
||||||
max_loops--;
|
max_loops--;
|
||||||
|
|
||||||
if (SA_IN_U8_P(&rnd)[3] == 255) /* broadcast */
|
if (SA_IN_U8_P(&rnd)[3] == 255) /* broadcast */
|
||||||
bignum_add(SA_IN_U8_P(&rnd), sizeof(struct in_addr), 1);
|
bignum_add(SA_IN_U8_P(&rnd),
|
||||||
|
sizeof(struct in_addr), 1);
|
||||||
|
|
||||||
/* Mask the random number with the netmask */
|
/* Mask the random number with the netmask */
|
||||||
for (i=0;i<sizeof(struct in_addr);i++) {
|
for (i = 0; i < sizeof(struct in_addr); i++) {
|
||||||
SA_IN_U8_P(&rnd)[i] &= ~(SA_IN_U8_P(&mask)[i]);
|
SA_IN_U8_P(&rnd)[i] &= ~(SA_IN_U8_P(&mask)[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SA_IN_U8_P(&rnd)[sizeof(struct in_addr)-1] &= 0xFE;
|
SA_IN_U8_P(&rnd)[sizeof(struct in_addr) - 1] &= 0xFE;
|
||||||
|
|
||||||
/* Now add the IP to the masked random number */
|
/* Now add the IP to the masked random number */
|
||||||
for (i=0;i<sizeof(struct in_addr);i++)
|
for (i = 0; i < sizeof(struct in_addr); i++)
|
||||||
SA_IN_U8_P(&rnd)[i] |= (SA_IN_U8_P(&network)[i]);
|
SA_IN_U8_P(&rnd)[i] |=
|
||||||
|
(SA_IN_U8_P(&network)[i]);
|
||||||
|
|
||||||
/* check if it exists in the hash table */
|
/* check if it exists in the hash table */
|
||||||
if (ip_lease_exists(s, &rnd, sizeof(struct sockaddr_in)) != 0) {
|
if (ip_lease_exists(s, &rnd, sizeof(struct sockaddr_in))
|
||||||
mslog(s, proc, LOG_DEBUG, "cannot assign remote IP %s to '%s'; it is in use.",
|
!= 0) {
|
||||||
human_addr((void*)&rnd, sizeof(struct sockaddr_in), buf, sizeof(buf)),
|
mslog(s, proc, LOG_DEBUG,
|
||||||
|
"cannot assign remote IP %s to '%s'; it is in use.",
|
||||||
|
human_addr((void *)&rnd,
|
||||||
|
sizeof(struct sockaddr_in),
|
||||||
|
buf, sizeof(buf)),
|
||||||
proc->username);
|
proc->username);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&proc->ipv4->lip, &rnd, sizeof(struct sockaddr_in));
|
memcpy(&proc->ipv4->lip, &rnd,
|
||||||
proc->ipv4->lip_len = sizeof(struct sockaddr_in);
|
sizeof(struct sockaddr_in));
|
||||||
|
proc->ipv4->lip_len = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
/* RIP = LIP + 1 */
|
/* RIP = LIP + 1 */
|
||||||
memcpy(&tmp, &proc->ipv4->lip, sizeof(struct sockaddr_in));
|
memcpy(&tmp, &proc->ipv4->lip,
|
||||||
bignum_add(SA_IN_U8_P(&tmp), sizeof(struct in_addr), 1);
|
sizeof(struct sockaddr_in));
|
||||||
|
bignum_add(SA_IN_U8_P(&tmp), sizeof(struct in_addr), 1);
|
||||||
|
|
||||||
/* check if it exists in the hash table */
|
/* check if it exists in the hash table */
|
||||||
if (ip_lease_exists(s, &tmp, sizeof(struct sockaddr_in)) != 0) {
|
if (ip_lease_exists(s, &tmp, sizeof(struct sockaddr_in))
|
||||||
mslog(s, proc, LOG_DEBUG, "cannot assign remote IP %s to '%s'; it is in use.",
|
!= 0) {
|
||||||
human_addr((void*)&tmp, sizeof(struct sockaddr_in), buf, sizeof(buf)),
|
mslog(s, proc, LOG_DEBUG,
|
||||||
|
"cannot assign remote IP %s to '%s'; it is in use.",
|
||||||
|
human_addr((void *)&tmp,
|
||||||
|
sizeof(struct sockaddr_in),
|
||||||
|
buf, sizeof(buf)),
|
||||||
proc->username);
|
proc->username);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&proc->ipv4->rip, &tmp, sizeof(struct sockaddr_in));
|
memcpy(&proc->ipv4->rip, &tmp,
|
||||||
proc->ipv4->rip_len = sizeof(struct sockaddr_in);
|
sizeof(struct sockaddr_in));
|
||||||
|
proc->ipv4->rip_len = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
/* mask the last IP with the netmask */
|
/* mask the last IP with the netmask */
|
||||||
for (i=0;i<sizeof(struct in_addr);i++)
|
for (i = 0; i < sizeof(struct in_addr); i++)
|
||||||
SA_IN_U8_P(&tmp)[i] &= (SA_IN_U8_P(&mask)[i]);
|
SA_IN_U8_P(&tmp)[i] &= (SA_IN_U8_P(&mask)[i]);
|
||||||
|
|
||||||
/* the result should match the network */
|
/* the result should match the network */
|
||||||
if (memcmp(SA_IN_U8_P(&network), SA_IN_U8_P(&tmp), sizeof(struct in_addr)) != 0) {
|
if (memcmp
|
||||||
continue;
|
(SA_IN_U8_P(&network), SA_IN_U8_P(&tmp),
|
||||||
}
|
sizeof(struct in_addr)) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
mslog(s, proc, LOG_DEBUG, "selected IP for '%s': %s", proc->username,
|
mslog(s, proc, LOG_DEBUG, "selected IP for '%s': %s",
|
||||||
human_addr((void*)&proc->ipv4->lip, proc->ipv4->lip_len, buf, sizeof(buf)));
|
proc->username,
|
||||||
|
human_addr((void *)&proc->ipv4->lip,
|
||||||
if (icmp_ping4(s, (void*)&proc->ipv4->lip, (void*)&proc->ipv4->rip) == 0)
|
proc->ipv4->lip_len, buf,
|
||||||
break;
|
sizeof(buf)));
|
||||||
} while(1);
|
|
||||||
|
if (icmp_ping4
|
||||||
|
(s, (void *)&proc->ipv4->lip,
|
||||||
|
(void *)&proc->ipv4->rip) == 0)
|
||||||
|
break;
|
||||||
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
free(proc->ipv4);
|
free(proc->ipv4);
|
||||||
proc->ipv4 = NULL;
|
proc->ipv4 = NULL;
|
||||||
|
|
||||||
@@ -243,13 +267,13 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
|
int get_ipv6_lease(main_server_st * s, struct proc_st *proc)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct sockaddr_storage tmp, mask, network, rnd;
|
struct sockaddr_storage tmp, mask, network, rnd;
|
||||||
unsigned i, max_loops = MAX_IP_TRIES;
|
unsigned i, max_loops = MAX_IP_TRIES;
|
||||||
int ret;
|
int ret;
|
||||||
const char* c_network, *c_netmask;
|
const char *c_network, *c_netmask;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
|
||||||
if (proc->config.ipv6_network && proc->config.ipv6_netmask) {
|
if (proc->config.ipv6_network && proc->config.ipv6_netmask) {
|
||||||
@@ -261,114 +285,112 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (c_network && c_netmask) {
|
if (c_network && c_netmask) {
|
||||||
ret =
|
ret = inet_pton(AF_INET6, c_network, SA_IN6_P(&network));
|
||||||
inet_pton(AF_INET6, c_network, SA_IN6_P(&network));
|
|
||||||
|
|
||||||
if (ret != 1) {
|
if (ret != 1) {
|
||||||
mslog(s, NULL, LOG_ERR, "error reading IP: %s", c_network);
|
mslog(s, NULL, LOG_ERR, "error reading IP: %s",
|
||||||
|
c_network);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret =
|
ret = inet_pton(AF_INET6, c_netmask, SA_IN6_P(&mask));
|
||||||
inet_pton(AF_INET6, c_netmask, SA_IN6_P(&mask));
|
|
||||||
|
|
||||||
if (ret != 1) {
|
if (ret != 1) {
|
||||||
mslog(s, NULL, LOG_ERR, "error reading mask: %s", c_netmask);
|
mslog(s, NULL, LOG_ERR, "error reading mask: %s",
|
||||||
|
c_netmask);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
proc->ipv6 = calloc(1, sizeof(*proc->ipv6));
|
proc->ipv6 = calloc(1, sizeof(*proc->ipv6));
|
||||||
if (proc->ipv6 == NULL)
|
if (proc->ipv6 == NULL)
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
|
|
||||||
/* mask the network */
|
/* mask the network */
|
||||||
for (i=0;i<sizeof(struct in6_addr);i++)
|
for (i = 0; i < sizeof(struct in6_addr); i++)
|
||||||
SA_IN6_U8_P(&network)[i] &= (SA_IN6_U8_P(&mask)[i]);
|
SA_IN6_U8_P(&network)[i] &= (SA_IN6_U8_P(&mask)[i]);
|
||||||
((struct sockaddr_in6*)&network)->sin6_family = AF_INET6;
|
((struct sockaddr_in6 *)&network)->sin6_family = AF_INET6;
|
||||||
((struct sockaddr_in6*)&network)->sin6_port = 0;
|
((struct sockaddr_in6 *)&network)->sin6_port = 0;
|
||||||
|
|
||||||
memcpy(&tmp, &network, sizeof(tmp));
|
memcpy(&tmp, &network, sizeof(tmp));
|
||||||
((struct sockaddr_in6*)&tmp)->sin6_family = AF_INET6;
|
((struct sockaddr_in6 *)&tmp)->sin6_family = AF_INET6;
|
||||||
((struct sockaddr_in6*)&tmp)->sin6_port = 0;
|
((struct sockaddr_in6 *)&tmp)->sin6_port = 0;
|
||||||
|
|
||||||
((struct sockaddr_in6*)&rnd)->sin6_family = AF_INET6;
|
((struct sockaddr_in6 *)&rnd)->sin6_family = AF_INET6;
|
||||||
((struct sockaddr_in6*)&rnd)->sin6_port = 0;
|
((struct sockaddr_in6 *)&rnd)->sin6_port = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (max_loops == 0) {
|
if (max_loops == 0) {
|
||||||
mslog(s, NULL, LOG_ERR, "could not figure out a valid IPv6 IP.");
|
mslog(s, NULL, LOG_ERR,
|
||||||
|
"could not figure out a valid IPv6 IP.");
|
||||||
ret = ERR_NO_IP;
|
ret = ERR_NO_IP;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max_loops == MAX_IP_TRIES) {
|
if (max_loops == MAX_IP_TRIES) {
|
||||||
memset(SA_IN6_U8_P(&rnd), 0, sizeof(struct in6_addr));
|
memset(SA_IN6_U8_P(&rnd), 0,
|
||||||
|
sizeof(struct in6_addr));
|
||||||
if (proc->seeds_are_set) {
|
if (proc->seeds_are_set) {
|
||||||
memcpy(SA_IN6_U8_P(&rnd)+sizeof(struct in6_addr)-5, proc->ipv4_seed, 4);
|
memcpy(SA_IN6_U8_P(&rnd) +
|
||||||
|
sizeof(struct in6_addr) - 5,
|
||||||
|
proc->ipv4_seed, 4);
|
||||||
} else {
|
} else {
|
||||||
uint32_t t = hash_any(proc->username, strlen(proc->username), 0);
|
uint32_t t =
|
||||||
memcpy(SA_IN6_U8_P(&rnd)+sizeof(struct in6_addr)-5, &t, 4);
|
hash_any(proc->username,
|
||||||
|
strlen(proc->username), 0);
|
||||||
|
memcpy(SA_IN6_U8_P(&rnd) +
|
||||||
|
sizeof(struct in6_addr) - 5, &t,
|
||||||
|
4);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
gnutls_rnd(GNUTLS_RND_NONCE, SA_IN6_U8_P(&rnd), sizeof(struct in6_addr));
|
gnutls_rnd(GNUTLS_RND_NONCE, SA_IN6_U8_P(&rnd),
|
||||||
|
sizeof(struct in6_addr));
|
||||||
max_loops--;
|
max_loops--;
|
||||||
|
|
||||||
/* Mask the random number with the netmask */
|
|
||||||
for (i=0;i<sizeof(struct in6_addr);i++)
|
|
||||||
SA_IN6_U8_P(&rnd)[i] &= ~(SA_IN6_U8_P(&mask)[i]);
|
|
||||||
|
|
||||||
SA_IN6_U8_P(&rnd)[sizeof(struct in6_addr)-1] &= 0xFE;
|
/* Mask the random number with the netmask */
|
||||||
|
for (i = 0; i < sizeof(struct in6_addr); i++)
|
||||||
|
SA_IN6_U8_P(&rnd)[i] &=
|
||||||
|
~(SA_IN6_U8_P(&mask)[i]);
|
||||||
|
|
||||||
|
SA_IN6_U8_P(&rnd)[sizeof(struct in6_addr) - 1] &= 0xFE;
|
||||||
|
|
||||||
/* Now add the network to the masked random number */
|
/* Now add the network to the masked random number */
|
||||||
for (i=0;i<sizeof(struct in6_addr);i++)
|
for (i = 0; i < sizeof(struct in6_addr); i++)
|
||||||
SA_IN6_U8_P(&rnd)[i] |= (SA_IN6_U8_P(&network)[i]);
|
SA_IN6_U8_P(&rnd)[i] |=
|
||||||
|
(SA_IN6_U8_P(&network)[i]);
|
||||||
/* check if it exists in the hash table */
|
|
||||||
if (ip_lease_exists(s, &rnd, sizeof(struct sockaddr_in6)) != 0) {
|
/* check if it exists in the hash table */
|
||||||
mslog(s, proc, LOG_DEBUG, "cannot assign local IP %s to '%s'; it is in use.",
|
if (ip_lease_exists
|
||||||
human_addr((void*)&rnd, sizeof(struct sockaddr_in6), buf, sizeof(buf)),
|
(s, &rnd, sizeof(struct sockaddr_in6)) != 0) {
|
||||||
|
mslog(s, proc, LOG_DEBUG,
|
||||||
|
"cannot assign local IP %s to '%s'; it is in use.",
|
||||||
|
human_addr((void *)&rnd,
|
||||||
|
sizeof(struct sockaddr_in6),
|
||||||
|
buf, sizeof(buf)),
|
||||||
proc->username);
|
proc->username);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
proc->ipv6->lip_len = sizeof(struct sockaddr_in6);
|
proc->ipv6->lip_len = sizeof(struct sockaddr_in6);
|
||||||
memcpy(&proc->ipv6->lip, &rnd, proc->ipv6->lip_len);
|
memcpy(&proc->ipv6->lip, &rnd, proc->ipv6->lip_len);
|
||||||
|
|
||||||
/* RIP = LIP + 1 */
|
/* RIP = LIP in IPv6 */
|
||||||
memcpy(&tmp, &proc->ipv6->lip, sizeof(tmp));
|
memcpy(&proc->ipv6->rip, &proc->ipv6->lip,
|
||||||
proc->ipv6->rip_len = proc->ipv6->lip_len;
|
sizeof(proc->ipv6->lip));
|
||||||
|
proc->ipv6->rip_len = proc->ipv6->lip_len;
|
||||||
|
|
||||||
bignum_add(SA_IN6_U8_P(&tmp), sizeof(struct in6_addr), 1);
|
mslog(s, proc, LOG_DEBUG, "selected IP for '%s': %s",
|
||||||
|
proc->username,
|
||||||
|
human_addr((void *)&proc->ipv6->lip,
|
||||||
|
proc->ipv6->lip_len, buf,
|
||||||
|
sizeof(buf)));
|
||||||
|
|
||||||
/* check if it exists in the hash table */
|
if (icmp_ping6(s, (void *)&proc->ipv6->lip) == 0)
|
||||||
if (ip_lease_exists(s, &tmp, sizeof(struct sockaddr_in6)) != 0) {
|
break;
|
||||||
mslog(s, proc, LOG_DEBUG, "cannot assign remote IP %s to '%s'; it is in use.",
|
} while (1);
|
||||||
human_addr((void*)&tmp, sizeof(struct sockaddr_in6), buf, sizeof(buf)),
|
|
||||||
proc->username);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&proc->ipv6->rip, &tmp, proc->ipv6->rip_len);
|
|
||||||
|
|
||||||
/* mask the last IP with the netmask */
|
|
||||||
for (i=0;i<sizeof(struct in6_addr);i++)
|
|
||||||
SA_IN6_U8_P(&tmp)[i] &= (SA_IN6_U8_P(&mask)[i]);
|
|
||||||
|
|
||||||
/* the result should match the network */
|
|
||||||
if (memcmp(SA_IN6_U8_P(&network), SA_IN6_U8_P(&tmp), sizeof(struct in6_addr)) != 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
mslog(s, proc, LOG_DEBUG, "selected IP for '%s': %s", proc->username,
|
|
||||||
human_addr((void*)&proc->ipv6->lip, proc->ipv6->lip_len, buf, sizeof(buf)));
|
|
||||||
|
|
||||||
if (icmp_ping6(s, (void*)&proc->ipv6->lip, (void*)&proc->ipv6->rip) == 0)
|
|
||||||
break;
|
|
||||||
} while(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
free(proc->ipv6);
|
free(proc->ipv6);
|
||||||
proc->ipv6 = NULL;
|
proc->ipv6 = NULL;
|
||||||
|
|
||||||
@@ -376,10 +398,10 @@ fail:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_ip_leases(main_server_st* s, struct proc_st* proc)
|
int get_ip_leases(main_server_st * s, struct proc_st *proc)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
||||||
if (proc->ipv4 == NULL) {
|
if (proc->ipv4 == NULL) {
|
||||||
ret = get_ipv4_lease(s, proc);
|
ret = get_ipv4_lease(s, proc);
|
||||||
@@ -387,8 +409,11 @@ char buf[128];
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (proc->ipv4) {
|
if (proc->ipv4) {
|
||||||
if (htable_add(&s->ip_leases.ht, rehash(proc->ipv4, NULL), proc->ipv4) == 0) {
|
if (htable_add
|
||||||
mslog(s, proc, LOG_ERR, "could not add IPv4 lease to hash table.");
|
(&s->ip_leases.ht, rehash(proc->ipv4, NULL),
|
||||||
|
proc->ipv4) == 0) {
|
||||||
|
mslog(s, proc, LOG_ERR,
|
||||||
|
"could not add IPv4 lease to hash table.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -400,38 +425,48 @@ char buf[128];
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (proc->ipv6) {
|
if (proc->ipv6) {
|
||||||
if (htable_add(&s->ip_leases.ht, rehash(proc->ipv6, NULL), proc->ipv6) == 0) {
|
if (htable_add
|
||||||
mslog(s, proc, LOG_ERR, "could not add IPv6 lease to hash table.");
|
(&s->ip_leases.ht, rehash(proc->ipv6, NULL),
|
||||||
|
proc->ipv6) == 0) {
|
||||||
|
mslog(s, proc, LOG_ERR,
|
||||||
|
"could not add IPv6 lease to hash table.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proc->ipv4 == 0 && proc->ipv6 == 0) {
|
if (proc->ipv4 == 0 && proc->ipv6 == 0) {
|
||||||
mslog(s, proc, LOG_ERR, "no IPv4 or IPv6 addresses are configured. Cannot obtain lease.");
|
mslog(s, proc, LOG_ERR,
|
||||||
|
"no IPv4 or IPv6 addresses are configured. Cannot obtain lease.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proc->ipv4)
|
if (proc->ipv4)
|
||||||
mslog(s, proc, LOG_INFO, "assigned IPv4 to '%s': %s", proc->username,
|
mslog(s, proc, LOG_INFO, "assigned IPv4 to '%s': %s",
|
||||||
human_addr((void*)&proc->ipv4->rip, proc->ipv4->rip_len, buf, sizeof(buf)));
|
proc->username, human_addr((void *)&proc->ipv4->rip,
|
||||||
|
proc->ipv4->rip_len, buf,
|
||||||
|
sizeof(buf)));
|
||||||
|
|
||||||
if (proc->ipv6)
|
if (proc->ipv6)
|
||||||
mslog(s, proc, LOG_INFO, "assigned IPv6 to '%s': %s", proc->username,
|
mslog(s, proc, LOG_INFO, "assigned IPv6 to '%s': %s",
|
||||||
human_addr((void*)&proc->ipv6->rip, proc->ipv6->rip_len, buf, sizeof(buf)));
|
proc->username, human_addr((void *)&proc->ipv6->rip,
|
||||||
|
proc->ipv6->rip_len, buf,
|
||||||
|
sizeof(buf)));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_ip_leases(main_server_st* s, struct proc_st* proc)
|
void remove_ip_leases(main_server_st * s, struct proc_st *proc)
|
||||||
{
|
{
|
||||||
if (proc->ipv4) {
|
if (proc->ipv4) {
|
||||||
htable_del(&s->ip_leases.ht, rehash(proc->ipv4, NULL), proc->ipv4);
|
htable_del(&s->ip_leases.ht, rehash(proc->ipv4, NULL),
|
||||||
|
proc->ipv4);
|
||||||
free(proc->ipv4);
|
free(proc->ipv4);
|
||||||
proc->ipv4 = NULL;
|
proc->ipv4 = NULL;
|
||||||
}
|
}
|
||||||
if (proc->ipv6) {
|
if (proc->ipv6) {
|
||||||
htable_del(&s->ip_leases.ht, rehash(proc->ipv6, NULL), proc->ipv6);
|
htable_del(&s->ip_leases.ht, rehash(proc->ipv6, NULL),
|
||||||
|
proc->ipv6);
|
||||||
free(proc->ipv6);
|
free(proc->ipv6);
|
||||||
proc->ipv6 = NULL;
|
proc->ipv6 = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user