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_dbdefs.h> 39 #include "nss.h" 40 41 #ifdef PIC 42 43 static struct hostent *__process_getipnode(struct hostent *, char *, int, int *, 44 nsc_data_t *); 45 46 struct hostent * 47 _door_getipnodebyname_r(const char *name, struct hostent *result, char *buffer, 48 int buflen, int af_family, int flags, 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 - 2 * sizeof (int)))) { 67 errno = ERANGE; 68 if (h_errnop) 69 *h_errnop = HOST_NOT_FOUND; 70 return (NULL); 71 } 72 73 adata = (sizeof (nsc_call_t) + strlen(name) + 1 + 2 * sizeof (int)); 74 ndata = sizeof (space); 75 space.s_d.nsc_call.nsc_callnumber = GETIPNODEBYNAME; 76 space.s_d.nsc_call.nsc_u.ipnode.af_family = af_family; 77 space.s_d.nsc_call.nsc_u.ipnode.flags = flags; 78 (void) strcpy(space.s_d.nsc_call.nsc_u.ipnode.name, name); 79 sptr = &space.s_d; 80 81 switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) { 82 case SUCCESS: /* positive cache hit */ 83 break; 84 case NOTFOUND: /* negative cache hit */ 85 if (h_errnop) 86 *h_errnop = space.s_d.nsc_ret.nsc_errno; 87 return (NULL); 88 default: 89 return ((struct hostent *)_switch_getipnodebyname_r(name, 90 result, buffer, buflen, af_family, flags, h_errnop)); 91 } 92 resptr = __process_getipnode(result, buffer, buflen, h_errnop, sptr); 93 94 /* 95 * check if doors realloced buffer underneath of us.... 96 * munmap or suffer a memory leak 97 */ 98 99 if (sptr != &space.s_d) { 100 munmap((char *)sptr, ndata); /* return memory */ 101 } 102 103 return (resptr); 104 } 105 106 struct hostent * 107 _door_getipnodebyaddr_r(const char *addr, int length, int type, 108 struct hostent *result, char *buffer, int buflen, int *h_errnop) 109 { 110 /* 111 * allocate space on the stack for the nscd to return 112 * host and host alias information 113 */ 114 union { 115 nsc_data_t s_d; 116 char s_b[8192]; 117 } space; 118 nsc_data_t *sptr; 119 int ndata; 120 int adata; 121 struct hostent *resptr = NULL; 122 123 if (addr == NULL) { 124 if (h_errnop) 125 *h_errnop = HOST_NOT_FOUND; 126 return (NULL); 127 } 128 129 ndata = sizeof (space); 130 adata = length + sizeof (nsc_call_t) + 1; 131 sptr = &space.s_d; 132 133 space.s_d.nsc_call.nsc_callnumber = GETIPNODEBYADDR; 134 space.s_d.nsc_call.nsc_u.addr.a_type = type; 135 space.s_d.nsc_call.nsc_u.addr.a_length = length; 136 (void) memcpy(space.s_d.nsc_call.nsc_u.addr.a_data, addr, length); 137 138 switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) { 139 case SUCCESS: /* positive cache hit */ 140 break; 141 case NOTFOUND: /* negative cache hit */ 142 if (h_errnop) 143 *h_errnop = space.s_d.nsc_ret.nsc_errno; 144 return (NULL); 145 default: 146 return ((struct hostent *)_switch_getipnodebyaddr_r(addr, 147 length, type, result, buffer, buflen, h_errnop)); 148 } 149 150 resptr = __process_getipnode(result, buffer, buflen, h_errnop, sptr); 151 152 /* 153 * check if doors realloced buffer underneath of us.... 154 * munmap it or suffer a memory leak 155 */ 156 157 if (sptr != &space.s_d) { 158 munmap((char *)sptr, ndata); /* return memory */ 159 } 160 161 return (resptr); 162 } 163 164 #if !defined(_LP64) 165 166 static struct hostent * 167 __process_getipnode(struct hostent *result, char *buffer, int buflen, 168 int *h_errnop, nsc_data_t *sptr) 169 { 170 int i; 171 172 char *fixed; 173 174 fixed = (char *)ROUND_UP((int)buffer, sizeof (char *)); 175 buflen -= fixed - buffer; 176 buffer = fixed; 177 178 if (buflen + sizeof (struct hostent) 179 < sptr->nsc_ret.nsc_bufferbytesused) { 180 /* 181 * no enough space allocated by user 182 */ 183 errno = ERANGE; 184 if (h_errnop) 185 *h_errnop = HOST_NOT_FOUND; 186 return (NULL); 187 } 188 189 (void) memcpy(buffer, 190 sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent), 191 sptr->nsc_ret.nsc_bufferbytesused - sizeof (struct hostent)); 192 193 sptr->nsc_ret.nsc_u.hst.h_name += (int)buffer; 194 sptr->nsc_ret.nsc_u.hst.h_aliases = 195 (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_aliases + (int)buffer); 196 sptr->nsc_ret.nsc_u.hst.h_addr_list = 197 (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_addr_list + 198 (int)buffer); 199 for (i = 0; sptr->nsc_ret.nsc_u.hst.h_aliases[i]; i++) { 200 sptr->nsc_ret.nsc_u.hst.h_aliases[i] += (int)buffer; 201 } 202 for (i = 0; sptr->nsc_ret.nsc_u.hst.h_addr_list[i]; i++) { 203 sptr->nsc_ret.nsc_u.hst.h_addr_list[i] += (int)buffer; 204 } 205 206 *result = sptr->nsc_ret.nsc_u.hst; 207 208 return (result); 209 } 210 211 #else /* _LP64 */ 212 213 static struct hostent * 214 __process_getipnode(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 *)ROUND_UP(buffer, sizeof (char *)); 230 buflen -= fixed - buffer; 231 buffer = fixed; 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 /* 241 * find out whether the user has provided sufficient space 242 */ 243 start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32); 244 /* 245 * Length of hostname + null 246 */ 247 strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start); 248 /* 249 * length of all aliases + null 250 */ 251 alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases); 252 for (numaliases = 0; alias[numaliases]; numaliases++) 253 strs += 1 + strlen(start + alias[numaliases]); 254 /* 255 * Realign on word boundary 256 */ 257 strs = ROUND_UP(strs, sizeof (char *)); 258 /* 259 * Count the array of pointers to all aliases + null pointer 260 */ 261 strs += sizeof (char *) * (numaliases + 1); 262 /* 263 * length of all addresses + null. Also, account for word alignment. 264 */ 265 address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list); 266 for (numaddrs = 0; address[numaddrs]; numaddrs++) { 267 strs += sptr->nsc_ret.nsc_u.hst.h_length; 268 strs = ROUND_UP(strs, sizeof (char *)); 269 } 270 /* 271 * Count the array of pointers to all addresses + null pointer 272 */ 273 strs += sizeof (char *) * (numaddrs + 1); 274 275 if (buflen < strs) { 276 277 /* no enough space allocated by user */ 278 279 errno = ERANGE; 280 if (h_errnop) 281 *h_errnop = HOST_NOT_FOUND; 282 return (NULL); 283 } 284 285 /* 286 * allocat the h_aliases list and the h_addr_list first to align 'em. 287 */ 288 dest = buffer; 289 aliaseslist = (char **)dest; 290 dest += sizeof (char *) * (numaliases + 1); 291 addrlist = (char **)dest; 292 dest += sizeof (char *) * (numaddrs + 1); 293 /* 294 * fill out h_name 295 */ 296 start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32); 297 (void) strcpy(dest, sptr->nsc_ret.nsc_u.hst.h_name + start); 298 strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start); 299 result->h_name = dest; 300 dest += strs; 301 /* 302 * fill out the h_aliases list 303 */ 304 alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases); 305 for (i = 0; i < numaliases; i++) { 306 (void) strcpy(dest, start + alias[i]); 307 aliaseslist[i] = dest; 308 dest += 1 + strlen(start + alias[i]); 309 } 310 aliaseslist[i] = 0; /* null term ptr chain */ 311 result->h_aliases = aliaseslist; 312 313 /* 314 * fill out the h_addr list 315 */ 316 dest = (char *)ROUND_UP(dest, sizeof (char *)); 317 address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list); 318 for (i = 0; i < numaddrs; i++) { 319 (void) memcpy(dest, start + address[i], 320 sptr->nsc_ret.nsc_u.hst.h_length); 321 addrlist[i] = dest; 322 dest += sptr->nsc_ret.nsc_u.hst.h_length; 323 dest = (char *)ROUND_UP(dest, sizeof (char *)); 324 } 325 326 addrlist[i] = 0; /* null term ptr chain */ 327 328 result->h_addr_list = addrlist; 329 330 result->h_length = sptr->nsc_ret.nsc_u.hst.h_length; 331 result->h_addrtype = sptr->nsc_ret.nsc_u.hst.h_addrtype; 332 333 return (result); 334 } 335 #endif /* _LP64 */ 336 337 #endif /* PIC */ 338