]>
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
, const char* domain
, time_t* t
) {
47 // Initialise the resolver
50 ERROR(ctx
, "res_init() failed\n");
54 // Fall back to default domain
56 domain
= LOC_DATABASE_DOMAIN_LATEST(LOC_DATABASE_VERSION
);
58 unsigned char answer
[PACKETSZ
];
61 DEBUG(ctx
, "Querying %s\n", domain
);
64 if ((len
= res_query(domain
, C_IN
, T_TXT
, answer
, sizeof(answer
))) < 0 || len
> PACKETSZ
) {
65 ERROR(ctx
, "Could not query %s: \n", domain
);
70 unsigned char* end
= answer
+ len
;
71 unsigned char* payload
= answer
+ sizeof(HEADER
);
75 if ((len
= dn_expand(answer
, end
, payload
, host
, sizeof(host
))) < 0) {
76 ERROR(ctx
, "dn_expand() failed\n");
80 // Payload starts after hostname
83 if (payload
> end
- 4) {
84 ERROR(ctx
, "DNS reply too short\n");
89 GETSHORT(type
, payload
);
91 ERROR(ctx
, "DNS reply of unexpected type: %d\n", type
);
98 // Walk through CNAMEs
99 unsigned int size
= 0;
104 if ((len
= dn_expand(answer
, end
, payload
, host
, sizeof(host
))) < 0) {
105 ERROR(ctx
, "dn_expand() failed\n");
111 if (payload
> end
- 10) {
112 ERROR(ctx
, "DNS reply too short\n");
116 // Skip type, class, ttl
117 GETSHORT(type
, payload
);
119 GETLONG(ttl
, payload
);
122 GETSHORT(size
, payload
);
123 if (payload
+ size
< answer
|| payload
+ size
> end
) {
124 ERROR(ctx
, "DNS RR overflow\n");
127 } while (type
== T_CNAME
);
130 ERROR(ctx
, "Not a TXT record\n");
134 if (!size
|| (len
= *payload
) >= size
|| !len
) {
135 ERROR(ctx
, "Broken TXT record (len = %d, size = %d)\n", len
, size
);
139 // Get start of the string
140 unsigned char* txt
= payload
+ 1;
143 DEBUG(ctx
, "Resolved to: %s\n", txt
);
146 r
= parse_timestamp(txt
, t
);