1 /* $NetBSD: getnetnamadr.c,v 1.24 2002/08/27 08:50:49 itojun Exp $ */ 2 3 /* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro 4 * Dep. Matematica Universidade de Coimbra, Portugal, Europe 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 */ 10 /* 11 * Copyright (c) 1983, 1993 12 * The Regents of the University of California. All rights reserved. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by the University of 25 * California, Berkeley and its contributors. 26 * 4. Neither the name of the University nor the names of its contributors 27 * may be used to endorse or promote products derived from this software 28 * without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 */ 42 43 #include <sys/cdefs.h> 44 #if defined(LIBC_SCCS) && !defined(lint) 45 #if 0 46 static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93"; 47 static char sccsid_[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03"; 48 static char rcsid[] = "Id: getnetnamadr.c,v 8.8 1997/06/01 20:34:37 vixie Exp "; 49 #else 50 __RCSID("$NetBSD: getnetnamadr.c,v 1.24 2002/08/27 08:50:49 itojun Exp $"); 51 #endif 52 #endif /* LIBC_SCCS and not lint */ 53 54 #include "namespace.h" 55 #include <sys/types.h> 56 #include <sys/param.h> 57 #include <sys/socket.h> 58 #include <netinet/in.h> 59 #include <arpa/inet.h> 60 #include <arpa/nameser.h> 61 62 #include <assert.h> 63 #include <ctype.h> 64 #include <errno.h> 65 #include <netdb.h> 66 #include <nsswitch.h> 67 #include <resolv.h> 68 #include <stdarg.h> 69 #include <stdio.h> 70 #include <stdlib.h> 71 #include <string.h> 72 73 #ifdef YP 74 #include <rpc/rpc.h> 75 #include <rpcsvc/yp_prot.h> 76 #include <rpcsvc/ypclnt.h> 77 #endif 78 79 #ifdef __weak_alias 80 __weak_alias(getnetbyaddr,_getnetbyaddr) 81 __weak_alias(getnetbyname,_getnetbyname) 82 #endif 83 84 extern int _net_stayopen; 85 86 #define BYADDR 0 87 #define BYNAME 1 88 #define MAXALIASES 35 89 90 #define MAXPACKET (64*1024) 91 92 typedef union { 93 HEADER hdr; 94 u_char buf[MAXPACKET]; 95 } querybuf; 96 97 typedef union { 98 long al; 99 char ac; 100 } align; 101 102 #ifdef YP 103 static char *__ypdomain; 104 static char *__ypcurrent; 105 static int __ypcurrentlen; 106 #endif 107 108 static struct netent net_entry; 109 static char *net_aliases[MAXALIASES]; 110 111 static struct netent *getnetanswer __P((querybuf *, int, int)); 112 int _files_getnetbyaddr __P((void *, void *, va_list)); 113 int _files_getnetbyname __P((void *, void *, va_list)); 114 int _dns_getnetbyaddr __P((void *, void *, va_list)); 115 int _dns_getnetbyname __P((void *, void *, va_list)); 116 #ifdef YP 117 int _yp_getnetbyaddr __P((void *, void *, va_list)); 118 int _yp_getnetbyname __P((void *, void *, va_list)); 119 struct netent *_ypnetent __P((char *)); 120 #endif 121 122 static struct netent * 123 getnetanswer(answer, anslen, net_i) 124 querybuf *answer; 125 int anslen; 126 int net_i; 127 { 128 HEADER *hp; 129 u_char *cp; 130 int n; 131 u_char *eom; 132 int type, class, ancount, qdcount, haveanswer, i, nchar; 133 char aux1[30], aux2[30], ans[30], *in, *st, *pauxt, *bp, **ap, 134 *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0, *ep; 135 static char netbuf[PACKETSZ]; 136 137 _DIAGASSERT(answer != NULL); 138 139 /* 140 * find first satisfactory answer 141 * 142 * answer --> +------------+ ( MESSAGE ) 143 * | Header | 144 * +------------+ 145 * | Question | the question for the name server 146 * +------------+ 147 * | Answer | RRs answering the question 148 * +------------+ 149 * | Authority | RRs pointing toward an authority 150 * | Additional | RRs holding additional information 151 * +------------+ 152 */ 153 eom = answer->buf + anslen; 154 hp = &answer->hdr; 155 ancount = ntohs(hp->ancount); /* #/records in the answer section */ 156 qdcount = ntohs(hp->qdcount); /* #/entries in the question section */ 157 bp = netbuf; 158 ep = netbuf + sizeof(netbuf); 159 cp = answer->buf + HFIXEDSZ; 160 if (!qdcount) { 161 if (hp->aa) 162 h_errno = HOST_NOT_FOUND; 163 else 164 h_errno = TRY_AGAIN; 165 return (NULL); 166 } 167 while (qdcount-- > 0) 168 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 169 ap = net_aliases; 170 *ap = NULL; 171 net_entry.n_aliases = net_aliases; 172 haveanswer = 0; 173 while (--ancount >= 0 && cp < eom) { 174 n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 175 if ((n < 0) || !res_dnok(bp)) 176 break; 177 cp += n; 178 ans[0] = '\0'; 179 (void)strcpy(&ans[0], bp); 180 GETSHORT(type, cp); 181 GETSHORT(class, cp); 182 cp += INT32SZ; /* TTL */ 183 GETSHORT(n, cp); 184 if (class == C_IN && type == T_PTR) { 185 n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 186 if ((n < 0) || !res_hnok(bp)) { 187 cp += n; 188 return (NULL); 189 } 190 cp += n; 191 *ap++ = bp; 192 bp += strlen(bp) + 1; 193 net_entry.n_addrtype = 194 (class == C_IN) ? AF_INET : AF_UNSPEC; 195 haveanswer++; 196 } 197 } 198 if (haveanswer) { 199 *ap = NULL; 200 switch (net_i) { 201 case BYADDR: 202 net_entry.n_name = *net_entry.n_aliases; 203 net_entry.n_net = 0L; 204 break; 205 case BYNAME: 206 in = *net_entry.n_aliases; 207 net_entry.n_name = &ans[0]; 208 aux2[0] = '\0'; 209 for (i = 0; i < 4; i++) { 210 for (st = in, nchar = 0; 211 *st != '.'; 212 st++, nchar++) 213 ; 214 if (nchar != 1 || *in != '0' || flag) { 215 flag = 1; 216 (void)strncpy(paux1, 217 (i==0) ? in : in-1, 218 (size_t)((i==0) ? nchar : nchar+1)); 219 paux1[(i==0) ? nchar : nchar+1] = '\0'; 220 pauxt = paux2; 221 paux2 = strcat(paux1, paux2); 222 paux1 = pauxt; 223 } 224 in = ++st; 225 } 226 net_entry.n_net = inet_network(paux2); 227 break; 228 } 229 net_entry.n_aliases++; 230 return (&net_entry); 231 } 232 h_errno = TRY_AGAIN; 233 return (NULL); 234 } 235 236 /*ARGSUSED*/ 237 int 238 _files_getnetbyaddr(rv, cb_data, ap) 239 void *rv; 240 void *cb_data; 241 va_list ap; 242 { 243 struct netent *p; 244 unsigned long net; 245 int type; 246 247 _DIAGASSERT(rv != NULL); 248 249 net = va_arg(ap, unsigned long); 250 type = va_arg(ap, int); 251 252 setnetent(_net_stayopen); 253 while ((p = getnetent()) != NULL) 254 if (p->n_addrtype == type && p->n_net == net) 255 break; 256 if (!_net_stayopen) 257 endnetent(); 258 *((struct netent **)rv) = p; 259 if (p==NULL) { 260 h_errno = HOST_NOT_FOUND; 261 return NS_NOTFOUND; 262 } 263 return NS_SUCCESS; 264 } 265 266 /*ARGSUSED*/ 267 int 268 _dns_getnetbyaddr(rv, cb_data, ap) 269 void *rv; 270 void *cb_data; 271 va_list ap; 272 { 273 unsigned int netbr[4]; 274 int nn, anslen; 275 querybuf *buf; 276 char qbuf[MAXDNAME]; 277 unsigned long net2; 278 struct netent *np; 279 unsigned long net; 280 int type; 281 282 _DIAGASSERT(rv != NULL); 283 284 net = va_arg(ap, unsigned long); 285 type = va_arg(ap, int); 286 287 if (type != AF_INET) 288 return NS_UNAVAIL; 289 290 for (nn = 4, net2 = net; net2; net2 >>= 8) 291 netbr[--nn] = (unsigned int)(net2 & 0xff); 292 switch (nn) { 293 default: 294 return NS_UNAVAIL; 295 case 3: /* Class A */ 296 snprintf(qbuf, sizeof(qbuf), "0.0.0.%u.in-addr.arpa", netbr[3]); 297 break; 298 case 2: /* Class B */ 299 snprintf(qbuf, sizeof(qbuf), "0.0.%u.%u.in-addr.arpa", 300 netbr[3], netbr[2]); 301 break; 302 case 1: /* Class C */ 303 snprintf(qbuf, sizeof(qbuf), "0.%u.%u.%u.in-addr.arpa", 304 netbr[3], netbr[2], netbr[1]); 305 break; 306 case 0: /* Class D - E */ 307 snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa", 308 netbr[3], netbr[2], netbr[1], netbr[0]); 309 break; 310 } 311 buf = malloc(sizeof(*buf)); 312 if (buf == NULL) { 313 h_errno = NETDB_INTERNAL; 314 return NS_NOTFOUND; 315 } 316 anslen = res_query(qbuf, C_IN, T_PTR, buf->buf, sizeof(buf->buf)); 317 if (anslen < 0) { 318 free(buf); 319 #ifdef DEBUG 320 if (_res.options & RES_DEBUG) 321 printf("res_query failed\n"); 322 #endif 323 return NS_NOTFOUND; 324 } 325 np = getnetanswer(buf, anslen, BYADDR); 326 free(buf); 327 if (np) { 328 /* maybe net should be unsigned? */ 329 unsigned long u_net = net; 330 331 /* Strip trailing zeros */ 332 while ((u_net & 0xff) == 0 && u_net != 0) 333 u_net >>= 8; 334 np->n_net = u_net; 335 } 336 *((struct netent **)rv) = np; 337 if (np == NULL) { 338 h_errno = HOST_NOT_FOUND; 339 return NS_NOTFOUND; 340 } 341 return NS_SUCCESS; 342 } 343 344 345 struct netent * 346 getnetbyaddr(net, net_type) 347 u_long net; 348 int net_type; 349 { 350 struct netent *np; 351 static const ns_dtab dtab[] = { 352 NS_FILES_CB(_files_getnetbyaddr, NULL) 353 { NSSRC_DNS, _dns_getnetbyaddr, NULL }, /* force -DHESIOD */ 354 NS_NIS_CB(_yp_getnetbyaddr, NULL) 355 { 0 } 356 }; 357 358 if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 359 h_errno = NETDB_INTERNAL; 360 return (NULL); 361 } 362 363 np = NULL; 364 h_errno = NETDB_INTERNAL; 365 if (nsdispatch(&np, dtab, NSDB_NETWORKS, "getnetbyaddr", __nsdefaultsrc, 366 net, net_type) != NS_SUCCESS) 367 return (NULL); 368 h_errno = NETDB_SUCCESS; 369 return (np); 370 } 371 372 /*ARGSUSED*/ 373 int 374 _files_getnetbyname(rv, cb_data, ap) 375 void *rv; 376 void *cb_data; 377 va_list ap; 378 { 379 struct netent *p; 380 char **cp; 381 const char *name; 382 383 _DIAGASSERT(rv != NULL); 384 385 name = va_arg(ap, const char *); 386 setnetent(_net_stayopen); 387 while ((p = getnetent()) != NULL) { 388 if (strcasecmp(p->n_name, name) == 0) 389 break; 390 for (cp = p->n_aliases; *cp != 0; cp++) 391 if (strcasecmp(*cp, name) == 0) 392 goto found; 393 } 394 found: 395 if (!_net_stayopen) 396 endnetent(); 397 *((struct netent **)rv) = p; 398 if (p==NULL) { 399 h_errno = HOST_NOT_FOUND; 400 return NS_NOTFOUND; 401 } 402 return NS_SUCCESS; 403 } 404 405 /*ARGSUSED*/ 406 int 407 _dns_getnetbyname(rv, cb_data, ap) 408 void *rv; 409 void *cb_data; 410 va_list ap; 411 { 412 int anslen; 413 querybuf *buf; 414 char qbuf[MAXDNAME]; 415 struct netent *np; 416 const char *net; 417 418 _DIAGASSERT(rv != NULL); 419 420 net = va_arg(ap, const char *); 421 strcpy(&qbuf[0], net); 422 buf = malloc(sizeof(*buf)); 423 if (buf == NULL) { 424 h_errno = NETDB_INTERNAL; 425 return NS_NOTFOUND; 426 } 427 anslen = res_search(qbuf, C_IN, T_PTR, buf->buf, sizeof(buf->buf)); 428 if (anslen < 0) { 429 free(buf); 430 #ifdef DEBUG 431 if (_res.options & RES_DEBUG) 432 printf("res_search failed\n"); 433 #endif 434 return NS_NOTFOUND; 435 } 436 np = getnetanswer(buf, anslen, BYNAME); 437 free(buf); 438 *((struct netent **)rv) = np; 439 if (np == NULL) { 440 h_errno = HOST_NOT_FOUND; 441 return NS_NOTFOUND; 442 } 443 return NS_SUCCESS; 444 } 445 446 struct netent * 447 getnetbyname(net) 448 const char *net; 449 { 450 struct netent *np; 451 static const ns_dtab dtab[] = { 452 NS_FILES_CB(_files_getnetbyname, NULL) 453 { NSSRC_DNS, _dns_getnetbyname, NULL }, /* force -DHESIOD */ 454 NS_NIS_CB(_yp_getnetbyname, NULL) 455 { 0 } 456 }; 457 458 _DIAGASSERT(net != NULL); 459 460 if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 461 h_errno = NETDB_INTERNAL; 462 return (NULL); 463 } 464 465 np = NULL; 466 h_errno = NETDB_INTERNAL; 467 if (nsdispatch(&np, dtab, NSDB_NETWORKS, "getnetbyname", __nsdefaultsrc, 468 net) != NS_SUCCESS) 469 return (NULL); 470 h_errno = NETDB_SUCCESS; 471 return (np); 472 } 473 474 #ifdef YP 475 /*ARGSUSED*/ 476 int 477 _yp_getnetbyaddr(rv, cb_data, ap) 478 void *rv; 479 void *cb_data; 480 va_list ap; 481 { 482 struct netent *np; 483 char qbuf[MAXDNAME]; 484 unsigned int netbr[4]; 485 unsigned long net, net2; 486 int type, r; 487 488 _DIAGASSERT(rv != NULL); 489 490 net = va_arg(ap, unsigned long); 491 type = va_arg(ap, int); 492 493 if (type != AF_INET) 494 return NS_UNAVAIL; 495 496 if (!__ypdomain) { 497 if (_yp_check(&__ypdomain) == 0) 498 return NS_UNAVAIL; 499 } 500 np = NULL; 501 if (__ypcurrent) 502 free(__ypcurrent); 503 __ypcurrent = NULL; 504 for (r = 4, net2 = net; net2; net2 >>= 8) 505 netbr[--r] = (unsigned int)(net2 & 0xff); 506 switch (r) { 507 default: 508 return NS_UNAVAIL; 509 case 3: /* Class A */ 510 snprintf(qbuf, sizeof(qbuf), "%u", netbr[0]); 511 break; 512 case 2: /* Class B */ 513 snprintf(qbuf, sizeof(qbuf), "%u.%u", netbr[0], netbr[1]); 514 break; 515 case 1: /* Class C */ 516 snprintf(qbuf, sizeof(qbuf), "%u.%u.%u", netbr[0], netbr[1], 517 netbr[2]); 518 break; 519 case 0: /* Class D - E */ 520 snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u", netbr[0], netbr[1], 521 netbr[2], netbr[3]); 522 break; 523 } 524 r = yp_match(__ypdomain, "networks.byaddr", qbuf, (int)strlen(qbuf), 525 &__ypcurrent, &__ypcurrentlen); 526 if (r == 0) 527 np = _ypnetent(__ypcurrent); 528 529 *((struct netent **)rv) = np; 530 if (np == NULL) { 531 h_errno = HOST_NOT_FOUND; 532 return NS_NOTFOUND; 533 } 534 return NS_SUCCESS; 535 536 } 537 538 int 539 /*ARGSUSED*/ 540 _yp_getnetbyname(rv, cb_data, ap) 541 void *rv; 542 void *cb_data; 543 va_list ap; 544 { 545 struct netent *np; 546 const char *name; 547 int r; 548 549 _DIAGASSERT(rv != NULL); 550 551 name = va_arg(ap, const char *); 552 553 if (!__ypdomain) { 554 if (_yp_check(&__ypdomain) == 0) 555 return NS_UNAVAIL; 556 } 557 np = NULL; 558 if (__ypcurrent) 559 free(__ypcurrent); 560 __ypcurrent = NULL; 561 r = yp_match(__ypdomain, "networks.byname", name, (int)strlen(name), 562 &__ypcurrent, &__ypcurrentlen); 563 if (r == 0) 564 np = _ypnetent(__ypcurrent); 565 566 *((struct netent **)rv) = np; 567 if (np == NULL) { 568 h_errno = HOST_NOT_FOUND; 569 return NS_NOTFOUND; 570 } 571 return NS_SUCCESS; 572 } 573 574 struct netent * 575 _ypnetent(line) 576 char *line; 577 { 578 char *cp, *p, **q; 579 580 _DIAGASSERT(line != NULL); 581 582 net_entry.n_name = line; 583 cp = strpbrk(line, " \t"); 584 if (cp == NULL) 585 return (NULL); 586 *cp++ = '\0'; 587 while (*cp == ' ' || *cp == '\t') 588 cp++; 589 p = strpbrk(cp, " \t"); 590 if (p != NULL) 591 *p++ = '\0'; 592 net_entry.n_net = inet_network(cp); 593 net_entry.n_addrtype = AF_INET; 594 q = net_entry.n_aliases = net_aliases; 595 if (p != NULL) { 596 cp = p; 597 while (cp && *cp) { 598 if (*cp == ' ' || *cp == '\t') { 599 cp++; 600 continue; 601 } 602 if (q < &net_aliases[MAXALIASES - 1]) 603 *q++ = cp; 604 cp = strpbrk(cp, " \t"); 605 if (cp != NULL) 606 *cp++ = '\0'; 607 } 608 } 609 *q = NULL; 610 611 return (&net_entry); 612 } 613 #endif 614