always assign the first network address as PtP address

This commit is contained in:
Nikos Mavrogiannopoulos
2015-02-11 10:00:15 +01:00
parent 75af003f12
commit 965ea48ee2
5 changed files with 84 additions and 155 deletions

View File

@@ -210,32 +210,6 @@ int ip_cmp(const struct sockaddr_storage *s1, const struct sockaddr_storage *s2,
}
}
/* returns an allocated string with the mask to apply for the prefix
*/
char* ipv6_prefix_to_mask(void *pool, unsigned prefix)
{
switch (prefix) {
case 16:
return talloc_strdup(pool, "ffff::");
case 32:
return talloc_strdup(pool, "ffff:ffff::");
case 48:
return talloc_strdup(pool, "ffff:ffff:ffff::");
case 64:
return talloc_strdup(pool, "ffff:ffff:ffff:ffff::");
case 80:
return talloc_strdup(pool, "ffff:ffff:ffff:ffff:ffff::");
case 96:
return talloc_strdup(pool, "ffff:ffff:ffff:ffff:ffff:ffff::");
case 112:
return talloc_strdup(pool, "ffff:ffff:ffff:ffff:ffff:ffff:ffff::");
case 128:
return talloc_strdup(pool, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
default:
return NULL;
}
}
/* returns an allocated string with the mask to apply for the prefix
*/
char* ipv4_prefix_to_mask(void *pool, unsigned prefix)

View File

@@ -42,7 +42,6 @@ ssize_t force_read(int sockfd, void *buf, size_t len);
ssize_t force_read_timeout(int sockfd, void *buf, size_t len, unsigned sec);
ssize_t recv_timeout(int sockfd, void *buf, size_t len, unsigned sec);
int ip_cmp(const struct sockaddr_storage *s1, const struct sockaddr_storage *s2, size_t n);
char* ipv6_prefix_to_mask(void *pool, unsigned prefix);
char* ipv4_prefix_to_mask(void *pool, unsigned prefix);
inline static int valid_ipv6_prefix(unsigned prefix)
{

View File

@@ -172,14 +172,12 @@ ssize_t recvfrom_timeout(int sockfd, void *buf, size_t len, int flags,
}
int icmp_ping4(main_server_st * s, struct sockaddr_in *addr1,
struct sockaddr_in *addr2)
int icmp_ping4(main_server_st * s, struct sockaddr_in *addr1)
{
struct icmp *pkt;
int pingsock, c, e;
char packet1[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
char packet2[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
char buf1[64], buf2[64];
char buf1[64];
time_t now;
uint16_t id1, id2;
unsigned gotreply = 0, unreachable = 0;
@@ -205,20 +203,9 @@ int icmp_ping4(main_server_st * s, struct sockaddr_in *addr1,
pkt->icmp_cksum =
in_cksum((unsigned short *) pkt, sizeof(packet1));
pkt = (struct icmp *) packet2;
memset(pkt, 0, sizeof(packet2));
pkt->icmp_type = ICMP_ECHO;
pkt->icmp_id = id2;
pkt->icmp_cksum =
in_cksum((unsigned short *) pkt, sizeof(packet2));
while ((c = sendto(pingsock, packet1, DEFDATALEN + ICMP_MINLEN, 0,
(struct sockaddr *) addr1,
sizeof(*addr1)) == -1) && retry(errno));
while ((c =
sendto(pingsock, packet2, DEFDATALEN + ICMP_MINLEN, 0,
(struct sockaddr *) addr2, sizeof(*addr2)) == -1)
&& retry(errno));
/* listen for replies */
now = time(0);
@@ -235,10 +222,7 @@ int icmp_ping4(main_server_st * s, struct sockaddr_in *addr1,
} else if (c >= 76 && fromlen == sizeof(struct sockaddr_in)) { /* icmp6_hdr */
if (memcmp
(SA_IN_P(&from), SA_IN_P(addr1),
SA_IN_SIZE(sizeof(*addr1))) == 0 ||
memcmp
(SA_IN_P(&from), SA_IN_P(addr2),
SA_IN_SIZE(sizeof(*addr2))) == 0) {
SA_IN_SIZE(sizeof(*addr1))) == 0) {
#ifdef HAVE_STRUCT_IPHDR_IHL
struct iphdr *iphdr =
@@ -261,38 +245,29 @@ int icmp_ping4(main_server_st * s, struct sockaddr_in *addr1,
if (gotreply > 0) {
mslog(s, NULL, LOG_INFO,
"pinged %s and %s and are in use",
"pinged %s and is in use",
human_addr((void *) addr1,
sizeof(struct sockaddr_in), buf1,
sizeof(buf1)), human_addr((void *) addr2,
sizeof(struct
sockaddr_in),
buf2,
sizeof(buf2)));
sizeof(buf1)));
return gotreply;
} else {
mslog(s, NULL, LOG_INFO,
"pinged %s and %s and are not in use",
"pinged %s and is not in use",
human_addr((void *) addr1,
sizeof(struct sockaddr_in), buf1,
sizeof(buf1)), human_addr((void *) addr2,
sizeof(struct
sockaddr_in),
buf2,
sizeof(buf2)));
sizeof(buf1)));
return 0;
}
}
int icmp_ping6(main_server_st * s,
struct sockaddr_in6 *addr1, struct sockaddr_in6 *addr2)
struct sockaddr_in6 *addr1)
{
struct icmp6_hdr *pkt;
char buf1[64], buf2[64];
char buf1[64];
int pingsock, c, e;
int sockopt;
char packet1[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
char packet2[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
uint16_t id1, id2;
unsigned gotreply = 0, unreachable = 0;
time_t now;
@@ -316,11 +291,6 @@ int icmp_ping6(main_server_st * s,
pkt->icmp6_type = ICMP6_ECHO_REQUEST;
pkt->icmp6_id = id1;
pkt = (struct icmp6_hdr *) packet2;
memset(pkt, 0, sizeof(packet2));
pkt->icmp6_type = ICMP6_ECHO_REQUEST;
pkt->icmp6_id = id2;
#if defined(SOL_RAW) && defined(IPV6_CHECKSUM)
sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM,
@@ -332,13 +302,6 @@ int icmp_ping6(main_server_st * s,
(struct sockaddr *) addr1,
sizeof(*addr1)) == -1) && retry(errno));
while ((c =
sendto(pingsock, packet2,
DEFDATALEN +
sizeof(struct icmp6_hdr), 0,
(struct sockaddr *) addr2, sizeof(*addr2)) == -1)
&& retry(errno));
/* listen for replies */
now = time(0);
while (time(0) - now < PING_TIMEOUT
@@ -354,10 +317,7 @@ int icmp_ping6(main_server_st * s,
} else if (c >= 8 && fromlen == sizeof(struct sockaddr_in6)) { /* icmp6_hdr */
if (memcmp
(SA_IN6_P(&from), SA_IN6_P(addr1),
SA_IN_SIZE(sizeof(*addr1))) == 0 ||
memcmp(SA_IN6_P(&from),
SA_IN6_P(addr2),
SA_IN_SIZE(sizeof(*addr2))) == 0) {
SA_IN_SIZE(sizeof(*addr1))) == 0) {
pkt = (struct icmp6_hdr *) packet1;
if (pkt->icmp6_id == id1 || pkt->icmp6_id == id2) {
@@ -374,25 +334,17 @@ int icmp_ping6(main_server_st * s,
if (gotreply > 0) {
mslog(s, NULL, LOG_INFO,
"pinged %s and %s and are in use",
"pinged %s and is in use",
human_addr((void *) addr1,
sizeof(struct sockaddr_in6), buf1,
sizeof(buf1)), human_addr((void *) addr2,
sizeof(struct
sockaddr_in6),
buf2,
sizeof(buf2)));
sizeof(buf1)));
return gotreply;
} else {
mslog(s, NULL, LOG_INFO,
"pinged %s and %s and are not in use",
"pinged %s and is not in use",
human_addr((void *) addr1,
sizeof(struct sockaddr_in6), buf1,
sizeof(buf1)), human_addr((void *) addr2,
sizeof(struct
sockaddr_in6),
buf2,
sizeof(buf2)));
sizeof(buf1)));
return 0;
}
}

View File

@@ -25,7 +25,7 @@
/* returns the number of positive replies received or
* 0 if no host with this IP exists. */
int icmp_ping4(main_server_st* s, struct sockaddr_in* addr1, struct sockaddr_in* addr2);
int icmp_ping6(main_server_st* s, struct sockaddr_in6* addr1, struct sockaddr_in6* addr2);
int icmp_ping4(main_server_st* s, struct sockaddr_in* addr1);
int icmp_ping6(main_server_st* s, struct sockaddr_in6* addr1);
#endif

View File

@@ -152,8 +152,8 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
}
if (c_network == NULL || c_netmask == NULL) {
mslog(s, NULL, LOG_ERR, "there is no IPv4 network assigned");
return -1;
mslog(s, NULL, LOG_DEBUG, "there is no IPv4 network assigned");
return 0;
}
ret =
@@ -200,7 +200,8 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
if (ip_lease_exists(s, &tmp, sizeof(struct sockaddr_in)) != 0) {
mslog(s, proc, LOG_DEBUG, "cannot assign explicit IP %s; it is in use.",
human_addr((void*)&tmp, sizeof(struct sockaddr_in), buf, sizeof(buf)));
return -1;
ret = ERR_NO_IP;
goto fail;
}
/* LIP = 1st network address */
@@ -209,7 +210,8 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
if (memcmp(SA_IN_U8_P(&proc->ipv4->lip), SA_IN_U8_P(&proc->ipv4->rip), sizeof(struct in_addr)) == 0) {
mslog(s, NULL, LOG_ERR, "cannot assign explicit IP: %s (net: %s)", proc->config.explicit_ipv4, c_network);
return ERR_NO_IP;
ret = ERR_NO_IP;
goto fail;
}
return 0;
@@ -251,8 +253,6 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
SA_IN_U8_P(&rnd)[i] &= ~(SA_IN_U8_P(&mask)[i]);
}
SA_IN_U8_P(&rnd)[sizeof(struct in_addr)-1] &= 0xFE;
/* Now add the IP to the masked random number */
for (i=0;i<sizeof(struct in_addr);i++)
SA_IN_U8_P(&rnd)[i] |= (SA_IN_U8_P(&network)[i]);
@@ -264,36 +264,21 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
continue;
}
memcpy(&proc->ipv4->lip, &rnd, sizeof(struct sockaddr_in));
proc->ipv4->lip_len = sizeof(struct sockaddr_in);
memcpy(&proc->ipv4->rip, &rnd, sizeof(struct sockaddr_in));
proc->ipv4->rip_len = sizeof(struct sockaddr_in);
/* RIP = LIP + 1 */
memcpy(&tmp, &proc->ipv4->lip, sizeof(struct sockaddr_in));
bignum_add(SA_IN_U8_P(&tmp), sizeof(struct in_addr), 1);
/* LIP = 1st network address */
memcpy(&proc->ipv4->lip, &network, sizeof(struct sockaddr_in));
proc->ipv4->lip_len = sizeof(struct sockaddr_in);
/* check if it exists in the hash table */
if (ip_lease_exists(s, &tmp, sizeof(struct sockaddr_in)) != 0) {
mslog(s, proc, LOG_DEBUG, "cannot assign remote IP %s; it is in use.",
human_addr((void*)&tmp, sizeof(struct sockaddr_in), buf, sizeof(buf)));
if (memcmp(SA_IN_U8_P(&proc->ipv4->lip), SA_IN_U8_P(&proc->ipv4->rip), sizeof(struct in_addr)) == 0) {
continue;
}
memcpy(&proc->ipv4->rip, &tmp, sizeof(struct sockaddr_in));
proc->ipv4->rip_len = sizeof(struct sockaddr_in);
/* mask the last IP with the netmask */
for (i=0;i<sizeof(struct in_addr);i++)
SA_IN_U8_P(&tmp)[i] &= (SA_IN_U8_P(&mask)[i]);
/* the result should match the network */
if (memcmp(SA_IN_U8_P(&network), SA_IN_U8_P(&tmp), sizeof(struct in_addr)) != 0) {
continue;
}
mslog(s, proc, LOG_DEBUG, "selected IP: %s",
human_addr((void*)&proc->ipv4->lip, proc->ipv4->lip_len, buf, sizeof(buf)));
if (icmp_ping4(s, (void*)&proc->ipv4->lip, (void*)&proc->ipv4->rip) == 0)
human_addr((void*)&proc->ipv4->rip, proc->ipv4->rip_len, buf, sizeof(buf)));
if (icmp_ping4(s, (void*)&proc->ipv4->rip) == 0)
break;
} while(1);
@@ -306,6 +291,42 @@ fail:
return ret;
}
/* returns an allocated string with the mask to apply for the prefix
*/
static
char* ipv6_prefix_to_mask(char buf[MAX_IP_STR], unsigned prefix)
{
switch (prefix) {
case 16:
strlcpy(buf, "ffff::", MAX_IP_STR);
break;
case 32:
strlcpy(buf, "ffff:ffff::", MAX_IP_STR);
break;
case 48:
strlcpy(buf, "ffff:ffff:ffff::", MAX_IP_STR);
break;
case 64:
strlcpy(buf, "ffff:ffff:ffff:ffff::", MAX_IP_STR);
break;
case 80:
strlcpy(buf, "ffff:ffff:ffff:ffff:ffff::", MAX_IP_STR);
break;
case 96:
strlcpy(buf, "ffff:ffff:ffff:ffff:ffff:ffff::", MAX_IP_STR);
break;
case 112:
strlcpy(buf, "ffff:ffff:ffff:ffff:ffff:ffff:ffff::", MAX_IP_STR);
break;
case 128:
strlcpy(buf, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", MAX_IP_STR);
break;
default:
return NULL;
}
return buf;
}
static
int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
{
@@ -315,21 +336,21 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
int ret;
const char* c_network;
char *c_netmask = NULL;
char c_netmask_buf[64];
char buf[64];
if (proc->config.ipv6_network && proc->config.ipv6_prefix) {
c_network = proc->config.ipv6_network;
c_netmask = ipv6_prefix_to_mask(proc, proc->config.ipv6_prefix);
c_netmask = ipv6_prefix_to_mask(c_netmask_buf, proc->config.ipv6_prefix);
} else {
c_network = s->config->network.ipv6;
c_netmask = ipv6_prefix_to_mask(proc, s->config->network.ipv6_prefix);
c_netmask = ipv6_prefix_to_mask(c_netmask_buf, s->config->network.ipv6_prefix);
}
if (c_network == NULL || c_netmask == NULL) {
mslog(s, NULL, LOG_ERR, "there is no IPv6 network assigned");
return -1;
return 0;
}
ret =
inet_pton(AF_INET6, c_network, SA_IN6_P(&network));
if (ret != 1) {
@@ -375,7 +396,8 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
if (ip_lease_exists(s, &tmp, sizeof(struct sockaddr_in6)) != 0) {
mslog(s, proc, LOG_DEBUG, "cannot assign explicit IP %s; it is in use.",
human_addr((void*)&tmp, sizeof(struct sockaddr_in6), buf, sizeof(buf)));
return ERR_NO_IP;
ret = ERR_NO_IP;
goto fail;
}
/* LIP = 1st network address */
@@ -384,7 +406,8 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
if (memcmp(SA_IN6_U8_P(&proc->ipv6->lip), SA_IN6_U8_P(&proc->ipv6->rip), sizeof(struct in6_addr)) == 0) {
mslog(s, NULL, LOG_ERR, "cannot assign explicit IP: %s (net: %s)", proc->config.explicit_ipv6, c_network);
return ERR_NO_IP;
ret = ERR_NO_IP;
goto fail;
}
return 0;
@@ -423,8 +446,6 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
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 */
for (i=0;i<sizeof(struct in6_addr);i++)
SA_IN6_U8_P(&rnd)[i] |= (SA_IN6_U8_P(&network)[i]);
@@ -436,44 +457,27 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
continue;
}
proc->ipv6->lip_len = sizeof(struct sockaddr_in6);
memcpy(&proc->ipv6->lip, &rnd, proc->ipv6->lip_len);
proc->ipv6->rip_len = sizeof(struct sockaddr_in6);
memcpy(&proc->ipv6->rip, &rnd, proc->ipv6->rip_len);
/* RIP = LIP + 1 */
memcpy(&tmp, &proc->ipv6->lip, sizeof(tmp));
proc->ipv6->rip_len = proc->ipv6->lip_len;
/* LIP = 1st network address */
memcpy(&proc->ipv6->lip, &network, sizeof(struct sockaddr_in6));
proc->ipv6->lip_len = sizeof(struct sockaddr_in6);
bignum_add(SA_IN6_U8_P(&tmp), sizeof(struct in6_addr), 1);
/* check if it exists in the hash table */
if (ip_lease_exists(s, &tmp, sizeof(struct sockaddr_in6)) != 0) {
mslog(s, proc, LOG_DEBUG, "cannot assign remote IP %s; it is in use.",
human_addr((void*)&tmp, sizeof(struct sockaddr_in6), buf, sizeof(buf)));
if (memcmp(SA_IN6_U8_P(&proc->ipv6->lip), SA_IN6_U8_P(&proc->ipv6->rip), sizeof(struct in6_addr)) == 0) {
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: %s",
human_addr((void*)&proc->ipv6->lip, proc->ipv6->lip_len, buf, sizeof(buf)));
human_addr((void*)&proc->ipv6->rip, proc->ipv6->rip_len, buf, sizeof(buf)));
if (icmp_ping6(s, (void*)&proc->ipv6->lip, (void*)&proc->ipv6->rip) == 0)
if (icmp_ping6(s, (void*)&proc->ipv6->rip) == 0)
break;
} while(1);
return 0;
fail:
talloc_free(proc->ipv6);
talloc_free(c_netmask);
proc->ipv6 = NULL;
return ret;