1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * lib/libnsl/nss/gethostbyname_r.c 31 * 32 * gethostbyname_r() is defined in this file. It is implemented on top of 33 * _get_hostserv_inetnetdir_byname() which is also used to implement 34 * netdir_getbyname() for inet family transports. In turn the common code 35 * uses the name service switch policy for "hosts" and "services" unless 36 * the administrator chooses to bypass the name service switch by 37 * specifying third-party supplied nametoaddr libs for inet transports 38 * in /etc/netconfig. 39 * 40 * gethostbyaddr_r() is similarly related to _get_hostserv_inetnetdir_byaddr() 41 * and netdir_getbyaddr(); 42 * 43 * The common code lives in netdir_inet.c. 44 * 45 * gethostent_r(), sethostent() and endhostent() are *not* implemented on top 46 * of the common interface; they go straight to the switch and are 47 * defined in gethostent_r.c. 48 * 49 * There is absolutely no data sharing, not even the stayopen flag or 50 * enumeration state, between gethostbyYY_r() and gethostent_r(); 51 */ 52 53 #include <netdb.h> 54 #include <rpc/trace.h> 55 #include <netdir.h> 56 #include <sys/types.h> 57 #include <nss_netdir.h> 58 #include <string.h> 59 60 extern struct netconfig *__rpc_getconfip(); 61 62 /* 63 * h_errno POLICY: The frontends expect the name service 64 * backends to modify the h_errno in "arg"; _switch_gethostbyYY_r() 65 * will copy that over onto user's h_errnop pointer. This h_errno is 66 * never used for "switching" -- status from nss_search serves 67 * the purpose. There is no explicit zeroing in the case of success. 68 */ 69 70 extern struct hostent * 71 _switch_gethostbyname_r(const char *nam, struct hostent *result, char *buffer, 72 int buflen, int *h_errnop); 73 74 extern struct hostent * 75 _switch_gethostbyaddr_r(const char *addr, int length, int type, 76 struct hostent *result, char *buffer, int buflen, int *h_errnop); 77 78 #ifdef PIC 79 struct hostent * 80 _uncached_gethostbyname_r(const char *nam, struct hostent *result, 81 char *buffer, int buflen, int *h_errnop) 82 { 83 return (_switch_gethostbyname_r(nam, result, 84 buffer, buflen, h_errnop)); 85 } 86 87 struct hostent * 88 _uncached_gethostbyaddr_r(const char *addr, int length, int type, 89 struct hostent *result, char *buffer, int buflen, int *h_errnop) 90 { 91 return (_switch_gethostbyaddr_r(addr, length, type, 92 result, buffer, buflen, h_errnop)); 93 } 94 95 #endif 96 97 extern struct hostent * 98 gethostbyname_r(const char *nam, struct hostent *result, char *buffer, 99 int buflen, int *h_errnop); 100 101 extern struct hostent * 102 gethostbyaddr_r(const char *addr, int length, int type, 103 struct hostent *result, char *buffer, int buflen, int *h_errnop); 104 105 struct hostent * 106 gethostbyname_r(const char *nam, struct hostent *result, char *buffer, 107 int buflen, int *h_errnop) 108 { 109 struct netconfig *nconf; 110 struct nss_netdirbyname_in nssin; 111 union nss_netdirbyname_out nssout; 112 int neterr, dummy; 113 114 trace2(TR_gethostbyname_r, 0, buflen); 115 116 if (h_errnop == NULL) 117 h_errnop = &dummy; 118 119 if (strlen(nam) == 0) { 120 *h_errnop = HOST_NOT_FOUND; 121 trace2(TR_gethostbyname_r, 1, buflen); 122 return ((struct hostent *)NULL); 123 } 124 125 if ((nconf = __rpc_getconfip("udp")) == NULL && 126 (nconf = __rpc_getconfip("tcp")) == NULL) { 127 *h_errnop = NO_RECOVERY; 128 trace2(TR_gethostbyname_r, 1, buflen); 129 return ((struct hostent *)NULL); 130 } 131 132 nssin.op_t = NSS_HOST; 133 nssin.arg.nss.host.name = nam; 134 nssin.arg.nss.host.buf = buffer; 135 nssin.arg.nss.host.buflen = buflen; 136 137 nssout.nss.host.hent = result; 138 nssout.nss.host.herrno_p = h_errnop; 139 140 /* 141 * We pass in nconf and let the implementation of the long-named func 142 * decide whether to use the switch based on nc_nlookups. 143 */ 144 neterr = _get_hostserv_inetnetdir_byname(nconf, &nssin, &nssout); 145 146 (void) freenetconfigent(nconf); 147 if (neterr != ND_OK) { 148 trace2(TR_gethostbyname_r, 1, buflen); 149 return ((struct hostent *)NULL); 150 } 151 trace2(TR_gethostbyname_r, 1, buflen); 152 return (nssout.nss.host.hent); 153 } 154 155 struct hostent * 156 gethostbyaddr_r(const char *addr, int length, int type, 157 struct hostent *result, char *buffer, int buflen, int *h_errnop) 158 { 159 struct netconfig *nconf; 160 struct nss_netdirbyaddr_in nssin; 161 union nss_netdirbyaddr_out nssout; 162 int neterr; 163 164 trace3(TR_gethostbyaddr_r, 0, length, buflen); 165 166 if (type != AF_INET) { 167 *h_errnop = HOST_NOT_FOUND; 168 return ((struct hostent *)NULL); 169 } 170 171 if ((nconf = __rpc_getconfip("udp")) == NULL && 172 (nconf = __rpc_getconfip("tcp")) == NULL) { 173 *h_errnop = NO_RECOVERY; 174 trace3(TR_gethostbyaddr_r, 0, length, buflen); 175 return ((struct hostent *)NULL); 176 } 177 178 nssin.op_t = NSS_HOST; 179 nssin.arg.nss.host.addr = addr; 180 nssin.arg.nss.host.len = length; 181 nssin.arg.nss.host.type = type; 182 nssin.arg.nss.host.buf = buffer; 183 nssin.arg.nss.host.buflen = buflen; 184 185 nssout.nss.host.hent = result; 186 nssout.nss.host.herrno_p = h_errnop; 187 188 /* 189 * We pass in nconf and let the implementation of this long-named func 190 * decide whether to use the switch based on nc_nlookups. 191 */ 192 neterr = _get_hostserv_inetnetdir_byaddr(nconf, &nssin, &nssout); 193 194 (void) freenetconfigent(nconf); 195 if (neterr != ND_OK) { 196 trace3(TR_gethostbyaddr_r, 0, length, buflen); 197 return ((struct hostent *)NULL); 198 } 199 return (nssout.nss.host.hent); 200 } 201