diff --git a/CHANGES b/CHANGES index 487da9d5c0..7a24028370 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,16 @@ +2.6-27 | 2018-12-10 11:53:41 -0600 + + * GH-216: Add FTS dependency when building on Alpine (Jon Siwek, Corelight) + + * Remove unnecessary header include (Jon Siwek, Corelight) + + * GH-216: Improve default DNS resolution support for Alpine/musl (Jon Siwek, Corelight) + + /etc/resolv.conf now gets parsed for the first IPv4 nameserver that works. + + * Add dns_resolver option (Jon Siwek, Corelight) + 2.6-22 | 2018-12-10 11:16:53 -0600 * Introduce --enable-static-broker configuration option. (Johanna Amann) diff --git a/CMakeLists.txt b/CMakeLists.txt index 523093d34d..8171ad5bf4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -188,6 +188,20 @@ endif () # if one specifies --with-openssl (which may be common). include_directories(BEFORE ${OPENSSL_INCLUDE_DIR}) +# Alpine support +if ( ${CMAKE_SYSTEM_NAME} MATCHES Linux AND EXISTS /etc/os-release ) + execute_process( + COMMAND grep -q alpine /etc/os-release + RESULT_VARIABLE os_release_alpine + ) + + if ( os_release_alpine EQUAL 0 ) + find_package(FTS REQUIRED) + list(APPEND OPTLIBS ${FTS_LIBRARY}) + include_directories(BEFORE ${FTS_INCLUDE_DIR}) + endif () +endif () + set(brodeps ${BinPAC_LIBRARY} ${PCAP_LIBRARY} diff --git a/VERSION b/VERSION index baff7e1f33..f6cdb0d036 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.6-22 +2.6-27 diff --git a/aux/bifcl b/aux/bifcl index eeeeba5c93..e836dcaa48 160000 --- a/aux/bifcl +++ b/aux/bifcl @@ -1 +1 @@ -Subproject commit eeeeba5c936d7af5bba006c02d26f32457da5146 +Subproject commit e836dcaa48df69fccda3ddc2a64cd8be09333391 diff --git a/aux/binpac b/aux/binpac index 8d0c0f874f..d0a89916c7 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit 8d0c0f874f9dbf3cb87f2f76579508693c8ff051 +Subproject commit d0a89916c77de69154a50339985d17fa0bf13823 diff --git a/aux/broccoli b/aux/broccoli index 494fe25456..9bd910e88d 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 494fe254562e68842adfa35bc93a618e90fbad68 +Subproject commit 9bd910e88d412b00fbcd1e5301144aa0746923a5 diff --git a/aux/broctl b/aux/broctl index 64dd162ad7..879d035086 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 64dd162ad7b8a9624c491a836062957efbb73cc9 +Subproject commit 879d03508619608308307645181d5c5fcf9e1abc diff --git a/aux/broker b/aux/broker index 63df57d444..d0bddc7598 160000 --- a/aux/broker +++ b/aux/broker @@ -1 +1 @@ -Subproject commit 63df57d44430af31da573956b639f869a339a3a8 +Subproject commit d0bddc7598c0f10031120a6c55499af0e4f67d0e diff --git a/aux/zeek-aux b/aux/zeek-aux index cf569fed9d..22aac5f179 160000 --- a/aux/zeek-aux +++ b/aux/zeek-aux @@ -1 +1 @@ -Subproject commit cf569fed9d450129b3fb241b9a42148fb22012e2 +Subproject commit 22aac5f17935c4d2ff2cab3ae37e95aaec8fa9a1 diff --git a/cmake b/cmake index 433676df0a..56143d2589 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 433676df0af266540b8a3d9216cfd9dbc1361b09 +Subproject commit 56143d25890f5f65a27761d35f154c63e5454ca3 diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 3f13bd232a..600a507d4f 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -3656,6 +3656,12 @@ global dns_skip_all_addl = T &redef; ## traffic and do not process it. Set to 0 to turn off this functionality. global dns_max_queries = 25 &redef; +## The address of the DNS resolver to use. If not changed from the +## unspecified address, ``[::]``, the first nameserver from /etc/resolv.conf +## gets used (IPv6 is currently only supported if set via this option, not +## when parsed from the file). +const dns_resolver = [::] &redef; + ## HTTP session statistics. ## ## .. bro:see:: http_stats diff --git a/src/DNS_Mgr.cc b/src/DNS_Mgr.cc index 7f651b5fdd..266217c02a 100644 --- a/src/DNS_Mgr.cc +++ b/src/DNS_Mgr.cc @@ -376,12 +376,6 @@ DNS_Mgr::DNS_Mgr(DNS_MgrMode arg_mode) mode = arg_mode; - char err[NB_DNS_ERRSIZE]; - nb_dns = nb_dns_init(err); - - if ( ! nb_dns ) - reporter->Warning("problem initializing NB-DNS: %s", err); - dns_mapping_valid = dns_mapping_unverified = dns_mapping_new_name = dns_mapping_lost_name = dns_mapping_name_changed = dns_mapping_altered = 0; @@ -410,6 +404,35 @@ void DNS_Mgr::InitPostScript() if ( did_init ) return; + auto dns_resolver_id = global_scope()->Lookup("dns_resolver"); + auto dns_resolver_addr = dns_resolver_id->ID_Val()->AsAddr(); + char err[NB_DNS_ERRSIZE]; + + if ( dns_resolver_addr == IPAddr("::") ) + nb_dns = nb_dns_init(err); + else + { + struct sockaddr_storage ss = {0}; + + if ( dns_resolver_addr.GetFamily() == IPv4 ) + { + struct sockaddr_in* sa = (struct sockaddr_in*)&ss; + sa->sin_family = AF_INET; + dns_resolver_addr.CopyIPv4(&sa->sin_addr); + } + else + { + struct sockaddr_in6* sa = (struct sockaddr_in6*)&ss; + sa->sin6_family = AF_INET6; + dns_resolver_addr.CopyIPv6(&sa->sin6_addr); + } + + nb_dns = nb_dns_init2(err, (struct sockaddr*)&ss); + } + + if ( ! nb_dns ) + reporter->Warning("problem initializing NB-DNS: %s", err); + const char* cache_dir = dir ? dir : "."; if ( mode == DNS_PRIME && ! ensure_dir(cache_dir) ) @@ -471,15 +494,15 @@ static const char* fake_addr_lookup_result(const IPAddr& addr) TableVal* DNS_Mgr::LookupHost(const char* name) { + if ( mode == DNS_FAKE ) + return fake_name_lookup_result(name); + if ( ! nb_dns ) return empty_addr_set(); if ( ! did_init ) Init(); - if ( mode == DNS_FAKE ) - return fake_name_lookup_result(name); - if ( mode != DNS_PRIME ) { HostMap::iterator it = host_mappings.find(name); diff --git a/src/nb_dns.c b/src/nb_dns.c index a1f0d018dd..f8abc167b5 100644 --- a/src/nb_dns.c +++ b/src/nb_dns.c @@ -86,7 +86,7 @@ struct nb_dns_hostent { struct nb_dns_info { int s; /* Resolver file descriptor */ - struct sockaddr_in server; /* server address to bind to */ + struct sockaddr_storage server; /* server address to bind to */ struct nb_dns_entry *list; /* outstanding requests */ struct nb_dns_hostent dns_hostent; }; @@ -109,6 +109,18 @@ my_strerror(int errnum) #endif } +static const char* sa_ntop(struct sockaddr* sa, char* buf, int len) + { + if ( sa->sa_family == AF_INET ) + return inet_ntop(sa->sa_family, + &(((struct sockaddr_in*)sa)->sin_addr), + buf, len); + else + return inet_ntop(sa->sa_family, + &(((struct sockaddr_in6*)sa)->sin6_addr), + buf, len); + } + struct nb_dns_info * nb_dns_init(char *errstr) { @@ -132,17 +144,98 @@ nb_dns_init(char *errstr) return (NULL); } + if ( _res.nscount == 0 ) + { + // Really? Let's try parsing resolv.conf ourselves to see what's + // there. (e.g. musl libc has res_init() that doesn't actually + // parse the config file). + const char* config_file_path = "/etc/resolv.conf"; + +#ifdef _PATH_RESCONF + config_file_path = _PATH_RESCONF; +#endif + + FILE* config_file = fopen(config_file_path, "r"); + + if ( config_file ) + { + char line[128]; + char* ns; + + while ( fgets(line, sizeof(line), config_file) ) + { + ns = strtok(line, " \t\n"); + + if ( ! ns || strcmp(ns, "nameserver") ) + continue; + + ns = strtok(0, " \t\n"); + + if ( ! ns ) + continue; + + /* XXX support IPv6 */ + struct sockaddr_in a; + memset(&a, 0, sizeof(a)); + a.sin_family = AF_INET; + a.sin_port = htons(53); + + if ( inet_pton(AF_INET, ns, &a.sin_addr) == 1 ) + { + memcpy(&nd->server, &a, sizeof(a)); + nd->s = socket(nd->server.ss_family, SOCK_DGRAM, 0); + + if ( nd->s < 0 ) + { + snprintf(errstr, NB_DNS_ERRSIZE, "socket(): %s", + my_strerror(errno)); + fclose(config_file); + free(nd); + return (NULL); + } + + if ( connect(nd->s, (struct sockaddr *)&nd->server, + nd->server.ss_family == AF_INET ? + sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6)) < 0 ) + { + char s[INET6_ADDRSTRLEN]; + sa_ntop((struct sockaddr*)&nd->server, s, INET6_ADDRSTRLEN); + snprintf(errstr, NB_DNS_ERRSIZE, "connect(%s): %s", s, + my_strerror(errno)); + fclose(config_file); + close(nd->s); + free(nd); + return (NULL); + } + + fclose(config_file); + return (nd); + } + } + + fclose(config_file); + snprintf(errstr, NB_DNS_ERRSIZE, "no valid nameserver found in %s", + config_file_path); + free(nd); + return (NULL); + } + + snprintf(errstr, NB_DNS_ERRSIZE, "resolver config file not located"); + free(nd); + return (NULL); + } + int i; for ( i = 0; i < _res.nscount; ++i ) { - nd->server = _res.nsaddr_list[i]; - + memcpy(&nd->server, &_res.nsaddr_list[i], sizeof(struct sockaddr_in)); /* XXX support IPv6 */ - if ( nd->server.sin_family != AF_INET ) + if ( nd->server.ss_family != AF_INET ) continue; - nd->s = socket(nd->server.sin_family, SOCK_DGRAM, 0); + nd->s = socket(nd->server.ss_family, SOCK_DGRAM, 0); if ( nd->s < 0 ) { @@ -153,10 +246,14 @@ nb_dns_init(char *errstr) } if ( connect(nd->s, (struct sockaddr *)&nd->server, - sizeof(struct sockaddr)) < 0 ) + nd->server.ss_family == AF_INET ? + sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6)) < 0 ) { - snprintf(errstr, NB_DNS_ERRSIZE, "connect(%s): %s", - inet_ntoa(nd->server.sin_addr), my_strerror(errno)); + char s[INET6_ADDRSTRLEN]; + sa_ntop((struct sockaddr*)&nd->server, s, INET6_ADDRSTRLEN); + snprintf(errstr, NB_DNS_ERRSIZE, "connect(%s): %s", s, + my_strerror(errno)); close(nd->s); free(nd); return (NULL); @@ -170,6 +267,58 @@ nb_dns_init(char *errstr) return (NULL); } +struct nb_dns_info * +nb_dns_init2(char *errstr, struct sockaddr* sa) +{ + register struct nb_dns_info *nd; + + nd = (struct nb_dns_info *)malloc(sizeof(*nd)); + if (nd == NULL) { + snprintf(errstr, NB_DNS_ERRSIZE, "nb_dns_init: malloc(): %s", + my_strerror(errno)); + return (NULL); + } + memset(nd, 0, sizeof(*nd)); + nd->s = -1; + + if ( sa->sa_family == AF_INET ) + { + memcpy(&nd->server, sa, sizeof(struct sockaddr_in)); + ((struct sockaddr_in*)&nd->server)->sin_port = htons(53); + } + else + { + memcpy(&nd->server, sa, sizeof(struct sockaddr_in6)); + ((struct sockaddr_in6*)&nd->server)->sin6_port = htons(53); + } + + nd->s = socket(nd->server.ss_family, SOCK_DGRAM, 0); + + if ( nd->s < 0 ) + { + snprintf(errstr, NB_DNS_ERRSIZE, "socket(): %s", + my_strerror(errno)); + free(nd); + return (NULL); + } + + if ( connect(nd->s, (struct sockaddr *)&nd->server, + nd->server.ss_family == AF_INET ? + sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6)) < 0 ) + { + char s[INET6_ADDRSTRLEN]; + sa_ntop((struct sockaddr*)&nd->server, s, INET6_ADDRSTRLEN); + snprintf(errstr, NB_DNS_ERRSIZE, "connect(%s): %s", s, + my_strerror(errno)); + close(nd->s); + free(nd); + return (NULL); + } + + return (nd); +} + void nb_dns_finish(struct nb_dns_info *nd) { @@ -226,12 +375,12 @@ _nb_dns_cmpsockaddr(register struct sockaddr *sa1, sin6a = (struct sockaddr_in6 *)sa1; sin6b = (struct sockaddr_in6 *)sa2; if (sin6a->sin6_port != sin6b->sin6_port) { - snprintf(errstr, NB_DNS_ERRSIZE, serr, 2); + snprintf(errstr, NB_DNS_ERRSIZE, serr, 62); return (-1); } if (memcmp(&sin6a->sin6_addr, &sin6b->sin6_addr, sizeof(sin6a->sin6_addr)) != 0) { - snprintf(errstr, NB_DNS_ERRSIZE, serr, 3); + snprintf(errstr, NB_DNS_ERRSIZE, serr, 63); return (-1); } break; @@ -446,7 +595,7 @@ nb_dns_activity(struct nb_dns_info *nd, struct nb_dns_result *nr, char *errstr) register int msglen, qtype, atype, n, i; register struct nb_dns_entry *ne, *lastne; socklen_t fromlen; - struct sockaddr from; + struct sockaddr_storage from; u_long msg[MAXPACKET / sizeof(u_long)]; register char *bp, *ep; register char **ap, **hap; @@ -460,7 +609,8 @@ nb_dns_activity(struct nb_dns_info *nd, struct nb_dns_result *nr, char *errstr) /* This comes from the second half of do_query() */ fromlen = sizeof(from); - msglen = recvfrom(nd->s, (char *)msg, sizeof(msg), 0, &from, &fromlen); + msglen = recvfrom(nd->s, (char *)msg, sizeof(msg), 0, + (struct sockaddr*)&from, &fromlen); if (msglen <= 0) { snprintf(errstr, NB_DNS_ERRSIZE, "recvfrom(): %s", my_strerror(errno)); @@ -479,8 +629,8 @@ nb_dns_activity(struct nb_dns_info *nd, struct nb_dns_result *nr, char *errstr) } /* RES_INSECURE1 style check */ - if (_nb_dns_cmpsockaddr((struct sockaddr *)&nd->server, &from, - errstr) < 0) { + if (_nb_dns_cmpsockaddr((struct sockaddr*)&nd->server, + (struct sockaddr*)&from, errstr) < 0) { nr->host_errno = NO_RECOVERY; return (-1); } diff --git a/src/nb_dns.h b/src/nb_dns.h index 33e09aa226..eba9d39084 100644 --- a/src/nb_dns.h +++ b/src/nb_dns.h @@ -17,6 +17,7 @@ typedef unsigned int nb_uint32_t; /* Public routines */ struct nb_dns_info *nb_dns_init(char *); +struct nb_dns_info *nb_dns_init2(char *, struct sockaddr*); void nb_dns_finish(struct nb_dns_info *); int nb_dns_fd(struct nb_dns_info *); diff --git a/src/threading/BasicThread.cc b/src/threading/BasicThread.cc index f111028475..95bfd8acd0 100644 --- a/src/threading/BasicThread.cc +++ b/src/threading/BasicThread.cc @@ -1,5 +1,4 @@ -#include #include #include "bro-config.h"