[dhcp6relay] Add retry mechanism for binding socket to interface ipv6 addresses (#10712)
This commit is contained in:
parent
a1e76d25b7
commit
243d0c73f9
@ -378,29 +378,33 @@ void prepare_socket(int *local_sock, int *server_sock, relay_config *config, int
|
|||||||
memset(&ll_addr, 0, sizeof(ll_addr));
|
memset(&ll_addr, 0, sizeof(ll_addr));
|
||||||
|
|
||||||
if ((*local_sock = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) {
|
if ((*local_sock = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) {
|
||||||
syslog(LOG_ERR, "socket: Failed to create socket\n");
|
syslog(LOG_ERR, "socket: Failed to create socket on interface %s\n", config->interface.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*server_sock= socket(AF_INET6, SOCK_DGRAM, 0)) == -1) {
|
if ((*server_sock= socket(AF_INET6, SOCK_DGRAM, 0)) == -1) {
|
||||||
syslog(LOG_ERR, "socket: Failed to create socket\n");
|
syslog(LOG_ERR, "socket: Failed to create socket on interface %s\n", config->interface.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int retry = 0;
|
||||||
|
bool bind_addr = false;
|
||||||
|
bool bind_ll_addr = false;
|
||||||
|
do {
|
||||||
if (getifaddrs(&ifa) == -1) {
|
if (getifaddrs(&ifa) == -1) {
|
||||||
syslog(LOG_WARNING, "getifaddrs: Unable to get network interfaces\n");
|
syslog(LOG_WARNING, "getifaddrs: Unable to get network interfaces with %s\n", strerror(errno));
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
ifa_tmp = ifa;
|
ifa_tmp = ifa;
|
||||||
while (ifa_tmp) {
|
while (ifa_tmp) {
|
||||||
if (ifa_tmp->ifa_addr->sa_family == AF_INET6) {
|
if ((ifa_tmp->ifa_addr->sa_family == AF_INET6) && (strcmp(ifa_tmp->ifa_name, config->interface.c_str()) == 0)) {
|
||||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6*) ifa_tmp->ifa_addr;
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6*) ifa_tmp->ifa_addr;
|
||||||
if((strcmp(ifa_tmp->ifa_name, config->interface.c_str()) == 0) && !IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr)) {
|
if(!IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr)) {
|
||||||
|
bind_addr = true;
|
||||||
in6->sin6_family = AF_INET6;
|
in6->sin6_family = AF_INET6;
|
||||||
in6->sin6_port = htons(RELAY_PORT);
|
in6->sin6_port = htons(RELAY_PORT);
|
||||||
addr = *in6;
|
addr = *in6;
|
||||||
}
|
}
|
||||||
if((strcmp(ifa_tmp->ifa_name, config->interface.c_str()) == 0) && IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr)) {
|
if(IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr)) {
|
||||||
|
bind_ll_addr = true;
|
||||||
in6->sin6_family = AF_INET6;
|
in6->sin6_family = AF_INET6;
|
||||||
in6->sin6_port = htons(RELAY_PORT);
|
in6->sin6_port = htons(RELAY_PORT);
|
||||||
ll_addr = *in6;
|
ll_addr = *in6;
|
||||||
@ -409,13 +413,22 @@ void prepare_socket(int *local_sock, int *server_sock, relay_config *config, int
|
|||||||
ifa_tmp = ifa_tmp->ifa_next;
|
ifa_tmp = ifa_tmp->ifa_next;
|
||||||
}
|
}
|
||||||
freeifaddrs(ifa);
|
freeifaddrs(ifa);
|
||||||
|
|
||||||
if (bind(*local_sock, (sockaddr *)&addr, sizeof(addr)) == -1) {
|
|
||||||
syslog(LOG_ERR, "bind: Failed to bind to socket\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind(*server_sock, (sockaddr *)&ll_addr, sizeof(addr)) == -1) {
|
if (bind_addr && bind_ll_addr) {
|
||||||
syslog(LOG_ERR, "bind: Failed to bind to socket\n");
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
syslog(LOG_WARNING, "Retry #%d to bind to sockets on interface %s\n", ++retry, config->interface.c_str());
|
||||||
|
sleep(5);
|
||||||
|
} while (retry < 6);
|
||||||
|
|
||||||
|
if ((!bind_addr) || (bind(*local_sock, (sockaddr *)&addr, sizeof(addr)) == -1)) {
|
||||||
|
syslog(LOG_ERR, "bind: Failed to bind socket to global ipv6 address on interface %s after %d retries with %s\n", config->interface.c_str(), retry, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!bind_ll_addr) || (bind(*server_sock, (sockaddr *)&ll_addr, sizeof(addr)) == -1)) {
|
||||||
|
syslog(LOG_ERR, "bind: Failed to bind socket to link local ipv6 address on interface %s after %d retries with %s\n", config->interface.c_str(), retry, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user