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