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