summaryrefslogtreecommitdiffstats
path: root/bind97-rh714049.patch
blob: 77ed80687575697ca5d7b655b576cd0b67e012df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
diff -up bind-9.7.3-P3/bin/nsupdate/nsupdate.c.rh714049 bind-9.7.3-P3/bin/nsupdate/nsupdate.c
--- bind-9.7.3-P3/bin/nsupdate/nsupdate.c.rh714049	2011-08-12 14:17:39.520175003 +0200
+++ bind-9.7.3-P3/bin/nsupdate/nsupdate.c	2011-08-12 15:11:01.812173573 +0200
@@ -109,6 +109,13 @@ extern int h_errno;
 
 #define DNSDEFAULTPORT 53
 
+/*
+ * Assume that bind9_getaddresses returns IPv6 and IPv4 addrs
+ * so when master server is not reachable via IPv6
+ * we can switch to IPv4.
+ */
+#define MAX_SERVERADDRS 4
+
 static isc_uint16_t dnsport = DNSDEFAULTPORT;
 
 #ifndef RESOLV_CONF
@@ -151,6 +158,8 @@ static isc_sockaddr_t *servers;
 static int ns_inuse = 0;
 static int ns_total = 0;
 static isc_sockaddr_t *userserver = NULL;
+static int curserver = 0;
+static int userservers = 0;
 static isc_sockaddr_t *localaddr = NULL;
 static isc_sockaddr_t *serveraddr = NULL;
 static isc_sockaddr_t tempaddr;
@@ -703,7 +712,8 @@ doshutdown(void) {
 	isc_task_detach(&global_task);
 
 	if (userserver != NULL)
-		isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t));
+		isc_mem_put(mctx, userserver,
+			    MAX_SERVERADDRS * sizeof(isc_sockaddr_t));
 
 	if (localaddr != NULL)
 		isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t));
@@ -914,17 +924,21 @@ setup_system(void) {
 }
 
 static void
-get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
+get_addresses(char *host, in_port_t port, isc_sockaddr_t *sockaddr, int *naddrs) {
 	int count;
 	isc_result_t result;
 
 	isc_app_block();
-	result = bind9_getaddresses(host, port, sockaddr, 1, &count);
+	result = bind9_getaddresses(host, port, sockaddr,
+				    (naddrs == NULL) ? 1 : MAX_SERVERADDRS, &count);
 	isc_app_unblock();
 	if (result != ISC_R_SUCCESS)
 		fatal("couldn't get address for '%s': %s",
 		      host, isc_result_totext(result));
-	INSIST(count == 1);
+	if (naddrs == NULL)
+		INSIST(count == 1);
+	else
+		*naddrs = count;
 }
 
 #define PARSE_ARGS_FMT "dDML:y:ghlovk:p:rR::t:u:"
@@ -1364,12 +1378,14 @@ evaluate_server(char *cmdline) {
 	}
 
 	if (userserver == NULL) {
-		userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
+		userserver = isc_mem_get(mctx,
+					 MAX_SERVERADDRS * sizeof(isc_sockaddr_t));
 		if (userserver == NULL)
 			fatal("out of memory");
 	}
 
-	get_address(server, (in_port_t)port, userserver);
+	memset(userserver, 0, MAX_SERVERADDRS * sizeof(isc_sockaddr_t));
+	get_addresses(server, (in_port_t)port, userserver, &userservers);
 
 	return (STATUS_MORE);
 }
@@ -2207,19 +2223,25 @@ recvsoa(isc_task_t *task, isc_event_t *e
 
 	if (eresult != ISC_R_SUCCESS) {
 		char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+		isc_sockaddr_t *server;
 
 		isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
 		fprintf(stderr, "; Communication with %s failed: %s\n",
 			addrbuf, isc_result_totext(eresult));
-		if (userserver != NULL)
-			fatal("could not talk to specified name server");
-		else if (++ns_inuse >= lwconf->nsnext)
+		if (userserver != NULL) {
+			if (++curserver == MAX_SERVERADDRS)
+				fatal("could not talk to specified name server");
+			else
+				ddebug("recvsoa: trying next server");
+		} else if (++ns_inuse >= lwconf->nsnext)
 			fatal("could not talk to any default name server");
 		ddebug("Destroying request [%p]", request);
 		dns_request_destroy(&request);
 		dns_message_renderreset(soaquery);
 		dns_message_settsigkey(soaquery, NULL);
-		sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
+		server = (userserver != NULL) ? &userserver[curserver] :
+						&servers[ns_inuse];
+		sendrequest(localaddr, server, soaquery, &request);
 		isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
 		isc_event_free(&event);
 		setzoneclass(dns_rdataclass_none);
@@ -2351,7 +2373,7 @@ recvsoa(isc_task_t *task, isc_event_t *e
 	}
 
 	if (userserver != NULL)
-		serveraddr = userserver;
+		serveraddr = &userserver[curserver];
 	else {
 		char serverstr[DNS_NAME_MAXTEXT+1];
 		isc_buffer_t buf;
@@ -2360,7 +2382,7 @@ recvsoa(isc_task_t *task, isc_event_t *e
 		result = dns_name_totext(&master, ISC_TRUE, &buf);
 		check_result(result, "dns_name_totext");
 		serverstr[isc_buffer_usedlength(&buf)] = 0;
-		get_address(serverstr, dnsport, &tempaddr);
+		get_addresses(serverstr, dnsport, &tempaddr, NULL);
 		serveraddr = &tempaddr;
 	}
 	dns_rdata_freestruct(&soa);
@@ -2464,9 +2486,9 @@ start_gssrequest(dns_name_t *master)
 			fatal("out of memory");
 	}
 	if (userserver == NULL)
-		get_address(namestr, dnsport, kserver);
+		get_addresses(namestr, dnsport, kserver, NULL);
 	else
-		(void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t));
+		(void)memcpy(kserver, &userserver[curserver], sizeof(isc_sockaddr_t));
 
 	dns_fixedname_init(&fname);
 	servname = dns_fixedname_name(&fname);
@@ -2594,15 +2616,17 @@ recvgss(isc_task_t *task, isc_event_t *e
 		isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
 		fprintf(stderr, "; Communication with %s failed: %s\n",
 			addrbuf, isc_result_totext(eresult));
-		if (userserver != NULL)
+		if (userserver != NULL) {
 			fatal("could not talk to specified name server");
-		else if (++ns_inuse >= lwconf->nsnext)
+		} else if (++ns_inuse >= lwconf->nsnext)
 			fatal("could not talk to any default name server");
 		ddebug("Destroying request [%p]", request);
 		dns_request_destroy(&request);
 		dns_message_renderreset(tsigquery);
-		sendrequest(localaddr, &servers[ns_inuse], tsigquery,
-			    &request);
+		sendrequest(localaddr,
+			    (userserver != NULL) ? &userserver[curserver] :
+						   &servers[ns_inuse],
+			    tsigquery, &request);
 		isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
 		isc_event_free(&event);
 		return;