diff options
Diffstat (limited to 'services/outside_network.c')
-rw-r--r-- | services/outside_network.c | 121 |
1 files changed, 68 insertions, 53 deletions
diff --git a/services/outside_network.c b/services/outside_network.c index 80b1f12454d6..44e01d7450cb 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -205,18 +205,25 @@ pick_outgoing_tcp(struct waiting_tcp* w, int s) /** get TCP file descriptor for address, returns -1 on failure, * tcp_mss is 0 or maxseg size to set for TCP packets. */ int -outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss) +outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, int dscp) { int s; + int af; + char* err; #ifdef SO_REUSEADDR int on = 1; #endif #ifdef INET6 - if(addr_is_ip6(addr, addrlen)) + if(addr_is_ip6(addr, addrlen)){ s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); - else + af = AF_INET6; + } else { +#else + { #endif + af = AF_INET; s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + } if(s == -1) { #ifndef USE_WINSOCK log_err_addr("outgoing tcp: socket", strerror(errno), @@ -236,6 +243,12 @@ outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss) } #endif + err = set_ip_dscp(s, af, dscp); + if(err != NULL) { + verbose(VERB_ALGO, "outgoing tcp:" + "error setting IP DiffServ codepoint on socket"); + } + if(tcp_mss > 0) { #if defined(IPPROTO_TCP) && defined(TCP_MAXSEG) if(setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, @@ -291,7 +304,7 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) log_assert(pkt); log_assert(w->addrlen > 0); /* open socket */ - s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss); + s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss, w->outnet->ip_dscp); if(s == -1) return 0; @@ -373,45 +386,16 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl); #endif pend->c->ssl_shake_state = comm_ssl_shake_write; - if(w->tls_auth_name) { + if(!set_auth_name_on_ssl(pend->c->ssl, w->tls_auth_name, + w->outnet->tls_use_sni)) { + pend->c->fd = s; #ifdef HAVE_SSL - (void)SSL_set_tlsext_host_name(pend->c->ssl, w->tls_auth_name); + SSL_free(pend->c->ssl); #endif + pend->c->ssl = NULL; + comm_point_close(pend->c); + return 0; } -#ifdef HAVE_SSL_SET1_HOST - if(w->tls_auth_name) { - SSL_set_verify(pend->c->ssl, SSL_VERIFY_PEER, NULL); - /* setting the hostname makes openssl verify the - * host name in the x509 certificate in the - * SSL connection*/ - if(!SSL_set1_host(pend->c->ssl, w->tls_auth_name)) { - log_err("SSL_set1_host failed"); - pend->c->fd = s; - SSL_free(pend->c->ssl); - pend->c->ssl = NULL; - comm_point_close(pend->c); - return 0; - } - } -#elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) - /* openssl 1.0.2 has this function that can be used for - * set1_host like verification */ - if(w->tls_auth_name) { - X509_VERIFY_PARAM* param = SSL_get0_param(pend->c->ssl); - X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); - if(!X509_VERIFY_PARAM_set1_host(param, w->tls_auth_name, strlen(w->tls_auth_name))) { - log_err("X509_VERIFY_PARAM_set1_host failed"); - pend->c->fd = s; - SSL_free(pend->c->ssl); - pend->c->ssl = NULL; - comm_point_close(pend->c); - return 0; - } - SSL_set_verify(pend->c->ssl, SSL_VERIFY_PEER, NULL); - } -#else - verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication"); -#endif /* HAVE_SSL_SET1_HOST */ } w->pkt = NULL; w->next_waiting = (void*)pend; @@ -512,7 +496,9 @@ portcomm_loweruse(struct outside_network* outnet, struct port_comm* pc) comm_point_close(pc->cp); pif = pc->pif; log_assert(pif->inuse > 0); +#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION pif->avail_ports[pif->avail_total - pif->inuse] = pc->number; +#endif pif->inuse--; pif->out[pc->index] = pif->out[pif->inuse]; pif->out[pc->index]->index = pc->index; @@ -725,10 +711,12 @@ create_pending_tcp(struct outside_network* outnet, size_t bufsize) static int setup_if(struct port_if* pif, const char* addrstr, int* avail, int numavail, size_t numfd) { +#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION pif->avail_total = numavail; pif->avail_ports = (int*)memdup(avail, (size_t)numavail*sizeof(int)); if(!pif->avail_ports) return 0; +#endif if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen) && !netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen, &pif->pfxlen)) @@ -745,11 +733,11 @@ static int setup_if(struct port_if* pif, const char* addrstr, struct outside_network* outside_network_create(struct comm_base *base, size_t bufsize, size_t num_ports, char** ifs, int num_ifs, int do_ip4, - int do_ip6, size_t num_tcp, struct infra_cache* infra, + int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra, struct ub_randstate* rnd, int use_caps_for_id, int* availports, int numavailports, size_t unwanted_threshold, int tcp_mss, void (*unwanted_action)(void*), void* unwanted_param, int do_udp, - void* sslctx, int delayclose, struct dt_env* dtenv) + void* sslctx, int delayclose, int tls_use_sni, struct dt_env* dtenv) { struct outside_network* outnet = (struct outside_network*) calloc(1, sizeof(struct outside_network)); @@ -765,6 +753,7 @@ outside_network_create(struct comm_base *base, size_t bufsize, outnet->infra = infra; outnet->rnd = rnd; outnet->sslctx = sslctx; + outnet->tls_use_sni = tls_use_sni; #ifdef USE_DNSTAP outnet->dtenv = dtenv; #else @@ -778,6 +767,7 @@ outside_network_create(struct comm_base *base, size_t bufsize, outnet->use_caps_for_id = use_caps_for_id; outnet->do_udp = do_udp; outnet->tcp_mss = tcp_mss; + outnet->ip_dscp = dscp; #ifndef S_SPLINT_S if(delayclose) { outnet->delayclose = 1; @@ -955,7 +945,9 @@ outside_network_delete(struct outside_network* outnet) comm_point_delete(pc->cp); free(pc); } +#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION free(outnet->ip4_ifs[i].avail_ports); +#endif free(outnet->ip4_ifs[i].out); } free(outnet->ip4_ifs); @@ -969,7 +961,9 @@ outside_network_delete(struct outside_network* outnet) comm_point_delete(pc->cp); free(pc); } +#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION free(outnet->ip6_ifs[i].avail_ports); +#endif free(outnet->ip6_ifs[i].out); } free(outnet->ip6_ifs); @@ -1059,11 +1053,12 @@ sai6_putrandom(struct sockaddr_in6 *sa, int pfxlen, struct ub_randstate *rnd) * @param port: port override for addr. * @param inuse: if -1 is returned, this bool means the port was in use. * @param rnd: random state (for address randomisation). + * @param dscp: DSCP to use. * @return fd or -1 */ static int udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen, - int port, int* inuse, struct ub_randstate* rnd) + int port, int* inuse, struct ub_randstate* rnd, int dscp) { int fd, noproto; if(addr_is_ip6(addr, addrlen)) { @@ -1078,13 +1073,13 @@ udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen, } fd = create_udp_sock(AF_INET6, SOCK_DGRAM, (struct sockaddr*)&sa, addrlen, 1, inuse, &noproto, - 0, 0, 0, NULL, 0, freebind, 0); + 0, 0, 0, NULL, 0, freebind, 0, dscp); } else { struct sockaddr_in* sa = (struct sockaddr_in*)addr; sa->sin_port = (in_port_t)htons((uint16_t)port); fd = create_udp_sock(AF_INET, SOCK_DGRAM, (struct sockaddr*)addr, addrlen, 1, inuse, &noproto, - 0, 0, 0, NULL, 0, 0, 0); + 0, 0, 0, NULL, 0, 0, 0, dscp); } return fd; } @@ -1133,6 +1128,7 @@ select_ifport(struct outside_network* outnet, struct pending* pend, while(1) { my_if = ub_random_max(outnet->rnd, num_if); pif = &ifs[my_if]; +#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION my_port = ub_random_max(outnet->rnd, pif->avail_total); if(my_port < pif->inuse) { /* port already open */ @@ -1144,8 +1140,11 @@ select_ifport(struct outside_network* outnet, struct pending* pend, /* try to open new port, if fails, loop to try again */ log_assert(pif->inuse < pif->maxout); portno = pif->avail_ports[my_port - pif->inuse]; +#else + my_port = portno = 0; +#endif fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen, - portno, &inuse, outnet->rnd); + portno, &inuse, outnet->rnd, outnet->ip_dscp); if(fd == -1 && !inuse) { /* nonrecoverable error making socket */ return 0; @@ -1167,8 +1166,10 @@ select_ifport(struct outside_network* outnet, struct pending* pend, /* grab port in interface */ pif->out[pif->inuse] = pend->pc; +#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION pif->avail_ports[my_port - pif->inuse] = pif->avail_ports[pif->avail_total-pif->inuse-1]; +#endif pif->inuse++; break; } @@ -2192,10 +2193,11 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr, { struct sockaddr_storage* addr; socklen_t addrlen; - int i, try, pnum; + int i, try, pnum, dscp; struct port_if* pif; /* create fd */ + dscp = outnet->ip_dscp; for(try = 0; try<1000; try++) { int port = 0; int freebind = 0; @@ -2225,6 +2227,7 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr, } addr = &pif->addr; addrlen = pif->addrlen; +#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION pnum = ub_random_max(outnet->rnd, pif->avail_total); if(pnum < pif->inuse) { /* port already open */ @@ -2233,19 +2236,21 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr, /* unused ports in start part of array */ port = pif->avail_ports[pnum - pif->inuse]; } - +#else + pnum = port = 0; +#endif if(addr_is_ip6(to_addr, to_addrlen)) { struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr; sa.sin6_port = (in_port_t)htons((uint16_t)port); fd = create_udp_sock(AF_INET6, SOCK_DGRAM, (struct sockaddr*)&sa, addrlen, 1, &inuse, &noproto, - 0, 0, 0, NULL, 0, freebind, 0); + 0, 0, 0, NULL, 0, freebind, 0, dscp); } else { struct sockaddr_in* sa = (struct sockaddr_in*)addr; sa->sin_port = (in_port_t)htons((uint16_t)port); fd = create_udp_sock(AF_INET, SOCK_DGRAM, (struct sockaddr*)addr, addrlen, 1, &inuse, &noproto, - 0, 0, 0, NULL, 0, freebind, 0); + 0, 0, 0, NULL, 0, freebind, 0, dscp); } if(fd != -1) { return fd; @@ -2294,6 +2299,11 @@ setup_comm_ssl(struct comm_point* cp, struct outside_network* outnet, #endif cp->ssl_shake_state = comm_ssl_shake_write; /* https verification */ +#ifdef HAVE_SSL + if(outnet->tls_use_sni) { + (void)SSL_set_tlsext_host_name(cp->ssl, host); + } +#endif #ifdef HAVE_SSL_SET1_HOST if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) { /* because we set SSL_VERIFY_PEER, in netevent in @@ -2316,7 +2326,9 @@ setup_comm_ssl(struct comm_point* cp, struct outside_network* outnet, * set1_host like verification */ if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) { X509_VERIFY_PARAM* param = SSL_get0_param(cp->ssl); +# ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); +# endif if(!X509_VERIFY_PARAM_set1_host(param, host, strlen(host))) { log_err("X509_VERIFY_PARAM_set1_host failed"); return 0; @@ -2335,7 +2347,7 @@ outnet_comm_point_for_tcp(struct outside_network* outnet, sldns_buffer* query, int timeout, int ssl, char* host) { struct comm_point* cp; - int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss); + int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp); if(fd == -1) { return 0; } @@ -2397,7 +2409,7 @@ outnet_comm_point_for_http(struct outside_network* outnet, { /* cp calls cb with err=NETEVENT_DONE when transfer is done */ struct comm_point* cp; - int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss); + int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp); if(fd == -1) { return 0; } @@ -2455,7 +2467,10 @@ if_get_mem(struct port_if* pif) { size_t s; int i; - s = sizeof(*pif) + sizeof(int)*pif->avail_total + + s = sizeof(*pif) + +#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION + sizeof(int)*pif->avail_total + +#endif sizeof(struct port_comm*)*pif->maxout; for(i=0; i<pif->inuse; i++) s += sizeof(*pif->out[i]) + |