| 973 | #ifndef NO_IPV6 |
| 974 | |
| 975 | static int setup_named_sock(char *listen_addr, int listen_port, struct socketlist *socklist) |
| 976 | { |
| 977 | int socknum = 0; |
| 978 | char pbuf[NI_MAXSERV]; |
| 979 | struct addrinfo hints, *ai0, *ai; |
| 980 | int gai; |
| 981 | long flags; |
| 982 | |
| 983 | xsnprintf(pbuf, sizeof(pbuf), "%d", listen_port); |
| 984 | memset(&hints, 0, sizeof(hints)); |
| 985 | hints.ai_family = AF_UNSPEC; |
| 986 | hints.ai_socktype = SOCK_STREAM; |
| 987 | hints.ai_protocol = IPPROTO_TCP; |
| 988 | hints.ai_flags = AI_PASSIVE; |
| 989 | |
| 990 | gai = getaddrinfo(listen_addr, pbuf, &hints, &ai0); |
| 991 | if (gai) { |
| 992 | logerror("getaddrinfo() for %s failed: %s", listen_addr, gai_strerror(gai)); |
| 993 | return 0; |
| 994 | } |
| 995 | |
| 996 | for (ai = ai0; ai; ai = ai->ai_next) { |
| 997 | int sockfd; |
| 998 | |
| 999 | sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
| 1000 | if (sockfd < 0) |
| 1001 | continue; |
| 1002 | |
| 1003 | #ifdef IPV6_V6ONLY |
| 1004 | if (ai->ai_family == AF_INET6) { |
| 1005 | int on = 1; |
| 1006 | setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, |
| 1007 | &on, sizeof(on)); |
| 1008 | /* Note: error is not fatal */ |
| 1009 | } |
| 1010 | #endif |
| 1011 | |
| 1012 | if (set_reuse_addr(sockfd)) { |
| 1013 | logerror("Could not set SO_REUSEADDR: %s", strerror(errno)); |
| 1014 | close(sockfd); |
| 1015 | continue; |
| 1016 | } |
| 1017 | |
| 1018 | set_keep_alive(sockfd); |
| 1019 | |
| 1020 | if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) { |
| 1021 | logerror("Could not bind to %s: %s", |
| 1022 | ip2str(ai->ai_family, ai->ai_addr), |
| 1023 | strerror(errno)); |
| 1024 | close(sockfd); |
| 1025 | continue; /* not fatal */ |
| 1026 | } |
| 1027 | if (listen(sockfd, 5) < 0) { |
| 1028 | logerror("Could not listen to %s: %s", |
| 1029 | ip2str(ai->ai_family, ai->ai_addr), |
| 1030 | strerror(errno)); |
| 1031 | close(sockfd); |
| 1032 | continue; /* not fatal */ |
no test coverage detected