mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 08:46:58 +08:00
always assign the first network address as PtP address
This commit is contained in:
26
src/common.c
26
src/common.c
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
126
src/ip-lease.c
126
src/ip-lease.c
@@ -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);
|
||||
|
||||
/* RIP = LIP + 1 */
|
||||
memcpy(&tmp, &proc->ipv4->lip, sizeof(struct sockaddr_in));
|
||||
bignum_add(SA_IN_U8_P(&tmp), sizeof(struct in_addr), 1);
|
||||
|
||||
/* 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)));
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(&proc->ipv4->rip, &tmp, sizeof(struct sockaddr_in));
|
||||
memcpy(&proc->ipv4->rip, &rnd, 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]);
|
||||
/* LIP = 1st network address */
|
||||
memcpy(&proc->ipv4->lip, &network, sizeof(struct sockaddr_in));
|
||||
proc->ipv4->lip_len = sizeof(struct sockaddr_in);
|
||||
|
||||
/* 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(SA_IN_U8_P(&proc->ipv4->lip), SA_IN_U8_P(&proc->ipv4->rip), 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)));
|
||||
human_addr((void*)&proc->ipv4->rip, proc->ipv4->rip_len, buf, sizeof(buf)));
|
||||
|
||||
if (icmp_ping4(s, (void*)&proc->ipv4->lip, (void*)&proc->ipv4->rip) == 0)
|
||||
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,19 +336,19 @@ 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 =
|
||||
@@ -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->rip_len = sizeof(struct sockaddr_in6);
|
||||
memcpy(&proc->ipv6->rip, &rnd, proc->ipv6->rip_len);
|
||||
|
||||
/* LIP = 1st network address */
|
||||
memcpy(&proc->ipv6->lip, &network, sizeof(struct sockaddr_in6));
|
||||
proc->ipv6->lip_len = sizeof(struct sockaddr_in6);
|
||||
memcpy(&proc->ipv6->lip, &rnd, proc->ipv6->lip_len);
|
||||
|
||||
/* RIP = LIP + 1 */
|
||||
memcpy(&tmp, &proc->ipv6->lip, sizeof(tmp));
|
||||
proc->ipv6->rip_len = proc->ipv6->lip_len;
|
||||
|
||||
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)));
|
||||
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) {
|
||||
if (memcmp(SA_IN6_U8_P(&proc->ipv6->lip), SA_IN6_U8_P(&proc->ipv6->rip), 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;
|
||||
|
||||
Reference in New Issue
Block a user