Coverage Report

Created: 2023-06-06 06:17

/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
        // ipv6 or ipv4
148
0
        if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
149
0
            struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cmsg);
150
0
            memcpy(ip, &pi->ipi_addr, 4);
151
0
            return 4;
152
0
        }
153
154
0
        if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
155
0
            struct in6_pktinfo *pi6 = (struct in6_pktinfo *) CMSG_DATA(cmsg);
156
0
            memcpy(ip, &pi6->ipi6_addr, 16);
157
0
            return 16;
158
0
        }
159
0
    }
160
161
0
    return 0; // no length
162
163
0
#endif
164
0
}
165
166
0
char *bsd_udp_packet_buffer_peer(void *msgvec, int index) {
167
#if defined(_WIN32) || defined(__APPLE__)
168
    struct us_internal_udp_packet_buffer *packet_buffer = (struct us_internal_udp_packet_buffer *) msgvec;
169
    return (char *)&packet_buffer->addr[index];
170
#else
171
0
    return ((struct mmsghdr *) msgvec)[index].msg_hdr.msg_name;
172
0
#endif
173
0
}
174
175
0
char *bsd_udp_packet_buffer_payload(void *msgvec, int index) {
176
#if defined(_WIN32) || defined(__APPLE__)
177
    struct us_internal_udp_packet_buffer *packet_buffer = (struct us_internal_udp_packet_buffer *) msgvec;
178
    return packet_buffer->buf[index];
179
#else
180
0
    return ((struct mmsghdr *) msgvec)[index].msg_hdr.msg_iov[0].iov_base;
181
0
#endif
182
0
}
183
184
0
int bsd_udp_packet_buffer_payload_length(void *msgvec, int index) {
185
#if defined(_WIN32) || defined(__APPLE__)
186
    struct us_internal_udp_packet_buffer *packet_buffer = (struct us_internal_udp_packet_buffer *) msgvec;
187
    return packet_buffer->len[index];
188
#else
189
0
    return ((struct mmsghdr *) msgvec)[index].msg_len;
190
0
#endif
191
0
}
192
193
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) {
194
#if defined(_WIN32) || defined(__APPLE__)
195
    struct us_internal_udp_packet_buffer *packet_buffer = (struct us_internal_udp_packet_buffer *) send_buf;
196
197
    memcpy(packet_buffer->buf[index], payload, length);
198
    memcpy(&packet_buffer->addr[index], peer_addr, sizeof(struct sockaddr_storage));
199
200
    packet_buffer->len[index] = length;
201
#else
202
    //printf("length: %d, offset: %d\n", length, offset);
203
204
0
    struct mmsghdr *ss = (struct mmsghdr *) send_buf;
205
206
    // copy the peer address
207
0
    memcpy(ss[index].msg_hdr.msg_name, peer_addr, /*ss[index].msg_hdr.msg_namelen*/ sizeof(struct sockaddr_in));
208
209
    // set control length to 0
210
0
    ss[index].msg_hdr.msg_controllen = 0;
211
212
    // copy the payload
213
    
214
0
    ss[index].msg_hdr.msg_iov->iov_len = length + offset;
215
216
217
0
    memcpy(((char *) ss[index].msg_hdr.msg_iov->iov_base) + offset, payload, length);
218
0
#endif
219
0
}
220
221
/* The maximum UDP payload size is 64kb, but in IPV6 you can have jumbopackets larger than so.
222
 * We do not support those jumbo packets currently, but will safely ignore them.
223
 * Any sane sender would assume we don't support them if we consistently drop them.
224
 * Therefore a udp_packet_buffer_t will be 64 MB in size (64kb * 1024). */
225
0
void *bsd_create_udp_packet_buffer() {
226
#if defined(_WIN32) || defined(__APPLE__)
227
    struct us_internal_udp_packet_buffer *b = malloc(sizeof(struct us_internal_udp_packet_buffer) + LIBUS_UDP_MAX_SIZE * LIBUS_UDP_MAX_NUM);
228
229
    for (int i = 0; i < LIBUS_UDP_MAX_NUM; i++) {
230
        b->buf[i] = ((char *) b) + sizeof(struct us_internal_udp_packet_buffer) + LIBUS_UDP_MAX_SIZE * i;
231
    }
232
233
    return (struct us_udp_packet_buffer_t *) b;
234
#else
235
    /* Allocate 64kb times 1024 */
236
0
    struct us_internal_udp_packet_buffer *b = malloc(sizeof(struct us_internal_udp_packet_buffer) + LIBUS_UDP_MAX_SIZE * LIBUS_UDP_MAX_NUM);
237
238
0
    for (int n = 0; n < LIBUS_UDP_MAX_NUM; ++n) {
239
240
0
        b->iov[n].iov_base = &((char *) (b + 1))[n * LIBUS_UDP_MAX_SIZE];
241
0
        b->iov[n].iov_len = LIBUS_UDP_MAX_SIZE;
242
243
0
        b->msgvec[n].msg_hdr = (struct msghdr) {
244
0
            .msg_name       = &b->addr,
245
0
            .msg_namelen    = sizeof (struct sockaddr_storage),
246
247
0
            .msg_iov        = &b->iov[n],
248
0
            .msg_iovlen     = 1,
249
250
0
            .msg_control    = b->control[n],
251
0
            .msg_controllen = 256,
252
0
        };
253
0
    }
254
255
0
    return (struct us_udp_packet_buffer_t *) b;
256
0
#endif
257
0
}
258
259
1.01M
LIBUS_SOCKET_DESCRIPTOR apple_no_sigpipe(LIBUS_SOCKET_DESCRIPTOR fd) {
260
#ifdef __APPLE__
261
    if (fd != LIBUS_SOCKET_ERROR) {
262
        int no_sigpipe = 1;
263
        setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *) &no_sigpipe, sizeof(int));
264
    }
265
#endif
266
1.01M
    return fd;
267
1.01M
}
268
269
1.01M
LIBUS_SOCKET_DESCRIPTOR bsd_set_nonblocking(LIBUS_SOCKET_DESCRIPTOR fd) {
270
#ifdef _WIN32
271
    /* Libuv will set windows sockets as non-blocking */
272
#else
273
1.01M
    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
274
1.01M
#endif
275
1.01M
    return fd;
276
1.01M
}
277
278
1.01M
void bsd_socket_nodelay(LIBUS_SOCKET_DESCRIPTOR fd, int enabled) {
279
1.01M
    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *) &enabled, sizeof(enabled));
280
1.01M
}
281
282
0
void bsd_socket_flush(LIBUS_SOCKET_DESCRIPTOR fd) {
283
    // Linux TCP_CORK has the same underlying corking mechanism as with MSG_MORE
284
0
#ifdef TCP_CORK
285
0
    int enabled = 0;
286
0
    setsockopt(fd, IPPROTO_TCP, TCP_CORK, (void *) &enabled, sizeof(int));
287
0
#endif
288
0
}
289
290
1.65k
LIBUS_SOCKET_DESCRIPTOR bsd_create_socket(int domain, int type, int protocol) {
291
    // returns INVALID_SOCKET on error
292
1.65k
    int flags = 0;
293
1.65k
#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
294
1.65k
    flags = SOCK_CLOEXEC | SOCK_NONBLOCK;
295
1.65k
#endif
296
297
1.65k
    LIBUS_SOCKET_DESCRIPTOR created_fd = socket(domain, type | flags, protocol);
298
299
1.65k
    return bsd_set_nonblocking(apple_no_sigpipe(created_fd));
300
1.65k
}
301
302
1.01M
void bsd_close_socket(LIBUS_SOCKET_DESCRIPTOR fd) {
303
#ifdef _WIN32
304
    closesocket(fd);
305
#else
306
1.01M
    close(fd);
307
1.01M
#endif
308
1.01M
}
309
310
90.8k
void bsd_shutdown_socket(LIBUS_SOCKET_DESCRIPTOR fd) {
311
#ifdef _WIN32
312
    shutdown(fd, SD_SEND);
313
#else
314
90.8k
    shutdown(fd, SHUT_WR);
315
90.8k
#endif
316
90.8k
}
317
318
0
void bsd_shutdown_socket_read(LIBUS_SOCKET_DESCRIPTOR fd) {
319
#ifdef _WIN32
320
    shutdown(fd, SD_RECEIVE);
321
#else
322
0
    shutdown(fd, SHUT_RD);
323
0
#endif
324
0
}
325
326
1.01M
void internal_finalize_bsd_addr(struct bsd_addr_t *addr) {
327
    // parse, so to speak, the address
328
1.01M
    if (addr->mem.ss_family == AF_INET6) {
329
558k
        addr->ip = (char *) &((struct sockaddr_in6 *) addr)->sin6_addr;
330
558k
        addr->ip_length = sizeof(struct in6_addr);
331
558k
        addr->port = ntohs(((struct sockaddr_in6 *) addr)->sin6_port);
332
558k
    } else if (addr->mem.ss_family == AF_INET) {
333
451k
        addr->ip = (char *) &((struct sockaddr_in *) addr)->sin_addr;
334
451k
        addr->ip_length = sizeof(struct in_addr);
335
451k
        addr->port = ntohs(((struct sockaddr_in *) addr)->sin_port);
336
451k
    } else {
337
0
        addr->ip_length = 0;
338
0
        addr->port = -1;
339
0
    }
340
1.01M
}
341
342
0
int bsd_local_addr(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr) {
343
0
    addr->len = sizeof(addr->mem);
344
0
    if (getsockname(fd, (struct sockaddr *) &addr->mem, &addr->len)) {
345
0
        return -1;
346
0
    }
347
0
    internal_finalize_bsd_addr(addr);
348
0
    return 0;
349
0
}
350
351
0
int bsd_remote_addr(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr) {
352
0
    addr->len = sizeof(addr->mem);
353
0
    if (getpeername(fd, (struct sockaddr *) &addr->mem, &addr->len)) {
354
0
        return -1;
355
0
    }
356
0
    internal_finalize_bsd_addr(addr);
357
0
    return 0;
358
0
}
359
360
1.01M
char *bsd_addr_get_ip(struct bsd_addr_t *addr) {
361
1.01M
    return addr->ip;
362
1.01M
}
363
364
1.01M
int bsd_addr_get_ip_length(struct bsd_addr_t *addr) {
365
1.01M
    return addr->ip_length;
366
1.01M
}
367
368
0
int bsd_addr_get_port(struct bsd_addr_t *addr) {
369
0
    return addr->port;
370
0
}
371
372
// called by dispatch_ready_poll
373
3.02M
LIBUS_SOCKET_DESCRIPTOR bsd_accept_socket(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr) {
374
3.02M
    LIBUS_SOCKET_DESCRIPTOR accepted_fd;
375
3.02M
    addr->len = sizeof(addr->mem);
376
377
3.02M
#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
378
    // Linux, FreeBSD
379
3.02M
    accepted_fd = accept4(fd, (struct sockaddr *) addr, &addr->len, SOCK_CLOEXEC | SOCK_NONBLOCK);
380
#else
381
    // Windows, OS X
382
    accepted_fd = accept(fd, (struct sockaddr *) addr, &addr->len);
383
384
#endif
385
386
    /* We cannot rely on addr since it is not initialized if failed */
387
3.02M
    if (accepted_fd == LIBUS_SOCKET_ERROR) {
388
2.01M
        return LIBUS_SOCKET_ERROR;
389
2.01M
    }
390
391
1.01M
    internal_finalize_bsd_addr(addr);
392
393
1.01M
    return bsd_set_nonblocking(apple_no_sigpipe(accepted_fd));
394
3.02M
}
395
396
160k
int bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags) {
397
160k
    return recv(fd, buf, length, flags);
398
160k
}
399
400
#if !defined(_WIN32)
401
#include <sys/uio.h>
402
403
0
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
404
0
    struct iovec chunks[2];
405
    
406
0
    chunks[0].iov_base = (char *)header;
407
0
    chunks[0].iov_len = header_length;
408
0
    chunks[1].iov_base = (char *)payload;
409
0
    chunks[1].iov_len = payload_length;
410
    
411
0
    return writev(fd, chunks, 2);
412
0
}
413
#else
414
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
415
    int written = bsd_send(fd, header, header_length, 0);
416
    if (written == header_length) {
417
        int second_write = bsd_send(fd, payload, payload_length, 0);
418
        if (second_write > 0) {
419
            written += second_write;
420
        }
421
    }
422
    return written;
423
}
424
#endif
425
426
141k
int bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more) {
427
428
    // MSG_MORE (Linux), MSG_PARTIAL (Windows), TCP_NOPUSH (BSD)
429
430
#ifndef MSG_NOSIGNAL
431
#define MSG_NOSIGNAL 0
432
#endif
433
434
141k
#ifdef MSG_MORE
435
436
    // for Linux we do not want signals
437
141k
    return send(fd, buf, length, ((msg_more != 0) * MSG_MORE) | MSG_NOSIGNAL);
438
439
#else
440
441
    // use TCP_NOPUSH
442
443
    return send(fd, buf, length, MSG_NOSIGNAL);
444
445
#endif
446
141k
}
447
448
1.21k
int bsd_would_block() {
449
#ifdef _WIN32
450
    return WSAGetLastError() == WSAEWOULDBLOCK;
451
#else
452
1.21k
    return errno == EWOULDBLOCK;// || errno == EAGAIN;
453
1.21k
#endif
454
1.21k
}
455
456
// return LIBUS_SOCKET_ERROR or the fd that represents listen socket
457
// listen both on ipv6 and ipv4
458
1.65k
LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket(const char *host, int port, int options) {
459
1.65k
    struct addrinfo hints, *result;
460
1.65k
    memset(&hints, 0, sizeof(struct addrinfo));
461
462
1.65k
    hints.ai_flags = AI_PASSIVE;
463
1.65k
    hints.ai_family = AF_UNSPEC;
464
1.65k
    hints.ai_socktype = SOCK_STREAM;
465
466
1.65k
    char port_string[16];
467
1.65k
    snprintf(port_string, 16, "%d", port);
468
469
1.65k
    if (getaddrinfo(host, port_string, &hints, &result)) {
470
0
        return LIBUS_SOCKET_ERROR;
471
0
    }
472
473
1.65k
    LIBUS_SOCKET_DESCRIPTOR listenFd = LIBUS_SOCKET_ERROR;
474
1.65k
    struct addrinfo *listenAddr;
475
3.31k
    for (struct addrinfo *a = result; a && listenFd == LIBUS_SOCKET_ERROR; a = a->ai_next) {
476
1.65k
        if (a->ai_family == AF_INET6) {
477
931
            listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
478
931
            listenAddr = a;
479
931
        }
480
1.65k
    }
481
482
2.37k
    for (struct addrinfo *a = result; a && listenFd == LIBUS_SOCKET_ERROR; a = a->ai_next) {
483
724
        if (a->ai_family == AF_INET) {
484
723
            listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
485
723
            listenAddr = a;
486
723
        }
487
724
    }
488
489
1.65k
    if (listenFd == LIBUS_SOCKET_ERROR) {
490
1
        freeaddrinfo(result);
491
1
        return LIBUS_SOCKET_ERROR;
492
1
    }
493
494
1.65k
    if (port != 0) {
495
        /* Otherwise, always enable SO_REUSEPORT and SO_REUSEADDR _unless_ options specify otherwise */
496
#ifdef _WIN32
497
        if (options & LIBUS_LISTEN_EXCLUSIVE_PORT) {
498
            int optval2 = 1;
499
            setsockopt(listenFd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (void *) &optval2, sizeof(optval2));
500
        } else {
501
            int optval3 = 1;
502
            setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval3, sizeof(optval3));
503
        }
504
#else
505
1.65k
    #if /*defined(__linux) &&*/ defined(SO_REUSEPORT)
506
1.65k
        if (!(options & LIBUS_LISTEN_EXCLUSIVE_PORT)) {
507
1.65k
            int optval = 1;
508
1.65k
            setsockopt(listenFd, SOL_SOCKET, SO_REUSEPORT, (void *) &optval, sizeof(optval));
509
1.65k
        }
510
1.65k
    #endif
511
1.65k
        int enabled = 1;
512
1.65k
        setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &enabled, sizeof(enabled));
513
1.65k
#endif
514
515
1.65k
    }
516
    
517
1.65k
#ifdef IPV6_V6ONLY
518
1.65k
    int disabled = 0;
519
1.65k
    setsockopt(listenFd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &disabled, sizeof(disabled));
520
1.65k
#endif
521
522
1.65k
    if (bind(listenFd, listenAddr->ai_addr, (socklen_t) listenAddr->ai_addrlen) || listen(listenFd, 512)) {
523
11
        bsd_close_socket(listenFd);
524
11
        freeaddrinfo(result);
525
11
        return LIBUS_SOCKET_ERROR;
526
11
    }
527
528
1.64k
    freeaddrinfo(result);
529
1.64k
    return listenFd;
530
1.65k
}
531
532
#ifndef _WIN32
533
#include <sys/un.h>
534
#else
535
#include <afunix.h>
536
#include <io.h>
537
#endif
538
#include <sys/stat.h>
539
#include <stddef.h>
540
0
LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket_unix(const char *path, int options) {
541
542
0
    LIBUS_SOCKET_DESCRIPTOR listenFd = LIBUS_SOCKET_ERROR;
543
544
0
    listenFd = bsd_create_socket(AF_UNIX, SOCK_STREAM, 0);
545
546
0
    if (listenFd == LIBUS_SOCKET_ERROR) {
547
0
        return LIBUS_SOCKET_ERROR;
548
0
    }
549
550
0
#ifndef _WIN32
551
    // 700 permission by default
552
0
    fchmod(listenFd, S_IRWXU);
553
#else
554
    _chmod(path, S_IREAD | S_IWRITE | S_IEXEC);
555
#endif
556
557
0
    struct sockaddr_un server_address;
558
0
    memset(&server_address, 0, sizeof(server_address));
559
0
    server_address.sun_family = AF_UNIX;
560
0
    strcpy(server_address.sun_path, path);
561
0
    int size = offsetof(struct sockaddr_un, sun_path) + strlen(server_address.sun_path);
562
#ifdef _WIN32
563
    _unlink(path);
564
#else
565
0
    unlink(path);
566
0
#endif
567
568
0
    if (bind(listenFd, (struct sockaddr *)&server_address, size) || listen(listenFd, 512)) {
569
0
        bsd_close_socket(listenFd);
570
0
        return LIBUS_SOCKET_ERROR;
571
0
    }
572
573
0
    return listenFd;
574
0
}
575
576
0
LIBUS_SOCKET_DESCRIPTOR bsd_create_udp_socket(const char *host, int port) {
577
0
    struct addrinfo hints, *result;
578
0
    memset(&hints, 0, sizeof(struct addrinfo));
579
580
0
    hints.ai_flags = AI_PASSIVE;
581
0
    hints.ai_family = AF_UNSPEC;
582
0
    hints.ai_socktype = SOCK_DGRAM;
583
584
0
    char port_string[16];
585
0
    snprintf(port_string, 16, "%d", port);
586
587
0
    if (getaddrinfo(host, port_string, &hints, &result)) {
588
0
        return LIBUS_SOCKET_ERROR;
589
0
    }
590
591
0
    LIBUS_SOCKET_DESCRIPTOR listenFd = LIBUS_SOCKET_ERROR;
592
0
    struct addrinfo *listenAddr;
593
0
    for (struct addrinfo *a = result; a && listenFd == LIBUS_SOCKET_ERROR; a = a->ai_next) {
594
0
        if (a->ai_family == AF_INET6) {
595
0
            listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
596
0
            listenAddr = a;
597
0
        }
598
0
    }
599
600
0
    for (struct addrinfo *a = result; a && listenFd == LIBUS_SOCKET_ERROR; a = a->ai_next) {
601
0
        if (a->ai_family == AF_INET) {
602
0
            listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
603
0
            listenAddr = a;
604
0
        }
605
0
    }
606
607
0
    if (listenFd == LIBUS_SOCKET_ERROR) {
608
0
        freeaddrinfo(result);
609
0
        return LIBUS_SOCKET_ERROR;
610
0
    }
611
612
0
    if (port != 0) {
613
        /* Should this also go for UDP? */
614
0
        int enabled = 1;
615
0
        setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &enabled, sizeof(enabled));
616
0
    }
617
    
618
0
#ifdef IPV6_V6ONLY
619
0
    int disabled = 0;
620
0
    setsockopt(listenFd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &disabled, sizeof(disabled));
621
0
#endif
622
623
    /* We need destination address for udp packets in both ipv6 and ipv4 */
624
625
/* On FreeBSD this option seems to be called like so */
626
#ifndef IPV6_RECVPKTINFO
627
#define IPV6_RECVPKTINFO IPV6_PKTINFO
628
#endif
629
630
0
    int enabled = 1;
631
0
    if (setsockopt(listenFd, IPPROTO_IPV6, IPV6_RECVPKTINFO, (void *) &enabled, sizeof(enabled)) == -1) {
632
0
        if (errno == 92) {
633
0
            if (setsockopt(listenFd, IPPROTO_IP, IP_PKTINFO, (void *) &enabled, sizeof(enabled)) != 0) {
634
0
                printf("Error setting IPv4 pktinfo!\n");
635
0
            }
636
0
        } else {
637
0
            printf("Error setting IPv6 pktinfo!\n");
638
0
        }
639
0
    }
640
641
    /* These are used for getting the ECN */
642
0
    if (setsockopt(listenFd, IPPROTO_IPV6, IPV6_RECVTCLASS, (void *) &enabled, sizeof(enabled)) == -1) {
643
0
        if (errno == 92) {
644
0
            if (setsockopt(listenFd, IPPROTO_IP, IP_RECVTOS, (void *) &enabled, sizeof(enabled)) != 0) {
645
0
                printf("Error setting IPv4 ECN!\n");
646
0
            }
647
0
        } else {
648
0
            printf("Error setting IPv6 ECN!\n");
649
0
        }
650
0
    }
651
652
    /* We bind here as well */
653
0
    if (bind(listenFd, listenAddr->ai_addr, (socklen_t) listenAddr->ai_addrlen)) {
654
0
        bsd_close_socket(listenFd);
655
0
        freeaddrinfo(result);
656
0
        return LIBUS_SOCKET_ERROR;
657
0
    }
658
659
0
    freeaddrinfo(result);
660
0
    return listenFd;
661
0
}
662
663
0
int bsd_udp_packet_buffer_ecn(void *msgvec, int index) {
664
665
#if defined(_WIN32) || defined(__APPLE__)
666
    printf("ECN not supported!\n");
667
#else
668
    // we should iterate all control messages once, after recvmmsg and then only fetch them with these functions
669
0
    struct msghdr *mh = &((struct mmsghdr *) msgvec)[index].msg_hdr;
670
0
    for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(mh); cmsg != NULL; cmsg = CMSG_NXTHDR(mh, cmsg)) {
671
        // do we need to get TOS from ipv6 also?
672
0
        if (cmsg->cmsg_level == IPPROTO_IP) {
673
0
            if (cmsg->cmsg_type == IP_TOS) {
674
0
                uint8_t tos = *(uint8_t *)CMSG_DATA(cmsg);
675
0
                return tos & 3;
676
0
            }
677
0
        }
678
679
0
        if (cmsg->cmsg_level == IPPROTO_IPV6) {
680
0
            if (cmsg->cmsg_type == IPV6_TCLASS) {
681
                // is this correct?
682
0
                uint8_t tos = *(uint8_t *)CMSG_DATA(cmsg);
683
0
                return tos & 3;
684
0
            }
685
0
        }
686
0
    }
687
0
#endif
688
689
0
    printf("We got no ECN!\n");
690
691
0
    return 0; // no ecn defaults to 0
692
0
}
693
694
0
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(const char *host, int port, const char *source_host, int options) {
695
0
    struct addrinfo hints, *result;
696
0
    memset(&hints, 0, sizeof(struct addrinfo));
697
0
    hints.ai_family = AF_UNSPEC;
698
0
    hints.ai_socktype = SOCK_STREAM;
699
700
0
    char port_string[16];
701
0
    snprintf(port_string, 16, "%d", port);
702
703
0
    if (getaddrinfo(host, port_string, &hints, &result) != 0) {
704
0
        return LIBUS_SOCKET_ERROR;
705
0
    }
706
707
0
    LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_socket(result->ai_family, result->ai_socktype, result->ai_protocol);
708
0
    if (fd == LIBUS_SOCKET_ERROR) {
709
0
        freeaddrinfo(result);
710
0
        return LIBUS_SOCKET_ERROR;
711
0
    }
712
713
0
    if (source_host) {
714
0
        struct addrinfo *interface_result;
715
0
        if (!getaddrinfo(source_host, NULL, NULL, &interface_result)) {
716
0
            int ret = bind(fd, interface_result->ai_addr, (socklen_t) interface_result->ai_addrlen);
717
0
            freeaddrinfo(interface_result);
718
0
            if (ret == LIBUS_SOCKET_ERROR) {
719
0
                bsd_close_socket(fd);
720
0
                freeaddrinfo(result);
721
0
                return LIBUS_SOCKET_ERROR;
722
0
            }
723
0
        }
724
0
    }
725
726
0
    connect(fd, result->ai_addr, (socklen_t) result->ai_addrlen);
727
0
    freeaddrinfo(result);
728
729
0
    return fd;
730
0
}
731
732
0
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket_unix(const char *server_path, int options) {
733
734
0
    struct sockaddr_un server_address;
735
0
    memset(&server_address, 0, sizeof(server_address));
736
0
    server_address.sun_family = AF_UNIX;
737
0
    strcpy(server_address.sun_path, server_path);
738
0
    int size = offsetof(struct sockaddr_un, sun_path) + strlen(server_address.sun_path);
739
740
0
    LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_socket(AF_UNIX, SOCK_STREAM, 0);
741
742
0
    if (fd == LIBUS_SOCKET_ERROR) {
743
0
        return LIBUS_SOCKET_ERROR;
744
0
    }
745
746
0
    connect(fd, (struct sockaddr *)&server_address, size);
747
748
0
    return fd;
749
0
}