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 1994-2002 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 == (const char *)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 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 == (const char *)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 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 memcpy(buffer, sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent), 187 sptr->nsc_ret.nsc_bufferbytesused - sizeof (struct hostent)); 188 189 sptr->nsc_ret.nsc_u.hst.h_name += (int)buffer; 190 sptr->nsc_ret.nsc_u.hst.h_aliases = 191 (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_aliases + (int)buffer); 192 sptr->nsc_ret.nsc_u.hst.h_addr_list = 193 (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_addr_list + 194 (int)buffer); 195 for (i = 0; sptr->nsc_ret.nsc_u.hst.h_aliases[i]; i++) { 196 sptr->nsc_ret.nsc_u.hst.h_aliases[i] += (int)buffer; 197 } 198 for (i = 0; sptr->nsc_ret.nsc_u.hst.h_addr_list[i]; i++) { 199 sptr->nsc_ret.nsc_u.hst.h_addr_list[i] += (int)buffer; 200 } 201 202 *result = sptr->nsc_ret.nsc_u.hst; 203 204 return (result); 205 } 206 207 #else /* _LP64 */ 208 209 #define RNDUP(buf, n) (((uintptr_t)buf + n - 1l) & ~(n - 1l)) 210 211 static struct hostent * 212 process_gethost(struct hostent *result, char *buffer, int buflen, 213 int *h_errnop, nsc_data_t *sptr) 214 { 215 char *fixed; 216 char *dest; 217 char *start; 218 char **aliaseslist; 219 char **addrlist; 220 int *alias; 221 int *address; 222 size_t strs; 223 int numaliases; 224 int numaddrs; 225 int i; 226 227 fixed = (char *)RNDUP(buffer, sizeof (char *)); 228 buflen -= fixed - buffer; 229 buffer = fixed; 230 231 if (buflen < 0) { 232 /* no enough space allocated by user */ 233 errno = ERANGE; 234 if (h_errnop) 235 *h_errnop = HOST_NOT_FOUND; 236 return (NULL); 237 } 238 239 /* find out whether the user has provided sufficient space */ 240 241 start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32); 242 strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start); 243 alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases); 244 for (numaliases = 0; alias[numaliases]; numaliases++) 245 strs += 1 + strlen(start + alias[numaliases]); 246 strs = RNDUP(strs, sizeof (int)); 247 strs += sizeof (char *) * (numaliases + 1); 248 address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list); 249 for (numaddrs = 0; address[numaddrs]; numaddrs++) 250 strs += RNDUP(sptr->nsc_ret.nsc_u.hst.h_length, sizeof (int)); 251 strs += sizeof (char *) * (numaddrs + 1); 252 253 if (buflen < strs) { 254 255 /* no enough space allocated by user */ 256 257 errno = ERANGE; 258 if (h_errnop) 259 *h_errnop = HOST_NOT_FOUND; 260 return (NULL); 261 } 262 263 264 /* 265 * allocat the h_aliases list and the h_addr_list first to align 'em. 266 */ 267 268 dest = buffer; 269 aliaseslist = (char **)dest; 270 dest += sizeof (char *) * (numaliases + 1); 271 addrlist = (char **)dest; 272 dest += sizeof (char *) * (numaddrs + 1); 273 274 /* fill out h_name */ 275 276 start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32); 277 strcpy(dest, sptr->nsc_ret.nsc_u.hst.h_name + start); 278 strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start); 279 result->h_name = dest; 280 dest += strs; 281 282 /* 283 * fill out the h_aliases list 284 */ 285 for (i = 0; i < numaliases; i++) { 286 alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases); 287 strcpy(dest, start + alias[i]); 288 strs = 1 + strlen(start + alias[i]); 289 aliaseslist[i] = dest; 290 dest += strs; 291 } 292 aliaseslist[i] = 0; /* null term ptr chain */ 293 294 result->h_aliases = aliaseslist; 295 296 /* 297 * fill out the h_addr list 298 */ 299 300 dest = (char *)RNDUP(dest, sizeof (int)); 301 302 for (i = 0; i < numaddrs; i++) { 303 address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list); 304 memcpy(dest, start + address[i], 305 sptr->nsc_ret.nsc_u.hst.h_length); 306 strs = sptr->nsc_ret.nsc_u.hst.h_length; 307 addrlist[i] = dest; 308 dest += strs; 309 dest = (char *)RNDUP(dest, sizeof (int)); 310 } 311 312 addrlist[i] = 0; /* null term ptr chain */ 313 314 result->h_addr_list = addrlist; 315 316 result->h_length = sptr->nsc_ret.nsc_u.hst.h_length; 317 result->h_addrtype = sptr->nsc_ret.nsc_u.hst.h_addrtype; 318 319 return (result); 320 } 321 #endif /* _LP64 */ 322 #endif /* PIC */ 323