662
669
if (!with_ggz) { /* No listening socket when using GGZ. */
663
if (FD_ISSET(sock, &exceptfs)) { /* handle Ctrl-Z suspend/resume */
671
for (i = 0; i < listen_count; i++) {
672
if (FD_ISSET(listen_socks[i], &exceptfs)) {
677
if (excepting) { /* handle Ctrl-Z suspend/resume */
666
if (FD_ISSET(sock, &readfs)) { /* new players connects */
667
freelog(LOG_VERBOSE, "got new connection");
668
if (-1 == server_accept_connection(sock)) {
669
/* There will be a LOG_ERROR message from
670
* server_accept_connection() if something
671
* goes wrong, so no need to make another
672
* error-level message here. */
673
freelog(LOG_VERBOSE, "failed accepting connection");
680
for (i = 0; i < listen_count; i++) {
682
if (FD_ISSET(s, &readfs)) { /* new players connects */
683
freelog(LOG_VERBOSE, "got new connection");
684
if (-1 == server_accept_connection(s)) {
685
/* There will be a LOG_ERROR message from
686
* server_accept_connection() if something
687
* goes wrong, so no need to make another
688
* error-level message here. */
689
freelog(LOG_VERBOSE, "failed accepting connection");
888
905
#ifdef IPV6_SUPPORT
889
if (!getnameinfo(&fromend.saddr, fromlen, host, NI_MAXHOST,
890
service, NI_MAXSERV, NI_NUMERICSERV)) {
906
nameinfo = (0 == getnameinfo(&fromend.saddr, fromlen, host, NI_MAXHOST,
907
service, NI_MAXSERV, NI_NUMERICSERV)
893
909
#else /* IPv6 support */
895
gethostbyaddr((char *) &fromend.saddr_in4.sin_addr,
896
sizeof(fromend.saddr_in4.sin_addr), AF_INET);
910
from = gethostbyaddr((char *) &fromend.saddr_in4.sin_addr,
911
sizeof(fromend.saddr_in4.sin_addr), AF_INET);
912
if (NULL != from && '\0' != from->h_name[0]) {
898
913
host = from->h_name;
901
916
#endif /* IPv6 support */
903
918
return server_make_connection(new_sock,
904
(nameinfo ? host : dst), dst);
919
(nameinfo ? host : dst), dst);
907
922
/********************************************************************
963
978
int server_open_socket(void)
965
980
/* setup socket address */
966
union fc_sockaddr src;
981
union fc_sockaddr names[2];
967
982
union fc_sockaddr addr;
968
983
struct ip_mreq mreq4;
984
const char *cause, *group;
985
int i, j, name_count, on, s;
973
988
#ifdef IPV6_SUPPORT
974
989
struct ipv6_mreq mreq6;
977
if (!net_lookup_service(srvarg.bind_addr, srvarg.port, &src, FALSE)) {
992
/* Lookup addresses to bind. */
993
if (!net_lookup_service(srvarg.bind_addr, srvarg.port, &names[0], FALSE)) {
978
994
freelog(LOG_FATAL, _("Server: bad address: <%s:%d>."),
979
995
srvarg.bind_addr, srvarg.port);
980
996
exit(EXIT_FAILURE);
983
/* Create socket for client connections. */
984
if((sock = socket(src.saddr.sa_family, SOCK_STREAM, 0)) == -1) {
985
fc_errno error = fc_get_errno();
989
bool still_error = TRUE;
991
if (error == EAFNOSUPPORT && src.saddr.sa_family == AF_INET6 && srvarg.bind_addr == NULL) {
992
/* Let's try IPv4 socket instead */
993
freelog(LOG_NORMAL, _("Cannot open IPv6 socket, trying IPv4 instead"));
995
if (!net_lookup_service(NULL, srvarg.port, &src, TRUE)) {
996
freelog(LOG_FATAL, _("IPv4 service lookup failed <%d>."),
1000
if (names[0].saddr.sa_family == AF_INET6) {
1001
/* net_lookup_service() prefers IPv6 address.
1002
* Check if there is also IPv4 address.
1003
* TODO: This would be easier using getaddrinfo() */
1004
if (net_lookup_service(srvarg.bind_addr, srvarg.port,
1005
&names[1], TRUE /* force IPv4 */)) {
1014
/* Loop to create sockets, bind, listen. */
1015
listen_socks = fc_calloc(name_count, sizeof(listen_socks[0]));
1017
for (i = 0; i < name_count; i++) {
1019
/* Create socket for client connections. */
1020
s = socket(names[i].saddr.sa_family, SOCK_STREAM, 0);
1022
/* Probably EAFNOSUPPORT or EPROTONOSUPPORT.
1023
* Kernel might have disabled AF_INET6. */
1028
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
1029
(char *)&on, sizeof(on)) == -1) {
1030
freelog(LOG_ERROR, "setsockopt SO_REUSEADDR failed: %s",
1031
fc_strerror(fc_get_errno()));
1032
sockaddr_debug(&names[i]);
1035
/* AF_INET6 sockets should use IPv6 only,
1036
* without stealing IPv4 from AF_INET sockets. */
1038
if (names[i].saddr.sa_family == AF_INET6) {
1040
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
1041
(char *)&on, sizeof(on)) == -1) {
1042
freelog(LOG_ERROR, "setsockopt IPV6_V6ONLY failed: %s",
1043
fc_strerror(fc_get_errno()));
1044
sockaddr_debug(&names[i]);
1001
/* Create socket for client connections. */
1002
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
1003
fc_errno error2 = fc_get_errno();
1004
freelog(LOG_ERROR, "Even IPv4 socket failed: %s", fc_strerror(error2));
1050
if (bind(s, &names[i].saddr, sockaddr_size(&names[i])) == -1) {
1053
if (fc_get_errno() == EADDRNOTAVAIL) {
1054
/* Close only this socket. This address is not available.
1055
* This can happen with the IPv6 wildcard address if this
1056
* machine has no IPv6 interfaces. */
1006
still_error = FALSE;
1060
/* Close all sockets. Another program might have bound to
1061
* one of our addresses, and might hijack some of our
1064
for (j = 0; j < listen_count; j++) {
1065
fc_closesocket(listen_socks[j]);
1011
#endif /* EAFNOSUPPORT */
1012
#endif /* IPv6 support */
1014
die("socket failed: %s", fc_strerror(error));
1019
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1020
(char *)&opt, sizeof(opt)) == -1) {
1021
freelog(LOG_ERROR, "SO_REUSEADDR failed: %s", fc_strerror(fc_get_errno()));
1024
if(bind(sock, &src.saddr, sockaddr_size(&src)) == -1) {
1025
freelog(LOG_FATAL, "Server bind failed: %s", fc_strerror(fc_get_errno()));
1026
sockaddr_debug(&src);
1030
if(listen(sock, MAX_NUM_CONNECTIONS) == -1) {
1031
freelog(LOG_FATAL, "listen failed: %s", fc_strerror(fc_get_errno()));
1072
if (listen(s, MAX_NUM_CONNECTIONS) == -1) {
1078
listen_socks[listen_count] = s;
1082
if (listen_count == 0) {
1083
freelog(LOG_FATAL, "%s failed: %s", cause, fc_strerror(fc_get_errno()));
1084
for (i = 0; i < name_count; i++) {
1085
sockaddr_debug(&names[i]);
1032
1087
exit(EXIT_FAILURE);