Coverage Report

Created: 2024-04-25 06:10

/src/uWebSockets/uSockets/src/bsd.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Authored by Alex Hultman, 2018-2021.
3
 * Intellectual property of third-party.
4
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
9
 *     http://www.apache.org/licenses/LICENSE-2.0
10
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
/* Todo: this file should lie in networking/bsd.c */
19
20
#define __APPLE_USE_RFC_3542
21
22
#include "libusockets.h"
23
#include "internal/internal.h"
24
25
#include <stdio.h>
26
#include <stdlib.h>
27
28
#ifndef _WIN32
29
//#define _GNU_SOURCE
30
#include <sys/types.h>
31
#include <sys/socket.h>
32
#include <netinet/in.h>
33
#include <netinet/tcp.h>
34
#include <netdb.h>
35
#include <string.h>
36
#include <unistd.h>
37
#include <fcntl.h>
38
#include <errno.h>
39
#endif
40
41
/* Internal structure of packet buffer */
42
struct us_internal_udp_packet_buffer {
43
#if defined(_WIN32) || defined(__APPLE__)
44
    char *buf[LIBUS_UDP_MAX_NUM];
45
    size_t len[LIBUS_UDP_MAX_NUM];
46
    struct sockaddr_storage addr[LIBUS_UDP_MAX_NUM];
47
#else
48
    struct mmsghdr msgvec[LIBUS_UDP_MAX_NUM];
49
    struct iovec iov[LIBUS_UDP_MAX_NUM];
50
    struct sockaddr_storage addr[LIBUS_UDP_MAX_NUM];
51
    char control[LIBUS_UDP_MAX_NUM][256];
52
#endif
53
};
54
55
/* We need to emulate sendmmsg, recvmmsg on platform who don't have it */
56
0
int bsd_sendmmsg(LIBUS_SOCKET_DESCRIPTOR fd, void *msgvec, unsigned int vlen, int flags) {
57
#if defined(__APPLE__)
58
59
struct mmsghdr {
60
    struct msghdr msg_hdr;  /* Message header */
61
    unsigned int  msg_len;  /* Number of bytes transmitted */
62
};
63
64
    struct mmsghdr *hdrs = (struct mmsghdr *) msgvec;
65
66
    for (int i = 0; i < vlen; i++) {
67
        int ret = sendmsg(fd, &hdrs[i].msg_hdr, flags);
68
        if (ret == -1) {
69
            if (i) {
70
                return i;
71
            } else {
72
                return -1;
73
            }
74
        } else {
75
            hdrs[i].msg_len = ret;
76
        }
77
    }
78
79
    return vlen;
80
81
#elif defined(_WIN32)
82
83
    struct us_internal_udp_packet_buffer *packet_buffer = (struct us_internal_udp_packet_buffer *) msgvec;
84
85
    /* Let's just use sendto here */
86
    /* Winsock does not have sendmsg, while macOS has, however, we simply use sendto since both macOS and Winsock has it.
87
     * Besides, you should use Linux either way to get best performance with the sendmmsg */
88
89
90
    // while we do not get error, send next
91
92
    for (int i = 0; i < LIBUS_UDP_MAX_NUM; i++) {
93
        // need to support ipv6 addresses also!
94
        int ret = sendto(fd, packet_buffer->buf[i], packet_buffer->len[i], flags, (struct sockaddr *)&packet_buffer->addr[i], sizeof(struct sockaddr_in));
95
96
        if (ret == -1) {
97
            // if we fail then we need to buffer up, no that's not our problem
98
            // we do need to register poll out though and have a callback for it
99
            return i;
100
        }
101
102
        //printf("sendto: %d\n", ret);
103
    }
104
105
    return LIBUS_UDP_MAX_NUM; // one message
106
#else
107
0
    return sendmmsg(fd, (struct mmsghdr *)msgvec, vlen, flags | MSG_NOSIGNAL);
108
0
#endif
109
0
}
110
111
0
int bsd_recvmmsg(LIBUS_SOCKET_DESCRIPTOR fd, void *msgvec, unsigned int vlen, int flags, void *timeout) {
112
#if defined(_WIN32) || defined(__APPLE__)
113
    struct us_internal_udp_packet_buffer *packet_buffer = (struct us_internal_udp_packet_buffer *) msgvec;
114
115
116
    for (int i = 0; i < LIBUS_UDP_MAX_NUM; i++) {
117
        socklen_t addr_len = sizeof(struct sockaddr_storage);
118
        int ret = recvfrom(fd, packet_buffer->buf[i], LIBUS_UDP_MAX_SIZE, flags, (struct sockaddr *)&packet_buffer->addr[i], &addr_len);
119
120
        if (ret == -1) {
121
            return i;
122
        }
123
124
        packet_buffer->len[i] = ret;
125
    }
126
127
    return LIBUS_UDP_MAX_NUM;
128
#else
129
    // we need to set controllen for ip packet
130
0
    for (int i = 0; i < vlen; i++) {
131
0
        ((struct mmsghdr *)msgvec)[i].msg_hdr.msg_controllen = 256;
132
0
    }
133
134
0
    return recvmmsg(fd, (struct mmsghdr *)msgvec, vlen, flags, 0);
135
0
#endif
136
0
}
137
138
// this one is needed for knowing the destination addr of udp packet
139
// an udp socket can only bind to one port, and that port never changes
140
// this function returns ONLY the IP address, not any port
141
0
int bsd_udp_packet_buffer_local_ip(void *msgvec, int index, char *ip) {
142
#if defined(_WIN32) || defined(__APPLE__)
143
    return 0; // not supported
144
#else
145
0
    struct msghdr *mh = &((struct mmsghdr *) msgvec)[index].msg_hdr;
146
0
    for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(mh); cmsg != NULL; cmsg = CMSG_NXTHDR(mh, cmsg)) {
147
        // Linux ipv4
148
0
    #ifdef IP_PKTINFO
149
0
        if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
150
0
            struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cmsg);
151
0
            memcpy(ip, &pi->ipi_addr, 4);
152
0
            return 4;
153
0
        }
154
        // FreeBSD ipv4
155
    #elif IP_RECVDSTADDR
156
        if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
157
            struct in_addr *addr = (struct in_addr *) CMSG_DATA(cmsg);
158
            memcpy(ip, addr, 4);
159
            return 4;
160
        }
161
    #endif
162
163
        // Linux, FreeBSD ipv6
164
0
        if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
165
0
            struct in6_pktinfo *pi6 = (struct in6_pktinfo *) CMSG_DATA(cmsg);
166
0
            memcpy(ip, &pi6->ipi6_addr, 16);
167
0
            return 16;
168
0
        }
169
0
    }
170
171
0
    return 0; // no length
172
173
0
#endif
174
0
}
175
176
0
char *bsd_udp_packet_buffer_peer(void *msgvec, int index) {
177
#if defined(_WIN32) || defined(__APPLE__)
178
    struct us_internal_udp_packet_buffer *packet_buffer = (struct us_internal_udp_packet_buffer *) msgvec;
179
    return (char *)&packet_buffer->addr[index];
180
#else
181
0
    return ((struct mmsghdr *) msgvec)[index].msg_hdr.msg_name;
182
0
#endif
183
0
}
184
185
0
char *bsd_udp_packet_buffer_payload(void *msgvec, int index) {
186
#if defined(_WIN32) || defined(__APPLE__)
187
    struct us_internal_udp_packet_buffer *packet_buffer = (struct us_internal_udp_packet_buffer *) msgvec;
188
    return packet_buffer->buf[index];
189
#else
190
0
    return ((struct mmsghdr *) msgvec)[index].msg_hdr.msg_iov[0].iov_base;
191
0
#endif
192
0
}
193
194
0
int bsd_udp_packet_buffer_payload_length(void *msgvec, int index) {
195
#if defined(_WIN32) || defined(__APPLE__)
196
    struct us_internal_udp_packet_buffer *packet_buffer = (struct us_internal_udp_packet_buffer *) msgvec;
197
    return packet_buffer->len[index];
198
#else
199
0
    return ((struct mmsghdr *) msgvec)[index].msg_len;
200
0
#endif
201
0
}
202
203
0
void bsd_udp_buffer_set_packet_payload(struct us_udp_packet_buffer_t *send_buf, int index, int offset, void *payload, int length, void *peer_addr) {
204
#if defined(_WIN32) || defined(__APPLE__)
205
    struct us_internal_udp_packet_buffer *packet_buffer = (struct us_internal_udp_packet_buffer *) send_buf;
206
207
    memcpy(packet_buffer->buf[index], payload, length);
208
    memcpy(&packet_buffer->addr[index], peer_addr, sizeof(struct sockaddr_storage));
209
210
    packet_buffer->len[index] = length;
211
#else
212
    //printf("length: %d, offset: %d\n", length, offset);
213
214
0
    struct mmsghdr *ss = (struct mmsghdr *) send_buf;
215
216
    // copy the peer address
217
0
    memcpy(ss[index].msg_hdr.msg_name, peer_addr, /*ss[index].msg_hdr.msg_namelen*/ sizeof(struct sockaddr_in));
218
219
    // set control length to 0
220
0
    ss[index].msg_hdr.msg_controllen = 0;
221
222
    // copy the payload
223
    
224
0
    ss[index].msg_hdr.msg_iov->iov_len = length + offset;
225
226
227
0
    memcpy(((char *) ss[index].msg_hdr.msg_iov->iov_base) + offset, payload, length);
228
0
#endif
229
0
}
230
231
/* The maximum UDP payload size is 64kb, but in IPV6 you can have jumbopackets larger than so.
232
 * We do not support those jumbo packets currently, but will safely ignore them.
233
 * Any sane sender would assume we don't support them if we consistently drop them.
234
 * Therefore a udp_packet_buffer_t will be 64 MB in size (64kb * 1024). */
235
0
void *bsd_create_udp_packet_buffer() {
236
#if defined(_WIN32) || defined(__APPLE__)
237
    struct us_internal_udp_packet_buffer *b = malloc(sizeof(struct us_internal_udp_packet_buffer) + LIBUS_UDP_MAX_SIZE * LIBUS_UDP_MAX_NUM);
238
239
    for (int i = 0; i < LIBUS_UDP_MAX_NUM; i++) {
240
        b->buf[i] = ((char *) b) + sizeof(struct us_internal_udp_packet_buffer) + LIBUS_UDP_MAX_SIZE * i;
241
    }
242
243
    return (struct us_udp_packet_buffer_t *) b;
244
#else
245
    /* Allocate 64kb times 1024 */
246
0
    struct us_internal_udp_packet_buffer *b = malloc(sizeof(struct us_internal_udp_packet_buffer) + LIBUS_UDP_MAX_SIZE * LIBUS_UDP_MAX_NUM);
247
248
0
    for (int n = 0; n < LIBUS_UDP_MAX_NUM; ++n) {
249
250
0
        b->iov[n].iov_base = &((char *) (b + 1))[n * LIBUS_UDP_MAX_SIZE];
251
0
        b->iov[n].iov_len = LIBUS_UDP_MAX_SIZE;
252
253
0
        b->msgvec[n].msg_hdr = (struct msghdr) {
254
0
            .msg_name       = &b->addr,
255
0
            .msg_namelen    = sizeof (struct sockaddr_storage),
256
257
0
            .msg_iov        = &b->iov[n],
258
0
            .msg_iovlen     = 1,
259
260
0
            .msg_control    = b->control[n],
261
0
            .msg_controllen = 256,
262
0
        };
263
0
    }
264
265
0
    return (struct us_udp_packet_buffer_t *) b;
266
0
#endif
267
0
}
268
269
6.06M
LIBUS_SOCKET_DESCRIPTOR apple_no_sigpipe(LIBUS_SOCKET_DESCRIPTOR fd) {
270
#ifdef __APPLE__
271
    if (fd != LIBUS_SOCKET_ERROR) {
272
        int no_sigpipe = 1;
273
        setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *) &no_sigpipe, sizeof(int));
274
    }
275
#endif
276
6.06M
    return fd;
277
6.06M
}
278
279
6.06M
LIBUS_SOCKET_DESCRIPTOR bsd_set_nonblocking(LIBUS_SOCKET_DESCRIPTOR fd) {
280
#ifdef _WIN32
281
    /* Libuv will set windows sockets as non-blocking */
282
#else
283
6.06M
    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
284
6.06M
#endif
285
6.06M
    return fd;
286
6.06M
}
287
288
6.03M
void bsd_socket_nodelay(LIBUS_SOCKET_DESCRIPTOR fd, int enabled) {
289
6.03M
    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *) &enabled, sizeof(enabled));
290
6.03M
}
291
292
255
void bsd_socket_flush(LIBUS_SOCKET_DESCRIPTOR fd) {
293
    // Linux TCP_CORK has the same underlying corking mechanism as with MSG_MORE
294
255
#ifdef TCP_CORK
295
255
    int enabled = 0;
296
255
    setsockopt(fd, IPPROTO_TCP, TCP_CORK, (void *) &enabled, sizeof(int));
297
255
#endif
298
255
}
299
300
26.1k
LIBUS_SOCKET_DESCRIPTOR bsd_create_socket(int domain, int type, int protocol) {
301
    // returns INVALID_SOCKET on error
302
26.1k
    int flags = 0;
303
26.1k
#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
304
26.1k
    flags = SOCK_CLOEXEC | SOCK_NONBLOCK;
305
26.1k
#endif
306
307
26.1k
    LIBUS_SOCKET_DESCRIPTOR created_fd = socket(domain, type | flags, protocol);
308
309
26.1k
    return bsd_set_nonblocking(apple_no_sigpipe(created_fd));
310
26.1k
}
311
312
6.05M
void bsd_close_socket(LIBUS_SOCKET_DESCRIPTOR fd) {
313
#ifdef _WIN32
314
    closesocket(fd);
315
#else
316
6.05M
    close(fd);
317
6.05M
#endif
318
6.05M
}
319
320
1.77M
void bsd_shutdown_socket(LIBUS_SOCKET_DESCRIPTOR fd) {
321
#ifdef _WIN32
322
    shutdown(fd, SD_SEND);
323
#else
324
1.77M
    shutdown(fd, SHUT_WR);
325
1.77M
#endif
326
1.77M
}
327
328
852
void bsd_shutdown_socket_read(LIBUS_SOCKET_DESCRIPTOR fd) {
329
#ifdef _WIN32
330
    shutdown(fd, SD_RECEIVE);
331
#else
332
852
    shutdown(fd, SHUT_RD);
333
852
#endif
334
852
}
335
336
6.07M
void internal_finalize_bsd_addr(struct bsd_addr_t *addr) {
337
    // parse, so to speak, the address
338
6.07M
    if (addr->mem.ss_family == AF_INET6) {
339
1.97M
        addr->ip = (char *) &((struct sockaddr_in6 *) addr)->sin6_addr;
340
1.97M
        addr->ip_length = sizeof(struct in6_addr);
341
1.97M
        addr->port = ntohs(((struct sockaddr_in6 *) addr)->sin6_port);
342
4.09M
    } else if (addr->mem.ss_family == AF_INET) {
343
4.09M
        addr->ip = (char *) &((struct sockaddr_in *) addr)->sin_addr;
344
4.09M
        addr->ip_length = sizeof(struct in_addr);
345
4.09M
        addr->port = ntohs(((struct sockaddr_in *) addr)->sin_port);
346
4.09M
    } else {
347
0
        addr->ip_length = 0;
348
0
        addr->port = -1;
349
0
    }
350
6.07M
}
351
352
2.32k
int bsd_local_addr(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr) {
353
2.32k
    addr->len = sizeof(addr->mem);
354
2.32k
    if (getsockname(fd, (struct sockaddr *) &addr->mem, &addr->len)) {
355
2.32k
        return -1;
356
2.32k
    }
357
0
    internal_finalize_bsd_addr(addr);
358
0
    return 0;
359
2.32k
}
360
361
39.0k
int bsd_remote_addr(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr) {
362
39.0k
    addr->len = sizeof(addr->mem);
363
39.0k
    if (getpeername(fd, (struct sockaddr *) &addr->mem, &addr->len)) {
364
0
        return -1;
365
0
    }
366
39.0k
    internal_finalize_bsd_addr(addr);
367
39.0k
    return 0;
368
39.0k
}
369
370
6.07M
char *bsd_addr_get_ip(struct bsd_addr_t *addr) {
371
6.07M
    return addr->ip;
372
6.07M
}
373
374
6.11M
int bsd_addr_get_ip_length(struct bsd_addr_t *addr) {
375
6.11M
    return addr->ip_length;
376
6.11M
}
377
378
0
int bsd_addr_get_port(struct bsd_addr_t *addr) {
379
0
    return addr->port;
380
0
}
381
382
// called by dispatch_ready_poll
383
11.6M
LIBUS_SOCKET_DESCRIPTOR bsd_accept_socket(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr) {
384
11.6M
    LIBUS_SOCKET_DESCRIPTOR accepted_fd;
385
11.6M
    addr->len = sizeof(addr->mem);
386
387
11.6M
#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
388
    // Linux, FreeBSD
389
11.6M
    accepted_fd = accept4(fd, (struct sockaddr *) addr, &addr->len, SOCK_CLOEXEC | SOCK_NONBLOCK);
390
#else
391
    // Windows, OS X
392
    accepted_fd = accept(fd, (struct sockaddr *) addr, &addr->len);
393
394
#endif
395
396
    /* We cannot rely on addr since it is not initialized if failed */
397
11.6M
    if (accepted_fd == LIBUS_SOCKET_ERROR) {
398
5.61M
        return LIBUS_SOCKET_ERROR;
399
5.61M
    }
400
401
6.03M
    internal_finalize_bsd_addr(addr);
402
403
6.03M
    return bsd_set_nonblocking(apple_no_sigpipe(accepted_fd));
404
11.6M
}
405
406
2.69M
int bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags) {
407
2.69M
    return recv(fd, buf, length, flags);
408
2.69M
}
409
410
#if !defined(_WIN32)
411
#include <sys/uio.h>
412
413
0
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
414
0
    struct iovec chunks[2];
415
    
416
0
    chunks[0].iov_base = (char *)header;
417
0
    chunks[0].iov_len = header_length;
418
0
    chunks[1].iov_base = (char *)payload;
419
0
    chunks[1].iov_len = payload_length;
420
    
421
0
    return writev(fd, chunks, 2);
422
0
}
423
#else
424
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
425
    int written = bsd_send(fd, header, header_length, 0);
426
    if (written == header_length) {
427
        int second_write = bsd_send(fd, payload, payload_length, 0);
428
        if (second_write > 0) {
429
            written += second_write;
430
        }
431
    }
432
    return written;
433
}
434
#endif
435
436
2.51M
int bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more) {
437
438
    // MSG_MORE (Linux), MSG_PARTIAL (Windows), TCP_NOPUSH (BSD)
439
440
#ifndef MSG_NOSIGNAL
441
#define MSG_NOSIGNAL 0
442
#endif
443
444
2.51M
#ifdef MSG_MORE
445
446
    // for Linux we do not want signals
447
2.51M
    return send(fd, buf, length, ((msg_more != 0) * MSG_MORE) | MSG_NOSIGNAL);
448
449
#else
450
451
    // use TCP_NOPUSH
452
453
    return send(fd, buf, length, MSG_NOSIGNAL);
454
455
#endif
456
2.51M
}
457
458
27.1k
int bsd_would_block() {
459
#ifdef _WIN32
460
    return WSAGetLastError() == WSAEWOULDBLOCK;
461
#else
462
27.1k
    return errno == EWOULDBLOCK;// || errno == EAGAIN;
463
27.1k
#endif
464
27.1k
}
465
466
// return LIBUS_SOCKET_ERROR or the fd that represents listen socket
467
// listen both on ipv6 and ipv4
468
19.9k
LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket(const char *host, int port, int options) {
469
19.9k
    struct addrinfo hints, *result;
470
19.9k
    memset(&hints, 0, sizeof(struct addrinfo));
471
472
19.9k
    hints.ai_flags = AI_PASSIVE;
473
19.9k
    hints.ai_family = AF_UNSPEC;
474
19.9k
    hints.ai_socktype = SOCK_STREAM;
475
476
19.9k
    char port_string[16];
477
19.9k
    snprintf(port_string, 16, "%d", port);
478
479
19.9k
    if (getaddrinfo(host, port_string, &hints, &result)) {
480
6
        return LIBUS_SOCKET_ERROR;
481
6
    }
482
483
19.9k
    LIBUS_SOCKET_DESCRIPTOR listenFd = LIBUS_SOCKET_ERROR;
484
19.9k
    struct addrinfo *listenAddr;
485
39.8k
    for (struct addrinfo *a = result; a && listenFd == LIBUS_SOCKET_ERROR; a = a->ai_next) {
486
19.9k
        if (a->ai_family == AF_INET6) {
487
13.4k
            listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
488
13.4k
            listenAddr = a;
489
13.4k
        }
490
19.9k
    }
491
492
26.3k
    for (struct addrinfo *a = result; a && listenFd == LIBUS_SOCKET_ERROR; a = a->ai_next) {
493
6.44k
        if (a->ai_family == AF_INET) {
494
6.29k
            listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
495
6.29k
            listenAddr = a;
496
6.29k
        }
497
6.44k
    }
498
499
19.9k
    if (listenFd == LIBUS_SOCKET_ERROR) {
500
147
        freeaddrinfo(result);
501
147
        return LIBUS_SOCKET_ERROR;
502
147
    }
503
504
19.7k
    if (port != 0) {
505
        /* Otherwise, always enable SO_REUSEPORT and SO_REUSEADDR _unless_ options specify otherwise */
506
#ifdef _WIN32
507
        if (options & LIBUS_LISTEN_EXCLUSIVE_PORT) {
508
            int optval2 = 1;
509
            setsockopt(listenFd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (void *) &optval2, sizeof(optval2));
510
        } else {
511
            int optval3 = 1;
512
            setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval3, sizeof(optval3));
513
        }
514
#else
515
19.7k
    #if /*defined(__linux) &&*/ defined(SO_REUSEPORT)
516
19.7k
        if (!(options & LIBUS_LISTEN_EXCLUSIVE_PORT)) {
517
19.7k
            int optval = 1;
518
19.7k
            setsockopt(listenFd, SOL_SOCKET, SO_REUSEPORT, (void *) &optval, sizeof(optval));
519
19.7k
        }
520
19.7k
    #endif
521
19.7k
        int enabled = 1;
522
19.7k
        setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &enabled, sizeof(enabled));
523
19.7k
#endif
524
525
19.7k
    }
526
    
527
19.7k
#ifdef IPV6_V6ONLY
528
19.7k
    int disabled = 0;
529
19.7k
    setsockopt(listenFd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &disabled, sizeof(disabled));
530
19.7k
#endif
531
532
19.7k
    if (bind(listenFd, listenAddr->ai_addr, (socklen_t) listenAddr->ai_addrlen) || listen(listenFd, 512)) {
533
44
        bsd_close_socket(listenFd);
534
44
        freeaddrinfo(result);
535
44
        return LIBUS_SOCKET_ERROR;
536
44
    }
537
538
19.7k
    freeaddrinfo(result);
539
19.7k
    return listenFd;
540
19.7k
}
541
542
#ifndef _WIN32
543
#include <sys/un.h>
544
#else
545
#include <afunix.h>
546
#include <io.h>
547
#endif
548
#include <sys/stat.h>
549
#include <stddef.h>
550
0
LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket_unix(const char *path, int options) {
551
552
0
    LIBUS_SOCKET_DESCRIPTOR listenFd = LIBUS_SOCKET_ERROR;
553
554
0
    listenFd = bsd_create_socket(AF_UNIX, SOCK_STREAM, 0);
555
556
0
    if (listenFd == LIBUS_SOCKET_ERROR) {
557
0
        return LIBUS_SOCKET_ERROR;
558
0
    }
559
560
0
#ifndef _WIN32
561
    // 700 permission by default
562
0
    fchmod(listenFd, S_IRWXU);
563
#else
564
    _chmod(path, S_IREAD | S_IWRITE | S_IEXEC);
565
#endif
566
567
0
    struct sockaddr_un server_address;
568
0
    memset(&server_address, 0, sizeof(server_address));
569
0
    server_address.sun_family = AF_UNIX;
570
0
    strcpy(server_address.sun_path, path);
571
0
    int size = offsetof(struct sockaddr_un, sun_path) + strlen(server_address.sun_path);
572
#ifdef _WIN32
573
    _unlink(path);
574
#else
575
0
    unlink(path);
576
0
#endif
577
578
0
    if (bind(listenFd, (struct sockaddr *)&server_address, size) || listen(listenFd, 512)) {
579
0
        bsd_close_socket(listenFd);
580
0
        return LIBUS_SOCKET_ERROR;
581
0
    }
582
583
0
    return listenFd;
584
0
}
585
586
0
LIBUS_SOCKET_DESCRIPTOR bsd_create_udp_socket(const char *host, int port) {
587
0
    struct addrinfo hints, *result;
588
0
    memset(&hints, 0, sizeof(struct addrinfo));
589
590
0
    hints.ai_flags = AI_PASSIVE;
591
0
    hints.ai_family = AF_UNSPEC;
592
0
    hints.ai_socktype = SOCK_DGRAM;
593
594
0
    char port_string[16];
595
0
    snprintf(port_string, 16, "%d", port);
596
597
0
    if (getaddrinfo(host, port_string, &hints, &result)) {
598
0
        return LIBUS_SOCKET_ERROR;
599
0
    }
600
601
0
    LIBUS_SOCKET_DESCRIPTOR listenFd = LIBUS_SOCKET_ERROR;
602
0
    struct addrinfo *listenAddr;
603
0
    for (struct addrinfo *a = result; a && listenFd == LIBUS_SOCKET_ERROR; a = a->ai_next) {
604
0
        if (a->ai_family == AF_INET6) {
605
0
            listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
606
0
            listenAddr = a;
607
0
        }
608
0
    }
609
610
0
    for (struct addrinfo *a = result; a && listenFd == LIBUS_SOCKET_ERROR; a = a->ai_next) {
611
0
        if (a->ai_family == AF_INET) {
612
0
            listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
613
0
            listenAddr = a;
614
0
        }
615
0
    }
616
617
0
    if (listenFd == LIBUS_SOCKET_ERROR) {
618
0
        freeaddrinfo(result);
619
0
        return LIBUS_SOCKET_ERROR;
620
0
    }
621
622
0
    if (port != 0) {
623
        /* Should this also go for UDP? */
624
0
        int enabled = 1;
625
0
        setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &enabled, sizeof(enabled));
626
0
    }
627
    
628
0
#ifdef IPV6_V6ONLY
629
0
    int disabled = 0;
630
0
    setsockopt(listenFd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &disabled, sizeof(disabled));
631
0
#endif
632
633
    /* We need destination address for udp packets in both ipv6 and ipv4 */
634
635
/* On FreeBSD this option seems to be called like so */
636
#ifndef IPV6_RECVPKTINFO
637
#define IPV6_RECVPKTINFO IPV6_PKTINFO
638
#endif
639
640
0
    int enabled = 1;
641
0
    if (setsockopt(listenFd, IPPROTO_IPV6, IPV6_RECVPKTINFO, (void *) &enabled, sizeof(enabled)) == -1) {
642
0
        if (errno == 92) {
643
            // Linux ipv4
644
0
        #ifdef IP_PKTINFO
645
0
            if (setsockopt(listenFd, IPPROTO_IP, IP_PKTINFO, (void *) &enabled, sizeof(enabled)) != 0) {
646
0
                printf("Error setting IPv4 pktinfo!\n");
647
0
            }
648
            // FreeBSD ipv4
649
        #elif IP_RECVDSTADDR
650
            if (setsockopt(listenFd, IPPROTO_IP, IP_RECVDSTADDR, (void *) &enabled, sizeof(enabled)) != 0) {
651
                printf("Error setting IPv4 pktinfo!\n");
652
            }
653
        #endif
654
0
        } else {
655
0
            printf("Error setting IPv6 pktinfo!\n");
656
0
        }
657
0
    }
658
659
    /* These are used for getting the ECN */
660
0
    if (setsockopt(listenFd, IPPROTO_IPV6, IPV6_RECVTCLASS, (void *) &enabled, sizeof(enabled)) == -1) {
661
0
        if (errno == 92) {
662
0
            if (setsockopt(listenFd, IPPROTO_IP, IP_RECVTOS, (void *) &enabled, sizeof(enabled)) != 0) {
663
0
                printf("Error setting IPv4 ECN!\n");
664
0
            }
665
0
        } else {
666
0
            printf("Error setting IPv6 ECN!\n");
667
0
        }
668
0
    }
669
670
    /* We bind here as well */
671
0
    if (bind(listenFd, listenAddr->ai_addr, (socklen_t) listenAddr->ai_addrlen)) {
672
0
        bsd_close_socket(listenFd);
673
0
        freeaddrinfo(result);
674
0
        return LIBUS_SOCKET_ERROR;
675
0
    }
676
677
0
    freeaddrinfo(result);
678
0
    return listenFd;
679
0
}
680
681
0
int bsd_udp_packet_buffer_ecn(void *msgvec, int index) {
682
683
#if defined(_WIN32) || defined(__APPLE__)
684
    printf("ECN not supported!\n");
685
#else
686
    // we should iterate all control messages once, after recvmmsg and then only fetch them with these functions
687
0
    struct msghdr *mh = &((struct mmsghdr *) msgvec)[index].msg_hdr;
688
0
    for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(mh); cmsg != NULL; cmsg = CMSG_NXTHDR(mh, cmsg)) {
689
        // do we need to get TOS from ipv6 also?
690
0
        if (cmsg->cmsg_level == IPPROTO_IP) {
691
0
            if (cmsg->cmsg_type == IP_TOS) {
692
0
                uint8_t tos = *(uint8_t *)CMSG_DATA(cmsg);
693
0
                return tos & 3;
694
0
            }
695
0
        }
696
697
0
        if (cmsg->cmsg_level == IPPROTO_IPV6) {
698
0
            if (cmsg->cmsg_type == IPV6_TCLASS) {
699
                // is this correct?
700
0
                uint8_t tos = *(uint8_t *)CMSG_DATA(cmsg);
701
0
                return tos & 3;
702
0
            }
703
0
        }
704
0
    }
705
0
#endif
706
707
0
    printf("We got no ECN!\n");
708
709
0
    return 0; // no ecn defaults to 0
710
0
}
711
712
6.41k
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(const char *host, int port, const char *source_host, int options) {
713
6.41k
    struct addrinfo hints, *result;
714
6.41k
    memset(&hints, 0, sizeof(struct addrinfo));
715
6.41k
    hints.ai_family = AF_UNSPEC;
716
6.41k
    hints.ai_socktype = SOCK_STREAM;
717
718
6.41k
    char port_string[16];
719
6.41k
    snprintf(port_string, 16, "%d", port);
720
721
6.41k
    if (getaddrinfo(host, port_string, &hints, &result) != 0) {
722
21
        return LIBUS_SOCKET_ERROR;
723
21
    }
724
725
6.39k
    LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_socket(result->ai_family, result->ai_socktype, result->ai_protocol);
726
6.39k
    if (fd == LIBUS_SOCKET_ERROR) {
727
4.06k
        freeaddrinfo(result);
728
4.06k
        return LIBUS_SOCKET_ERROR;
729
4.06k
    }
730
731
2.32k
    if (source_host) {
732
2.32k
        struct addrinfo *interface_result;
733
2.32k
        if (!getaddrinfo(source_host, NULL, NULL, &interface_result)) {
734
2.32k
            int ret = bind(fd, interface_result->ai_addr, (socklen_t) interface_result->ai_addrlen);
735
2.32k
            freeaddrinfo(interface_result);
736
2.32k
            if (ret == LIBUS_SOCKET_ERROR) {
737
0
                bsd_close_socket(fd);
738
0
                freeaddrinfo(result);
739
0
                return LIBUS_SOCKET_ERROR;
740
0
            }
741
2.32k
        }
742
2.32k
    }
743
744
2.32k
    connect(fd, result->ai_addr, (socklen_t) result->ai_addrlen);
745
2.32k
    freeaddrinfo(result);
746
747
2.32k
    return fd;
748
2.32k
}
749
750
0
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket_unix(const char *server_path, int options) {
751
752
0
    struct sockaddr_un server_address;
753
0
    memset(&server_address, 0, sizeof(server_address));
754
0
    server_address.sun_family = AF_UNIX;
755
0
    strcpy(server_address.sun_path, server_path);
756
0
    int size = offsetof(struct sockaddr_un, sun_path) + strlen(server_address.sun_path);
757
758
0
    LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_socket(AF_UNIX, SOCK_STREAM, 0);
759
760
0
    if (fd == LIBUS_SOCKET_ERROR) {
761
0
        return LIBUS_SOCKET_ERROR;
762
0
    }
763
764
0
    connect(fd, (struct sockaddr *)&server_address, size);
765
766
0
    return fd;
767
0
}