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