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 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include <pwd.h> 31 #include <strings.h> 32 #include <sys/mman.h> 33 #include <sys/door.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <synch.h> 37 #include <getxby_door.h> 38 #include "nss.h" 39 40 #ifdef PIC 41 42 static struct hostent *process_gethost(struct hostent *, char *, int, int *, 43 nsc_data_t *); 44 45 struct hostent * 46 _door_gethostbyname_r(const char *name, struct hostent *result, char *buffer, 47 int buflen, int *h_errnop) 48 { 49 50 /* 51 * allocate space on the stack for the nscd to return 52 * host and host alias information 53 */ 54 union { 55 nsc_data_t s_d; 56 char s_b[8192]; 57 } space; 58 nsc_data_t *sptr; 59 int ndata; 60 int adata; 61 struct hostent *resptr = NULL; 62 63 if ((name == NULL) || 64 (strlen(name) >= (sizeof (space) - sizeof (nsc_data_t)))) { 65 errno = ERANGE; 66 if (h_errnop) 67 *h_errnop = HOST_NOT_FOUND; 68 return (NULL); 69 } 70 71 adata = (sizeof (nsc_call_t) + strlen(name) + 1); 72 ndata = sizeof (space); 73 space.s_d.nsc_call.nsc_callnumber = GETHOSTBYNAME; 74 (void) strcpy(space.s_d.nsc_call.nsc_u.name, name); 75 sptr = &space.s_d; 76 77 switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) { 78 case SUCCESS: /* positive cache hit */ 79 break; 80 case NOTFOUND: /* negative cache hit */ 81 if (h_errnop) 82 *h_errnop = space.s_d.nsc_ret.nsc_errno; 83 return (NULL); 84 default: 85 return ((struct hostent *)_switch_gethostbyname_r(name, 86 result, buffer, buflen, h_errnop)); 87 } 88 resptr = process_gethost(result, buffer, buflen, h_errnop, sptr); 89 90 /* 91 * check if doors realloced buffer underneath of us.... 92 * munmap or suffer a memory leak 93 */ 94 95 if (sptr != &space.s_d) { 96 munmap((char *)sptr, ndata); /* return memory */ 97 } 98 99 return (resptr); 100 } 101 102 struct hostent * 103 _door_gethostbyaddr_r(const char *addr, int length, int type, 104 struct hostent *result, char *buffer, int buflen, int *h_errnop) 105 { 106 /* 107 * allocate space on the stack for the nscd to return 108 * host and host alias information 109 */ 110 union { 111 nsc_data_t s_d; 112 char s_b[8192]; 113 } space; 114 nsc_data_t *sptr; 115 int ndata; 116 int adata; 117 struct hostent *resptr = NULL; 118 119 if (addr == NULL) { 120 if (h_errnop) 121 *h_errnop = HOST_NOT_FOUND; 122 return (NULL); 123 } 124 125 ndata = sizeof (space); 126 adata = length + sizeof (nsc_call_t) + 1; 127 sptr = &space.s_d; 128 129 space.s_d.nsc_call.nsc_callnumber = GETHOSTBYADDR; 130 space.s_d.nsc_call.nsc_u.addr.a_type = type; 131 space.s_d.nsc_call.nsc_u.addr.a_length = length; 132 (void) memcpy(space.s_d.nsc_call.nsc_u.addr.a_data, addr, length); 133 134 switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) { 135 case SUCCESS: /* positive cache hit */ 136 break; 137 case NOTFOUND: /* negative cache hit */ 138 if (h_errnop) 139 *h_errnop = space.s_d.nsc_ret.nsc_errno; 140 return (NULL); 141 default: 142 return ((struct hostent *)_switch_gethostbyaddr_r(addr, 143 length, type, result, buffer, buflen, h_errnop)); 144 } 145 146 resptr = process_gethost(result, buffer, buflen, h_errnop, sptr); 147 148 /* 149 * check if doors realloced buffer underneath of us.... 150 * munmap it or suffer a memory leak 151 */ 152 153 if (sptr != &space.s_d) { 154 munmap((char *)sptr, ndata); /* return memory */ 155 } 156 157 return (resptr); 158 159 } 160 161 #if !defined(_LP64) 162 163 static struct hostent * 164 process_gethost(struct hostent *result, char *buffer, int buflen, 165 int *h_errnop, nsc_data_t *sptr) 166 { 167 int i; 168 169 char *fixed; 170 171 fixed = (char *)(((int)buffer +3) & ~3); 172 buflen -= fixed - buffer; 173 buffer = fixed; 174 175 if (buflen + sizeof (struct hostent) 176 < sptr->nsc_ret.nsc_bufferbytesused) { 177 /* 178 * no enough space allocated by user 179 */ 180 errno = ERANGE; 181 if (h_errnop) 182 *h_errnop = HOST_NOT_FOUND; 183 return (NULL); 184 } 185 186 (void) memcpy(buffer, 187 sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent), 188 sptr->nsc_ret.nsc_bufferbytesused - sizeof (struct hostent)); 189 190 sptr->nsc_ret.nsc_u.hst.h_name += (int)buffer; 191 sptr->nsc_ret.nsc_u.hst.h_aliases = 192 (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_aliases + (int)buffer); 193 sptr->nsc_ret.nsc_u.hst.h_addr_list = 194 (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_addr_list + 195 (int)buffer); 196 for (i = 0; sptr->nsc_ret.nsc_u.hst.h_aliases[i]; i++) { 197 sptr->nsc_ret.nsc_u.hst.h_aliases[i] += (int)buffer; 198 } 199 for (i = 0; sptr->nsc_ret.nsc_u.hst.h_addr_list[i]; i++) { 200 sptr->nsc_ret.nsc_u.hst.h_addr_list[i] += (int)buffer; 201 } 202 203 *result = sptr->nsc_ret.nsc_u.hst; 204 205 return (result); 206 } 207 208 #else /* _LP64 */ 209 210 #define RNDUP(buf, n) (((uintptr_t)buf + n - 1l) & ~(n - 1l)) 211 212 static struct hostent * 213 process_gethost(struct hostent *result, char *buffer, int buflen, 214 int *h_errnop, nsc_data_t *sptr) 215 { 216 char *fixed; 217 char *dest; 218 char *start; 219 char **aliaseslist; 220 char **addrlist; 221 int *alias; 222 int *address; 223 size_t strs; 224 int numaliases; 225 int numaddrs; 226 int i; 227 228 fixed = (char *)RNDUP(buffer, sizeof (char *)); 229 buflen -= fixed - buffer; 230 buffer = fixed; 231 232 if (buflen < 0) { 233 /* no enough space allocated by user */ 234 errno = ERANGE; 235 if (h_errnop) 236 *h_errnop = HOST_NOT_FOUND; 237 return (NULL); 238 } 239 240 /* find out whether the user has provided sufficient space */ 241 242 start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32); 243 strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start); 244 alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases); 245 for (numaliases = 0; alias[numaliases]; numaliases++) 246 strs += 1 + strlen(start + alias[numaliases]); 247 strs = RNDUP(strs, sizeof (int)); 248 strs += sizeof (char *) * (numaliases + 1); 249 address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list); 250 for (numaddrs = 0; address[numaddrs]; numaddrs++) 251 strs += RNDUP(sptr->nsc_ret.nsc_u.hst.h_length, sizeof (int)); 252 strs += sizeof (char *) * (numaddrs + 1); 253 254 if (buflen < strs) { 255 256 /* no enough space allocated by user */ 257 258 errno = ERANGE; 259 if (h_errnop) 260 *h_errnop = HOST_NOT_FOUND; 261 return (NULL); 262 } 263 264 265 /* 266 * allocat the h_aliases list and the h_addr_list first to align 'em. 267 */ 268 269 dest = buffer; 270 aliaseslist = (char **)dest; 271 dest += sizeof (char *) * (numaliases + 1); 272 addrlist = (char **)dest; 273 dest += sizeof (char *) * (numaddrs + 1); 274 275 /* fill out h_name */ 276 277 start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32); 278 (void) strcpy(dest, sptr->nsc_ret.nsc_u.hst.h_name + start); 279 strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start); 280 result->h_name = dest; 281 dest += strs; 282 283 /* 284 * fill out the h_aliases list 285 */ 286 for (i = 0; i < numaliases; i++) { 287 alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases); 288 (void) strcpy(dest, start + alias[i]); 289 strs = 1 + strlen(start + alias[i]); 290 aliaseslist[i] = dest; 291 dest += strs; 292 } 293 aliaseslist[i] = 0; /* null term ptr chain */ 294 295 result->h_aliases = aliaseslist; 296 297 /* 298 * fill out the h_addr list 299 */ 300 301 dest = (char *)RNDUP(dest, sizeof (int)); 302 303 for (i = 0; i < numaddrs; i++) { 304 address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list); 305 (void) memcpy(dest, start + address[i], 306 sptr->nsc_ret.nsc_u.hst.h_length); 307 strs = sptr->nsc_ret.nsc_u.hst.h_length; 308 addrlist[i] = dest; 309 dest += strs; 310 dest = (char *)RNDUP(dest, sizeof (int)); 311 } 312 313 addrlist[i] = 0; /* null term ptr chain */ 314 315 result->h_addr_list = addrlist; 316 317 result->h_length = sptr->nsc_ret.nsc_u.hst.h_length; 318 result->h_addrtype = sptr->nsc_ret.nsc_u.hst.h_addrtype; 319 320 return (result); 321 } 322 #endif /* _LP64 */ 323 #endif /* PIC */ 324