mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-01-18 04:32:54 -05:00
Added -b / source address option to smallapp/unbound-anchor.c
This commit is contained in:
parent
13d96540de
commit
b966dd8e06
2 changed files with 51 additions and 21 deletions
|
|
@ -69,6 +69,10 @@ The server name, it connects to https://name. Specify without https:// prefix.
|
|||
The default is "data.iana.org". It connects to the port specified with \-P.
|
||||
You can pass an IPv4 address or IPv6 address (no brackets) if you want.
|
||||
.TP
|
||||
.B \-b \fIaddress
|
||||
The source address to bind to for domain resolution and contacting the server
|
||||
on https. May be either an IPv4 address or IPv6 address (no brackets).
|
||||
.TP
|
||||
.B \-x \fIpath
|
||||
The pathname to the root\-anchors.xml file on the server. (forms URL with \-u).
|
||||
The default is /root\-anchors/root\-anchors.xml.
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ usage(void)
|
|||
printf("-x path pathname to xml in url, default %s\n", XMLNAME);
|
||||
printf("-s path pathname to p7s in url, default %s\n", P7SNAME);
|
||||
printf("-n name signer's subject emailAddress, default %s\n", P7SIGNER);
|
||||
printf("-b address source address to bind to\n");
|
||||
printf("-4 work using IPv4 only\n");
|
||||
printf("-6 work using IPv6 only\n");
|
||||
printf("-f resolv.conf use given resolv.conf\n");
|
||||
|
|
@ -277,7 +278,7 @@ ub_ctx_error_exit(struct ub_ctx* ctx, const char* str, const char* str2)
|
|||
*/
|
||||
static struct ub_ctx*
|
||||
create_unbound_context(const char* res_conf, const char* root_hints,
|
||||
const char* debugconf, int ip4only, int ip6only)
|
||||
const char* debugconf, const char* srcaddr, int ip4only, int ip6only)
|
||||
{
|
||||
int r;
|
||||
struct ub_ctx* ctx = ub_ctx_create();
|
||||
|
|
@ -301,6 +302,10 @@ create_unbound_context(const char* res_conf, const char* root_hints,
|
|||
r = ub_ctx_set_option(ctx, "root-hints:", root_hints);
|
||||
if(r) ub_ctx_error_exit(ctx, root_hints, ub_strerror(r));
|
||||
}
|
||||
if(srcaddr) {
|
||||
r = ub_ctx_set_option(ctx, "outgoing-interface:", srcaddr);
|
||||
if(r) ub_ctx_error_exit(ctx, srcaddr, ub_strerror(r));
|
||||
}
|
||||
if(ip4only) {
|
||||
r = ub_ctx_set_option(ctx, "do-ip6:", "no");
|
||||
if(r) ub_ctx_error_exit(ctx, "ip4only", ub_strerror(r));
|
||||
|
|
@ -627,7 +632,8 @@ parse_ip_addr(const char* str, int port)
|
|||
*/
|
||||
static struct ip_list*
|
||||
resolve_name(const char* host, int port, const char* res_conf,
|
||||
const char* root_hints, const char* debugconf, int ip4only, int ip6only)
|
||||
const char* root_hints, const char* debugconf,
|
||||
const char* srcaddr, int ip4only, int ip6only)
|
||||
{
|
||||
struct ub_ctx* ctx;
|
||||
struct ip_list* list = NULL;
|
||||
|
|
@ -638,7 +644,7 @@ resolve_name(const char* host, int port, const char* res_conf,
|
|||
|
||||
/* create resolver context */
|
||||
ctx = create_unbound_context(res_conf, root_hints, debugconf,
|
||||
ip4only, ip6only);
|
||||
srcaddr, ip4only, ip6only);
|
||||
|
||||
/* try resolution of A */
|
||||
if(!ip6only) {
|
||||
|
|
@ -728,7 +734,7 @@ print_sock_err(const char* msg)
|
|||
|
||||
/** connect to IP address */
|
||||
static int
|
||||
connect_to_ip(struct ip_list* ip)
|
||||
connect_to_ip(struct ip_list* ip, struct ip_list* src)
|
||||
{
|
||||
int fd;
|
||||
verb_addr("connect to", ip);
|
||||
|
|
@ -738,6 +744,11 @@ connect_to_ip(struct ip_list* ip)
|
|||
print_sock_err("socket");
|
||||
return -1;
|
||||
}
|
||||
if(src && bind(fd, (struct sockaddr*)&src->addr, src->len) < 0) {
|
||||
print_sock_err("bind");
|
||||
fd_close(fd);
|
||||
return -1;
|
||||
}
|
||||
if(connect(fd, (struct sockaddr*)&ip->addr, ip->len) < 0) {
|
||||
print_sock_err("connect");
|
||||
fd_close(fd);
|
||||
|
|
@ -1110,7 +1121,8 @@ read_http_result(SSL* ssl)
|
|||
|
||||
/** https to an IP addr, return BIO with pathname or NULL */
|
||||
static BIO*
|
||||
https_to_ip(struct ip_list* ip, const char* pathname, const char* urlname)
|
||||
https_to_ip(struct ip_list* ip, const char* pathname, const char* urlname,
|
||||
struct ip_list* src)
|
||||
{
|
||||
int fd;
|
||||
SSL* ssl;
|
||||
|
|
@ -1119,7 +1131,7 @@ https_to_ip(struct ip_list* ip, const char* pathname, const char* urlname)
|
|||
if(!sslctx) {
|
||||
return NULL;
|
||||
}
|
||||
fd = connect_to_ip(ip);
|
||||
fd = connect_to_ip(ip, src);
|
||||
if(fd == -1) {
|
||||
SSL_CTX_free(sslctx);
|
||||
return NULL;
|
||||
|
|
@ -1150,7 +1162,8 @@ https_to_ip(struct ip_list* ip, const char* pathname, const char* urlname)
|
|||
* @return a memory BIO with the file in it.
|
||||
*/
|
||||
static BIO*
|
||||
https(struct ip_list* ip_list, const char* pathname, const char* urlname)
|
||||
https(struct ip_list* ip_list, const char* pathname, const char* urlname,
|
||||
struct ip_list* src)
|
||||
{
|
||||
struct ip_list* ip;
|
||||
BIO* bio = NULL;
|
||||
|
|
@ -1158,7 +1171,7 @@ https(struct ip_list* ip_list, const char* pathname, const char* urlname)
|
|||
wipe_ip_usage(ip_list);
|
||||
while( (ip = pick_random_ip(ip_list)) ) {
|
||||
ip->used = 1;
|
||||
bio = https_to_ip(ip, pathname, urlname);
|
||||
bio = https_to_ip(ip, pathname, urlname, src);
|
||||
if(bio) break;
|
||||
}
|
||||
if(!bio) {
|
||||
|
|
@ -1913,18 +1926,27 @@ static int
|
|||
do_certupdate(const char* root_anchor_file, const char* root_cert_file,
|
||||
const char* urlname, const char* xmlname, const char* p7sname,
|
||||
const char* p7signer, const char* res_conf, const char* root_hints,
|
||||
const char* debugconf, int ip4only, int ip6only, int port)
|
||||
const char* debugconf, const char* srcaddr, int ip4only, int ip6only,
|
||||
int port)
|
||||
|
||||
{
|
||||
STACK_OF(X509)* cert;
|
||||
BIO *xml, *p7s;
|
||||
struct ip_list* ip_list = NULL;
|
||||
struct ip_list* src = NULL;
|
||||
|
||||
/* read pem file or provide builtin */
|
||||
cert = read_cert_or_builtin(root_cert_file);
|
||||
|
||||
/* lookup A, AAAA for the urlname (or parse urlname if IP address) */
|
||||
ip_list = resolve_name(urlname, port, res_conf, root_hints, debugconf,
|
||||
ip4only, ip6only);
|
||||
srcaddr, ip4only, ip6only);
|
||||
|
||||
if(srcaddr && !(src = parse_ip_addr(srcaddr, 0))) {
|
||||
if(verb) printf("cannot parse source address: %s\n", srcaddr);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
if(1) { /* libunbound finished, startup WSA for the https connection */
|
||||
|
|
@ -1940,8 +1962,8 @@ do_certupdate(const char* root_anchor_file, const char* root_cert_file,
|
|||
#endif
|
||||
|
||||
/* fetch the necessary files over HTTPS */
|
||||
xml = https(ip_list, xmlname, urlname);
|
||||
p7s = https(ip_list, p7sname, urlname);
|
||||
xml = https(ip_list, xmlname, urlname, src);
|
||||
p7s = https(ip_list, p7sname, urlname, src);
|
||||
|
||||
/* verify and update the root anchor */
|
||||
verify_and_update_anchor(root_anchor_file, xml, p7s, cert, p7signer);
|
||||
|
|
@ -2192,14 +2214,14 @@ probe_date_allows_certupdate(const char* root_anchor_file)
|
|||
|
||||
static struct ub_result *
|
||||
fetch_root_key(const char* root_anchor_file, const char* res_conf,
|
||||
const char* root_hints, const char* debugconf,
|
||||
const char* root_hints, const char* debugconf, const char* srcaddr,
|
||||
int ip4only, int ip6only)
|
||||
{
|
||||
struct ub_ctx* ctx;
|
||||
struct ub_result* dnskey;
|
||||
|
||||
ctx = create_unbound_context(res_conf, root_hints, debugconf,
|
||||
ip4only, ip6only);
|
||||
srcaddr, ip4only, ip6only);
|
||||
add_5011_probe_root(ctx, root_anchor_file);
|
||||
dnskey = prime_root_key(ctx);
|
||||
ub_ctx_delete(ctx);
|
||||
|
|
@ -2211,8 +2233,8 @@ static int
|
|||
do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
|
||||
const char* urlname, const char* xmlname, const char* p7sname,
|
||||
const char* p7signer, const char* res_conf, const char* root_hints,
|
||||
const char* debugconf, int ip4only, int ip6only, int force,
|
||||
int res_conf_fallback, int port)
|
||||
const char* debugconf, const char* srcaddr, int ip4only, int ip6only,
|
||||
int force, int res_conf_fallback, int port)
|
||||
{
|
||||
struct ub_result* dnskey;
|
||||
int used_builtin = 0;
|
||||
|
|
@ -2226,7 +2248,7 @@ do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
|
|||
/* make unbound context with 5011-probe for root anchor,
|
||||
* and probe . DNSKEY */
|
||||
dnskey = fetch_root_key(root_anchor_file, res_conf,
|
||||
root_hints, debugconf, ip4only, ip6only);
|
||||
root_hints, debugconf, srcaddr, ip4only, ip6only);
|
||||
rcode = dnskey->rcode;
|
||||
|
||||
if (res_conf_fallback && res_conf && !dnskey->secure) {
|
||||
|
|
@ -2234,7 +2256,7 @@ do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
|
|||
ub_resolve_free(dnskey);
|
||||
/* try direct query without res_conf */
|
||||
dnskey = fetch_root_key(root_anchor_file, NULL,
|
||||
root_hints, debugconf, ip4only, ip6only);
|
||||
root_hints, debugconf, srcaddr, ip4only, ip6only);
|
||||
if (rcode != 0 && dnskey->rcode == 0) {
|
||||
res_conf = NULL;
|
||||
rcode = 0;
|
||||
|
|
@ -2255,7 +2277,7 @@ do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
|
|||
probe_date_allows_certupdate(root_anchor_file)) || force) {
|
||||
if(do_certupdate(root_anchor_file, root_cert_file, urlname,
|
||||
xmlname, p7sname, p7signer, res_conf, root_hints,
|
||||
debugconf, ip4only, ip6only, port))
|
||||
debugconf, srcaddr, ip4only, ip6only, port))
|
||||
return 1;
|
||||
return used_builtin;
|
||||
}
|
||||
|
|
@ -2281,10 +2303,11 @@ int main(int argc, char* argv[])
|
|||
const char* res_conf = NULL;
|
||||
const char* root_hints = NULL;
|
||||
const char* debugconf = NULL;
|
||||
const char* srcaddr = NULL;
|
||||
int dolist=0, ip4only=0, ip6only=0, force=0, port = HTTPS_PORT;
|
||||
int res_conf_fallback = 0;
|
||||
/* parse the options */
|
||||
while( (c=getopt(argc, argv, "46C:FRP:a:c:f:hln:r:s:u:vx:")) != -1) {
|
||||
while( (c=getopt(argc, argv, "46C:FRP:a:b:c:f:hln:r:s:u:vx:")) != -1) {
|
||||
switch(c) {
|
||||
case 'l':
|
||||
dolist = 1;
|
||||
|
|
@ -2298,6 +2321,9 @@ int main(int argc, char* argv[])
|
|||
case 'a':
|
||||
root_anchor_file = optarg;
|
||||
break;
|
||||
case 'b':
|
||||
srcaddr = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
root_cert_file = optarg;
|
||||
break;
|
||||
|
|
@ -2368,5 +2394,5 @@ int main(int argc, char* argv[])
|
|||
|
||||
return do_root_update_work(root_anchor_file, root_cert_file, urlname,
|
||||
xmlname, p7sname, p7signer, res_conf, root_hints, debugconf,
|
||||
ip4only, ip6only, force, res_conf_fallback, port);
|
||||
srcaddr, ip4only, ip6only, force, res_conf_fallback, port);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue