* @brief Create a TCP or UDP server socket * * To accept connections from clients via TCP or receive datagrams via UDP, you * need to create a server socket. This function creates such a socket and * `bind(2)`s it to the specified address. If `proto_osi4` is `LIBSOCKET_TCP`, * `listen(2)` is called, too. * * @param bind_addr Address to bind to. If you want to bind to every address use * "0
| 670 | */ |
| 671 | // Bind address Port TCP/UDP IPv4/6 |
| 672 | int create_inet_server_socket(const char *bind_addr, const char *bind_port, |
| 673 | char proto_osi4, char proto_osi3, int flags) { |
| 674 | int sfd, domain, type, retval; |
| 675 | struct addrinfo *result, *result_check, hints; |
| 676 | #ifdef VERBOSE |
| 677 | const char *errstr; |
| 678 | #endif |
| 679 | |
| 680 | // if ( flags != SOCK_NONBLOCK && flags != SOCK_CLOEXEC && flags != |
| 681 | // (SOCK_CLOEXEC|SOCK_NONBLOCK) && flags != 0 ) return -1; |
| 682 | |
| 683 | if (bind_addr == NULL || bind_port == NULL) return -1; |
| 684 | |
| 685 | switch (proto_osi4) { |
| 686 | case LIBSOCKET_TCP: |
| 687 | type = SOCK_STREAM; |
| 688 | break; |
| 689 | case LIBSOCKET_UDP: |
| 690 | type = SOCK_DGRAM; |
| 691 | break; |
| 692 | default: |
| 693 | return -1; |
| 694 | } |
| 695 | switch (proto_osi3) { |
| 696 | case LIBSOCKET_IPv4: |
| 697 | domain = AF_INET; |
| 698 | break; |
| 699 | case LIBSOCKET_IPv6: |
| 700 | domain = AF_INET6; |
| 701 | break; |
| 702 | case LIBSOCKET_BOTH: |
| 703 | domain = AF_UNSPEC; |
| 704 | break; |
| 705 | default: |
| 706 | return -1; |
| 707 | } |
| 708 | |
| 709 | memset(&hints, 0, sizeof(struct addrinfo)); |
| 710 | |
| 711 | hints.ai_socktype = type; |
| 712 | hints.ai_family = domain; |
| 713 | hints.ai_flags = AI_PASSIVE; |
| 714 | |
| 715 | if (0 != (retval = getaddrinfo(bind_addr, bind_port, &hints, &result))) { |
| 716 | #ifdef VERBOSE |
| 717 | errstr = gai_strerror(retval); |
| 718 | debug_write(errstr); |
| 719 | #endif |
| 720 | return -1; |
| 721 | } |
| 722 | |
| 723 | // As described in "The Linux Programming Interface", Michael Kerrisk 2010, |
| 724 | // chapter 59.11 (p. 1220ff) |
| 725 | for (result_check = result; result_check != NULL; |
| 726 | result_check = result_check->ai_next) // go through the linked list of |
| 727 | // struct addrinfo elements |
| 728 | { |
| 729 | sfd = socket(result_check->ai_family, result_check->ai_socktype | flags, |