View | Details | Raw Unified | Return to bug 787 | Differences between
and this patch

Collapse All | Expand All

(-)b/doc/unbound.conf.5.in (-1 / +13 lines)
 Lines 127-133   Detect source interface on UDP queries and copy them to replies. This Link Here 
127
feature is experimental, and needs support in your OS for particular socket
127
feature is experimental, and needs support in your OS for particular socket
128
options.  Default value is no.
128
options.  Default value is no.
129
.TP
129
.TP
130
.B outgoing\-interface: \fI<ip address>
130
.B outgoing\-interface: \fI<ip address or ip6 netblock>
131
Interface to use to connect to the network. This interface is used to send
131
Interface to use to connect to the network. This interface is used to send
132
queries to authoritative servers and receive their replies. Can be given 
132
queries to authoritative servers and receive their replies. Can be given 
133
multiple times to work on several interfaces. If none are given the 
133
multiple times to work on several interfaces. If none are given the 
 Lines 137-142   and Link Here 
137
.B outgoing\-interface:
137
.B outgoing\-interface:
138
lines, the interfaces are then used for both purposes. Outgoing queries are 
138
lines, the interfaces are then used for both purposes. Outgoing queries are 
139
sent via a random outgoing interface to counter spoofing.
139
sent via a random outgoing interface to counter spoofing.
140
.IP
141
If an IPv6 netblock is specified instead of an individual IPv6 address,
142
outgoing UDP queries will use a randomised source address taken from the
143
netblock to counter spoofing. Requires the IPv6 netblock to be routed to the
144
host running unbound, and requires OS support for unprivileged non-local binds
145
(currently only supported on Linux). Several netblocks may be specified with
146
multiple
147
.B outgoing\-interface:
148
options, but do not specify both an individual IPv6 address and an IPv6
149
netblock, or the randomisation will be compromised.  Consider combining with
150
.B prefer\-ip6: yes
151
to increase the likelihood of IPv6 nameservers being selected for queries.
140
.TP
152
.TP
141
.B outgoing\-range: \fI<number>
153
.B outgoing\-range: \fI<number>
142
Number of ports to open. This number of file descriptors can be opened per 
154
Number of ports to open. This number of file descriptors can be opened per 
(-)b/services/listen_dnsport.c (-8 / +8 lines)
 Lines 184-197   create_udp_sock(int family, int socktype, struct sockaddr* addr, Link Here 
184
#else
184
#else
185
		(void)reuseport;
185
		(void)reuseport;
186
#endif /* defined(SO_REUSEPORT) */
186
#endif /* defined(SO_REUSEPORT) */
187
#ifdef IP_FREEBIND
188
		if (freebind &&
189
		    setsockopt(s, IPPROTO_IP, IP_FREEBIND, (void*)&on,
190
		    (socklen_t)sizeof(on)) < 0) {
191
			log_warn("setsockopt(.. IP_FREEBIND ..) failed: %s",
192
			strerror(errno));
193
		}
194
#endif /* IP_FREEBIND */
195
#ifdef IP_TRANSPARENT
187
#ifdef IP_TRANSPARENT
196
		if (transparent &&
188
		if (transparent &&
197
		    setsockopt(s, IPPROTO_IP, IP_TRANSPARENT, (void*)&on,
189
		    setsockopt(s, IPPROTO_IP, IP_TRANSPARENT, (void*)&on,
 Lines 209-214   create_udp_sock(int family, int socktype, struct sockaddr* addr, Link Here 
209
		}
201
		}
210
#endif /* IP_TRANSPARENT || IP_BINDANY */
202
#endif /* IP_TRANSPARENT || IP_BINDANY */
211
	}
203
	}
204
#ifdef IP_FREEBIND
205
	if(freebind &&
206
	    setsockopt(s, IPPROTO_IP, IP_FREEBIND, (void*)&on,
207
	    (socklen_t)sizeof(on)) < 0) {
208
		log_warn("setsockopt(.. IP_FREEBIND ..) failed: %s",
209
		strerror(errno));
210
	}
211
#endif /* IP_FREEBIND */
212
	if(rcv) {
212
	if(rcv) {
213
#ifdef SO_RCVBUF
213
#ifdef SO_RCVBUF
214
		int got;
214
		int got;
(-)b/services/outside_network.c (-8 / +34 lines)
 Lines 591-597   static int setup_if(struct port_if* pif, const char* addrstr, Link Here 
591
	pif->avail_ports = (int*)memdup(avail, (size_t)numavail*sizeof(int));
591
	pif->avail_ports = (int*)memdup(avail, (size_t)numavail*sizeof(int));
592
	if(!pif->avail_ports)
592
	if(!pif->avail_ports)
593
		return 0;
593
		return 0;
594
	if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen))
594
	if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen) &&
595
	   !netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT,
596
			      &pif->addr, &pif->addrlen, &pif->pfxlen))
595
		return 0;
597
		return 0;
596
	pif->maxout = (int)numfd;
598
	pif->maxout = (int)numfd;
597
	pif->inuse = 0;
599
	pif->inuse = 0;
 Lines 893-918   pending_delete(struct outside_network* outnet, struct pending* p) Link Here 
893
	free(p);
895
	free(p);
894
}
896
}
895
897
898
static void
899
sai6_putrandom(struct sockaddr_in6 *sa, int pfxlen, struct ub_randstate *rnd)
900
{
901
	int i, last;
902
	if(!(pfxlen > 0 && pfxlen < 128))
903
		return;
904
	for(i = 0; i < (128 - pfxlen) / 8; i++) {
905
		sa->sin6_addr.s6_addr[15-i] = ub_random_max(rnd, 256);
906
	}
907
	last = pfxlen & 7;
908
	if(last != 0) {
909
		sa->sin6_addr.s6_addr[15-i] |=
910
			((0xFF >> last) & ub_random_max(rnd, 256));
911
	}
912
}
913
896
/**
914
/**
897
 * Try to open a UDP socket for outgoing communication.
915
 * Try to open a UDP socket for outgoing communication.
898
 * Sets sockets options as needed.
916
 * Sets sockets options as needed.
899
 * @param addr: socket address.
917
 * @param addr: socket address.
900
 * @param addrlen: length of address.
918
 * @param addrlen: length of address.
919
 * @param pfxlen: length of network prefix (for address randomisation).
901
 * @param port: port override for addr.
920
 * @param port: port override for addr.
902
 * @param inuse: if -1 is returned, this bool means the port was in use.
921
 * @param inuse: if -1 is returned, this bool means the port was in use.
922
 * @param rnd: random state (for address randomisation).
903
 * @return fd or -1
923
 * @return fd or -1
904
 */
924
 */
905
static int
925
static int
906
udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int port, 
926
udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen,
907
	int* inuse)
927
	int port, int* inuse, struct ub_randstate* rnd)
908
{
928
{
909
	int fd, noproto;
929
	int fd, noproto;
910
	if(addr_is_ip6(addr, addrlen)) {
930
	if(addr_is_ip6(addr, addrlen)) {
911
		struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
931
		int freebind = 0;
912
		sa->sin6_port = (in_port_t)htons((uint16_t)port);
932
		struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
933
		sa.sin6_port = (in_port_t)htons((uint16_t)port);
934
		if(pfxlen != 0) {
935
			freebind = 1;
936
			sai6_putrandom(&sa, pfxlen, rnd);
937
		}
913
		fd = create_udp_sock(AF_INET6, SOCK_DGRAM, 
938
		fd = create_udp_sock(AF_INET6, SOCK_DGRAM, 
914
			(struct sockaddr*)addr, addrlen, 1, inuse, &noproto,
939
			(struct sockaddr*)&sa, addrlen, 1, inuse, &noproto,
915
			0, 0, 0, NULL, 0, 0);
940
			0, 0, 0, NULL, 0, freebind);
916
	} else {
941
	} else {
917
		struct sockaddr_in* sa = (struct sockaddr_in*)addr;
942
		struct sockaddr_in* sa = (struct sockaddr_in*)addr;
918
		sa->sin_port = (in_port_t)htons((uint16_t)port);
943
		sa->sin_port = (in_port_t)htons((uint16_t)port);
 Lines 978-984   select_ifport(struct outside_network* outnet, struct pending* pend, Link Here 
978
		/* try to open new port, if fails, loop to try again */
1003
		/* try to open new port, if fails, loop to try again */
979
		log_assert(pif->inuse < pif->maxout);
1004
		log_assert(pif->inuse < pif->maxout);
980
		portno = pif->avail_ports[my_port - pif->inuse];
1005
		portno = pif->avail_ports[my_port - pif->inuse];
981
		fd = udp_sockport(&pif->addr, pif->addrlen, portno, &inuse);
1006
		fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen,
1007
			portno, &inuse, outnet->rnd);
982
		if(fd == -1 && !inuse) {
1008
		if(fd == -1 && !inuse) {
983
			/* nonrecoverable error making socket */
1009
			/* nonrecoverable error making socket */
984
			return 0;
1010
			return 0;
(-)b/services/outside_network.h (+4 lines)
 Lines 165-170   struct port_if { Link Here 
165
	/** length of addr field */
165
	/** length of addr field */
166
	socklen_t addrlen;
166
	socklen_t addrlen;
167
167
168
	/** prefix length of network address (in bits), for randomisation.
169
	 * if 0, no randomisation. */
170
	int pfxlen;
171
168
	/** the available ports array. These are unused.
172
	/** the available ports array. These are unused.
169
	 * Only the first total-inuse part is filled. */
173
	 * Only the first total-inuse part is filled. */
170
	int* avail_ports;
174
	int* avail_ports;
(-)b/smallapp/unbound-checkconf.c (-3 / +3 lines)
 Lines 161-166   warn_hosts(const char* typ, struct config_stub* list) Link Here 
161
static void
161
static void
162
interfacechecks(struct config_file* cfg)
162
interfacechecks(struct config_file* cfg)
163
{
163
{
164
	int d;
164
	struct sockaddr_storage a;
165
	struct sockaddr_storage a;
165
	socklen_t alen;
166
	socklen_t alen;
166
	int i, j;
167
	int i, j;
 Lines 177-184   interfacechecks(struct config_file* cfg) Link Here 
177
		}
178
		}
178
	}
179
	}
179
	for(i=0; i<cfg->num_out_ifs; i++) {
180
	for(i=0; i<cfg->num_out_ifs; i++) {
180
		if(!ipstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT, 
181
		if(!ipstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT, &a, &alen) &&
181
			&a, &alen)) {
182
		   !netblockstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT, &a, &alen, &d)) {
182
			fatal_exit("cannot parse outgoing-interface "
183
			fatal_exit("cannot parse outgoing-interface "
183
				"specified as '%s'", cfg->out_ifs[i]);
184
				"specified as '%s'", cfg->out_ifs[i]);
184
		}
185
		}
185
- 

Return to bug 787