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