@@ -1266,31 +1266,38 @@ static void add_listening_port(const NetworkInterface *interf, in_port_t port, s
12661266/* *
12671267 * Create a socket and bind it to a specific port number
12681268 * @param interface the interface to bind to
1269- * @param port the port number to bind to
1269+ * @param true if we was able to set up this interface
1270+ * false if we failed to set up this interface
12701271 */
1271- static int server_socket (const NetworkInterface * interf) {
1272+ static bool server_socket (const NetworkInterface& interf) {
12721273 SOCKET sfd;
1273- struct addrinfo hints;
1274- int success = 0 ;
1275- const char *host = NULL ;
1274+ addrinfo hints = {};
1275+
1276+ // Set to true when we create an IPv4 interface
1277+ bool ipv4 = false ;
1278+ // Set to true when we create an IPv6 interface
1279+ bool ipv6 = false ;
12761280
1277- memset (&hints, 0 , sizeof (hints));
12781281 hints.ai_flags = AI_PASSIVE;
12791282 hints.ai_protocol = IPPROTO_TCP;
12801283 hints.ai_socktype = SOCK_STREAM;
12811284
1282- if (interf-> ipv4 && interf-> ipv6 ) {
1285+ if (interf. ipv4 && interf. ipv6 ) {
12831286 hints.ai_family = AF_UNSPEC;
1284- } else if (interf-> ipv4 ) {
1287+ } else if (interf. ipv4 ) {
12851288 hints.ai_family = AF_INET;
1286- } else if (interf-> ipv6 ) {
1289+ } else if (interf. ipv6 ) {
12871290 hints.ai_family = AF_INET6;
1291+ } else {
1292+ throw std::invalid_argument (
1293+ " server_socket: can't create a socket without IPv4 or IPv6" );
12881294 }
12891295
1290- std::string port_buf = std::to_string (interf-> port );
1296+ std::string port_buf = std::to_string (interf. port );
12911297
1292- if (!interf->host .empty () && interf->host != " *" ) {
1293- host = interf->host .c_str ();
1298+ const char * host = nullptr ;
1299+ if (!interf.host .empty () && interf.host != " *" ) {
1300+ host = interf.host .c_str ();
12941301 }
12951302
12961303 struct addrinfo *ai;
@@ -1305,32 +1312,37 @@ static int server_socket(const NetworkInterface *interf) {
13051312 LOG_WARNING (" getaddrinfo(): {}" , cb_strerror (error));
13061313 }
13071314#endif
1308- return 1 ;
1315+ return false ;
13091316 }
13101317
1318+ // getaddrinfo may return multiple entries for a given name/port pair.
1319+ // Iterate over all of them and try to set up a listen object.
1320+ // We need at least _one_ entry per requested configuration (IPv4/6) in
1321+ // order to call it a success.
13111322 for (struct addrinfo * next = ai; next; next = next->ai_next ) {
1312- if ((sfd = new_server_socket (next, interf->tcp_nodelay )) == INVALID_SOCKET) {
1313- /* getaddrinfo can return "junk" addresses,
1314- * we make sure at least one works before erroring.
1315- */
1323+ if ((sfd = new_server_socket (next, interf.tcp_nodelay )) ==
1324+ INVALID_SOCKET) {
1325+ // getaddrinfo can return "junk" addresses,
13161326 continue ;
13171327 }
13181328
13191329 in_port_t listenport = 0 ;
13201330 if (bind (sfd, next->ai_addr , (socklen_t )next->ai_addrlen ) == SOCKET_ERROR) {
1321- error = cb::net::get_socket_error ();
1322- if (!cb::net::is_addrinuse (error)) {
1323- LOG_WARNING (" Failed to bind to address: {}" ,
1324- cb_strerror (error));
1325- safe_close (sfd);
1326- freeaddrinfo (ai);
1327- return 1 ;
1328- }
1331+ LOG_WARNING (" Failed to bind to address: {}" ,
1332+ cb_strerror (cb::net::get_socket_error ()));
13291333 safe_close (sfd);
13301334 continue ;
13311335 }
13321336
1333- success++;
1337+ // We've configured this port.
1338+ if (next->ai_addr ->sa_family == AF_INET) {
1339+ // We have at least one entry
1340+ ipv4 = true ;
1341+ } else if (next->ai_addr ->sa_family == AF_INET6) {
1342+ // We have at least one entry
1343+ ipv6 = true ;
1344+ }
1345+
13341346 if (next->ai_addr ->sa_family == AF_INET ||
13351347 next->ai_addr ->sa_family == AF_INET6) {
13361348 union {
@@ -1347,28 +1359,50 @@ static int server_socket(const NetworkInterface *interf) {
13471359 }
13481360 }
13491361
1350- auto * lconn = conn_new_server (sfd, listenport, next-> ai_addr -> sa_family ,
1351- * interf, main_base);
1362+ auto * lconn = conn_new_server (
1363+ sfd, listenport, next-> ai_addr -> sa_family , interf, main_base);
13521364 if (lconn == nullptr ) {
1353- FATAL_ERROR (EXIT_FAILURE, " Failed to create listening connection" );
1365+ FATAL_ERROR (
1366+ EXIT_FAILURE,
1367+ R"( Failed to create listening object: Host "{}" Port "{}" IPv{})" ,
1368+ interf.host .empty () ? " *" : interf.host ,
1369+ interf.port ,
1370+ next->ai_addr ->sa_family == AF_INET ? " 4" : " 6" );
13541371 }
13551372
13561373 lconn->setNext (listen_conn);
13571374 listen_conn = lconn;
13581375
13591376 stats.daemon_conns ++;
13601377 stats.curr_conns .fetch_add (1 , std::memory_order_relaxed);
1361- add_listening_port (interf, listenport, next->ai_addr ->sa_family );
1378+ add_listening_port (& interf, listenport, next->ai_addr ->sa_family );
13621379 }
13631380
13641381 freeaddrinfo (ai);
13651382
1366- /* Return zero iff we detected no errors in starting up connections */
1367- return success == 0 ;
1383+ bool ret = true ;
1384+
1385+ if (interf.ipv4 && !ipv4) {
1386+ // Failed to create an IPv4 port
1387+ LOG_CRITICAL (R"( Failed to create IPv4 port for "{}:{}")" ,
1388+ interf.host .empty () ? " *" : interf.host ,
1389+ interf.port );
1390+ ret = false ;
1391+ }
1392+
1393+ if (interf.ipv6 && !ipv6) {
1394+ // Failed to create an IPv6 oprt
1395+ LOG_CRITICAL (R"( Failed to create IPv6 port for "{}:{}")" ,
1396+ interf.host .empty () ? " *" : interf.host ,
1397+ interf.port );
1398+ ret = false ;
1399+ }
1400+
1401+ return ret;
13681402}
13691403
1370- static int server_sockets (bool management) {
1371- int ret = 0 ;
1404+ static bool server_sockets (bool management) {
1405+ bool success = true ;
13721406
13731407 if (management) {
13741408 LOG_INFO (" Enable management port(s)" );
@@ -1378,25 +1412,29 @@ static int server_sockets(bool management) {
13781412
13791413 for (auto & interface : settings.getInterfaces ()) {
13801414 if (management && interface.management ) {
1381- ret |= server_socket (&interface);
1415+ if (!server_socket (interface)) {
1416+ success = false ;
1417+ }
13821418 } else if (!management && !interface.management ) {
1383- ret |= server_socket (&interface);
1419+ if (!server_socket (interface)) {
1420+ success = false ;
1421+ }
13841422 }
13851423 }
13861424
1387- return ret ;
1425+ return success ;
13881426}
13891427
13901428static void create_listen_sockets (bool management) {
1391- if (server_sockets (management)) {
1392- FATAL_ERROR (EX_OSERR, " Failed to create listening socket" );
1429+ if (! server_sockets (management)) {
1430+ FATAL_ERROR (EX_OSERR, " Failed to create listening socket(s) " );
13931431 }
13941432
13951433 if (management) {
13961434 // the client is not expecting us to update the port set at
13971435 // later time, so enable all ports immediately
1398- if (server_sockets (false )) {
1399- FATAL_ERROR (EX_OSERR, " Failed to create listening socket" );
1436+ if (! server_sockets (false )) {
1437+ FATAL_ERROR (EX_OSERR, " Failed to create listening socket(s) " );
14001438 }
14011439 }
14021440
0 commit comments