When using socket functions, "sockerrno" is supposed to be used to
retrieve the error code as opposed to "errno", so that it is translated
to the correct call on Windows (WSAGetLastError() - Windows does not
update errno on socket errors). Unfortunately, the use of sockerrno is
inconsistent throughout the tinc codebase, as errno is often used
incorrectly on socket-related calls.
This commit fixes these oversights, which improves socket error
handling on Windows.
#ifndef HAVE_MINGW
int unix_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if(unix_fd < 0) {
#ifndef HAVE_MINGW
int unix_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if(unix_fd < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not create UNIX socket: %s", sockstrerror(errno));
+ logger(DEBUG_ALWAYS, LOG_ERR, "Could not create UNIX socket: %s", sockstrerror(sockerrno));
umask(mask);
if(result < 0) {
umask(mask);
if(result < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not bind UNIX socket to %s: %s", unixsocketname, sockstrerror(errno));
+ logger(DEBUG_ALWAYS, LOG_ERR, "Could not bind UNIX socket to %s: %s", unixsocketname, sockstrerror(sockerrno));
return false;
}
if(listen(unix_fd, 3) < 0) {
return false;
}
if(listen(unix_fd, 3) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not listen on UNIX socket %s: %s", unixsocketname, sockstrerror(errno));
+ logger(DEBUG_ALWAYS, LOG_ERR, "Could not listen on UNIX socket %s: %s", unixsocketname, sockstrerror(sockerrno));
- if(sockwouldblock(errno))
+ if(sockwouldblock(sockerrno))
continue;
else
return false;
continue;
else
return false;
inlen = recv(c->socket, inbuf, sizeof inbuf - c->inbuf.len, 0);
if(inlen <= 0) {
inlen = recv(c->socket, inbuf, sizeof inbuf - c->inbuf.len, 0);
if(inlen <= 0) {
+ if(!inlen || !sockerrno) {
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)",
c->name, c->hostname);
} else if(sockwouldblock(sockerrno))
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)",
c->name, c->hostname);
} else if(sockwouldblock(sockerrno))
if((lenin = recv(device_fd, (void *)packet->data, MTU, 0)) <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
if((lenin = recv(device_fd, (void *)packet->data, MTU, 0)) <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
- device, strerror(errno));
+ device, sockstrerror(sockerrno));
if(sendto(device_fd, (void *)packet->data, packet->len, 0, ai->ai_addr, ai->ai_addrlen) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
if(sendto(device_fd, (void *)packet->data, packet->len, 0, ai->ai_addr, ai->ai_addrlen) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
+ sockstrerror(sockerrno));
#endif
if(!event_loop()) {
#endif
if(!event_loop()) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", strerror(errno));
+ logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", sockstrerror(sockerrno));
priority = origpriority;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting outgoing packet priority to %d", priority);
if(setsockopt(listen_socket[n->sock].udp.fd, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */
priority = origpriority;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting outgoing packet priority to %d", priority);
if(setsockopt(listen_socket[n->sock].udp.fd, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */
- logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno));
+ logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", sockstrerror(sockerrno));
return false;
}
if(gethostname(hostname, sizeof hostname) || !*hostname) {
return false;
}
if(gethostname(hostname, sizeof hostname) || !*hostname) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not get hostname: %s\n", strerror(errno));
+ logger(DEBUG_ALWAYS, LOG_ERR, "Could not get hostname: %s\n", sockstrerror(sockerrno));
return false;
}
hostname[31] = 0;
return false;
}
hostname[31] = 0;
for(int i = 0; i < listen_sockets; i++) {
salen = sizeof sa;
if(getsockname(i + 3, &sa.sa, &salen) < 0) {
for(int i = 0; i < listen_sockets; i++) {
salen = sizeof sa;
if(getsockname(i + 3, &sa.sa, &salen) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(errno));
+ logger(DEBUG_ALWAYS, LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(sockerrno));
status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr));
if(status) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface,
status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr));
if(status) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface,
+ sockstrerror(sockerrno));
return false;
}
#else /* if !defined(SOL_SOCKET) || !defined(SO_BINDTODEVICE) */
return false;
}
#else /* if !defined(SOL_SOCKET) || !defined(SO_BINDTODEVICE) */
sa.in6.sin6_port = 0;
if(bind(c->socket, &sa.sa, SALEN(sa.sa))) {
sa.in6.sin6_port = 0;
if(bind(c->socket, &sa.sa, SALEN(sa.sa))) {
- logger(DEBUG_CONNECTIONS, LOG_WARNING, "Can't bind outgoing socket: %s", strerror(errno));
+ logger(DEBUG_CONNECTIONS, LOG_WARNING, "Can't bind outgoing socket: %s", sockstrerror(sockerrno));
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof ifr)) {
closesocket(nfd);
logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface,
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof ifr)) {
closesocket(nfd);
logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface,
+ sockstrerror(sockerrno));
setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof option);
if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf)))
setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof option);
if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf)))
- logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, strerror(errno));
+ logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, sockstrerror(sockerrno));
if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf)))
if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf)))
- logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, strerror(errno));
+ logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, sockstrerror(sockerrno));
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
if(sa->sa.sa_family == AF_INET6)
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
if(sa->sa.sa_family == AF_INET6)
int fd[2];
if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
int fd[2];
if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not create socketpair: %s", strerror(errno));
+ logger(DEBUG_ALWAYS, LOG_ERR, "Could not create socketpair: %s", sockstrerror(sockerrno));
ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, 0);
if(outlen <= 0) {
ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, 0);
if(outlen <= 0) {
- if(!errno || errno == EPIPE) {
+ if(!sockerrno || sockerrno == EPIPE) {
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)", c->name, c->hostname);
} else if(sockwouldblock(sockerrno)) {
logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Sending %d bytes to %s (%s) would block", c->outbuf.len - c->outbuf.offset, c->name, c->hostname);
return;
} else {
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)", c->name, c->hostname);
} else if(sockwouldblock(sockerrno)) {
logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Sending %d bytes to %s (%s) would block", c->outbuf.len - c->outbuf.offset, c->name, c->hostname);
return;
} else {
- logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not send %d bytes of data to %s (%s): %s", c->outbuf.len - c->outbuf.offset, c->name, c->hostname, strerror(errno));
+ logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not send %d bytes of data to %s (%s): %s", c->outbuf.len - c->outbuf.offset, c->name, c->hostname, sockstrerror(sockerrno));
}
terminate_connection(c, c->status.active);
}
terminate_connection(c, c->status.active);
int fd[2];
if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
int fd[2];
if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
- fprintf(stderr, "Could not create a UNIX socket pair: %s\n", strerror(errno));
+ fprintf(stderr, "Could not create a UNIX socket pair: %s\n", sockstrerror(sockerrno));
close(fd[1]);
if(socketpair(AF_UNIX, SOCK_DGRAM, 0, fd)) {
close(fd[1]);
if(socketpair(AF_UNIX, SOCK_DGRAM, 0, fd)) {
- fprintf(stderr, "Could not create a UNIX socket pair: %s\n", strerror(errno));
+ fprintf(stderr, "Could not create a UNIX socket pair: %s\n", sockstrerror(sockerrno));
hint.ai_flags = initiator ? 0 : AI_PASSIVE;
if(getaddrinfo(initiator ? argv[3] : NULL, initiator ? argv[4] : argv[3], &hint, &ai) || !ai) {
hint.ai_flags = initiator ? 0 : AI_PASSIVE;
if(getaddrinfo(initiator ? argv[3] : NULL, initiator ? argv[4] : argv[3], &hint, &ai) || !ai) {
- fprintf(stderr, "getaddrinfo() failed: %s\n", strerror(errno));
+ fprintf(stderr, "getaddrinfo() failed: %s\n", sockstrerror(sockerrno));
return 1;
}
int sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if(sock < 0) {
return 1;
}
int sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if(sock < 0) {
- fprintf(stderr, "Could not create socket: %s\n", strerror(errno));
+ fprintf(stderr, "Could not create socket: %s\n", sockstrerror(sockerrno));
if(initiator) {
if(connect(sock, ai->ai_addr, ai->ai_addrlen)) {
if(initiator) {
if(connect(sock, ai->ai_addr, ai->ai_addrlen)) {
- fprintf(stderr, "Could not connect to peer: %s\n", strerror(errno));
+ fprintf(stderr, "Could not connect to peer: %s\n", sockstrerror(sockerrno));
return 1;
}
fprintf(stderr, "Connected\n");
} else {
if(bind(sock, ai->ai_addr, ai->ai_addrlen)) {
return 1;
}
fprintf(stderr, "Connected\n");
} else {
if(bind(sock, ai->ai_addr, ai->ai_addrlen)) {
- fprintf(stderr, "Could not bind socket: %s\n", strerror(errno));
+ fprintf(stderr, "Could not bind socket: %s\n", sockstrerror(sockerrno));
return 1;
}
if(!datagram) {
if(listen(sock, 1)) {
return 1;
}
if(!datagram) {
if(listen(sock, 1)) {
- fprintf(stderr, "Could not listen on socket: %s\n", strerror(errno));
+ fprintf(stderr, "Could not listen on socket: %s\n", sockstrerror(sockerrno));
return 1;
}
fprintf(stderr, "Listening...\n");
sock = accept(sock, NULL, NULL);
if(sock < 0) {
return 1;
}
fprintf(stderr, "Listening...\n");
sock = accept(sock, NULL, NULL);
if(sock < 0) {
- fprintf(stderr, "Could not accept connection: %s\n", strerror(errno));
+ fprintf(stderr, "Could not accept connection: %s\n", sockstrerror(sockerrno));
socklen_t addrlen = sizeof addr;
if(recvfrom(sock, buf, sizeof buf, MSG_PEEK, &addr, &addrlen) <= 0) {
socklen_t addrlen = sizeof addr;
if(recvfrom(sock, buf, sizeof buf, MSG_PEEK, &addr, &addrlen) <= 0) {
- fprintf(stderr, "Could not read from socket: %s\n", strerror(errno));
+ fprintf(stderr, "Could not read from socket: %s\n", sockstrerror(sockerrno));
return 1;
}
if(connect(sock, &addr, addrlen)) {
return 1;
}
if(connect(sock, &addr, addrlen)) {
- fprintf(stderr, "Could not accept connection: %s\n", strerror(errno));
+ fprintf(stderr, "Could not accept connection: %s\n", sockstrerror(sockerrno));
if(FD_ISSET(sock, &fds)) {
ssize_t len = recv(sock, buf, sizeof buf, 0);
if(len < 0) {
if(FD_ISSET(sock, &fds)) {
ssize_t len = recv(sock, buf, sizeof buf, 0);
if(len < 0) {
- fprintf(stderr, "Could not read from socket: %s\n", strerror(errno));
+ fprintf(stderr, "Could not read from socket: %s\n", sockstrerror(sockerrno));
return 1;
}
if(len == 0) {
return 1;
}
if(len == 0) {
while(!(newline = memchr(buffer, '\n', blen))) {
int result = recv(fd, buffer + blen, sizeof buffer - blen, 0);
while(!(newline = memchr(buffer, '\n', blen))) {
int result = recv(fd, buffer + blen, sizeof buffer - blen, 0);
- if(result == -1 && errno == EINTR)
+ if(result == -1 && sockerrno == EINTR)
continue;
else if(result <= 0)
return false;
continue;
else if(result <= 0)
return false;
while(blen < len) {
int result = recv(fd, buffer + blen, sizeof buffer - blen, 0);
while(blen < len) {
int result = recv(fd, buffer + blen, sizeof buffer - blen, 0);
- if(result == -1 && errno == EINTR)
+ if(result == -1 && sockerrno == EINTR)
continue;
else if(result <= 0)
return false;
continue;
else if(result <= 0)
return false;
while(blen) {
int result = send(fd, p, blen, MSG_NOSIGNAL);
while(blen) {
int result = send(fd, p, blen, MSG_NOSIGNAL);
- if(result == -1 && errno == EINTR)
+ if(result == -1 && sockerrno == EINTR)
continue;
else if(result <= 0)
return false;
continue;
else if(result <= 0)
return false;
if(getaddrinfo(host, port, &hints, &res) || !res) {
if(verbose)
if(getaddrinfo(host, port, &hints, &res) || !res) {
if(verbose)
- fprintf(stderr, "Cannot resolve %s port %s: %s", host, port, strerror(errno));
+ fprintf(stderr, "Cannot resolve %s port %s: %s", host, port, sockstrerror(sockerrno));