[dhcp6relay] Add retry mechanism for binding socket to interface ipv6 addresses (#10712)

This commit is contained in:
kellyyeh 2022-05-02 17:14:13 -07:00 committed by GitHub
parent a1e76d25b7
commit 243d0c73f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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));
} }
} }