]>
git.ipfire.org Git - people/ms/libloc.git/blob - src/resolv.c
2 libloc - A library to determine the location of someone on the Internet
4 Copyright (C) 2019 IPFire Development Team <info@ipfire.org>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
17 #include <arpa/nameser.h>
18 #include <arpa/nameser_compat.h>
23 #include <loc/format.h>
24 #include <loc/private.h>
25 #include <loc/resolv.h>
27 static int parse_timestamp(const unsigned char* txt
, time_t* t
) {
31 char* p
= strptime((const char*)txt
, "%a, %d %b %Y %H:%M:%S GMT", &ts
);
33 // If the whole string has been parsed, we convert the parse value to time_t
37 // Otherwise we reset t
46 LOC_EXPORT
int loc_discover_latest_version(struct loc_ctx
* ctx
,
47 unsigned int version
, time_t* t
) {
48 // Initialise the resolver
51 ERROR(ctx
, "res_init() failed\n");
57 snprintf(domain
, 63, LOC_DATABASE_DOMAIN
, version
);
59 unsigned char answer
[PACKETSZ
];
62 DEBUG(ctx
, "Querying %s\n", domain
);
65 if ((len
= res_query(domain
, C_IN
, T_TXT
, answer
, sizeof(answer
))) < 0 || len
> PACKETSZ
) {
66 ERROR(ctx
, "Could not query %s: \n", domain
);
71 unsigned char* end
= answer
+ len
;
72 unsigned char* payload
= answer
+ sizeof(HEADER
);
76 if ((len
= dn_expand(answer
, end
, payload
, host
, sizeof(host
))) < 0) {
77 ERROR(ctx
, "dn_expand() failed\n");
81 // Payload starts after hostname
84 if (payload
> end
- 4) {
85 ERROR(ctx
, "DNS reply too short\n");
90 GETSHORT(type
, payload
);
92 ERROR(ctx
, "DNS reply of unexpected type: %d\n", type
);
99 // Walk through CNAMEs
100 unsigned int size
= 0;
101 int ttl
__attribute__ ((unused
));
105 if ((len
= dn_expand(answer
, end
, payload
, host
, sizeof(host
))) < 0) {
106 ERROR(ctx
, "dn_expand() failed\n");
112 if (payload
> end
- 10) {
113 ERROR(ctx
, "DNS reply too short\n");
117 // Skip type, class, ttl
118 GETSHORT(type
, payload
);
120 GETLONG(ttl
, payload
);
123 GETSHORT(size
, payload
);
124 if (payload
+ size
< answer
|| payload
+ size
> end
) {
125 ERROR(ctx
, "DNS RR overflow\n");
128 } while (type
== T_CNAME
);
131 ERROR(ctx
, "Not a TXT record\n");
135 if (!size
|| (len
= *payload
) >= size
|| !len
) {
136 ERROR(ctx
, "Broken TXT record (len = %d, size = %d)\n", len
, size
);
140 // Get start of the string
141 unsigned char* txt
= payload
+ 1;
144 DEBUG(ctx
, "Resolved to: %s\n", txt
);
147 r
= parse_timestamp(txt
, t
);