/* open fd */
fd = create_tcp_accept_sock(res, 1, &noproto, 0,
- cfg->ip_transparent, 0, cfg->ip_freebind, cfg->use_systemd);
+ cfg->ip_transparent, 0, cfg->ip_freebind, cfg->use_systemd, cfg->ip_dscp);
freeaddrinfo(res);
}
worker->back = outside_network_create(worker->base,
cfg->msg_buffer_size, (size_t)cfg->outgoing_num_ports,
cfg->out_ifs, cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
- cfg->do_tcp?cfg->outgoing_num_tcp:0,
+ cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp,
worker->daemon->env->infra_cache, worker->rndstate,
cfg->use_caps_bits_for_id, worker->ports, worker->numports,
cfg->unwanted_threshold, cfg->outgoing_tcp_mss,
w->back = outside_network_create(w->base, cfg->msg_buffer_size,
(size_t)cfg->outgoing_num_ports, cfg->out_ifs,
cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
- cfg->do_tcp?cfg->outgoing_num_tcp:0,
+ cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp,
w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
ports, numports, cfg->unwanted_threshold,
cfg->outgoing_tcp_mss, &libworker_alloc_cleanup, w,
create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto,
int rcv, int snd, int listen, int* reuseport, int transparent,
- int freebind, int use_systemd)
+ int freebind, int use_systemd, int dscp)
{
int s;
+ char* err;
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined (SO_BINDANY)
int on=1;
#endif
# endif
#endif /* SO_SNDBUF */
}
+ err = set_ip_dscp(s, family, dscp);
+ if(err != NULL)
+ log_warn("error setting IP DiffServ codepoint %d on UDP socket: %s", dscp, err);
if(family == AF_INET6) {
# if defined(IPV6_V6ONLY)
if(v6only) {
int
create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
- int* reuseport, int transparent, int mss, int freebind, int use_systemd)
+ int* reuseport, int transparent, int mss, int freebind, int use_systemd, int dscp)
{
int s;
+ char* err;
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined(SO_BINDANY)
int on = 1;
#endif
strerror(errno));
}
#endif /* IP_TRANSPARENT || IP_BINDANY || SO_BINDANY */
+ err = set_ip_dscp(s, addr->ai_family, dscp);
+ if(err != NULL)
+ log_warn("error setting IP DiffServ codepoint %d on TCP socket: %s", dscp, err);
if(
#ifdef HAVE_SYSTEMD
!got_fd_from_systemd &&
return s;
}
+char*
+set_ip_dscp(int socket, int addrfamily, int dscp) {
+ int ds;
+
+ if(dscp == 0)
+ return NULL;
+ ds = dscp << 2;
+ switch(addrfamily) {
+ case AF_INET6:
+ if(setsockopt(socket, IPPROTO_IPV6, IPV6_TCLASS, &ds, sizeof(ds)) < 0)
+ return sock_strerror(errno);
+ default:
+ if(setsockopt(socket, IPPROTO_IP, IP_TOS, &ds, sizeof(ds)) < 0)
+ return sock_strerror(errno);
+ }
+ return NULL;
+}
+
+# ifndef USE_WINSOCK
+char*
+sock_strerror(int errn){
+ return strerror(errno);
+}
+
+void
+sock_close(int socket) {
+ close(socket);
+}
+
+# else
+char*
+sock_strerror(int errn){
+ return wsa_strerror(WSAGetLastError()))
+}
+
+void
+sock_close(int socket) {
+ closesocket(socket);
+}
+
+# endif /* USE_WINSOCK */
+
int
create_local_accept_sock(const char *path, int* noproto, int use_systemd)
{
static int
make_sock(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
- int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd)
+ int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd, int dscp)
{
struct addrinfo *res = NULL;
int r, s, inuse, noproto;
s = create_udp_sock(res->ai_family, res->ai_socktype,
(struct sockaddr*)res->ai_addr, res->ai_addrlen,
v6only, &inuse, &noproto, (int)rcv, (int)snd, 1,
- reuseport, transparent, freebind, use_systemd);
+ reuseport, transparent, freebind, use_systemd, dscp);
if(s == -1 && inuse) {
log_err("bind: address already in use");
} else if(s == -1 && noproto && hints->ai_family == AF_INET6){
}
} else {
s = create_tcp_accept_sock(res, v6only, &noproto, reuseport,
- transparent, tcp_mss, freebind, use_systemd);
+ transparent, tcp_mss, freebind, use_systemd, dscp);
if(s == -1 && noproto && hints->ai_family == AF_INET6){
*noip6 = 1;
}
static int
make_sock_port(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
- int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd)
+ int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd, int dscp)
{
char* s = strchr(ifname, '@');
if(s) {
(void)strlcpy(p, s+1, sizeof(p));
p[strlen(s+1)]=0;
return make_sock(stype, newif, p, hints, v6only, noip6,
- rcv, snd, reuseport, transparent, tcp_mss, freebind, use_systemd);
+ rcv, snd, reuseport, transparent, tcp_mss, freebind, use_systemd, dscp);
}
return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd,
- reuseport, transparent, tcp_mss, freebind, use_systemd);
+ reuseport, transparent, tcp_mss, freebind, use_systemd, dscp);
}
/**
size_t rcv, size_t snd, int ssl_port,
struct config_strlist* tls_additional_port, int* reuseport,
int transparent, int tcp_mss, int freebind, int use_systemd,
- int dnscrypt_port)
+ int dnscrypt_port, int dscp)
{
int s, noip6=0;
#ifdef USE_DNSCRYPT
if(do_auto) {
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
- tcp_mss, freebind, use_systemd)) == -1) {
+ tcp_mss, freebind, use_systemd, dscp)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
/* regular udp socket */
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
- tcp_mss, freebind, use_systemd)) == -1) {
+ tcp_mss, freebind, use_systemd, dscp)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
tls_additional_port);
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
&noip6, 0, 0, reuseport, transparent, tcp_mss,
- freebind, use_systemd)) == -1) {
+ freebind, use_systemd, dscp)) == -1) {
if(noip6) {
/*log_warn("IPv6 protocol not available");*/
return 1;
cfg->ssl_port, cfg->tls_additional_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
- cfg->dnscrypt_port)) {
+ cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
cfg->ssl_port, cfg->tls_additional_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
- cfg->dnscrypt_port)) {
+ cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
cfg->ssl_port, cfg->tls_additional_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
- cfg->dnscrypt_port)) {
+ cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
cfg->ssl_port, cfg->tls_additional_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
- cfg->dnscrypt_port)) {
+ cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
*/
int create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv,
- int snd, int listen, int* reuseport, int transparent, int freebind, int use_systemd);
+ int snd, int listen, int* reuseport, int transparent, int freebind, int use_systemd, int dscp);
/**
* Create and bind TCP listening socket
* @return: the socket. -1 on error.
*/
int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
- int* reuseport, int transparent, int mss, int freebind, int use_systemd);
+ int* reuseport, int transparent, int mss, int freebind, int use_systemd, int dscp);
/**
* Create and bind local listening socket
/** get the size of currently used tcp stream wait buffers (in bytes) */
size_t tcp_req_info_get_stream_buffer_size(void);
+char* set_ip_dscp(int socket, int addrfamily, int ds);
+char* sock_strerror(int errn);
+
#endif /* LISTEN_DNSPORT_H */
/** 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),
}
#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,
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;
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,
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;
*/
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)) {
}
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;
}
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;
{
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;
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;
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;
}
{
/* 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;
}
#endif
/** maximum segment size of tcp socket */
int tcp_mss;
+ /** IP_TOS socket option requested on the sockets */
+ int ip_dscp;
/**
* Array of tcp pending used for outgoing TCP connections.
*/
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_ip4, 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,
/** 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);
+int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, int dscp);
/**
* Create udp commpoint suitable for sending packets to the destination.
size_t ATTR_UNUSED(num_ports), char** ATTR_UNUSED(ifs),
int ATTR_UNUSED(num_ifs), int ATTR_UNUSED(do_ip4),
int ATTR_UNUSED(do_ip6), size_t ATTR_UNUSED(num_tcp),
+ int ATTR_UNUSED(dscp),
struct infra_cache* infra,
struct ub_randstate* ATTR_UNUSED(rnd),
int ATTR_UNUSED(use_caps_for_id), int* ATTR_UNUSED(availports),
int* ATTR_UNUSED(noproto), int ATTR_UNUSED(rcv), int ATTR_UNUSED(snd),
int ATTR_UNUSED(listen), int* ATTR_UNUSED(reuseport),
int ATTR_UNUSED(transparent), int ATTR_UNUSED(freebind),
- int ATTR_UNUSED(use_systemd))
+ int ATTR_UNUSED(use_systemd), int ATTR_UNUSED(dscp))
{
/* if you actually print to this, it'll be stdout during test */
return 1;
}
int outnet_get_tcp_fd(struct sockaddr_storage* ATTR_UNUSED(addr),
- socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(tcp_mss))
+ socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(tcp_mss), int ATTR_UNUSED(dscp))
{
log_assert(0);
return -1;