1 /* $NetBSD: getnetnamadr.c,v 1.20 2000/12/20 20:51:08 christos 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.20 2000/12/20 20:51:08 christos 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 <stdio.h> 69 #include <stdlib.h> 70 #include <string.h> 71 72 #ifdef __STDC__ 73 #include <stdarg.h> 74 #else 75 #include <varargs.h> 76 #endif 77 78 #ifdef YP 79 #include <rpc/rpc.h> 80 #include <rpcsvc/yp_prot.h> 81 #include <rpcsvc/ypclnt.h> 82 #endif 83 84 #ifdef __weak_alias 85 __weak_alias(getnetbyaddr,_getnetbyaddr) 86 __weak_alias(getnetbyname,_getnetbyname) 87 #endif 88 89 extern int _net_stayopen; 90 91 #define BYADDR 0 92 #define BYNAME 1 93 #define MAXALIASES 35 94 95 #if PACKETSZ > 1024 96 #define MAXPACKET PACKETSZ 97 #else 98 #define MAXPACKET 1024 99 #endif 100 101 typedef union { 102 HEADER hdr; 103 u_char buf[MAXPACKET]; 104 } querybuf; 105 106 typedef union { 107 long al; 108 char ac; 109 } align; 110 111 #ifdef YP 112 static char *__ypdomain; 113 static char *__ypcurrent; 114 static int __ypcurrentlen; 115 #endif 116 117 static struct netent net_entry; 118 static char *net_aliases[MAXALIASES]; 119 120 static struct netent *getnetanswer __P((querybuf *, int, int)); 121 int _files_getnetbyaddr __P((void *, void *, va_list)); 122 int _files_getnetbyname __P((void *, void *, va_list)); 123 int _dns_getnetbyaddr __P((void *, void *, va_list)); 124 int _dns_getnetbyname __P((void *, void *, va_list)); 125 #ifdef YP 126 int _yp_getnetbyaddr __P((void *, void *, va_list)); 127 int _yp_getnetbyname __P((void *, void *, va_list)); 128 struct netent *_ypnetent __P((char *)); 129 #endif 130 131 static struct netent * 132 getnetanswer(answer, anslen, net_i) 133 querybuf *answer; 134 int anslen; 135 int net_i; 136 { 137 HEADER *hp; 138 u_char *cp; 139 int n; 140 u_char *eom; 141 int type, class, buflen, ancount, qdcount, haveanswer, i, nchar; 142 char aux1[30], aux2[30], ans[30], *in, *st, *pauxt, *bp, **ap, 143 *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0; 144 static char netbuf[PACKETSZ]; 145 146 _DIAGASSERT(answer != NULL); 147 148 /* 149 * find first satisfactory answer 150 * 151 * answer --> +------------+ ( MESSAGE ) 152 * | Header | 153 * +------------+ 154 * | Question | the question for the name server 155 * +------------+ 156 * | Answer | RRs answering the question 157 * +------------+ 158 * | Authority | RRs pointing toward an authority 159 * | Additional | RRs holding additional information 160 * +------------+ 161 */ 162 eom = answer->buf + anslen; 163 hp = &answer->hdr; 164 ancount = ntohs(hp->ancount); /* #/records in the answer section */ 165 qdcount = ntohs(hp->qdcount); /* #/entries in the question section */ 166 bp = netbuf; 167 buflen = sizeof(netbuf); 168 cp = answer->buf + HFIXEDSZ; 169 if (!qdcount) { 170 if (hp->aa) 171 h_errno = HOST_NOT_FOUND; 172 else 173 h_errno = TRY_AGAIN; 174 return (NULL); 175 } 176 while (qdcount-- > 0) 177 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 178 ap = net_aliases; 179 *ap = NULL; 180 net_entry.n_aliases = net_aliases; 181 haveanswer = 0; 182 while (--ancount >= 0 && cp < eom) { 183 n = dn_expand(answer->buf, eom, cp, bp, buflen); 184 if ((n < 0) || !res_dnok(bp)) 185 break; 186 cp += n; 187 ans[0] = '\0'; 188 (void)strcpy(&ans[0], bp); 189 GETSHORT(type, cp); 190 GETSHORT(class, cp); 191 cp += INT32SZ; /* TTL */ 192 GETSHORT(n, cp); 193 if (class == C_IN && type == T_PTR) { 194 n = dn_expand(answer->buf, eom, cp, bp, buflen); 195 if ((n < 0) || !res_hnok(bp)) { 196 cp += n; 197 return (NULL); 198 } 199 cp += n; 200 *ap++ = bp; 201 bp += strlen(bp) + 1; 202 net_entry.n_addrtype = 203 (class == C_IN) ? AF_INET : AF_UNSPEC; 204 haveanswer++; 205 } 206 } 207 if (haveanswer) { 208 *ap = NULL; 209 switch (net_i) { 210 case BYADDR: 211 net_entry.n_name = *net_entry.n_aliases; 212 net_entry.n_net = 0L; 213 break; 214 case BYNAME: 215 in = *net_entry.n_aliases; 216 net_entry.n_name = &ans[0]; 217 aux2[0] = '\0'; 218 for (i = 0; i < 4; i++) { 219 for (st = in, nchar = 0; 220 *st != '.'; 221 st++, nchar++) 222 ; 223 if (nchar != 1 || *in != '0' || flag) { 224 flag = 1; 225 (void)strncpy(paux1, 226 (i==0) ? in : in-1, 227 (size_t)((i==0) ? nchar : nchar+1)); 228 paux1[(i==0) ? nchar : nchar+1] = '\0'; 229 pauxt = paux2; 230 paux2 = strcat(paux1, paux2); 231 paux1 = pauxt; 232 } 233 in = ++st; 234 } 235 net_entry.n_net = inet_network(paux2); 236 break; 237 } 238 net_entry.n_aliases++; 239 return (&net_entry); 240 } 241 h_errno = TRY_AGAIN; 242 return (NULL); 243 } 244 245 /*ARGSUSED*/ 246 int 247 _files_getnetbyaddr(rv, cb_data, ap) 248 void *rv; 249 void *cb_data; 250 va_list ap; 251 { 252 struct netent *p; 253 unsigned long net; 254 int type; 255 256 _DIAGASSERT(rv != NULL); 257 258 net = va_arg(ap, unsigned long); 259 type = va_arg(ap, int); 260 261 setnetent(_net_stayopen); 262 while ((p = getnetent()) != NULL) 263 if (p->n_addrtype == type && p->n_net == net) 264 break; 265 if (!_net_stayopen) 266 endnetent(); 267 *((struct netent **)rv) = p; 268 if (p==NULL) { 269 h_errno = HOST_NOT_FOUND; 270 return NS_NOTFOUND; 271 } 272 return NS_SUCCESS; 273 } 274 275 /*ARGSUSED*/ 276 int 277 _dns_getnetbyaddr(rv, cb_data, ap) 278 void *rv; 279 void *cb_data; 280 va_list ap; 281 { 282 unsigned int netbr[4]; 283 int nn, anslen; 284 querybuf buf; 285 char qbuf[MAXDNAME]; 286 unsigned long net2; 287 struct netent *np; 288 unsigned long net; 289 int type; 290 291 _DIAGASSERT(rv != NULL); 292 293 net = va_arg(ap, unsigned long); 294 type = va_arg(ap, int); 295 296 if (type != AF_INET) 297 return NS_UNAVAIL; 298 299 for (nn = 4, net2 = net; net2; net2 >>= 8) 300 netbr[--nn] = (unsigned int)(net2 & 0xff); 301 switch (nn) { 302 default: 303 return NS_UNAVAIL; 304 case 3: /* Class A */ 305 sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]); 306 break; 307 case 2: /* Class B */ 308 sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]); 309 break; 310 case 1: /* Class C */ 311 sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], 312 netbr[1]); 313 break; 314 case 0: /* Class D - E */ 315 sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], 316 netbr[1], netbr[0]); 317 break; 318 } 319 anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)(void *)&buf, 320 sizeof(buf)); 321 if (anslen < 0) { 322 #ifdef DEBUG 323 if (_res.options & RES_DEBUG) 324 printf("res_query failed\n"); 325 #endif 326 return NS_NOTFOUND; 327 } 328 np = getnetanswer(&buf, anslen, BYADDR); 329 if (np) { 330 /* maybe net should be unsigned? */ 331 unsigned long u_net = net; 332 333 /* Strip trailing zeros */ 334 while ((u_net & 0xff) == 0 && u_net != 0) 335 u_net >>= 8; 336 np->n_net = u_net; 337 } 338 *((struct netent **)rv) = np; 339 if (np == NULL) { 340 h_errno = HOST_NOT_FOUND; 341 return NS_NOTFOUND; 342 } 343 return NS_SUCCESS; 344 } 345 346 347 struct netent * 348 getnetbyaddr(net, net_type) 349 u_long net; 350 int net_type; 351 { 352 struct netent *np; 353 static const ns_dtab dtab[] = { 354 NS_FILES_CB(_files_getnetbyaddr, NULL) 355 { NSSRC_DNS, _dns_getnetbyaddr, NULL }, /* force -DHESIOD */ 356 NS_NIS_CB(_yp_getnetbyaddr, NULL) 357 { 0 } 358 }; 359 360 if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 361 h_errno = NETDB_INTERNAL; 362 return (NULL); 363 } 364 365 np = NULL; 366 h_errno = NETDB_INTERNAL; 367 if (nsdispatch(&np, dtab, NSDB_NETWORKS, "getnetbyaddr", __nsdefaultsrc, 368 net, net_type) != NS_SUCCESS) 369 return (NULL); 370 h_errno = NETDB_SUCCESS; 371 return (np); 372 } 373 374 /*ARGSUSED*/ 375 int 376 _files_getnetbyname(rv, cb_data, ap) 377 void *rv; 378 void *cb_data; 379 va_list ap; 380 { 381 struct netent *p; 382 char **cp; 383 const char *name; 384 385 _DIAGASSERT(rv != NULL); 386 387 name = va_arg(ap, const char *); 388 setnetent(_net_stayopen); 389 while ((p = getnetent()) != NULL) { 390 if (strcasecmp(p->n_name, name) == 0) 391 break; 392 for (cp = p->n_aliases; *cp != 0; cp++) 393 if (strcasecmp(*cp, name) == 0) 394 goto found; 395 } 396 found: 397 if (!_net_stayopen) 398 endnetent(); 399 *((struct netent **)rv) = p; 400 if (p==NULL) { 401 h_errno = HOST_NOT_FOUND; 402 return NS_NOTFOUND; 403 } 404 return NS_SUCCESS; 405 } 406 407 /*ARGSUSED*/ 408 int 409 _dns_getnetbyname(rv, cb_data, ap) 410 void *rv; 411 void *cb_data; 412 va_list ap; 413 { 414 int anslen; 415 querybuf buf; 416 char qbuf[MAXDNAME]; 417 struct netent *np; 418 const char *net; 419 420 _DIAGASSERT(rv != NULL); 421 422 net = va_arg(ap, const char *); 423 strcpy(&qbuf[0], net); 424 anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)(void *)&buf, 425 sizeof(buf)); 426 if (anslen < 0) { 427 #ifdef DEBUG 428 if (_res.options & RES_DEBUG) 429 printf("res_query failed\n"); 430 #endif 431 return NS_NOTFOUND; 432 } 433 np = getnetanswer(&buf, anslen, BYNAME); 434 435 *((struct netent **)rv) = np; 436 if (np == NULL) { 437 h_errno = HOST_NOT_FOUND; 438 return NS_NOTFOUND; 439 } 440 return NS_SUCCESS; 441 } 442 443 struct netent * 444 getnetbyname(net) 445 const char *net; 446 { 447 struct netent *np; 448 static const ns_dtab dtab[] = { 449 NS_FILES_CB(_files_getnetbyname, NULL) 450 { NSSRC_DNS, _dns_getnetbyname, NULL }, /* force -DHESIOD */ 451 NS_NIS_CB(_yp_getnetbyname, NULL) 452 { 0 } 453 }; 454 455 _DIAGASSERT(net != NULL); 456 457 if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 458 h_errno = NETDB_INTERNAL; 459 return (NULL); 460 } 461 462 np = NULL; 463 h_errno = NETDB_INTERNAL; 464 if (nsdispatch(&np, dtab, NSDB_NETWORKS, "getnetbyname", __nsdefaultsrc, 465 net) != NS_SUCCESS) 466 return (NULL); 467 h_errno = NETDB_SUCCESS; 468 return (np); 469 } 470 471 #ifdef YP 472 /*ARGSUSED*/ 473 int 474 _yp_getnetbyaddr(rv, cb_data, ap) 475 void *rv; 476 void *cb_data; 477 va_list ap; 478 { 479 struct netent *np; 480 char qbuf[MAXDNAME]; 481 unsigned int netbr[4]; 482 unsigned long net, net2; 483 int type, r; 484 485 _DIAGASSERT(rv != NULL); 486 487 net = va_arg(ap, unsigned long); 488 type = va_arg(ap, int); 489 490 if (type != AF_INET) 491 return NS_UNAVAIL; 492 493 if (!__ypdomain) { 494 if (_yp_check(&__ypdomain) == 0) 495 return NS_UNAVAIL; 496 } 497 np = NULL; 498 if (__ypcurrent) 499 free(__ypcurrent); 500 __ypcurrent = NULL; 501 for (r = 4, net2 = net; net2; net2 >>= 8) 502 netbr[--r] = (unsigned int)(net2 & 0xff); 503 switch (r) { 504 default: 505 return NS_UNAVAIL; 506 case 3: /* Class A */ 507 sprintf(qbuf, "%u", netbr[0]); 508 break; 509 case 2: /* Class B */ 510 sprintf(qbuf, "%u.%u", netbr[0], netbr[1]); 511 break; 512 case 1: /* Class C */ 513 sprintf(qbuf, "%u.%u.%u", netbr[0], netbr[1], netbr[2]); 514 break; 515 case 0: /* Class D - E */ 516 sprintf(qbuf, "%u.%u.%u.%u", netbr[0], netbr[1], netbr[2], 517 netbr[3]); 518 break; 519 } 520 r = yp_match(__ypdomain, "networks.byaddr", qbuf, (int)strlen(qbuf), 521 &__ypcurrent, &__ypcurrentlen); 522 if (r == 0) 523 np = _ypnetent(__ypcurrent); 524 525 *((struct netent **)rv) = np; 526 if (np == NULL) { 527 h_errno = HOST_NOT_FOUND; 528 return NS_NOTFOUND; 529 } 530 return NS_SUCCESS; 531 532 } 533 534 int 535 /*ARGSUSED*/ 536 _yp_getnetbyname(rv, cb_data, ap) 537 void *rv; 538 void *cb_data; 539 va_list ap; 540 { 541 struct netent *np; 542 const char *name; 543 int r; 544 545 _DIAGASSERT(rv != NULL); 546 547 name = va_arg(ap, const char *); 548 549 if (!__ypdomain) { 550 if (_yp_check(&__ypdomain) == 0) 551 return NS_UNAVAIL; 552 } 553 np = NULL; 554 if (__ypcurrent) 555 free(__ypcurrent); 556 __ypcurrent = NULL; 557 r = yp_match(__ypdomain, "networks.byname", name, (int)strlen(name), 558 &__ypcurrent, &__ypcurrentlen); 559 if (r == 0) 560 np = _ypnetent(__ypcurrent); 561 562 *((struct netent **)rv) = np; 563 if (np == NULL) { 564 h_errno = HOST_NOT_FOUND; 565 return NS_NOTFOUND; 566 } 567 return NS_SUCCESS; 568 } 569 570 struct netent * 571 _ypnetent(line) 572 char *line; 573 { 574 char *cp, *p, **q; 575 576 _DIAGASSERT(line != NULL); 577 578 net_entry.n_name = line; 579 cp = strpbrk(line, " \t"); 580 if (cp == NULL) 581 return (NULL); 582 *cp++ = '\0'; 583 while (*cp == ' ' || *cp == '\t') 584 cp++; 585 p = strpbrk(cp, " \t"); 586 if (p != NULL) 587 *p++ = '\0'; 588 net_entry.n_net = inet_network(cp); 589 net_entry.n_addrtype = AF_INET; 590 q = net_entry.n_aliases = net_aliases; 591 if (p != NULL) { 592 cp = p; 593 while (cp && *cp) { 594 if (*cp == ' ' || *cp == '\t') { 595 cp++; 596 continue; 597 } 598 if (q < &net_aliases[MAXALIASES - 1]) 599 *q++ = cp; 600 cp = strpbrk(cp, " \t"); 601 if (cp != NULL) 602 *cp++ = '\0'; 603 } 604 } 605 *q = NULL; 606 607 return (&net_entry); 608 } 609 #endif 610