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 61 switch(af) { 62 case AF_INET: 63 size = NS_INADDRSZ; 64 break; 65 case AF_INET6: 66 size = NS_IN6ADDRSZ; 67 break; 68 default: 69 errno = EAFNOSUPPORT; 70 RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); 71 return -1; 72 } 73 74 if (hed->yp_domain == (char *)NULL) 75 if (yp_get_default_domain (&hed->yp_domain)) { 76 RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL); 77 return -1; 78 } 79 80 if (yp_match(hed->yp_domain, map, name, strlen(name), &result, 81 &resultlen)) { 82 RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND); 83 return -1; 84 } 85 86 /* avoid potential memory leak */ 87 bcopy((char *)result, (char *)&ypbuf, resultlen); 88 ypbuf[resultlen] = '\0'; 89 free(result); 90 result = (char *)&ypbuf; 91 92 if ((cp = index(result, '\n'))) 93 *cp = '\0'; 94 95 cp = strpbrk(result, " \t"); 96 *cp++ = '\0'; 97 he->h_addr_list = hed->h_addr_ptrs; 98 he->h_addr = (char *)hed->host_addr; 99 switch (af) { 100 case AF_INET: 101 addrok = inet_aton(result, (struct in_addr *)hed->host_addr); 102 if (addrok != 1) 103 break; 104 if (hed->res->options & RES_USE_INET6) { 105 _map_v4v6_address((char *)hed->host_addr, 106 (char *)hed->host_addr); 107 af = AF_INET6; 108 size = NS_IN6ADDRSZ; 109 } 110 break; 111 case AF_INET6: 112 addrok = inet_pton(af, result, hed->host_addr); 113 break; 114 } 115 if (addrok != 1) { 116 RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND); 117 return -1; 118 } 119 he->h_addr_list[1] = NULL; 120 he->h_length = size; 121 he->h_addrtype = af; 122 while (*cp == ' ' || *cp == '\t') 123 cp++; 124 bp = hed->hostbuf; 125 ep = hed->hostbuf + sizeof hed->hostbuf; 126 he->h_name = bp; 127 q = he->h_aliases = hed->host_aliases; 128 p = strpbrk(cp, " \t"); 129 if (p != NULL) 130 *p++ = '\0'; 131 size = strlen(cp) + 1; 132 if (ep - bp < size) { 133 RES_SET_H_ERRNO(hed->res, NO_RECOVERY); 134 return -1; 135 } 136 strlcpy(bp, cp, ep - bp); 137 bp += size; 138 cp = p; 139 while (cp && *cp) { 140 if (*cp == ' ' || *cp == '\t') { 141 cp++; 142 continue; 143 } 144 if (q >= &hed->host_aliases[_MAXALIASES - 1]) 145 break; 146 p = strpbrk(cp, " \t"); 147 if (p != NULL) 148 *p++ = '\0'; 149 size = strlen(cp) + 1; 150 if (ep - bp < size) 151 break; 152 strlcpy(bp, cp, ep - bp); 153 *q++ = bp; 154 bp += size; 155 cp = p; 156 } 157 *q = NULL; 158 return 0; 159 } 160 161 static int 162 _gethostbynisname_r(const char *name, int af, struct hostent *he, 163 struct hostent_data *hed) 164 { 165 char *map; 166 167 switch (af) { 168 case AF_INET: 169 map = "hosts.byname"; 170 break; 171 default: 172 map = "ipnodes.byname"; 173 break; 174 } 175 return _gethostbynis(name, map, af, he, hed); 176 } 177 178 static int 179 _gethostbynisaddr_r(const char *addr, int len, int af, struct hostent *he, 180 struct hostent_data *hed) 181 { 182 char *map; 183 char numaddr[46]; 184 185 switch (af) { 186 case AF_INET: 187 map = "hosts.byaddr"; 188 break; 189 default: 190 map = "ipnodes.byaddr"; 191 break; 192 } 193 if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL) 194 return -1; 195 return _gethostbynis(numaddr, map, af, he, hed); 196 } 197 #endif /* YP */ 198 199 /* XXX _gethostbynisname/_gethostbynisaddr only used by getipnodeby*() */ 200 struct hostent * 201 _gethostbynisname(const char *name, int af) 202 { 203 #ifdef YP 204 struct hostdata *hd; 205 u_long oresopt; 206 int error; 207 res_state statp; 208 209 statp = __res_state(); 210 if ((hd = __hostdata_init()) == NULL) { 211 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 212 return NULL; 213 } 214 hd->data.res = statp; 215 oresopt = statp->options; 216 statp->options &= ~RES_USE_INET6; 217 error = _gethostbynisname_r(name, af, &hd->host, &hd->data); 218 statp->options = oresopt; 219 return (error == 0) ? &hd->host : NULL; 220 #else 221 return NULL; 222 #endif 223 } 224 225 struct hostent * 226 _gethostbynisaddr(const char *addr, int len, int af) 227 { 228 #ifdef YP 229 struct hostdata *hd; 230 u_long oresopt; 231 int error; 232 res_state statp; 233 234 statp = __res_state(); 235 if ((hd = __hostdata_init()) == NULL) { 236 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 237 return NULL; 238 } 239 hd->data.res = statp; 240 oresopt = statp->options; 241 statp->options &= ~RES_USE_INET6; 242 error = _gethostbynisaddr_r(addr, len, af, &hd->host, &hd->data); 243 statp->options = oresopt; 244 return (error == 0) ? &hd->host : NULL; 245 #else 246 return NULL; 247 #endif 248 } 249 250 int 251 _nis_gethostbyname(void *rval, void *cb_data, va_list ap) 252 { 253 #ifdef YP 254 const char *name; 255 int af; 256 struct hostent *he; 257 struct hostent_data *hed; 258 int error; 259 260 name = va_arg(ap, const char *); 261 af = va_arg(ap, int); 262 he = va_arg(ap, struct hostent *); 263 hed = va_arg(ap, struct hostent_data *); 264 265 error = _gethostbynisname_r(name, af, he, hed); 266 return (error == 0) ? NS_SUCCESS : NS_NOTFOUND; 267 #else 268 return NS_UNAVAIL; 269 #endif 270 } 271 272 int 273 _nis_gethostbyaddr(void *rval, void *cb_data, va_list ap) 274 { 275 #ifdef YP 276 const char *addr; 277 int len; 278 int af; 279 struct hostent *he; 280 struct hostent_data *hed; 281 int error; 282 283 addr = va_arg(ap, const char *); 284 len = va_arg(ap, int); 285 af = va_arg(ap, int); 286 he = va_arg(ap, struct hostent *); 287 hed = va_arg(ap, struct hostent_data *); 288 289 error = _gethostbynisaddr_r(addr, len, af, he, hed); 290 return (error == 0) ? NS_SUCCESS : NS_NOTFOUND; 291 #else 292 return NS_UNAVAIL; 293 #endif 294 } 295