1 /*- 2 * Copyright (c) 1994, Garrett Wollman 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * 25 * $FreeBSD: src/lib/libc/net/gethostbynis.c,v 1.28 2006/05/12 15:37:23 ume Exp $ 26 */ 27 28 #include <sys/param.h> 29 #include <sys/socket.h> 30 #include <netinet/in.h> 31 #include <arpa/inet.h> 32 #include <arpa/nameser.h> 33 #include <netdb.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <ctype.h> 37 #include <errno.h> 38 #include <string.h> 39 #include <stdarg.h> 40 #include <nsswitch.h> 41 #include <resolv.h> /* XXX */ 42 #ifdef YP 43 #include <rpc/rpc.h> 44 #include <rpcsvc/yp_prot.h> 45 #include <rpcsvc/ypclnt.h> 46 #endif 47 #include "netdb_private.h" 48 49 #ifdef YP 50 static int 51 _gethostbynis(const char *name, char *map, int af, struct hostent *he, 52 struct hostent_data *hed) 53 { 54 char *p, *bp, *ep; 55 char *cp, **q; 56 char *result; 57 int resultlen, size, addrok = 0; 58 char ypbuf[YPMAXRECORD + 2]; 59 res_state statp; 60 61 statp = __res_state(); 62 switch(af) { 63 case AF_INET: 64 size = NS_INADDRSZ; 65 break; 66 case AF_INET6: 67 size = NS_IN6ADDRSZ; 68 break; 69 default: 70 errno = EAFNOSUPPORT; 71 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 72 return (-1); 73 } 74 75 if (hed->yp_domain == NULL) 76 if (yp_get_default_domain (&hed->yp_domain)) { 77 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 78 return (-1); 79 } 80 81 if (yp_match(hed->yp_domain, map, name, strlen(name), &result, 82 &resultlen)) { 83 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 84 return (-1); 85 } 86 87 /* avoid potential memory leak */ 88 bcopy((char *)result, (char *)&ypbuf, resultlen); 89 ypbuf[resultlen] = '\0'; 90 free(result); 91 result = (char *)&ypbuf; 92 93 if ((cp = index(result, '\n'))) 94 *cp = '\0'; 95 96 cp = strpbrk(result, " \t"); 97 *cp++ = '\0'; 98 he->h_addr_list = hed->h_addr_ptrs; 99 he->h_addr = (char *)hed->host_addr; 100 switch (af) { 101 case AF_INET: 102 addrok = inet_aton(result, (struct in_addr *)hed->host_addr); 103 if (addrok != 1) 104 break; 105 if (statp->options & RES_USE_INET6) { 106 _map_v4v6_address((char *)hed->host_addr, 107 (char *)hed->host_addr); 108 af = AF_INET6; 109 size = NS_IN6ADDRSZ; 110 } 111 break; 112 case AF_INET6: 113 addrok = inet_pton(af, result, hed->host_addr); 114 break; 115 } 116 if (addrok != 1) { 117 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 118 return (-1); 119 } 120 he->h_addr_list[1] = NULL; 121 he->h_length = size; 122 he->h_addrtype = af; 123 while (*cp == ' ' || *cp == '\t') 124 cp++; 125 bp = hed->hostbuf; 126 ep = hed->hostbuf + sizeof hed->hostbuf; 127 he->h_name = bp; 128 q = he->h_aliases = hed->host_aliases; 129 p = strpbrk(cp, " \t"); 130 if (p != NULL) 131 *p++ = '\0'; 132 size = strlen(cp) + 1; 133 if (ep - bp < size) { 134 RES_SET_H_ERRNO(statp, NO_RECOVERY); 135 return (-1); 136 } 137 strlcpy(bp, cp, ep - bp); 138 bp += size; 139 cp = p; 140 while (cp && *cp) { 141 if (*cp == ' ' || *cp == '\t') { 142 cp++; 143 continue; 144 } 145 if (q >= &hed->host_aliases[_MAXALIASES - 1]) 146 break; 147 p = strpbrk(cp, " \t"); 148 if (p != NULL) 149 *p++ = '\0'; 150 size = strlen(cp) + 1; 151 if (ep - bp < size) 152 break; 153 strlcpy(bp, cp, ep - bp); 154 *q++ = bp; 155 bp += size; 156 cp = p; 157 } 158 *q = NULL; 159 return (0); 160 } 161 162 static int 163 _gethostbynisname_r(const char *name, int af, struct hostent *he, 164 struct hostent_data *hed) 165 { 166 char *map; 167 168 switch (af) { 169 case AF_INET: 170 map = "hosts.byname"; 171 break; 172 default: 173 map = "ipnodes.byname"; 174 break; 175 } 176 return (_gethostbynis(name, map, af, he, hed)); 177 } 178 179 static int 180 _gethostbynisaddr_r(const void *addr, socklen_t len __unused, int af, 181 struct hostent *he, struct hostent_data *hed) 182 { 183 char *map; 184 char numaddr[46]; 185 186 switch (af) { 187 case AF_INET: 188 map = "hosts.byaddr"; 189 break; 190 default: 191 map = "ipnodes.byaddr"; 192 break; 193 } 194 if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL) 195 return (-1); 196 return (_gethostbynis(numaddr, map, af, he, hed)); 197 } 198 #endif /* YP */ 199 200 /* XXX _gethostbynisname/_gethostbynisaddr only used by getipnodeby*() */ 201 struct hostent * 202 _gethostbynisname(const char *name, int af) 203 { 204 #ifdef YP 205 struct hostent *he; 206 struct hostent_data *hed; 207 u_long oresopt; 208 int error; 209 res_state statp; 210 211 statp = __res_state(); 212 if ((he = __hostent_init()) == NULL || 213 (hed = __hostent_data_init()) == NULL) { 214 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 215 return (NULL); 216 } 217 218 oresopt = statp->options; 219 statp->options &= ~RES_USE_INET6; 220 error = _gethostbynisname_r(name, af, he, hed); 221 statp->options = oresopt; 222 return (error == 0) ? he : NULL; 223 #else 224 return (NULL); 225 #endif 226 } 227 228 struct hostent * 229 _gethostbynisaddr(const void *addr, socklen_t len, int af) 230 { 231 #ifdef YP 232 struct hostent *he; 233 struct hostent_data *hed; 234 u_long oresopt; 235 int error; 236 res_state statp; 237 238 statp = __res_state(); 239 if ((he = __hostent_init()) == NULL || 240 (hed = __hostent_data_init()) == NULL) { 241 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 242 return (NULL); 243 } 244 245 oresopt = statp->options; 246 statp->options &= ~RES_USE_INET6; 247 error = _gethostbynisaddr_r(addr, len, af, he, hed); 248 statp->options = oresopt; 249 return (error == 0) ? he : NULL; 250 #else 251 return (NULL); 252 #endif 253 } 254 255 int 256 _nis_gethostbyname(void *rval, void *cb_data __unused, va_list ap) 257 { 258 #ifdef YP 259 const char *name; 260 int af; 261 char *buffer; 262 size_t buflen; 263 int *errnop __unused; 264 int *h_errnop; 265 struct hostent *hptr, he; 266 struct hostent_data *hed; 267 res_state statp; 268 269 name = va_arg(ap, const char *); 270 af = va_arg(ap, int); 271 hptr = va_arg(ap, struct hostent *); 272 buffer = va_arg(ap, char *); 273 buflen = va_arg(ap, size_t); 274 errnop = va_arg(ap, int *); 275 h_errnop = va_arg(ap, int *); 276 277 *((struct hostent **)rval) = NULL; 278 279 statp = __res_state(); 280 if ((hed = __hostent_data_init()) == NULL) { 281 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 282 *h_errnop = statp->res_h_errno; 283 return (NS_NOTFOUND); 284 } 285 286 if (_gethostbynisname_r(name, af, &he, hed) != 0) { 287 *h_errnop = statp->res_h_errno; 288 return (NS_NOTFOUND); 289 } 290 if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { 291 *h_errnop = statp->res_h_errno; 292 return (NS_NOTFOUND); 293 } 294 *((struct hostent **)rval) = hptr; 295 return (NS_SUCCESS); 296 #else 297 *((struct hostent **)rval) = NULL; 298 return (NS_UNAVAIL); 299 #endif 300 } 301 302 int 303 _nis_gethostbyaddr(void *rval, void *cb_data __unused, va_list ap) 304 { 305 #ifdef YP 306 const void *addr; 307 socklen_t len; 308 int af; 309 char *buffer; 310 size_t buflen; 311 int *errnop __unused; 312 int *h_errnop; 313 struct hostent *hptr, he; 314 struct hostent_data *hed; 315 res_state statp; 316 317 addr = va_arg(ap, const void *); 318 len = va_arg(ap, socklen_t); 319 af = va_arg(ap, int); 320 hptr = va_arg(ap, struct hostent *); 321 buffer = va_arg(ap, char *); 322 buflen = va_arg(ap, size_t); 323 errnop = va_arg(ap, int *); 324 h_errnop = va_arg(ap, int *); 325 326 *((struct hostent **)rval) = NULL; 327 328 statp = __res_state(); 329 if ((hed = __hostent_data_init()) == NULL) { 330 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 331 *h_errnop = statp->res_h_errno; 332 return (NS_NOTFOUND); 333 } 334 335 if (_gethostbynisaddr_r(addr, len, af, &he, hed) != 0) { 336 *h_errnop = statp->res_h_errno; 337 return (NS_NOTFOUND); 338 } 339 if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { 340 *h_errnop = statp->res_h_errno; 341 return (NS_NOTFOUND); 342 } 343 *((struct hostent **)rval) = hptr; 344 return (NS_SUCCESS); 345 #else 346 *((struct hostent **)rval) = NULL; 347 return (NS_UNAVAIL); 348 #endif 349 } 350