30#ifdef HAVE_NETINET_IN_H
31#include <netinet/in.h>
33#ifdef HAVE_ARPA_INET_H
42#ifdef HAVE_SYS_IOCTL_H
47#elif defined(HAVE_SYS_SIGNAL_H)
48#include <sys/signal.h>
50#ifdef FREECIV_MSWINDOWS
64#define INADDR_NONE 0xffffffff
67#ifdef HAVE_GETADDRINFO
69#define FC_AI_NUMERICSERV AI_NUMERICSERV
71#define FC_AI_NUMERICSERV 0
75#ifdef FREECIV_HAVE_WINSOCK
79static void set_socket_errno(
void)
81 int err = WSAGetLastError();
90 case WSAEADDRNOTAVAIL:
111 result = connect(sockfd, serv_addr, addrlen);
113#ifdef FREECIV_HAVE_WINSOCK
125int fc_select(
int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
130 result = select(
n, readfds, writefds, exceptfds, timeout);
132#ifdef FREECIV_HAVE_WINSOCK
148#ifdef FREECIV_HAVE_WINSOCK
149 result = recv(sock, buf,
size, 0);
154 result = read(sock, buf,
size);
167#ifdef FREECIV_HAVE_WINSOCK
168 result = send(sock, buf,
size, 0);
174 result = send(sock, buf,
size, MSG_NOSIGNAL);
176 result = write(sock, buf,
size);
188#ifdef FREECIV_HAVE_WINSOCK
200#ifdef FREECIV_HAVE_WINSOCK
203 if (WSAStartup(MAKEWORD(1, 1), &wsa) != 0) {
210 (void)
signal(SIGPIPE, SIG_IGN);
219#ifdef FREECIV_HAVE_WINSOCK
229#ifdef NONBLOCKING_SOCKETS
230#ifdef FREECIV_HAVE_WINSOCK
237 ioctlsocket(sockfd, FIONBIO, &b);
242 if ((f_set = fcntl(sockfd, F_GETFL)) == -1) {
248 if (fcntl(sockfd, F_SETFL, f_set) == -1) {
255 if (ioctl(sockfd, FIONBIO, (
char*)&value) == -1) {
262 log_warn(
"NONBLOCKING_SOCKETS not available");
271#ifdef FREECIV_IPV6_SUPPORT
272 char buf[INET6_ADDRSTRLEN] =
"Unknown";
274 if (addr->
saddr.sa_family == AF_INET6) {
275 inet_ntop(AF_INET6, &addr->saddr_in6.sin6_addr, buf, INET6_ADDRSTRLEN);
276 log_base(lvl,
"Host: %s, Port: %d (IPv6)",
277 buf, ntohs(addr->saddr_in6.sin6_port));
279 }
else if (addr->
saddr.sa_family == AF_INET) {
280 inet_ntop(AF_INET, &addr->
saddr_in4.sin_addr, buf, INET_ADDRSTRLEN);
281 log_base(lvl,
"Host: %s, Port: %d (IPv4)",
286 if (addr->
saddr.sa_family == AF_INET) {
289 buf = inet_ntoa(addr->
saddr_in4.sin_addr);
298 log_error(
"Unsupported address family in sockaddr_debug()");
307#ifdef FREECIV_MSWINDOWS
308 return sizeof(*addr);
310#ifdef FREECIV_IPV6_SUPPORT
311 if (addr->
saddr.sa_family == AF_INET6) {
312 return sizeof(addr->saddr_in6);
315 if (addr->
saddr.sa_family == AF_INET) {
320 log_error(
"Unsupported address family in sockaddr_size()");
332#ifdef FREECIV_IPV6_SUPPORT
333 if (addr->
saddr.sa_family == AF_INET6) {
341#ifdef HAVE_GETADDRINFO
345static struct fc_sockaddr_list *net_lookup_getaddrinfo(
const char *
name,
349 struct addrinfo hints;
350 struct addrinfo *res;
354 struct fc_sockaddr_list *addrs =
355 fc_sockaddr_list_new_full((fc_sockaddr_list_free_fn_t) free);
365#ifndef FREECIV_IPV6_SUPPORT
378 fc_snprintf(servname,
sizeof(servname),
"%d", port);
381 memset(&hints, 0,
sizeof(hints));
382 hints.ai_family = gafam;
383 hints.ai_socktype = SOCK_DGRAM;
384 hints.ai_flags = AI_PASSIVE | FC_AI_NUMERICSERV;
385 err = getaddrinfo(
name, servname, &hints, &res);
388 struct addrinfo *current = res;
390 while (current != NULL) {
395 memcpy(caddr, current->ai_addr, current->ai_addrlen);
397 fc_sockaddr_list_append(addrs, caddr);
399 current = current->ai_next;
416#ifdef HAVE_GETADDRINFO
417 return net_lookup_getaddrinfo(
name, port, family);
420 struct sockaddr_in *sock4;
422 struct fc_sockaddr_list *addrs = fc_sockaddr_list_new();
429 result->
saddr.sa_family = AF_INET;
430 sock4->sin_port = htons(port);
433 sock4->sin_addr.s_addr = htonl(INADDR_ANY);
434 fc_sockaddr_list_append(addrs, result);
440 fc_sockaddr_list_append(addrs, result);
445 hp = gethostbyname(
name);
446 if (!hp || hp->h_addrtype != AF_INET) {
452 memcpy(&sock4->sin_addr, hp->h_addr, hp->h_length);
453 fc_sockaddr_list_append(addrs, result);
466bool fc_inet_aton(
const char *cp,
struct in_addr *inp,
bool addr_none_ok)
468#ifdef FREECIV_IPV6_SUPPORT
470 if (!inet_pton(AF_INET, cp, &inp->s_addr)) {
475 if (!inet_aton(cp, inp)) {
479 inp->s_addr = inet_addr(cp);
498 fp = fdopen(sock,
"r+b");
501 log_error(
"socket %d: failed to fdopen()", sock);
506 if (fwrite(buf, 1,
size, fp) !=
size) {
507 log_error(
"socket %d: write error", sock);
518#ifdef FREECIV_MSWINDOWS
522 char filename[MAX_PATH];
524 GetTempPath(
sizeof(filename), filename);
542 if (fwrite(tmp, 1,
n, fp) !=
n) {
543 log_error(
"socket %d: write error", sock);
562 char *net_interface,
bool not_avail_ok)
569#ifndef FREECIV_IPV6_SUPPORT
577#ifdef FREECIV_IPV6_SUPPORT
583 gafamily = AF_UNSPEC;
587 log_error(
"Port from unsupported address family requested!");
592 for (port = starting_port; !found && highest_port > port; port++) {
594#ifdef HAVE_GETADDRINFO
595 struct addrinfo hints;
598 struct addrinfo *res;
600 fc_snprintf(servname,
sizeof(servname),
"%d", port);
602 memset(&hints, 0,
sizeof(hints));
603 hints.ai_family = gafamily;
604 hints.ai_socktype = SOCK_DGRAM;
605 hints.ai_flags = AI_PASSIVE | FC_AI_NUMERICSERV;
607 err = getaddrinfo(net_interface, servname, &hints, &res);
609 struct addrinfo *current = res;
610 bool unusable =
FALSE;
612 while (current != NULL && !unusable) {
613 s = socket(current->ai_family, SOCK_STREAM, 0);
618 if (bind(s, current->ai_addr, current->ai_addrlen) != 0) {
624 current = current->ai_next;
630 if (!unusable && res != NULL) {
636 struct sockaddr_in *sock4;
638 s = socket(gafamily, SOCK_STREAM, 0);
641 memset(&tmp, 0,
sizeof(tmp));
642 sock4->sin_family = AF_INET;
643 sock4->sin_port = htons(port);
644 if (net_interface != NULL) {
648 hp = gethostbyname(net_interface);
650 log_error(
"No hostent for %s!", net_interface);
654 if (hp->h_addrtype != AF_INET) {
655 log_error(
"Requested IPv4 address for %s, got something else! (%d)",
656 net_interface, hp->h_addrtype);
661 memcpy(&sock4->sin_addr, hp->h_addr, hp->h_length);
664 sock4->sin_addr.s_addr = htonl(INADDR_ANY);
676 log_error(
"None of the ports %d - %d is available.",
677 starting_port, highest_port);
void bugreport_request(const char *reason_format,...)
enum announce_type announce
fz_FILE * fz_from_stream(FILE *stream)
#define log_warn(message,...)
#define fc_assert(condition)
#define fc_assert_action(condition, action)
#define log_base(level, message,...)
#define log_error(message,...)
void fc_shutdown_network(void)
bool fc_inet_aton(const char *cp, struct in_addr *inp, bool addr_none_ok)
bool sockaddr_ipv6(union fc_sockaddr *addr)
struct fc_sockaddr_list * net_lookup_service(const char *name, int port, enum fc_addr_family family)
void fc_init_network(void)
void fc_closesocket(int sock)
void sockaddr_debug(union fc_sockaddr *addr, enum log_level lvl)
int find_next_free_port(int starting_port, int highest_port, enum fc_addr_family family, char *net_interface, bool not_avail_ok)
int addr_family_for_announce_type(enum announce_type announce)
int sockaddr_size(union fc_sockaddr *addr)
int fc_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
int fc_readsocket(int sock, void *buf, size_t size)
int fc_writesocket(int sock, const void *buf, size_t size)
void fc_nonblock(int sockfd)
int fc_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, fc_timeval *timeout)
fz_FILE * fc_querysocket(int sock, void *buf, size_t size)
struct timeval fc_timeval
int fc_snprintf(char *str, size_t n, const char *format,...)
const char * fc_strerror(fc_errno err)
FILE * fc_fopen(const char *filename, const char *opentype)
fc_errno fc_get_errno(void)
#define sz_strlcat(dest, src)
struct sockaddr_in saddr_in4