1
autofs-5.0.5 - replace GPLv3 code
3
From: Ian Kent <raven@themaw.net>
5
The code to get SRV records from DNS was taken from Samba.
6
Samba is a GPLv3 licensed work which forces autofs to GPLv3.
8
I don't know enough about GPLv3 to know if that is a good thing
9
but I also don't like autofs being forced to GPLv3 because one
10
of the copyright holders won't grant permission to use the code
11
under a GPLv2 license.
15
modules/dclist.c | 590 +++++++++++++++++-------------------------------------
16
2 files changed, 192 insertions(+), 399 deletions(-)
19
diff --git a/CHANGELOG b/CHANGELOG
20
index b9d8299..347d7d7 100644
24
- fix prune cache valid check.
25
- fix mountd vers retry.
27
+- replace GPLv3 code.
29
03/09/2009 autofs-5.0.5
30
-----------------------
31
diff --git a/modules/dclist.c b/modules/dclist.c
32
index 967581c..aeb107f 100644
33
--- a/modules/dclist.c
34
+++ b/modules/dclist.c
37
- * Copyright 2009 Ian Kent <raven@themaw.net>
38
- * Copyright 2009 Red Hat, Inc.
40
- * This module was apapted from code contained in the Samba distribution
41
- * file source/libads/dns.c which contained the following copyright
44
- * Unix SMB/CIFS implementation.
45
- * DNS utility library
46
- * Copyright (C) Gerald (Jerry) Carter 2006.
47
- * Copyright (C) Jeremy Allison 2007.
48
+ * Copyright 2011 Ian Kent <raven@themaw.net>
49
+ * Copyright 2011 Red Hat, Inc.
51
* This program is free software; you can redistribute it and/or modify
52
* it under the terms of the GNU General Public License as published by
53
- * the Free Software Foundation; either version 3 of the License, or
54
+ * the Free Software Foundation, either version 2 of the License, or
55
* (at your option) any later version.
57
* This program is distributed in the hope that it will be useful,
59
* along with this program. If not, see <http://www.gnu.org/licenses/>.
62
+#include <sys/types.h>
63
#include <netinet/in.h>
64
+#include <arpa/inet.h>
65
#include <arpa/nameser.h>
69
#include "automount.h"
72
-#define MAX_DNS_PACKET_SIZE 0xffff
73
-#define MAX_DNS_NAME_LENGTH MAXHOSTNAMELEN
74
-/* The longest time we will cache dns srv records */
75
-#define MAX_TTL (60*60*1) /* 1 hours */
77
-#ifdef NS_HFIXEDSZ /* Bind 8/9 interface */
78
-#if !defined(C_IN) /* AIX 5.3 already defines C_IN */
79
-# define C_IN ns_c_in
81
-#if !defined(T_A) /* AIX 5.3 already defines T_A */
85
-# define T_SRV ns_t_srv
86
-#if !defined(T_NS) /* AIX 5.3 already defines T_NS */
87
-# define T_NS ns_t_ns
91
-# define NS_HFIXEDSZ HFIXEDSZ
93
-# define NS_HFIXEDSZ sizeof(HEADER)
94
-# endif /* HFIXEDSZ */
96
-# define NS_PACKETSZ PACKETSZ
97
-# else /* 512 is usually the default */
98
-# define NS_PACKETSZ 512
99
-# endif /* PACKETSZ */
103
-#define SVAL(buf, pos) (*(const uint16_t *)((const char *)(buf) + (pos)))
104
-#define IVAL(buf, pos) (*(const uint32_t *)((const char *)(buf) + (pos)))
106
-#if __BYTE_ORDER == __LITTLE_ENDIAN
107
-#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
108
-#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
114
-#define RSVAL(buf, pos) SREV(SVAL(buf, pos))
115
-#define RIVAL(buf, pos) IREV(IVAL(buf, pos))
117
-#define QSORT_CAST (int (*)(const void *, const void *))
119
-/* DNS query section in replies */
122
- const char *hostname;
127
-/* DNS RR record in reply */
128
+#define MAX_TTL (60*60) /* 1 hour */
131
- const char *hostname;
139
+ unsigned int class;
147
- const char *hostname;
154
+ unsigned int priority;
155
+ unsigned int weight;
160
static pthread_mutex_t dclist_mutex = PTHREAD_MUTEX_INITIALIZER;
161
@@ -133,374 +67,224 @@ static void dclist_mutex_unlock(void)
165
-static int dns_parse_query(unsigned int logopt,
166
- uint8_t *start, uint8_t *end,
167
- uint8_t **ptr, struct dns_query *q)
168
+static int do_srv_query(unsigned int logopt, char *name, u_char **packet)
171
- char hostname[MAX_DNS_NAME_LENGTH];
172
- char buf[MAX_ERR_BUF];
175
- if (!start || !end || !q || !*ptr)
178
- memset(q, 0, sizeof(*q));
180
- /* See RFC 1035 for details. If this fails, then return. */
182
- namelen = dn_expand(start, end, p, hostname, sizeof(hostname));
184
- error(logopt, "failed to expand query hostname");
187
+ unsigned int len = PACKETSZ;
188
+ unsigned int last_len = len;
189
+ char ebuf[MAX_ERR_BUF];
193
+ buf = malloc(last_len);
195
+ char *estr = strerror_r(errno, ebuf, MAX_ERR_BUF);
196
+ error(logopt, "malloc: %s", estr);
201
- q->hostname = strdup(hostname);
203
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
204
- error(logopt, "strdup: %s", estr);
207
+ len = res_query(name, C_IN, T_SRV, buf, last_len);
209
+ char *estr = strerror_r(errno, ebuf, MAX_ERR_BUF);
210
+ error(logopt, "Failed to resolve %s (%s)", name, estr);
215
- /* check that we have space remaining */
216
+ if (len == last_len) {
217
+ /* These shouldn't too large, bump by PACKETSZ only */
218
+ last_len += PACKETSZ;
224
- error(logopt, "insufficient buffer space for result");
225
- free((void *) q->hostname);
230
- q->type = RSVAL(p, 0);
231
- q->in_class = RSVAL(p, 2);
241
-static int dns_parse_rr(unsigned int logopt,
242
- uint8_t *start, uint8_t *end,
243
- uint8_t **ptr, struct dns_rr *rr)
244
+static int get_name_len(u_char *buffer, u_char *start, u_char *end)
247
- char hostname[MAX_DNS_NAME_LENGTH];
248
- char buf[MAX_ERR_BUF];
251
- if (!start || !end || !rr || !*ptr)
254
- memset(rr, 0, sizeof(*rr));
256
- /* pull the name from the answer */
258
- namelen = dn_expand(start, end, p, hostname, sizeof(hostname));
260
- error(logopt, "failed to expand query hostname");
264
- rr->hostname = strdup(hostname);
265
- if (!rr->hostname) {
266
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
267
- error(logopt, "strdup: %s", estr);
271
- /* check that we have space remaining */
273
- if (p + 10 > end) {
274
- error(logopt, "insufficient buffer space for result");
275
- free((void *) rr->hostname);
279
- /* pull some values and then skip onto the string */
281
- rr->type = RSVAL(p, 0);
282
- rr->in_class = RSVAL(p, 2);
283
- rr->ttl = RIVAL(p, 4);
284
- rr->rdatalen = RSVAL(p, 8);
288
- /* sanity check the available space */
290
- if (p + rr->rdatalen > end) {
291
- error(logopt, "insufficient buffer space for data");
292
- free((void *) rr->hostname);
296
- /* save a point to the rdata for this section */
304
+ char tmp[MAXDNAME];
305
+ return dn_expand(buffer, end, start, tmp, MAXDNAME);
308
-static int dns_parse_rr_srv(unsigned int logopt,
309
- uint8_t *start, uint8_t *end,
310
- uint8_t **ptr, struct dns_rr_srv *srv)
311
+static int get_data_offset(u_char *buffer,
312
+ u_char *start, u_char *end,
317
- char dcname[MAX_DNS_NAME_LENGTH];
318
- char buf[MAX_ERR_BUF];
321
- if (!start || !end || !srv || !*ptr)
324
- /* Parse the RR entry. Coming out of the this, ptr is at the beginning
325
- of the next record */
327
- if (!dns_parse_rr(logopt, start, end, ptr, &rr)) {
328
- error(logopt, "Failed to parse RR record");
331
+ u_char *cp = start;
334
- if (rr.type != T_SRV) {
335
- error(logopt, "Bad answer type (%d)", rr.type);
340
+ name_len = get_name_len(buffer, start, end);
345
- srv->priority = RSVAL(p, 0);
346
- srv->weight = RSVAL(p, 2);
347
- srv->port = RSVAL(p, 4);
349
+ GETSHORT(rr->type, cp);
350
+ GETSHORT(rr->class, cp);
351
+ GETLONG(rr->ttl, cp);
352
+ GETSHORT(rr->len, cp);
355
+ return (cp - start);
358
- namelen = dn_expand(start, end, p, dcname, sizeof(dcname));
360
- error(logopt, "Failed to expand dcname");
362
+static struct srv_rr *parse_srv_rr(unsigned int logopt,
363
+ u_char *buffer, u_char *start, u_char *end,
364
+ struct rr *rr, struct srv_rr *srv)
366
+ u_char *cp = start;
367
+ char ebuf[MAX_ERR_BUF];
368
+ char tmp[MAXDNAME];
371
+ GETSHORT(srv->priority, cp);
372
+ GETSHORT(srv->weight, cp);
373
+ GETSHORT(srv->port, cp);
374
+ srv->ttl = rr->ttl;
376
+ len = dn_expand(buffer, end, cp, tmp, MAXDNAME);
378
+ error(logopt, "failed to expand name");
382
- srv->hostname = strdup(dcname);
383
- if (!srv->hostname) {
384
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
385
+ srv->name = strdup(tmp);
387
+ char *estr = strerror_r(errno, ebuf, MAX_ERR_BUF);
388
error(logopt, "strdup: %s", estr);
393
- debug(logopt, "Parsed %s [%u, %u, %u]",
394
- srv->hostname, srv->priority, srv->weight, srv->port);
400
-/*********************************************************************
401
- Sort SRV record list based on weight and priority. See RFC 2782.
402
-*********************************************************************/
404
-static int dnssrvcmp(struct dns_rr_srv *a, struct dns_rr_srv *b)
405
+static int cmp(struct srv_rr *a, struct srv_rr *b)
407
- if (a->priority == b->priority) {
408
- /* randomize entries with an equal weight and priority */
409
- if (a->weight == b->weight)
411
+ if (a->priority < b->priority)
414
- /* higher weights should be sorted lower */
415
- if (a->weight > b->weight)
420
+ if (a->priority > b->priority)
423
- if (a->priority < b->priority)
424
+ if (!a->weight || a->weight == b->weight)
427
+ if (a->weight > b->weight)
433
-#define DNS_FAILED_WAITTIME 30
435
-static int dns_send_req(unsigned int logopt,
436
- const char *name, int q_type, uint8_t **rbuf,
438
+static void free_srv_rrs(struct srv_rr *dcs, unsigned int count)
440
- uint8_t *buffer = NULL;
441
- size_t buf_len = 0;
442
- int resp_len = NS_PACKETSZ;
443
- static time_t last_dns_check = 0;
444
- static unsigned int last_dns_status = 0;
445
- time_t now = time(NULL);
446
- char buf[MAX_ERR_BUF];
448
- /* Try to prevent bursts of DNS lookups if the server is down */
450
- /* Protect against large clock changes */
452
- if (last_dns_check > now)
453
- last_dns_check = 0;
456
- /* IF we had a DNS timeout or a bad server and we are still
457
- in the 30 second cache window, just return the previous
458
- status and save the network timeout. */
460
- if ((last_dns_status == ETIMEDOUT ||
461
- last_dns_status == ECONNREFUSED) &&
462
- ((last_dns_check + DNS_FAILED_WAITTIME) > now)) {
463
- char *estr = strerror_r(last_dns_status, buf, MAX_ERR_BUF);
464
- debug(logopt, "Returning cached status (%s)", estr);
465
- return last_dns_status;
466
+ for (i = 0; i < count; i++) {
468
+ free((void *) dcs[i].name);
471
- /* Send the Query */
476
- buf_len = resp_len * sizeof(uint8_t);
479
- buffer = malloc(buf_len);
481
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
482
- error(logopt, "malloc: %s", estr);
483
- last_dns_status = ENOMEM;
484
- last_dns_check = time(NULL);
485
- return last_dns_status;
489
- resp_len = res_query(name, C_IN, q_type, buffer, buf_len);
490
- if (resp_len < 0) {
491
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
492
- error(logopt, "Failed to resolve %s (%s)", name, estr);
494
- last_dns_status = ENOENT;
495
- last_dns_check = time(NULL);
496
- return last_dns_status;
499
- /* On AIX, Solaris, and possibly some older glibc systems (e.g. SLES8)
500
- truncated replies never give back a resp_len > buflen
501
- which ends up causing DNS resolve failures on large tcp DNS replies */
503
- if (buf_len == resp_len) {
504
- if (resp_len == MAX_DNS_PACKET_SIZE) {
506
- "DNS reply too large when resolving %s",
509
- last_dns_status = EMSGSIZE;
510
- last_dns_check = time(NULL);
511
- return last_dns_status;
514
- resp_len = MIN(resp_len * 2, MAX_DNS_PACKET_SIZE);
516
- } while (buf_len < resp_len && resp_len <= MAX_DNS_PACKET_SIZE);
519
- *resp_length = resp_len;
521
- last_dns_check = time(NULL);
522
- last_dns_status = 0;
528
-static int dns_lookup_srv(unsigned int logopt, const char *name,
529
- struct dns_rr_srv **dclist, int *numdcs)
530
+int get_srv_rrs(unsigned int logopt,
531
+ char *name, struct srv_rr **dcs, unsigned int *dcs_count)
533
- uint8_t *buffer = NULL;
535
- struct dns_rr_srv *dcs = NULL;
536
- int query_count, answer_count;
537
- uint8_t *p = buffer;
540
- char buf[MAX_ERR_BUF];
542
+ struct srv_rr *srvs;
543
+ unsigned int srv_num;
548
+ unsigned int count;
550
+ char ebuf[MAX_ERR_BUF];
552
+ len = do_srv_query(logopt, name, &packet);
556
- if (!name || !dclist)
558
+ header = (HEADER *) packet;
559
+ start = packet + sizeof(HEADER);
560
+ end = packet + len;
562
- /* Send the request. May have to loop several times in case
563
- of large replies */
567
- ret = dns_send_req(logopt, name, T_SRV, &buffer, &resp_len);
569
- error(logopt, "Failed to send DNS query");
571
+ /* Skip over question */
572
+ len = get_name_len(packet, start, end);
574
+ error(logopt, "failed to get name length");
579
- /* For some insane reason, the ns_initparse() et. al. routines are only
580
- available in libresolv.a, and not the shared lib. Who knows why....
581
- So we have to parse the DNS reply ourselves */
582
+ start += len + QFIXEDSZ;
584
- /* Pull the answer RR's count from the header.
585
- * Use the NMB ordering macros */
586
+ count = ntohs(header->ancount);
588
- query_count = RSVAL(p, 4);
589
- answer_count = RSVAL(p, 6);
590
+ debug(logopt, "%d records returned in the answer section", count);
593
- "%d records returned in the answer section.",
596
+ error(logopt, "no records found in answers section");
600
- if (answer_count) {
601
- dcs = malloc(sizeof(struct dns_rr_srv) * answer_count);
603
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
604
- error(logopt, "malloc: %s", estr);
608
+ srvs = malloc(sizeof(struct srv_rr) * count);
610
+ char *estr = strerror_r(errno, ebuf, MAX_ERR_BUF);
611
+ error(logopt, "malloc: %s", estr);
614
+ memset(srvs, 0, sizeof(struct srv_rr) * count);
616
- /* now skip the header */
618
+ for (i = 0; i < count && (start < end); i++) {
619
+ unsigned int data_offset;
621
+ struct srv_rr *psrv;
625
+ memset(&rr, 0, sizeof(struct rr));
627
- /* parse the query section */
628
+ data_offset = get_data_offset(packet, start, end, &rr);
629
+ if (data_offset <= 0) {
630
+ error(logopt, "failed to get start of data");
633
+ start += data_offset;
635
- for (rrnum = 0; rrnum < query_count; rrnum++) {
636
- struct dns_query q;
637
+ if (rr.type != T_SRV)
640
- ret = dns_parse_query(logopt, buffer, buffer+resp_len, &p, &q);
643
- "Failed to parse query record [%d]", rrnum);
647
+ psrv = parse_srv_rr(logopt, packet, start, end, &rr, &srv);
649
+ memcpy(&srvs[srv_num], psrv, sizeof(struct srv_rr));
654
- /* now we are at the answer section */
659
- for (rrnum = 0; rrnum < answer_count; rrnum++) {
660
- ret = dns_parse_rr_srv(logopt,
661
- buffer, buffer+resp_len,
665
- "Failed to parse answer record [%d]", rrnum);
671
+ error(logopt, "no srv resource records found");
676
- qsort(dcs, idx, sizeof(struct dns_rr_srv), QSORT_CAST dnssrvcmp);
677
+ qsort(srvs, srv_num, sizeof(struct srv_rr),
678
+ (int (*)(const void *, const void *)) cmp);
683
+ *dcs_count = srv_num;
691
+ free_srv_rrs(srvs, srv_num);
695
@@ -553,14 +337,14 @@ void free_dclist(struct dclist *dclist)
696
static char *getdnsdomainname(unsigned int logopt)
698
struct addrinfo hints, *ni;
699
- char name[MAX_DNS_NAME_LENGTH + 1];
700
+ char name[MAXDNAME + 1];
701
char buf[MAX_ERR_BUF];
702
char *dnsdomain = NULL;
706
memset(name, 0, sizeof(name));
707
- if (gethostname(name, MAX_DNS_NAME_LENGTH) == -1) {
708
+ if (gethostname(name, MAXDNAME) == -1) {
709
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
710
error(logopt, "gethostname: %s", estr);
712
@@ -593,14 +377,12 @@ struct dclist *get_dc_list(unsigned int logopt, const char *uri)
714
LDAPURLDesc *ludlist = NULL;
716
- struct dns_rr_srv *dcs;
717
unsigned int min_ttl = MAX_TTL;
718
struct dclist *dclist = NULL;;
719
char buf[MAX_ERR_BUF];
720
char *dn_uri, *esc_uri;
726
if (strcmp(uri, "ldap:///") && strcmp(uri, "ldaps:///")) {
727
@@ -679,6 +461,8 @@ struct dclist *get_dc_list(unsigned int logopt, const char *uri)
729
for (ludp = &ludlist; *ludp != NULL;) {
730
LDAPURLDesc *lud = *ludp;
731
+ struct srv_rr *dcs = NULL;
732
+ unsigned int numdcs = 0;
734
char *request = NULL;
736
@@ -716,7 +500,7 @@ struct dclist *get_dc_list(unsigned int logopt, const char *uri)
740
- if (dns_lookup_srv(logopt, request, &dcs, &numdcs)) {
741
+ if (!get_srv_rrs(logopt, request, &dcs, &numdcs)) {
743
"DNS SRV query failed for domain %s", domain);
744
dclist_mutex_unlock();
745
@@ -733,7 +517,7 @@ struct dclist *get_dc_list(unsigned int logopt, const char *uri)
746
for (i = 0; i < numdcs; i++) {
747
if (dcs[i].ttl > 0 && dcs[i].ttl < min_ttl)
748
min_ttl = dcs[i].ttl;
749
- len += strlen(dcs[i].hostname);
750
+ len += strlen(dcs[i].name);
752
len += sizeof(":65535");
754
@@ -742,6 +526,8 @@ struct dclist *get_dc_list(unsigned int logopt, const char *uri)
756
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
757
error(logopt, "realloc: %s", estr);
759
+ free_srv_rrs(dcs, numdcs);
763
@@ -755,13 +541,15 @@ struct dclist *get_dc_list(unsigned int logopt, const char *uri)
765
strcat(tmp, lud->lud_scheme);
767
- strcat(tmp, dcs[i].hostname);
768
+ strcat(tmp, dcs[i].name);
769
if (dcs[i].port > 0) {
771
ret = snprintf(port, 7, ":%d", dcs[i].port);
774
"invalid port: %u", dcs[i].port);
776
+ free_srv_rrs(dcs, numdcs);
780
@@ -771,10 +559,14 @@ struct dclist *get_dc_list(unsigned int logopt, const char *uri)
782
*ludp = lud->lud_next;
784
+ free_srv_rrs(dcs, numdcs);
787
ldap_free_urldesc(ludlist);
792
dclist->expire = time(NULL) + min_ttl;