struct servent * getservbyport_r(int port, const char *proto, struct servent *result, char *buffer, int buflen) { struct netconfig *nconf; struct nss_netdirbyaddr_in nssin; union nss_netdirbyaddr_out nssout; int neterr; if ((nconf = __rpc_getconfip("udp")) == NULL && (nconf = __rpc_getconfip("tcp")) == NULL) { return ((struct servent *)NULL); } nssin.op_t = NSS_SERV; nssin.arg.nss.serv.port = port; nssin.arg.nss.serv.proto = proto; nssin.arg.nss.serv.buf = buffer; nssin.arg.nss.serv.buflen = buflen; nssout.nss.serv = result; /* * We pass in nconf and let the implementation of this long-named func * decide whether to use the switch based on nc_nlookups. */ neterr = _get_hostserv_inetnetdir_byaddr(nconf, &nssin, &nssout); (void) freenetconfigent(nconf); if (neterr != ND_OK) { return ((struct servent *)NULL); } return (nssout.nss.serv); }
/* * Remove the mapping between program, version and port. * Calls the pmap service remotely to do the un-mapping. */ bool_t pmap_unset(u_long program, u_long version) { struct netconfig *nconf; bool_t udp_rslt = FALSE; bool_t tcp_rslt = FALSE; nconf = __rpc_getconfip("udp"); if (nconf != NULL) { udp_rslt = rpcb_unset((rpcprog_t)program, (rpcvers_t)version, nconf); freenetconfigent(nconf); } nconf = __rpc_getconfip("tcp"); if (nconf != NULL) { tcp_rslt = rpcb_unset((rpcprog_t)program, (rpcvers_t)version, nconf); freenetconfigent(nconf); } /* * XXX: The call may still succeed even if only one of the * calls succeeded. This was the best that could be * done for backward compatibility. */ return (tcp_rslt || udp_rslt); }
bool_t pmap_set(u_long program, u_long version, int protocol, int port) { bool_t rslt; struct netbuf *na; struct netconfig *nconf; char buf[32]; if ((protocol != IPPROTO_UDP) && (protocol != IPPROTO_TCP)) { return (FALSE); } nconf = __rpc_getconfip(protocol == IPPROTO_UDP ? "udp" : "tcp"); if (nconf == NULL) { return (FALSE); } snprintf(buf, sizeof buf, "0.0.0.0.%d.%d", (((u_int32_t)port) >> 8) & 0xff, port & 0xff); na = uaddr2taddr(nconf, buf); if (na == NULL) { freenetconfigent(nconf); return (FALSE); } rslt = rpcb_set((rpcprog_t)program, (rpcvers_t)version, nconf, na); free(na); freenetconfigent(nconf); return (rslt); }
/* * Create the client des authentication object. Obsoleted by * authdes_seccreate(). */ AUTH * authdes_create(char *servername, uint_t window, struct sockaddr_in *syncaddr, des_block *ckey) { char *hostname = NULL; if (syncaddr) { /* * Change addr to hostname, because that is the way * new interface takes it. */ struct netconfig *nconf; struct netbuf nb_syncaddr; struct nd_hostservlist *hlist; AUTH *nauth; int fd; struct t_info tinfo; if ((nconf = __rpc_getconfip("udp")) == NULL && (nconf = __rpc_getconfip("tcp")) == NULL) goto fallback; /* Transform sockaddr_in to netbuf */ if ((fd = t_open(nconf->nc_device, O_RDWR, &tinfo)) == -1) { (void) freenetconfigent(nconf); goto fallback; } (void) t_close(fd); nb_syncaddr.maxlen = nb_syncaddr.len = __rpc_get_a_size(tinfo.addr); nb_syncaddr.buf = (char *)syncaddr; if (netdir_getbyaddr(nconf, &hlist, &nb_syncaddr)) { (void) freenetconfigent(nconf); goto fallback; } if (hlist && hlist->h_cnt > 0 && hlist->h_hostservs) hostname = hlist->h_hostservs->h_host; nauth = authdes_seccreate(servername, window, hostname, ckey); (void) netdir_free((char *)hlist, ND_HOSTSERVLIST); (void) freenetconfigent(nconf); return (nauth); } fallback: return (authdes_seccreate(servername, window, hostname, ckey)); }
/* * A common server create routine */ static SVCXPRT * svc_com_create(int fd, u_int sendsize, u_int recvsize, const char *netid) { struct netconfig *nconf; SVCXPRT *svc; int madefd = FALSE; int port; struct sockaddr_in sccsin; _DIAGASSERT(netid != NULL); if ((nconf = __rpc_getconfip(netid)) == NULL) { (void) syslog(LOG_ERR, "Could not get %s transport", netid); return (NULL); } if (fd == RPC_ANYSOCK) { fd = __rpc_nconf2fd(nconf); if (fd == -1) { (void) freenetconfigent(nconf); (void) syslog(LOG_ERR, "svc%s_create: could not open connection", netid); return (NULL); } madefd = TRUE; } memset(&sccsin, 0, sizeof sccsin); sccsin.sin_family = AF_INET; (void)bindresvport(fd, &sccsin); switch (nconf->nc_semantics) { case NC_TPI_COTS: case NC_TPI_COTS_ORD: if (listen(fd, SOMAXCONN) == -1) { (void) syslog(LOG_ERR, "svc%s_create: listen(2) failed: %s", netid, strerror(errno)); (void) freenetconfigent(nconf); goto out; } break; default: break; } svc = svc_tli_create(fd, nconf, NULL, sendsize, recvsize); (void) freenetconfigent(nconf); if (svc == NULL) goto out; port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port); svc->xp_port = ntohs(port); return svc; out: if (madefd) (void) close(fd); return NULL; }
bool pmap_set(u_long program, u_long version, int protocol, int port) { bool rslt; struct netbuf *na; struct netconfig *nconf; char buf[32]; if ((protocol != IPPROTO_UDP) && (protocol != IPPROTO_TCP)) return (false); nconf = __rpc_getconfip(protocol == IPPROTO_UDP ? "udp" : "tcp"); if (nconf == NULL) return (false); if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { snprintf(buf, sizeof(buf), "0.0.0.0.%d.%d", (((u_int32_t) port) >> 8) & 0xff, port & 0xff); } else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0) {
/* * A common server create routine */ static SVCXPRT * svc_com_create(int fd, uint_t sendsize, uint_t recvsize, char *netid) { struct netconfig *nconf; SVCXPRT *svc; int madefd = FALSE; int port; int res; if ((nconf = __rpc_getconfip(netid)) == NULL) { (void) syslog(LOG_ERR, "Could not get %s transport", netid); return (NULL); } if (fd == RPC_ANYSOCK) { fd = t_open(nconf->nc_device, O_RDWR, NULL); if (fd == -1) { char errorstr[100]; __tli_sys_strerror(errorstr, sizeof (errorstr), t_errno, errno); (void) syslog(LOG_ERR, "svc%s_create: could not open connection : %s", netid, errorstr); (void) freenetconfigent(nconf); return (NULL); } madefd = TRUE; } res = __rpc_bindresvport(fd, NULL, &port, 8); svc = svc_tli_create(fd, nconf, NULL, sendsize, recvsize); (void) freenetconfigent(nconf); if (svc == NULL) { if (madefd) (void) t_close(fd); return (NULL); } if (res == -1) /* LINTED pointer cast */ port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port); svc->xp_port = ntohs(port); return (svc); }
/* * A common server create routine */ static SVCXPRT * svc_com_create(int fd, u_int sendsize, u_int recvsize, char *netid) { struct netconfig *nconf; SVCXPRT *svc; int madefd = FALSE; int port; struct sockaddr_in sin; if ((nconf = __rpc_getconfip(netid)) == NULL) { (void) syslog(LOG_ERR, "Could not get %s transport", netid); return (NULL); } if (fd == RPC_ANYSOCK) { fd = __rpc_nconf2fd(nconf); if (fd == -1) { (void) freenetconfigent(nconf); (void) syslog(LOG_ERR, "svc%s_create: could not open connection", netid); return (NULL); } madefd = TRUE; } memset(&sin, 0, sizeof sin); sin.sin_family = AF_INET; bindresvport(fd, &sin); _listen(fd, SOMAXCONN); svc = svc_tli_create(fd, nconf, NULL, sendsize, recvsize); (void) freenetconfigent(nconf); if (svc == NULL) { if (madefd) (void)_close(fd); return (NULL); } port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port); svc->xp_port = ntohs(port); return (svc); }
/* * A common clnt create routine */ static CLIENT * clnt_com_create(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers, int *sockp, u_int sendsz, u_int recvsz, const char *tp) { CLIENT *cl; int madefd = FALSE; int fd; struct netconfig *nconf; struct netbuf bindaddr; _DIAGASSERT(raddr != NULL); _DIAGASSERT(sockp != NULL); _DIAGASSERT(tp != NULL); fd = *sockp; mutex_lock(&rpcsoc_lock); if ((nconf = __rpc_getconfip(tp)) == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; mutex_unlock(&rpcsoc_lock); return (NULL); } if (fd == RPC_ANYSOCK) { fd = __rpc_nconf2fd(nconf); if (fd == -1) goto syserror; madefd = TRUE; } if (raddr->sin_port == 0) { u_int proto; u_short sport; mutex_unlock(&rpcsoc_lock); /* pmap_getport is recursive */ proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP; sport = pmap_getport(raddr, (u_long)prog, (u_long)vers, proto); if (sport == 0) { goto err; } raddr->sin_port = htons(sport); mutex_lock(&rpcsoc_lock); /* pmap_getport is recursive */ } /* Transform sockaddr_in to netbuf */ bindaddr.maxlen = bindaddr.len = sizeof (struct sockaddr_in); bindaddr.buf = raddr; (void)bindresvport(fd, NULL); cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers, sendsz, recvsz); if (cl) { if (madefd == TRUE) { /* * The fd should be closed while destroying the handle. */ (void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL); *sockp = fd; } (void) freenetconfigent(nconf); mutex_unlock(&rpcsoc_lock); return (cl); } goto err; syserror: rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; err: if (madefd == TRUE) (void) close(fd); (void) freenetconfigent(nconf); mutex_unlock(&rpcsoc_lock); return (NULL); }
/* * A common clnt create routine */ static CLIENT * clnt_com_create(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers, int *sockp, uint_t sendsz, uint_t recvsz, char *tp) { CLIENT *cl; int madefd = FALSE; int fd = *sockp; struct t_info tinfo; struct netconfig *nconf; int port; struct netbuf bindaddr; bool_t locked = TRUE; (void) mutex_lock(&rpcsoc_lock); if ((nconf = __rpc_getconfip(tp)) == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; (void) mutex_unlock(&rpcsoc_lock); return (NULL); } if (fd == RPC_ANYSOCK) { fd = t_open(nconf->nc_device, O_RDWR, &tinfo); if (fd == -1) goto syserror; RPC_RAISEFD(fd); madefd = TRUE; } else { if (t_getinfo(fd, &tinfo) == -1) goto syserror; } if (raddr->sin_port == 0) { uint_t proto; ushort_t sport; /* pmap_getport is recursive */ (void) mutex_unlock(&rpcsoc_lock); proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP; sport = pmap_getport(raddr, prog, vers, proto); if (sport == 0) { locked = FALSE; goto err; } raddr->sin_port = htons(sport); /* pmap_getport is recursive */ (void) mutex_lock(&rpcsoc_lock); } /* Transform sockaddr_in to netbuf */ bindaddr.maxlen = bindaddr.len = __rpc_get_a_size(tinfo.addr); bindaddr.buf = (char *)raddr; (void) __rpc_bindresvport(fd, NULL, &port, 0); cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers, sendsz, recvsz); if (cl) { if (madefd == TRUE) { /* * The fd should be closed while destroying the handle. */ (void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL); *sockp = fd; } (void) freenetconfigent(nconf); (void) mutex_unlock(&rpcsoc_lock); return (cl); } goto err; syserror: rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; rpc_createerr.cf_error.re_terrno = t_errno; err: if (madefd == TRUE) (void) t_close(fd); (void) freenetconfigent(nconf); if (locked == TRUE) (void) mutex_unlock(&rpcsoc_lock); return (NULL); }
/* * This is the IPv6 interface for "gethostbyaddr". */ struct hostent * getipnodebyaddr(const void *src, size_t len, int type, int *error_num) { struct in6_addr *addr6 = 0; struct in_addr *addr4 = 0; nss_XbyY_buf_t *buf = 0; nss_XbyY_buf_t *res = 0; struct netconfig *nconf; struct hostent *hp = 0; struct nss_netdirbyaddr_in nssin; union nss_netdirbyaddr_out nssout; int neterr; char tmpbuf[64]; if (type == AF_INET6) { if ((addr6 = (struct in6_addr *)src) == NULL) { *error_num = HOST_NOT_FOUND; return (NULL); } } else if (type == AF_INET) { if ((addr4 = (struct in_addr *)src) == NULL) { *error_num = HOST_NOT_FOUND; return (NULL); } } else { *error_num = HOST_NOT_FOUND; return (NULL); } /* * Specific case: query for "::" */ if (type == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(addr6)) { *error_num = HOST_NOT_FOUND; return (NULL); } /* * Step 1: IPv4-mapped address or IPv4 Compat */ if ((type == AF_INET6 && len == 16) && ((IN6_IS_ADDR_V4MAPPED(addr6)) || (IN6_IS_ADDR_V4COMPAT(addr6)))) { if ((buf = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == 0) { *error_num = NO_RECOVERY; return (NULL); } if ((nconf = __rpc_getconfip("udp")) == NULL && (nconf = __rpc_getconfip("tcp")) == NULL) { *error_num = NO_RECOVERY; __IPv6_cleanup(buf); return (NULL); } nssin.op_t = NSS_HOST6; if (IN6_IS_ADDR_V4COMPAT(addr6)) { (void) memcpy(tmpbuf, addr6, sizeof (*addr6)); tmpbuf[10] = 0xffU; tmpbuf[11] = 0xffU; nssin.arg.nss.host.addr = (const char *)tmpbuf; } else { nssin.arg.nss.host.addr = (const char *)addr6; } nssin.arg.nss.host.len = sizeof (struct in6_addr); nssin.arg.nss.host.type = AF_INET6; nssin.arg.nss.host.buf = buf->buffer; nssin.arg.nss.host.buflen = buf->buflen; nssout.nss.host.hent = buf->result; nssout.nss.host.herrno_p = error_num; /* * We pass in nconf and let the implementation of the * long-named func decide whether to use the switch based on * nc_nlookups. */ neterr = _get_hostserv_inetnetdir_byaddr(nconf, &nssin, &nssout); (void) freenetconfigent(nconf); if (neterr != ND_OK) { /* Failover case, try hosts db for v4 address */ if (!gethostbyaddr_r(((char *)addr6) + 12, sizeof (in_addr_t), AF_INET, buf->result, buf->buffer, buf->buflen, error_num)) { __IPv6_cleanup(buf); return (NULL); } /* Found one, now format it into mapped/compat addr */ if ((res = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == 0) { __IPv6_cleanup(buf); *error_num = NO_RECOVERY; return (NULL); } /* Convert IPv4 to mapped/compat address w/name */ hp = res->result; (void) __mapv4tov6(buf->result, 0, res, IN6_IS_ADDR_V4MAPPED(addr6)); __IPv6_cleanup(buf); free(res); return (hp); } /* * At this point, we'll have a v4mapped hostent. If that's * what was passed in, just return. If the request was a compat, * twiggle the two bytes to make the mapped address a compat. */ hp = buf->result; if (IN6_IS_ADDR_V4COMPAT(addr6)) { /* LINTED pointer cast */ addr6 = (struct in6_addr *)hp->h_addr_list[0]; addr6->s6_addr[10] = 0; addr6->s6_addr[11] = 0; } free(buf); return (hp); } /* * Step 2: AF_INET, v4 lookup. Since we're going to search the * ipnodes (v6) path first, we need to treat this as a v4mapped * address. nscd(1m) caches v4 from ipnodes as mapped v6's. The * switch backend knows to lookup v4's (not v4mapped) from the * name services. */ if (type == AF_INET) { struct in6_addr v4mapbuf; addr6 = &v4mapbuf; IN6_INADDR_TO_V4MAPPED(addr4, addr6); if ((nconf = __rpc_getconfip("udp")) == NULL && (nconf = __rpc_getconfip("tcp")) == NULL) { *error_num = NO_RECOVERY; return (NULL); } if ((buf = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == 0) { *error_num = NO_RECOVERY; freenetconfigent(nconf); return (NULL); } nssin.op_t = NSS_HOST6; nssin.arg.nss.host.addr = (const char *)addr6; nssin.arg.nss.host.len = sizeof (struct in6_addr); nssin.arg.nss.host.type = AF_INET6; nssin.arg.nss.host.buf = buf->buffer; nssin.arg.nss.host.buflen = buf->buflen; nssout.nss.host.hent = buf->result; nssout.nss.host.herrno_p = error_num; /* * We pass in nconf and let the implementation of the * long-named func decide whether to use the switch based on * nc_nlookups. */ neterr = _get_hostserv_inetnetdir_byaddr(nconf, &nssin, &nssout); (void) freenetconfigent(nconf); if (neterr != ND_OK) { /* Failover case, try hosts db for v4 address */ hp = buf->result; if (!gethostbyaddr_r(src, len, type, buf->result, buf->buffer, buf->buflen, error_num)) { __IPv6_cleanup(buf); return (NULL); } free(buf); return (hp); } if ((hp = __mappedtov4(buf->result, error_num)) == NULL) { __IPv6_cleanup(buf); return (NULL); } __IPv6_cleanup(buf); return (hp); } /* * Step 3: AF_INET6, plain vanilla v6 getipnodebyaddr() call. */ if (type == AF_INET6) { if ((nconf = __rpc_getconfip("udp")) == NULL && (nconf = __rpc_getconfip("tcp")) == NULL) { *error_num = NO_RECOVERY; return (NULL); } if ((buf = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == 0) { *error_num = NO_RECOVERY; freenetconfigent(nconf); return (NULL); } nssin.op_t = NSS_HOST6; nssin.arg.nss.host.addr = (const char *)addr6; nssin.arg.nss.host.len = len; nssin.arg.nss.host.type = type; nssin.arg.nss.host.buf = buf->buffer; nssin.arg.nss.host.buflen = buf->buflen; nssout.nss.host.hent = buf->result; nssout.nss.host.herrno_p = error_num; /* * We pass in nconf and let the implementation of the * long-named func decide whether to use the switch based on * nc_nlookups. */ neterr = _get_hostserv_inetnetdir_byaddr(nconf, &nssin, &nssout); (void) freenetconfigent(nconf); if (neterr != ND_OK) { __IPv6_cleanup(buf); return (NULL); } free(buf); return (nssout.nss.host.hent); } /* * If we got here, unknown type. */ *error_num = HOST_NOT_FOUND; return (NULL); }
struct hostent * getipnodebyname(const char *name, int af, int flags, int *error_num) { struct hostent *hp = NULL; nss_XbyY_buf_t *buf4 = NULL; nss_XbyY_buf_t *buf6 = NULL; struct netconfig *nconf; struct nss_netdirbyname_in nssin; union nss_netdirbyname_out nssout; int ret; uint_t ipnode_bits; if ((nconf = __rpc_getconfip("udp")) == NULL && (nconf = __rpc_getconfip("tcp")) == NULL) { *error_num = NO_RECOVERY; return (NULL); } ipnode_bits = getipnodebyname_processflags(name, af, flags); /* Make sure we have something to look up. */ if (!(ipnode_bits & (IPNODE_WANTIPV6 | IPNODE_WANTIPV4))) { *error_num = HOST_NOT_FOUND; goto cleanup; } /* * Perform the requested lookups. We always look through * ipnodes first for both IPv4 and IPv6 addresses. Depending * on what was returned and what was needed, we either filter * out the garbage, or ask for more using hosts. */ if (ipnode_bits & IPNODE_LOOKUPIPNODES) { if ((buf6 = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == NULL) { *error_num = NO_RECOVERY; goto cleanup; } nssin.op_t = NSS_HOST6; nssin.arg.nss.host6.name = name; nssin.arg.nss.host6.buf = buf6->buffer; nssin.arg.nss.host6.buflen = buf6->buflen; nssin.arg.nss.host6.af_family = af; nssin.arg.nss.host6.flags = flags; nssout.nss.host.hent = buf6->result; nssout.nss.host.herrno_p = error_num; ret = _get_hostserv_inetnetdir_byname(nconf, &nssin, &nssout); if (ret != ND_OK) { __IPv6_cleanup(buf6); buf6 = NULL; } else if (ipnode_bits & IPNODE_WANTIPV4) { /* * buf6 may have all that we need if we either * only wanted IPv4 addresses if there were no * IPv6 addresses returned, or if there are * IPv4-mapped addresses in buf6. If either * of these are true, then there's no need to * look in hosts. */ if (ipnode_bits & IPNODE_IPV4IFNOIPV6 || __find_mapped(buf6->result, 0) != 0) { ipnode_bits &= ~IPNODE_LOOKUPHOSTS; } else if (!(ipnode_bits & IPNODE_WANTIPV6)) { /* * If all we're looking for are IPv4 * addresses and there are none in * buf6 then buf6 is now useless. */ __IPv6_cleanup(buf6); buf6 = NULL; } } } if (ipnode_bits & IPNODE_LOOKUPHOSTS) { if ((buf4 = __IPv6_alloc(NSS_BUFLEN_HOSTS)) == NULL) { *error_num = NO_RECOVERY; goto cleanup; } nssin.op_t = NSS_HOST; nssin.arg.nss.host.name = name; nssin.arg.nss.host.buf = buf4->buffer; nssin.arg.nss.host.buflen = buf4->buflen; nssout.nss.host.hent = buf4->result; nssout.nss.host.herrno_p = error_num; ret = _get_hostserv_inetnetdir_byname(nconf, &nssin, &nssout); if (ret != ND_OK) { __IPv6_cleanup(buf4); buf4 = NULL; } } if (buf6 == NULL && buf4 == NULL) { *error_num = HOST_NOT_FOUND; goto cleanup; } /* Extract the appropriate addresses from the returned buffer(s). */ switch (af) { case AF_INET6: { if (buf4 != NULL) { nss_XbyY_buf_t *mergebuf; /* * The IPv4 results we have need to be * converted to IPv4-mapped addresses, * conditionally merged with the IPv6 * results, and the end result needs to be * re-ordered. */ mergebuf = __IPv6_alloc(NSS_BUFLEN_IPNODES); if (mergebuf == NULL) { *error_num = NO_RECOVERY; goto cleanup; } hp = __mapv4tov6(buf4->result, ((buf6 != NULL) ? buf6->result : NULL), mergebuf, 1); if (hp != NULL) order_haddrlist_af(AF_INET6, hp->h_addr_list); else *error_num = NO_RECOVERY; free(mergebuf); } if (buf4 == NULL && buf6 != NULL) { hp = buf6->result; /* * We have what we need in buf6, but we may need * to filter out some addresses depending on what * is being asked for. */ if (!(ipnode_bits & IPNODE_WANTIPV4)) hp = __filter_addresses(AF_INET, buf6->result); else if (!(ipnode_bits & IPNODE_WANTIPV6)) hp = __filter_addresses(AF_INET6, buf6->result); /* * We've been asked to unmap v4 addresses. This * situation implies IPNODE_WANTIPV4 and * !IPNODE_WANTIPV6. */ if (hp != NULL && (ipnode_bits & IPNODE_UNMAP)) { /* * Just set hp to a new value, cleanup: will * free the old one */ hp = __mappedtov4(hp, error_num); } else if (hp == NULL) *error_num = NO_ADDRESS; } break; } case AF_INET: /* We could have results in buf6 or buf4, not both */ if (buf6 != NULL) { /* * Extract the IPv4-mapped addresses from buf6 * into hp. */ hp = __mappedtov4(buf6->result, error_num); } else { /* We have what we need in buf4. */ hp = buf4->result; if (ipnode_bits & IPNODE_LITERAL) { /* * There is a special case here for literal * IPv4 address strings. The hosts * front-end sets h_aliases to a one * element array containing a single NULL * pointer (in ndaddr2hent()), while * getipnodebyname() requires h_aliases to * be a NULL pointer itself. We're not * going to change the front-end since it * needs to remain backward compatible for * gethostbyname() and friends. Just set * h_aliases to NULL here instead. */ hp->h_aliases = NULL; } } break; default: break; } cleanup: /* * Free the memory we allocated, but make sure we don't free * the memory we're returning to the caller. */ if (buf6 != NULL) { if (buf6->result == hp) buf6->result = NULL; __IPv6_cleanup(buf6); } if (buf4 != NULL) { if (buf4->result == hp) buf4->result = NULL; __IPv6_cleanup(buf4); } (void) freenetconfigent(nconf); return (hp); }