2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A * This file defines and implements the re-entrant getipnodebyname(), 2N/A * getipnodebyaddr(), and freehostent() routines for IPv6. These routines 2N/A * The number of nanoseconds getipnodebyname() waits before getting 2N/A * fresh interface count information with SIOCGLIFNUM. The default is 2N/A * Bits in the bitfield returned by getipnodebyname_processflags(). 2N/A * IPNODE_WANTIPV6 The user wants IPv6 addresses returned. 2N/A * IPNODE_WANTIPV4 The user wants IPv4 addresses returned. 2N/A * IPNODE_IPV4IFNOIPV6 The user only wants IPv4 addresses returned if no IPv6 2N/A * addresses are returned. 2N/A * IPNODE_LOOKUPIPNODES getipnodebyname() needs to lookup the name in ipnodes. 2N/A * IPNODE_LOOKUPHOSTS getipnodebyname() needs to lookup the name in hosts. 2N/A * IPNODE_ISLITERAL The name supplied is a literal address string. 2N/A * The default set of bits corresponding to a getipnodebyname() flags 2N/A * argument of AI_DEFAULT. 2N/A * Given a name, an address family, and a set of flags, return a 2N/A * bitfield that getipnodebyname() will use. 2N/A * If AI_ADDRCONFIG is specified, we need to determine the number 2N/A * of addresses of each address family configured on the system as 2N/A * Determine what kinds of addresses the user is interested 2N/A * If flag AI_ADDRCONFIG is set, an address is only returned if 2N/A * an address of the same address family is configured on the local 2N/A * system. The handling is separate for loopback vs. non-loopback 2N/A * addresses, in that only the existence of configured non-loopback 2N/A * addresses affects the the handling of non-loopback results, and 2N/A * No external v6 interface is configured, 2N/A * check if v6 loopback address is configured. 2N/A * If yes, allow string representation of "localhost" 2N/A * No external v4 interface is configured, 2N/A * check if v4 loopback address is configured. 2N/A * If yes, allow string representation of 2N/A * "localhost" to be resolved. 2N/A * No external v4 interface is configured, 2N/A * check if v4 loopback address is configured. 2N/A * If yes, allow sting representation of "localhost" 2N/A * If we're not looking for IPv4 addresses, don't bother looking 2N/A * Determine if name is a literal IP address. This will 2N/A * further narrow down what type of lookup we're going to do. 2N/A /* Literal IPv6 address */ 2N/A * In s9 we accepted the literal without filtering independent 2N/A * of what family was passed in hints. We continue to do 2N/A /* Literal IPv4 address */ 2N/A * Check to see if AI_ADDRCONFIG is specified. 2N/A * Unset AI_ADDRCONFIG if name points to a literal address. 2N/A * This diverges from RFC 3493 in that even with no external interfaces 2N/A * configured, we allow literal address strings to be returned. This 2N/A * allows certain applications that are specifically using literal 2N/A * addresses for robustness to continue when the interfaces are being 2N/A /* Check to see if name points to a literal address */ 2N/A /* Unset AI_ADDRCONFIG if name points to a literal address. */ 2N/A /* Make sure we have something to look up. */ 2N/A * Perform the requested lookups. We always look through 2N/A * ipnodes first for both IPv4 and IPv6 addresses. Depending 2N/A * on what was returned and what was needed, we either filter 2N/A * out the garbage, or ask for more using hosts. 2N/A * buf6 may have all that we need if we either 2N/A * only wanted IPv4 addresses if there were no 2N/A * IPv6 addresses returned, or if there are 2N/A * IPv4-mapped addresses in buf6. If either 2N/A * of these are true, then there's no need to 2N/A * If all we're looking for are IPv4 2N/A * addresses and there are none in 2N/A * buf6 then buf6 is now useless. 2N/A /* Should not happen; lets be clear if it does. */ 2N/A /* Extract the appropriate addresses from the returned buffer(s). */ 2N/A * The IPv4 results we have need to be 2N/A * converted to IPv4-mapped addresses, 2N/A * conditionally merged with the IPv6 2N/A * results, and the end result needs to be 2N/A * We have what we need in buf6, but we may need 2N/A * to filter out some addresses depending on what 2N/A * is being asked for. 2N/A /* We could have results in buf6 or buf4, not both */ 2N/A * Extract the IPv4-mapped addresses from buf6 2N/A /* We have what we need in buf4. */ 2N/A * There is a special case here for literal 2N/A * IPv4 address strings. The hosts 2N/A * front-end sets h_aliases to a one 2N/A * element array containing a single NULL 2N/A * pointer (in ndaddr2hent()), while 2N/A * getipnodebyname() requires h_aliases to 2N/A * be a NULL pointer itself. We're not 2N/A * going to change the front-end since it 2N/A * needs to remain backward compatible for 2N/A * gethostbyname() and friends. Just set 2N/A * h_aliases to NULL here instead. 2N/A * Free the memory we allocated, but make sure we don't free 2N/A * the memory we're returning to the caller. 2N/A * This is the IPv6 interface for "gethostbyaddr". 2N/A * Specific case: query for "::" 2N/A * Step 1: IPv4-mapped address or IPv4 Compat 2N/A * We pass in nconf and let the implementation of the 2N/A * long-named func decide whether to use the switch based on 2N/A /* Failover case, try hosts db for v4 address */ 2N/A * At this point, we'll have a v4mapped hostent. If that's 2N/A * what was passed in, just return. If the request was a compat, 2N/A * twiggle the two bytes to make the mapped address a compat. 2N/A /* LINTED pointer cast */ 2N/A * Step 2: AF_INET, v4 lookup. Since we're going to search the 2N/A * ipnodes (v6) path first, we need to treat this as a v4mapped 2N/A * address. nscd(1m) caches v4 from ipnodes as mapped v6's. The 2N/A * switch backend knows to lookup v4's (not v4mapped) from the 2N/A * We pass in nconf and let the implementation of the 2N/A * long-named func decide whether to use the switch based on 2N/A /* Failover case, try hosts db for v4 address */ 2N/A * Step 3: AF_INET6, plain vanilla v6 getipnodebyaddr() call. 2N/A * We pass in nconf and let the implementation of the 2N/A * long-named func decide whether to use the switch based on 2N/A * If we got here, unknown type. 2N/A * We don't need to check this every time someone does a name 2N/A * lookup. Do it every IFNUM_TIMEOUT for each address family. 2N/A * There's no need to protect all of this with a lock. The 2N/A * worst that can happen is that we update the interface count 2N/A * twice instead of once. That's no big deal. 2N/A * We want to determine if this machine knows anything 2N/A * at all about the address family; the status of the 2N/A * interface is less important. Hence, set 2N/A * 'lifn_flags' to zero. 2N/A * Pad the interface count to detect when additional 2N/A * interfaces have been configured between SIOCGLIFNUM 2N/A * Do not include any loopback addresses, 127.0.0.1 for AF_INET 2N/A * and ::1 for AF_INET6, while counting the number of available 2N/A * IPv4 or IPv6 addresses. (RFC 3493 requires this, whenever 2N/A * AI_ADDRCONFIG flag is set) 2N/A * If the process is running without the NET_ACCESS basic privilege, 2N/A * This routine will either convert an IPv4 address to a mapped or compat 2N/A * IPv6 (if he6 == NULL) or merge IPv6 (he6) addresses with mapped 2N/A * v4 (he4) addresses. In either case, the results are returned in res. 2N/A * Caller must provide all buffers. 2N/A * he4 pointer to IPv4 buffer 2N/A * he6 pointer to IPv6 buffer (NULL if not merging v4/v6 2N/A * res pointer to results buffer 2N/A * mapped mapped == 1, map IPv4 : mapped == 0, compat IPv4 2N/A * mapped flag is ignored if he6 != NULL 2N/A * The results are packed into the res->buffer as follows: 2N/A * <--------------- buffer + buflen --------------------------------------> 2N/A * |-----------------|-----------------|----------------|----------------| 2N/A * | pointers vector | pointers vector | aliases grow | addresses grow | 2N/A * | for addresses | for aliases | | | 2N/A * | this way -> | this way -> | <- this way |<- this way | 2N/A * |-----------------|-----------------|----------------|----------------| 2N/A * | grows in PASS 1 | grows in PASS2 | grows in PASS2 | grows in PASS 1| 2N/A * If he6==NULL, map the v4 address into the v6 address format. 2N/A * This is used for getipnodebyaddr() (single address, mapped or 2N/A * compatible) or for v4 mapped for getipnodebyname(), which 2N/A * could be multiple addresses. This could also be a literal 2N/A * address string, which is why there is a inet_addr() call. 2N/A * Has to be room for the pointer to the address we're 2N/A * about to add, as well as the final NULL ptr. 2N/A /* LINTED pointer cast */ 2N/A * Set last array element to NULL and add cname as first alias 2N/A * Literal address string, since we're mapping, we need the IPv6 2N/A * V4 mapped literal address string for h_name. 2N/A return (
host);
/* we're done, return result */ 2N/A * Not a literal address string, so just copy h_name. 2N/A * Pass 2 (IPv4 aliases): 2N/A * Has to be room for the pointer to the address we're 2N/A * about to add, as well as the final NULL ptr. 2N/A * Merge IPv4 mapped addresses with IPv6 addresses. The 2N/A * IPv6 address will go in first, followed by the v4 mapped. 2N/A * Pass 1 (IPv6 addresses): 2N/A * Has to be room for the pointer to the address we're 2N/A * about to add, as well as the final NULL ptr. 2N/A * Pass 1 (IPv4 mapped addresses): 2N/A * Has to be room for the pointer to the address we're 2N/A * about to add, as well as the final NULL ptr. 2N/A /* LINTED pointer cast */ 2N/A * Pass 2 (IPv6 aliases, host name first). We start h_aliases 2N/A * one after where h_addr_list array ended. This is where cname 2N/A * is put, followed by all aliases. Reset count to 0, for index 2N/A * in the h_aliases array. 2N/A * Has to be room for the pointer to the address we're 2N/A * about to add, as well as the final NULL ptr. 2N/A * Pass 2 (IPv4 aliases): 2N/A * Has to be room for the pointer to the address we're 2N/A * about to add, as well as the final NULL ptr. 2N/A * This routine will convert a mapped v4 hostent (AF_INET6) to a 2N/A * AF_INET hostent. If no mapped addrs found, then a NULL is returned. 2N/A * If mapped addrs found, then a new buffer is alloc'd and all the v4 mapped 2N/A * addresses are extracted and copied to it. On sucess, a pointer to a new 2N/A * hostent is returned. 2N/A * There are two possible errors in which case a NULL is returned. 2N/A * One of two error codes are returned: 2N/A * NO_RECOVERY - a malloc failed or the like for which there's no recovery. 2N/A * NO_ADDRESS - after filtering all the v4, there was nothing left! 2N/A * he pointer to hostent with mapped v4 addresses 2N/A * filter_error pointer to return error code 2N/A * pointer to a malloc'd hostent with v4 addresses. 2N/A * The results are packed into the res->buffer as follows: 2N/A * <--------------- buffer + buflen --------------------------------------> 2N/A * |-----------------|-----------------|----------------|----------------| 2N/A * | pointers vector | pointers vector | aliases grow | addresses grow | 2N/A * | for addresses | for aliases | | | 2N/A * | this way -> | this way -> | <- this way |<- this way | 2N/A * |-----------------|-----------------|----------------|----------------| 2N/A * | grows in PASS 1 | grows in PASS2 | grows in PASS2 | grows in PASS 1| 2N/A * "Unmap" the v4 mapped address(es) into a v4 hostent format. 2N/A * This is used for getipnodebyaddr() (single address) or for 2N/A * v4 mapped for getipnodebyname(), which could be multiple 2N/A * addresses. This could also be a literal address string, 2N/A * which is why there is a inet_addr() call. 2N/A /* LINTED pointer cast */ 2N/A * Has to be room for the pointer to the address we're 2N/A * about to add, as well as the final NULL ptr. 2N/A /* LINTED pointer cast */ 2N/A /* LINTED pointer cast */ 2N/A * Set last array element to NULL and add cname as first alias 2N/A /* Copy official host name */ 2N/A * Pass 2 (IPv4 aliases): 2N/A * Has to be room for the pointer to the address we're 2N/A * about to add, as well as the final NULL ptr. 2N/A * This routine takes as input a pointer to a hostent and filters out 2N/A * the type of addresses specified by the af argument. AF_INET 2N/A * indicates that the caller wishes to filter out IPv4-mapped 2N/A * addresses, and AF_INET6 indicates that the caller wishes to filter 2N/A * out IPv6 addresses which aren't IPv4-mapped. If filtering would 2N/A * result in all addresses being filtered out, a NULL pointer is returned. 2N/A * Otherwise, the he pointer passed in is returned, even if no addresses 2N/A * were filtered out. 2N/A /* We filtered everything out. */ 2N/A /* NULL terminate the list and return the hostent */ 2N/A * This routine searches a hostent for v4 mapped IPv6 addresses. 2N/A * he hostent structure to seach 2N/A * find_both flag indicating if only want mapped or both map'd and v6 2N/A * 0 = No mapped addresses 2N/A * 1 = Mapped v4 address found (returns on first one found) 2N/A * 2 = Both v6 and v4 mapped are present 2N/A * If hostent passed in with no addresses, zero will be returned. 2N/A /* LINTED pointer cast */ 2N/A /* save some iterations once both found */ 2N/A * This routine was added specifically for the IPv6 getipnodeby*() APIs. This 2N/A * separates the result pointer (ptr to hostent+data buf) from the 2N/A * nss_XbyY_buf_t ptr (required for nsswitch API). The returned hostent ptr 2N/A * can be passed to freehostent() and freed independently. 2N/A * bufp->result bufp->buffer 2N/A * ------------------------------------------------...-- 2N/A * |struct hostent |addresses aliases | 2N/A * ------------------------------------------------...-- 2N/A * | |<--------bufp->buflen-------------->| 2N/A#
define ALIGN(x) ((((
long)(x)) +
sizeof (
long) -
1) & ~(
sizeof (
long) -
1))
2N/A * This routine is use only for error return cleanup. This will free the 2N/A * hostent pointer, so don't use for successful returns.