1 /* 2 * Copyright (C) 2024 Jo-Philipp Wich <jo@mein.io> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /** 18 * # Socket Module 19 * 20 * The `socket` module provides functions for interacting with sockets. 21 * 22 * Functions can be individually imported and directly accessed using the 23 * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#named_import named import} 24 * syntax: 25 * 26 * ```javascript 27 * import { AF_INET, SOCK_STREAM, create as socket } from 'socket'; 28 * 29 * let sock = socket(AF_INET, SOCK_STREAM, 0); 30 * sock.connect('192.168.1.1', 80); 31 * sock.send(…); 32 * sock.recv(…); 33 * sock.close(); 34 * ``` 35 * 36 * Alternatively, the module namespace can be imported 37 * using a wildcard import statement: 38 * 39 * ```javascript 40 * import * as socket from 'socket'; 41 * 42 * let sock = socket.create(socket.AF_INET, socket.SOCK_STREAM, 0); 43 * sock.connect('192.168.1.1', 80); 44 * sock.send(…); 45 * sock.recv(…); 46 * sock.close(); 47 * ``` 48 * 49 * Additionally, the socket module namespace may also be imported by invoking 50 * the `ucode` interpreter with the `-lsocket` switch. 51 * 52 * @module socket 53 */ 54 55 #include <errno.h> 56 #include <ctype.h> 57 #include <sys/stat.h> 58 #include <sys/un.h> 59 #include <netinet/tcp.h> 60 #include <netinet/udp.h> 61 #include <arpa/inet.h> 62 #include <unistd.h> 63 #include <fcntl.h> 64 #include <net/if.h> 65 #include <netdb.h> 66 #include <poll.h> 67 #include <limits.h> 68 #include <dirent.h> 69 70 #include "ucode/module.h" 71 72 #if defined(__linux__) 73 # include <linux/in6.h> 74 # include <linux/if_packet.h> 75 # include <linux/filter.h> 76 # include <linux/can.h> 77 # include <linux/can/raw.h> 78 79 # ifndef SO_TIMESTAMP_OLD 80 # define SO_TIMESTAMP_OLD SO_TIMESTAMP 81 # endif 82 83 # ifndef SO_TIMESTAMPNS_OLD 84 # define SO_TIMESTAMPNS_OLD SO_TIMESTAMP 85 # endif 86 #endif 87 88 #if defined(__APPLE__) 89 # include <sys/ucred.h> 90 91 # define SOCK_NONBLOCK (1 << 16) 92 # define SOCK_CLOEXEC (1 << 17) 93 #endif 94 95 #ifndef NI_IDN 96 # define NI_IDN 0 97 #endif 98 99 #ifndef AI_IDN 100 # define AI_IDN 0 101 #endif 102 103 #ifndef AI_CANONIDN 104 # define AI_CANONIDN 0 105 #endif 106 107 #ifndef IPV6_FLOWINFO 108 # define IPV6_FLOWINFO 11 109 #endif 110 111 #ifndef IPV6_FLOWLABEL_MGR 112 # define IPV6_FLOWLABEL_MGR 32 113 #endif 114 115 #ifndef IPV6_FLOWINFO_SEND 116 # define IPV6_FLOWINFO_SEND 33 117 #endif 118 119 #define ok_return(expr) do { set_error(0, NULL); return (expr); } while(0) 120 #define err_return(err, ...) do { set_error(err, __VA_ARGS__); return NULL; } while(0) 121 122 static struct { 123 int code; 124 char *msg; 125 } last_error; 126 127 __attribute__((format(printf, 2, 3))) static void 128 set_error(int errcode, const char *fmt, ...) 129 { 130 va_list ap; 131 132 free(last_error.msg); 133 134 last_error.code = errcode; 135 last_error.msg = NULL; 136 137 if (fmt) { 138 va_start(ap, fmt); 139 xvasprintf(&last_error.msg, fmt, ap); 140 va_end(ap); 141 } 142 } 143 144 static char * 145 arg_type_(uc_type_t type) 146 { 147 switch (type) { 148 case UC_INTEGER: return "an integer value"; 149 case UC_BOOLEAN: return "a boolean value"; 150 case UC_STRING: return "a string value"; 151 case UC_DOUBLE: return "a double value"; 152 case UC_ARRAY: return "an array"; 153 case UC_OBJECT: return "an object"; 154 case UC_REGEXP: return "a regular expression"; 155 case UC_CLOSURE: return "a function"; 156 case UC_RESOURCE: return "a resource value"; 157 default: return "the expected type"; 158 } 159 } 160 161 static bool 162 args_get_(uc_vm_t *vm, size_t nargs, int *fdptr, ...) 163 { 164 const char *name, *rtype = NULL; 165 uc_value_t **ptr, *arg; 166 uc_type_t type, t; 167 size_t index = 0; 168 int *sockfd; 169 va_list ap; 170 bool opt; 171 172 if (fdptr) { 173 sockfd = uc_fn_this("socket"); 174 175 if (!sockfd || *sockfd == -1) 176 err_return(EBADF, "Invalid socket context"); 177 178 *fdptr = *sockfd; 179 } 180 181 va_start(ap, fdptr); 182 183 while (true) { 184 name = va_arg(ap, const char *); 185 186 if (!name) 187 break; 188 189 arg = uc_fn_arg(index++); 190 191 type = va_arg(ap, uc_type_t); 192 opt = va_arg(ap, int); 193 ptr = va_arg(ap, uc_value_t **); 194 195 if (type == UC_RESOURCE) { 196 rtype = name; 197 name = strrchr(rtype, '.'); 198 name = name ? name + 1 : rtype; 199 200 if (arg && !ucv_resource_dataptr(arg, rtype)) 201 err_return(EINVAL, 202 "Argument %s is not a %s resource", name, rtype); 203 } 204 205 if (!opt && !arg) 206 err_return(EINVAL, 207 "Argument %s is required", name); 208 209 t = ucv_type(arg); 210 211 if (t == UC_CFUNCTION) 212 t = UC_CLOSURE; 213 214 if (arg && type != UC_NULL && t != type) 215 err_return(EINVAL, 216 "Argument %s is not %s", name, arg_type_(type)); 217 218 *ptr = arg; 219 } 220 221 va_end(ap); 222 223 ok_return(true); 224 } 225 226 #define args_get(vm, nargs, fdptr, ...) do { \ 227 if (!args_get_(vm, nargs, fdptr, ##__VA_ARGS__, NULL)) \ 228 return NULL; \ 229 } while(0) 230 231 static void 232 strbuf_free(uc_stringbuf_t *sb) 233 { 234 printbuf_free(sb); 235 } 236 237 static bool 238 strbuf_grow(uc_stringbuf_t *sb, size_t size) 239 { 240 if (size > 0) { 241 if (printbuf_memset(sb, sizeof(uc_string_t) + size - 1, '\0', 1)) 242 err_return(ENOMEM, "Out of memory"); 243 } 244 245 return true; 246 } 247 248 static char * 249 strbuf_data(uc_stringbuf_t *sb) 250 { 251 return sb->buf + sizeof(uc_string_t); 252 } 253 254 static size_t 255 strbuf_size(uc_stringbuf_t *sb) 256 { 257 return (size_t)sb->bpos - sizeof(uc_string_t); 258 } 259 260 static uc_value_t * 261 strbuf_finish(uc_stringbuf_t **sb, size_t final_size) 262 { 263 size_t buffer_size; 264 uc_string_t *us; 265 266 if (!sb || !*sb) 267 return NULL; 268 269 buffer_size = strbuf_size(*sb); 270 us = (uc_string_t *)(*sb)->buf; 271 272 if (final_size > buffer_size) 273 final_size = buffer_size; 274 275 free(*sb); 276 *sb = NULL; 277 278 us = xrealloc(us, sizeof(uc_string_t) + final_size + 1); 279 us->length = final_size; 280 us->str[us->length] = 0; 281 282 return &us->header; 283 } 284 285 static uc_stringbuf_t * 286 strbuf_alloc(size_t size) 287 { 288 uc_stringbuf_t *sb = ucv_stringbuf_new(); 289 290 if (!strbuf_grow(sb, size)) { 291 printbuf_free(sb); 292 293 return NULL; 294 } 295 296 return sb; 297 } 298 299 #if defined(__linux__) 300 static uc_value_t * 301 hwaddr_to_uv(uint8_t *addr, size_t alen) 302 { 303 char buf[sizeof("FF:FF:FF:FF:FF:FF:FF:FF")], *p = buf; 304 const char *hex = "0123456789ABCDEF"; 305 306 if (alen > 8) 307 alen = 8; 308 309 for (size_t i = 0; i < alen; i++) { 310 if (i) *p++ = ':'; 311 *p++ = hex[addr[i] / 16]; 312 *p++ = hex[addr[i] % 16]; 313 } 314 315 return ucv_string_new_length(buf, p - buf); 316 } 317 318 static bool 319 uv_to_hwaddr(uc_value_t *addr, uint8_t *out, size_t *outlen) 320 { 321 const char *p; 322 size_t len; 323 324 memset(out, 0, 8); 325 *outlen = 0; 326 327 if (ucv_type(addr) != UC_STRING) 328 goto err; 329 330 len = ucv_string_length(addr); 331 p = ucv_string_get(addr); 332 333 while (len > 0 && isxdigit(*p) && *outlen < 8) { 334 uint8_t n = (*p > '9') ? 10 + (*p|32) - 'a' : *p - ''; 335 p++, len--; 336 337 if (len > 0 && isxdigit(*p)) { 338 n = n * 16 + ((*p > '9') ? 10 + (*p|32) - 'a' : *p - ''); 339 p++, len--; 340 } 341 342 if (len > 0 && (*p == ':' || *p == '-' || *p == '.')) 343 p++, len--; 344 345 out[(*outlen)++] = n; 346 } 347 348 if (len == 0 || *p == 0) 349 return true; 350 351 err: 352 err_return(EINVAL, "Invalid hardware address"); 353 } 354 #endif 355 356 static bool 357 sockaddr_to_uv(struct sockaddr_storage *ss, uc_value_t *addrobj) 358 { 359 char *ifname, addrstr[INET6_ADDRSTRLEN]; 360 struct sockaddr_in6 *s6; 361 struct sockaddr_in *s4; 362 struct sockaddr_un *su; 363 #if defined(__linux__) 364 struct sockaddr_ll *sl; 365 struct sockaddr_can *sc; 366 #endif 367 368 ucv_object_add(addrobj, "family", ucv_uint64_new(ss->ss_family)); 369 370 switch (ss->ss_family) { 371 case AF_INET6: 372 s6 = (struct sockaddr_in6 *)ss; 373 374 inet_ntop(AF_INET6, &s6->sin6_addr, addrstr, sizeof(addrstr)); 375 ucv_object_add(addrobj, "address", 376 ucv_string_new(addrstr)); 377 378 ucv_object_add(addrobj, "port", 379 ucv_uint64_new(ntohs(s6->sin6_port))); 380 381 ucv_object_add(addrobj, "flowinfo", 382 ucv_uint64_new(ntohl(s6->sin6_flowinfo))); 383 384 if (s6->sin6_scope_id) { 385 ifname = if_indextoname(s6->sin6_scope_id, addrstr); 386 387 if (ifname) 388 ucv_object_add(addrobj, "interface", 389 ucv_string_new(ifname)); 390 else 391 ucv_object_add(addrobj, "interface", 392 ucv_uint64_new(s6->sin6_scope_id)); 393 } 394 395 return true; 396 397 case AF_INET: 398 s4 = (struct sockaddr_in *)ss; 399 400 inet_ntop(AF_INET, &s4->sin_addr, addrstr, sizeof(addrstr)); 401 ucv_object_add(addrobj, "address", 402 ucv_string_new(addrstr)); 403 404 ucv_object_add(addrobj, "port", 405 ucv_uint64_new(ntohs(s4->sin_port))); 406 407 return true; 408 409 case AF_UNIX: 410 su = (struct sockaddr_un *)ss; 411 412 ucv_object_add(addrobj, "path", 413 ucv_string_new(su->sun_path)); 414 415 return true; 416 417 #if defined(__linux__) 418 case AF_PACKET: 419 sl = (struct sockaddr_ll *)ss; 420 421 ucv_object_add(addrobj, "protocol", 422 ucv_uint64_new(ntohs(sl->sll_protocol))); 423 424 ifname = (sl->sll_ifindex > 0) 425 ? if_indextoname(sl->sll_ifindex, addrstr) : NULL; 426 427 if (ifname) 428 ucv_object_add(addrobj, "interface", 429 ucv_string_new(ifname)); 430 else if (sl->sll_ifindex != 0) 431 ucv_object_add(addrobj, "interface", 432 ucv_int64_new(sl->sll_ifindex)); 433 434 ucv_object_add(addrobj, "hardware_type", 435 ucv_uint64_new(sl->sll_hatype)); 436 437 ucv_object_add(addrobj, "packet_type", 438 ucv_uint64_new(sl->sll_pkttype)); 439 440 ucv_object_add(addrobj, "address", 441 hwaddr_to_uv(sl->sll_addr, sl->sll_halen)); 442 443 return true; 444 445 case AF_CAN: 446 sc = (struct sockaddr_can *)ss; 447 448 ifname = (sc->can_ifindex > 0) 449 ? if_indextoname(sc->can_ifindex, addrstr) : NULL; 450 451 if (ifname) 452 ucv_object_add(addrobj, "interface", 453 ucv_string_new(ifname)); 454 else if (sc->can_ifindex != 0) 455 ucv_object_add(addrobj, "interface", 456 ucv_int64_new(sc->can_ifindex)); 457 458 return true; 459 #endif 460 } 461 462 return false; 463 } 464 465 static int64_t 466 parse_integer(char *s, size_t len) 467 { 468 union { int8_t i8; int16_t i16; int32_t i32; int64_t i64; } v; 469 470 memcpy(&v, s, len < sizeof(v) ? len : sizeof(v)); 471 472 switch (len) { 473 case 1: return v.i8; 474 case 2: return v.i16; 475 case 4: return v.i32; 476 case 8: return v.i64; 477 default: return 0; 478 } 479 } 480 481 static uint64_t 482 parse_unsigned(char *s, size_t len) 483 { 484 union { uint8_t u8; uint16_t u16; uint32_t u32; uint64_t u64; } v; 485 486 memcpy(&v, s, len < sizeof(v) ? len : sizeof(v)); 487 488 switch (len) { 489 case 1: return v.u8; 490 case 2: return v.u16; 491 case 4: return v.u32; 492 case 8: return v.u64; 493 default: return 0; 494 } 495 } 496 497 static bool 498 parse_addr(char *addr, struct sockaddr_storage *ss) 499 { 500 bool v6 = (ss->ss_family == 0 || ss->ss_family == AF_INET6); 501 bool v4 = (ss->ss_family == 0 || ss->ss_family == AF_INET); 502 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ss; 503 struct sockaddr_in *s4 = (struct sockaddr_in *)ss; 504 unsigned long n; 505 char *scope, *e; 506 507 if (v6 && (scope = strchr(addr, '%')) != NULL) { 508 *scope++ = 0; 509 n = strtoul(scope, &e, 10); 510 511 if (e == scope || *e != 0) { 512 n = if_nametoindex(scope); 513 514 if (n == 0) 515 err_return(errno, "Unable to resolve interface %s", scope); 516 } 517 518 if (inet_pton(AF_INET6, addr, &s6->sin6_addr) != 1) 519 err_return(errno, "Invalid IPv6 address"); 520 521 s6->sin6_family = AF_INET6; 522 s6->sin6_scope_id = n; 523 524 return true; 525 } 526 else if (v6 && inet_pton(AF_INET6, addr, &s6->sin6_addr) == 1) { 527 s6->sin6_family = AF_INET6; 528 529 return true; 530 } 531 else if (v4 && inet_pton(AF_INET, addr, &s4->sin_addr) == 1) { 532 s4->sin_family = AF_INET; 533 534 return true; 535 } 536 537 err_return(EINVAL, "Unable to parse IP address"); 538 } 539 540 static bool 541 uv_to_sockaddr(uc_value_t *addr, struct sockaddr_storage *ss, socklen_t *slen) 542 { 543 char *s, *p, addrstr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255%interface012345")]; 544 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ss; 545 struct sockaddr_in *s4 = (struct sockaddr_in *)ss; 546 struct sockaddr_un *su = (struct sockaddr_un *)ss; 547 #if defined(__linux__) 548 struct sockaddr_ll *sl = (struct sockaddr_ll *)ss; 549 struct sockaddr_can *sc = (struct sockaddr_can *)ss; 550 #endif 551 uc_value_t *item; 552 unsigned long n; 553 size_t len; 554 555 memset(ss, 0, sizeof(*ss)); 556 557 if (ucv_type(addr) == UC_STRING) { 558 s = ucv_string_get(addr); 559 len = ucv_string_length(addr); 560 561 if (memchr(s, '/', len) != NULL) { 562 if (len >= sizeof(su->sun_path)) 563 len = sizeof(su->sun_path) - 1; 564 565 memcpy(su->sun_path, s, len); 566 su->sun_path[len++] = 0; 567 su->sun_family = AF_UNIX; 568 *slen = sizeof(*su); 569 570 ok_return(true); 571 } 572 573 if (len == 0) 574 err_return(EINVAL, "Invalid IP address"); 575 576 if (*s == '[') { 577 p = memchr(++s, ']', --len); 578 579 if (!p || (size_t)(p - s) >= sizeof(addrstr)) 580 err_return(EINVAL, "Invalid IPv6 address"); 581 582 memcpy(addrstr, s, p - s); 583 addrstr[p - s] = 0; 584 585 ss->ss_family = AF_INET6; 586 len -= ((p - s) + 1); 587 s = p + 1; 588 } 589 else if ((p = memchr(s, ':', len)) != NULL && 590 memchr(p + 1, ':', len - ((p - s) + 1)) == NULL) { 591 if ((size_t)(p - s) >= sizeof(addrstr)) 592 err_return(EINVAL, "Invalid IP address"); 593 594 memcpy(addrstr, s, p - s); 595 addrstr[p - s] = 0; 596 597 ss->ss_family = AF_INET; 598 len -= (p - s); 599 s = p; 600 } 601 else { 602 if (len >= sizeof(addrstr)) 603 err_return(EINVAL, "Invalid IP address"); 604 605 memcpy(addrstr, s, len); 606 addrstr[len] = 0; 607 608 ss->ss_family = 0; 609 len = 0; 610 s = NULL; 611 } 612 613 if (!parse_addr(addrstr, ss)) 614 return NULL; 615 616 if (s && *s == ':') { 617 if (len <= 1) 618 err_return(EINVAL, "Invalid port number"); 619 620 for (s++, len--, n = 0; len > 0; len--, s++) { 621 if (*s < '' || *s > '9') 622 err_return(EINVAL, "Invalid port number"); 623 624 n = n * 10 + (*s - ''); 625 } 626 627 if (n > 65535) 628 err_return(EINVAL, "Invalid port number"); 629 630 s6->sin6_port = htons(n); 631 } 632 633 *slen = (ss->ss_family == AF_INET6) ? sizeof(*s6) : sizeof(*s4); 634 635 ok_return(true); 636 } 637 else if (ucv_type(addr) == UC_ARRAY) { 638 if (ucv_array_length(addr) == 16) { 639 uint8_t *u8 = (uint8_t *)&s6->sin6_addr; 640 641 for (size_t i = 0; i < 16; i++) { 642 item = ucv_array_get(addr, i); 643 n = ucv_uint64_get(item); 644 645 if (ucv_type(item) != UC_INTEGER || errno != 0 || n > 255) 646 err_return(EINVAL, "Invalid IP address array"); 647 648 u8[i] = n; 649 } 650 651 s6->sin6_family = AF_INET6; 652 *slen = sizeof(*s6); 653 654 ok_return(true); 655 } 656 else if (ucv_array_length(addr) == 4) { 657 s4->sin_addr.s_addr = 0; 658 659 for (size_t i = 0; i < 4; i++) { 660 item = ucv_array_get(addr, i); 661 n = ucv_uint64_get(item); 662 663 if (ucv_type(item) != UC_INTEGER || errno != 0 || n > 255) 664 err_return(EINVAL, "Invalid IP address array"); 665 666 s4->sin_addr.s_addr = s4->sin_addr.s_addr * 256 + n; 667 } 668 669 s4->sin_addr.s_addr = htonl(s4->sin_addr.s_addr); 670 s4->sin_family = AF_INET; 671 *slen = sizeof(*s4); 672 673 ok_return(true); 674 } 675 676 err_return(EINVAL, "Invalid IP address array"); 677 } 678 else if (ucv_type(addr) == UC_OBJECT) { 679 n = ucv_to_unsigned(ucv_object_get(addr, "family", NULL)); 680 681 if (n == 0) { 682 if (ucv_type(ucv_object_get(addr, "path", NULL)) == UC_STRING) { 683 n = AF_UNIX; 684 } 685 else { 686 item = ucv_object_get(addr, "address", NULL); 687 len = ucv_string_length(item); 688 s = ucv_string_get(item); 689 n = (s && memchr(s, ':', len) != NULL) ? AF_INET6 : AF_INET; 690 } 691 692 if (n == 0) 693 err_return(EINVAL, "Invalid address object"); 694 } 695 696 switch (n) { 697 case AF_INET6: 698 item = ucv_object_get(addr, "flowinfo", NULL); 699 s6->sin6_flowinfo = htonl(ucv_to_unsigned(item)); 700 701 item = ucv_object_get(addr, "interface", NULL); 702 703 if (ucv_type(item) == UC_STRING) { 704 s6->sin6_scope_id = if_nametoindex(ucv_string_get(item)); 705 706 if (s6->sin6_scope_id == 0) 707 err_return(errno, "Unable to resolve interface %s", 708 ucv_string_get(item)); 709 } 710 else if (item != NULL) { 711 s6->sin6_scope_id = ucv_to_unsigned(item); 712 713 if (errno != 0) 714 err_return(errno, "Invalid scope ID"); 715 } 716 717 /* fall through */ 718 719 case AF_INET: 720 ss->ss_family = n; 721 *slen = (n == AF_INET6) ? sizeof(*s6) : sizeof(*s4); 722 723 item = ucv_object_get(addr, "port", NULL); 724 n = ucv_to_unsigned(item); 725 726 if (errno != 0 || n > 65535) 727 err_return(EINVAL, "Invalid port number"); 728 729 s6->sin6_port = htons(n); 730 731 item = ucv_object_get(addr, "address", NULL); 732 len = ucv_string_length(item); 733 s = ucv_string_get(item); 734 735 if (len >= sizeof(addrstr)) 736 err_return(EINVAL, "Invalid IP address"); 737 738 if (len > 0) { 739 memcpy(addrstr, s, len); 740 addrstr[len] = 0; 741 742 if (!parse_addr(addrstr, ss)) 743 return NULL; 744 } 745 746 ok_return(true); 747 748 case AF_UNIX: 749 item = ucv_object_get(addr, "path", NULL); 750 len = ucv_string_length(item); 751 752 if (len == 0 || len >= sizeof(su->sun_path)) 753 err_return(EINVAL, "Invalid path value"); 754 755 memcpy(su->sun_path, ucv_string_get(item), len); 756 su->sun_path[len++] = 0; 757 su->sun_family = AF_UNIX; 758 *slen = sizeof(*su); 759 760 ok_return(true); 761 762 #if defined(__linux__) 763 case AF_PACKET: 764 item = ucv_object_get(addr, "protocol", NULL); 765 766 if (item) { 767 n = ucv_to_unsigned(item); 768 769 if (errno != 0 || n > 65535) 770 err_return(EINVAL, "Invalid protocol number"); 771 772 sl->sll_protocol = htons(n); 773 } 774 775 item = ucv_object_get(addr, "address", NULL); 776 777 if (uv_to_hwaddr(item, sl->sll_addr, &len)) 778 sl->sll_halen = len; 779 else 780 return false; 781 782 item = ucv_object_get(addr, "interface", NULL); 783 784 if (ucv_type(item) == UC_STRING) { 785 sl->sll_ifindex = if_nametoindex(ucv_string_get(item)); 786 787 if (sl->sll_ifindex == 0) 788 err_return(errno, "Unable to resolve interface %s", 789 ucv_string_get(item)); 790 } 791 else if (item != NULL) { 792 sl->sll_ifindex = ucv_to_integer(item); 793 794 if (errno) 795 err_return(errno, "Unable to convert interface to integer"); 796 } 797 798 item = ucv_object_get(addr, "hardware_type", NULL); 799 800 if (item) { 801 n = ucv_to_unsigned(item); 802 803 if (errno != 0 || n > 65535) 804 err_return(EINVAL, "Invalid hardware type"); 805 806 sl->sll_hatype = n; 807 } 808 809 item = ucv_object_get(addr, "packet_type", NULL); 810 811 if (item) { 812 n = ucv_to_unsigned(item); 813 814 if (errno != 0 || n > 255) 815 err_return(EINVAL, "Invalid packet type"); 816 817 sl->sll_pkttype = n; 818 } 819 820 sl->sll_family = AF_PACKET; 821 *slen = sizeof(*sl); 822 823 ok_return(true); 824 825 case AF_CAN: 826 item = ucv_object_get(addr, "interface", NULL); 827 828 if (ucv_type(item) == UC_STRING) { 829 sc->can_ifindex = if_nametoindex(ucv_string_get(item)); 830 831 if (sc->can_ifindex == 0) 832 err_return(errno, "Unable to resolve interface %s", 833 ucv_string_get(item)); 834 } 835 else if (item != NULL) { 836 sc->can_ifindex = ucv_to_integer(item); 837 838 if (errno) 839 err_return(errno, "Unable to convert interface to integer"); 840 } 841 842 sc->can_family = AF_CAN; 843 *slen = sizeof(*sc); 844 845 ok_return(true); 846 #endif 847 } 848 } 849 850 err_return(EINVAL, "Invalid address value"); 851 } 852 853 static bool 854 uv_to_fileno(uc_vm_t *vm, uc_value_t *val, int *fileno) 855 { 856 uc_value_t *fn; 857 int *fdptr; 858 859 fdptr = (int *)ucv_resource_dataptr(val, "socket"); 860 861 if (fdptr) { 862 if (*fdptr < 0) 863 err_return(EBADF, "Socket is closed"); 864 865 *fileno = *fdptr; 866 867 return true; 868 } 869 870 fn = ucv_property_get(val, "fileno"); 871 872 if (ucv_is_callable(fn)) { 873 uc_vm_stack_push(vm, ucv_get(val)); 874 uc_vm_stack_push(vm, ucv_get(fn)); 875 876 if (uc_vm_call(vm, true, 0) != EXCEPTION_NONE) 877 return false; 878 879 val = uc_vm_stack_pop(vm); 880 } 881 else { 882 ucv_get(val); 883 } 884 885 *fileno = ucv_int64_get(val); 886 887 ucv_put(val); 888 889 if (errno != 0 || *fileno < 0) 890 err_return(EBADF, "Invalid file descriptor number"); 891 892 return true; 893 } 894 895 static uc_value_t * 896 uv_to_pollfd(uc_vm_t *vm, uc_value_t *val, struct pollfd *pfd) 897 { 898 uc_value_t *rv; 899 int64_t flags; 900 901 if (ucv_type(val) == UC_ARRAY) { 902 if (!uv_to_fileno(vm, ucv_array_get(val, 0), &pfd->fd)) 903 return NULL; 904 905 flags = ucv_to_integer(ucv_array_get(val, 1)); 906 907 if (errno != 0 || flags < -32768 || flags > 32767) 908 err_return(ERANGE, "Flags value out of range"); 909 910 pfd->events = flags; 911 pfd->revents = 0; 912 913 return ucv_get(val); 914 } 915 916 if (!uv_to_fileno(vm, val, &pfd->fd)) 917 return NULL; 918 919 pfd->events = POLLIN | POLLERR | POLLHUP; 920 pfd->revents = 0; 921 922 rv = ucv_array_new_length(vm, 2); 923 924 ucv_array_set(rv, 0, ucv_get(val)); 925 ucv_array_set(rv, 1, ucv_uint64_new(pfd->events)); 926 927 return rv; 928 } 929 930 static uc_value_t * 931 ucv_socket_new(uc_vm_t *vm, int fd) 932 { 933 return ucv_resource_new( 934 ucv_resource_type_lookup(vm, "socket"), 935 (void *)(intptr_t)fd 936 ); 937 } 938 939 static bool 940 xclose(int *fdptr) 941 { 942 bool rv = true; 943 944 if (fdptr) { 945 if (*fdptr >= 0) 946 rv = (close(*fdptr) == 0); 947 948 *fdptr = -1; 949 } 950 951 return rv; 952 } 953 954 955 typedef struct { 956 const char *name; 957 enum { DT_SIGNED, DT_UNSIGNED, DT_IPV4ADDR, DT_IPV6ADDR, DT_CALLBACK } type; 958 union { 959 size_t offset; 960 bool (*to_c)(void *, uc_value_t *); 961 } u1; 962 union { 963 size_t size; 964 uc_value_t *(*to_uv)(void *); 965 } u2; 966 } member_t; 967 968 typedef struct { 969 size_t size; 970 member_t *members; 971 } struct_t; 972 973 typedef struct { 974 int level; 975 int option; 976 struct_t *ctype; 977 } sockopt_t; 978 979 typedef struct { 980 int level; 981 int type; 982 struct_t *ctype; 983 } cmsgtype_t; 984 985 #define STRUCT_MEMBER_NP(struct_name, member_name, data_type) \ 986 { #member_name, data_type, \ 987 { .offset = offsetof(struct struct_name, member_name) }, \ 988 { .size = sizeof(((struct struct_name *)NULL)->member_name) } } 989 990 #define STRUCT_MEMBER_CB(member_name, to_c_fn, to_uv_fn) \ 991 { #member_name, DT_CALLBACK, { .to_c = to_c_fn }, { .to_uv = to_uv_fn } } 992 993 #define STRUCT_MEMBER(struct_name, member_prefix, member_name, data_type) \ 994 { #member_name, data_type, \ 995 { .offset = offsetof(struct struct_name, member_prefix##_##member_name) }, \ 996 { .size = sizeof(((struct struct_name *)NULL)->member_prefix##_##member_name) } } 997 998 static struct_t st_timeval = { 999 .size = sizeof(struct timeval), 1000 .members = (member_t []){ 1001 STRUCT_MEMBER(timeval, tv, sec, DT_SIGNED), 1002 STRUCT_MEMBER(timeval, tv, usec, DT_SIGNED), 1003 { 0 } 1004 } 1005 }; 1006 1007 #if defined(__linux__) 1008 static bool 1009 filter_to_c(void *st, uc_value_t *uv) 1010 { 1011 struct sock_fprog **fpp = st; 1012 struct sock_fprog *fp = *fpp; 1013 size_t i, len; 1014 1015 if (ucv_type(uv) == UC_STRING) { 1016 size_t len = ucv_string_length(uv); 1017 1018 if (len == 0 || (len % sizeof(struct sock_filter)) != 0) 1019 err_return(EINVAL, "Filter program length not a multiple of %zu", 1020 sizeof(struct sock_filter)); 1021 1022 fp = *fpp = xrealloc(fp, sizeof(struct sock_fprog) + len); 1023 fp->filter = memcpy((char *)fp + sizeof(struct sock_fprog), ucv_string_get(uv), len); 1024 1025 if (fp->len == 0) 1026 fp->len = len / sizeof(struct sock_filter); 1027 } 1028 else if (ucv_type(uv) == UC_ARRAY) { 1029 /* Opcode array of array. Each sub-array is a 4 element tuple */ 1030 if (ucv_type(ucv_array_get(uv, 0)) == UC_ARRAY) { 1031 len = ucv_array_length(uv); 1032 1033 fp = *fpp = xrealloc(fp, sizeof(struct sock_fprog) 1034 + (len * sizeof(struct sock_filter))); 1035 1036 fp->filter = (struct sock_filter *)((char *)fp + sizeof(struct sock_fprog)); 1037 1038 for (i = 0; i < len; i++) { 1039 uc_value_t *op = ucv_array_get(uv, i); 1040 1041 if (ucv_type(op) != UC_ARRAY) 1042 continue; 1043 1044 fp->filter[i].code = ucv_to_unsigned(ucv_array_get(op, 0)); 1045 fp->filter[i].jt = ucv_to_unsigned(ucv_array_get(op, 1)); 1046 fp->filter[i].jf = ucv_to_unsigned(ucv_array_get(op, 2)); 1047 fp->filter[i].k = ucv_to_unsigned(ucv_array_get(op, 3)); 1048 } 1049 } 1050 1051 /* Flat opcode array, must be a multiple of 4 */ 1052 else { 1053 len = ucv_array_length(uv); 1054 1055 if (len % 4) 1056 err_return(EINVAL, "Opcode array length not a multiple of 4"); 1057 1058 len /= 4; 1059 1060 fp = *fpp = xrealloc(fp, sizeof(struct sock_fprog) 1061 + (len * sizeof(struct sock_filter))); 1062 1063 fp->filter = (struct sock_filter *)((char *)fp + sizeof(struct sock_fprog)); 1064 1065 for (i = 0; i < len; i++) { 1066 fp->filter[i].code = ucv_to_unsigned(ucv_array_get(uv, i * 4 + 0)); 1067 fp->filter[i].jt = ucv_to_unsigned(ucv_array_get(uv, i * 4 + 1)); 1068 fp->filter[i].jf = ucv_to_unsigned(ucv_array_get(uv, i * 4 + 2)); 1069 fp->filter[i].k = ucv_to_unsigned(ucv_array_get(uv, i * 4 + 3)); 1070 } 1071 } 1072 1073 if (fp->len == 0) 1074 fp->len = i; 1075 } 1076 else { 1077 err_return(EINVAL, "Expecting either BPF bytecode string or array of opcodes"); 1078 } 1079 1080 return true; 1081 } 1082 1083 static struct_t st_sock_fprog = { 1084 .size = sizeof(struct sock_fprog), 1085 .members = (member_t []){ 1086 STRUCT_MEMBER_NP(sock_fprog, len, DT_UNSIGNED), 1087 STRUCT_MEMBER_CB(filter, filter_to_c, NULL), 1088 { 0 } 1089 } 1090 }; 1091 1092 static struct_t st_ucred = { 1093 .size = sizeof(struct ucred), 1094 .members = (member_t []){ 1095 STRUCT_MEMBER_NP(ucred, pid, DT_SIGNED), 1096 STRUCT_MEMBER_NP(ucred, uid, DT_SIGNED), 1097 STRUCT_MEMBER_NP(ucred, gid, DT_SIGNED), 1098 { 0 } 1099 } 1100 }; 1101 #endif 1102 1103 static struct_t st_linger = { 1104 .size = sizeof(struct linger), 1105 .members = (member_t []){ 1106 STRUCT_MEMBER(linger, l, onoff, DT_SIGNED), 1107 STRUCT_MEMBER(linger, l, linger, DT_SIGNED), 1108 { 0 } 1109 } 1110 }; 1111 1112 static struct_t st_ip_mreqn = { 1113 .size = sizeof(struct ip_mreqn), 1114 .members = (member_t []){ 1115 STRUCT_MEMBER(ip_mreqn, imr, multiaddr, DT_IPV4ADDR), 1116 STRUCT_MEMBER(ip_mreqn, imr, address, DT_IPV4ADDR), 1117 STRUCT_MEMBER(ip_mreqn, imr, ifindex, DT_SIGNED), 1118 { 0 } 1119 } 1120 }; 1121 1122 static struct_t st_ip_mreq_source = { 1123 .size = sizeof(struct ip_mreq_source), 1124 .members = (member_t []){ 1125 STRUCT_MEMBER(ip_mreq_source, imr, multiaddr, DT_IPV4ADDR), 1126 STRUCT_MEMBER(ip_mreq_source, imr, interface, DT_IPV4ADDR), 1127 STRUCT_MEMBER(ip_mreq_source, imr, sourceaddr, DT_IPV4ADDR), 1128 { 0 } 1129 } 1130 }; 1131 1132 /* This structure is declared in kernel, but not libc headers, so redeclare it 1133 locally */ 1134 struct in6_flowlabel_req_local { 1135 struct in6_addr flr_dst; 1136 uint32_t flr_label; 1137 uint8_t flr_action; 1138 uint8_t flr_share; 1139 uint16_t flr_flags; 1140 uint16_t flr_expires; 1141 uint16_t flr_linger; 1142 }; 1143 1144 static struct_t st_in6_flowlabel_req = { 1145 .size = sizeof(struct in6_flowlabel_req_local), 1146 .members = (member_t []){ 1147 STRUCT_MEMBER(in6_flowlabel_req_local, flr, dst, DT_IPV6ADDR), 1148 STRUCT_MEMBER(in6_flowlabel_req_local, flr, label, DT_UNSIGNED), 1149 STRUCT_MEMBER(in6_flowlabel_req_local, flr, action, DT_UNSIGNED), 1150 STRUCT_MEMBER(in6_flowlabel_req_local, flr, share, DT_UNSIGNED), 1151 STRUCT_MEMBER(in6_flowlabel_req_local, flr, flags, DT_UNSIGNED), 1152 STRUCT_MEMBER(in6_flowlabel_req_local, flr, expires, DT_UNSIGNED), 1153 STRUCT_MEMBER(in6_flowlabel_req_local, flr, linger, DT_UNSIGNED), 1154 { 0 } 1155 } 1156 }; 1157 1158 #if defined(__linux__) 1159 static uc_value_t * 1160 in6_ifindex_to_uv(void *st) 1161 { 1162 char ifname[IF_NAMESIZE] = { 0 }; 1163 struct ipv6_mreq *mr = st; 1164 1165 if (mr->ipv6mr_interface > 0 && if_indextoname(mr->ipv6mr_interface, ifname)) 1166 return ucv_string_new(ifname); 1167 1168 return ucv_int64_new(mr->ipv6mr_interface); 1169 } 1170 1171 static bool 1172 in6_ifindex_to_c(void *st, uc_value_t *uv) 1173 { 1174 struct ipv6_mreq *mr = *(struct ipv6_mreq **)st; 1175 1176 if (ucv_type(uv) == UC_STRING) { 1177 mr->ipv6mr_interface = if_nametoindex(ucv_string_get(uv)); 1178 1179 if (mr->ipv6mr_interface == 0) 1180 err_return(errno, "Unable to resolve interface %s", 1181 ucv_string_get(uv)); 1182 } 1183 else { 1184 mr->ipv6mr_interface = ucv_to_integer(uv); 1185 1186 if (errno) 1187 err_return(errno, "Unable to convert interface to integer"); 1188 } 1189 1190 return true; 1191 } 1192 1193 static struct_t st_ipv6_mreq = { 1194 .size = sizeof(struct ipv6_mreq), 1195 .members = (member_t []){ 1196 STRUCT_MEMBER(ipv6_mreq, ipv6mr, multiaddr, DT_IPV6ADDR), 1197 STRUCT_MEMBER_CB(interface, in6_ifindex_to_c, in6_ifindex_to_uv), 1198 { 0 } 1199 } 1200 }; 1201 1202 /* NB: this is the same layout as struct ipv6_mreq, so we reuse the callbacks */ 1203 static struct_t st_in6_pktinfo = { 1204 .size = sizeof(struct in6_pktinfo), 1205 .members = (member_t []){ 1206 STRUCT_MEMBER(in6_pktinfo, ipi6, addr, DT_IPV6ADDR), 1207 STRUCT_MEMBER_CB(interface, in6_ifindex_to_c, in6_ifindex_to_uv), 1208 { 0 } 1209 } 1210 }; 1211 1212 struct ipv6_recv_error_local { 1213 struct { 1214 uint32_t ee_errno; 1215 uint8_t ee_origin; 1216 uint8_t ee_type; 1217 uint8_t ee_code; 1218 uint8_t ee_pad; 1219 uint32_t ee_info; 1220 union { 1221 uint32_t ee_data; 1222 struct { 1223 uint16_t ee_len; 1224 uint8_t ee_flags; 1225 uint8_t ee_reserved; 1226 } ee_rfc4884; 1227 } u; 1228 } ee; 1229 struct sockaddr_in6 offender; 1230 }; 1231 1232 static uc_value_t * 1233 offender_to_uv(void *st) 1234 { 1235 struct ipv6_recv_error_local *e = st; 1236 uc_value_t *addr = ucv_object_new(NULL); 1237 1238 if (sockaddr_to_uv((struct sockaddr_storage *)&e->offender, addr)) 1239 return addr; 1240 1241 ucv_put(addr); 1242 1243 return NULL; 1244 } 1245 1246 static struct_t st_ip_recv_error = { 1247 .size = sizeof(struct ipv6_recv_error_local), 1248 .members = (member_t []){ 1249 STRUCT_MEMBER(ipv6_recv_error_local, ee.ee, errno, DT_UNSIGNED), 1250 STRUCT_MEMBER(ipv6_recv_error_local, ee.ee, origin, DT_UNSIGNED), 1251 STRUCT_MEMBER(ipv6_recv_error_local, ee.ee, type, DT_UNSIGNED), 1252 STRUCT_MEMBER(ipv6_recv_error_local, ee.ee, code, DT_UNSIGNED), 1253 STRUCT_MEMBER(ipv6_recv_error_local, ee.ee, info, DT_UNSIGNED), 1254 STRUCT_MEMBER(ipv6_recv_error_local, ee.u.ee, data, DT_UNSIGNED), 1255 STRUCT_MEMBER(ipv6_recv_error_local, ee.u.ee_rfc4884.ee, len, DT_UNSIGNED), 1256 STRUCT_MEMBER(ipv6_recv_error_local, ee.u.ee_rfc4884.ee, flags, DT_UNSIGNED), 1257 STRUCT_MEMBER_CB(offender, NULL, offender_to_uv), 1258 { 0 } 1259 } 1260 }; 1261 1262 static uc_value_t * 1263 ip6m_addr_to_uv(void *st) 1264 { 1265 struct ip6_mtuinfo *mi = st; 1266 uc_value_t *addr = ucv_object_new(NULL); 1267 1268 if (sockaddr_to_uv((struct sockaddr_storage *)&mi->ip6m_addr, addr)) 1269 return addr; 1270 1271 ucv_put(addr); 1272 1273 return NULL; 1274 } 1275 1276 static struct_t st_ip6_mtuinfo = { 1277 .size = sizeof(struct ip6_mtuinfo), 1278 .members = (member_t []){ 1279 STRUCT_MEMBER_CB(addr, NULL, ip6m_addr_to_uv), 1280 STRUCT_MEMBER(ip6_mtuinfo, ip6m, mtu, DT_UNSIGNED), 1281 { 0 } 1282 } 1283 }; 1284 1285 static struct_t st_ip_msfilter = { 1286 .size = sizeof(struct ip_msfilter), 1287 .members = (member_t []){ 1288 STRUCT_MEMBER(ip_msfilter, imsf, multiaddr, DT_IPV4ADDR), 1289 STRUCT_MEMBER(ip_msfilter, imsf, interface, DT_IPV4ADDR), 1290 STRUCT_MEMBER(ip_msfilter, imsf, fmode, DT_SIGNED), 1291 STRUCT_MEMBER(ip_msfilter, imsf, numsrc, DT_SIGNED), 1292 STRUCT_MEMBER(ip_msfilter, imsf, slist, DT_SIGNED), 1293 { 0 } 1294 } 1295 }; 1296 1297 static uc_value_t * 1298 snd_wscale_to_uv(void *st) 1299 { 1300 return ucv_uint64_new(((struct tcp_info *)st)->tcpi_snd_wscale); 1301 } 1302 1303 static uc_value_t * 1304 rcv_wscale_to_uv(void *st) 1305 { 1306 return ucv_uint64_new(((struct tcp_info *)st)->tcpi_rcv_wscale); 1307 } 1308 1309 static bool 1310 snd_wscale_to_c(void *st, uc_value_t *uv) 1311 { 1312 struct tcp_info *ti = *(struct tcp_info **)st; 1313 1314 ti->tcpi_snd_wscale = ucv_to_unsigned(uv); 1315 1316 if (errno) 1317 err_return(errno, "Unable to convert field snd_wscale to unsigned"); 1318 1319 return true; 1320 } 1321 1322 static bool 1323 rcv_wscale_to_c(void *st, uc_value_t *uv) 1324 { 1325 struct tcp_info *ti = *(struct tcp_info **)st; 1326 1327 ti->tcpi_rcv_wscale = ucv_to_unsigned(uv); 1328 1329 if (errno) 1330 err_return(errno, "Unable to convert field rcv_wscale to unsigned"); 1331 1332 return true; 1333 } 1334 1335 static struct_t st_tcp_info = { 1336 .size = sizeof(struct tcp_info), 1337 .members = (member_t []){ 1338 STRUCT_MEMBER(tcp_info, tcpi, state, DT_UNSIGNED), 1339 STRUCT_MEMBER(tcp_info, tcpi, ca_state, DT_UNSIGNED), 1340 STRUCT_MEMBER(tcp_info, tcpi, retransmits, DT_UNSIGNED), 1341 STRUCT_MEMBER(tcp_info, tcpi, probes, DT_UNSIGNED), 1342 STRUCT_MEMBER(tcp_info, tcpi, backoff, DT_UNSIGNED), 1343 STRUCT_MEMBER(tcp_info, tcpi, options, DT_UNSIGNED), 1344 STRUCT_MEMBER_CB(snd_wscale, snd_wscale_to_c, snd_wscale_to_uv), 1345 STRUCT_MEMBER_CB(rcv_wscale, rcv_wscale_to_c, rcv_wscale_to_uv), 1346 STRUCT_MEMBER(tcp_info, tcpi, rto, DT_UNSIGNED), 1347 STRUCT_MEMBER(tcp_info, tcpi, ato, DT_UNSIGNED), 1348 STRUCT_MEMBER(tcp_info, tcpi, snd_mss, DT_UNSIGNED), 1349 STRUCT_MEMBER(tcp_info, tcpi, rcv_mss, DT_UNSIGNED), 1350 STRUCT_MEMBER(tcp_info, tcpi, unacked, DT_UNSIGNED), 1351 STRUCT_MEMBER(tcp_info, tcpi, sacked, DT_UNSIGNED), 1352 STRUCT_MEMBER(tcp_info, tcpi, lost, DT_UNSIGNED), 1353 STRUCT_MEMBER(tcp_info, tcpi, retrans, DT_UNSIGNED), 1354 STRUCT_MEMBER(tcp_info, tcpi, fackets, DT_UNSIGNED), 1355 STRUCT_MEMBER(tcp_info, tcpi, last_data_sent, DT_UNSIGNED), 1356 STRUCT_MEMBER(tcp_info, tcpi, last_ack_sent, DT_UNSIGNED), 1357 STRUCT_MEMBER(tcp_info, tcpi, last_data_recv, DT_UNSIGNED), 1358 STRUCT_MEMBER(tcp_info, tcpi, last_ack_recv, DT_UNSIGNED), 1359 STRUCT_MEMBER(tcp_info, tcpi, pmtu, DT_UNSIGNED), 1360 STRUCT_MEMBER(tcp_info, tcpi, rcv_ssthresh, DT_UNSIGNED), 1361 STRUCT_MEMBER(tcp_info, tcpi, rtt, DT_UNSIGNED), 1362 STRUCT_MEMBER(tcp_info, tcpi, rttvar, DT_UNSIGNED), 1363 STRUCT_MEMBER(tcp_info, tcpi, snd_ssthresh, DT_UNSIGNED), 1364 STRUCT_MEMBER(tcp_info, tcpi, snd_cwnd, DT_UNSIGNED), 1365 STRUCT_MEMBER(tcp_info, tcpi, advmss, DT_UNSIGNED), 1366 STRUCT_MEMBER(tcp_info, tcpi, reordering, DT_UNSIGNED), 1367 STRUCT_MEMBER(tcp_info, tcpi, rcv_rtt, DT_UNSIGNED), 1368 STRUCT_MEMBER(tcp_info, tcpi, rcv_space, DT_UNSIGNED), 1369 STRUCT_MEMBER(tcp_info, tcpi, total_retrans, DT_UNSIGNED), 1370 { 0 } 1371 } 1372 }; 1373 #endif 1374 1375 static uc_value_t * 1376 ai_addr_to_uv(void *st) 1377 { 1378 uc_value_t *rv = ucv_object_new(NULL); 1379 struct sockaddr_storage ss = { 0 }; 1380 struct addrinfo *ai = st; 1381 1382 memcpy(&ss, ai->ai_addr, ai->ai_addrlen); 1383 1384 if (!sockaddr_to_uv(&ss, rv)) { 1385 ucv_put(rv); 1386 return NULL; 1387 } 1388 1389 return rv; 1390 } 1391 1392 static uc_value_t * 1393 ai_canonname_to_uv(void *st) 1394 { 1395 struct addrinfo *ai = st; 1396 return ai->ai_canonname ? ucv_string_new(ai->ai_canonname) : NULL; 1397 } 1398 1399 /** 1400 * Represents a network address information object returned by 1401 * {@link module:socket#addrinfo|`addrinfo()`}. 1402 * 1403 * @typedef {Object} module:socket.AddressInfo 1404 * 1405 * @property {module:socket.socket.SocketAddress} addr - A socket address structure. 1406 * @property {string} [canonname=null] - The canonical hostname associated with the address. 1407 * @property {number} family - The address family (e.g., `2` for `AF_INET`, `10` for `AF_INET6`). 1408 * @property {number} flags - Additional flags indicating properties of the address. 1409 * @property {number} protocol - The protocol number. 1410 * @property {number} socktype - The socket type (e.g., `1` for `SOCK_STREAM`, `2` for `SOCK_DGRAM`). 1411 */ 1412 static struct_t st_addrinfo = { 1413 .size = sizeof(struct addrinfo), 1414 .members = (member_t []){ 1415 STRUCT_MEMBER(addrinfo, ai, flags, DT_SIGNED), 1416 STRUCT_MEMBER(addrinfo, ai, family, DT_SIGNED), 1417 STRUCT_MEMBER(addrinfo, ai, socktype, DT_SIGNED), 1418 STRUCT_MEMBER(addrinfo, ai, protocol, DT_SIGNED), 1419 STRUCT_MEMBER_CB(addr, NULL, ai_addr_to_uv), 1420 STRUCT_MEMBER_CB(canonname, NULL, ai_canonname_to_uv), 1421 { 0 } 1422 } 1423 }; 1424 1425 #if defined(__linux__) 1426 static uc_value_t * 1427 mr_ifindex_to_uv(void *st) 1428 { 1429 char ifname[IF_NAMESIZE] = { 0 }; 1430 struct packet_mreq *mr = st; 1431 1432 if (mr->mr_ifindex > 0 && if_indextoname(mr->mr_ifindex, ifname)) 1433 return ucv_string_new(ifname); 1434 1435 return ucv_int64_new(mr->mr_ifindex); 1436 } 1437 1438 static bool 1439 mr_ifindex_to_c(void *st, uc_value_t *uv) 1440 { 1441 struct packet_mreq *mr = *(struct packet_mreq **)st; 1442 1443 if (ucv_type(uv) == UC_STRING) { 1444 mr->mr_ifindex = if_nametoindex(ucv_string_get(uv)); 1445 1446 if (mr->mr_ifindex == 0) 1447 err_return(errno, "Unable to resolve interface %s", 1448 ucv_string_get(uv)); 1449 } 1450 else { 1451 mr->mr_ifindex = ucv_to_integer(uv); 1452 1453 if (errno) 1454 err_return(errno, "Unable to convert interface to integer"); 1455 } 1456 1457 return true; 1458 } 1459 1460 static uc_value_t * 1461 mr_address_to_uv(void *st) 1462 { 1463 struct packet_mreq *mr = st; 1464 1465 return hwaddr_to_uv(mr->mr_address, mr->mr_alen); 1466 } 1467 1468 static bool 1469 mr_address_to_c(void *st, uc_value_t *uv) 1470 { 1471 struct packet_mreq *mr = *(struct packet_mreq **)st; 1472 size_t len; 1473 1474 if (!uv_to_hwaddr(uv, mr->mr_address, &len)) 1475 return false; 1476 1477 mr->mr_alen = len; 1478 1479 return true; 1480 } 1481 1482 static struct_t st_packet_mreq = { 1483 .size = sizeof(struct packet_mreq), 1484 .members = (member_t []){ 1485 STRUCT_MEMBER_CB(interface, mr_ifindex_to_c, mr_ifindex_to_uv), 1486 STRUCT_MEMBER(packet_mreq, mr, type, DT_UNSIGNED), 1487 STRUCT_MEMBER_CB(address, mr_address_to_c, mr_address_to_uv), 1488 { 0 } 1489 } 1490 }; 1491 1492 static struct_t st_tpacket_req = { 1493 .size = sizeof(struct tpacket_req), 1494 .members = (member_t []){ 1495 STRUCT_MEMBER(tpacket_req, tp, block_size, DT_UNSIGNED), 1496 STRUCT_MEMBER(tpacket_req, tp, block_nr, DT_UNSIGNED), 1497 STRUCT_MEMBER(tpacket_req, tp, frame_size, DT_UNSIGNED), 1498 STRUCT_MEMBER(tpacket_req, tp, frame_nr, DT_UNSIGNED), 1499 { 0 } 1500 } 1501 }; 1502 1503 static struct_t st_tpacket_stats = { 1504 .size = sizeof(struct tpacket_stats), 1505 .members = (member_t []){ 1506 STRUCT_MEMBER(tpacket_stats, tp, packets, DT_UNSIGNED), 1507 STRUCT_MEMBER(tpacket_stats, tp, drops, DT_UNSIGNED), 1508 { 0 } 1509 } 1510 }; 1511 1512 static struct_t st_tpacket_auxdata = { 1513 .size = sizeof(struct tpacket_auxdata), 1514 .members = (member_t []){ 1515 STRUCT_MEMBER(tpacket_auxdata, tp, status, DT_UNSIGNED), 1516 STRUCT_MEMBER(tpacket_auxdata, tp, len, DT_UNSIGNED), 1517 STRUCT_MEMBER(tpacket_auxdata, tp, snaplen, DT_UNSIGNED), 1518 STRUCT_MEMBER(tpacket_auxdata, tp, mac, DT_UNSIGNED), 1519 STRUCT_MEMBER(tpacket_auxdata, tp, net, DT_UNSIGNED), 1520 STRUCT_MEMBER(tpacket_auxdata, tp, vlan_tci, DT_UNSIGNED), 1521 STRUCT_MEMBER(tpacket_auxdata, tp, vlan_tpid, DT_UNSIGNED), 1522 { 0 } 1523 } 1524 }; 1525 1526 struct fanout_args_local { 1527 #if __BYTE_ORDER == __LITTLE_ENDIAN 1528 uint16_t id; 1529 uint16_t type_flags; 1530 #else 1531 uint16_t type_flags; 1532 uint16_t id; 1533 #endif 1534 uint32_t max_num_members; 1535 }; 1536 1537 static struct_t st_fanout_args = { 1538 .size = sizeof(struct fanout_args_local), 1539 .members = (member_t []){ 1540 STRUCT_MEMBER_NP(fanout_args_local, id, DT_UNSIGNED), 1541 STRUCT_MEMBER_NP(fanout_args_local, type_flags, DT_UNSIGNED), 1542 STRUCT_MEMBER_NP(fanout_args_local, max_num_members, DT_UNSIGNED), 1543 { 0 } 1544 } 1545 }; 1546 1547 struct timeval_old_local { 1548 long tv_sec; 1549 #if defined(__sparc__) && defined(__arch64__) 1550 int tv_usec; 1551 #else 1552 long tv_usec; 1553 #endif 1554 }; 1555 1556 static struct_t st_timeval_old = { 1557 .size = sizeof(struct timeval_old_local), 1558 .members = (member_t []){ 1559 STRUCT_MEMBER(timeval_old_local, tv, sec, DT_SIGNED), 1560 STRUCT_MEMBER(timeval_old_local, tv, usec, DT_SIGNED), 1561 { 0 } 1562 } 1563 }; 1564 1565 # ifdef SO_TIMESTAMP_NEW 1566 struct timeval_new_local { int64_t tv_sec; int64_t tv_usec; }; 1567 static struct_t st_timeval_new = { 1568 .size = sizeof(struct timeval_old_local), 1569 .members = (member_t []){ 1570 STRUCT_MEMBER(timeval_new_local, tv, sec, DT_SIGNED), 1571 STRUCT_MEMBER(timeval_new_local, tv, usec, DT_SIGNED), 1572 { 0 } 1573 } 1574 }; 1575 # endif 1576 1577 struct timespec_old_local { long tv_sec; long tv_nsec; }; 1578 static struct_t st_timespec_old = { 1579 .size = sizeof(struct timespec_old_local), 1580 .members = (member_t []){ 1581 STRUCT_MEMBER(timespec_old_local, tv, sec, DT_SIGNED), 1582 STRUCT_MEMBER(timespec_old_local, tv, nsec, DT_SIGNED), 1583 { 0 } 1584 } 1585 }; 1586 1587 # ifdef SO_TIMESTAMPNS_NEW 1588 struct timespec_new_local { long long tv_sec; long long tv_nsec; }; 1589 static struct_t st_timespec_new = { 1590 .size = sizeof(struct timespec_new_local), 1591 .members = (member_t []){ 1592 STRUCT_MEMBER(timespec_new_local, tv, sec, DT_SIGNED), 1593 STRUCT_MEMBER(timespec_new_local, tv, nsec, DT_SIGNED), 1594 { 0 } 1595 } 1596 }; 1597 # endif 1598 #endif 1599 1600 #define SV_VOID (struct_t *)0 1601 #define SV_INT (struct_t *)1 1602 #define SV_INT_RO (struct_t *)2 1603 #define SV_BOOL (struct_t *)3 1604 #define SV_STRING (struct_t *)4 1605 #define SV_IFNAME (struct_t *)5 1606 1607 #define CV_INT (struct_t *)0 1608 #define CV_UINT (struct_t *)1 1609 #define CV_BE32 (struct_t *)2 1610 #define CV_STRING (struct_t *)3 1611 #define CV_SOCKADDR (struct_t *)4 1612 #define CV_FDS (struct_t *)5 1613 1614 static sockopt_t sockopts[] = { 1615 { SOL_SOCKET, SO_ACCEPTCONN, SV_BOOL }, 1616 { SOL_SOCKET, SO_BROADCAST, SV_BOOL }, 1617 { SOL_SOCKET, SO_DEBUG, SV_BOOL }, 1618 { SOL_SOCKET, SO_ERROR, SV_INT_RO }, 1619 { SOL_SOCKET, SO_DONTROUTE, SV_BOOL }, 1620 { SOL_SOCKET, SO_KEEPALIVE, SV_BOOL }, 1621 { SOL_SOCKET, SO_LINGER, &st_linger }, 1622 { SOL_SOCKET, SO_OOBINLINE, SV_BOOL }, 1623 { SOL_SOCKET, SO_RCVBUF, SV_INT }, 1624 { SOL_SOCKET, SO_RCVLOWAT, SV_INT }, 1625 { SOL_SOCKET, SO_RCVTIMEO, &st_timeval }, 1626 { SOL_SOCKET, SO_REUSEADDR, SV_BOOL }, 1627 { SOL_SOCKET, SO_REUSEPORT, SV_BOOL }, 1628 { SOL_SOCKET, SO_SNDBUF, SV_INT }, 1629 { SOL_SOCKET, SO_SNDLOWAT, SV_INT }, 1630 { SOL_SOCKET, SO_SNDTIMEO, &st_timeval }, 1631 { SOL_SOCKET, SO_TIMESTAMP, SV_BOOL }, 1632 { SOL_SOCKET, SO_TYPE, SV_INT }, 1633 #if defined(__linux__) 1634 { SOL_SOCKET, SO_ATTACH_FILTER, &st_sock_fprog }, 1635 { SOL_SOCKET, SO_ATTACH_BPF, SV_INT }, 1636 { SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, SV_STRING }, 1637 { SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, SV_INT }, 1638 { SOL_SOCKET, SO_BINDTODEVICE, SV_STRING }, 1639 { SOL_SOCKET, SO_DETACH_FILTER, SV_VOID }, 1640 { SOL_SOCKET, SO_DETACH_BPF, SV_VOID }, 1641 { SOL_SOCKET, SO_DOMAIN, SV_INT_RO }, 1642 { SOL_SOCKET, SO_INCOMING_CPU, SV_INT }, 1643 { SOL_SOCKET, SO_INCOMING_NAPI_ID, SV_INT_RO }, 1644 { SOL_SOCKET, SO_LOCK_FILTER, SV_INT }, 1645 { SOL_SOCKET, SO_MARK, SV_INT }, 1646 { SOL_SOCKET, SO_PASSCRED, SV_BOOL }, 1647 { SOL_SOCKET, SO_PASSSEC, SV_BOOL }, 1648 { SOL_SOCKET, SO_PEEK_OFF, SV_INT }, 1649 { SOL_SOCKET, SO_PEERCRED, &st_ucred }, 1650 { SOL_SOCKET, SO_PEERSEC, SV_STRING }, 1651 { SOL_SOCKET, SO_PRIORITY, SV_INT }, 1652 { SOL_SOCKET, SO_PROTOCOL, SV_INT }, 1653 { SOL_SOCKET, SO_RCVBUFFORCE, SV_INT }, 1654 { SOL_SOCKET, SO_RXQ_OVFL, SV_BOOL }, 1655 { SOL_SOCKET, SO_SNDBUFFORCE, SV_INT }, 1656 { SOL_SOCKET, SO_TIMESTAMPNS, SV_BOOL }, 1657 { SOL_SOCKET, SO_BUSY_POLL, SV_INT }, 1658 #endif 1659 1660 { IPPROTO_IP, IP_ADD_MEMBERSHIP, &st_ip_mreqn }, 1661 { IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, &st_ip_mreq_source }, 1662 { IPPROTO_IP, IP_BLOCK_SOURCE, &st_ip_mreq_source }, 1663 { IPPROTO_IP, IP_DROP_MEMBERSHIP, &st_ip_mreqn }, 1664 { IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP, &st_ip_mreq_source }, 1665 { IPPROTO_IP, IP_HDRINCL, SV_BOOL }, 1666 { IPPROTO_IP, IP_MULTICAST_IF, &st_ip_mreqn }, 1667 { IPPROTO_IP, IP_MULTICAST_LOOP, SV_BOOL }, 1668 { IPPROTO_IP, IP_MULTICAST_TTL, SV_INT }, 1669 { IPPROTO_IP, IP_OPTIONS, SV_STRING }, 1670 { IPPROTO_IP, IP_PKTINFO, SV_BOOL }, 1671 { IPPROTO_IP, IP_RECVOPTS, SV_BOOL }, 1672 { IPPROTO_IP, IP_RECVTOS, SV_BOOL }, 1673 { IPPROTO_IP, IP_RECVTTL, SV_BOOL }, 1674 { IPPROTO_IP, IP_RETOPTS, SV_BOOL }, 1675 { IPPROTO_IP, IP_TOS, SV_INT }, 1676 { IPPROTO_IP, IP_TTL, SV_INT }, 1677 { IPPROTO_IP, IP_UNBLOCK_SOURCE, &st_ip_mreq_source }, 1678 #if defined(__linux__) 1679 { IPPROTO_IP, IP_MSFILTER, &st_ip_msfilter }, 1680 { IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, SV_BOOL }, 1681 { IPPROTO_IP, IP_FREEBIND, SV_BOOL }, 1682 { IPPROTO_IP, IP_MTU, SV_INT }, 1683 { IPPROTO_IP, IP_MTU_DISCOVER, SV_INT }, 1684 { IPPROTO_IP, IP_MULTICAST_ALL, SV_BOOL }, 1685 { IPPROTO_IP, IP_NODEFRAG, SV_BOOL }, 1686 { IPPROTO_IP, IP_PASSSEC, SV_BOOL }, 1687 { IPPROTO_IP, IP_RECVERR, SV_BOOL }, 1688 { IPPROTO_IP, IP_RECVORIGDSTADDR, SV_BOOL }, 1689 { IPPROTO_IP, IP_ROUTER_ALERT, SV_BOOL }, 1690 { IPPROTO_IP, IP_TRANSPARENT, SV_BOOL }, 1691 #endif 1692 1693 { IPPROTO_IPV6, IPV6_FLOWINFO_SEND, SV_BOOL }, 1694 { IPPROTO_IPV6, IPV6_FLOWINFO, SV_BOOL }, 1695 { IPPROTO_IPV6, IPV6_FLOWLABEL_MGR, &st_in6_flowlabel_req }, 1696 { IPPROTO_IPV6, IPV6_MULTICAST_HOPS, SV_INT }, 1697 { IPPROTO_IPV6, IPV6_MULTICAST_IF, SV_IFNAME }, 1698 { IPPROTO_IPV6, IPV6_MULTICAST_LOOP, SV_BOOL }, 1699 { IPPROTO_IPV6, IPV6_RECVTCLASS, SV_BOOL }, 1700 { IPPROTO_IPV6, IPV6_TCLASS, SV_INT }, 1701 { IPPROTO_IPV6, IPV6_UNICAST_HOPS, SV_INT }, 1702 { IPPROTO_IPV6, IPV6_V6ONLY, SV_BOOL }, 1703 #if defined(__linux__) 1704 { IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &st_ipv6_mreq }, 1705 { IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, SV_INT }, 1706 { IPPROTO_IPV6, IPV6_ADDRFORM, SV_INT }, 1707 { IPPROTO_IPV6, IPV6_AUTHHDR, SV_BOOL }, 1708 { IPPROTO_IPV6, IPV6_AUTOFLOWLABEL, SV_BOOL }, 1709 { IPPROTO_IPV6, IPV6_DONTFRAG, SV_BOOL }, 1710 { IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &st_ipv6_mreq }, 1711 { IPPROTO_IPV6, IPV6_DSTOPTS, SV_STRING }, 1712 { IPPROTO_IPV6, IPV6_FREEBIND, SV_BOOL }, 1713 { IPPROTO_IPV6, IPV6_HOPLIMIT, SV_BOOL }, 1714 { IPPROTO_IPV6, IPV6_HOPOPTS, SV_STRING }, 1715 { IPPROTO_IPV6, IPV6_JOIN_ANYCAST, &st_ipv6_mreq }, 1716 { IPPROTO_IPV6, IPV6_LEAVE_ANYCAST, &st_ipv6_mreq }, 1717 { IPPROTO_IPV6, IPV6_MINHOPCOUNT, SV_INT }, 1718 { IPPROTO_IPV6, IPV6_MTU_DISCOVER, SV_INT }, 1719 { IPPROTO_IPV6, IPV6_MTU, SV_INT }, 1720 { IPPROTO_IPV6, IPV6_MULTICAST_ALL, SV_BOOL }, 1721 { IPPROTO_IPV6, IPV6_PKTINFO, &st_in6_pktinfo }, 1722 { IPPROTO_IPV6, IPV6_RECVDSTOPTS, SV_BOOL }, 1723 { IPPROTO_IPV6, IPV6_RECVERR, SV_BOOL }, 1724 { IPPROTO_IPV6, IPV6_RECVFRAGSIZE, SV_BOOL }, 1725 { IPPROTO_IPV6, IPV6_RECVHOPLIMIT, SV_BOOL }, 1726 { IPPROTO_IPV6, IPV6_RECVHOPOPTS, SV_BOOL }, 1727 { IPPROTO_IPV6, IPV6_RECVORIGDSTADDR, SV_BOOL }, 1728 { IPPROTO_IPV6, IPV6_RECVPATHMTU, SV_BOOL }, 1729 { IPPROTO_IPV6, IPV6_RECVPKTINFO, SV_BOOL }, 1730 { IPPROTO_IPV6, IPV6_RECVRTHDR, SV_BOOL }, 1731 { IPPROTO_IPV6, IPV6_ROUTER_ALERT_ISOLATE, SV_BOOL }, 1732 { IPPROTO_IPV6, IPV6_ROUTER_ALERT, SV_BOOL }, 1733 { IPPROTO_IPV6, IPV6_RTHDR, SV_STRING }, 1734 { IPPROTO_IPV6, IPV6_RTHDRDSTOPTS, SV_STRING }, 1735 { IPPROTO_IPV6, IPV6_TRANSPARENT, SV_BOOL }, 1736 { IPPROTO_IPV6, IPV6_UNICAST_IF, SV_IFNAME }, 1737 #endif 1738 1739 { IPPROTO_TCP, TCP_KEEPCNT, SV_INT }, 1740 { IPPROTO_TCP, TCP_KEEPINTVL, SV_INT }, 1741 { IPPROTO_TCP, TCP_MAXSEG, SV_INT }, 1742 { IPPROTO_TCP, TCP_NODELAY, SV_BOOL }, 1743 { IPPROTO_TCP, TCP_FASTOPEN, SV_INT }, 1744 #if defined(__linux__) 1745 { IPPROTO_TCP, TCP_CONGESTION, SV_STRING }, 1746 { IPPROTO_TCP, TCP_CORK, SV_BOOL }, 1747 { IPPROTO_TCP, TCP_DEFER_ACCEPT, SV_INT }, 1748 { IPPROTO_TCP, TCP_INFO, &st_tcp_info }, 1749 { IPPROTO_TCP, TCP_KEEPIDLE, SV_INT }, 1750 { IPPROTO_TCP, TCP_LINGER2, SV_INT }, 1751 { IPPROTO_TCP, TCP_QUICKACK, SV_BOOL }, 1752 { IPPROTO_TCP, TCP_SYNCNT, SV_INT }, 1753 { IPPROTO_TCP, TCP_USER_TIMEOUT, SV_INT }, 1754 { IPPROTO_TCP, TCP_WINDOW_CLAMP, SV_INT }, 1755 { IPPROTO_TCP, TCP_FASTOPEN_CONNECT, SV_INT }, 1756 #endif 1757 1758 #if defined(__linux__) 1759 { IPPROTO_UDP, UDP_CORK, SV_BOOL }, 1760 #endif 1761 1762 #if defined(__linux__) 1763 { SOL_PACKET, PACKET_ADD_MEMBERSHIP, &st_packet_mreq }, 1764 { SOL_PACKET, PACKET_DROP_MEMBERSHIP, &st_packet_mreq }, 1765 { SOL_PACKET, PACKET_AUXDATA, SV_BOOL }, 1766 { SOL_PACKET, PACKET_FANOUT, &st_fanout_args }, 1767 { SOL_PACKET, PACKET_LOSS, SV_BOOL }, 1768 { SOL_PACKET, PACKET_RESERVE, SV_INT }, 1769 { SOL_PACKET, PACKET_RX_RING, &st_tpacket_req }, 1770 { SOL_PACKET, PACKET_STATISTICS, &st_tpacket_stats }, 1771 { SOL_PACKET, PACKET_TIMESTAMP, SV_INT }, 1772 { SOL_PACKET, PACKET_TX_RING, &st_tpacket_req }, 1773 { SOL_PACKET, PACKET_VERSION, SV_INT }, 1774 { SOL_PACKET, PACKET_QDISC_BYPASS, SV_BOOL }, 1775 #endif 1776 1777 #if defined(__linux__) 1778 { SOL_CAN_RAW, CAN_RAW_FILTER, SV_STRING }, 1779 { SOL_CAN_RAW, CAN_RAW_ERR_FILTER, SV_INT }, 1780 { SOL_CAN_RAW, CAN_RAW_LOOPBACK, SV_BOOL }, 1781 { SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, SV_BOOL }, 1782 { SOL_CAN_RAW, CAN_RAW_FD_FRAMES, SV_BOOL }, 1783 { SOL_CAN_RAW, CAN_RAW_JOIN_FILTERS, SV_BOOL }, 1784 # ifdef CAN_RAW_XL_FRAMES 1785 { SOL_CAN_RAW, CAN_RAW_XL_FRAMES, SV_BOOL }, 1786 # endif 1787 #endif 1788 }; 1789 1790 static cmsgtype_t cmsgtypes[] = { 1791 #if defined(__linux__) 1792 { SOL_PACKET, PACKET_AUXDATA, &st_tpacket_auxdata }, 1793 1794 { SOL_SOCKET, SO_TIMESTAMP_OLD, &st_timeval_old }, 1795 # ifdef SO_TIMESTAMP_NEW 1796 { SOL_SOCKET, SO_TIMESTAMP_NEW, &st_timeval_new }, 1797 # endif 1798 { SOL_SOCKET, SO_TIMESTAMPNS_OLD, &st_timespec_old }, 1799 # ifdef SO_TIMESTAMPNS_NEW 1800 { SOL_SOCKET, SO_TIMESTAMPNS_NEW, &st_timespec_new }, 1801 # endif 1802 1803 { SOL_SOCKET, SCM_CREDENTIALS, &st_ucred }, 1804 { SOL_SOCKET, SCM_RIGHTS, CV_FDS }, 1805 #endif 1806 1807 { IPPROTO_IP, IP_RECVOPTS, SV_STRING }, 1808 { IPPROTO_IP, IP_RETOPTS, SV_STRING }, 1809 { IPPROTO_IP, IP_TOS, CV_INT }, 1810 { IPPROTO_IP, IP_TTL, CV_INT }, 1811 #if defined(__linux__) 1812 { IPPROTO_IP, IP_CHECKSUM, CV_UINT }, 1813 { IPPROTO_IP, IP_ORIGDSTADDR, CV_SOCKADDR }, 1814 { IPPROTO_IP, IP_RECVERR, &st_ip_recv_error }, 1815 { IPPROTO_IP, IP_RECVFRAGSIZE, CV_INT }, 1816 #endif 1817 1818 { IPPROTO_IPV6, IPV6_TCLASS, CV_INT }, 1819 { IPPROTO_IPV6, IPV6_FLOWINFO, CV_BE32 }, 1820 #if defined(__linux__) 1821 { IPPROTO_IPV6, IPV6_DSTOPTS, CV_STRING }, 1822 { IPPROTO_IPV6, IPV6_HOPLIMIT, CV_INT }, 1823 { IPPROTO_IPV6, IPV6_HOPOPTS, CV_STRING }, 1824 { IPPROTO_IPV6, IPV6_ORIGDSTADDR, CV_SOCKADDR }, 1825 { IPPROTO_IPV6, IPV6_PATHMTU, &st_ip6_mtuinfo }, 1826 { IPPROTO_IPV6, IPV6_PKTINFO, &st_in6_pktinfo }, 1827 { IPPROTO_IPV6, IPV6_RECVERR, &st_ip_recv_error }, 1828 { IPPROTO_IPV6, IPV6_RECVFRAGSIZE, CV_INT }, 1829 { IPPROTO_IPV6, IPV6_RTHDR, CV_STRING }, 1830 1831 { IPPROTO_TCP, TCP_CM_INQ, CV_INT }, 1832 { IPPROTO_UDP, UDP_GRO, CV_INT }, 1833 #endif 1834 }; 1835 1836 1837 static char * 1838 uv_to_struct(uc_value_t *uv, struct_t *spec) 1839 { 1840 uc_value_t *fv; 1841 const char *s; 1842 uint64_t u64; 1843 int64_t s64; 1844 member_t *m; 1845 bool found; 1846 char *st; 1847 1848 union { 1849 int8_t s8; 1850 int16_t s16; 1851 int32_t s32; 1852 int64_t s64; 1853 uint8_t u8; 1854 uint16_t u16; 1855 uint32_t u32; 1856 uint64_t u64; 1857 } v; 1858 1859 st = xalloc(spec->size); 1860 1861 for (size_t i = 0; spec->members[i].name; i++) { 1862 m = &spec->members[i]; 1863 fv = ucv_object_get(uv, m->name, &found); 1864 1865 if (!found || !fv) 1866 continue; 1867 1868 switch (spec->members[i].type) { 1869 case DT_UNSIGNED: 1870 u64 = ucv_to_unsigned(fv); 1871 1872 if (errno) { 1873 free(st); 1874 err_return(errno, 1875 "Unable to convert field %s to unsigned", 1876 m->name); 1877 } 1878 1879 switch (m->u2.size) { 1880 case 1: v.u8 = (uint8_t)u64; break; 1881 case 2: v.u16 = (uint16_t)u64; break; 1882 case 4: v.u32 = (uint32_t)u64; break; 1883 case 8: v.u64 = (uint64_t)u64; break; 1884 } 1885 1886 memcpy(st + m->u1.offset, &v, m->u2.size); 1887 break; 1888 1889 case DT_SIGNED: 1890 s64 = ucv_to_integer(fv); 1891 1892 if (errno) { 1893 free(st); 1894 err_return(errno, 1895 "Unable to convert field %s to integer", m->name); 1896 } 1897 1898 switch (m->u2.size) { 1899 case 1: v.s8 = (int8_t)s64; break; 1900 case 2: v.s16 = (int16_t)s64; break; 1901 case 4: v.s32 = (int32_t)s64; break; 1902 case 8: v.s64 = (int64_t)s64; break; 1903 } 1904 1905 memcpy(st + m->u1.offset, &v, m->u2.size); 1906 break; 1907 1908 case DT_IPV4ADDR: 1909 s = ucv_string_get(fv); 1910 1911 if (!s || inet_pton(AF_INET, s, st + m->u1.offset) != 1) { 1912 free(st); 1913 err_return(EINVAL, 1914 "Unable to convert field %s to IP address", m->name); 1915 } 1916 1917 break; 1918 1919 case DT_IPV6ADDR: 1920 s = ucv_string_get(fv); 1921 1922 if (!s || inet_pton(AF_INET6, s, st + m->u1.offset) != 1) { 1923 free(st); 1924 err_return(EINVAL, 1925 "Unable to convert field %s to IPv6 address", m->name); 1926 } 1927 1928 break; 1929 1930 case DT_CALLBACK: 1931 if (m->u1.to_c && !m->u1.to_c(&st, fv)) { 1932 free(st); 1933 return NULL; 1934 } 1935 1936 break; 1937 } 1938 } 1939 1940 return st; 1941 } 1942 1943 static uc_value_t * 1944 struct_to_uv(char *st, struct_t *spec) 1945 { 1946 char s[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; 1947 uc_value_t *uv, *fv; 1948 member_t *m; 1949 1950 uv = ucv_object_new(NULL); 1951 1952 for (size_t i = 0; spec->members[i].name; i++) { 1953 m = &spec->members[i]; 1954 fv = NULL; 1955 1956 switch (spec->members[i].type) { 1957 case DT_UNSIGNED: 1958 switch (spec->members[i].u2.size) { 1959 case 1: 1960 fv = ucv_uint64_new(*(uint8_t *)(st + m->u1.offset)); 1961 break; 1962 1963 case 2: 1964 fv = ucv_uint64_new(*(uint16_t *)(st + m->u1.offset)); 1965 break; 1966 1967 case 4: 1968 fv = ucv_uint64_new(*(uint32_t *)(st + m->u1.offset)); 1969 break; 1970 1971 case 8: 1972 fv = ucv_uint64_new(*(uint64_t *)(st + m->u1.offset)); 1973 break; 1974 } 1975 1976 break; 1977 1978 case DT_SIGNED: 1979 switch (spec->members[i].u2.size) { 1980 case 1: 1981 fv = ucv_int64_new(*(int8_t *)(st + m->u1.offset)); 1982 break; 1983 1984 case 2: 1985 fv = ucv_int64_new(*(int16_t *)(st + m->u1.offset)); 1986 break; 1987 1988 case 4: 1989 fv = ucv_int64_new(*(int32_t *)(st + m->u1.offset)); 1990 break; 1991 1992 case 8: 1993 fv = ucv_int64_new(*(int64_t *)(st + m->u1.offset)); 1994 break; 1995 } 1996 1997 break; 1998 1999 case DT_IPV4ADDR: 2000 if (inet_ntop(AF_INET, st + m->u1.offset, s, sizeof(s))) 2001 fv = ucv_string_new(s); 2002 2003 break; 2004 2005 case DT_IPV6ADDR: 2006 if (inet_ntop(AF_INET6, st + m->u1.offset, s, sizeof(s))) 2007 fv = ucv_string_new(s); 2008 2009 break; 2010 2011 case DT_CALLBACK: 2012 fv = m->u2.to_uv ? m->u2.to_uv(st) : NULL; 2013 break; 2014 } 2015 2016 ucv_object_add(uv, m->name, fv); 2017 } 2018 2019 return uv; 2020 } 2021 2022 /** 2023 * Sets options on the socket. 2024 * 2025 * Sets the specified option on the socket to the given value. 2026 * 2027 * Returns `true` if the option was successfully set. 2028 * 2029 * Returns `null` if an error occurred. 2030 * 2031 * @function module:socket.socket#setopt 2032 * 2033 * @param {number} level 2034 * The protocol level at which the option resides. This can be a level such as 2035 * `SOL_SOCKET` for the socket API level or a specific protocol level defined 2036 * by the system. 2037 * 2038 * @param {number} option 2039 * The socket option to set. This can be an integer representing the option, 2040 * such as `SO_REUSEADDR`, or a constant defined by the system. 2041 * 2042 * @param {*} value 2043 * The value to set the option to. The type of this argument depends on the 2044 * specific option being set. It can be an integer, a boolean, a string, or a 2045 * dictionary representing the value to set. If a dictionary is provided, it is 2046 * internally translated to the corresponding C struct type required by the 2047 * option. 2048 * 2049 * @returns {?boolean} 2050 */ 2051 static uc_value_t * 2052 uc_socket_inst_setopt(uc_vm_t *vm, size_t nargs) 2053 { 2054 int sockfd, solvl, soopt, soval, ret; 2055 uc_value_t *level, *option, *value; 2056 void *valptr = NULL, *st = NULL; 2057 socklen_t vallen = 0; 2058 size_t i; 2059 2060 args_get(vm, nargs, &sockfd, 2061 "level", UC_INTEGER, false, &level, 2062 "option", UC_INTEGER, false, &option, 2063 "value", UC_NULL, false, &value); 2064 2065 solvl = ucv_int64_get(level); 2066 soopt = ucv_int64_get(option); 2067 2068 for (i = 0; i < ARRAY_SIZE(sockopts); i++) { 2069 if (sockopts[i].level != solvl || sockopts[i].option != soopt) 2070 continue; 2071 2072 switch ((uintptr_t)sockopts[i].ctype) { 2073 case (uintptr_t)SV_INT_RO: 2074 err_return(EOPNOTSUPP, "Socket option is read only"); 2075 2076 case (uintptr_t)SV_VOID: 2077 valptr = NULL; 2078 vallen = 0; 2079 break; 2080 2081 case (uintptr_t)SV_INT: 2082 soval = ucv_to_integer(value); 2083 2084 if (errno) 2085 err_return(errno, "Unable to convert value to integer"); 2086 2087 valptr = &soval; 2088 vallen = sizeof(int); 2089 break; 2090 2091 case (uintptr_t)SV_BOOL: 2092 soval = ucv_to_unsigned(value) ? 1 : 0; 2093 2094 if (errno) 2095 err_return(errno, "Unable to convert value to boolean"); 2096 2097 valptr = &soval; 2098 vallen = sizeof(int); 2099 break; 2100 2101 case (uintptr_t)SV_STRING: 2102 valptr = ucv_string_get(value); 2103 vallen = ucv_string_length(value); 2104 break; 2105 2106 case (uintptr_t)SV_IFNAME: 2107 if (ucv_type(value) == UC_STRING) { 2108 soval = if_nametoindex(ucv_string_get(value)); 2109 2110 if (soval <= 0) 2111 err_return(errno, "Unable to resolve interface %s", 2112 ucv_string_get(value)); 2113 } 2114 else { 2115 soval = ucv_to_integer(value); 2116 2117 if (errno) 2118 err_return(errno, "Unable to convert value to integer"); 2119 } 2120 2121 valptr = &soval; 2122 vallen = sizeof(int); 2123 break; 2124 2125 default: 2126 st = uv_to_struct(value, sockopts[i].ctype); 2127 valptr = st; 2128 vallen = sockopts[i].ctype->size; 2129 break; 2130 } 2131 2132 break; 2133 } 2134 2135 if (i == ARRAY_SIZE(sockopts)) 2136 err_return(EINVAL, "Unknown socket level or option"); 2137 2138 ret = setsockopt(sockfd, solvl, soopt, valptr, vallen); 2139 2140 free(st); 2141 2142 if (ret == -1) 2143 err_return(errno, "setsockopt()"); 2144 2145 ok_return(ucv_boolean_new(true)); 2146 } 2147 2148 /** 2149 * Gets options from the socket. 2150 * 2151 * Retrieves the value of the specified option from the socket. 2152 * 2153 * Returns the value of the requested option. 2154 * 2155 * Returns `null` if an error occurred or if the option is not supported. 2156 * 2157 * @function module:socket.socket#getopt 2158 * 2159 * @param {number} level 2160 * The protocol level at which the option resides. This can be a level such as 2161 * `SOL_SOCKET` for the socket API level or a specific protocol level defined 2162 * by the system. 2163 * 2164 * @param {number} option 2165 * The socket option to retrieve. This can be an integer representing the 2166 * option, such as `SO_REUSEADDR`, or a constant defined by the system. 2167 * 2168 * @returns {?*} 2169 * The value of the requested option. The type of the returned value depends 2170 * on the specific option being retrieved. It can be an integer, a boolean, a 2171 * string, or a dictionary representing a complex data structure. 2172 */ 2173 static uc_value_t * 2174 uc_socket_inst_getopt(uc_vm_t *vm, size_t nargs) 2175 { 2176 uc_value_t *level, *option, *value = NULL; 2177 char ival[sizeof(int64_t)] = { 0 }; 2178 void *valptr = NULL, *st = NULL; 2179 int sockfd, solvl, soopt, ret; 2180 uc_stringbuf_t *sb = NULL; 2181 socklen_t vallen; 2182 size_t i; 2183 2184 args_get(vm, nargs, &sockfd, 2185 "level", UC_INTEGER, false, &level, 2186 "option", UC_INTEGER, false, &option); 2187 2188 solvl = ucv_int64_get(level); 2189 soopt = ucv_int64_get(option); 2190 2191 for (i = 0; i < ARRAY_SIZE(sockopts); i++) { 2192 if (sockopts[i].level != solvl || sockopts[i].option != soopt) 2193 continue; 2194 2195 switch ((uintptr_t)sockopts[i].ctype) { 2196 case (uintptr_t)SV_VOID: 2197 err_return(EOPNOTSUPP, "Socket option is write only"); 2198 2199 case (uintptr_t)SV_INT: 2200 case (uintptr_t)SV_INT_RO: 2201 case (uintptr_t)SV_BOOL: 2202 case (uintptr_t)SV_IFNAME: 2203 valptr = ival; 2204 vallen = sizeof(ival); 2205 break; 2206 2207 case (uintptr_t)SV_STRING: 2208 sb = strbuf_alloc(64); 2209 valptr = strbuf_data(sb); 2210 vallen = strbuf_size(sb); 2211 break; 2212 2213 default: 2214 st = xalloc(sockopts[i].ctype->size); 2215 valptr = st; 2216 vallen = sockopts[i].ctype->size; 2217 break; 2218 } 2219 2220 break; 2221 } 2222 2223 if (i == ARRAY_SIZE(sockopts)) 2224 err_return(EINVAL, "Unknown socket level or option"); 2225 2226 while (true) { 2227 ret = getsockopt(sockfd, solvl, soopt, valptr, &vallen); 2228 2229 if (sockopts[i].ctype == SV_STRING && 2230 (ret == 0 || (ret == -1 && errno == ERANGE)) && 2231 vallen > strbuf_size(sb)) { 2232 2233 if (!strbuf_grow(sb, vallen)) 2234 return NULL; 2235 2236 valptr = strbuf_data(sb); 2237 continue; 2238 } 2239 2240 break; 2241 } 2242 2243 if (ret == 0) { 2244 char ifname[IF_NAMESIZE]; 2245 int ifidx; 2246 2247 switch ((uintptr_t)sockopts[i].ctype) { 2248 case (uintptr_t)SV_VOID: 2249 break; 2250 2251 case (uintptr_t)SV_INT: 2252 case (uintptr_t)SV_INT_RO: 2253 value = ucv_int64_new(parse_integer(ival, vallen)); 2254 break; 2255 2256 case (uintptr_t)SV_BOOL: 2257 value = ucv_boolean_new(parse_integer(ival, vallen) != 0); 2258 break; 2259 2260 case (uintptr_t)SV_STRING: 2261 value = strbuf_finish(&sb, vallen); 2262 break; 2263 2264 case (uintptr_t)SV_IFNAME: 2265 ifidx = parse_integer(ival, vallen); 2266 if (if_indextoname(ifidx, ifname)) 2267 value = ucv_string_new(ifname); 2268 else 2269 value = ucv_int64_new(ifidx); 2270 break; 2271 2272 default: 2273 value = struct_to_uv(st, sockopts[i].ctype); 2274 break; 2275 } 2276 } 2277 2278 strbuf_free(sb); 2279 free(st); 2280 2281 if (ret == -1) 2282 err_return(errno, "getsockopt()"); 2283 2284 ok_return(value); 2285 } 2286 2287 /** 2288 * Returns the UNIX file descriptor number associated with the socket. 2289 * 2290 * Returns the file descriptor number. 2291 * 2292 * Returns `-1` if an error occurred. 2293 * 2294 * @function module:socket.socket#fileno 2295 * 2296 * @returns {number} 2297 */ 2298 static uc_value_t * 2299 uc_socket_inst_fileno(uc_vm_t *vm, size_t nargs) 2300 { 2301 int sockfd; 2302 2303 args_get(vm, nargs, &sockfd); 2304 2305 ok_return(ucv_int64_new(sockfd)); 2306 } 2307 2308 /** 2309 * Query error information. 2310 * 2311 * Returns a string containing a description of the last occurred error when 2312 * the *numeric* argument is absent or false. 2313 * 2314 * Returns a positive (`errno`) or negative (`EAI_*` constant) error code number 2315 * when the *numeric* argument is `true`. 2316 * 2317 * Returns `null` if there is no error information. 2318 * 2319 * @function module:socket#error 2320 * 2321 * @param {boolean} [numeric] 2322 * Whether to return a numeric error code (`true`) or a human readable error 2323 * message (false). 2324 * 2325 * @returns {?string|?number} 2326 * 2327 * @example 2328 * // Trigger socket error by attempting to bind IPv6 address with IPv4 socket 2329 * socket.create(socket.AF_INET, socket.SOCK_STREAM, 0).bind("::", 8080); 2330 * 2331 * // Print error (should yield "Address family not supported by protocol") 2332 * print(socket.error(), "\n"); 2333 * 2334 * // Trigger resolve error 2335 * socket.addrinfo("doesnotexist.org"); 2336 * 2337 * // Query error code (should yield -2 for EAI_NONAME) 2338 * print(socket.error(true), "\n"); // 2339 */ 2340 static uc_value_t * 2341 uc_socket_error(uc_vm_t *vm, size_t nargs) 2342 { 2343 uc_value_t *numeric = uc_fn_arg(0), *rv; 2344 uc_stringbuf_t *buf; 2345 2346 if (last_error.code == 0) 2347 return NULL; 2348 2349 if (ucv_is_truish(numeric)) { 2350 rv = ucv_int64_new(last_error.code); 2351 } 2352 else { 2353 buf = ucv_stringbuf_new(); 2354 2355 if (last_error.msg) 2356 ucv_stringbuf_printf(buf, "%s: ", last_error.msg); 2357 2358 if (last_error.code >= 0) 2359 ucv_stringbuf_printf(buf, "%s", strerror(last_error.code)); 2360 else 2361 ucv_stringbuf_printf(buf, "%s", gai_strerror(last_error.code)); 2362 2363 rv = ucv_stringbuf_finish(buf); 2364 } 2365 2366 return rv; 2367 } 2368 2369 /** 2370 * Returns a string containing a description of the positive (`errno`) or 2371 * negative (`EAI_*` constant) error code number given by the *code* argument. 2372 * 2373 * Returns `null` if the error code number is unknown. 2374 * 2375 * @function module:socket#strerror 2376 * 2377 * @param {number} code 2378 * The error code. 2379 * 2380 * @returns {?string} 2381 * 2382 * @example 2383 * // Should output 'Name or service not known'. 2384 * print(socket.strerror(-2), '\n'); 2385 * 2386 * // Should output 'No route to host'. 2387 * print(socket.strerror(113), '\n'); 2388 */ 2389 static uc_value_t * 2390 uc_socket_strerror(uc_vm_t *vm, size_t nargs) 2391 { 2392 uc_value_t *codearg, *rv; 2393 int code; 2394 2395 args_get(vm, nargs, NULL, 2396 "code", UC_INTEGER, false, &codearg); 2397 2398 code = ucv_to_integer(codearg); 2399 2400 if (code < 0) 2401 rv = ucv_string_new( gai_strerror(code) ); 2402 else 2403 rv = ucv_string_new( strerror(code) ); 2404 2405 return rv; 2406 } 2407 2408 /** 2409 * @typedef {Object} module:socket.socket.SocketAddress 2410 * @property {number} family 2411 * Address family, one of AF_INET, AF_INET6, AF_UNIX, AF_PACKET or AF_CAN. 2412 * 2413 * @property {string} address 2414 * IPv4/IPv6 address string (AF_INET or AF_INET6 only) or hardware address in 2415 * hexadecimal notation (AF_PACKET only). 2416 * 2417 * @property {number} [port] 2418 * Port number (AF_INET or AF_INET6 only). 2419 * 2420 * @property {number} [flowinfo] 2421 * IPv6 flow information (AF_INET6 only). 2422 * 2423 * @property {string|number} [interface] 2424 * Link local address scope (for IPv6 sockets) or bound network interface 2425 * (for packet and CAN sockets), either a network device name string or a 2426 * nonzero positive integer representing a network interface index (AF_INET6, 2427 * AF_PACKET and AF_CAN only). 2428 * 2429 * @property {string} path 2430 * Domain socket filesystem path (AF_UNIX only). 2431 * 2432 * @property {number} [protocol=0] 2433 * Physical layer protocol (AF_PACKET only). 2434 * 2435 * @property {number} [hardware_type=0] 2436 * ARP hardware type (AF_PACKET only). 2437 * 2438 * @property {number} [packet_type=PACKET_HOST] 2439 * Packet type (AF_PACKET only). 2440 */ 2441 2442 /** 2443 * Parses the provided address value into a socket address representation. 2444 * 2445 * This function parses the given address value into a socket address 2446 * representation required for a number of socket operations. The address value 2447 * can be provided in various formats: 2448 * - For IPv4 addresses, it can be a string representing the IP address, 2449 * optionally followed by a port number separated by colon, e.g. 2450 * `192.168.0.1:8080`. 2451 * - For IPv6 addresses, it must be an address string enclosed in square 2452 * brackets if a port number is specified, otherwise the brackets are 2453 * optional. The address string may also include a scope ID in the form 2454 * `%ifname` or `%number`, e.g. `[fe80::1%eth0]:8080` or `fe80::1%15`. 2455 * - Any string value containing a slash is treated as UNIX domain socket path. 2456 * - Alternatively, it can be provided as an array returned by 2457 * {@link module:core#iptoarr|iptoarr()}, representing the address octets. 2458 * - It can also be an object representing a network address, with properties 2459 * for `address` (the IP address) and `port` or a single property `path` to 2460 * denote a UNIX domain socket address. 2461 * 2462 * @function module:socket#sockaddr 2463 * 2464 * @param {string|number[]|module:socket.socket.SocketAddress} address 2465 * The address value to parse. 2466 * 2467 * @returns {?module:socket.socket.SocketAddress} 2468 * A socket address representation of the provided address value, or `null` if 2469 * the address could not be parsed. 2470 * 2471 * @example 2472 * // Parse an IP address string with port 2473 * const address1 = sockaddr('192.168.0.1:8080'); 2474 * 2475 * // Parse an IPv6 address string with port and scope identifier 2476 * const address2 = sockaddr('[fe80::1%eth0]:8080'); 2477 * 2478 * // Parse an array representing an IP address 2479 * const address3 = sockaddr([192, 168, 0, 1]); 2480 * 2481 * // Parse a network address object 2482 * const address4 = sockaddr({ address: '192.168.0.1', port: 8080 }); 2483 * 2484 * // Convert a path value to a UNIX domain socket address 2485 * const address5 = sockaddr('/var/run/daemon.sock'); 2486 */ 2487 static uc_value_t * 2488 uc_socket_sockaddr(uc_vm_t *vm, size_t nargs) 2489 { 2490 struct sockaddr_storage ss = { 0 }; 2491 uc_value_t *addr, *rv; 2492 socklen_t slen; 2493 2494 args_get(vm, nargs, NULL, 2495 "address", UC_NULL, false, &addr); 2496 2497 if (!uv_to_sockaddr(addr, &ss, &slen)) 2498 return NULL; 2499 2500 rv = ucv_object_new(vm); 2501 2502 if (!sockaddr_to_uv(&ss, rv)) { 2503 ucv_put(rv); 2504 return NULL; 2505 } 2506 2507 ok_return(rv); 2508 } 2509 2510 /** 2511 * Resolves the given network address into hostname and service name. 2512 * 2513 * The `nameinfo()` function provides an API for reverse DNS lookup and service 2514 * name resolution. It returns an object containing the following properties: 2515 * - `hostname`: The resolved hostname. 2516 * - `service`: The resolved service name. 2517 * 2518 * Returns an object representing the resolved hostname and service name. 2519 * Return `null` if an error occurred during resolution. 2520 * 2521 * @function module:socket#nameinfo 2522 * 2523 * @param {string|module:socket.socket.SocketAddress} address 2524 * The network address to resolve. It can be specified as: 2525 * - A string representing the IP address. 2526 * - An object representing the address with properties `address` and `port`. 2527 * 2528 * @param {number} [flags] 2529 * Optional flags that provide additional control over the resolution process, 2530 * specified as bitwise OR-ed number of `NI_*` constants. 2531 * 2532 * @returns {?{hostname: string, service: string}} 2533 * 2534 * @see {@link module:socket~"Socket Types"|Socket Types} 2535 * @see {@link module:socket~"Name Info Constants"|AName Info Constants} 2536 * 2537 * @example 2538 * // Resolve a network address into hostname and service name 2539 * const result = network.getnameinfo('192.168.1.1:80'); 2540 * print(result); // { "hostname": "example.com", "service": "http" } 2541 */ 2542 static uc_value_t * 2543 uc_socket_nameinfo(uc_vm_t *vm, size_t nargs) 2544 { 2545 char host[NI_MAXHOST], serv[NI_MAXSERV]; 2546 uc_value_t *addr, *flags, *rv; 2547 struct sockaddr_storage ss; 2548 socklen_t slen; 2549 int ret; 2550 2551 args_get(vm, nargs, NULL, 2552 "address", UC_NULL, false, &addr, 2553 "flags", UC_INTEGER, true, &flags); 2554 2555 if (!uv_to_sockaddr(addr, &ss, &slen)) 2556 return NULL; 2557 2558 ret = getnameinfo((struct sockaddr *)&ss, slen, 2559 host, sizeof(host), serv, sizeof(serv), 2560 flags ? ucv_int64_get(flags) : 0); 2561 2562 if (ret != 0) 2563 err_return((ret == EAI_SYSTEM) ? errno : ret, "getnameinfo()"); 2564 2565 rv = ucv_object_new(vm); 2566 2567 ucv_object_add(rv, "hostname", ucv_string_new(host)); 2568 ucv_object_add(rv, "service", ucv_string_new(serv)); 2569 2570 ok_return(rv); 2571 } 2572 2573 /** 2574 * Resolves the given hostname and optional service name into a list of network 2575 * addresses, according to the provided hints. 2576 * 2577 * The `addrinfo()` function provides an API for performing DNS and service name 2578 * resolution. It returns an array of objects, each representing a resolved 2579 * address. 2580 * 2581 * Returns an array of resolved addresses. 2582 * Returns `null` if an error occurred during resolution. 2583 * 2584 * @function module:socket#addrinfo 2585 * 2586 * @param {string} hostname 2587 * The hostname to resolve. 2588 * 2589 * @param {string} [service] 2590 * Optional service name to resolve. If not provided, the service field of the 2591 * resulting address information structures is left uninitialized. 2592 * 2593 * @param {Object} [hints] 2594 * Optional hints object that provides additional control over the resolution 2595 * process. It can contain the following properties: 2596 * - `family`: The preferred address family (`AF_INET` or `AF_INET6`). 2597 * - `socktype`: The socket type (`SOCK_STREAM`, `SOCK_DGRAM`, etc.). 2598 * - `protocol`: The protocol of returned addresses. 2599 * - `flags`: Bitwise OR-ed `AI_*` flags to control the resolution behavior. 2600 * 2601 * @returns {?module:socket.AddressInfo[]} 2602 * 2603 * @see {@link module:socket~"Socket Types"|Socket Types} 2604 * @see {@link module:socket~"Address Info Flags"|Address Info Flags} 2605 * 2606 * @example 2607 * // Resolve all addresses 2608 * const addresses = socket.addrinfo('example.org'); 2609 * 2610 * // Resolve IPv4 addresses for a given hostname and service 2611 * const ipv4addresses = socket.addrinfo('example.com', 'http', { family: socket.AF_INET }); 2612 * 2613 * // Resolve IPv6 addresses without specifying a service 2614 * const ipv6Addresses = socket.addrinfo('example.com', null, { family: socket.AF_INET6 }); 2615 */ 2616 2617 static uc_value_t * 2618 uc_socket_addrinfo(uc_vm_t *vm, size_t nargs) 2619 { 2620 char hostbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255%interface012345")]; 2621 struct addrinfo *ai_hints = NULL, *ai_res; 2622 uc_value_t *host, *serv, *hints, *rv; 2623 char *hostname, *servstr; 2624 size_t hostlen; 2625 int ret; 2626 2627 args_get(vm, nargs, NULL, 2628 "hostname", UC_STRING, false, &host, 2629 "service", UC_NULL, true, &serv, 2630 "hints", UC_OBJECT, true, &hints); 2631 2632 if (hints) { 2633 ai_hints = (struct addrinfo *)uv_to_struct(hints, &st_addrinfo); 2634 2635 if (!ai_hints) 2636 return NULL; 2637 } 2638 2639 hostname = ucv_string_get(host); 2640 hostlen = ucv_string_length(host); 2641 2642 if (hostlen > 2 && hostname[0] == '[' && hostname[hostlen - 1] == ']' 2643 && hostlen - 2 < sizeof(hostbuf)) { 2644 memcpy(hostbuf, hostname + 1, hostlen - 2); 2645 hostbuf[hostlen - 2] = '\0'; 2646 hostname = hostbuf; 2647 } 2648 2649 servstr = (serv && ucv_type(serv) != UC_STRING) ? ucv_to_string(vm, serv) : NULL; 2650 ret = getaddrinfo(hostname, 2651 servstr ? servstr : ucv_string_get(serv), 2652 ai_hints, &ai_res); 2653 2654 free(ai_hints); 2655 free(servstr); 2656 2657 if (ret != 0) 2658 err_return((ret == EAI_SYSTEM) ? errno : ret, "getaddrinfo()"); 2659 2660 rv = ucv_array_new(vm); 2661 2662 for (struct addrinfo *ai = ai_res; ai; ai = ai->ai_next) { 2663 uc_value_t *item = struct_to_uv((char *)ai, &st_addrinfo); 2664 2665 if (item) 2666 ucv_array_push(rv, item); 2667 } 2668 2669 freeaddrinfo(ai_res); 2670 2671 ok_return(rv); 2672 } 2673 2674 /** 2675 * Represents a poll state serving as input parameter and return value type for 2676 * {@link module:socket#poll|`poll()`}. 2677 * 2678 * @typedef {Array} module:socket.PollSpec 2679 * @property {module:socket.socket} 0 2680 * The polled socket instance. 2681 * 2682 * @property {number} 1 2683 * Requested or returned status flags of the polled socket instance. 2684 */ 2685 2686 /** 2687 * Polls a number of sockets for state changes. 2688 * 2689 * Returns an array of `[socket, flags]` tuples for each socket with pending 2690 * events. When a tuple is passed as socket argument, it is included as-is into 2691 * the result tuple array, with the flags entry changed to a bitwise OR-ed value 2692 * describing the pending events for this socket. When a plain socket instance 2693 * (or another kind of handle) is passed, a new tuple array is created for this 2694 * socket within the result tuple array, containing this socket as first and the 2695 * bitwise OR-ed pending events as second element. 2696 * 2697 * Returns `null` if an error occurred. 2698 * 2699 * @function module:socket#poll 2700 * 2701 * @param {number} timeout 2702 * Amount of milliseconds to wait for socket activity before aborting the poll 2703 * call. If set to `0`, the poll call will return immediately if none of the 2704 * provided sockets has pending events, if set to a negative value, the poll 2705 * call will wait indefinitely, in all other cases the poll call will wait at 2706 * most for the given amount of milliseconds before returning. 2707 * 2708 * @param {...(module:socket.socket|module:socket.PollSpec)} sockets 2709 * An arbitrary amount of socket arguments. Each argument may be either a plain 2710 * {@link module:socket.socket|socket instance} (or any other kind of handle 2711 * implementing a `fileno()` method) or a `[socket, flags]` tuple specifying the 2712 * socket and requested poll flags. If a plain socket (or other kind of handle) 2713 * instead of a tuple is provided, the requested poll flags default to 2714 * `POLLIN|POLLERR|POLLHUP` for this socket. 2715 * 2716 * @returns {module:socket.PollSpec[]} 2717 * 2718 * @example 2719 * let x = socket.connect("example.org", 80); 2720 * let y = socket.connect("example.com", 80); 2721 * 2722 * // Pass plain socket arguments 2723 * let events = socket.poll(10, x, y); 2724 * print(events); // [ [ "<socket 0x7>", 0 ], [ "<socket 0x8>", 0 ] ] 2725 * 2726 * // Passing tuples allows attaching state information and requesting 2727 * // different I/O events 2728 * let events = socket.poll(10, 2729 * [ x, socket.POLLOUT | socket.POLLHUP, "This is example.org" ], 2730 * [ y, socket.POLLOUT | socket.POLLHUP, "This is example.com" ] 2731 * ); 2732 * print(events); // [ [ "<socket 0x7>", 4, "This is example.org" ], 2733 * // [ "<socket 0x8>", 4, "This is example.com" ] ] 2734 */ 2735 static uc_value_t * 2736 uc_socket_poll(uc_vm_t *vm, size_t nargs) 2737 { 2738 struct { struct pollfd *entries; size_t count; } pfds = { 0 }; 2739 uc_value_t *timeoutarg, *rv, *item; 2740 int64_t timeout; 2741 int ret; 2742 2743 args_get(vm, nargs, NULL, "timeout", UC_INTEGER, false, &timeoutarg); 2744 2745 timeout = ucv_to_integer(timeoutarg); 2746 2747 if (errno != 0 || timeout < (int64_t)INT_MIN || timeout > (int64_t)INT_MAX) 2748 err_return(ERANGE, "Invalid timeout value"); 2749 2750 size_t argoff = vm->stack.count - nargs; 2751 2752 rv = ucv_array_new(vm); 2753 uc_vm_stack_push(vm, ucv_get(rv)); 2754 2755 for (size_t i = 1; i < nargs; i++) { 2756 uc_vector_grow(&pfds); 2757 item = uv_to_pollfd(vm, vm->stack.entries[argoff + i], &pfds.entries[pfds.count]); 2758 2759 if (item) 2760 ucv_array_set(rv, pfds.count++, item); 2761 } 2762 2763 ret = poll(pfds.entries, pfds.count, timeout); 2764 2765 if (ret == -1) { 2766 ucv_put(uc_vm_stack_pop(vm)); 2767 ucv_put(rv); 2768 uc_vector_clear(&pfds); 2769 err_return(errno, "poll()"); 2770 } 2771 2772 for (size_t i = 0; i < pfds.count; i++) 2773 ucv_array_set(ucv_array_get(rv, i), 1, 2774 ucv_int64_new(pfds.entries[i].revents)); 2775 2776 ucv_put(uc_vm_stack_pop(vm)); 2777 uc_vector_clear(&pfds); 2778 ok_return(rv); 2779 } 2780 2781 static bool 2782 should_resolve(uc_value_t *host) 2783 { 2784 char *s = ucv_string_get(host); 2785 2786 return (s != NULL && memchr(s, '/', ucv_string_length(host)) == NULL); 2787 } 2788 2789 /** 2790 * Creates a network socket and connects it to the specified host and service. 2791 * 2792 * This high level function combines the functionality of 2793 * {@link module:socket#create|create()}, 2794 * {@link module:socket#addrinfo|addrinfo()} and 2795 * {@link module:socket.socket#connect|connect()} to simplify connection 2796 * establishment with the socket module. 2797 * 2798 * @function module:socket#connect 2799 * 2800 * @param {string|number[]|module:socket.socket.SocketAddress} host 2801 * The host to connect to, can be an IP address, hostname, 2802 * {@link module:socket.socket.SocketAddress|SocketAddress}, or an array value 2803 * returned by {@link module:core#iptoarr|iptoarr()}. 2804 * 2805 * @param {string|number} [service] 2806 * The service to connect to, can be a symbolic service name (such as "http") or 2807 * a port number. Optional if host is specified as 2808 * {@link module:socket.socket.SocketAddress|SocketAddress}. 2809 * 2810 * @param {Object} [hints] 2811 * Optional preferences for the socket. It can contain the following properties: 2812 * - `family`: The preferred address family (`AF_INET` or `AF_INET6`). 2813 * - `socktype`: The socket type (`SOCK_STREAM`, `SOCK_DGRAM`, etc.). 2814 * - `protocol`: The protocol of the created socket. 2815 * - `flags`: Bitwise OR-ed `AI_*` flags to control the resolution behavior. 2816 * 2817 * If no hints are not provided, the default socket type preference is set to 2818 * `SOCK_STREAM`. 2819 * 2820 * @param {number} [timeout=-1] 2821 * The timeout in milliseconds for socket connect operations. If set to a 2822 * negative value, no specifc time limit is imposed and the function will 2823 * block until either a connection was successfull or the underlying operating 2824 * system timeout is reached. 2825 * 2826 * @returns {module:socket.socket} 2827 * 2828 * @example 2829 * // Resolve host, try to connect to both resulting IPv4 and IPv6 addresses 2830 * let conn = socket.connect("example.org", 80); 2831 * 2832 * // Enforce usage of IPv6 2833 * let conn = socket.connect("example.com", 80, { family: socket.AF_INET6 }); 2834 * 2835 * // Connect a UDP socket 2836 * let conn = socket.connect("192.168.1.1", 53, { socktype: socket.SOCK_DGRAM }); 2837 * 2838 * // Bypass name resolution by specifying a SocketAddress structure 2839 * let conn = socket.connect({ address: "127.0.0.1", port: 9000 }); 2840 * 2841 * // Use SocketAddress structure to connect a UNIX domain socket 2842 * let conn = socket.connect({ path: "/var/run/daemon.sock" }); 2843 */ 2844 static uc_value_t * 2845 uc_socket_connect(uc_vm_t *vm, size_t nargs) 2846 { 2847 struct address { 2848 struct sockaddr_storage ss; 2849 struct addrinfo ai; 2850 int flags; 2851 int fd; 2852 } *ap; 2853 2854 struct { struct address *entries; size_t count; } addresses = { 0 }; 2855 struct { struct pollfd *entries; size_t count; } pollfds = { 0 }; 2856 struct addrinfo *ai_results, *ai_hints, *ai; 2857 uc_value_t *host, *serv, *hints, *timeout; 2858 const char *errmsg = NULL; 2859 struct pollfd *pp = NULL; 2860 size_t slot, connected; 2861 int ret, err; 2862 2863 args_get(vm, nargs, NULL, 2864 "host", UC_NULL, false, &host, 2865 "service", UC_NULL, true, &serv, 2866 "hints", UC_OBJECT, true, &hints, 2867 "timeout", UC_INTEGER, true, &timeout); 2868 2869 ai_hints = hints 2870 ? (struct addrinfo *)uv_to_struct(hints, &st_addrinfo) : NULL; 2871 2872 if (should_resolve(host)) { 2873 char *servstr = (ucv_type(serv) != UC_STRING) 2874 ? ucv_to_string(vm, serv) : NULL; 2875 2876 ret = getaddrinfo(ucv_string_get(host), 2877 servstr ? servstr : ucv_string_get(serv), 2878 ai_hints ? ai_hints : &(struct addrinfo){ 2879 .ai_socktype = SOCK_STREAM 2880 }, &ai_results); 2881 2882 if (ret != 0) { 2883 free(servstr); 2884 free(ai_hints); 2885 err_return((ret == EAI_SYSTEM) ? errno : ret, 2886 "getaddrinfo()"); 2887 } 2888 2889 for (ai = ai_results; ai != NULL; ai = ai->ai_next) { 2890 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) 2891 continue; 2892 2893 uc_vector_grow(&addresses); 2894 ap = &addresses.entries[addresses.count++]; 2895 memcpy(&ap->ss, ai->ai_addr, ai->ai_addrlen); 2896 memcpy(&ap->ai, ai, sizeof(*ai)); 2897 ap->ai.ai_addr = (struct sockaddr *)&ap->ss; 2898 } 2899 2900 freeaddrinfo(ai_results); 2901 free(servstr); 2902 } 2903 else { 2904 uc_vector_grow(&addresses); 2905 ap = &addresses.entries[addresses.count++]; 2906 2907 if (!uv_to_sockaddr(host, &ap->ss, &ap->ai.ai_addrlen)) { 2908 free(ai_hints); 2909 uc_vector_clear(&addresses); 2910 return NULL; 2911 } 2912 2913 if (serv) { 2914 uint64_t port = ucv_to_unsigned(serv); 2915 2916 if (port > 65535) 2917 errno = ERANGE; 2918 2919 if (errno != 0) { 2920 free(ai_hints); 2921 uc_vector_clear(&addresses); 2922 err_return(errno, "Invalid port number"); 2923 } 2924 2925 ((struct sockaddr_in *)&ap->ss)->sin_port = htons(port); 2926 } 2927 2928 ap->ai.ai_addr = (struct sockaddr *)&ap->ss; 2929 ap->ai.ai_family = ap->ss.ss_family; 2930 ap->ai.ai_socktype = ai_hints ? ai_hints->ai_socktype : SOCK_STREAM; 2931 ap->ai.ai_protocol = ai_hints ? ai_hints->ai_protocol : 0; 2932 } 2933 2934 free(ai_hints); 2935 2936 for (connected = 0, slot = 0, ap = &addresses.entries[slot]; 2937 slot < addresses.count; 2938 slot++, ap = &addresses.entries[slot]) 2939 { 2940 uc_vector_grow(&pollfds); 2941 pp = &pollfds.entries[pollfds.count++]; 2942 pp->events = POLLIN | POLLOUT | POLLHUP | POLLERR; 2943 pp->fd = socket(ap->ai.ai_family, ap->ai.ai_socktype, ap->ai.ai_protocol); 2944 2945 if (pp->fd == -1) 2946 continue; 2947 2948 if ((ap->flags = fcntl(pp->fd, F_GETFL, 0)) == -1) { 2949 xclose(&pp->fd); 2950 continue; 2951 } 2952 2953 if (fcntl(pp->fd, F_SETFL, ap->flags | O_NONBLOCK) == -1) { 2954 xclose(&pp->fd); 2955 continue; 2956 } 2957 2958 ret = connect(pp->fd, ap->ai.ai_addr, ap->ai.ai_addrlen); 2959 2960 if (ret == -1 && errno != EINPROGRESS) { 2961 xclose(&pp->fd); 2962 continue; 2963 } 2964 2965 connected++; 2966 } 2967 2968 if (connected == 0) { 2969 err = EAI_NONAME; 2970 errmsg = "Could not connect to any host address"; 2971 goto out; 2972 } 2973 2974 ret = poll(pollfds.entries, pollfds.count, 2975 timeout ? ucv_int64_get(timeout) : -1); 2976 2977 if (ret == -1) { 2978 err = errno; 2979 errmsg = "poll()"; 2980 goto out; 2981 } 2982 2983 err = 0; 2984 errmsg = NULL; 2985 2986 for (slot = 0, ap = NULL, pp = NULL; slot < pollfds.count; slot++) { 2987 if (pollfds.entries[slot].revents & (POLLIN|POLLOUT)) { 2988 ret = getsockopt(pollfds.entries[slot].fd, SOL_SOCKET, SO_ERROR, 2989 &err, &(socklen_t){ sizeof(err) }); 2990 2991 if (ret == -1) { 2992 err = errno; 2993 errmsg = "getsockopt()"; 2994 continue; 2995 } 2996 else if (err != 0) { 2997 errmsg = "connect()"; 2998 continue; 2999 } 3000 3001 ap = &addresses.entries[slot]; 3002 pp = &pollfds.entries[slot]; 3003 break; 3004 } 3005 } 3006 3007 if (!ap) { 3008 if (!errmsg) { 3009 err = ETIMEDOUT; 3010 errmsg = "Connection timed out"; 3011 } 3012 3013 goto out; 3014 } 3015 3016 if (fcntl(pp->fd, F_SETFL, ap->flags) == -1) { 3017 err = errno; 3018 errmsg = "fcntl(F_SETFL)"; 3019 goto out; 3020 } 3021 3022 out: 3023 for (slot = 0, ret = -1; slot < pollfds.count; slot++) { 3024 if (pp == &pollfds.entries[slot]) 3025 ret = pollfds.entries[slot].fd; 3026 else 3027 xclose(&pollfds.entries[slot].fd); 3028 } 3029 3030 uc_vector_clear(&addresses); 3031 uc_vector_clear(&pollfds); 3032 3033 if (errmsg) 3034 err_return(err, "%s", errmsg); 3035 3036 ok_return(ucv_socket_new(vm, ret)); 3037 } 3038 3039 /** 3040 * Binds a listening network socket to the specified host and service. 3041 * 3042 * This high-level function combines the functionality of 3043 * {@link module:socket#create|create()}, 3044 * {@link module:socket#addrinfo|addrinfo()}, 3045 * {@link module:socket.socket#bind|bind()}, and 3046 * {@link module:socket.socket#listen|listen()} to simplify setting up a 3047 * listening socket with the socket module. 3048 * 3049 * @function module:socket#listen 3050 * 3051 * @param {string|number[]|module:socket.socket.SocketAddress} host 3052 * The host to bind to, can be an IP address, hostname, 3053 * {@link module:socket.socket.SocketAddress|SocketAddress}, or an array value 3054 * returned by {@link module:core#iptoarr|iptoarr()}. 3055 * 3056 * @param {string|number} [service] 3057 * The service to listen on, can be a symbolic service name (such as "http") or 3058 * a port number. Optional if host is specified as 3059 * {@link module:socket.socket.SocketAddress|SocketAddress}. 3060 * 3061 * @param {Object} [hints] 3062 * Optional preferences for the socket. It can contain the following properties: 3063 * - `family`: The preferred address family (`AF_INET` or `AF_INET6`). 3064 * - `socktype`: The socket type (`SOCK_STREAM`, `SOCK_DGRAM`, etc.). 3065 * - `protocol`: The protocol of the created socket. 3066 * - `flags`: Bitwise OR-ed `AI_*` flags to control the resolution behavior. 3067 * 3068 * If no hints are provided, the default socket type preference is set to 3069 * `SOCK_STREAM`. 3070 * 3071 * @param {number} [backlog=128] 3072 * The maximum length of the queue of pending connections. 3073 * 3074 * @param {boolean} [reuseaddr] 3075 * Whether to set the SO_REUSEADDR option before calling bind(). 3076 * 3077 * @returns {module:socket.socket} 3078 * 3079 * @example 3080 * // Listen for incoming TCP connections on port 80 3081 * let server = socket.listen("localhost", 80); 3082 * 3083 * // Listen on IPv6 address only 3084 * let server = socket.listen("machine.local", 8080, { family: socket.AF_INET6 }); 3085 * 3086 * // Listen on a UNIX domain socket 3087 * let server = socket.listen({ path: "/var/run/server.sock" }); 3088 */ 3089 static uc_value_t * 3090 uc_socket_listen(uc_vm_t *vm, size_t nargs) 3091 { 3092 int ret, fd, curr_weight, prev_weight, socktype = 0, protocol = 0; 3093 struct addrinfo *ai_results, *ai_hints, *ai; 3094 uc_value_t *host, *serv, *hints, *backlog, *reuseaddr; 3095 struct sockaddr_storage ss = { 0 }; 3096 bool v6, lo, ll; 3097 socklen_t slen; 3098 3099 args_get(vm, nargs, NULL, 3100 "host", UC_NULL, true, &host, 3101 "service", UC_NULL, true, &serv, 3102 "hints", UC_OBJECT, true, &hints, 3103 "backlog", UC_INTEGER, true, &backlog, 3104 "reuseaddr", UC_BOOLEAN, true, &reuseaddr); 3105 3106 ai_hints = hints 3107 ? (struct addrinfo *)uv_to_struct(hints, &st_addrinfo) : NULL; 3108 3109 if (host == NULL || should_resolve(host)) { 3110 char *servstr = (ucv_type(serv) != UC_STRING) 3111 ? ucv_to_string(vm, serv) : NULL; 3112 3113 ret = getaddrinfo(ucv_string_get(host), 3114 servstr ? servstr : ucv_string_get(serv), 3115 ai_hints ? ai_hints : &(struct addrinfo){ 3116 .ai_flags = AI_PASSIVE | AI_ADDRCONFIG, 3117 .ai_socktype = SOCK_STREAM 3118 }, &ai_results); 3119 3120 free(servstr); 3121 3122 if (ret != 0) { 3123 free(ai_hints); 3124 err_return((ret == EAI_SYSTEM) ? errno : ret, 3125 "getaddrinfo()"); 3126 } 3127 3128 for (ai = ai_results, prev_weight = -1; ai != NULL; ai = ai->ai_next) { 3129 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ai->ai_addr; 3130 struct sockaddr_in *s4 = (struct sockaddr_in *)ai->ai_addr; 3131 3132 v6 = (s6->sin6_family == AF_INET6); 3133 ll = v6 3134 ? IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr) 3135 : ((ntohl(s4->sin_addr.s_addr) & 0xffff0000) == 0xa9fe0000); 3136 lo = v6 3137 ? IN6_IS_ADDR_LOOPBACK(&s6->sin6_addr) 3138 : ((ntohl(s4->sin_addr.s_addr) & 0xff000000) == 0x7f000000); 3139 3140 curr_weight = (!lo << 2) | (v6 << 1) | (!ll << 0); 3141 3142 if (curr_weight > prev_weight) { 3143 prev_weight = curr_weight; 3144 socktype = ai->ai_socktype; 3145 protocol = ai->ai_protocol; 3146 slen = ai->ai_addrlen; 3147 memcpy(&ss, ai->ai_addr, slen); 3148 } 3149 } 3150 3151 freeaddrinfo(ai_results); 3152 } 3153 else { 3154 if (!uv_to_sockaddr(host, &ss, &slen)) { 3155 free(ai_hints); 3156 return NULL; 3157 } 3158 3159 if (serv) { 3160 uint64_t port = ucv_to_unsigned(serv); 3161 3162 if (port > 65535) 3163 errno = ERANGE; 3164 3165 if (errno != 0) { 3166 free(ai_hints); 3167 err_return(errno, "Invalid port number"); 3168 } 3169 3170 ((struct sockaddr_in *)&ss)->sin_port = htons(port); 3171 } 3172 3173 int default_socktype = SOCK_STREAM; 3174 3175 if (ss.ss_family != AF_INET && ss.ss_family != AF_INET6) 3176 default_socktype = SOCK_DGRAM; 3177 3178 socktype = ai_hints ? ai_hints->ai_socktype : default_socktype; 3179 protocol = ai_hints ? ai_hints->ai_protocol : 0; 3180 } 3181 3182 free(ai_hints); 3183 3184 if (ss.ss_family == AF_UNSPEC) 3185 err_return(EAI_NONAME, "Could not resolve host address"); 3186 3187 fd = socket(ss.ss_family, socktype, protocol); 3188 3189 if (fd == -1) 3190 err_return(errno, "socket()"); 3191 3192 if (ucv_is_truish(reuseaddr)) { 3193 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)); 3194 3195 if (ret == -1) 3196 err_return(errno, "setsockopt()"); 3197 } 3198 3199 ret = bind(fd, (struct sockaddr *)&ss, slen); 3200 3201 if (ret == -1) { 3202 close(fd); 3203 err_return(errno, "bind()"); 3204 } 3205 3206 ret = listen(fd, backlog ? ucv_to_unsigned(backlog) : 128); 3207 3208 if (ret == -1 && errno != EOPNOTSUPP) { 3209 close(fd); 3210 err_return(errno, "listen()"); 3211 } 3212 3213 ok_return(ucv_socket_new(vm, fd)); 3214 } 3215 3216 /** 3217 * Represents a socket handle. 3218 * 3219 * @class module:socket.socket 3220 * @hideconstructor 3221 * 3222 * @borrows module:socket#error as module:socket.socket#error 3223 * 3224 * @see {@link module:socket#create|create()} 3225 * 3226 * @example 3227 * 3228 * const sock = create(…); 3229 * 3230 * sock.getopt(…); 3231 * sock.setopt(…); 3232 * 3233 * sock.connect(…); 3234 * sock.listen(…); 3235 * sock.accept(…); 3236 * sock.bind(…); 3237 * 3238 * sock.send(…); 3239 * sock.recv(…); 3240 * 3241 * sock.shutdown(…); 3242 * 3243 * sock.fileno(); 3244 * sock.peername(); 3245 * sock.sockname(); 3246 * 3247 * sock.close(); 3248 * 3249 * sock.error(); 3250 */ 3251 3252 /** 3253 * Creates a network socket instance. 3254 * 3255 * This function creates a new network socket with the specified domain and 3256 * type, determined by one of the modules `AF_*` and `SOCK_*` constants 3257 * respectively, and returns the resulting socket instance for use in subsequent 3258 * socket operations. 3259 * 3260 * The domain argument specifies the protocol family, such as AF_INET or 3261 * AF_INET6, and defaults to AF_INET if not provided. 3262 * 3263 * The type argument specifies the socket type, such as SOCK_STREAM or 3264 * SOCK_DGRAM, and defaults to SOCK_STREAM if not provided. It may also 3265 * be bitwise OR-ed with SOCK_NONBLOCK to enable non-blocking mode or 3266 * SOCK_CLOEXEC to enable close-on-exec semantics. 3267 * 3268 * The protocol argument may be used to indicate a particular protocol 3269 * to be used with the socket, and it defaults to 0 (automatically 3270 * determined protocol) if not provided. 3271 * 3272 * Returns a socket descriptor representing the newly created socket. 3273 * 3274 * Returns `null` if an error occurred during socket creation. 3275 * 3276 * @function module:socket#create 3277 * 3278 * @param {number} [domain=AF_INET] 3279 * The communication domain for the socket, e.g., AF_INET or AF_INET6. 3280 * 3281 * @param {number} [type=SOCK_STREAM] 3282 * The socket type, e.g., SOCK_STREAM or SOCK_DGRAM. It may also be 3283 * bitwise OR-ed with SOCK_NONBLOCK or SOCK_CLOEXEC. 3284 * 3285 * @param {number} [protocol=0] 3286 * The protocol to be used with the socket. 3287 * 3288 * @returns {?module:socket.socket} 3289 * A socket instance representing the newly created socket. 3290 * 3291 * @example 3292 * // Create a TCP socket 3293 * const tcp_socket = create(AF_INET, SOCK_STREAM); 3294 * 3295 * // Create a nonblocking IPv6 UDP socket 3296 * const udp_socket = create(AF_INET6, SOCK_DGRAM | SOCK_NONBLOCK); 3297 */ 3298 static uc_value_t * 3299 uc_socket_create(uc_vm_t *vm, size_t nargs) 3300 { 3301 uc_value_t *domain, *type, *protocol; 3302 int sockfd, socktype; 3303 3304 args_get(vm, nargs, NULL, 3305 "domain", UC_INTEGER, true, &domain, 3306 "type", UC_INTEGER, true, &type, 3307 "protocol", UC_INTEGER, true, &protocol); 3308 3309 socktype = type ? (int)ucv_int64_get(type) : SOCK_STREAM; 3310 3311 sockfd = socket( 3312 domain ? (int)ucv_int64_get(domain) : AF_INET, 3313 #if defined(__APPLE__) 3314 socktype & ~(SOCK_NONBLOCK|SOCK_CLOEXEC), 3315 #else 3316 socktype, 3317 #endif 3318 protocol ? (int)ucv_int64_get(protocol) : 0); 3319 3320 if (sockfd == -1) 3321 err_return(errno, "socket()"); 3322 3323 #if defined(__APPLE__) 3324 if (socktype & SOCK_NONBLOCK) { 3325 int flags = fcntl(sockfd, F_GETFL); 3326 3327 if (flags == -1) { 3328 close(sockfd); 3329 err_return(errno, "fcntl(F_GETFL)"); 3330 } 3331 3332 if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1) { 3333 close(sockfd); 3334 err_return(errno, "fcntl(F_SETFL)"); 3335 } 3336 } 3337 3338 if (socktype & SOCK_CLOEXEC) { 3339 if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) { 3340 close(sockfd); 3341 err_return(errno, "fcntl(F_SETFD)"); 3342 } 3343 } 3344 #endif 3345 3346 ok_return(ucv_socket_new(vm, sockfd)); 3347 } 3348 3349 /** 3350 * Creates a network socket instance from an existing file descriptor. 3351 * 3352 * Returns a socket descriptor representing the newly created socket. 3353 * 3354 * Returns `null` if an error occurred during socket creation. 3355 * 3356 * @function module:socket#open 3357 * 3358 * @param {number} [fd] 3359 * The file descriptor number 3360 * 3361 * @returns {?module:socket.socket} 3362 * A socket instance representing the socket. 3363 */ 3364 static uc_value_t * 3365 uc_socket_open(uc_vm_t *vm, size_t nargs) 3366 { 3367 uc_value_t *fd; 3368 3369 args_get(vm, nargs, NULL, 3370 "fd", UC_INTEGER, false, &fd); 3371 3372 ok_return(ucv_socket_new(vm, ucv_int64_get(fd))); 3373 } 3374 3375 /** 3376 * Creates a connected socket instance with a pair file descriptor. 3377 * 3378 * This function creates new network sockets with the specified type, 3379 * determined by one of the `SOCK_*` constants, and returns resulting socket 3380 * instances for use in subsequent socket operations. 3381 * 3382 * The type argument specifies the socket type, such as SOCK_STREAM or 3383 * SOCK_DGRAM, and defaults to SOCK_STREAM if not provided. It may also 3384 * be bitwise OR-ed with SOCK_NONBLOCK to enable non-blocking mode or 3385 * SOCK_CLOEXEC to enable close-on-exec semantics. 3386 * 3387 * Returns an array of socket descriptors. 3388 * 3389 * Returns `null` if an error occurred during socket creation. 3390 * 3391 * @function module:socket#pair 3392 * 3393 * @param {number} [type=SOCK_STREAM] 3394 * The socket type, e.g., SOCK_STREAM or SOCK_DGRAM. It may also be 3395 * bitwise OR-ed with SOCK_NONBLOCK or SOCK_CLOEXEC. 3396 * 3397 * @returns {Array.<?module:socket.socket>} 3398 * Socket instances representing the newly created sockets. 3399 * 3400 * @example 3401 * // Create a TCP socket pair 3402 * const tcp_sockets = pair(SOCK_STREAM); 3403 * 3404 * // Create a nonblocking IPv6 UDP socket pair 3405 * const udp_sockets = pair(SOCK_DGRAM | SOCK_NONBLOCK); 3406 */ 3407 static uc_value_t * 3408 uc_socket_pair(uc_vm_t *vm, size_t nargs) 3409 { 3410 uc_value_t *type, *res; 3411 int sockfds[2], socktype; 3412 3413 args_get(vm, nargs, NULL, 3414 "type", UC_INTEGER, true, &type); 3415 3416 socktype = type ? (int)ucv_int64_get(type) : SOCK_STREAM; 3417 3418 if (socketpair(AF_UNIX, 3419 #if defined(__APPLE__) 3420 socktype & ~(SOCK_NONBLOCK|SOCK_CLOEXEC), 3421 #else 3422 socktype, 3423 #endif 3424 0, sockfds) < 0) 3425 err_return(errno, "socketpair()"); 3426 3427 #if defined(__APPLE__) 3428 if (socktype & SOCK_NONBLOCK) { 3429 int flags = fcntl(sockfds[0], F_GETFL); 3430 3431 if (flags == -1) 3432 goto error; 3433 3434 if (fcntl(sockfds[0], F_SETFL, flags | O_NONBLOCK) == -1) 3435 goto error; 3436 } 3437 3438 if (socktype & SOCK_CLOEXEC) { 3439 if (fcntl(sockfds[0], F_SETFD, FD_CLOEXEC) == -1) 3440 goto error; 3441 } 3442 #endif 3443 3444 res = ucv_array_new(vm); 3445 ucv_array_set(res, 0, ucv_socket_new(vm, sockfds[0])); 3446 ucv_array_set(res, 1, ucv_socket_new(vm, sockfds[1])); 3447 ok_return(res); 3448 3449 #if defined(__APPLE__) 3450 error: 3451 #endif 3452 close(sockfds[0]); 3453 close(sockfds[1]); 3454 err_return(errno, "fcntl"); 3455 } 3456 3457 /** 3458 * Connects the socket to a remote address. 3459 * 3460 * Attempts to establish a connection to the specified remote address. 3461 * 3462 * Returns `true` if the connection is successfully established. 3463 * Returns `null` if an error occurred during the connection attempt. 3464 * 3465 * @function module:socket.socket#connect 3466 * 3467 * @param {string|module:socket.socket.SocketAddress} address 3468 * The address of the remote endpoint to connect to. 3469 * 3470 * @param {number} port 3471 * The port number of the remote endpoint to connect to. 3472 * 3473 * @returns {?boolean} 3474 */ 3475 static uc_value_t * 3476 uc_socket_inst_connect(uc_vm_t *vm, size_t nargs) 3477 { 3478 struct sockaddr_storage ss; 3479 uc_value_t *addr, *port; 3480 unsigned long n; 3481 int ret, sockfd; 3482 socklen_t slen; 3483 3484 args_get(vm, nargs, &sockfd, 3485 "address", UC_NULL, false, &addr, 3486 "port", UC_INTEGER, true, &port); 3487 3488 if (!uv_to_sockaddr(addr, &ss, &slen)) 3489 return NULL; 3490 3491 if (port) { 3492 if (ss.ss_family != AF_INET && ss.ss_family != AF_INET6) 3493 err_return(EINVAL, "Port argument is only valid for IPv4 and IPv6 addresses"); 3494 3495 n = ucv_to_unsigned(port); 3496 3497 if (n > 65535) 3498 errno = ERANGE; 3499 3500 if (errno != 0) 3501 err_return(errno, "Invalid port number"); 3502 3503 ((struct sockaddr_in6 *)&ss)->sin6_port = htons(n); 3504 } 3505 3506 ret = connect(sockfd, (struct sockaddr *)&ss, slen); 3507 3508 if (ret == -1) 3509 err_return(errno, "connect()"); 3510 3511 ok_return(ucv_boolean_new(true)); 3512 } 3513 3514 /** 3515 * Sends data through the socket. 3516 * 3517 * Sends the provided data through the socket handle to the specified remote 3518 * address, if provided. 3519 * 3520 * Returns the number of bytes sent. 3521 * Returns `null` if an error occurred during the send operation. 3522 * 3523 * @function module:socket.socket#send 3524 * 3525 * @param {*} data 3526 * The data to be sent through the socket. String data is sent as-is, any other 3527 * type is implicitly converted to a string first before being sent on the 3528 * socket. 3529 * 3530 * @param {number} [flags] 3531 * Optional flags that modify the behavior of the send operation. 3532 * 3533 * @param {module:socket.socket.SocketAddress|number[]|string} [address] 3534 * The address of the remote endpoint to send the data to. It can be either an 3535 * IP address string, an array returned by {@link module:core#iptoarr|iptoarr()}, 3536 * or an object representing a network address. If not provided, the data is 3537 * sent to the remote endpoint the socket is connected to. 3538 * 3539 * @returns {?number} 3540 * 3541 * @see {@link module:socket#sockaddr|sockaddr()} 3542 * 3543 * @example 3544 * // Send to connected socket 3545 * let tcp_sock = socket.create(socket.AF_INET, socket.SOCK_STREAM); 3546 * tcp_sock.connect("192.168.1.1", 80); 3547 * tcp_sock.send("GET / HTTP/1.0\r\n\r\n"); 3548 * 3549 * // Send a datagram on unconnected socket 3550 * let udp_sock = socket.create(socket.AF_INET, socket.SOCK_DGRAM); 3551 * udp_sock.send("Hello there!", 0, "255.255.255.255:9000"); 3552 * udp_sock.send("Hello there!", 0, { 3553 * family: socket.AF_INET, // optional 3554 * address: "255.255.255.255", 3555 * port: 9000 3556 * }); 3557 */ 3558 static uc_value_t * 3559 uc_socket_inst_send(uc_vm_t *vm, size_t nargs) 3560 { 3561 uc_value_t *data, *flags, *addr; 3562 struct sockaddr_storage ss = { 0 }; 3563 struct sockaddr *sa = NULL; 3564 socklen_t salen = 0; 3565 char *buf = NULL; 3566 ssize_t ret; 3567 int sockfd; 3568 3569 args_get(vm, nargs, &sockfd, 3570 "data", UC_NULL, false, &data, 3571 "flags", UC_INTEGER, true, &flags, 3572 "address", UC_NULL, true, &addr); 3573 3574 if (addr) { 3575 if (!uv_to_sockaddr(addr, &ss, &salen)) 3576 return NULL; 3577 3578 sa = (struct sockaddr *)&ss; 3579 } 3580 3581 if (ucv_type(data) != UC_STRING) 3582 buf = ucv_to_string(vm, data); 3583 3584 ret = sendto(sockfd, 3585 buf ? buf : ucv_string_get(data), 3586 buf ? strlen(buf) : ucv_string_length(data), 3587 (flags ? ucv_int64_get(flags) : 0) | MSG_NOSIGNAL, sa, salen); 3588 3589 free(buf); 3590 3591 if (ret == -1) 3592 err_return(errno, "send()"); 3593 3594 ok_return(ucv_int64_new(ret)); 3595 } 3596 3597 /** 3598 * Receives data from the socket. 3599 * 3600 * Receives data from the socket handle, optionally specifying the maximum 3601 * length of data to receive, flags to modify the receive behavior, and an 3602 * optional address dictionary where the function will place the address from 3603 * which the data was received (for unconnected sockets). 3604 * 3605 * Returns a string containing the received data. 3606 * Returns an empty string if the remote side closed the socket. 3607 * Returns `null` if an error occurred during the receive operation. 3608 * 3609 * @function module:socket.socket#recv 3610 * 3611 * @param {number} [length=4096] 3612 * The maximum number of bytes to receive. 3613 * 3614 * @param {number} [flags] 3615 * Optional flags that modify the behavior of the receive operation. 3616 * 3617 * @param {Object} [address] 3618 * An object where the function will store the address from which the data was 3619 * received. If provided, it will be filled with the details obtained from the 3620 * sockaddr argument of the underlying `recvfrom()` syscall. See the type 3621 * definition of {@link module:socket.socket.SocketAddress|SocketAddress} for 3622 * details on the format. 3623 * 3624 * @returns {?string} 3625 */ 3626 static uc_value_t * 3627 uc_socket_inst_recv(uc_vm_t *vm, size_t nargs) 3628 { 3629 uc_value_t *length, *flags, *addrobj; 3630 struct sockaddr_storage ss = { 0 }; 3631 uc_stringbuf_t *buf; 3632 ssize_t len, ret; 3633 socklen_t sslen; 3634 int sockfd; 3635 3636 args_get(vm, nargs, &sockfd, 3637 "length", UC_INTEGER, true, &length, 3638 "flags", UC_INTEGER, true, &flags, 3639 "address", UC_OBJECT, true, &addrobj); 3640 3641 if (length) { 3642 len = ucv_to_integer(length); 3643 3644 if (errno || len <= 0) 3645 err_return(errno, "Invalid length argument"); 3646 } 3647 else { 3648 len = 4096; 3649 } 3650 3651 buf = strbuf_alloc(len); 3652 3653 if (!buf) 3654 return NULL; 3655 3656 do { 3657 sslen = sizeof(ss); 3658 ret = recvfrom(sockfd, strbuf_data(buf), len, 3659 flags ? ucv_int64_get(flags) : 0, (struct sockaddr *)&ss, &sslen); 3660 } while (ret == -1 && errno == EINTR); 3661 3662 if (ret == -1) { 3663 strbuf_free(buf); 3664 err_return(errno, "recv()"); 3665 } 3666 3667 if (addrobj) 3668 sockaddr_to_uv(&ss, addrobj); 3669 3670 ok_return(strbuf_finish(&buf, ret)); 3671 } 3672 3673 uc_declare_vector(strbuf_array_t, uc_stringbuf_t *); 3674 3675 #if defined(__linux__) 3676 static void optmem_max(size_t *sz) { 3677 char buf[sizeof("18446744073709551615")] = { 0 }; 3678 int fd, rv; 3679 3680 fd = open("/proc/sys/net/core/optmem_max", O_RDONLY); 3681 3682 if (fd >= 0) { 3683 if (read(fd, buf, sizeof(buf) - 1) > 0) { 3684 rv = strtol(buf, NULL, 10); 3685 3686 if (rv > 0 && (size_t)rv < *sz) 3687 *sz = rv; 3688 } 3689 3690 if (fd > 2) 3691 close(fd); 3692 } 3693 } 3694 #else 3695 # define optmem_max(x) 3696 #endif 3697 3698 3699 /** 3700 * Represents a single control (ancillary data) message returned 3701 * in the *ancillary* array by {@link module:socket.socket#recvmsg|`recvmsg()`}. 3702 * 3703 * @typedef {Object} module:socket.socket.ControlMessage 3704 * @property {number} level 3705 * The message socket level (`cmsg_level`), e.g. `SOL_SOCKET`. 3706 * 3707 * @property {number} type 3708 * The protocol specific message type (`cmsg_type`), e.g. `SCM_RIGHTS`. 3709 * 3710 * @property {*} data 3711 * The payload of the control message. If the control message type is known by 3712 * the socket module, it is represented as a mixed value (array, object, number, 3713 * etc.) with structure specific to the control message type. If the control 3714 * message cannot be decoded, *data* is set to a string value containing the raw 3715 * payload. 3716 */ 3717 static uc_value_t * 3718 decode_cmsg(uc_vm_t *vm, struct cmsghdr *cmsg) 3719 { 3720 char *s = (char *)CMSG_DATA(cmsg); 3721 size_t sz = cmsg->cmsg_len - sizeof(*cmsg); 3722 struct sockaddr_storage *ss; 3723 uc_value_t *fdarr; 3724 struct stat st; 3725 int *fds; 3726 3727 for (size_t i = 0; i < ARRAY_SIZE(cmsgtypes); i++) { 3728 3729 if (cmsgtypes[i].level != cmsg->cmsg_level) 3730 continue; 3731 3732 if (cmsgtypes[i].type != cmsg->cmsg_type) 3733 continue; 3734 3735 switch ((uintptr_t)cmsgtypes[i].ctype) { 3736 case (uintptr_t)CV_INT: 3737 return ucv_int64_new(parse_integer(s, sz)); 3738 3739 case (uintptr_t)CV_UINT: 3740 case (uintptr_t)CV_BE32: 3741 return ucv_uint64_new(parse_unsigned(s, sz)); 3742 3743 case (uintptr_t)CV_SOCKADDR: 3744 ss = (struct sockaddr_storage *)s; 3745 3746 if ((sz >= sizeof(struct sockaddr_in) && 3747 ss->ss_family == AF_INET) || 3748 (sz >= sizeof(struct sockaddr_in6) && 3749 ss->ss_family == AF_INET6)) 3750 { 3751 uc_value_t *addr = ucv_object_new(vm); 3752 3753 if (sockaddr_to_uv(ss, addr)) 3754 return addr; 3755 3756 ucv_put(addr); 3757 } 3758 3759 return NULL; 3760 3761 case (uintptr_t)CV_FDS: 3762 fdarr = ucv_array_new_length(vm, sz / sizeof(int)); 3763 fds = (int *)s; 3764 3765 for (size_t i = 0; i < sz / sizeof(int); i++) { 3766 if (fstat(fds[i], &st) == 0) { 3767 uc_resource_type_t *t; 3768 3769 if (S_ISSOCK(st.st_mode)) { 3770 t = ucv_resource_type_lookup(vm, "socket"); 3771 3772 ucv_array_push(fdarr, 3773 ucv_resource_new(t, (void *)(intptr_t)fds[i])); 3774 3775 continue; 3776 } 3777 else if (S_ISDIR(st.st_mode)) { 3778 t = ucv_resource_type_lookup(vm, "fs.dir"); 3779 3780 if (t) { 3781 DIR *d = fdopendir(fds[i]); 3782 3783 if (d) { 3784 ucv_array_push(fdarr, ucv_resource_new(t, d)); 3785 continue; 3786 } 3787 } 3788 } 3789 else { 3790 t = ucv_resource_type_lookup(vm, "fs.file"); 3791 3792 if (t) { 3793 int n = fcntl(fds[i], F_GETFL); 3794 const char *mode; 3795 3796 if (n <= 0 || (n & O_ACCMODE) == O_RDONLY) 3797 mode = "r"; 3798 else if ((n & O_ACCMODE) == O_WRONLY) 3799 mode = (n & O_APPEND) ? "a" : "w"; 3800 else 3801 mode = (n & O_APPEND) ? "a+" : "w+"; 3802 3803 FILE *f = fdopen(fds[i], mode); 3804 3805 if (f) { 3806 ucv_array_push(fdarr, uc_resource_new(t, f)); 3807 continue; 3808 } 3809 } 3810 } 3811 } 3812 3813 ucv_array_push(fdarr, ucv_int64_new(fds[i])); 3814 } 3815 3816 return fdarr; 3817 3818 case (uintptr_t)CV_STRING: 3819 break; 3820 3821 default: 3822 if (sz >= cmsgtypes[i].ctype->size) 3823 return struct_to_uv(s, cmsgtypes[i].ctype); 3824 } 3825 3826 break; 3827 } 3828 3829 return ucv_string_new_length(s, sz); 3830 } 3831 3832 static size_t 3833 estimate_cmsg_size(uc_value_t *uv) 3834 { 3835 int cmsg_level = ucv_to_integer(ucv_object_get(uv, "level", NULL)); 3836 int cmsg_type = ucv_to_integer(ucv_object_get(uv, "type", NULL)); 3837 uc_value_t *val = ucv_object_get(uv, "data", NULL); 3838 3839 for (size_t i = 0; i < ARRAY_SIZE(cmsgtypes); i++) { 3840 if (cmsgtypes[i].level != cmsg_level) 3841 continue; 3842 3843 if (cmsgtypes[i].type != cmsg_type) 3844 continue; 3845 3846 switch ((uintptr_t)cmsgtypes[i].ctype) { 3847 case (uintptr_t)CV_INT: return sizeof(int); 3848 case (uintptr_t)CV_UINT: return sizeof(unsigned int); 3849 case (uintptr_t)CV_BE32: return sizeof(uint32_t); 3850 case (uintptr_t)CV_SOCKADDR: return sizeof(struct sockaddr_storage); 3851 case (uintptr_t)CV_FDS: return ucv_array_length(val) * sizeof(int); 3852 case (uintptr_t)CV_STRING: return ucv_string_length(val); 3853 default: return cmsgtypes[i].ctype->size; 3854 } 3855 } 3856 3857 switch (ucv_type(val)) { 3858 case UC_BOOLEAN: return sizeof(unsigned int); 3859 case UC_INTEGER: return sizeof(int); 3860 case UC_STRING: return ucv_string_length(val); 3861 default: return 0; 3862 } 3863 } 3864 3865 static bool 3866 encode_cmsg(uc_vm_t *vm, uc_value_t *uv, struct cmsghdr *cmsg) 3867 { 3868 struct { int *entries; size_t count; } fds = { 0 }; 3869 void *dataptr = NULL; 3870 socklen_t datasz = 0; 3871 char *st = NULL; 3872 size_t i; 3873 union { 3874 int i; 3875 unsigned int u; 3876 uint32_t u32; 3877 struct sockaddr_storage ss; 3878 } val; 3879 3880 cmsg->cmsg_level = ucv_to_integer(ucv_object_get(uv, "level", NULL)); 3881 cmsg->cmsg_type = ucv_to_integer(ucv_object_get(uv, "type", NULL)); 3882 3883 uc_value_t *data = ucv_object_get(uv, "data", NULL); 3884 3885 for (i = 0; i < ARRAY_SIZE(cmsgtypes); i++) { 3886 if (cmsgtypes[i].level != cmsg->cmsg_level) 3887 continue; 3888 3889 if (cmsgtypes[i].type != cmsg->cmsg_type) 3890 continue; 3891 3892 switch ((uintptr_t)cmsgtypes[i].ctype) { 3893 case (uintptr_t)CV_INT: 3894 val.i = ucv_to_integer(data); 3895 datasz = sizeof(val.i); 3896 dataptr = &val; 3897 break; 3898 3899 case (uintptr_t)CV_UINT: 3900 val.u = ucv_to_unsigned(data); 3901 datasz = sizeof(val.u); 3902 dataptr = &val; 3903 break; 3904 3905 case (uintptr_t)CV_BE32: 3906 val.u32 = ucv_to_unsigned(data); 3907 datasz = sizeof(val.u32); 3908 dataptr = &val; 3909 break; 3910 3911 case (uintptr_t)CV_SOCKADDR: 3912 if (uv_to_sockaddr(data, &val.ss, &datasz)) 3913 dataptr = &val; 3914 else 3915 datasz = 0, dataptr = NULL; 3916 break; 3917 3918 case (uintptr_t)CV_FDS: 3919 if (ucv_type(data) == UC_ARRAY) { 3920 for (size_t i = 0; i < ucv_array_length(data); i++) { 3921 int fd; 3922 3923 if (uv_to_fileno(vm, ucv_array_get(data, i), &fd)) 3924 uc_vector_push(&fds, fd); 3925 } 3926 } 3927 3928 datasz = sizeof(fds.entries[0]) * fds.count; 3929 dataptr = fds.entries; 3930 break; 3931 3932 case (uintptr_t)CV_STRING: 3933 datasz = ucv_string_length(data); 3934 dataptr = ucv_string_get(data); 3935 break; 3936 3937 default: 3938 st = uv_to_struct(data, cmsgtypes[i].ctype); 3939 datasz = st ? cmsgtypes[i].ctype->size : 0; 3940 dataptr = st; 3941 break; 3942 } 3943 3944 break; 3945 } 3946 3947 /* we don't know this kind of control message, guess encoding */ 3948 if (i == ARRAY_SIZE(cmsgtypes)) { 3949 switch (ucv_type(data)) { 3950 /* treat boolean as int with values 1 or 0 */ 3951 case UC_BOOLEAN: 3952 val.u = ucv_boolean_get(data); 3953 dataptr = &val; 3954 datasz = sizeof(val.u); 3955 break; 3956 3957 /* treat integers as int */ 3958 case UC_INTEGER: 3959 if (ucv_is_u64(data)) { 3960 val.u = ucv_uint64_get(data); 3961 datasz = sizeof(val.u); 3962 } 3963 else { 3964 val.i = ucv_int64_get(data); 3965 datasz = sizeof(val.i); 3966 } 3967 3968 dataptr = &val; 3969 break; 3970 3971 /* pass strings as-is */ 3972 case UC_STRING: 3973 dataptr = ucv_string_get(data); 3974 datasz = ucv_string_length(data); 3975 break; 3976 3977 default: 3978 break; 3979 } 3980 } 3981 3982 cmsg->cmsg_len = CMSG_LEN(datasz); 3983 3984 if (dataptr) 3985 memcpy(CMSG_DATA(cmsg), dataptr, datasz); 3986 3987 uc_vector_clear(&fds); 3988 free(st); 3989 3990 return true; 3991 } 3992 3993 /** 3994 * Sends a message through the socket. 3995 * 3996 * Sends a message through the socket handle, supporting complex message 3997 * structures including multiple data buffers and ancillary data. This function 3998 * allows for precise control over the message content and delivery behavior. 3999 * 4000 * Returns the number of sent bytes. 4001 * 4002 * Returns `null` if an error occurred. 4003 * 4004 * @function module:socket.socket#sendmsg 4005 * 4006 * @param {*} [data] 4007 * The data to be sent. If a string is provided, it is sent as is. If an array 4008 * is specified, each item is sent as a separate `struct iovec`. Non-string 4009 * values are implicitly converted to a string and sent. If omitted, only 4010 * ancillary data and address are considered. 4011 * 4012 * @param {module:socket.socket.ControlMessage[]|string} [ancillaryData] 4013 * Optional ancillary data to be sent. If an array is provided, each element is 4014 * converted to a control message. If a string is provided, it is sent as-is 4015 * without further interpretation. Refer to 4016 * {@link module:socket.socket#recvmsg|`recvmsg()`} and 4017 * {@link module:socket.socket.ControlMessage|ControlMessage} for details. 4018 * 4019 * @param {module:socket.socket.SocketAddress} [address] 4020 * The destination address for the message. If provided, it sets or overrides 4021 * the packet destination address. 4022 * 4023 * @param {number} [flags] 4024 * Optional flags to modify the behavior of the send operation. This should be a 4025 * bitwise OR-ed combination of `MSG_*` flag values. 4026 * 4027 * @returns {?number} 4028 * Returns the number of bytes sent on success, or `null` if an error occurred. 4029 * 4030 * @example 4031 * // Send file descriptors over domain socket 4032 * const f1 = fs.open("example.txt", "w"); 4033 * const f2 = fs.popen("date +%s", "r"); 4034 * const sk = socket.connect({ family: socket.AF_UNIX, path: "/tmp/socket" }); 4035 4036 * sk.sendmsg("Hi there, here's some descriptors!", [ 4037 * { level: socket.SOL_SOCKET, type: socket.SCM_RIGHTS, data: [ f1, f2 ] } 4038 * ]); 4039 * 4040 * // Send multiple values in one datagram 4041 * sk.sendmsg([ "This", "is", "one", "message" ]); 4042 */ 4043 static uc_value_t * 4044 uc_socket_inst_sendmsg(uc_vm_t *vm, size_t nargs) 4045 { 4046 uc_value_t *data, *ancdata, *addr, *flags; 4047 struct sockaddr_storage ss = { 0 }; 4048 strbuf_array_t sbarr = { 0 }; 4049 struct msghdr msg = { 0 }; 4050 struct iovec vec = { 0 }; 4051 int flagval, sockfd; 4052 socklen_t slen; 4053 ssize_t ret; 4054 4055 args_get(vm, nargs, &sockfd, 4056 "data", UC_NULL, true, &data, 4057 "ancillary data", UC_NULL, true, &ancdata, 4058 "address", UC_OBJECT, true, &addr, 4059 "flags", UC_INTEGER, true, &flags); 4060 4061 flagval = flags ? ucv_int64_get(flags) : 0; 4062 4063 /* treat string ancdata arguemnt as raw controldata buffer */ 4064 if (ucv_type(ancdata) == UC_STRING) { 4065 msg.msg_control = ucv_string_get(ancdata); 4066 msg.msg_controllen = ucv_string_length(ancdata); 4067 } 4068 /* encode ancdata passed as array */ 4069 else if (ucv_type(ancdata) == UC_ARRAY) { 4070 msg.msg_controllen = 0; 4071 4072 for (size_t i = 0; i < ucv_array_length(ancdata); i++) { 4073 size_t sz = estimate_cmsg_size(ucv_array_get(ancdata, i)); 4074 4075 if (sz > 0) 4076 msg.msg_controllen += CMSG_SPACE(sz); 4077 } 4078 4079 if (msg.msg_controllen > 0) { 4080 msg.msg_control = xalloc(msg.msg_controllen); 4081 4082 struct cmsghdr *cmsg = NULL; 4083 4084 for (size_t i = 0; i < ucv_array_length(ancdata); i++) { 4085 #ifdef __clang_analyzer__ 4086 /* Clang static analyzer assumes that CMSG_*HDR() returns 4087 * allocated heap pointers and not pointers into the 4088 * msg.msg_control buffer. Nudge it. */ 4089 cmsg = (struct cmsghdr *)msg.msg_control; 4090 #else 4091 cmsg = cmsg ? CMSG_NXTHDR(&msg, cmsg) : CMSG_FIRSTHDR(&msg); 4092 #endif 4093 4094 if (!cmsg) { 4095 free(msg.msg_control); 4096 err_return(ENOBUFS, "Not enough CMSG buffer space"); 4097 } 4098 4099 if (!encode_cmsg(vm, ucv_array_get(ancdata, i), cmsg)) { 4100 free(msg.msg_control); 4101 return NULL; 4102 } 4103 } 4104 4105 msg.msg_controllen = (cmsg != NULL) 4106 ? (char *)cmsg - (char *)msg.msg_control + CMSG_SPACE(cmsg->cmsg_len) 4107 : 0; 4108 } 4109 } 4110 else if (ancdata) { 4111 err_return(EINVAL, "Ancillary data must be string or array value"); 4112 } 4113 4114 /* prepare iov array */ 4115 if (ucv_type(data) == UC_ARRAY) { 4116 msg.msg_iovlen = ucv_array_length(data); 4117 msg.msg_iov = (msg.msg_iovlen > 1) 4118 ? xalloc(sizeof(vec) * msg.msg_iovlen) : &vec; 4119 4120 for (size_t i = 0; i < (size_t)msg.msg_iovlen; i++) { 4121 uc_value_t *item = ucv_array_get(data, i); 4122 4123 if (ucv_type(item) == UC_STRING) { 4124 msg.msg_iov[i].iov_base = _ucv_string_get(&((uc_array_t *)data)->entries[i]); 4125 msg.msg_iov[i].iov_len = ucv_string_length(item); 4126 } 4127 else if (item) { 4128 struct printbuf *pb = xprintbuf_new(); 4129 uc_vector_push(&sbarr, pb); 4130 ucv_to_stringbuf(vm, pb, item, false); 4131 msg.msg_iov[i].iov_base = pb->buf; 4132 msg.msg_iov[i].iov_len = pb->bpos; 4133 } 4134 } 4135 } 4136 else if (ucv_type(data) == UC_STRING) { 4137 msg.msg_iovlen = 1; 4138 msg.msg_iov = &vec; 4139 vec.iov_base = ucv_string_get(data); 4140 vec.iov_len = ucv_string_length(data); 4141 } 4142 else if (data) { 4143 struct printbuf *pb = xprintbuf_new(); 4144 uc_vector_push(&sbarr, pb); 4145 ucv_to_stringbuf(vm, pb, data, false); 4146 msg.msg_iovlen = 1; 4147 msg.msg_iov = &vec; 4148 vec.iov_base = pb->buf; 4149 vec.iov_len = pb->bpos; 4150 } 4151 4152 /* prepare address */ 4153 if (addr && uv_to_sockaddr(addr, &ss, &slen)) { 4154 msg.msg_name = &ss; 4155 msg.msg_namelen = slen; 4156 } 4157 4158 /* now send actual data */ 4159 do { 4160 ret = sendmsg(sockfd, &msg, flagval); 4161 } while (ret == -1 && errno == EINTR); 4162 4163 while (sbarr.count > 0) 4164 printbuf_free(sbarr.entries[--sbarr.count]); 4165 4166 uc_vector_clear(&sbarr); 4167 4168 if (msg.msg_iov != &vec) 4169 free(msg.msg_iov); 4170 4171 free(msg.msg_control); 4172 4173 if (ret == -1) 4174 err_return(errno, "sendmsg()"); 4175 4176 ok_return(ucv_int64_new(ret)); 4177 } 4178 4179 4180 4181 /** 4182 * Represents a message object returned by 4183 * {@link module:socket.socket#recvmsg|`recvmsg()`}. 4184 * 4185 * @typedef {Object} module:socket.socket.ReceivedMessage 4186 * @property {number} flags 4187 * Integer value containing bitwise OR-ed `MSG_*` result flags returned by the 4188 * underlying receive call. 4189 * 4190 * @property {number} length 4191 * Integer value containing the number of bytes returned by the `recvmsg()` 4192 * syscall, which might be larger than the received data in case `MSG_TRUNC` 4193 * was passed. 4194 * 4195 * @property {module:socket.socket.SocketAddress} address 4196 * The address from which the message was received. 4197 * 4198 * @property {string[]|string} data 4199 * An array of strings, each representing the received message data. 4200 * Each string corresponds to one buffer size specified in the *sizes* argument. 4201 * If a single receive size was passed instead of an array of sizes, *data* will 4202 * hold a string containing the received data. 4203 * 4204 * @property {module:socket.socket.ControlMessage[]} [ancillary] 4205 * An array of received control messages. Only included if a non-zero positive 4206 * *ancillarySize* was passed to `recvmsg()`. 4207 */ 4208 4209 /** 4210 * Receives a message from the socket. 4211 * 4212 * Receives a message from the socket handle, allowing for more complex data 4213 * reception compared to `recv()`. This includes the ability to receive 4214 * ancillary data (such as file descriptors, credentials, etc.), multiple 4215 * message segments, and optional flags to modify the receive behavior. 4216 * 4217 * Returns an object containing the received message data, ancillary data, 4218 * and the sender's address. 4219 * 4220 * Returns `null` if an error occurred during the receive operation. 4221 * 4222 * @function module:socket.socket#recvmsg 4223 * 4224 * @param {number[]|number} [sizes] 4225 * Specifies the sizes of the buffers used for receiving the message. If an 4226 * array of numbers is provided, each number determines the size of an 4227 * individual buffer segment, creating multiple `struct iovec` for reception. 4228 * If a single number is provided, a single buffer of that size is used. 4229 * 4230 * @param {number} [ancillarySize] 4231 * The size allocated for the ancillary data buffer. If not provided, ancillary 4232 * data is not processed. 4233 * 4234 * @param {number} [flags] 4235 * Optional flags to modify the behavior of the receive operation. This should 4236 * be a bitwise OR-ed combination of flag values. 4237 * 4238 * @returns {?module:socket.socket.ReceivedMessage} 4239 * An object containing the received message data, ancillary data, 4240 * and the sender's address. 4241 * 4242 * @example 4243 * // Receive file descriptors over domain socket 4244 * const sk = socket.listen({ family: socket.AF_UNIX, path: "/tmp/socket" }); 4245 * sk.setopt(socket.SOL_SOCKET, socket.SO_PASSCRED, true); 4246 * 4247 * const msg = sk.recvmsg(1024, 1024); * 4248 * for (let cmsg in msg.ancillary) 4249 * if (cmsg.level == socket.SOL_SOCKET && cmsg.type == socket.SCM_RIGHTS) 4250 * print(`Got some descriptors: ${cmsg.data}!\n`); 4251 * 4252 * // Receive message in segments of 10, 128 and 512 bytes 4253 * const msg = sk.recvmsg([ 10, 128, 512 ]); 4254 * print(`Message parts: ${msg.data[0]}, ${msg.data[1]}, ${msg.data[2]}\n`); 4255 * 4256 * // Peek buffer 4257 * const msg = sk.recvmsg(0, 0, socket.MSG_PEEK|socket.MSG_TRUNC); 4258 * print(`Received ${length(msg.data)} bytes, ${msg.length} bytes available\n`); 4259 */ 4260 static uc_value_t * 4261 uc_socket_inst_recvmsg(uc_vm_t *vm, size_t nargs) 4262 { 4263 uc_value_t *length, *anclength, *flags, *rv; 4264 struct sockaddr_storage ss = { 0 }; 4265 strbuf_array_t sbarr = { 0 }; 4266 struct msghdr msg = { 0 }; 4267 struct iovec vec = { 0 }; 4268 int flagval, sockfd; 4269 ssize_t ret; 4270 4271 args_get(vm, nargs, &sockfd, 4272 "length", UC_NULL, true, &length, 4273 "ancillary length", UC_INTEGER, true, &anclength, 4274 "flags", UC_INTEGER, true, &flags); 4275 4276 flagval = flags ? ucv_int64_get(flags) : 0; 4277 4278 /* prepare ancillary data buffer */ 4279 if (anclength) { 4280 size_t sz = ucv_to_unsigned(anclength); 4281 4282 if (errno != 0) 4283 err_return(errno, "Invalid ancillary data length"); 4284 4285 optmem_max(&sz); 4286 4287 if (sz > 0) { 4288 msg.msg_controllen = sz; 4289 msg.msg_control = xalloc(sz); 4290 } 4291 } 4292 4293 /* prepare iov array */ 4294 if (ucv_type(length) == UC_ARRAY) { 4295 msg.msg_iovlen = ucv_array_length(length); 4296 msg.msg_iov = (msg.msg_iovlen > 1) 4297 ? xalloc(sizeof(vec) * msg.msg_iovlen) : &vec; 4298 4299 for (size_t i = 0; i < (size_t)msg.msg_iovlen; i++) { 4300 size_t sz = ucv_to_unsigned(ucv_array_get(length, i)); 4301 4302 if (errno != 0) { 4303 while (sbarr.count > 0) 4304 strbuf_free(sbarr.entries[--sbarr.count]); 4305 4306 uc_vector_clear(&sbarr); 4307 4308 if (msg.msg_iov != &vec) 4309 free(msg.msg_iov); 4310 4311 free(msg.msg_control); 4312 4313 err_return(errno, "Invalid length value"); 4314 } 4315 4316 uc_vector_push(&sbarr, strbuf_alloc(sz)); 4317 msg.msg_iov[i].iov_base = strbuf_data(sbarr.entries[i]); 4318 msg.msg_iov[i].iov_len = sz; 4319 } 4320 } 4321 else { 4322 size_t sz = ucv_to_unsigned(length); 4323 4324 if (errno != 0) { 4325 free(msg.msg_control); 4326 err_return(errno, "Invalid length value"); 4327 } 4328 4329 uc_vector_push(&sbarr, strbuf_alloc(sz)); 4330 4331 msg.msg_iovlen = 1; 4332 msg.msg_iov = &vec; 4333 vec.iov_base = strbuf_data(sbarr.entries[0]); 4334 vec.iov_len = sz; 4335 } 4336 4337 /* now receive actual data */ 4338 msg.msg_name = &ss; 4339 msg.msg_namelen = sizeof(ss); 4340 4341 do { 4342 ret = recvmsg(sockfd, &msg, flagval); 4343 } while (ret == -1 && errno == EINTR); 4344 4345 if (ret == -1) { 4346 while (sbarr.count > 0) 4347 strbuf_free(sbarr.entries[--sbarr.count]); 4348 4349 uc_vector_clear(&sbarr); 4350 4351 if (msg.msg_iov != &vec) 4352 free(msg.msg_iov); 4353 4354 free(msg.msg_control); 4355 4356 err_return(errno, "recvmsg()"); 4357 } 4358 4359 rv = ucv_object_new(vm); 4360 4361 ucv_object_add(rv, "flags", ucv_int64_new(msg.msg_flags)); 4362 ucv_object_add(rv, "length", ucv_int64_new(ret)); 4363 4364 if (msg.msg_namelen > 0) { 4365 uc_value_t *addr = ucv_object_new(vm); 4366 4367 if (sockaddr_to_uv(&ss, addr)) 4368 ucv_object_add(rv, "address", addr); 4369 else 4370 ucv_put(addr); 4371 } 4372 4373 if (msg.msg_controllen > 0) { 4374 uc_value_t *ancillary = ucv_array_new(vm); 4375 4376 for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); 4377 cmsg != NULL; 4378 cmsg = CMSG_NXTHDR(&msg, cmsg)) 4379 { 4380 uc_value_t *c = ucv_object_new(vm); 4381 4382 ucv_object_add(c, "level", ucv_int64_new(cmsg->cmsg_level)); 4383 ucv_object_add(c, "type", ucv_int64_new(cmsg->cmsg_type)); 4384 ucv_object_add(c, "data", decode_cmsg(vm, cmsg)); 4385 4386 ucv_array_push(ancillary, c); 4387 } 4388 4389 ucv_object_add(rv, "ancillary", ancillary); 4390 } 4391 4392 if (ret >= 0) { 4393 if (ucv_type(length) == UC_ARRAY) { 4394 uc_value_t *data = ucv_array_new_length(vm, msg.msg_iovlen); 4395 4396 for (size_t i = 0; i < (size_t)msg.msg_iovlen; i++) { 4397 size_t sz = ret; 4398 4399 if (sz > msg.msg_iov[i].iov_len) 4400 sz = msg.msg_iov[i].iov_len; 4401 4402 ucv_array_push(data, strbuf_finish(&sbarr.entries[i], sz)); 4403 ret -= sz; 4404 } 4405 4406 ucv_object_add(rv, "data", data); 4407 } 4408 else { 4409 size_t sz = ret; 4410 4411 if (sz > msg.msg_iov[0].iov_len) 4412 sz = msg.msg_iov[0].iov_len; 4413 4414 ucv_object_add(rv, "data", strbuf_finish(&sbarr.entries[0], sz)); 4415 } 4416 } 4417 4418 uc_vector_clear(&sbarr); 4419 4420 if (msg.msg_iov != &vec) 4421 free(msg.msg_iov); 4422 4423 free(msg.msg_control); 4424 4425 ok_return(rv); 4426 } 4427 4428 /** 4429 * Binds a socket to a specific address. 4430 * 4431 * This function binds the socket to the specified address. 4432 * 4433 * Returns `true` if the socket is successfully bound. 4434 * 4435 * Returns `null` on error, e.g. when the address is in use. 4436 * 4437 * @function module:socket.socket#bind 4438 * 4439 * @param {string|module:socket.socket.SocketAddress} address 4440 * The IP address to bind the socket to. 4441 * 4442 * @returns {?boolean} 4443 * 4444 * @example 4445 * const sock = socket.create(…); 4446 * const success = sock.bind("192.168.0.1:80"); 4447 * 4448 * if (success) 4449 * print(`Socket bound successfully!\n`); 4450 * else 4451 * print(`Failed to bind socket: ${sock.error()}.\n`); 4452 */ 4453 static uc_value_t * 4454 uc_socket_inst_bind(uc_vm_t *vm, size_t nargs) 4455 { 4456 struct sockaddr_storage ss = { 0 }; 4457 uc_value_t *addr; 4458 socklen_t slen; 4459 int sockfd; 4460 4461 args_get(vm, nargs, &sockfd, 4462 "address", UC_NULL, true, &addr); 4463 4464 if (addr) { 4465 if (!uv_to_sockaddr(addr, &ss, &slen)) 4466 return NULL; 4467 4468 if (bind(sockfd, (struct sockaddr *)&ss, slen) == -1) 4469 err_return(errno, "bind()"); 4470 } 4471 else { 4472 #if defined(__linux__) 4473 int sval = 0; 4474 slen = sizeof(sval); 4475 4476 if (getsockopt(sockfd, SOL_SOCKET, SO_DOMAIN, &sval, &slen) == -1) 4477 err_return(errno, "getsockopt()"); 4478 4479 switch (sval) { 4480 case AF_INET6: 4481 ss.ss_family = AF_INET6; 4482 slen = sizeof(struct sockaddr_in6); 4483 break; 4484 4485 case AF_INET: 4486 ss.ss_family = AF_INET; 4487 slen = sizeof(struct sockaddr_in); 4488 break; 4489 4490 default: 4491 err_return(EAFNOSUPPORT, "Unsupported socket address family"); 4492 } 4493 4494 if (bind(sockfd, (struct sockaddr *)&ss, slen) == -1) 4495 err_return(errno, "bind()"); 4496 #else 4497 ss.ss_family = AF_INET6; 4498 slen = sizeof(struct sockaddr_in6); 4499 4500 if (bind(sockfd, (struct sockaddr *)&ss, slen) == -1) { 4501 if (errno != EAFNOSUPPORT) 4502 err_return(errno, "bind()"); 4503 4504 ss.ss_family = AF_INET; 4505 slen = sizeof(struct sockaddr_in); 4506 4507 if (bind(sockfd, (struct sockaddr *)&ss, slen) == -1) 4508 err_return(errno, "bind()"); 4509 } 4510 #endif 4511 } 4512 4513 ok_return(ucv_boolean_new(true)); 4514 } 4515 4516 /** 4517 * Listen for connections on a socket. 4518 * 4519 * This function marks the socket as a passive socket, that is, as a socket that 4520 * will be used to accept incoming connection requests using `accept()`. 4521 * 4522 * The `backlog` parameter specifies the maximum length to which the queue of 4523 * pending connections may grow. If a connection request arrives when the queue 4524 * is full, the client connection might get refused. 4525 * 4526 * If `backlog` is not provided, it defaults to 128. 4527 * 4528 * Returns `true` if the socket is successfully marked as passive. 4529 * Returns `null` if an error occurred, e.g. when the requested port is in use. 4530 * 4531 * @function module:socket.socket#listen 4532 * 4533 * @param {number} [backlog=128] 4534 * The maximum length of the queue of pending connections. 4535 * 4536 * @returns {?boolean} 4537 * 4538 * @see {@link module:socket.socket#accept|accept()} 4539 * 4540 * @example 4541 * const sock = socket.create(…); 4542 * sock.bind(…); 4543 * 4544 * const success = sock.listen(10); 4545 * if (success) 4546 * print(`Socket is listening for incoming connections!\n`); 4547 * else 4548 * print(`Failed to listen on socket: ${sock.error()}\n`); 4549 */ 4550 static uc_value_t * 4551 uc_socket_inst_listen(uc_vm_t *vm, size_t nargs) 4552 { 4553 uc_value_t *backlog; 4554 int ret, sockfd; 4555 4556 args_get(vm, nargs, &sockfd, 4557 "backlog", UC_INTEGER, true, &backlog); 4558 4559 ret = listen(sockfd, backlog ? ucv_to_unsigned(backlog) : 128); 4560 4561 if (ret == -1) 4562 err_return(errno, "listen()"); 4563 4564 ok_return(ucv_boolean_new(true)); 4565 } 4566 4567 /** 4568 * Accept a connection on a socket. 4569 * 4570 * This function accepts a connection on the socket. It extracts the first 4571 * connection request on the queue of pending connections, creates a new 4572 * connected socket, and returns a new socket handle referring to that socket. 4573 * The newly created socket is not in listening state and has no backlog. 4574 * 4575 * When a optional `address` dictionary is provided, it is populated with the 4576 * remote address details of the peer socket. 4577 * 4578 * The optional `flags` parameter is a bitwise-or-ed number of flags to modify 4579 * the behavior of accepted peer socket. Possible values are: 4580 * - `SOCK_CLOEXEC`: Enable close-on-exec semantics for the new socket. 4581 * - `SOCK_NONBLOCK`: Enable nonblocking mode for the new socket. 4582 * 4583 * Returns a socket handle representing the newly created peer socket of the 4584 * accepted connection. 4585 * 4586 * Returns `null` if an error occurred. 4587 * 4588 * @function module:socket.socket#accept 4589 * 4590 * @param {object} [address] 4591 * An optional dictionary to receive the address details of the peer socket. 4592 * See {@link module:socket.socket.SocketAddress|SocketAddress} for details. 4593 * 4594 * @param {number} [flags] 4595 * Optional flags to modify the behavior of the peer socket. 4596 * 4597 * @returns {?module:socket.socket} 4598 * 4599 * @example 4600 * const sock = socket.create(…); 4601 * sock.bind(…); 4602 * sock.listen(); 4603 * 4604 * const peerAddress = {}; 4605 * const newSocket = sock.accept(peerAddress, socket.SOCK_CLOEXEC); 4606 * if (newSocket) 4607 * print(`Accepted connection from: ${peerAddress}\n`); 4608 * else 4609 * print(`Failed to accept connection: ${sock.error()}\n`); 4610 */ 4611 static uc_value_t * 4612 uc_socket_inst_accept(uc_vm_t *vm, size_t nargs) 4613 { 4614 struct sockaddr_storage ss = { 0 }; 4615 int peerfd, sockfd, sockflags; 4616 uc_value_t *addrobj, *flags; 4617 socklen_t slen; 4618 4619 args_get(vm, nargs, &sockfd, 4620 "address", UC_OBJECT, true, &addrobj, 4621 "flags", UC_INTEGER, true, &flags); 4622 4623 slen = sizeof(ss); 4624 sockflags = flags ? ucv_to_integer(flags) : 0; 4625 4626 #ifdef __APPLE__ 4627 peerfd = accept(sockfd, (struct sockaddr *)&ss, &slen); 4628 4629 if (peerfd == -1) 4630 err_return(errno, "accept()"); 4631 4632 if (sockflags & SOCK_CLOEXEC) { 4633 if (fcntl(peerfd, F_SETFD, FD_CLOEXEC) == -1) { 4634 close(peerfd); 4635 err_return(errno, "fcntl(F_SETFD)"); 4636 } 4637 } 4638 4639 if (sockflags & SOCK_NONBLOCK) { 4640 sockflags = fcntl(peerfd, F_GETFL); 4641 4642 if (sockflags == -1) { 4643 close(peerfd); 4644 err_return(errno, "fcntl(F_GETFL)"); 4645 } 4646 4647 if (fcntl(peerfd, F_SETFL, sockflags | O_NONBLOCK) == -1) { 4648 close(peerfd); 4649 err_return(errno, "fcntl(F_SETFL)"); 4650 } 4651 } 4652 #else 4653 peerfd = accept4(sockfd, (struct sockaddr *)&ss, &slen, sockflags); 4654 4655 if (peerfd == -1) 4656 err_return(errno, "accept4()"); 4657 #endif 4658 4659 if (addrobj) 4660 sockaddr_to_uv(&ss, addrobj); 4661 4662 ok_return(ucv_socket_new(vm, peerfd)); 4663 } 4664 4665 /** 4666 * Shutdown part of a full-duplex connection. 4667 * 4668 * This function shuts down part of the full-duplex connection associated with 4669 * the socket handle. The `how` parameter specifies which half of the connection 4670 * to shut down. It can take one of the following constant values: 4671 * 4672 * - `SHUT_RD`: Disables further receive operations. 4673 * - `SHUT_WR`: Disables further send operations. 4674 * - `SHUT_RDWR`: Disables further send and receive operations. 4675 * 4676 * Returns `true` if the shutdown operation is successful. 4677 * Returns `null` if an error occurred. 4678 * 4679 * @function module:socket.socket#shutdown 4680 * 4681 * @param {number} how 4682 * Specifies which half of the connection to shut down. 4683 * It can be one of the following constant values: `SHUT_RD`, `SHUT_WR`, 4684 * or `SHUT_RDWR`. 4685 * 4686 * @returns {?boolean} 4687 * 4688 * @example 4689 * const sock = socket.create(…); 4690 * sock.connect(…); 4691 * // Perform data exchange… 4692 * 4693 * const success = sock.shutdown(socket.SHUT_WR); 4694 * if (success) 4695 * print(`Send operations on socket shut down successfully.\n`); 4696 * else 4697 * print(`Failed to shut down send operations: ${sock.error()}\n`); 4698 */ 4699 static uc_value_t * 4700 uc_socket_inst_shutdown(uc_vm_t *vm, size_t nargs) 4701 { 4702 uc_value_t *how; 4703 int sockfd, ret; 4704 4705 args_get(vm, nargs, &sockfd, 4706 "how", UC_INTEGER, true, &how); 4707 4708 ret = shutdown(sockfd, ucv_int64_get(how)); 4709 4710 if (ret == -1) 4711 err_return(errno, "shutdown()"); 4712 4713 ok_return(ucv_boolean_new(true)); 4714 } 4715 4716 /** 4717 * Represents a credentials information object returned by 4718 * {@link module:socket.socket#peercred|`peercred()`}. 4719 * 4720 * @typedef {Object} module:socket.socket.PeerCredentials 4721 * @property {number} uid 4722 * The effective user ID the remote socket endpoint. 4723 * 4724 * @property {number} gid 4725 * The effective group ID the remote socket endpoint. 4726 * 4727 * @property {number} pid 4728 * The ID of the process the remote socket endpoint belongs to. 4729 */ 4730 4731 /** 4732 * Retrieves the peer credentials. 4733 * 4734 * This function retrieves the remote uid, gid and pid of a connected UNIX 4735 * domain socket. 4736 * 4737 * Returns the remote credentials if the operation is successful. 4738 * Returns `null` on error. 4739 * 4740 * @function module:socket.socket#peercred 4741 * 4742 * @returns {?module:socket.socket.PeerCredentials} 4743 * 4744 * @example 4745 * const sock = socket.create(socket.AF_UNIX, …); 4746 * sock.connect(…); 4747 * 4748 * const peerCredentials = sock.peercred(); 4749 * if (peerCredentials) 4750 * print(`Peer credentials: ${peerCredentials}\n`); 4751 * else 4752 * print(`Failed to retrieve peer credentials: ${sock.error()}\n`); 4753 */ 4754 static uc_value_t * 4755 uc_socket_inst_peercred(uc_vm_t *vm, size_t nargs) 4756 { 4757 uc_value_t *rv = NULL; 4758 socklen_t optlen; 4759 int ret, sockfd; 4760 4761 args_get(vm, nargs, &sockfd); 4762 4763 #if defined(__linux__) 4764 struct ucred cred; 4765 4766 optlen = sizeof(cred); 4767 ret = getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &optlen); 4768 4769 if (ret == -1) 4770 err_return(errno, "getsockopt()"); 4771 4772 if (optlen != sizeof(cred)) 4773 err_return(EINVAL, "Invalid credentials received"); 4774 4775 rv = ucv_object_new(vm); 4776 4777 ucv_object_add(rv, "uid", ucv_uint64_new(cred.uid)); 4778 ucv_object_add(rv, "gid", ucv_uint64_new(cred.gid)); 4779 ucv_object_add(rv, "pid", ucv_int64_new(cred.pid)); 4780 #elif defined(__APPLE__) 4781 struct xucred cred; 4782 pid_t pid; 4783 4784 optlen = sizeof(cred); 4785 ret = getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERCRED, &cred, &optlen); 4786 4787 if (ret == -1) 4788 err_return(errno, "getsockopt(LOCAL_PEERCRED)"); 4789 4790 if (optlen != sizeof(cred) || cred.cr_version != XUCRED_VERSION) 4791 err_return(EINVAL, "Invalid credentials received"); 4792 4793 rv = ucv_object_new(vm); 4794 4795 ucv_object_add(rv, "uid", ucv_uint64_new(cred.cr_uid)); 4796 ucv_object_add(rv, "gid", ucv_uint64_new(cred.cr_gid)); 4797 4798 optlen = sizeof(pid); 4799 ret = getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERPID, &pid, &optlen); 4800 4801 if (ret == -1) { 4802 ucv_put(rv); 4803 err_return(errno, "getsockopt(LOCAL_PEERPID)"); 4804 } 4805 4806 ucv_object_add(rv, "pid", ucv_int64_new(pid)); 4807 #else 4808 err_return(ENOSYS, "Operation not supported on this system"); 4809 #endif 4810 4811 ok_return(rv); 4812 } 4813 4814 /** 4815 * Retrieves the remote address. 4816 * 4817 * This function retrieves the remote address of a connected socket. 4818 * 4819 * Returns the remote address if the operation is successful. 4820 * Returns `null` on error. 4821 * 4822 * @function module:socket.socket#peername 4823 * 4824 * @returns {?module:socket.socket.SocketAddress} 4825 * 4826 * @see {@link module:socket.socket#sockname|sockname()} 4827 * 4828 * @example 4829 * const sock = socket.create(…); 4830 * sock.connect(…); 4831 * 4832 * const peerAddress = sock.peername(); 4833 * if (peerAddress) 4834 * print(`Connected to ${peerAddress}\n`); 4835 * else 4836 * print(`Failed to retrieve peer address: ${sock.error()}\n`); 4837 */ 4838 static uc_value_t * 4839 uc_socket_inst_peername(uc_vm_t *vm, size_t nargs) 4840 { 4841 struct sockaddr_storage ss = { 0 }; 4842 uc_value_t *addr; 4843 socklen_t sslen; 4844 int sockfd, ret; 4845 4846 args_get(vm, nargs, &sockfd); 4847 4848 sslen = sizeof(ss); 4849 ret = getpeername(sockfd, (struct sockaddr *)&ss, &sslen); 4850 4851 if (ret == -1) 4852 err_return(errno, "getpeername()"); 4853 4854 addr = ucv_object_new(vm); 4855 sockaddr_to_uv(&ss, addr); 4856 4857 ok_return(addr); 4858 } 4859 4860 /** 4861 * Retrieves the local address. 4862 * 4863 * This function retrieves the local address of a bound or connected socket. 4864 * 4865 * Returns the local address if the operation is successful. 4866 * Returns `null` on error. 4867 * 4868 * @function module:socket.socket#sockname 4869 * 4870 * @returns {?module:socket.socket.SocketAddress} 4871 * 4872 * @see {@link module:socket.socket#peername|peername()} 4873 * 4874 * @example 4875 * const sock = socket.create(…); 4876 * sock.connect(…); 4877 * 4878 * const myAddress = sock.sockname(); 4879 * if (myAddress) 4880 * print(`My source IP address is ${myAddress}\n`); 4881 * else 4882 * print(`Failed to retrieve peer address: ${sock.error()}\n`); 4883 */ 4884 static uc_value_t * 4885 uc_socket_inst_sockname(uc_vm_t *vm, size_t nargs) 4886 { 4887 struct sockaddr_storage ss = { 0 }; 4888 uc_value_t *addr; 4889 socklen_t sslen; 4890 int sockfd, ret; 4891 4892 args_get(vm, nargs, &sockfd); 4893 4894 sslen = sizeof(ss); 4895 ret = getsockname(sockfd, (struct sockaddr *)&ss, &sslen); 4896 4897 if (ret == -1) 4898 err_return(errno, "getsockname()"); 4899 4900 addr = ucv_object_new(vm); 4901 sockaddr_to_uv(&ss, addr); 4902 4903 ok_return(addr); 4904 } 4905 4906 /** 4907 * Closes the socket. 4908 * 4909 * This function closes the socket, releasing its resources and terminating its 4910 * associated connections. 4911 * 4912 * Returns `true` if the socket was successfully closed. 4913 * Returns `null` on error. 4914 * 4915 * @function module:socket.socket#close 4916 * 4917 * @returns {?boolean} 4918 * 4919 * @example 4920 * const sock = socket.create(…); 4921 * sock.connect(…); 4922 * // Perform operations with the socket… 4923 * sock.close(); 4924 */ 4925 static uc_value_t * 4926 uc_socket_inst_close(uc_vm_t *vm, size_t nargs) 4927 { 4928 int *sockfd = uc_fn_this("socket"); 4929 4930 if (!sockfd || *sockfd == -1) 4931 err_return(EBADF, "Invalid socket context"); 4932 4933 if (!xclose(sockfd)) 4934 err_return(errno, "close()"); 4935 4936 ok_return(ucv_boolean_new(true)); 4937 } 4938 4939 static void 4940 close_socket(void *ud) 4941 { 4942 int fd = (intptr_t)ud; 4943 4944 if (fd != -1) 4945 close(fd); 4946 } 4947 4948 static const uc_function_list_t socket_fns[] = { 4949 { "connect", uc_socket_inst_connect }, 4950 { "bind", uc_socket_inst_bind }, 4951 { "listen", uc_socket_inst_listen }, 4952 { "accept", uc_socket_inst_accept }, 4953 { "send", uc_socket_inst_send }, 4954 { "sendmsg", uc_socket_inst_sendmsg }, 4955 { "recv", uc_socket_inst_recv }, 4956 { "recvmsg", uc_socket_inst_recvmsg }, 4957 { "setopt", uc_socket_inst_setopt }, 4958 { "getopt", uc_socket_inst_getopt }, 4959 { "fileno", uc_socket_inst_fileno }, 4960 { "shutdown", uc_socket_inst_shutdown }, 4961 { "peercred", uc_socket_inst_peercred }, 4962 { "peername", uc_socket_inst_peername }, 4963 { "sockname", uc_socket_inst_sockname }, 4964 { "close", uc_socket_inst_close }, 4965 { "error", uc_socket_error }, 4966 }; 4967 4968 static const uc_function_list_t global_fns[] = { 4969 { "sockaddr", uc_socket_sockaddr }, 4970 { "create", uc_socket_create }, 4971 { "pair", uc_socket_pair }, 4972 { "open", uc_socket_open }, 4973 { "nameinfo", uc_socket_nameinfo }, 4974 { "addrinfo", uc_socket_addrinfo }, 4975 { "poll", uc_socket_poll }, 4976 { "connect", uc_socket_connect }, 4977 { "listen", uc_socket_listen }, 4978 { "error", uc_socket_error }, 4979 { "strerror", uc_socket_strerror }, 4980 }; 4981 4982 void uc_module_init(uc_vm_t *vm, uc_value_t *scope) 4983 { 4984 uc_function_list_register(scope, global_fns); 4985 4986 #define ADD_CONST(x) ucv_object_add(scope, #x, ucv_int64_new(x)) 4987 4988 /** 4989 * @typedef 4990 * @name Address Families 4991 * @description Constants representing address families and socket domains. 4992 * @property {number} AF_UNSPEC - Unspecified address family. 4993 * @property {number} AF_UNIX - UNIX domain sockets. 4994 * @property {number} AF_INET - IPv4 Internet protocols. 4995 * @property {number} AF_INET6 - IPv6 Internet protocols. 4996 * @property {number} AF_PACKET - Low-level packet interface. 4997 * @property {number} AF_CAN - Controller Area Network sockets. 4998 */ 4999 ADD_CONST(AF_UNSPEC); 5000 ADD_CONST(AF_UNIX); 5001 ADD_CONST(AF_INET); 5002 ADD_CONST(AF_INET6); 5003 #if defined(__linux__) 5004 ADD_CONST(AF_PACKET); 5005 ADD_CONST(AF_CAN); 5006 #endif 5007 5008 /** 5009 * @typedef 5010 * @name Socket Types 5011 * @description 5012 * The `SOCK_*` type and flag constants are used by 5013 * {@link module:socket#create|create()} to specify the type of socket to 5014 * open. The {@link module:socket.socket#accept|accept()} function 5015 * recognizes the `SOCK_NONBLOCK` and `SOCK_CLOEXEC` flags and applies them 5016 * to accepted peer sockets. 5017 * @property {number} SOCK_STREAM - Provides sequenced, reliable, two-way, connection-based byte streams. 5018 * @property {number} SOCK_DGRAM - Supports datagrams (connectionless, unreliable messages of a fixed maximum length). 5019 * @property {number} SOCK_RAW - Provides raw network protocol access. 5020 * @property {number} SOCK_PACKET - Obsolete and should not be used. 5021 * @property {number} SOCK_NONBLOCK - Enables non-blocking operation. 5022 * @property {number} SOCK_CLOEXEC - Sets the close-on-exec flag on the new file descriptor. 5023 */ 5024 ADD_CONST(SOCK_STREAM); 5025 ADD_CONST(SOCK_DGRAM); 5026 ADD_CONST(SOCK_RAW); 5027 ADD_CONST(SOCK_NONBLOCK); 5028 ADD_CONST(SOCK_CLOEXEC); 5029 #if defined(__linux__) 5030 ADD_CONST(SOCK_PACKET); 5031 #endif 5032 5033 /** 5034 * @typedef 5035 * @name Message Flags 5036 * @description 5037 * The `MSG_*` flag constants are commonly used in conjunction with the 5038 * {@link module:socket.socket#send|send()} and 5039 * {@link module:socket.socket#recv|recv()} functions. 5040 * @property {number} MSG_CONFIRM - Confirm path validity. 5041 * @property {number} MSG_DONTROUTE - Send without using routing tables. 5042 * @property {number} MSG_DONTWAIT - Enables non-blocking operation. 5043 * @property {number} MSG_EOR - End of record. 5044 * @property {number} MSG_MORE - Sender will send more. 5045 * @property {number} MSG_NOSIGNAL - Do not generate SIGPIPE. 5046 * @property {number} MSG_OOB - Process out-of-band data. 5047 * @property {number} MSG_FASTOPEN - Send data in TCP SYN. 5048 * @property {number} MSG_CMSG_CLOEXEC - Sets the close-on-exec flag on the received file descriptor. 5049 * @property {number} MSG_ERRQUEUE - Receive errors from ICMP. 5050 * @property {number} MSG_PEEK - Peeks at incoming messages. 5051 * @property {number} MSG_TRUNC - Report if datagram truncation occurred. 5052 * @property {number} MSG_WAITALL - Wait for full message. 5053 */ 5054 ADD_CONST(MSG_DONTROUTE); 5055 ADD_CONST(MSG_DONTWAIT); 5056 ADD_CONST(MSG_EOR); 5057 ADD_CONST(MSG_NOSIGNAL); 5058 ADD_CONST(MSG_OOB); 5059 ADD_CONST(MSG_PEEK); 5060 ADD_CONST(MSG_TRUNC); 5061 ADD_CONST(MSG_WAITALL); 5062 #if defined(__linux__) 5063 ADD_CONST(MSG_CONFIRM); 5064 ADD_CONST(MSG_MORE); 5065 ADD_CONST(MSG_FASTOPEN); 5066 ADD_CONST(MSG_CMSG_CLOEXEC); 5067 ADD_CONST(MSG_ERRQUEUE); 5068 #endif 5069 5070 /** 5071 * @typedef 5072 * @name IP Protocol Constants 5073 * @description 5074 * The `IPPROTO_IP` constant specifies the IP protocol number and may be 5075 * passed as third argument to {@link module:socket#create|create()} as well 5076 * as *level* argument value to {@link module:socket.socket#getopt|getopt()} 5077 * and {@link module:socket.socket#setopt|setopt()}. 5078 * 5079 * The `IP_*` constants are option names recognized by 5080 * {@link module:socket.socket#getopt|getopt()} 5081 * and {@link module:socket.socket#setopt|setopt()}, in conjunction with 5082 * the `IPPROTO_IP` socket level. 5083 * @property {number} IPPROTO_IP - Dummy protocol for IP. 5084 * @property {number} IP_ADD_MEMBERSHIP - Add an IP group membership. 5085 * @property {number} IP_ADD_SOURCE_MEMBERSHIP - Add an IP group/source membership. 5086 * @property {number} IP_BIND_ADDRESS_NO_PORT - Bind to the device only. 5087 * @property {number} IP_BLOCK_SOURCE - Block IP group/source. 5088 * @property {number} IP_DROP_MEMBERSHIP - Drop an IP group membership. 5089 * @property {number} IP_DROP_SOURCE_MEMBERSHIP - Drop an IP group/source membership. 5090 * @property {number} IP_FREEBIND - Allow binding to an IP address not assigned to a network interface. 5091 * @property {number} IP_HDRINCL - Header is included with data. 5092 * @property {number} IP_MSFILTER - Filter IP multicast source memberships. 5093 * @property {number} IP_MTU - Path MTU discovery. 5094 * @property {number} IP_MTU_DISCOVER - Control Path MTU discovery. 5095 * @property {number} IP_MULTICAST_ALL - Receive all multicast packets. 5096 * @property {number} IP_MULTICAST_IF - Set outgoing interface for multicast packets. 5097 * @property {number} IP_MULTICAST_LOOP - Control multicast packet looping. 5098 * @property {number} IP_MULTICAST_TTL - Set time-to-live for outgoing multicast packets. 5099 * @property {number} IP_NODEFRAG - Don't fragment IP packets. 5100 * @property {number} IP_OPTIONS - Set/get IP options. 5101 * @property {number} IP_PASSSEC - Pass security information. 5102 * @property {number} IP_PKTINFO - Receive packet information. 5103 * @property {number} IP_RECVERR - Receive all ICMP errors. 5104 * @property {number} IP_RECVOPTS - Receive all IP options. 5105 * @property {number} IP_RECVORIGDSTADDR - Receive original destination address of the socket. 5106 * @property {number} IP_RECVTOS - Receive IP TOS. 5107 * @property {number} IP_RECVTTL - Receive IP TTL. 5108 * @property {number} IP_RETOPTS - Set/get IP options. 5109 * @property {number} IP_ROUTER_ALERT - Receive ICMP msgs generated by router. 5110 * @property {number} IP_TOS - IP type of service and precedence. 5111 * @property {number} IP_TRANSPARENT - Transparent proxy support. 5112 * @property {number} IP_TTL - IP time-to-live. 5113 * @property {number} IP_UNBLOCK_SOURCE - Unblock IP group/source. 5114 */ 5115 ADD_CONST(IPPROTO_IP); 5116 ADD_CONST(IP_ADD_MEMBERSHIP); 5117 ADD_CONST(IP_ADD_SOURCE_MEMBERSHIP); 5118 ADD_CONST(IP_BLOCK_SOURCE); 5119 ADD_CONST(IP_DROP_MEMBERSHIP); 5120 ADD_CONST(IP_DROP_SOURCE_MEMBERSHIP); 5121 ADD_CONST(IP_HDRINCL); 5122 ADD_CONST(IP_MSFILTER); 5123 ADD_CONST(IP_MULTICAST_IF); 5124 ADD_CONST(IP_MULTICAST_LOOP); 5125 ADD_CONST(IP_MULTICAST_TTL); 5126 ADD_CONST(IP_OPTIONS); 5127 ADD_CONST(IP_PKTINFO); 5128 ADD_CONST(IP_RECVOPTS); 5129 ADD_CONST(IP_RECVTOS); 5130 ADD_CONST(IP_RECVTTL); 5131 ADD_CONST(IP_RETOPTS); 5132 ADD_CONST(IP_TOS); 5133 ADD_CONST(IP_TTL); 5134 ADD_CONST(IP_UNBLOCK_SOURCE); 5135 #if defined(__linux__) 5136 ADD_CONST(IP_BIND_ADDRESS_NO_PORT); 5137 ADD_CONST(IP_FREEBIND); 5138 ADD_CONST(IP_MTU); 5139 ADD_CONST(IP_MTU_DISCOVER); 5140 ADD_CONST(IP_MULTICAST_ALL); 5141 ADD_CONST(IP_NODEFRAG); 5142 ADD_CONST(IP_PASSSEC); 5143 ADD_CONST(IP_RECVERR); 5144 ADD_CONST(IP_RECVORIGDSTADDR); 5145 ADD_CONST(IP_ROUTER_ALERT); 5146 ADD_CONST(IP_TRANSPARENT); 5147 #endif 5148 5149 /** 5150 * @typedef {Object} IPv6 Protocol Constants 5151 * @description 5152 * The `IPPROTO_IPV6` constant specifies the IPv6 protocol number and may be 5153 * passed as third argument to {@link module:socket#create|create()} as well 5154 * as *level* argument value to {@link module:socket.socket#getopt|getopt()} 5155 * and {@link module:socket.socket#setopt|setopt()}. 5156 * 5157 * The `IPV6_*` constants are option names recognized by 5158 * {@link module:socket.socket#getopt|getopt()} 5159 * and {@link module:socket.socket#setopt|setopt()}, in conjunction with 5160 * the `IPPROTO_IPV6` socket level. 5161 * @property {number} IPPROTO_IPV6 - The IPv6 protocol. 5162 * @property {number} IPV6_ADDRFORM - Turn an AF_INET6 socket into a socket of a different address family. Only AF_INET is supported. 5163 * @property {number} IPV6_ADDR_PREFERENCES - Specify preferences for address selection. 5164 * @property {number} IPV6_ADD_MEMBERSHIP - Add an IPv6 group membership. 5165 * @property {number} IPV6_AUTHHDR - Set delivery of the authentication header control message for incoming datagrams. 5166 * @property {number} IPV6_AUTOFLOWLABEL - Enable or disable automatic flow labels. 5167 * @property {number} IPV6_DONTFRAG - Control whether the socket allows IPv6 fragmentation. 5168 * @property {number} IPV6_DROP_MEMBERSHIP - Drop an IPv6 group membership. 5169 * @property {number} IPV6_DSTOPTS - Set delivery of the destination options control message for incoming datagrams. 5170 * @property {number} IPV6_FLOWINFO_SEND - Control whether flow information is sent. 5171 * @property {number} IPV6_FLOWINFO - Set delivery of the flow ID control message for incoming datagrams. 5172 * @property {number} IPV6_FLOWLABEL_MGR - Manage flow labels. 5173 * @property {number} IPV6_FREEBIND - Allow binding to an IP address not assigned to a network interface. 5174 * @property {number} IPV6_HOPLIMIT - Set delivery of the hop limit control message for incoming datagrams. 5175 * @property {number} IPV6_HOPOPTS - Set delivery of the hop options control message for incoming datagrams. 5176 * @property {number} IPV6_JOIN_ANYCAST - Join an anycast group. 5177 * @property {number} IPV6_LEAVE_ANYCAST - Leave an anycast group. 5178 * @property {number} IPV6_MINHOPCOUNT - Set the minimum hop count. 5179 * @property {number} IPV6_MTU - Retrieve or set the MTU to be used for the socket. 5180 * @property {number} IPV6_MTU_DISCOVER - Control path-MTU discovery on the socket. 5181 * @property {number} IPV6_MULTICAST_ALL - Control whether the socket receives all multicast packets. 5182 * @property {number} IPV6_MULTICAST_HOPS - Set the multicast hop limit for the socket. 5183 * @property {number} IPV6_MULTICAST_IF - Set the device for outgoing multicast packets on the socket. 5184 * @property {number} IPV6_MULTICAST_LOOP - Control whether the socket sees multicast packets that it has sent itself. 5185 * @property {number} IPV6_PKTINFO - Set delivery of the IPV6_PKTINFO control message on incoming datagrams. 5186 * @property {number} IPV6_RECVDSTOPTS - Control receiving of the destination options control message. 5187 * @property {number} IPV6_RECVERR - Control receiving of asynchronous error options. 5188 * @property {number} IPV6_RECVFRAGSIZE - Control receiving of fragment size. 5189 * @property {number} IPV6_RECVHOPLIMIT - Control receiving of hop limit. 5190 * @property {number} IPV6_RECVHOPOPTS - Control receiving of hop options. 5191 * @property {number} IPV6_RECVORIGDSTADDR - Control receiving of the original destination address. 5192 * @property {number} IPV6_RECVPATHMTU - Control receiving of path MTU. 5193 * @property {number} IPV6_RECVPKTINFO - Control receiving of packet information. 5194 * @property {number} IPV6_RECVRTHDR - Control receiving of routing header. 5195 * @property {number} IPV6_RECVTCLASS - Control receiving of traffic class. 5196 * @property {number} IPV6_ROUTER_ALERT_ISOLATE - Control isolation of router alert messages. 5197 * @property {number} IPV6_ROUTER_ALERT - Pass forwarded packets containing a router alert hop-by-hop option to this socket. 5198 * @property {number} IPV6_RTHDR - Set delivery of the routing header control message for incoming datagrams. 5199 * @property {number} IPV6_RTHDRDSTOPTS - Set delivery of the routing header destination options control message. 5200 * @property {number} IPV6_TCLASS - Set the traffic class. 5201 * @property {number} IPV6_TRANSPARENT - Enable transparent proxy support. 5202 * @property {number} IPV6_UNICAST_HOPS - Set the unicast hop limit for the socket. 5203 * @property {number} IPV6_UNICAST_IF - Set the interface for outgoing unicast packets. 5204 * @property {number} IPV6_V6ONLY - Restrict the socket to sending and receiving IPv6 packets only. 5205 */ 5206 ADD_CONST(IPPROTO_IPV6); 5207 ADD_CONST(IPV6_FLOWINFO_SEND); 5208 ADD_CONST(IPV6_FLOWINFO); 5209 ADD_CONST(IPV6_FLOWLABEL_MGR); 5210 ADD_CONST(IPV6_MULTICAST_HOPS); 5211 ADD_CONST(IPV6_MULTICAST_IF); 5212 ADD_CONST(IPV6_MULTICAST_LOOP); 5213 ADD_CONST(IPV6_RECVTCLASS); 5214 ADD_CONST(IPV6_TCLASS); 5215 ADD_CONST(IPV6_UNICAST_HOPS); 5216 ADD_CONST(IPV6_V6ONLY); 5217 #if defined(__linux__) 5218 ADD_CONST(IPV6_ADD_MEMBERSHIP); 5219 ADD_CONST(IPV6_ADDR_PREFERENCES); 5220 ADD_CONST(IPV6_ADDRFORM); 5221 ADD_CONST(IPV6_AUTHHDR); 5222 ADD_CONST(IPV6_AUTOFLOWLABEL); 5223 ADD_CONST(IPV6_DONTFRAG); 5224 ADD_CONST(IPV6_DROP_MEMBERSHIP); 5225 ADD_CONST(IPV6_DSTOPTS); 5226 ADD_CONST(IPV6_FREEBIND); 5227 ADD_CONST(IPV6_HOPLIMIT); 5228 ADD_CONST(IPV6_HOPOPTS); 5229 ADD_CONST(IPV6_JOIN_ANYCAST); 5230 ADD_CONST(IPV6_LEAVE_ANYCAST); 5231 ADD_CONST(IPV6_MINHOPCOUNT); 5232 ADD_CONST(IPV6_MTU_DISCOVER); 5233 ADD_CONST(IPV6_MTU); 5234 ADD_CONST(IPV6_MULTICAST_ALL); 5235 ADD_CONST(IPV6_PKTINFO); 5236 ADD_CONST(IPV6_RECVDSTOPTS); 5237 ADD_CONST(IPV6_RECVERR); 5238 ADD_CONST(IPV6_RECVFRAGSIZE); 5239 ADD_CONST(IPV6_RECVHOPLIMIT); 5240 ADD_CONST(IPV6_RECVHOPOPTS); 5241 ADD_CONST(IPV6_RECVORIGDSTADDR); 5242 ADD_CONST(IPV6_RECVPATHMTU); 5243 ADD_CONST(IPV6_RECVPKTINFO); 5244 ADD_CONST(IPV6_RECVRTHDR); 5245 ADD_CONST(IPV6_ROUTER_ALERT_ISOLATE); 5246 ADD_CONST(IPV6_ROUTER_ALERT); 5247 ADD_CONST(IPV6_RTHDR); 5248 ADD_CONST(IPV6_RTHDRDSTOPTS); 5249 ADD_CONST(IPV6_TRANSPARENT); 5250 ADD_CONST(IPV6_UNICAST_IF); 5251 #endif 5252 5253 /** 5254 * @typedef 5255 * @name Socket Option Constants 5256 * @description 5257 * The `SOL_SOCKET` constant is passed as *level* argument to the 5258 * {@link module:socket.socket#getopt|getopt()} and 5259 * {@link module:socket.socket#setopt|setopt()} functions in order to set 5260 * or retrieve generic socket option values. 5261 * 5262 * The `SO_*` constants are passed as *option* argument in conjunction with 5263 * the `SOL_SOCKET` level to specify the specific option to get or set on 5264 * the socket. 5265 * @property {number} SOL_SOCKET - Socket options at the socket API level. 5266 * @property {number} SO_ACCEPTCONN - Reports whether socket listening is enabled. 5267 * @property {number} SO_ATTACH_BPF - Attach BPF program to socket. 5268 * @property {number} SO_ATTACH_FILTER - Attach a socket filter. 5269 * @property {number} SO_ATTACH_REUSEPORT_CBPF - Attach BPF program for cgroup and skb program reuseport hook. 5270 * @property {number} SO_ATTACH_REUSEPORT_EBPF - Attach eBPF program for cgroup and skb program reuseport hook. 5271 * @property {number} SO_BINDTODEVICE - Bind socket to a specific interface. 5272 * @property {number} SO_BROADCAST - Allow transmission of broadcast messages. 5273 * @property {number} SO_BUSY_POLL - Enable busy polling. 5274 * @property {number} SO_DEBUG - Enable socket debugging. 5275 * @property {number} SO_DETACH_BPF - Detach BPF program from socket. 5276 * @property {number} SO_DETACH_FILTER - Detach a socket filter. 5277 * @property {number} SO_DOMAIN - Retrieves the domain of the socket. 5278 * @property {number} SO_DONTROUTE - Send packets directly without routing. 5279 * @property {number} SO_ERROR - Retrieves and clears the error status for the socket. 5280 * @property {number} SO_INCOMING_CPU - Retrieves the CPU number on which the last packet was received. 5281 * @property {number} SO_INCOMING_NAPI_ID - Retrieves the NAPI ID of the device. 5282 * @property {number} SO_KEEPALIVE - Enable keep-alive packets. 5283 * @property {number} SO_LINGER - Set linger on close. 5284 * @property {number} SO_LOCK_FILTER - Set or get the socket filter lock state. 5285 * @property {number} SO_MARK - Set the mark for packets sent through the socket. 5286 * @property {number} SO_OOBINLINE - Enables out-of-band data to be received in the normal data stream. 5287 * @property {number} SO_PASSCRED - Enable the receiving of SCM_CREDENTIALS control messages. 5288 * @property {number} SO_PASSSEC - Enable the receiving of security context. 5289 * @property {number} SO_PEEK_OFF - Returns the number of bytes in the receive buffer without removing them. 5290 * @property {number} SO_PEERCRED - Retrieves the credentials of the foreign peer. 5291 * @property {number} SO_PEERSEC - Retrieves the security context of the foreign peer. 5292 * @property {number} SO_PRIORITY - Set the protocol-defined priority for all packets. 5293 * @property {number} SO_PROTOCOL - Retrieves the protocol number. 5294 * @property {number} SO_RCVBUF - Set the receive buffer size. 5295 * @property {number} SO_RCVBUFFORCE - Set the receive buffer size forcefully. 5296 * @property {number} SO_RCVLOWAT - Set the minimum number of bytes to process for input operations. 5297 * @property {number} SO_RCVTIMEO - Set the timeout for receiving data. 5298 * @property {number} SO_REUSEADDR - Allow the socket to be bound to an address that is already in use. 5299 * @property {number} SO_REUSEPORT - Enable duplicate address and port bindings. 5300 * @property {number} SO_RXQ_OVFL - Reports if the receive queue has overflown. 5301 * @property {number} SO_SNDBUF - Set the send buffer size. 5302 * @property {number} SO_SNDBUFFORCE - Set the send buffer size forcefully. 5303 * @property {number} SO_SNDLOWAT - Set the minimum number of bytes to process for output operations. 5304 * @property {number} SO_SNDTIMEO - Set the timeout for sending data. 5305 * @property {number} SO_TIMESTAMP - Enable receiving of timestamps. 5306 * @property {number} SO_TIMESTAMPNS - Enable receiving of nanosecond timestamps. 5307 * @property {number} SO_TYPE - Retrieves the type of the socket (e.g., SOCK_STREAM). 5308 */ 5309 ADD_CONST(SOL_SOCKET); 5310 ADD_CONST(SO_ACCEPTCONN); 5311 ADD_CONST(SO_BROADCAST); 5312 ADD_CONST(SO_DEBUG); 5313 ADD_CONST(SO_DONTROUTE); 5314 ADD_CONST(SO_ERROR); 5315 ADD_CONST(SO_KEEPALIVE); 5316 ADD_CONST(SO_LINGER); 5317 ADD_CONST(SO_OOBINLINE); 5318 ADD_CONST(SO_RCVBUF); 5319 ADD_CONST(SO_RCVLOWAT); 5320 ADD_CONST(SO_RCVTIMEO); 5321 ADD_CONST(SO_REUSEADDR); 5322 ADD_CONST(SO_REUSEPORT); 5323 ADD_CONST(SO_SNDBUF); 5324 ADD_CONST(SO_SNDLOWAT); 5325 ADD_CONST(SO_SNDTIMEO); 5326 ADD_CONST(SO_TIMESTAMP); 5327 ADD_CONST(SO_TYPE); 5328 #if defined(__linux__) 5329 ADD_CONST(SO_ATTACH_BPF); 5330 ADD_CONST(SO_ATTACH_FILTER); 5331 ADD_CONST(SO_ATTACH_REUSEPORT_CBPF); 5332 ADD_CONST(SO_ATTACH_REUSEPORT_EBPF); 5333 ADD_CONST(SO_BINDTODEVICE); 5334 ADD_CONST(SO_BUSY_POLL); 5335 ADD_CONST(SO_DETACH_BPF); 5336 ADD_CONST(SO_DETACH_FILTER); 5337 ADD_CONST(SO_DOMAIN); 5338 ADD_CONST(SO_INCOMING_CPU); 5339 ADD_CONST(SO_INCOMING_NAPI_ID); 5340 ADD_CONST(SO_LOCK_FILTER); 5341 ADD_CONST(SO_MARK); 5342 ADD_CONST(SO_PASSCRED); 5343 ADD_CONST(SO_PASSSEC); 5344 ADD_CONST(SO_PEEK_OFF); 5345 ADD_CONST(SO_PEERCRED); 5346 ADD_CONST(SO_PEERSEC); 5347 ADD_CONST(SO_PRIORITY); 5348 ADD_CONST(SO_PROTOCOL); 5349 ADD_CONST(SO_RCVBUFFORCE); 5350 ADD_CONST(SO_RXQ_OVFL); 5351 ADD_CONST(SO_SNDBUFFORCE); 5352 ADD_CONST(SO_TIMESTAMPNS); 5353 5354 ADD_CONST(SCM_CREDENTIALS); 5355 ADD_CONST(SCM_RIGHTS); 5356 #endif 5357 5358 /** 5359 * @typedef 5360 * @name TCP Protocol Constants 5361 * @description 5362 * The `IPPROTO_TCP` constant specifies the TCP protocol number and may be 5363 * passed as third argument to {@link module:socket#create|create()} as well 5364 * as *level* argument value to {@link module:socket.socket#getopt|getopt()} 5365 * and {@link module:socket.socket#setopt|setopt()}. 5366 * 5367 * The `TCP_*` constants are *option* argument values recognized by 5368 * {@link module:socket.socket#getopt|getopt()} 5369 * and {@link module:socket.socket#setopt|setopt()}, in conjunction with 5370 * the `IPPROTO_TCP` socket level. 5371 * @property {number} IPPROTO_TCP - TCP protocol. 5372 * @property {number} TCP_CONGESTION - Set the congestion control algorithm. 5373 * @property {number} TCP_CORK - Delay packet transmission until full-sized packets are available. 5374 * @property {number} TCP_DEFER_ACCEPT - Delay accepting incoming connections until data arrives. 5375 * @property {number} TCP_FASTOPEN - Enable TCP Fast Open. 5376 * @property {number} TCP_FASTOPEN_CONNECT - Perform TFO connect. 5377 * @property {number} TCP_INFO - Retrieve TCP statistics. 5378 * @property {number} TCP_KEEPCNT - Number of keepalive probes. 5379 * @property {number} TCP_KEEPIDLE - Time before keepalive probes begin. 5380 * @property {number} TCP_KEEPINTVL - Interval between keepalive probes. 5381 * @property {number} TCP_LINGER2 - Lifetime of orphaned FIN_WAIT2 state sockets. 5382 * @property {number} TCP_MAXSEG - Maximum segment size. 5383 * @property {number} TCP_NODELAY - Disable Nagle's algorithm. 5384 * @property {number} TCP_QUICKACK - Enable quick ACKs. 5385 * @property {number} TCP_SYNCNT - Number of SYN retransmits. 5386 * @property {number} TCP_USER_TIMEOUT - Set the user timeout. 5387 * @property {number} TCP_WINDOW_CLAMP - Set the maximum window. 5388 */ 5389 ADD_CONST(IPPROTO_TCP); 5390 ADD_CONST(TCP_FASTOPEN); 5391 ADD_CONST(TCP_KEEPCNT); 5392 ADD_CONST(TCP_KEEPINTVL); 5393 ADD_CONST(TCP_MAXSEG); 5394 ADD_CONST(TCP_NODELAY); 5395 #if defined(__linux__) 5396 ADD_CONST(TCP_CONGESTION); 5397 ADD_CONST(TCP_CORK); 5398 ADD_CONST(TCP_DEFER_ACCEPT); 5399 ADD_CONST(TCP_FASTOPEN_CONNECT); 5400 ADD_CONST(TCP_INFO); 5401 ADD_CONST(TCP_KEEPIDLE); 5402 ADD_CONST(TCP_LINGER2); 5403 ADD_CONST(TCP_QUICKACK); 5404 ADD_CONST(TCP_SYNCNT); 5405 ADD_CONST(TCP_USER_TIMEOUT); 5406 ADD_CONST(TCP_WINDOW_CLAMP); 5407 #endif 5408 5409 /** 5410 * @typedef 5411 * @name Packet Socket Constants 5412 * @description 5413 * The `SOL_PACKET` constant specifies the packet socket level and may be 5414 * passed as *level* argument value to 5415 * {@link module:socket.socket#getopt|getopt()} and 5416 * {@link module:socket.socket#setopt|setopt()}. 5417 * 5418 * Most `PACKET_*` constants are *option* argument values recognized by 5419 * {@link module:socket.socket#getopt|getopt()} 5420 * and {@link module:socket.socket#setopt|setopt()}, in conjunction with 5421 * the `SOL_PACKET` socket level. 5422 * 5423 * The constants `PACKET_MR_PROMISC`, `PACKET_MR_MULTICAST` and 5424 * `PACKET_MR_ALLMULTI` are used in conjunction with the 5425 * `PACKET_ADD_MEMBERSHIP` and `PACKET_DROP_MEMBERSHIP` options to specify 5426 * the packet socket receive mode. 5427 * 5428 * The constants `PACKET_HOST`, `PACKET_BROADCAST`, `PACKET_MULTICAST`, 5429 * `PACKET_OTHERHOST` and `PACKET_OUTGOING` may be used as *packet_type* 5430 * value in {@link module:socket.socket.SocketAddress|socket address} 5431 * structures. 5432 * @property {number} SOL_PACKET - Socket options at the packet API level. 5433 * @property {number} PACKET_ADD_MEMBERSHIP - Add a multicast group membership. 5434 * @property {number} PACKET_DROP_MEMBERSHIP - Drop a multicast group membership. 5435 * @property {number} PACKET_AUXDATA - Receive auxiliary data (packet info). 5436 * @property {number} PACKET_FANOUT - Configure packet fanout. 5437 * @property {number} PACKET_LOSS - Retrieve the current packet loss statistics. 5438 * @property {number} PACKET_RESERVE - Reserve space for packet headers. 5439 * @property {number} PACKET_RX_RING - Configure a receive ring buffer. 5440 * @property {number} PACKET_STATISTICS - Retrieve packet statistics. 5441 * @property {number} PACKET_TIMESTAMP - Retrieve packet timestamps. 5442 * @property {number} PACKET_TX_RING - Configure a transmit ring buffer. 5443 * @property {number} PACKET_VERSION - Set the packet protocol version. 5444 * @property {number} PACKET_QDISC_BYPASS - Bypass queuing discipline for outgoing packets. 5445 * 5446 * @property {number} PACKET_MR_PROMISC - Enable promiscuous mode. 5447 * @property {number} PACKET_MR_MULTICAST - Receive multicast packets. 5448 * @property {number} PACKET_MR_ALLMULTI - Receive all multicast packets. 5449 * 5450 * @property {number} PACKET_HOST - Receive packets destined for this host. 5451 * @property {number} PACKET_BROADCAST - Receive broadcast packets. 5452 * @property {number} PACKET_MULTICAST - Receive multicast packets. 5453 * @property {number} PACKET_OTHERHOST - Receive packets destined for other hosts. 5454 * @property {number} PACKET_OUTGOING - Transmit packets. 5455 */ 5456 #if defined(__linux__) 5457 ADD_CONST(SOL_PACKET); 5458 ADD_CONST(PACKET_ADD_MEMBERSHIP); 5459 ADD_CONST(PACKET_DROP_MEMBERSHIP); 5460 ADD_CONST(PACKET_AUXDATA); 5461 ADD_CONST(PACKET_FANOUT); 5462 ADD_CONST(PACKET_LOSS); 5463 ADD_CONST(PACKET_RESERVE); 5464 ADD_CONST(PACKET_RX_RING); 5465 ADD_CONST(PACKET_STATISTICS); 5466 ADD_CONST(PACKET_TIMESTAMP); 5467 ADD_CONST(PACKET_TX_RING); 5468 ADD_CONST(PACKET_VERSION); 5469 ADD_CONST(PACKET_QDISC_BYPASS); 5470 5471 ADD_CONST(PACKET_MR_PROMISC); 5472 ADD_CONST(PACKET_MR_MULTICAST); 5473 ADD_CONST(PACKET_MR_ALLMULTI); 5474 5475 ADD_CONST(PACKET_HOST); 5476 ADD_CONST(PACKET_BROADCAST); 5477 ADD_CONST(PACKET_MULTICAST); 5478 ADD_CONST(PACKET_OTHERHOST); 5479 ADD_CONST(PACKET_OUTGOING); 5480 #endif 5481 5482 /** 5483 * @typedef 5484 * @name CAN Protocol Constants 5485 * @description 5486 * The `CAN_RAW` and `CAN_BCM` constants specify SocketCAN protocol numbers 5487 * and may be passed as third argument to 5488 * {@link module:socket#create|create()} for `AF_CAN` sockets. 5489 * 5490 * The `SOL_CAN_RAW` constant specifies the raw CAN socket level and the 5491 * `CAN_RAW_*` constants are option names recognized by 5492 * {@link module:socket.socket#getopt|getopt()} and 5493 * {@link module:socket.socket#setopt|setopt()}, in conjunction with the 5494 * `SOL_CAN_RAW` socket level. 5495 * 5496 * The remaining constants describe the layout of the fixed size CAN frames 5497 * exchanged over raw CAN sockets: bit flags within the 32 bit CAN ID, ID 5498 * masks, frame sizes and payload limits as well as the flag bits used by 5499 * CAN FD frames. 5500 * @property {number} CAN_RAW - Raw CAN protocol. 5501 * @property {number} CAN_BCM - Broadcast manager CAN protocol. 5502 * @property {number} SOL_CAN_RAW - Raw CAN socket option level. 5503 * @property {number} CAN_RAW_FILTER - Set receive filter list, a packed array of 32 bit id/mask pairs. 5504 * @property {number} CAN_RAW_ERR_FILTER - Set error frame filter mask. 5505 * @property {number} CAN_RAW_LOOPBACK - Control local loopback of sent frames. 5506 * @property {number} CAN_RAW_RECV_OWN_MSGS - Control reception of own sent frames. 5507 * @property {number} CAN_RAW_FD_FRAMES - Enable CAN FD frame support. 5508 * @property {number} CAN_RAW_JOIN_FILTERS - All filters must match instead of any. 5509 * @property {number} CAN_RAW_XL_FRAMES - Enable CAN XL frame support. 5510 * @property {number} CAN_EFF_FLAG - Extended (29 bit) frame format flag within the CAN ID. 5511 * @property {number} CAN_RTR_FLAG - Remote transmission request flag within the CAN ID. 5512 * @property {number} CAN_ERR_FLAG - Error message frame flag within the CAN ID. 5513 * @property {number} CAN_SFF_MASK - Standard (11 bit) frame format ID mask. 5514 * @property {number} CAN_EFF_MASK - Extended (29 bit) frame format ID mask. 5515 * @property {number} CAN_ERR_MASK - Error frame class mask. 5516 * @property {number} CAN_MTU - Size of a classic CAN frame. 5517 * @property {number} CANFD_MTU - Size of a CAN FD frame. 5518 * @property {number} CANFD_BRS - CAN FD bit rate switch flag. 5519 * @property {number} CANFD_ESI - CAN FD error state indicator flag. 5520 * @property {number} CAN_MAX_DLEN - Maximum classic CAN payload length. 5521 * @property {number} CANFD_MAX_DLEN - Maximum CAN FD payload length. 5522 */ 5523 #if defined(__linux__) 5524 ADD_CONST(CAN_RAW); 5525 ADD_CONST(CAN_BCM); 5526 ADD_CONST(SOL_CAN_RAW); 5527 ADD_CONST(CAN_RAW_FILTER); 5528 ADD_CONST(CAN_RAW_ERR_FILTER); 5529 ADD_CONST(CAN_RAW_LOOPBACK); 5530 ADD_CONST(CAN_RAW_RECV_OWN_MSGS); 5531 ADD_CONST(CAN_RAW_FD_FRAMES); 5532 ADD_CONST(CAN_RAW_JOIN_FILTERS); 5533 # ifdef CAN_RAW_XL_FRAMES 5534 ADD_CONST(CAN_RAW_XL_FRAMES); 5535 # endif 5536 5537 ADD_CONST(CAN_EFF_FLAG); 5538 ADD_CONST(CAN_RTR_FLAG); 5539 ADD_CONST(CAN_ERR_FLAG); 5540 ADD_CONST(CAN_SFF_MASK); 5541 ADD_CONST(CAN_EFF_MASK); 5542 ADD_CONST(CAN_ERR_MASK); 5543 5544 ADD_CONST(CAN_MTU); 5545 ADD_CONST(CANFD_MTU); 5546 ADD_CONST(CANFD_BRS); 5547 ADD_CONST(CANFD_ESI); 5548 ADD_CONST(CAN_MAX_DLEN); 5549 ADD_CONST(CANFD_MAX_DLEN); 5550 #endif 5551 5552 /** 5553 * @typedef 5554 * @name UDP Protocol Constants 5555 * @description 5556 * The `IPPROTO_UDP` constant specifies the UDP protocol number and may be 5557 * passed as third argument to {@link module:socket#create|create()} as well 5558 * as *level* argument value to {@link module:socket.socket#getopt|getopt()} 5559 * and {@link module:socket.socket#setopt|setopt()}. 5560 * 5561 * The `UDP_*` constants are *option* argument values recognized by 5562 * {@link module:socket.socket#getopt|getopt()} 5563 * and {@link module:socket.socket#setopt|setopt()}, in conjunction with 5564 * the `IPPROTO_UDP` socket level. 5565 * @property {number} IPPROTO_UDP - UDP protocol. 5566 * @property {number} UDP_CORK - Cork data until flush. 5567 */ 5568 ADD_CONST(IPPROTO_UDP); 5569 #if defined(__linux__) 5570 ADD_CONST(UDP_CORK); 5571 #endif 5572 5573 /** 5574 * @typedef 5575 * @name Shutdown Constants 5576 * @description 5577 * The `SHUT_*` constants are passed as argument to the 5578 * {@link module:socket.socket#shutdown|shutdown()} function to specify 5579 * which direction of a full duplex connection to shut down. 5580 * @property {number} SHUT_RD - Disallow further receptions. 5581 * @property {number} SHUT_WR - Disallow further transmissions. 5582 * @property {number} SHUT_RDWR - Disallow further receptions and transmissions. 5583 */ 5584 ADD_CONST(SHUT_RD); 5585 ADD_CONST(SHUT_WR); 5586 ADD_CONST(SHUT_RDWR); 5587 5588 /** 5589 * @typedef 5590 * @name Address Info Flags 5591 * @description 5592 * The `AI_*` flags may be passed as bitwise OR-ed number in the *flags* 5593 * property of the *hints* dictionary argument of 5594 * {@link module:socket#addrinfo|addrinfo()}. 5595 * @property {number} AI_ADDRCONFIG - Address configuration flag. 5596 * @property {number} AI_ALL - Return IPv4 and IPv6 socket addresses. 5597 * @property {number} AI_CANONIDN - Canonicalize using the IDNA standard. 5598 * @property {number} AI_CANONNAME - Fill in the canonical name field. 5599 * @property {number} AI_IDN - Enable IDN encoding. 5600 * @property {number} AI_NUMERICHOST - Prevent hostname resolution. 5601 * @property {number} AI_NUMERICSERV - Prevent service name resolution. 5602 * @property {number} AI_PASSIVE - Use passive socket. 5603 * @property {number} AI_V4MAPPED - Map IPv6 addresses to IPv4-mapped format. 5604 */ 5605 ADD_CONST(AI_ADDRCONFIG); 5606 ADD_CONST(AI_ALL); 5607 ADD_CONST(AI_CANONIDN); 5608 ADD_CONST(AI_CANONNAME); 5609 ADD_CONST(AI_IDN); 5610 ADD_CONST(AI_NUMERICHOST); 5611 ADD_CONST(AI_NUMERICSERV); 5612 ADD_CONST(AI_PASSIVE); 5613 ADD_CONST(AI_V4MAPPED); 5614 5615 /** 5616 * @typedef 5617 * @name Name Info Constants 5618 * @description 5619 * The `NI_*` flags may be passed as bitwise OR-ed number via the *flags* 5620 * argument of {@link module:socket#nameinfo|nameinfo()}. 5621 * @property {number} NI_DGRAM - Datagram socket type. 5622 * @property {number} NI_IDN - Enable IDN encoding. 5623 * @property {number} NI_NAMEREQD - Hostname resolution required. 5624 * @property {number} NI_NOFQDN - Do not force fully qualified domain name. 5625 * @property {number} NI_NUMERICHOST - Return numeric form of the hostname. 5626 * @property {number} NI_NUMERICSERV - Return numeric form of the service name. 5627 */ 5628 ADD_CONST(NI_DGRAM); 5629 ADD_CONST(NI_IDN); 5630 ADD_CONST(NI_MAXHOST); 5631 ADD_CONST(NI_MAXSERV); 5632 ADD_CONST(NI_NAMEREQD); 5633 ADD_CONST(NI_NOFQDN); 5634 ADD_CONST(NI_NUMERICHOST); 5635 ADD_CONST(NI_NUMERICSERV); 5636 5637 /** 5638 * @typedef 5639 * @name Poll Event Constants 5640 * @description 5641 * The following constants represent event types for polling operations and 5642 * are set or returned as part of a 5643 * {@link module:socket.PollSpec|PollSpec} tuple by the 5644 * {@link module:socket#poll|poll()} function. When passed via an argument 5645 * PollSpec to `poll()`, they specify the I/O events to watch for on the 5646 * corresponding handle. When appearing in a PollSpec returned by `poll()`, 5647 * they specify the I/O events that occurred on a watched handle. 5648 * @property {number} POLLIN - Data available to read. 5649 * @property {number} POLLPRI - Priority data available to read. 5650 * @property {number} POLLOUT - Writable data available. 5651 * @property {number} POLLERR - Error condition. 5652 * @property {number} POLLHUP - Hang up. 5653 * @property {number} POLLNVAL - Invalid request. 5654 * @property {number} POLLRDHUP - Peer closed or shutdown writing. 5655 */ 5656 ADD_CONST(POLLIN); 5657 ADD_CONST(POLLPRI); 5658 ADD_CONST(POLLOUT); 5659 ADD_CONST(POLLERR); 5660 ADD_CONST(POLLHUP); 5661 ADD_CONST(POLLNVAL); 5662 #if defined(__linux__) 5663 ADD_CONST(POLLRDHUP); 5664 #endif 5665 5666 uc_type_declare(vm, "socket", socket_fns, close_socket); 5667 } 5668
This page was automatically generated by LXR 0.3.1. • OpenWrt