Skip to content

Commit

Permalink
Add -c DSCP codepoint option
Browse files Browse the repository at this point in the history
Specify a DSCP codepoint on DNS server upstream connections.  This may
be useful to those using qdiscs/AQMs that categorise traffic
importance/priority by DSCP value.

Whilst this could be done by ip/nftables rules, let's get the
application to do it.

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
  • Loading branch information
ldir-EDB0 committed Apr 22, 2020
1 parent 79fc7b0 commit 1bc54e7
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 2 deletions.
29 changes: 29 additions & 0 deletions src/https_client.c
Expand Up @@ -7,6 +7,7 @@
#include <grp.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <pwd.h>
#include <stdint.h>
#include <stdio.h>
Expand Down Expand Up @@ -35,6 +36,29 @@ static size_t write_buffer(void *buf, size_t size, size_t nmemb, void *userp) {
return size * nmemb;
}

#if defined(IP_TOS)
static curl_socket_t opensocket_callback(void *clientp, curlsocktype purpose, struct curl_sockaddr *addr)
{
/* int dscp=IPTOS_CLASS_CS4;
int val=*(int *)clientp;*/
curl_socket_t sock;

sock=socket(addr->family, addr->socktype, addr->protocol);

if (purpose != CURLSOCKTYPE_IPCXN)
return sock;

if (sock != -1) {
if (addr->family == AF_INET6)
(void)setsockopt(sock, IPPROTO_IPV6, IP_TOS, (int *)clientp, sizeof(int));
else if (addr->family == AF_INET)
(void)setsockopt(sock, IPPROTO_IP, IP_TOS, (int *)clientp, sizeof(int));
}

return sock;
}
#endif

static void https_fetch_ctx_init(https_client_t *client,
struct https_fetch_ctx *ctx, const char *url,
const char* data, size_t datalen,
Expand Down Expand Up @@ -63,6 +87,11 @@ static void https_fetch_ctx_init(https_client_t *client,
if (logging_debug_enabled()) {
curl_easy_setopt(ctx->curl, CURLOPT_VERBOSE, 1L);
}
#if defined(IP_TOS)
if (client->opt->dscp)
curl_easy_setopt(ctx->curl, CURLOPT_OPENSOCKETDATA, &client->opt->dscp);
curl_easy_setopt(ctx->curl, CURLOPT_OPENSOCKETFUNCTION, opensocket_callback);
#endif
curl_easy_setopt(ctx->curl, CURLOPT_URL, url);
ctx->header_list = curl_slist_append(ctx->header_list, "Accept: application/dns-message");
ctx->header_list = curl_slist_append(ctx->header_list, "Content-Type: application/dns-message");
Expand Down
16 changes: 14 additions & 2 deletions src/options.c
Expand Up @@ -25,6 +25,7 @@ void options_init(struct Options *opt) {
opt->logfd = -1;
opt->loglevel = LOG_ERROR;
opt->daemonize = 0;
opt->dscp = 0;
opt->user = NULL;
opt->group = NULL;
opt->uid = -1;
Expand All @@ -39,11 +40,14 @@ void options_init(struct Options *opt) {

int options_parse_args(struct Options *opt, int argc, char **argv) {
int c;
while ((c = getopt(argc, argv, "a:p:du:g:b:4r:e:t:l:vx")) != -1) {
while ((c = getopt(argc, argv, "a:c:p:du:g:b:4r:e:t:l:vx")) != -1) {
switch (c) {
case 'a': // listen_addr
opt->listen_addr = optarg;
break;
case 'c': // DSCP codepoint
opt->dscp = atoi(optarg);
break;
case 'p': // listen_port
opt->listen_port = atoi(optarg);
break;
Expand Down Expand Up @@ -103,6 +107,11 @@ int options_parse_args(struct Options *opt, int argc, char **argv) {
}
opt->gid = g->gr_gid;
}
if (opt->dscp < 0 || opt->dscp >63) {
printf("DSCP code (%d) invalid:[0-63]\n", opt->dscp);
return -1;
}
opt->dscp <<= 2;
// Get noisy about bad security practices.
if (getuid() == 0 && (!opt->user || !opt->group)) {
printf("----------------------------\n"
Expand Down Expand Up @@ -134,7 +143,8 @@ void options_show_usage(int argc, char **argv) {
printf("Usage: %s [-a <listen_addr>] [-p <listen_port>]\n", argv[0]);
printf(" [-d] [-u <user>] [-g <group>] [-b <dns_servers>]\n");
printf(" [-r <resolver_url>] [-e <subnet_addr>]\n");
printf(" [-t <proxy_server>] [-l <logfile>] [-x] [-v]+\n\n");
printf(" [-t <proxy_server>] [-l <logfile>] -c <dscp_codepoint>\n");
printf(" [-x] [-v]+\n\n");
printf(" -a listen_addr Local IPv4/v6 address to bind to. (%s)\n",
defaults.listen_addr);
printf(" -p listen_port Local port to bind to. (%d)\n",
Expand All @@ -157,6 +167,8 @@ void options_show_usage(int argc, char **argv) {
printf(" bootstrap DNS servers.\n");
printf(" -l logfile Path to file to log to. (\"%s\")\n",
defaults.logfile);
printf(" -c dscp_codepoint Optional DSCP codepoint[0-63] to set on upstream DNS server\n");
printf(" connections.\n");
printf(" -x Use HTTP/1.1 instead of HTTP/2. Useful with broken\n"
" or limited builds of libcurl. (false)\n");
printf(" -v Increase logging verbosity. (INFO)\n");
Expand Down
2 changes: 2 additions & 0 deletions src/options.h
Expand Up @@ -30,6 +30,8 @@ struct Options {

int ipv4; // if non-zero, will only use AF_INET addresses.

int dscp; // mark packet with DSCP

// Resolver URL prefix to use. Must start with https://.
const char *resolver_url;

Expand Down

0 comments on commit 1bc54e7

Please sign in to comment.