From 113e0b975fb7f06d2655b4675535556453609e1d Mon Sep 17 00:00:00 2001 From: david Date: Sat, 15 Sep 2012 17:56:11 +0000 Subject: [PATCH] Break out resolve and resolve_numeric. Besides the confusingness of the nodns argument being negatively phrased, it had the value 0 in every existing call. Split out the nodns special case into a separate function resolve_numeric. This also has the side effect of changing the number of parameters to the resolve function, which will cause a compile error for any calls I might have missed changing when I changed the return code meaning in the previous commit. Ncat has its own copy of resolve, which obeys the global o.nodns rather than a parameter. I'm leaving that alone for now. But give it the same resolve_internal function, and make resolve call it with different flags depending on the value of o.nodns. --- idle_scan.cc | 2 +- libnetutil/netutil.cc | 33 ++++++++++++++++++++++----------- libnetutil/netutil.h | 21 ++++++++++++--------- ncat/ncat_core.c | 36 ++++++++++++++++++++++++++++-------- ncat/ncat_core.h | 14 ++++++++++---- nmap.cc | 8 ++++---- nmap_dns.cc | 2 +- nping/utils_net.cc | 6 +++--- 8 files changed, 81 insertions(+), 41 deletions(-) diff --git a/idle_scan.cc b/idle_scan.cc index a485eabc6..f1e288875 100644 --- a/idle_scan.cc +++ b/idle_scan.cc @@ -339,7 +339,7 @@ static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName, } proxy->host.setHostName(name); - if (resolve(name, 0, 0, &ss, &sslen, o.pf()) != 0) { + if (resolve(name, 0, &ss, &sslen, o.pf()) != 0) { fatal("Could not resolve idle scan zombie host: %s", name); } proxy->host.setTargetSockAddr(&ss, sslen); diff --git a/libnetutil/netutil.cc b/libnetutil/netutil.cc index a27d92693..e2efd9848 100644 --- a/libnetutil/netutil.cc +++ b/libnetutil/netutil.cc @@ -374,15 +374,10 @@ after: return(d - data); } -/* Tries to resolve the given name (or literal IP) into a sockaddr structure. - - Parameter "hostname" is the name to be resolved. - - Parameter "port" sets the port in each returned address structure - (you can safely pass 0 for the port if you don't care) - - Parameter "nodns": If set, it means that the supplied hostname is actually a - numeric IP address. The flag prevents any type of name resolution service - from being called. In 99% of the cases this should be 0. - Returns 0 on success, or a getaddrinfo return code on failure. */ -int resolve(const char *hostname, u16 port, int nodns, struct sockaddr_storage *ss, size_t *sslen, int af){ +/* Internal helper for resolve and resolve_numeric. addl_flags is ored into + hints.ai_flags, so you can add AI_NUMERICHOST. */ +static int resolve_internal(const char *hostname, u16 port, + struct sockaddr_storage *ss, size_t *sslen, int af, int addl_flags) { struct addrinfo hints; struct addrinfo *result; char portbuf[16]; @@ -395,8 +390,7 @@ int resolve(const char *hostname, u16 port, int nodns, struct sockaddr_storage * memset(&hints, 0, sizeof(hints)); hints.ai_family = af; hints.ai_socktype = SOCK_DGRAM; - if (nodns) - hints.ai_flags |= AI_NUMERICHOST; + hints.ai_flags |= addl_flags; /* Make the port number a string to give to getaddrinfo. */ rc = Snprintf(portbuf, sizeof(portbuf), "%hu", port); @@ -414,6 +408,23 @@ int resolve(const char *hostname, u16 port, int nodns, struct sockaddr_storage * return 0; } +/* Resolves the given hostname or IP address with getaddrinfo, and stores the + first result (if any) in *ss and *sslen. The value of port will be set in the + appropriate place in *ss; set to 0 if you don't care. af may be AF_UNSPEC, in + which case getaddrinfo may return e.g. both IPv4 and IPv6 results; which one + is first depends on the system configuration. Returns 0 on success, or a + getaddrinfo return code (suitable for passing to gai_strerror) on failure. + *ss and *sslen are always defined when this function returns 0. */ +int resolve(const char *hostname, u16 port, struct sockaddr_storage *ss, size_t *sslen, int af) { + return resolve_internal(hostname, port, ss, sslen, af, 0); +} + +/* As resolve, but do not do DNS resolution of hostnames; the first argument + must be the string representation of a numeric IP address. */ +int resolve_numeric(const char *ip, u16 port, struct sockaddr_storage *ss, size_t *sslen, int af) { + return resolve_internal(ip, port, ss, sslen, af, AI_NUMERICHOST); +} + /* * Returns 1 if this is a reserved IP address, where "reserved" means * either a private address, non-routable address, or even a non-reserved diff --git a/libnetutil/netutil.h b/libnetutil/netutil.h index e052f75d4..47eb114fb 100644 --- a/libnetutil/netutil.h +++ b/libnetutil/netutil.h @@ -157,15 +157,18 @@ int netutil_error(const char *str, ...) contain a newline character at the end. */ int parse_ip_options(const char *txt, u8 *data, int datalen, int* firsthopoff, int* lasthopoff, char *errstr, size_t errstrlen); -/* Tries to resolve the given name (or literal IP) into a sockaddr structure. - - Parameter "hostname" is the name to be resolved. - - Parameter "port" sets the port in each returned address structure - (you can safely pass 0 for the port if you don't care) - - Parameter "nodns": If set, it means that the supplied hostname is actually a - numeric IP address. The flag prevents any type of name resolution service - from being called. In 99% of the cases this should be 0. - Returns 0 on success, or a getaddrinfo return code on failure. */ -int resolve(const char *hostname, u16 port, int nodns, struct sockaddr_storage *ss, size_t *sslen, int af); +/* Resolves the given hostname or IP address with getaddrinfo, and stores the + first result (if any) in *ss and *sslen. The value of port will be set in the + appropriate place in *ss; set to 0 if you don't care. af may be AF_UNSPEC, in + which case getaddrinfo may return e.g. both IPv4 and IPv6 results; which one + is first depends on the system configuration. Returns 0 on success, or a + getaddrinfo return code (suitable for passing to gai_strerror) on failure. + *ss and *sslen are always defined when this function returns 0. */ +int resolve(const char *hostname, u16 port, struct sockaddr_storage *ss, size_t *sslen, int af); + +/* As resolve, but do not do DNS resolution of hostnames; the first argument + must be the string representation of a numeric IP address. */ +int resolve_numeric(const char *ip, u16 port, struct sockaddr_storage *ss, size_t *sslen, int af); /* * Returns 1 if this is a reserved IP address, where "reserved" means diff --git a/ncat/ncat_core.c b/ncat/ncat_core.c index 9f07c99cc..e5afa056a 100644 --- a/ncat/ncat_core.c +++ b/ncat/ncat_core.c @@ -180,25 +180,24 @@ void options_init(void) #endif } -/* Tries to resolve the given name (or literal IP) into a sockaddr structure. - Pass 0 for the port if you don't care. Returns 0 on success, or a getaddrinfo - return code on error. */ -int resolve(char *hostname, unsigned short port, - struct sockaddr_storage *ss, size_t *sslen, int af) +/* Internal helper for resolve and resolve_numeric. addl_flags is ored into + hints.ai_flags, so you can add AI_NUMERICHOST. */ +static int resolve_internal(const char *hostname, unsigned short port, + struct sockaddr_storage *ss, size_t *sslen, int af, int addl_flags) { struct addrinfo hints; struct addrinfo *result; char portbuf[16]; - int rc; + size_t rc=0; + assert(hostname); assert(ss); assert(sslen); memset(&hints, 0, sizeof(hints)); hints.ai_family = af; hints.ai_socktype = SOCK_DGRAM; - if (o.nodns) - hints.ai_flags |= AI_NUMERICHOST; + hints.ai_flags |= addl_flags; /* Make the port number a string to give to getaddrinfo. */ rc = Snprintf(portbuf, sizeof(portbuf), "%hu", port); @@ -216,6 +215,27 @@ int resolve(char *hostname, unsigned short port, return 0; } +/* Resolves the given hostname or IP address with getaddrinfo, and stores the + first result (if any) in *ss and *sslen. The value of port will be set in the + appropriate place in *ss; set to 0 if you don't care. af may be AF_UNSPEC, in + which case getaddrinfo may return e.g. both IPv4 and IPv6 results; which one + is first depends on the system configuration. Returns 0 on success, or a + getaddrinfo return code (suitable for passing to gai_strerror) on failure. + *ss and *sslen are always defined when this function returns 0. + + If the global o.nodns is true, then do not resolve any names with DNS. */ +int resolve(const char *hostname, unsigned short port, + struct sockaddr_storage *ss, size_t *sslen, int af) +{ + int flags; + + flags = 0; + if (o.nodns) + flags |= AI_NUMERICHOST; + + return resolve_internal(hostname, port, ss, sslen, af, flags); +} + int fdinfo_close(struct fdinfo *fdn) { #ifdef HAVE_OPENSSL diff --git a/ncat/ncat_core.h b/ncat/ncat_core.h index 6fa09063c..59755c427 100644 --- a/ncat/ncat_core.h +++ b/ncat/ncat_core.h @@ -172,10 +172,16 @@ extern struct timeval start_time; /* Initializes global options to their default values. */ void options_init(void); -/* Tries to resolve the given name (or literal IP) into a sockaddr structure. - Pass 0 for the port if you don't care. Returns 0 on success, or a getaddrinfo - return code on error. */ -int resolve(char *hostname, unsigned short port, +/* Resolves the given hostname or IP address with getaddrinfo, and stores the + first result (if any) in *ss and *sslen. The value of port will be set in the + appropriate place in *ss; set to 0 if you don't care. af may be AF_UNSPEC, in + which case getaddrinfo may return e.g. both IPv4 and IPv6 results; which one + is first depends on the system configuration. Returns 0 on success, or a + getaddrinfo return code (suitable for passing to gai_strerror) on failure. + *ss and *sslen are always defined when this function returns 0. + + If the global o.nodns is true, then do not resolve any names with DNS. */ +int resolve(const char *hostname, unsigned short port, struct sockaddr_storage *ss, size_t *sslen, int af); int fdinfo_close(struct fdinfo *fdn); diff --git a/nmap.cc b/nmap.cc index f7d8ea273..28151aab9 100644 --- a/nmap.cc +++ b/nmap.cc @@ -996,7 +996,7 @@ void parse_options(int argc, char **argv) { /* Try to resolve it */ struct sockaddr_in decoytemp; size_t decoytemplen = sizeof(struct sockaddr_in); - if (resolve(p, 0, 0, (sockaddr_storage*)&decoytemp, &decoytemplen, AF_INET) == 0) { + if (resolve(p, 0, (sockaddr_storage*)&decoytemp, &decoytemplen, AF_INET) == 0) { o.decoys[o.numdecoys] = decoytemp.sin_addr; o.numdecoys++; } else { @@ -1338,7 +1338,7 @@ void apply_delayed_options() { size_t sslen; if (o.spoofsource) { - if (resolve(delayed_options.spoofSource, 0, 0, &ss, &sslen, o.af()) != 0) + if (resolve(delayed_options.spoofSource, 0, &ss, &sslen, o.af()) != 0) fatal("Failed to resolve/decode supposed %s source address %s.", (o.af() == AF_INET) ? "IPv4" : "IPv6", delayed_options.spoofSource); o.setSourceSockAddr(&ss, sslen); } @@ -1633,7 +1633,7 @@ int nmap_main(int argc, char *argv[]) { size_t sslen; dst = route_dst_hosts[i].c_str(); - if (resolve(dst, 0, 0, &ss, &sslen, o.af()) != 0) + if (resolve(dst, 0, &ss, &sslen, o.af()) != 0) fatal("Can't resolve %s.", dst); printf("%s\n", inet_ntop_ez(&ss, sslen)); @@ -1936,7 +1936,7 @@ int nmap_main(int argc, char *argv[]) { currenths->setSourceSockAddr(&ss, sslen); } else { if (gethostname(myname, MAXHOSTNAMELEN) || - resolve(myname, 0, 0, &ss, &sslen, o.af()) != 0) + resolve(myname, 0, &ss, &sslen, o.af()) != 0) fatal("Cannot get hostname! Try using -S or -e \n"); o.setSourceSockAddr(&ss, sslen); diff --git a/nmap_dns.cc b/nmap_dns.cc index 6a0bfa57c..f0aa8348f 100644 --- a/nmap_dns.cc +++ b/nmap_dns.cc @@ -820,7 +820,7 @@ static void add_dns_server(char *ipaddrs) { for (hostname = strtok(ipaddrs, " ,"); hostname != NULL; hostname = strtok(NULL, " ,")) { - if (resolve(hostname, 0, 0, (struct sockaddr_storage *) &addr, &addr_len, PF_UNSPEC) != 0) continue; + if (resolve(hostname, 0, (struct sockaddr_storage *) &addr, &addr_len, PF_UNSPEC) != 0) continue; for(servI = servs.begin(); servI != servs.end(); servI++) { tpserv = *servI; diff --git a/nping/utils_net.cc b/nping/utils_net.cc index 743ab739c..321e8365f 100644 --- a/nping/utils_net.cc +++ b/nping/utils_net.cc @@ -106,7 +106,7 @@ extern NpingOps o; int atoIP(const char *hostname, struct in_addr *dst){ struct sockaddr_in i; unsigned int stlen=0; - if ( resolve(hostname, 0, 0, (sockaddr_storage*)&i, (size_t *)&stlen , PF_INET) != 0 ) + if ( resolve(hostname, 0, (sockaddr_storage*)&i, (size_t *)&stlen , PF_INET) != 0 ) return OP_FAILURE; *dst=i.sin_addr; return OP_SUCCESS; @@ -118,7 +118,7 @@ int atoIP(const char *hostname, struct sockaddr_storage *ss, int family){ return OP_FAILURE; if(family!=AF_INET && family!=AF_INET6) return OP_FAILURE; - if ( resolve(hostname, 0, 0, ss, &stlen , family) != 0 ) + if ( resolve(hostname, 0, ss, &stlen , family) != 0 ) return OP_FAILURE; return OP_SUCCESS; } /* End of atoIP */ @@ -556,7 +556,7 @@ int resolveCached(char *host, struct sockaddr_storage *ss, size_t *sslen, int pf misses++; outPrint(DBG_4, "resolveCached(): Cache miss %d for %s\n", misses, host); - if( (result=resolve(host, 0, 0, ss, sslen, pf)) == 0 ){ + if( (result=resolve(host, 0, ss, sslen, pf)) == 0 ){ /* Increment count */ if( cached_count < MAX_CACHED_HOSTS )