diff options
author | June McEnroe <june@causal.agency> | 2022-03-02 22:15:55 -0500 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2022-03-02 22:15:55 -0500 |
commit | 6e7fab70100e22ee6f585eb36388bde16003fd66 (patch) | |
tree | efa5f420b8e7768eb3b2df75494da44ed9bcff0a | |
parent | Prompt for host and port, do address lookup (diff) | |
download | catgirl-6e7fab70100e22ee6f585eb36388bde16003fd66.tar.gz catgirl-6e7fab70100e22ee6f585eb36388bde16003fd66.zip |
Implement SRV record lookup
-rw-r--r-- | enroll.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/enroll.c b/enroll.c index 7ef8e36..4ea8289 100644 --- a/enroll.c +++ b/enroll.c @@ -29,8 +29,11 @@ #include <errno.h> #include <limits.h> #include <netdb.h> +#include <netinet/in.h> +#include <resolv.h> #include <stdarg.h> #include <stdbool.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -177,8 +180,44 @@ static int getConfig(const char *configHome) { } static int srvLookup(char **host, char **port, const char *name) { - // TODO - return -1; + char dname[256]; + snprintf(dname, sizeof(dname), "_ircs._tcp.%s", name); + log("Looking up SRV record for %s", dname); + + uint8_t msg[512]; + int len = res_query(dname, 1 /* IN */, 33 /* SRV */, msg, sizeof(msg)); + if (len < 12) return -1; + + uint8_t *ptr = &msg[12]; +#define NAME_SKIP \ + for (uint8_t n; ptr < &msg[len] && (n = *ptr++); ptr += n) { \ + if (n & 0xC0) { ptr++; break; } \ + } + + uint16_t qdcount = msg[4] << 8 | msg[5]; + for (uint16_t q = 0; ptr < &msg[len] && q < qdcount; ++q) { + NAME_SKIP; // QNAME + ptr += 4; // QTYPE, QCLASS + } + + NAME_SKIP; // NAME + ptr += 14; // TYPE, CLASS, TTL, RDLENGTH, Priority, Weight + if (&msg[len] < ptr + 3) return -1; +#undef NAME_SKIP + + int n = asprintf(port, "%d", ptr[0] << 8 | ptr[1]); + if (n < 0) err(EX_OSERR, "asprintf"); + ptr += 2; + + // Name compression is not used for Target. + if (!ptr[0]) return -1; + char *host0 = (char *)&ptr[1]; + for (uint8_t n; ptr < &msg[len] && (n = *ptr); ptr += n) { + *ptr++ = '.'; + } + *host = strdup(host0); + if (!*host) err(EX_OSERR, "strdup"); + return 0; } static int getHostPort(void) { |