#include "fdutil.h"
#include "socket.h"
#include "addr-util.h"
+#include "internal.h"
/* this is a portability hack */
#ifndef IPV6_ADD_MEMBERSHIP
* mcast groups when the iface is down, but don't allow rejoining
* when it comes back up. This is an ugly workaround */
if (join)
- setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
+ setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void *)&mreq, sizeof(mreq));
- if (setsockopt(fd, IPPROTO_IP, join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
+ if (setsockopt(fd, IPPROTO_IP, join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, (void *)&mreq, sizeof(mreq)) < 0) {
catta_log_warn("%s failed: %s", join ? "IP_ADD_MEMBERSHIP" : "IP_DROP_MEMBERSHIP", strerror(errno));
return -1;
}
mreq6.ipv6mr_interface = idx;
if (join)
- setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6));
+ setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (void *)&mreq6, sizeof(mreq6));
- if (setsockopt(fd, IPPROTO_IPV6, join ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
+ if (setsockopt(fd, IPPROTO_IPV6, join ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, (void *)&mreq6, sizeof(mreq6)) < 0) {
catta_log_warn("%s failed: %s", join ? "IPV6_ADD_MEMBERSHIP" : "IPV6_DROP_MEMBERSHIP", strerror(errno));
return -1;
}
int yes;
yes = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("SO_REUSEADDR failed: %s", strerror(errno));
return -1;
}
#ifdef SO_REUSEPORT
yes = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)) < 0) {
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("SO_REUSEPORT failed: %s", strerror(errno));
return -1;
}
assert(sa);
assert(l > 0);
+#ifdef _WIN32
+ // Windows does not allow address reuse when SO_REUSEADDR was set after
+ // bind() on the first socket, so we must set it before.
+ // Note that this spoils the detection trickery below and the warning will
+ // not be logged.
+
+ if (reuseaddr(fd) < 0)
+ return -1;
+#endif
+
if (bind(fd, sa, l) < 0) {
if (errno != EADDRINUSE) {
#ifdef IP_PKTINFO
yes = 1;
- if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0) {
+ if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("IP_PKTINFO failed: %s", strerror(errno));
return -1;
}
#ifdef IP_RECVINTERFACE
yes = 1;
- if (setsockopt (fd, IPPROTO_IP, IP_RECVINTERFACE, &yes, sizeof(yes)) < 0) {
+ if (setsockopt (fd, IPPROTO_IP, IP_RECVINTERFACE, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("IP_RECVINTERFACE failed: %s", strerror(errno));
return -1;
}
#elif defined(IP_RECVIF)
yes = 1;
- if (setsockopt (fd, IPPROTO_IP, IP_RECVIF, &yes, sizeof(yes)) < 0) {
+ if (setsockopt (fd, IPPROTO_IP, IP_RECVIF, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("IP_RECVIF failed: %s", strerror(errno));
return -1;
}
#ifdef IP_RECVDSTADDR
yes = 1;
- if (setsockopt (fd, IPPROTO_IP, IP_RECVDSTADDR, &yes, sizeof(yes)) < 0) {
+ if (setsockopt (fd, IPPROTO_IP, IP_RECVDSTADDR, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("IP_RECVDSTADDR failed: %s", strerror(errno));
return -1;
}
#ifdef IP_RECVTTL
yes = 1;
- if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0) {
+ if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("IP_RECVTTL failed: %s", strerror(errno));
return -1;
}
#ifdef IPV6_RECVPKTINFO
yes = 1;
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &yes, sizeof(yes)) < 0) {
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("IPV6_RECVPKTINFO failed: %s", strerror(errno));
return -1;
}
#elif defined(IPV6_PKTINFO)
yes = 1;
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &yes, sizeof(yes)) < 0) {
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("IPV6_PKTINFO failed: %s", strerror(errno));
return -1;
}
#ifdef IPV6_RECVHOPS
yes = 1;
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPS, &yes, sizeof(yes)) < 0) {
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPS, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("IPV6_RECVHOPS failed: %s", strerror(errno));
return -1;
}
#elif defined(IPV6_RECVHOPLIMIT)
yes = 1;
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &yes, sizeof(yes)) < 0) {
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("IPV6_RECVHOPLIMIT failed: %s", strerror(errno));
return -1;
}
#elif defined(IPV6_HOPLIMIT)
yes = 1;
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &yes, sizeof(yes)) < 0) {
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_HOPLIMIT, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("IPV6_HOPLIMIT failed: %s", strerror(errno));
return -1;
}
}
ttl = 255;
- if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) {
+ if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, sizeof(ttl)) < 0) {
catta_log_warn("IP_MULTICAST_TTL failed: %s", strerror(errno));
goto fail;
}
ittl = 255;
- if (setsockopt(fd, IPPROTO_IP, IP_TTL, &ittl, sizeof(ittl)) < 0) {
+ if (setsockopt(fd, IPPROTO_IP, IP_TTL, (void *)&ittl, sizeof(ittl)) < 0) {
catta_log_warn("IP_TTL failed: %s", strerror(errno));
goto fail;
}
cyes = 1;
- if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &cyes, sizeof(cyes)) < 0) {
+ if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *)&cyes, sizeof(cyes)) < 0) {
catta_log_warn("IP_MULTICAST_LOOP failed: %s", strerror(errno));
goto fail;
}
fail:
if (fd >= 0)
- close(fd);
+ closesocket(fd);
return -1;
}
}
ttl = 255;
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) < 0) {
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (void *)&ttl, sizeof(ttl)) < 0) {
catta_log_warn("IPV6_MULTICAST_HOPS failed: %s", strerror(errno));
goto fail;
}
ttl = 255;
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)) < 0) {
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (void *)&ttl, sizeof(ttl)) < 0) {
catta_log_warn("IPV6_UNICAST_HOPS failed: %s", strerror(errno));
goto fail;
}
yes = 1;
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) < 0) {
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("IPV6_V6ONLY failed: %s", strerror(errno));
goto fail;
}
yes = 1;
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("IPV6_MULTICAST_LOOP failed: %s", strerror(errno));
goto fail;
}
fail:
if (fd >= 0)
- close(fd);
+ closesocket(fd);
return -1;
}
if (errno == EINTR)
continue;
- if (errno != EAGAIN) {
+ if (errno != EAGAIN && errno != EWOULDBLOCK) {
char where[64];
struct sockaddr_in *sin = msg->msg_name;
int catta_send_dns_packet_ipv4(
int fd,
- CattaIfIndex interface,
+ CattaIfIndex iface,
CattaDnsPacket *p,
const CattaIPv4Address *src_address,
const CattaIPv4Address *dst_address,
msg.msg_controllen = 0;
#ifdef IP_PKTINFO
- if (interface > 0 || src_address) {
+ if (iface > 0 || src_address) {
struct in_pktinfo *pkti;
memset(cmsg_data, 0, sizeof(cmsg_data));
pkti = (struct in_pktinfo*) CMSG_DATA(cmsg);
- if (interface > 0)
- pkti->ipi_ifindex = interface;
+ if (iface > 0)
+ pkti->ipi_ifindex = iface;
+#ifdef HAVE_IPI_SPEC_DST
if (src_address)
pkti->ipi_spec_dst.s_addr = src_address->address;
+#endif
}
#elif defined(IP_MULTICAST_IF)
if (src_address) {
struct in_addr any = { INADDR_ANY };
- if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, src_address ? &src_address->address : &any, sizeof(struct in_addr)) < 0) {
+ if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (void *)(src_address ? &src_address->address : &any), sizeof(struct in_addr)) < 0) {
catta_log_warn("IP_MULTICAST_IF failed: %s", strerror(errno));
return -1;
}
int catta_send_dns_packet_ipv6(
int fd,
- CattaIfIndex interface,
+ CattaIfIndex iface,
CattaDnsPacket *p,
const CattaIPv6Address *src_address,
const CattaIPv6Address *dst_address,
msg.msg_iovlen = 1;
msg.msg_flags = 0;
- if (interface > 0 || src_address) {
+ if (iface > 0 || src_address) {
struct in6_pktinfo *pkti;
memset(cmsg_data, 0, sizeof(cmsg_data));
pkti = (struct in6_pktinfo*) CMSG_DATA(cmsg);
- if (interface > 0)
- pkti->ipi6_ifindex = interface;
+ if (iface > 0)
+ pkti->ipi6_ifindex = iface;
if (src_address)
memcpy(&pkti->ipi6_addr, src_address->address, sizeof(src_address->address));
fail:
if (fd >= 0)
- close(fd);
+ closesocket(fd);
return -1;
}
}
yes = 1;
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) < 0) {
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes)) < 0) {
catta_log_warn("IPV6_V6ONLY failed: %s", strerror(errno));
goto fail;
}
fail:
if (fd >= 0)
- close(fd);
+ closesocket(fd);
return -1;
}