diff options
Diffstat (limited to 'functions.c')
-rw-r--r-- | functions.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/functions.c b/functions.c index 54e2663..35be8e4 100644 --- a/functions.c +++ b/functions.c @@ -1710,3 +1710,119 @@ void strlower(char *string) { string[i] = tolower(string[i]); } } + +// Gets a single TXT record from DNS for "dnsname" and stores the result in "record" +// Returns 1 on success or 0 on failure +// TODO: If this is ever used for more than just version checks, then it needs to do more than a single record. +int gettxtrecordsingle(char *dnsname, char *record) { + debugprint(DEBUG_FULL, "gettxtrecordsingle(): given '%s'.\n", dnsname); + + unsigned char buffer[8000] = {0}; + char result[MAXDNSTXTLEN] = {0}; + const unsigned char *presult = NULL; + struct __res_state resState = {0}; + ns_msg nsMsg = {0}; + ns_rr rr; + + int type = 0; + int ret = 0; + int size = 0; + int count = 0; + long unsigned int len = 0; + int res_init = 0; + + ret = res_ninit(&resState); + + if (ret) { + debugprint(DEBUG_CRIT, "gettxtrecordsingle(): res_ninit() returned failure (it returned %d)! Returning 0.\n", ret); + return 0; + } else { + res_init = 1; + } + + memset(buffer, 0, sizeof (buffer)); + size = res_nquery(&resState, dnsname, C_IN, T_TXT, buffer, sizeof(buffer) - 1); + + if (size < 1) { + res_nclose(&resState); + debugprint(DEBUG_CRIT, "gettxtrecordsingle(): res_nquery() returned zero-length or failure (it returend %d)! Returning 0.\n", size); + return 0; + } + + ret = ns_initparse(buffer, size, &nsMsg); + + if (ret) { + res_nclose(&resState); + debugprint(DEBUG_CRIT, "gettxtrecordsingle(): ns_initparse() returned failure (failed to parse the buffer buffer?) (it returned %d)! Returning 0.\n", ret); + return 0; + } + + count = ns_msg_count(nsMsg, ns_s_an); + + for (int i = 0; i < count; i++) { + ret = ns_parserr(&nsMsg, ns_s_an, i , &rr); + + if (ret) { + res_nclose(&resState); + return 0; + } + + type = ns_rr_type(rr); + if (ns_t_txt == type) { + len = ns_rr_rdlen(rr); + presult = ns_rr_rdata(rr); + + if ((len > 1) && (len < sizeof(result))) { + len--; + memcpy (result, presult+1, len); + result[len] = '\0'; + debugprint(DEBUG_FULL, "gettxtrecordsingle(): record '%d' from DNS is '%s'.\n", i, result); + + // Only using the first result + if (i == 0) { + strncpy(record, result, sizeof(result) - 1); + } + } + } + } + + debugprint(DEBUG_FULL, "gettxtrecordsingle(): using record '%s'.\n", result); + + if (res_init) { + res_nclose (&resState); + } + + return 1; +} + +// Gets the latest blabouncer version string from DNS and stores it in "version" +// Ignores the Git version portion (everything after the first '-') of VERSION, if present +// Returns 1 if local VERSION is current, -1 if local VERSION is not current, or 0 on failure +int checkversion(char *version) { + if (!gettxtrecordsingle(VERSIONTXTNAME, version)) { + debugprint(DEBUG_CRIT, "checkversion(): gettxtrecordsingle() failure and the buffer contains '%s', returning 0.\n", version); + return 0; + } else { + debugprint(DEBUG_FULL, "checkversion(): gettxtrecordsingle() success and the returned record is '%s'.\n", version); + } + + // Ignore the Git version portion (everything after the first '-') of VERSION, if present + char localversion[MAXDNSTXTLEN]; + strncpy(localversion, VERSION, sizeof(localversion) - 1); + + for (size_t i = 0; i < strlen(localversion); i++) { + if (localversion[i] == '-') { + localversion[i] = '\0'; + debugprint(DEBUG_FULL, "checkversion(): Trimmed local VERSION string to '%s'.\n", localversion); + break; + } + } + + if (strncmp(localversion, version, sizeof(localversion))) { + debugprint(DEBUG_SOME, "checkversion(): Returned version '%s' doesn't match expected '%s', returning -1.\n", version, localversion); + return -1; + } else { + debugprint(DEBUG_FULL, "checkversion(): Returned version '%s' matches expected '%s', returning 1.\n", version, localversion); + return 1; + } +} |