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 26 #include <sys/cdefs.h> 27 __FBSDID("$FreeBSD$"); 28 29 #include <sys/param.h> 30 #include <sys/socket.h> 31 #include <netinet/in.h> 32 #include <arpa/inet.h> 33 #include <arpa/nameser.h> 34 #include <netdb.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <ctype.h> 38 #include <errno.h> 39 #include <string.h> 40 #include <stdarg.h> 41 #include <nsswitch.h> 42 #include <resolv.h> /* XXX */ 43 #ifdef YP 44 #include <rpc/rpc.h> 45 #include <rpcsvc/yp_prot.h> 46 #include <rpcsvc/ypclnt.h> 47 #endif 48 #include "netdb_private.h" 49 50 #ifdef YP 51 static int 52 _gethostbynis(const char *name, char *map, int af, struct hostent *he, 53 struct hostent_data *hed) 54 { 55 char *p, *bp, *ep; 56 char *cp, **q; 57 char *result; 58 int resultlen, size, addrok = 0; 59 char ypbuf[YPMAXRECORD + 2]; 60 res_state statp; 61 62 statp = __res_state(); 63 switch(af) { 64 case AF_INET: 65 size = NS_INADDRSZ; 66 break; 67 case AF_INET6: 68 size = NS_IN6ADDRSZ; 69 break; 70 default: 71 errno = EAFNOSUPPORT; 72 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 73 return (-1); 74 } 75 76 if (hed->yp_domain == (char *)NULL) 77 if (yp_get_default_domain (&hed->yp_domain)) { 78 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 79 return (-1); 80 } 81 82 if (yp_match(hed->yp_domain, map, name, strlen(name), &result, 83 &resultlen)) { 84 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 85 return (-1); 86 } 87 88 /* avoid potential memory leak */ 89 bcopy((char *)result, (char *)&ypbuf, resultlen); 90 ypbuf[resultlen] = '\0'; 91 free(result); 92 result = (char *)&ypbuf; 93 94 if ((cp = strchr(result, '\n'))) 95 *cp = '\0'; 96 97 cp = strpbrk(result, " \t"); 98 *cp++ = '\0'; 99 he->h_addr_list = hed->h_addr_ptrs; 100 he->h_addr = (char *)hed->host_addr; 101 switch (af) { 102 case AF_INET: 103 addrok = inet_aton(result, (struct in_addr *)hed->host_addr); 104 if (addrok != 1) 105 break; 106 if (statp->options & RES_USE_INET6) { 107 _map_v4v6_address((char *)hed->host_addr, 108 (char *)hed->host_addr); 109 af = AF_INET6; 110 size = NS_IN6ADDRSZ; 111 } 112 break; 113 case AF_INET6: 114 addrok = inet_pton(af, result, hed->host_addr); 115 break; 116 } 117 if (addrok != 1) { 118 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 119 return (-1); 120 } 121 he->h_addr_list[1] = NULL; 122 he->h_length = size; 123 he->h_addrtype = af; 124 while (*cp == ' ' || *cp == '\t') 125 cp++; 126 bp = hed->hostbuf; 127 ep = hed->hostbuf + sizeof hed->hostbuf; 128 he->h_name = bp; 129 q = he->h_aliases = hed->host_aliases; 130 p = strpbrk(cp, " \t"); 131 if (p != NULL) 132 *p++ = '\0'; 133 size = strlen(cp) + 1; 134 if (ep - bp < size) { 135 RES_SET_H_ERRNO(statp, NO_RECOVERY); 136 return (-1); 137 } 138 strlcpy(bp, cp, ep - bp); 139 bp += size; 140 cp = p; 141 while (cp && *cp) { 142 if (*cp == ' ' || *cp == '\t') { 143 cp++; 144 continue; 145 } 146 if (q >= &hed->host_aliases[_MAXALIASES - 1]) 147 break; 148 p = strpbrk(cp, " \t"); 149 if (p != NULL) 150 *p++ = '\0'; 151 size = strlen(cp) + 1; 152 if (ep - bp < size) 153 break; 154 strlcpy(bp, cp, ep - bp); 155 *q++ = bp; 156 bp += size; 157 cp = p; 158 } 159 *q = NULL; 160 return (0); 161 } 162 163 static int 164 _gethostbynisname_r(const char *name, int af, struct hostent *he, 165 struct hostent_data *hed) 166 { 167 char *map; 168 169 switch (af) { 170 case AF_INET: 171 map = "hosts.byname"; 172 break; 173 default: 174 map = "ipnodes.byname"; 175 break; 176 } 177 return (_gethostbynis(name, map, af, he, hed)); 178 } 179 180 static int 181 _gethostbynisaddr_r(const void *addr, socklen_t len, int af, 182 struct hostent *he, struct hostent_data *hed) 183 { 184 char *map; 185 char numaddr[46]; 186 187 switch (af) { 188 case AF_INET: 189 map = "hosts.byaddr"; 190 break; 191 default: 192 map = "ipnodes.byaddr"; 193 break; 194 } 195 if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL) 196 return (-1); 197 return (_gethostbynis(numaddr, map, af, he, hed)); 198 } 199 #endif /* YP */ 200 201 /* XXX _gethostbynisname/_gethostbynisaddr only used by getipnodeby*() */ 202 struct hostent * 203 _gethostbynisname(const char *name, int af) 204 { 205 #ifdef YP 206 struct hostent *he; 207 struct hostent_data *hed; 208 u_long oresopt; 209 int error; 210 res_state statp; 211 212 statp = __res_state(); 213 if ((he = __hostent_init()) == NULL || 214 (hed = __hostent_data_init()) == NULL) { 215 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 216 return (NULL); 217 } 218 219 oresopt = statp->options; 220 statp->options &= ~RES_USE_INET6; 221 error = _gethostbynisname_r(name, af, he, hed); 222 statp->options = oresopt; 223 return (error == 0) ? he : NULL; 224 #else 225 return (NULL); 226 #endif 227 } 228 229 struct hostent * 230 _gethostbynisaddr(const void *addr, socklen_t len, int af) 231 { 232 #ifdef YP 233 struct hostent *he; 234 struct hostent_data *hed; 235 u_long oresopt; 236 int error; 237 res_state statp; 238 239 statp = __res_state(); 240 if ((he = __hostent_init()) == NULL || 241 (hed = __hostent_data_init()) == NULL) { 242 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 243 return (NULL); 244 } 245 246 oresopt = statp->options; 247 statp->options &= ~RES_USE_INET6; 248 error = _gethostbynisaddr_r(addr, len, af, he, hed); 249 statp->options = oresopt; 250 return (error == 0) ? he : NULL; 251 #else 252 return (NULL); 253 #endif 254 } 255 256 int 257 _nis_gethostbyname(void *rval, void *cb_data, va_list ap) 258 { 259 #ifdef YP 260 const char *name; 261 int af; 262 char *buffer; 263 size_t buflen; 264 int *errnop, *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 *errnop = errno; 292 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 293 *h_errnop = statp->res_h_errno; 294 return (NS_RETURN); 295 } 296 *((struct hostent **)rval) = hptr; 297 return (NS_SUCCESS); 298 #else 299 *((struct hostent **)rval) = NULL; 300 return (NS_UNAVAIL); 301 #endif 302 } 303 304 int 305 _nis_gethostbyaddr(void *rval, void *cb_data, va_list ap) 306 { 307 #ifdef YP 308 const void *addr; 309 socklen_t len; 310 int af; 311 char *buffer; 312 size_t buflen; 313 int *errnop, *h_errnop; 314 struct hostent *hptr, he; 315 struct hostent_data *hed; 316 res_state statp; 317 318 addr = va_arg(ap, const void *); 319 len = va_arg(ap, socklen_t); 320 af = va_arg(ap, int); 321 hptr = va_arg(ap, struct hostent *); 322 buffer = va_arg(ap, char *); 323 buflen = va_arg(ap, size_t); 324 errnop = va_arg(ap, int *); 325 h_errnop = va_arg(ap, int *); 326 327 *((struct hostent **)rval) = NULL; 328 329 statp = __res_state(); 330 if ((hed = __hostent_data_init()) == NULL) { 331 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 332 *h_errnop = statp->res_h_errno; 333 return (NS_NOTFOUND); 334 } 335 336 if (_gethostbynisaddr_r(addr, len, af, &he, hed) != 0) { 337 *h_errnop = statp->res_h_errno; 338 return (NS_NOTFOUND); 339 } 340 if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { 341 *errnop = errno; 342 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 343 *h_errnop = statp->res_h_errno; 344 return (NS_RETURN); 345 } 346 *((struct hostent **)rval) = hptr; 347 return (NS_SUCCESS); 348 #else 349 *((struct hostent **)rval) = NULL; 350 return (NS_UNAVAIL); 351 #endif 352 } 353