33 struct sockaddr_storage from_addr;
36 struct sock_extended_err *ee;
39 qboolean found = qfalse;
42 memset(&from_addr, 0,
sizeof(from_addr));
44 memset(&
msg, 0,
sizeof(
msg));
45 msg.msg_name = &from_addr;
46 msg.msg_namelen =
sizeof(from_addr);
47 msg.msg_control = buffer;
48 msg.msg_controllen =
sizeof(buffer);
50 if (recvmsg(sock, &
msg, MSG_ERRQUEUE) == -1) {
51 if (errno != EWOULDBLOCK)
52 Com_DPrintf(
"%s: %s\n", __func__, strerror(errno));
56 if (!(
msg.msg_flags & MSG_ERRQUEUE)) {
57 Com_DPrintf(
"%s: no extended error received\n", __func__);
62 for (cmsg = CMSG_FIRSTHDR(&
msg);
64 cmsg = CMSG_NXTHDR(&
msg, cmsg)) {
65 if (cmsg->cmsg_level != IPPROTO_IP &&
66 cmsg->cmsg_level != IPPROTO_IPV6) {
69 if (cmsg->cmsg_type != IP_RECVERR &&
70 cmsg->cmsg_type != IPV6_RECVERR) {
73 ee = (
struct sock_extended_err *)CMSG_DATA(cmsg);
74 if (ee->ee_origin == SO_EE_ORIGIN_ICMP ||
75 ee->ee_origin == SO_EE_ORIGIN_ICMP6) {
81 Com_DPrintf(
"%s: no ICMP error found\n", __func__);
88 if (to != NULL && NET_IsEqualBaseAdr(&from, to) &&
89 (from.port == 0 || from.port == to->port)) {
90 Com_DPrintf(
"%s: found offending address: %s\n", __func__,
96 NET_ErrorEvent(sock, &from, ee->ee_errno, ee->ee_info);
99 return !!tries && !found;
106 size_t len, netadr_t *from)
108 struct sockaddr_storage addr;
114 memset(&addr, 0,
sizeof(addr));
115 addrlen =
sizeof(addr);
116 ret = recvfrom(sock, data, len, 0,
117 (
struct sockaddr *)&addr, &addrlen);
138 size_t len,
const netadr_t *to)
140 struct sockaddr_storage addr;
148 ret = sendto(sock, data, len, 0,
149 (
struct sockaddr *)&addr, addrlen);
175 static ssize_t
os_recv(qsocket_t sock,
void *data,
size_t len,
int flags)
177 ssize_t ret = recv(sock, data, len, flags);
185 static ssize_t
os_send(qsocket_t sock,
const void *data,
size_t len,
int flags)
187 ssize_t ret = send(sock, data, len, flags);
197 if (listen(sock, backlog) == -1) {
205 static neterr_t
os_accept(qsocket_t sock, qsocket_t *newsock, netadr_t *from)
207 struct sockaddr_storage addr;
211 memset(&addr, 0,
sizeof(addr));
212 addrlen =
sizeof(addr);
213 s = accept(sock, (
struct sockaddr *)&addr, &addrlen);
226 static neterr_t
os_connect(qsocket_t sock,
const netadr_t *to)
228 struct sockaddr_storage addr;
233 if (connect(sock, (
struct sockaddr *)&addr, addrlen) == -1) {
246 if (ioctl(sock, FIONBIO, &val) == -1) {
256 if (setsockopt(sock,
level, name, &val,
sizeof(val)) == -1) {
266 socklen_t _optlen =
sizeof(*val);
268 if (getsockopt(sock,
level, name, val, &_optlen) == -1) {
276 static neterr_t
os_bind(qsocket_t sock,
const struct sockaddr *addr,
size_t addrlen)
278 if (bind(sock, addr, addrlen) == -1) {
288 struct sockaddr_storage addr;
291 memset(&addr, 0,
sizeof(addr));
292 addrlen =
sizeof(addr);
293 if (getsockname(sock, (
struct sockaddr *)&addr, &addrlen) == -1) {
307 static qsocket_t
os_socket(
int domain,
int type,
int protocol)
309 int s = socket(domain, type, protocol);
321 if (fd < 0 || fd >= FD_SETSIZE)
322 Com_Error(ERR_FATAL,
"%s: fd out of range: %d", func, fd);
346 static int os_select(
int nfds, fd_set *rfds, fd_set *wfds,
347 fd_set *efds,
struct timeval *
tv)
349 int ret = select(nfds, rfds, wfds, efds,
tv);