1 /* $NetBSD: nametoaddr.c,v 1.3 2017/01/24 22:29:28 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 * 23 * Name to id translation routines used by the scanner. 24 * These functions are not time critical. 25 */ 26 27 #include <sys/cdefs.h> 28 __RCSID("$NetBSD: nametoaddr.c,v 1.3 2017/01/24 22:29:28 christos Exp $"); 29 30 #ifdef HAVE_CONFIG_H 31 #include "config.h" 32 #endif 33 34 #ifdef DECNETLIB 35 #include <sys/types.h> 36 #include <netdnet/dnetdb.h> 37 #endif 38 39 #ifdef _WIN32 40 #include <pcap-stdinc.h> 41 42 #ifdef INET6 43 /* 44 * To quote the MSDN page for getaddrinfo() at 45 * 46 * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx 47 * 48 * "Support for getaddrinfo on Windows 2000 and older versions 49 * The getaddrinfo function was added to the Ws2_32.dll on Windows XP and 50 * later. To execute an application that uses this function on earlier 51 * versions of Windows, then you need to include the Ws2tcpip.h and 52 * Wspiapi.h files. When the Wspiapi.h include file is added, the 53 * getaddrinfo function is defined to the WspiapiGetAddrInfo inline 54 * function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo 55 * function is implemented in such a way that if the Ws2_32.dll or the 56 * Wship6.dll (the file containing getaddrinfo in the IPv6 Technology 57 * Preview for Windows 2000) does not include getaddrinfo, then a 58 * version of getaddrinfo is implemented inline based on code in the 59 * Wspiapi.h header file. This inline code will be used on older Windows 60 * platforms that do not natively support the getaddrinfo function." 61 * 62 * We use getaddrinfo(), so we include Wspiapi.h here. pcap-stdinc.h 63 * includes Ws2tcpip.h, so we don't need to include it ourselves. 64 */ 65 #include <Wspiapi.h> 66 #endif 67 68 #else /* _WIN32 */ 69 70 #include <sys/param.h> 71 #include <sys/types.h> /* concession to AIX */ 72 #include <sys/socket.h> 73 #include <sys/time.h> 74 75 #include <netinet/in.h> 76 #endif /* _WIN32 */ 77 78 #ifndef _WIN32 79 #ifdef HAVE_ETHER_HOSTTON 80 /* 81 * XXX - do we need any of this if <netinet/if_ether.h> doesn't declare 82 * ether_hostton()? 83 */ 84 #ifdef HAVE_NETINET_IF_ETHER_H 85 struct mbuf; /* Squelch compiler warnings on some platforms for */ 86 struct rtentry; /* declarations in <net/if.h> */ 87 #include <net/if.h> /* for "struct ifnet" in "struct arpcom" on Solaris */ 88 #include <netinet/if_ether.h> 89 #endif /* HAVE_NETINET_IF_ETHER_H */ 90 #ifdef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON 91 #include <netinet/ether.h> 92 #endif /* NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */ 93 #endif /* HAVE_ETHER_HOSTTON */ 94 #include <arpa/inet.h> 95 #include <netdb.h> 96 #endif /* _WIN32 */ 97 98 #include <ctype.h> 99 #include <errno.h> 100 #include <stdlib.h> 101 #include <string.h> 102 #include <stdio.h> 103 104 #include "pcap-int.h" 105 106 #include "gencode.h" 107 #include <pcap/namedb.h> 108 #include "nametoaddr.h" 109 110 #ifdef HAVE_OS_PROTO_H 111 #include "os-proto.h" 112 #endif 113 114 #ifndef NTOHL 115 #define NTOHL(x) (x) = ntohl(x) 116 #define NTOHS(x) (x) = ntohs(x) 117 #endif 118 119 static inline int xdtoi(int); 120 121 /* 122 * Convert host name to internet address. 123 * Return 0 upon failure. 124 */ 125 bpf_u_int32 ** 126 pcap_nametoaddr(const char *name) 127 { 128 #ifndef h_addr 129 static bpf_u_int32 *hlist[2]; 130 #endif 131 bpf_u_int32 **p; 132 struct hostent *hp; 133 134 if ((hp = gethostbyname(name)) != NULL) { 135 #ifndef h_addr 136 hlist[0] = (bpf_u_int32 *)hp->h_addr; 137 NTOHL(hp->h_addr); 138 return hlist; 139 #else 140 for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p) 141 NTOHL(**p); 142 return (bpf_u_int32 **)hp->h_addr_list; 143 #endif 144 } 145 else 146 return 0; 147 } 148 149 #ifdef INET6 150 struct addrinfo * 151 pcap_nametoaddrinfo(const char *name) 152 { 153 struct addrinfo hints, *res; 154 int error; 155 156 memset(&hints, 0, sizeof(hints)); 157 hints.ai_family = PF_UNSPEC; 158 hints.ai_socktype = SOCK_STREAM; /*not really*/ 159 hints.ai_protocol = IPPROTO_TCP; /*not really*/ 160 error = getaddrinfo(name, NULL, &hints, &res); 161 if (error) 162 return NULL; 163 else 164 return res; 165 } 166 #endif /*INET6*/ 167 168 /* 169 * Convert net name to internet address. 170 * Return 0 upon failure. 171 */ 172 bpf_u_int32 173 pcap_nametonetaddr(const char *name) 174 { 175 #ifndef _WIN32 176 struct netent *np; 177 178 if ((np = getnetbyname(name)) != NULL) 179 return np->n_net; 180 else 181 return 0; 182 #else 183 /* 184 * There's no "getnetbyname()" on Windows. 185 * 186 * XXX - I guess we could use the BSD code to read 187 * C:\Windows\System32\drivers\etc/networks, assuming 188 * that's its home on all the versions of Windows 189 * we use, but that file probably just has the loopback 190 * network on 127/24 on 99 44/100% of Windows machines. 191 * 192 * (Heck, these days it probably just has that on 99 44/100% 193 * of *UN*X* machines.) 194 */ 195 return 0; 196 #endif 197 } 198 199 /* 200 * Convert a port name to its port and protocol numbers. 201 * We assume only TCP or UDP. 202 * Return 0 upon failure. 203 */ 204 int 205 pcap_nametoport(const char *name, int *port, int *proto) 206 { 207 struct servent *sp; 208 int tcp_port = -1; 209 int udp_port = -1; 210 211 /* 212 * We need to check /etc/services for ambiguous entries. 213 * If we find the ambiguous entry, and it has the 214 * same port number, change the proto to PROTO_UNDEF 215 * so both TCP and UDP will be checked. 216 */ 217 sp = getservbyname(name, "tcp"); 218 if (sp != NULL) tcp_port = ntohs(sp->s_port); 219 sp = getservbyname(name, "udp"); 220 if (sp != NULL) udp_port = ntohs(sp->s_port); 221 if (tcp_port >= 0) { 222 *port = tcp_port; 223 *proto = IPPROTO_TCP; 224 if (udp_port >= 0) { 225 if (udp_port == tcp_port) 226 *proto = PROTO_UNDEF; 227 #ifdef notdef 228 else 229 /* Can't handle ambiguous names that refer 230 to different port numbers. */ 231 warning("ambiguous port %s in /etc/services", 232 name); 233 #endif 234 } 235 return 1; 236 } 237 if (udp_port >= 0) { 238 *port = udp_port; 239 *proto = IPPROTO_UDP; 240 return 1; 241 } 242 #if defined(ultrix) || defined(__osf__) 243 /* Special hack in case NFS isn't in /etc/services */ 244 if (strcmp(name, "nfs") == 0) { 245 *port = 2049; 246 *proto = PROTO_UNDEF; 247 return 1; 248 } 249 #endif 250 return 0; 251 } 252 253 /* 254 * Convert a string in the form PPP-PPP, where correspond to ports, to 255 * a starting and ending port in a port range. 256 * Return 0 on failure. 257 */ 258 int 259 pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto) 260 { 261 u_int p1, p2; 262 char *off, *cpy; 263 int save_proto; 264 265 if (sscanf(name, "%d-%d", &p1, &p2) != 2) { 266 if ((cpy = strdup(name)) == NULL) 267 return 0; 268 269 if ((off = strchr(cpy, '-')) == NULL) { 270 free(cpy); 271 return 0; 272 } 273 274 *off = '\0'; 275 276 if (pcap_nametoport(cpy, port1, proto) == 0) { 277 free(cpy); 278 return 0; 279 } 280 save_proto = *proto; 281 282 if (pcap_nametoport(off + 1, port2, proto) == 0) { 283 free(cpy); 284 return 0; 285 } 286 free(cpy); 287 288 if (*proto != save_proto) 289 *proto = PROTO_UNDEF; 290 } else { 291 *port1 = p1; 292 *port2 = p2; 293 *proto = PROTO_UNDEF; 294 } 295 296 return 1; 297 } 298 299 int 300 pcap_nametoproto(const char *str) 301 { 302 struct protoent *p; 303 304 p = getprotobyname(str); 305 if (p != 0) 306 return p->p_proto; 307 else 308 return PROTO_UNDEF; 309 } 310 311 #include "ethertype.h" 312 313 struct eproto { 314 const char *s; 315 u_short p; 316 }; 317 318 /* 319 * Static data base of ether protocol types. 320 * tcpdump used to import this, and it's declared as an export on 321 * Debian, at least, so make it a public symbol, even though we 322 * don't officially export it by declaring it in a header file. 323 * (Programs *should* do this themselves, as tcpdump now does.) 324 */ 325 PCAP_API_DEF struct eproto eproto_db[] = { 326 { "pup", ETHERTYPE_PUP }, 327 { "xns", ETHERTYPE_NS }, 328 { "ip", ETHERTYPE_IP }, 329 #ifdef INET6 330 { "ip6", ETHERTYPE_IPV6 }, 331 #endif 332 { "arp", ETHERTYPE_ARP }, 333 { "rarp", ETHERTYPE_REVARP }, 334 { "sprite", ETHERTYPE_SPRITE }, 335 { "mopdl", ETHERTYPE_MOPDL }, 336 { "moprc", ETHERTYPE_MOPRC }, 337 { "decnet", ETHERTYPE_DN }, 338 { "lat", ETHERTYPE_LAT }, 339 { "sca", ETHERTYPE_SCA }, 340 { "lanbridge", ETHERTYPE_LANBRIDGE }, 341 { "vexp", ETHERTYPE_VEXP }, 342 { "vprod", ETHERTYPE_VPROD }, 343 { "atalk", ETHERTYPE_ATALK }, 344 { "atalkarp", ETHERTYPE_AARP }, 345 { "loopback", ETHERTYPE_LOOPBACK }, 346 { "decdts", ETHERTYPE_DECDTS }, 347 { "decdns", ETHERTYPE_DECDNS }, 348 { (char *)0, 0 } 349 }; 350 351 int 352 pcap_nametoeproto(const char *s) 353 { 354 struct eproto *p = eproto_db; 355 356 while (p->s != 0) { 357 if (strcmp(p->s, s) == 0) 358 return p->p; 359 p += 1; 360 } 361 return PROTO_UNDEF; 362 } 363 364 #include "llc.h" 365 366 /* Static data base of LLC values. */ 367 static struct eproto llc_db[] = { 368 { "iso", LLCSAP_ISONS }, 369 { "stp", LLCSAP_8021D }, 370 { "ipx", LLCSAP_IPX }, 371 { "netbeui", LLCSAP_NETBEUI }, 372 { (char *)0, 0 } 373 }; 374 375 int 376 pcap_nametollc(const char *s) 377 { 378 struct eproto *p = llc_db; 379 380 while (p->s != 0) { 381 if (strcmp(p->s, s) == 0) 382 return p->p; 383 p += 1; 384 } 385 return PROTO_UNDEF; 386 } 387 388 /* Hex digit to integer. */ 389 static inline int 390 xdtoi(c) 391 register int c; 392 { 393 if (isdigit(c)) 394 return c - '0'; 395 else if (islower(c)) 396 return c - 'a' + 10; 397 else 398 return c - 'A' + 10; 399 } 400 401 int 402 __pcap_atoin(const char *s, bpf_u_int32 *addr) 403 { 404 u_int n; 405 int len; 406 407 *addr = 0; 408 len = 0; 409 while (1) { 410 n = 0; 411 while (*s && *s != '.') 412 n = n * 10 + *s++ - '0'; 413 *addr <<= 8; 414 *addr |= n & 0xff; 415 len += 8; 416 if (*s == '\0') 417 return len; 418 ++s; 419 } 420 /* NOTREACHED */ 421 } 422 423 int 424 __pcap_atodn(const char *s, bpf_u_int32 *addr) 425 { 426 #define AREASHIFT 10 427 #define AREAMASK 0176000 428 #define NODEMASK 01777 429 430 u_int node, area; 431 432 if (sscanf(s, "%d.%d", &area, &node) != 2) 433 return(0); 434 435 *addr = (area << AREASHIFT) & AREAMASK; 436 *addr |= (node & NODEMASK); 437 438 return(32); 439 } 440 441 /* 442 * Convert 's', which can have the one of the forms: 443 * 444 * "xx:xx:xx:xx:xx:xx" 445 * "xx.xx.xx.xx.xx.xx" 446 * "xx-xx-xx-xx-xx-xx" 447 * "xxxx.xxxx.xxxx" 448 * "xxxxxxxxxxxx" 449 * 450 * (or various mixes of ':', '.', and '-') into a new 451 * ethernet address. Assumes 's' is well formed. 452 */ 453 u_char * 454 pcap_ether_aton(const char *s) 455 { 456 register u_char *ep, *e; 457 register u_int d; 458 459 e = ep = (u_char *)malloc(6); 460 if (e == NULL) 461 return (NULL); 462 463 while (*s) { 464 if (*s == ':' || *s == '.' || *s == '-') 465 s += 1; 466 d = xdtoi(*s++); 467 if (isxdigit((unsigned char)*s)) { 468 d <<= 4; 469 d |= xdtoi(*s++); 470 } 471 *ep++ = d; 472 } 473 474 return (e); 475 } 476 477 #ifndef HAVE_ETHER_HOSTTON 478 /* Roll our own */ 479 u_char * 480 pcap_ether_hostton(const char *name) 481 { 482 register struct pcap_etherent *ep; 483 register u_char *ap; 484 static FILE *fp = NULL; 485 static int init = 0; 486 487 if (!init) { 488 fp = fopen(PCAP_ETHERS_FILE, "r"); 489 ++init; 490 if (fp == NULL) 491 return (NULL); 492 } else if (fp == NULL) 493 return (NULL); 494 else 495 rewind(fp); 496 497 while ((ep = pcap_next_etherent(fp)) != NULL) { 498 if (strcmp(ep->name, name) == 0) { 499 ap = (u_char *)malloc(6); 500 if (ap != NULL) { 501 memcpy(ap, ep->addr, 6); 502 return (ap); 503 } 504 break; 505 } 506 } 507 return (NULL); 508 } 509 #else 510 511 #if !defined(HAVE_DECL_ETHER_HOSTTON) || !HAVE_DECL_ETHER_HOSTTON 512 #ifndef HAVE_STRUCT_ETHER_ADDR 513 struct ether_addr { 514 unsigned char ether_addr_octet[6]; 515 }; 516 #endif 517 extern int ether_hostton(const char *, struct ether_addr *); 518 #endif 519 520 /* Use the os supplied routines */ 521 u_char * 522 pcap_ether_hostton(const char *name) 523 { 524 register u_char *ap; 525 u_char a[6]; 526 527 ap = NULL; 528 if (ether_hostton(name, (struct ether_addr *)a) == 0) { 529 ap = (u_char *)malloc(6); 530 if (ap != NULL) 531 memcpy((char *)ap, (char *)a, 6); 532 } 533 return (ap); 534 } 535 #endif 536 537 int 538 __pcap_nametodnaddr(const char *name, u_short *res) 539 { 540 #ifdef DECNETLIB 541 struct nodeent *getnodebyname(); 542 struct nodeent *nep; 543 544 nep = getnodebyname(name); 545 if (nep == ((struct nodeent *)0)) 546 return(0); 547 548 memcpy((char *)res, (char *)nep->n_addr, sizeof(unsigned short)); 549 return(1); 550 #else 551 return(0); 552 #endif 553 } 554