int ip_init(anysin_t *addresses, int addresses_count) { int i; global_ip_sockets = (struct ip_socket_t *) calloc(addresses_count * 2, sizeof(struct ip_socket_t)); if (!global_ip_sockets) goto wrong; global_ip_sockets_count = addresses_count * 2; for (i = 0; i < global_ip_sockets_count; i++) global_ip_sockets[i].fd = -1; for (i = 0; i < addresses_count; i++) { int sid = i * 2; // Do UDP bindings: global_ip_sockets[sid].address = &addresses[i]; global_ip_sockets[sid].protocol = IP_PROTOCOL_UDP; if (!ip_udp_open(&global_ip_sockets[sid].fd, &addresses[i])) { debug_log(DEBUG_FATAL, "ip_init(): unable to open UDP socket (%s)\n", strerror(errno)); goto wrong; } if (!ip_reuse(global_ip_sockets[sid].fd)) debug_log(DEBUG_WARN, "ip_init(): unable to set UDP socket to reuse address (%s)\n", strerror(errno)); if (!ip_bind(global_ip_sockets[sid].fd, &addresses[i])) { debug_log(DEBUG_FATAL, "ip_init(): unable to bind UDP socket (%s)\n", strerror(errno)); goto wrong; } // Do TCP bindings: global_ip_sockets[sid+1].address = &addresses[i]; global_ip_sockets[sid+1].protocol = IP_PROTOCOL_TCP; if (!ip_tcp_open(&global_ip_sockets[sid+1].fd, &addresses[i])) { debug_log(DEBUG_FATAL, "ip_init(): unable to open TCP socket (%s)\n", strerror(errno)); goto wrong; } if (!ip_reuse(global_ip_sockets[sid+1].fd)) debug_log(DEBUG_WARN, "ip_init(): unable to set TCP socket to reuse address (%s)\n", strerror(errno)); if (!ip_bind(global_ip_sockets[sid+1].fd, &addresses[i])) { debug_log(DEBUG_FATAL, "ip_init(): unable to bind TCP socket (%s)\n", strerror(errno)); goto wrong; } if (!ip_tcp_listen(global_ip_sockets[sid+1].fd)) { debug_log(DEBUG_FATAL, "ip_init(): unable to listen on TCP socket (%s)\n", strerror(errno)); } } return 1; wrong: ip_close(); return 0; }
int dns_forward_query_udp(event_entry_t *general_entry) { int sock, n; struct event_udp_entry *entry = &general_entry->udp; if (!ip_udp_open(&sock, &global_target_address)) { debug_log(DEBUG_ERROR, "dns_forward_query_udp(): unable to open a UDP socket to forward query to authoritative server\n"); goto wrong; } // randomize the outgoing source port and set the source IP address, if needed if (!ip_bind_random(sock)) { // if this fails, let the kernel handle it (would mean source IP address is not guaranteed...) debug_log(DEBUG_WARN, "dns_forward_query_udp(): unable to bind to source IP address and/or random port\n"); } entry->state = EVENT_UDP_INT_WRITING; entry->read_int_watcher.data = general_entry; entry->timeout_int_watcher.data = general_entry; entry->retries++; // Now generate a new TXID to forecome any poisoning: entry->buffer[0] = misc_crypto_random(256); entry->buffer[1] = misc_crypto_random(256); // XXX: do this platform safe (i.e. ntoh) entry->dns.dsttxid = (entry->buffer[0] << 8) + entry->buffer[1]; ev_io_init(&entry->read_int_watcher, event_udp_int_cb, sock, EV_READ); ev_timer_init(&entry->timeout_int_watcher, event_udp_timeout_cb, 0., global_ip_internal_timeout); ev_io_start(event_default_loop, &entry->read_int_watcher); ev_timer_again(event_default_loop, &entry->timeout_int_watcher); debug_log(DEBUG_INFO, "dns_forward_query_udp(): forwarding query to authoritative name server (prev id = %d, new id = %d)\n", (entry->dns.type == DNS_DNSCURVE_STREAMLINED || entry->dns.type == DNS_NON_DNSCURVE) ? entry->dns.srctxid : entry->dns.srcinsidetxid, entry->dns.dsttxid); n = sendto(sock, entry->buffer, entry->packetsize, MSG_DONTWAIT, (struct sockaddr *) &global_target_address.sa, global_target_address_len); if (n == -1) { debug_log(DEBUG_ERROR, "dns_forward_query_udp(): unable to forward the query to authoritative name server (%s)\n", strerror(errno)); goto wrong; } return 1; wrong: return 0; }