static int uh_socket_bind( fd_set *serv_fds, int *max_fd, const char *host, const char *port, struct addrinfo *hints, int do_tls, struct config *conf ) { int sock = -1; int yes = 1; int status; int bound = 0; int tcp_ka_idl, tcp_ka_int, tcp_ka_cnt; struct listener *l = NULL; struct addrinfo *addrs = NULL, *p = NULL; if( (status = getaddrinfo(host, port, hints, &addrs)) != 0 ) { fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(status)); } /* try to bind a new socket to each found address */ for( p = addrs; p; p = p->ai_next ) { /* get the socket */ if( (sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1 ) { perror("socket()"); goto error; } /* "address already in use" */ if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) ) { perror("setsockopt()"); goto error; } /* TCP keep-alive */ if( conf->tcp_keepalive > 0 ) { tcp_ka_idl = 1; tcp_ka_cnt = 3; tcp_ka_int = conf->tcp_keepalive; if( setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) || setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &tcp_ka_idl, sizeof(tcp_ka_idl)) || setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &tcp_ka_int, sizeof(tcp_ka_int)) || setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &tcp_ka_cnt, sizeof(tcp_ka_cnt)) ) { fprintf(stderr, "Notice: Unable to enable TCP keep-alive: %s\n", strerror(errno)); } } /* required to get parallel v4 + v6 working */ if( p->ai_family == AF_INET6 ) { if( setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) == -1 ) { perror("setsockopt()"); goto error; } } /* bind */ if( bind(sock, p->ai_addr, p->ai_addrlen) == -1 ) { perror("bind()"); goto error; } /* listen */ if( listen(sock, UH_LIMIT_CLIENTS) == -1 ) { perror("listen()"); goto error; } /* add listener to global list */ if( ! (l = uh_listener_add(sock, conf)) ) { fprintf(stderr, "uh_listener_add(): Failed to allocate memory\n"); goto error; } #ifdef HAVE_TLS /* init TLS */ l->tls = do_tls ? conf->tls : NULL; #endif /* add socket to server fd set */ FD_SET(sock, serv_fds); fd_cloexec(sock); *max_fd = max(*max_fd, sock); bound++; continue; error: if( sock > 0 ) close(sock); } freeaddrinfo(addrs); return bound; }
static int uh_socket_bind( fd_set *serv_fds, int *max_fd, const char *host, const char *port, struct addrinfo *hints, int do_tls, struct config *conf ) { int sock = -1; int yes = 1; int status; int bound = 0; struct listener *l = NULL; struct addrinfo *addrs = NULL, *p = NULL; if( (status = getaddrinfo(host, port, hints, &addrs)) != 0 ) { fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(status)); } /* try to bind a new socket to each found address */ for( p = addrs; p; p = p->ai_next ) { /* get the socket */ if( (sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1 ) { perror("socket()"); goto error; } /* "address already in use" */ if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1 ) { perror("setsockopt()"); goto error; } /* required to get parallel v4 + v6 working */ if( p->ai_family == AF_INET6 ) { if( setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) == -1 ) { perror("setsockopt()"); goto error; } } /* bind */ if( bind(sock, p->ai_addr, p->ai_addrlen) == -1 ) { perror("bind()"); goto error; } /* listen */ if( listen(sock, UH_LIMIT_CLIENTS) == -1 ) { perror("listen()"); goto error; } /* add listener to global list */ if( ! (l = uh_listener_add(sock, conf)) ) { fprintf(stderr, "uh_listener_add(): Can not create more than " "%i listen sockets\n", UH_LIMIT_LISTENERS ); goto error; } #ifdef HAVE_TLS /* init TLS */ l->tls = do_tls ? conf->tls : NULL; #endif /* add socket to server fd set */ FD_SET(sock, serv_fds); fd_cloexec(sock); *max_fd = max(*max_fd, sock); bound++; continue; error: if( sock > 0 ) close(sock); } freeaddrinfo(addrs); return bound; }