From ef05120b07afc17186f2c3cbae47ff50fdf0d346 Mon Sep 17 00:00:00 2001 From: baranyaib90 <5031516+baranyaib90@users.noreply.github.com> Date: Sat, 10 May 2025 23:18:38 +0200 Subject: [PATCH 1/3] Fixing ring_buffer.h define --- src/ring_buffer.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ring_buffer.h b/src/ring_buffer.h index 2815377..0ffa7b9 100755 --- a/src/ring_buffer.h +++ b/src/ring_buffer.h @@ -1,5 +1,5 @@ -#ifndef _FR_H_ -#define _FR_H_ +#ifndef _RING_BUFFER_H_ +#define _RING_BUFFER_H_ #ifdef __cplusplus extern "C" { @@ -18,4 +18,4 @@ void ring_buffer_push_back(struct ring_buffer *rb, char* data, uint32_t size); } #endif -#endif // _FR_H_ +#endif // RING_BUFFER_H_ From e6fd23c76180e93af2c6f29e1b9198c230b6014c Mon Sep 17 00:00:00 2001 From: baranyaib90 <5031516+baranyaib90@users.noreply.github.com> Date: Sat, 10 May 2025 23:19:36 +0200 Subject: [PATCH 2/3] Debug log HTTPS request and response data --- src/https_client.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/https_client.c b/src/https_client.c index db50cac..b438259 100644 --- a/src/https_client.c +++ b/src/https_client.c @@ -139,7 +139,7 @@ static int closesocket_callback(void __attribute__((unused)) *clientp, curl_sock } static void https_log_data(enum LogSeverity level, struct https_fetch_ctx *ctx, - char *ptr, size_t size) + const char * prefix, char *ptr, size_t size) { const size_t width = 0x10; @@ -167,7 +167,7 @@ static void https_log_data(enum LogSeverity level, struct https_fetch_ctx *ctx, } } - LOG_REQ(level, "%4.4lx: %s%s", (long)i, hex, str); + LOG_REQ(level, "%s%4.4lx: %s%s", prefix, (long)i, hex, str); } } @@ -191,10 +191,8 @@ int https_curl_debug(CURL __attribute__((unused)) * handle, curl_infotype type, // not dumping DNS packets because of privacy case CURLINFO_DATA_OUT: case CURLINFO_DATA_IN: - // uncomment, to dump - /* DLOG_REQ("data %s", type == CURLINFO_DATA_IN ? "IN" : "OUT"); - * https_log_data(LOG_DEBUG, ctx, data, size); - * return 0; */ + https_log_data(LOG_DEBUG, ctx, (type == CURLINFO_DATA_IN ? "< " : "> "), data, size); + return 0; // uninformative case CURLINFO_SSL_DATA_OUT: case CURLINFO_SSL_DATA_IN: @@ -206,7 +204,7 @@ int https_curl_debug(CURL __attribute__((unused)) * handle, curl_infotype type, // for extra debugging purpose // if (type != CURLINFO_TEXT) { - // https_log_data(LOG_DEBUG, ctx, data, size); + // https_log_data(LOG_DEBUG, ctx, "", data, size); // } // process lines one-by one @@ -217,7 +215,7 @@ int https_curl_debug(CURL __attribute__((unused)) * handle, curl_infotype type, // skip empty string and curl info Expire if (start != NULL && (pos - start) > 0 && strncmp(start, "Expire", sizeof("Expire") - 1) != 0) { - // https_log_data(LOG_DEBUG, ctx, start, pos - start); + // https_log_data(LOG_DEBUG, ctx, "", start, pos - start); DLOG_REQ("%s%.*s", prefix, pos - start, start); start = NULL; } @@ -394,7 +392,7 @@ static int https_fetch_ctx_process_response(https_client_t *client, } else { WLOG_REQ("curl response code: %d, content length: %zu", long_resp, ctx->buflen); if (ctx->buflen > 0) { - https_log_data(LOG_WARNING, ctx, ctx->buf, ctx->buflen); + https_log_data(LOG_WARNING, ctx, "", ctx->buf, ctx->buflen); } } } From 83f7e922e34eee65ab880e17d94fb21a30b85f09 Mon Sep 17 00:00:00 2001 From: baranyaib90 <5031516+baranyaib90@users.noreply.github.com> Date: Sat, 10 May 2025 23:20:17 +0200 Subject: [PATCH 3/3] Printing curl library versions and used features - Moved argument parsing "decisions" into main() - getopt() handling changes, test OPR_PARSING_ERROR with "-j" and "-i" argument strings. - Minimal libcurl version raised to 7.66.0, so no need to check CURL_VERSION_HTTP3 availability. - Raised hardcoded version. --- CMakeLists.txt | 2 +- README.md | 4 +-- src/https_client.c | 4 --- src/main.c | 68 +++++++++++++++++++++++++++++++++++++--------- src/options.c | 46 ++++++++++++------------------- src/options.h | 11 ++++++-- 6 files changed, 84 insertions(+), 51 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 08613f6..55152ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,7 +117,7 @@ define_file_basename_for_sources("https_dns_proxy") if(SW_VERSION) set_source_files_properties( - src/options.c + src/main.c PROPERTIES COMPILE_FLAGS "-DSW_VERSION='\"${SW_VERSION}\"'") endif() diff --git a/README.md b/README.md index b57eeb0..14313c8 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ only makes sense if you trust your DoH provider. ## Build -Depends on `c-ares (>=1.11.0)`, `libcurl (>=7.65.0)`, `libev (>=4.25)`. +Depends on `c-ares (>=1.11.0)`, `libcurl (>=7.66.0)`, `libev (>=4.25)`. On Debian-derived systems those are libc-ares-dev, libcurl4-{openssl,nss,gnutls}-dev and libev-dev respectively. @@ -208,7 +208,7 @@ Usage: ./https_dns_proxy [-a ] [-p ] -F log_limit Flight recorder: storing desired amount of logs from all levels in memory and dumping them on fatal error or on SIGUSR2 signal. (Default: 0, Disabled: 0, Min: 100, Max: 100000) - -V Print version and exit. + -V Print versions and exit. -h Print help and exit. ``` diff --git a/src/https_client.c b/src/https_client.c index b438259..6f83026 100644 --- a/src/https_client.c +++ b/src/https_client.c @@ -235,10 +235,8 @@ static const char * http_version_str(const long version) { case CURL_HTTP_VERSION_2_0: // fallthrough case CURL_HTTP_VERSION_2TLS: return "2"; -#ifdef CURL_VERSION_HTTP3 case CURL_HTTP_VERSION_3: return "3"; -#endif default: FLOG("Unsupported HTTP version: %d", version); } @@ -255,9 +253,7 @@ static void https_set_request_version(https_client_t *client, case 2: break; case 3: -#ifdef CURL_VERSION_HTTP3 http_version_int = CURL_HTTP_VERSION_3; -#endif break; default: FLOG_REQ("Invalid HTTP version: %d", client->opt->use_http_version); diff --git a/src/main.c b/src/main.c index 7f39301..2e9f5f2 100644 --- a/src/main.c +++ b/src/main.c @@ -205,38 +205,80 @@ static int proxy_supports_name_resolution(const char *proxy) return 0; } +static const char * sw_version(void) { +#ifdef SW_VERSION + return SW_VERSION; +#else + return "2025.5.10-atLeast"; // update date sometimes, like 1-2 times a year +#endif +} + int main(int argc, char *argv[]) { struct Options opt; options_init(&opt); - if (options_parse_args(&opt, argc, argv)) { - options_show_usage(argc, argv); - exit(1); + switch (options_parse_args(&opt, argc, argv)) { + case OPR_SUCCESS: + break; + case OPR_HELP: + options_show_usage(argc, argv); + exit(0); // asking for help is not a problem + case OPR_VERSION: { + printf("%s\n", sw_version()); + CURLcode init_res = curl_global_init(CURL_GLOBAL_DEFAULT); + curl_version_info_data *curl_ver = curl_version_info(CURLVERSION_NOW); + if (init_res == CURLE_OK && curl_ver != NULL) { + printf("Using: ev/%d.%d c-ares/%s %s\n", + ev_version_major(), ev_version_minor(), + ares_version(NULL), curl_version()); + printf("Features: %s%s%s%s\n", + curl_ver->features & CURL_VERSION_HTTP2 ? "HTTP2 " : "", + curl_ver->features & CURL_VERSION_HTTP3 ? "HTTP3 " : "", + curl_ver->features & CURL_VERSION_HTTPS_PROXY ? "HTTPS-proxy " : "", + curl_ver->features & CURL_VERSION_IPV6 ? "IPv6" : ""); + exit(0); + } else { + printf("\nFailed to get curl version info!\n"); + exit(1); + } + } + case OPR_PARSING_ERROR: + printf("Failed to parse options!\n"); + // fallthrough + case OPR_OPTION_ERROR: + printf("\n"); + options_show_usage(argc, argv); + exit(1); + default: + abort(); // must not happen } logging_init(opt.logfd, opt.loglevel, opt.flight_recorder_size); - ILOG("Version: %s", options_sw_version()); + ILOG("Version: %s", sw_version()); ILOG("Built: " __DATE__ " " __TIME__); - ILOG("System c-ares: %s", ares_version(NULL)); - ILOG("System libcurl: %s", curl_version()); + ILOG("System ev library: %d.%d", ev_version_major(), ev_version_minor()); + ILOG("System c-ares library: %s", ares_version(NULL)); + ILOG("System curl library: %s", curl_version()); // Note: curl intentionally uses uninitialized stack variables and similar // tricks to increase it's entropy pool. This confuses valgrind and leaks // through to errors about use of uninitialized values in our code. :( - curl_global_init(CURL_GLOBAL_DEFAULT); + CURLcode code = curl_global_init(CURL_GLOBAL_DEFAULT); + if (code != CURLE_OK) { + FLOG("Failed to initialize curl, error code %d: %s", + code, curl_easy_strerror(code)); + } curl_version_info_data *curl_ver = curl_version_info(CURLVERSION_NOW); + if (curl_ver == NULL) { + FLOG("Failed to get curl version info!"); + } if (!(curl_ver->features & CURL_VERSION_HTTP2)) { WLOG("HTTP/2 is not supported by current libcurl"); } -#ifdef CURL_VERSION_HTTP3 - if (!(curl_ver->features & CURL_VERSION_HTTP3)) - { + if (!(curl_ver->features & CURL_VERSION_HTTP3)) { WLOG("HTTP/3 is not supported by current libcurl"); } -#else - WLOG("HTTP/3 was not available at build time, it will not work at all"); -#endif if (!(curl_ver->features & CURL_VERSION_IPV6)) { WLOG("IPv6 is not supported by current libcurl"); } diff --git a/src/options.c b/src/options.c index 9c9add9..e432e93 100644 --- a/src/options.c +++ b/src/options.c @@ -19,15 +19,6 @@ enum { DEFAULT_HTTP_VERSION = 2 }; - -const char * options_sw_version(void) { -#ifdef SW_VERSION - return SW_VERSION; -#else - return "2023.10.10-atLeast"; // update date sometimes, like 1-2 times a year -#endif -} - void options_init(struct Options *opt) { opt->listen_addr = "127.0.0.1"; opt->listen_port = 5053; @@ -53,7 +44,7 @@ void options_init(struct Options *opt) { opt->flight_recorder_size = 0; } -int options_parse_args(struct Options *opt, int argc, char **argv) { +enum OptionsParseResult options_parse_args(struct Options *opt, int argc, char **argv) { int c = 0; while ((c = getopt(argc, argv, "a:c:p:du:g:b:i:4r:e:t:l:vxqm:s:C:F:hV")) != -1) { switch (c) { @@ -105,7 +96,7 @@ int options_parse_args(struct Options *opt, int argc, char **argv) { } else { printf("HTTP version already set to: HTTP/%s\n", opt->use_http_version == 1 ? "1.1" : "3"); - return -1; + return OPR_OPTION_ERROR; } break; case 'm': @@ -120,24 +111,21 @@ int options_parse_args(struct Options *opt, int argc, char **argv) { case 'F': // Flight recorder size opt->flight_recorder_size = atoi(optarg); break; - case '?': - printf("Unknown option '-%c'\n", c); - // fallthrough case 'h': - return -1; + return OPR_HELP; case 'V': // version - printf("%s\n", options_sw_version()); - exit(0); + return OPR_VERSION; + case '?': default: - printf("Unknown state!"); - exit(EXIT_FAILURE); + return OPR_PARSING_ERROR; } } + if (opt->user) { struct passwd *p = getpwnam(opt->user); if (!p || !p->pw_uid) { printf("Username (%s) invalid.\n", opt->user); - return -1; + return OPR_OPTION_ERROR; } opt->uid = p->pw_uid; } @@ -145,13 +133,13 @@ int options_parse_args(struct Options *opt, int argc, char **argv) { struct group *g = getgrnam(opt->group); if (!g || !g->gr_gid) { printf("Group (%s) invalid.\n", opt->group); - return -1; + return OPR_OPTION_ERROR; } opt->gid = g->gr_gid; } if (opt->dscp < 0 || opt->dscp >63) { printf("DSCP code (%d) invalid:[0-63]\n", opt->dscp); - return -1; + return OPR_OPTION_ERROR; } opt->dscp <<= 2; // Get noisy about bad security practices. @@ -174,28 +162,28 @@ int options_parse_args(struct Options *opt, int argc, char **argv) { strncmp(opt->resolver_url, "https://", 8) != 0) { printf("Resolver prefix (%s) must be a https:// address.\n", opt->resolver_url); - return -1; + return OPR_OPTION_ERROR; } if (opt->bootstrap_dns_polling_interval < 5 || opt->bootstrap_dns_polling_interval > 3600) { printf("DNS servers polling interval must be between 5 and 3600.\n"); - return -1; + return OPR_OPTION_ERROR; } if (opt->max_idle_time < 0 || opt->max_idle_time > 3600) { printf("Maximum idle time must be between 0 and 3600.\n"); - return -1; + return OPR_OPTION_ERROR; } if (opt->stats_interval < 0 || opt->stats_interval > 3600) { printf("Statistic interval must be between 0 and 3600.\n"); - return -1; + return OPR_OPTION_ERROR; } if (opt->flight_recorder_size != 0 && (opt->flight_recorder_size < 100 || opt->flight_recorder_size > 100000)) { printf("Flight recorder limit must be between 100 and 100000.\n"); - return -1; + return OPR_OPTION_ERROR; } - return 0; + return OPR_SUCCESS; } void options_show_usage(int __attribute__((unused)) argc, char **argv) { @@ -254,7 +242,7 @@ void options_show_usage(int __attribute__((unused)) argc, char **argv) { " in memory and dumping them on fatal error or on SIGUSR2 signal.\n" " (Default: %u, Disabled: 0, Min: 100, Max: 100000)\n", defaults.flight_recorder_size); - printf(" -V Print version and exit.\n"); + printf(" -V Print versions and exit.\n"); printf(" -h Print help and exit.\n"); options_cleanup(&defaults); } diff --git a/src/options.h b/src/options.h index 9f6b3dc..b303ac0 100644 --- a/src/options.h +++ b/src/options.h @@ -59,12 +59,19 @@ struct Options { } __attribute__((aligned(128))); typedef struct Options options_t; +enum OptionsParseResult { + OPR_SUCCESS, + OPR_HELP, + OPR_VERSION, + OPR_OPTION_ERROR, + OPR_PARSING_ERROR +}; + #ifdef __cplusplus extern "C" { #endif -const char * options_sw_version(void); void options_init(struct Options *opt); -int options_parse_args(struct Options *opt, int argc, char **argv); +enum OptionsParseResult options_parse_args(struct Options *opt, int argc, char **argv); void options_show_usage(int argc, char **argv); void options_cleanup(struct Options *opt); #ifdef __cplusplus