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