summaryrefslogtreecommitdiff
path: root/src/network/getaddrinfo.c
AgeCommit message (Collapse)AuthorLines
2022-09-20getaddrinfo: add EAI_NODATA error code to distinguish NODATA vs NxDomainRich Felker-1/+4
this was apparently omitted long ago out of a lack of understanding of its importance and the fact that POSIX doesn't specify it. despite not being officially standardized, however, it turns out that at least AIX, glibc, NetBSD, OpenBSD, QNX, and Solaris document and support it. in certain usage cases, such as implementing a DNS gateway on top of the stub resolver interfaces, it's necessary to distinguish the case where a name does not exit (NxDomain) from one where it exists but has no addresses (or other records) of the requested type (NODATA). in fact, even the legacy gethostbyname API had this distinction, which we were previously unable to support correctly because the backend lacked it. apart from fixing an important functionality gap, adding this distinction helps clarify to users how search domain fallback works (falling back in cases corresponding to EAI_NONAME, not in ones corresponding to EAI_NODATA), a topic that has been a source of ongoing confusion and frustration. as a result of this change, EAI_NONAME is no longer a valid universal error code for getaddrinfo in the case where AI_ADDRCONFIG has suppressed use of all address families. in order to return an accurate result in this case, getaddrinfo is modified to still perform at least one lookup. this will almost surely fail (with a network error, since there is no v4 or v6 network to query DNS over) unless a result comes from the hosts file or from ip literal parsing, but in case it does succeed, the result is replaced by EAI_NODATA. glibc has a related error code, EAI_ADDRFAMILY, that could be used for the AI_ADDRCONFIG case and certain NODATA cases, but distinguishing them properly in full generality seems to require additional DNS queries that are otherwise not useful. on glibc, it is only used for ip literals with mismatching family, not for DNS or hosts file results where the name has addresses only in the opposite family. since this seems misleading and inconsistent, and since EAI_NODATA already covers the semantic case where the "name" exists but doesn't have any addresses in the requested family, we do not adopt EAI_ADDRFAMILY at this time. this could be changed at some point if desired, but the logic for getting all the corner cases with AI_ADDRCONFIG right is slightly nontrivial.
2022-08-01fix mishandling of errno in getaddrinfo AI_ADDRCONFIG logicRich Felker-0/+2
this code attempts to use the value of errno from failure of socket or connect to infer availability of the requested address family (v4 or v6). however, in the case where connect failed, there is an intervening call to close between connect and the use of errno. close is not required to preserve errno on success, and in fact the __aio_close code, which is called whenever aio is linked and thus always called in dynamic-linked programs, unconditionally clobbers errno. as a result, getaddrinfo fails with EAI_SYSTEM and errno=ENOENT rather than correctly determining that the address family was unavailable. this fix is based on report/patch by Jussi Nieminen, but simplified slightly to avoid breaking the case where socket, not connect, failed.
2019-02-20fix spurious undefined behavior in getaddrinfoRich Felker-3/+2
addressing &out[k].sa was arguably undefined, despite &out[k] being defined the slot one past the end of an array, since the member access .sa is intervening between the [] operator and the & operator.
2019-02-20fix invalid free of partial addrinfo list with multiple servicesRich Felker-1/+1
the backindex stored by getaddrinfo to allow freeaddrinfo to perform partial-free wrongly used the address result index, rather than the output slot index, and thus was only valid when they were equal (nservs==1). patch based on report with proposed fix by Markus Wichmann.
2018-10-04allow freeaddrinfo of arbitrary sublists of addrinfo listRich Felker-7/+3
the specification for freeaddrinfo allows it to be used to free "arbitrary sublists" of the list returned by getaddrinfo. it's not clearly stated how such sublists come into existence, but the interpretation seems to be that the application can edit the ai_next pointers to cut off a portion of the list and then free it. actual freeing of individual list slots is contrary to the design of our getaddrinfo implementation, which has no failure paths after making a single allocation, so that light callers can avoid linking realloc/free. freeing individual slots is also incompatible with sharing the string for ai_canonname, which the current implementation does despite no requirement that it be present except on the first result. so, rather than actually freeing individual slots, provide a way to find the start of the allocated array, and reference-count it, freeing the memory all at once after the last slot has been freed. since the language in the spec is "arbitrary sublists", no provision for handling other constructs like multiple lists glued together, circular links, etc. is made. presumably passing such a construct to freeaddrinfo produces undefined behavior.
2018-09-19fix getaddrinfo regression with AI_ADDRCONFIG on some configurationsRich Felker-1/+10
despite not being documented to do so in the standard or Linux documentation, attempts to udp connect to 127.0.0.1 or ::1 generate EADDRNOTAVAIL when the loopback device is not configured and there is no default route for IPv6. this caused getaddrinfo with AI_ADDRCONFIG to fail with EAI_SYSTEM and EADDRNOTAVAIL on some no-IPv6 configurations, rather than the intended behavior of detecting IPv6 as unsuppported and producing IPv4-only results. previously, only EAFNOSUPPORT was treated as unavailability of the address family being probed. instead, treat all errors related to inability to get an address or route as conclusive that the family being probed is unsupported, and only fail with EAI_SYSTEM on other errors. further improvements may be desirable, such as reporting EAI_AGAIN instead of EAI_SYSTEM for errors which are expected to be transient, but this patch should suffice to fix the serious regression.
2018-07-14implement getaddrinfo's AI_ADDRCONFIG flagRich Felker-0/+39
this flag is notoriously under-/mis-specified, and in the past it was implemented as a nop, essentially considering the absence of a loopback interface with 127.0.0.1 and ::1 addresses an unsupported configuration. however, common real-world container environments omit IPv6 support (even for the network-namespaced loopback interface), and some kernels omit IPv6 support entirely. future systems on the other hand might omit IPv4 entirely. treat these as supported configurations and suppress results of the unconfigured/unsupported address families when AI_ADDRCONFIG is requested. use routability of the loopback address to make the determination; unlike other implementations, we do not exclude loopback from the "an address is configured" condition, since there is no basis in the specification for such exclusion. obtaining a result with AI_ADDRCONFIG does not imply routability of the result, and applications must still be able to cope with unroutable results even if they pass AI_ADDRCONFIG.
2015-09-25make getaddrinfo return error if both host and service name are nullRich Felker-0/+2
this case is specified as a mandatory ("shall fail") error. based on patch by Julien Ramseier.
2015-02-07make getaddrinfo support SOCK_RAW and other socket typesRich Felker-30/+4
all socket types are accepted at this point, but that may be changed at a later time if the behavior is not meaningful for other types. as before, omitting type (a value of 0) gives both UDP and TCP results, and SOCK_DGRAM or SOCK_STREAM restricts to UDP or TCP, respectively. for other socket types, the service name argument is required to be a null pointer, and the protocol number provided by the caller is used.
2014-06-04add support for ipv6 scope_id to getaddrinfo and getnameinfoRich Felker-0/+1
for all address types, a scope_id specified as a decimal value is accepted. for addresses with link-local scope, a string containing the interface name is also accepted. some changes are made to error handling to avoid unwanted fallbacks in the case where the scope_id is invalid: if an earlier name lookup backend fails with an error rather than simply "0 results", this failure now suppresses any later attempts with other backends. in getnameinfo, a light "itoa" type function is added for generating decimal scope_id results, and decimal port strings for services are also generated using this function now so as not to pull in the dependency on snprintf. in netdb.h, a definition for the NI_NUMERICSCOPE flag is added. this is required by POSIX (it was previously missing) and needed to allow callers to suppress interface-name lookups.
2014-05-31refactor getaddrinfo and add support for most remaining featuresRich Felker-228/+94
this is the first phase of the "resolver overhaul" project. conceptually, the results of getaddrinfo are a direct product of a list of address results and a list of service results. the new code makes this explicit by computing these lists separately and combining the results. this adds support for services that have both tcp and udp versions, where the caller has not specified which it wants, and eliminates a number of duplicate code paths which were all producing the final output addrinfo structures, but in subtly different ways, making it difficult to implement any of the features which were missing. in addition to the above benefits, the refactoring allows for legacy functions like gethostbyname to be implemented without using the getaddrinfo function itself. such changes to the legacy functions have not yet been made, however. further improvements include matching of service alias names from /etc/services (previously only the primary name was supported), returning multiple results from /etc/hosts (previously only the first matching line was honored), and support for the AI_V4MAPPED and AI_ALL flags. features which remain unimplemented are IDN translations (encoding non-ASCII hostnames for DNS lookup) and the AI_ADDRCONFIG flag. at this point, the DNS-based name resolving code is still based on the old interfaces in __dns.c, albeit somewhat simpler in its use of them. there may be some dead code which could already be removed, but changes to this layer will be a later phase of the resolver overhaul.
2013-11-27reject invalid address families in getaddrinfoRich Felker-0/+3
subsequent code assumes the address family requested is either unspecified or one of IPv4/IPv6, and could malfunction if this constraint is not met, so other address families should be explicitly rejected.
2013-11-25remove duplicate includes from dynlink.c, strfmon.c and getaddrinfo.cSzabolcs Nagy-3/+0
2013-07-24make getaddrinfo with AF_UNSPEC and null host return both IPv4 and v6Rich Felker-14/+23
based on a patch by orc, with indexing and flow control cleaned up a little bit. this code is all going to be replaced at some point in the near future.
2013-02-02fix blank ai_canonname from getaddrinfo for non-CNAMEsRich Felker-1/+1
2012-09-22fix getaddrinfo to accept port 0 (zero)Rich Felker-2/+2
new behavior can be summarized as: inputs that parse completely as a decimal number are treated as one, and rejected only if the result is out of 16-bit range. inputs that do not parse as a decimal number (where strtoul leaves anything left over in the input) are searched in /etc/services.
2012-09-06use restrict everywhere it's required by c99 and/or posix 2008Rich Felker-1/+1
to deal with the fact that the public headers may be used with pre-c99 compilers, __restrict is used in place of restrict, and defined appropriately for any supported compiler. we also avoid the form [restrict] since older versions of gcc rejected it due to a bug in the original c99 standard, and instead use the form *restrict.
2012-07-22remove scanf dependency from getaddrinfo /etc/services supportRich Felker-5/+4
2012-07-22getaddrinfo /etc/services lookup supportRich Felker-3/+16
2012-04-01improve name lookup performance in corner casesRich Felker-1/+1
the buffer in getaddrinfo really only matters when /etc/hosts is huge, but in that case, the huge number of syscalls resulting from a tiny buffer would seriously impact the performance of every name lookup. the buffer in __dns.c has also been enlarged a bit so that typical resolv.conf files will fit fully in the buffer. there's no need to make it so large as to dominate the syscall overhead for large files, because resolv.conf should never be large.
2011-08-01port numbers should always be interpreted as decimalRich Felker-1/+1
per POSIX and RFC 3493: If the specified address family is AF_INET, AF_INET6, or AF_UNSPEC, the service can be specified as a string specifying a decimal port number. 021 is a valid decimal number, therefore, interpreting it as octal seems to be non-conformant.
2011-04-20disallow blank strings as service or host nameRich Felker-0/+3
2011-04-08return the requested string as the "canonical name" for numeric addressesRich Felker-0/+1
previously NULL was returned in ai_canonname, resulting in crashes in some callers. this behavior was incorrect. note however that the new behavior differs from glibc, which performs reverse dns lookups. POSIX is very clear that a reverse DNS lookup must not be performed for numeric addresses.
2011-03-25fix all implicit conversion between signed/unsigned pointersRich Felker-1/+1
sadly the C language does not specify any such implicit conversion, so this is not a matter of just fixing warnings (as gcc treats it) but actual errors. i would like to revisit a number of these changes and possibly revise the types used to reduce the number of casts required.
2011-02-12initial check-in, version 0.5.0v0.5.0Rich Felker-0/+224