int resolv_init(struct ev_loop *loop, char **nameservers, int nameserver_num, int ipv6first) { if (ipv6first) resolv_mode = MODE_IPV6_FIRST; else resolv_mode = MODE_IPV4_FIRST; struct dns_ctx *ctx = &dns_defctx; if (nameservers == NULL) { /* Nameservers not specified, use system resolver config */ dns_init(ctx, 0); } else { dns_reset(ctx); for (int i = 0; i < nameserver_num; i++) { char *server = nameservers[i]; dns_add_serv(ctx, server); } } int sockfd = dns_open(ctx); if (sockfd < 0) { FATAL("Failed to open DNS resolver socket"); } if (nameserver_num == 1 && nameservers != NULL) { if (strncmp("127.0.0.1", nameservers[0], 9) == 0 || strncmp("::1", nameservers[0], 3) == 0) { if (verbose) { LOGI("bind UDP resolver to %s", nameservers[0]); } if (bind_to_address(sockfd, nameservers[0]) == -1) ERROR("bind_to_address"); } } #ifdef __MINGW32__ setnonblocking(sockfd); #else int flags = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); #endif ev_io_init(&resolv_io_watcher, resolv_sock_cb, sockfd, EV_READ); resolv_io_watcher.data = ctx; ev_io_start(loop, &resolv_io_watcher); ev_timer_init(&resolv_timeout_watcher, resolv_timeout_cb, 0.0, 0.0); resolv_timeout_watcher.data = ctx; dns_set_tmcbck(ctx, dns_timer_setup_cb, loop); return sockfd; }
static inline int bind_socket(int sk, int index, int family) { char interface[IF_NAMESIZE]; int err; if (if_indextoname(index, interface) == NULL) return -1; err = setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE, interface, IF_NAMESIZE); if (err < 0) err = bind_to_address(sk, interface, family); return err; }
int bind_to_tcp_address(const char *ipaddr, const char *port, int backlog) { return bind_to_address(ipaddr, port, SOCK_STREAM, backlog); }
int bind_to_udp_address(const char *ipaddr, const char *port) { return bind_to_address(ipaddr, port, SOCK_DGRAM, 0); }