1335640Shselasky/* 2335640Shselasky * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 3335640Shselasky * The Regents of the University of California. All rights reserved. 4335640Shselasky * 5335640Shselasky * Redistribution and use in source and binary forms, with or without 6335640Shselasky * modification, are permitted provided that: (1) source code distributions 7335640Shselasky * retain the above copyright notice and this paragraph in its entirety, (2) 8335640Shselasky * distributions including binary code include the above copyright notice and 9335640Shselasky * this paragraph in its entirety in the documentation or other materials 10335640Shselasky * provided with the distribution, and (3) all advertising materials mentioning 11335640Shselasky * features or use of this software display the following acknowledgement: 12335640Shselasky * ``This product includes software developed by the University of California, 13335640Shselasky * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14335640Shselasky * the University nor the names of its contributors may be used to endorse 15335640Shselasky * or promote products derived from this software without specific prior 16335640Shselasky * written permission. 17335640Shselasky * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18335640Shselasky * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19335640Shselasky * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20335640Shselasky * 21335640Shselasky * Name to id translation routines used by the scanner. 22335640Shselasky * These functions are not time critical. 23335640Shselasky */ 24335640Shselasky 25335640Shselasky#ifdef HAVE_CONFIG_H 26335640Shselasky#include <config.h> 27335640Shselasky#endif 28335640Shselasky 29335640Shselasky#ifdef DECNETLIB 30335640Shselasky#include <sys/types.h> 31335640Shselasky#include <netdnet/dnetdb.h> 32335640Shselasky#endif 33335640Shselasky 34335640Shselasky#ifdef _WIN32 35335640Shselasky #include <winsock2.h> 36335640Shselasky #include <ws2tcpip.h> 37335640Shselasky 38335640Shselasky #ifdef INET6 39335640Shselasky /* 40335640Shselasky * To quote the MSDN page for getaddrinfo() at 41335640Shselasky * 42335640Shselasky * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx 43335640Shselasky * 44335640Shselasky * "Support for getaddrinfo on Windows 2000 and older versions 45335640Shselasky * The getaddrinfo function was added to the Ws2_32.dll on Windows XP and 46335640Shselasky * later. To execute an application that uses this function on earlier 47335640Shselasky * versions of Windows, then you need to include the Ws2tcpip.h and 48335640Shselasky * Wspiapi.h files. When the Wspiapi.h include file is added, the 49335640Shselasky * getaddrinfo function is defined to the WspiapiGetAddrInfo inline 50335640Shselasky * function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo 51335640Shselasky * function is implemented in such a way that if the Ws2_32.dll or the 52335640Shselasky * Wship6.dll (the file containing getaddrinfo in the IPv6 Technology 53335640Shselasky * Preview for Windows 2000) does not include getaddrinfo, then a 54335640Shselasky * version of getaddrinfo is implemented inline based on code in the 55335640Shselasky * Wspiapi.h header file. This inline code will be used on older Windows 56335640Shselasky * platforms that do not natively support the getaddrinfo function." 57335640Shselasky * 58335640Shselasky * We use getaddrinfo(), so we include Wspiapi.h here. 59335640Shselasky */ 60335640Shselasky #include <wspiapi.h> 61335640Shselasky #endif /* INET6 */ 62335640Shselasky#else /* _WIN32 */ 63335640Shselasky #include <sys/param.h> 64335640Shselasky #include <sys/types.h> 65335640Shselasky #include <sys/socket.h> 66335640Shselasky #include <sys/time.h> 67335640Shselasky 68335640Shselasky #include <netinet/in.h> 69335640Shselasky 70335640Shselasky #ifdef HAVE_ETHER_HOSTTON 71335640Shselasky #if defined(NET_ETHERNET_H_DECLARES_ETHER_HOSTTON) 72335640Shselasky /* 73335640Shselasky * OK, just include <net/ethernet.h>. 74335640Shselasky */ 75335640Shselasky #include <net/ethernet.h> 76335640Shselasky #elif defined(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON) 77335640Shselasky /* 78335640Shselasky * OK, just include <netinet/ether.h> 79335640Shselasky */ 80335640Shselasky #include <netinet/ether.h> 81335640Shselasky #elif defined(SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON) 82335640Shselasky /* 83335640Shselasky * OK, just include <sys/ethernet.h> 84335640Shselasky */ 85335640Shselasky #include <sys/ethernet.h> 86335640Shselasky #elif defined(ARPA_INET_H_DECLARES_ETHER_HOSTTON) 87335640Shselasky /* 88335640Shselasky * OK, just include <arpa/inet.h> 89335640Shselasky */ 90335640Shselasky #include <arpa/inet.h> 91335640Shselasky #elif defined(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON) 92335640Shselasky /* 93335640Shselasky * OK, include <netinet/if_ether.h>, after all the other stuff we 94335640Shselasky * need to include or define for its benefit. 95335640Shselasky */ 96335640Shselasky #define NEED_NETINET_IF_ETHER_H 97335640Shselasky #else 98335640Shselasky /* 99335640Shselasky * We'll have to declare it ourselves. 100335640Shselasky * If <netinet/if_ether.h> defines struct ether_addr, include 101335640Shselasky * it. Otherwise, define it ourselves. 102335640Shselasky */ 103335640Shselasky #ifdef HAVE_STRUCT_ETHER_ADDR 104335640Shselasky #define NEED_NETINET_IF_ETHER_H 105335640Shselasky #else /* HAVE_STRUCT_ETHER_ADDR */ 106335640Shselasky struct ether_addr { 107335640Shselasky unsigned char ether_addr_octet[6]; 108335640Shselasky }; 109335640Shselasky #endif /* HAVE_STRUCT_ETHER_ADDR */ 110335640Shselasky #endif /* what declares ether_hostton() */ 111335640Shselasky 112335640Shselasky #ifdef NEED_NETINET_IF_ETHER_H 113335640Shselasky #include <net/if.h> /* Needed on some platforms */ 114335640Shselasky #include <netinet/in.h> /* Needed on some platforms */ 115335640Shselasky #include <netinet/if_ether.h> 116335640Shselasky #endif /* NEED_NETINET_IF_ETHER_H */ 117335640Shselasky 118335640Shselasky #ifndef HAVE_DECL_ETHER_HOSTTON 119335640Shselasky /* 120335640Shselasky * No header declares it, so declare it ourselves. 121335640Shselasky */ 122335640Shselasky extern int ether_hostton(const char *, struct ether_addr *); 123335640Shselasky #endif /* !defined(HAVE_DECL_ETHER_HOSTTON) */ 124335640Shselasky #endif /* HAVE_ETHER_HOSTTON */ 125335640Shselasky 126335640Shselasky #include <arpa/inet.h> 127335640Shselasky #include <netdb.h> 128335640Shselasky#endif /* _WIN32 */ 129335640Shselasky 130335640Shselasky#include <ctype.h> 131335640Shselasky#include <errno.h> 132335640Shselasky#include <stdlib.h> 133335640Shselasky#include <string.h> 134335640Shselasky#include <stdio.h> 135335640Shselasky 136335640Shselasky#include "pcap-int.h" 137335640Shselasky 138335640Shselasky#include "gencode.h" 139335640Shselasky#include <pcap/namedb.h> 140335640Shselasky#include "nametoaddr.h" 141335640Shselasky 142335640Shselasky#ifdef HAVE_OS_PROTO_H 143335640Shselasky#include "os-proto.h" 144335640Shselasky#endif 145335640Shselasky 146335640Shselasky#ifndef NTOHL 147335640Shselasky#define NTOHL(x) (x) = ntohl(x) 148335640Shselasky#define NTOHS(x) (x) = ntohs(x) 149335640Shselasky#endif 150335640Shselasky 151335640Shselasky/* 152335640Shselasky * Convert host name to internet address. 153335640Shselasky * Return 0 upon failure. 154335640Shselasky * XXX - not thread-safe; don't use it inside libpcap. 155335640Shselasky */ 156335640Shselaskybpf_u_int32 ** 157335640Shselaskypcap_nametoaddr(const char *name) 158335640Shselasky{ 159335640Shselasky#ifndef h_addr 160335640Shselasky static bpf_u_int32 *hlist[2]; 161335640Shselasky#endif 162335640Shselasky bpf_u_int32 **p; 163335640Shselasky struct hostent *hp; 164335640Shselasky 165335640Shselasky if ((hp = gethostbyname(name)) != NULL) { 166335640Shselasky#ifndef h_addr 167335640Shselasky hlist[0] = (bpf_u_int32 *)hp->h_addr; 168335640Shselasky NTOHL(hp->h_addr); 169335640Shselasky return hlist; 170335640Shselasky#else 171335640Shselasky for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p) 172335640Shselasky NTOHL(**p); 173335640Shselasky return (bpf_u_int32 **)hp->h_addr_list; 174335640Shselasky#endif 175335640Shselasky } 176335640Shselasky else 177335640Shselasky return 0; 178335640Shselasky} 179335640Shselasky 180335640Shselaskystruct addrinfo * 181335640Shselaskypcap_nametoaddrinfo(const char *name) 182335640Shselasky{ 183335640Shselasky struct addrinfo hints, *res; 184335640Shselasky int error; 185335640Shselasky 186335640Shselasky memset(&hints, 0, sizeof(hints)); 187335640Shselasky hints.ai_family = PF_UNSPEC; 188335640Shselasky hints.ai_socktype = SOCK_STREAM; /*not really*/ 189335640Shselasky hints.ai_protocol = IPPROTO_TCP; /*not really*/ 190335640Shselasky error = getaddrinfo(name, NULL, &hints, &res); 191335640Shselasky if (error) 192335640Shselasky return NULL; 193335640Shselasky else 194335640Shselasky return res; 195335640Shselasky} 196335640Shselasky 197335640Shselasky/* 198335640Shselasky * Convert net name to internet address. 199335640Shselasky * Return 0 upon failure. 200335640Shselasky * XXX - not guaranteed to be thread-safe! See below for platforms 201335640Shselasky * on which it is thread-safe and on which it isn't. 202335640Shselasky */ 203335640Shselaskybpf_u_int32 204335640Shselaskypcap_nametonetaddr(const char *name) 205335640Shselasky{ 206335640Shselasky#ifdef _WIN32 207335640Shselasky /* 208335640Shselasky * There's no "getnetbyname()" on Windows. 209335640Shselasky * 210335640Shselasky * XXX - I guess we could use the BSD code to read 211335640Shselasky * C:\Windows\System32\drivers\etc/networks, assuming 212335640Shselasky * that's its home on all the versions of Windows 213335640Shselasky * we use, but that file probably just has the loopback 214335640Shselasky * network on 127/24 on 99 44/100% of Windows machines. 215335640Shselasky * 216335640Shselasky * (Heck, these days it probably just has that on 99 44/100% 217335640Shselasky * of *UN*X* machines.) 218335640Shselasky */ 219335640Shselasky return 0; 220335640Shselasky#else 221335640Shselasky /* 222335640Shselasky * UN*X. 223335640Shselasky */ 224335640Shselasky struct netent *np; 225335640Shselasky #if defined(HAVE_LINUX_GETNETBYNAME_R) 226335640Shselasky /* 227335640Shselasky * We have Linux's reentrant getnetbyname_r(). 228335640Shselasky */ 229335640Shselasky struct netent result_buf; 230335640Shselasky char buf[1024]; /* arbitrary size */ 231335640Shselasky int h_errnoval; 232335640Shselasky int err; 233335640Shselasky 234356341Scy /* 235356341Scy * Apparently, the man page at 236356341Scy * 237356341Scy * http://man7.org/linux/man-pages/man3/getnetbyname_r.3.html 238356341Scy * 239356341Scy * lies when it says 240356341Scy * 241356341Scy * If the function call successfully obtains a network record, 242356341Scy * then *result is set pointing to result_buf; otherwise, *result 243356341Scy * is set to NULL. 244356341Scy * 245356341Scy * and, in fact, at least in some versions of GNU libc, it does 246356341Scy * *not* always get set if getnetbyname_r() succeeds. 247356341Scy */ 248356341Scy np = NULL; 249356341Scy err = getnetbyname_r(name, &result_buf, buf, sizeof buf, &np, 250335640Shselasky &h_errnoval); 251335640Shselasky if (err != 0) { 252335640Shselasky /* 253335640Shselasky * XXX - dynamically allocate the buffer, and make it 254335640Shselasky * bigger if we get ERANGE back? 255335640Shselasky */ 256335640Shselasky return 0; 257335640Shselasky } 258335640Shselasky #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R) 259335640Shselasky /* 260335640Shselasky * We have Solaris's and IRIX's reentrant getnetbyname_r(). 261335640Shselasky */ 262335640Shselasky struct netent result_buf; 263335640Shselasky char buf[1024]; /* arbitrary size */ 264335640Shselasky 265335640Shselasky np = getnetbyname_r(name, &result_buf, buf, (int)sizeof buf); 266335640Shselasky #elif defined(HAVE_AIX_GETNETBYNAME_R) 267335640Shselasky /* 268335640Shselasky * We have AIX's reentrant getnetbyname_r(). 269335640Shselasky */ 270335640Shselasky struct netent result_buf; 271335640Shselasky struct netent_data net_data; 272335640Shselasky 273335640Shselasky if (getnetbyname_r(name, &result_buf, &net_data) == -1) 274335640Shselasky np = NULL; 275335640Shselasky else 276335640Shselasky np = &result_buf; 277335640Shselasky #else 278335640Shselasky /* 279335640Shselasky * We don't have any getnetbyname_r(); either we have a 280335640Shselasky * getnetbyname() that uses thread-specific data, in which 281335640Shselasky * case we're thread-safe (sufficiently recent FreeBSD, 282335640Shselasky * sufficiently recent Darwin-based OS, sufficiently recent 283335640Shselasky * HP-UX, sufficiently recent Tru64 UNIX), or we have the 284335640Shselasky * traditional getnetbyname() (everything else, including 285335640Shselasky * current NetBSD and OpenBSD), in which case we're not 286335640Shselasky * thread-safe. 287335640Shselasky */ 288335640Shselasky np = getnetbyname(name); 289335640Shselasky #endif 290335640Shselasky if (np != NULL) 291335640Shselasky return np->n_net; 292335640Shselasky else 293335640Shselasky return 0; 294335640Shselasky#endif /* _WIN32 */ 295335640Shselasky} 296335640Shselasky 297335640Shselasky/* 298335640Shselasky * Convert a port name to its port and protocol numbers. 299335640Shselasky * We assume only TCP or UDP. 300335640Shselasky * Return 0 upon failure. 301335640Shselasky */ 302335640Shselaskyint 303335640Shselaskypcap_nametoport(const char *name, int *port, int *proto) 304335640Shselasky{ 305335640Shselasky struct addrinfo hints, *res, *ai; 306335640Shselasky int error; 307335640Shselasky struct sockaddr_in *in4; 308335640Shselasky#ifdef INET6 309335640Shselasky struct sockaddr_in6 *in6; 310335640Shselasky#endif 311335640Shselasky int tcp_port = -1; 312335640Shselasky int udp_port = -1; 313335640Shselasky 314335640Shselasky /* 315335640Shselasky * We check for both TCP and UDP in case there are 316335640Shselasky * ambiguous entries. 317335640Shselasky */ 318335640Shselasky memset(&hints, 0, sizeof(hints)); 319335640Shselasky hints.ai_family = PF_UNSPEC; 320335640Shselasky hints.ai_socktype = SOCK_STREAM; 321335640Shselasky hints.ai_protocol = IPPROTO_TCP; 322335640Shselasky error = getaddrinfo(NULL, name, &hints, &res); 323335640Shselasky if (error != 0) { 324356341Scy if (error != EAI_NONAME && 325356341Scy error != EAI_SERVICE) { 326335640Shselasky /* 327335640Shselasky * This is a real error, not just "there's 328335640Shselasky * no such service name". 329335640Shselasky * XXX - this doesn't return an error string. 330335640Shselasky */ 331335640Shselasky return 0; 332335640Shselasky } 333335640Shselasky } else { 334335640Shselasky /* 335335640Shselasky * OK, we found it. Did it find anything? 336335640Shselasky */ 337335640Shselasky for (ai = res; ai != NULL; ai = ai->ai_next) { 338335640Shselasky /* 339335640Shselasky * Does it have an address? 340335640Shselasky */ 341335640Shselasky if (ai->ai_addr != NULL) { 342335640Shselasky /* 343335640Shselasky * Yes. Get a port number; we're done. 344335640Shselasky */ 345335640Shselasky if (ai->ai_addr->sa_family == AF_INET) { 346335640Shselasky in4 = (struct sockaddr_in *)ai->ai_addr; 347335640Shselasky tcp_port = ntohs(in4->sin_port); 348335640Shselasky break; 349335640Shselasky } 350335640Shselasky#ifdef INET6 351335640Shselasky if (ai->ai_addr->sa_family == AF_INET6) { 352335640Shselasky in6 = (struct sockaddr_in6 *)ai->ai_addr; 353335640Shselasky tcp_port = ntohs(in6->sin6_port); 354335640Shselasky break; 355335640Shselasky } 356335640Shselasky#endif 357335640Shselasky } 358335640Shselasky } 359335640Shselasky freeaddrinfo(res); 360335640Shselasky } 361335640Shselasky 362335640Shselasky memset(&hints, 0, sizeof(hints)); 363335640Shselasky hints.ai_family = PF_UNSPEC; 364335640Shselasky hints.ai_socktype = SOCK_DGRAM; 365335640Shselasky hints.ai_protocol = IPPROTO_UDP; 366335640Shselasky error = getaddrinfo(NULL, name, &hints, &res); 367335640Shselasky if (error != 0) { 368356341Scy if (error != EAI_NONAME && 369356341Scy error != EAI_SERVICE) { 370335640Shselasky /* 371335640Shselasky * This is a real error, not just "there's 372335640Shselasky * no such service name". 373335640Shselasky * XXX - this doesn't return an error string. 374335640Shselasky */ 375335640Shselasky return 0; 376335640Shselasky } 377335640Shselasky } else { 378335640Shselasky /* 379335640Shselasky * OK, we found it. Did it find anything? 380335640Shselasky */ 381335640Shselasky for (ai = res; ai != NULL; ai = ai->ai_next) { 382335640Shselasky /* 383335640Shselasky * Does it have an address? 384335640Shselasky */ 385335640Shselasky if (ai->ai_addr != NULL) { 386335640Shselasky /* 387335640Shselasky * Yes. Get a port number; we're done. 388335640Shselasky */ 389335640Shselasky if (ai->ai_addr->sa_family == AF_INET) { 390335640Shselasky in4 = (struct sockaddr_in *)ai->ai_addr; 391335640Shselasky udp_port = ntohs(in4->sin_port); 392335640Shselasky break; 393335640Shselasky } 394335640Shselasky#ifdef INET6 395335640Shselasky if (ai->ai_addr->sa_family == AF_INET6) { 396335640Shselasky in6 = (struct sockaddr_in6 *)ai->ai_addr; 397335640Shselasky udp_port = ntohs(in6->sin6_port); 398335640Shselasky break; 399335640Shselasky } 400335640Shselasky#endif 401335640Shselasky } 402335640Shselasky } 403335640Shselasky freeaddrinfo(res); 404335640Shselasky } 405335640Shselasky 406335640Shselasky /* 407335640Shselasky * We need to check /etc/services for ambiguous entries. 408335640Shselasky * If we find an ambiguous entry, and it has the 409335640Shselasky * same port number, change the proto to PROTO_UNDEF 410335640Shselasky * so both TCP and UDP will be checked. 411335640Shselasky */ 412335640Shselasky if (tcp_port >= 0) { 413335640Shselasky *port = tcp_port; 414335640Shselasky *proto = IPPROTO_TCP; 415335640Shselasky if (udp_port >= 0) { 416335640Shselasky if (udp_port == tcp_port) 417335640Shselasky *proto = PROTO_UNDEF; 418335640Shselasky#ifdef notdef 419335640Shselasky else 420335640Shselasky /* Can't handle ambiguous names that refer 421335640Shselasky to different port numbers. */ 422335640Shselasky warning("ambiguous port %s in /etc/services", 423335640Shselasky name); 424335640Shselasky#endif 425335640Shselasky } 426335640Shselasky return 1; 427335640Shselasky } 428335640Shselasky if (udp_port >= 0) { 429335640Shselasky *port = udp_port; 430335640Shselasky *proto = IPPROTO_UDP; 431335640Shselasky return 1; 432335640Shselasky } 433335640Shselasky#if defined(ultrix) || defined(__osf__) 434335640Shselasky /* Special hack in case NFS isn't in /etc/services */ 435335640Shselasky if (strcmp(name, "nfs") == 0) { 436335640Shselasky *port = 2049; 437335640Shselasky *proto = PROTO_UNDEF; 438335640Shselasky return 1; 439335640Shselasky } 440335640Shselasky#endif 441335640Shselasky return 0; 442335640Shselasky} 443335640Shselasky 444335640Shselasky/* 445335640Shselasky * Convert a string in the form PPP-PPP, where correspond to ports, to 446335640Shselasky * a starting and ending port in a port range. 447335640Shselasky * Return 0 on failure. 448335640Shselasky */ 449335640Shselaskyint 450335640Shselaskypcap_nametoportrange(const char *name, int *port1, int *port2, int *proto) 451335640Shselasky{ 452335640Shselasky u_int p1, p2; 453335640Shselasky char *off, *cpy; 454335640Shselasky int save_proto; 455335640Shselasky 456335640Shselasky if (sscanf(name, "%d-%d", &p1, &p2) != 2) { 457335640Shselasky if ((cpy = strdup(name)) == NULL) 458335640Shselasky return 0; 459335640Shselasky 460335640Shselasky if ((off = strchr(cpy, '-')) == NULL) { 461335640Shselasky free(cpy); 462335640Shselasky return 0; 463335640Shselasky } 464335640Shselasky 465335640Shselasky *off = '\0'; 466335640Shselasky 467335640Shselasky if (pcap_nametoport(cpy, port1, proto) == 0) { 468335640Shselasky free(cpy); 469335640Shselasky return 0; 470335640Shselasky } 471335640Shselasky save_proto = *proto; 472335640Shselasky 473335640Shselasky if (pcap_nametoport(off + 1, port2, proto) == 0) { 474335640Shselasky free(cpy); 475335640Shselasky return 0; 476335640Shselasky } 477335640Shselasky free(cpy); 478335640Shselasky 479335640Shselasky if (*proto != save_proto) 480335640Shselasky *proto = PROTO_UNDEF; 481335640Shselasky } else { 482335640Shselasky *port1 = p1; 483335640Shselasky *port2 = p2; 484335640Shselasky *proto = PROTO_UNDEF; 485335640Shselasky } 486335640Shselasky 487335640Shselasky return 1; 488335640Shselasky} 489335640Shselasky 490335640Shselasky/* 491335640Shselasky * XXX - not guaranteed to be thread-safe! See below for platforms 492335640Shselasky * on which it is thread-safe and on which it isn't. 493335640Shselasky */ 494335640Shselaskyint 495335640Shselaskypcap_nametoproto(const char *str) 496335640Shselasky{ 497335640Shselasky struct protoent *p; 498335640Shselasky #if defined(HAVE_LINUX_GETNETBYNAME_R) 499335640Shselasky /* 500335640Shselasky * We have Linux's reentrant getprotobyname_r(). 501335640Shselasky */ 502335640Shselasky struct protoent result_buf; 503335640Shselasky char buf[1024]; /* arbitrary size */ 504335640Shselasky int err; 505335640Shselasky 506335640Shselasky err = getprotobyname_r(str, &result_buf, buf, sizeof buf, &p); 507335640Shselasky if (err != 0) { 508335640Shselasky /* 509335640Shselasky * XXX - dynamically allocate the buffer, and make it 510335640Shselasky * bigger if we get ERANGE back? 511335640Shselasky */ 512335640Shselasky return 0; 513335640Shselasky } 514335640Shselasky #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R) 515335640Shselasky /* 516335640Shselasky * We have Solaris's and IRIX's reentrant getprotobyname_r(). 517335640Shselasky */ 518335640Shselasky struct protoent result_buf; 519335640Shselasky char buf[1024]; /* arbitrary size */ 520335640Shselasky 521335640Shselasky p = getprotobyname_r(str, &result_buf, buf, (int)sizeof buf); 522335640Shselasky #elif defined(HAVE_AIX_GETNETBYNAME_R) 523335640Shselasky /* 524335640Shselasky * We have AIX's reentrant getprotobyname_r(). 525335640Shselasky */ 526335640Shselasky struct protoent result_buf; 527335640Shselasky struct protoent_data proto_data; 528335640Shselasky 529335640Shselasky if (getprotobyname_r(str, &result_buf, &proto_data) == -1) 530335640Shselasky p = NULL; 531335640Shselasky else 532335640Shselasky p = &result_buf; 533335640Shselasky #else 534335640Shselasky /* 535335640Shselasky * We don't have any getprotobyname_r(); either we have a 536335640Shselasky * getprotobyname() that uses thread-specific data, in which 537335640Shselasky * case we're thread-safe (sufficiently recent FreeBSD, 538335640Shselasky * sufficiently recent Darwin-based OS, sufficiently recent 539335640Shselasky * HP-UX, sufficiently recent Tru64 UNIX, Windows), or we have 540335640Shselasky * the traditional getprotobyname() (everything else, including 541335640Shselasky * current NetBSD and OpenBSD), in which case we're not 542335640Shselasky * thread-safe. 543335640Shselasky */ 544335640Shselasky p = getprotobyname(str); 545335640Shselasky #endif 546335640Shselasky if (p != 0) 547335640Shselasky return p->p_proto; 548335640Shselasky else 549335640Shselasky return PROTO_UNDEF; 550335640Shselasky} 551335640Shselasky 552335640Shselasky#include "ethertype.h" 553335640Shselasky 554335640Shselaskystruct eproto { 555335640Shselasky const char *s; 556335640Shselasky u_short p; 557335640Shselasky}; 558335640Shselasky 559335640Shselasky/* 560335640Shselasky * Static data base of ether protocol types. 561335640Shselasky * tcpdump used to import this, and it's declared as an export on 562335640Shselasky * Debian, at least, so make it a public symbol, even though we 563335640Shselasky * don't officially export it by declaring it in a header file. 564335640Shselasky * (Programs *should* do this themselves, as tcpdump now does.) 565335640Shselasky * 566335640Shselasky * We declare it here, right before defining it, to squelch any 567335640Shselasky * warnings we might get from compilers about the lack of a 568335640Shselasky * declaration. 569335640Shselasky */ 570335640ShselaskyPCAP_API struct eproto eproto_db[]; 571335640ShselaskyPCAP_API_DEF struct eproto eproto_db[] = { 572335640Shselasky { "pup", ETHERTYPE_PUP }, 573335640Shselasky { "xns", ETHERTYPE_NS }, 574335640Shselasky { "ip", ETHERTYPE_IP }, 575335640Shselasky#ifdef INET6 576335640Shselasky { "ip6", ETHERTYPE_IPV6 }, 577335640Shselasky#endif 578335640Shselasky { "arp", ETHERTYPE_ARP }, 579335640Shselasky { "rarp", ETHERTYPE_REVARP }, 580335640Shselasky { "sprite", ETHERTYPE_SPRITE }, 581335640Shselasky { "mopdl", ETHERTYPE_MOPDL }, 582335640Shselasky { "moprc", ETHERTYPE_MOPRC }, 583335640Shselasky { "decnet", ETHERTYPE_DN }, 584335640Shselasky { "lat", ETHERTYPE_LAT }, 585335640Shselasky { "sca", ETHERTYPE_SCA }, 586335640Shselasky { "lanbridge", ETHERTYPE_LANBRIDGE }, 587335640Shselasky { "vexp", ETHERTYPE_VEXP }, 588335640Shselasky { "vprod", ETHERTYPE_VPROD }, 589335640Shselasky { "atalk", ETHERTYPE_ATALK }, 590335640Shselasky { "atalkarp", ETHERTYPE_AARP }, 591335640Shselasky { "loopback", ETHERTYPE_LOOPBACK }, 592335640Shselasky { "decdts", ETHERTYPE_DECDTS }, 593335640Shselasky { "decdns", ETHERTYPE_DECDNS }, 594335640Shselasky { (char *)0, 0 } 595335640Shselasky}; 596335640Shselasky 597335640Shselaskyint 598335640Shselaskypcap_nametoeproto(const char *s) 599335640Shselasky{ 600335640Shselasky struct eproto *p = eproto_db; 601335640Shselasky 602335640Shselasky while (p->s != 0) { 603335640Shselasky if (strcmp(p->s, s) == 0) 604335640Shselasky return p->p; 605335640Shselasky p += 1; 606335640Shselasky } 607335640Shselasky return PROTO_UNDEF; 608335640Shselasky} 609335640Shselasky 610335640Shselasky#include "llc.h" 611335640Shselasky 612335640Shselasky/* Static data base of LLC values. */ 613335640Shselaskystatic struct eproto llc_db[] = { 614335640Shselasky { "iso", LLCSAP_ISONS }, 615335640Shselasky { "stp", LLCSAP_8021D }, 616335640Shselasky { "ipx", LLCSAP_IPX }, 617335640Shselasky { "netbeui", LLCSAP_NETBEUI }, 618335640Shselasky { (char *)0, 0 } 619335640Shselasky}; 620335640Shselasky 621335640Shselaskyint 622335640Shselaskypcap_nametollc(const char *s) 623335640Shselasky{ 624335640Shselasky struct eproto *p = llc_db; 625335640Shselasky 626335640Shselasky while (p->s != 0) { 627335640Shselasky if (strcmp(p->s, s) == 0) 628335640Shselasky return p->p; 629335640Shselasky p += 1; 630335640Shselasky } 631335640Shselasky return PROTO_UNDEF; 632335640Shselasky} 633335640Shselasky 634335640Shselasky/* Hex digit to 8-bit unsigned integer. */ 635335640Shselaskystatic inline u_char 636335640Shselaskyxdtoi(u_char c) 637335640Shselasky{ 638335640Shselasky if (isdigit(c)) 639335640Shselasky return (u_char)(c - '0'); 640335640Shselasky else if (islower(c)) 641335640Shselasky return (u_char)(c - 'a' + 10); 642335640Shselasky else 643335640Shselasky return (u_char)(c - 'A' + 10); 644335640Shselasky} 645335640Shselasky 646335640Shselaskyint 647335640Shselasky__pcap_atoin(const char *s, bpf_u_int32 *addr) 648335640Shselasky{ 649335640Shselasky u_int n; 650335640Shselasky int len; 651335640Shselasky 652335640Shselasky *addr = 0; 653335640Shselasky len = 0; 654335640Shselasky for (;;) { 655335640Shselasky n = 0; 656356341Scy while (*s && *s != '.') { 657356341Scy if (n > 25) { 658356341Scy /* The result will be > 255 */ 659356341Scy return -1; 660356341Scy } 661335640Shselasky n = n * 10 + *s++ - '0'; 662356341Scy } 663356341Scy if (n > 255) 664356341Scy return -1; 665335640Shselasky *addr <<= 8; 666335640Shselasky *addr |= n & 0xff; 667335640Shselasky len += 8; 668335640Shselasky if (*s == '\0') 669335640Shselasky return len; 670335640Shselasky ++s; 671335640Shselasky } 672335640Shselasky /* NOTREACHED */ 673335640Shselasky} 674335640Shselasky 675335640Shselaskyint 676335640Shselasky__pcap_atodn(const char *s, bpf_u_int32 *addr) 677335640Shselasky{ 678335640Shselasky#define AREASHIFT 10 679335640Shselasky#define AREAMASK 0176000 680335640Shselasky#define NODEMASK 01777 681335640Shselasky 682335640Shselasky u_int node, area; 683335640Shselasky 684335640Shselasky if (sscanf(s, "%d.%d", &area, &node) != 2) 685335640Shselasky return(0); 686335640Shselasky 687335640Shselasky *addr = (area << AREASHIFT) & AREAMASK; 688335640Shselasky *addr |= (node & NODEMASK); 689335640Shselasky 690335640Shselasky return(32); 691335640Shselasky} 692335640Shselasky 693335640Shselasky/* 694335640Shselasky * Convert 's', which can have the one of the forms: 695335640Shselasky * 696335640Shselasky * "xx:xx:xx:xx:xx:xx" 697335640Shselasky * "xx.xx.xx.xx.xx.xx" 698335640Shselasky * "xx-xx-xx-xx-xx-xx" 699335640Shselasky * "xxxx.xxxx.xxxx" 700335640Shselasky * "xxxxxxxxxxxx" 701335640Shselasky * 702335640Shselasky * (or various mixes of ':', '.', and '-') into a new 703335640Shselasky * ethernet address. Assumes 's' is well formed. 704335640Shselasky */ 705335640Shselaskyu_char * 706335640Shselaskypcap_ether_aton(const char *s) 707335640Shselasky{ 708335640Shselasky register u_char *ep, *e; 709335640Shselasky register u_char d; 710335640Shselasky 711335640Shselasky e = ep = (u_char *)malloc(6); 712335640Shselasky if (e == NULL) 713335640Shselasky return (NULL); 714335640Shselasky 715335640Shselasky while (*s) { 716335640Shselasky if (*s == ':' || *s == '.' || *s == '-') 717335640Shselasky s += 1; 718335640Shselasky d = xdtoi(*s++); 719335640Shselasky if (isxdigit((unsigned char)*s)) { 720335640Shselasky d <<= 4; 721335640Shselasky d |= xdtoi(*s++); 722335640Shselasky } 723335640Shselasky *ep++ = d; 724335640Shselasky } 725335640Shselasky 726335640Shselasky return (e); 727335640Shselasky} 728335640Shselasky 729335640Shselasky#ifndef HAVE_ETHER_HOSTTON 730335640Shselasky/* 731335640Shselasky * Roll our own. 732335640Shselasky * XXX - not thread-safe, because pcap_next_etherent() isn't thread- 733335640Shselasky * safe! Needs a mutex or a thread-safe pcap_next_etherent(). 734335640Shselasky */ 735335640Shselaskyu_char * 736335640Shselaskypcap_ether_hostton(const char *name) 737335640Shselasky{ 738335640Shselasky register struct pcap_etherent *ep; 739335640Shselasky register u_char *ap; 740335640Shselasky static FILE *fp = NULL; 741335640Shselasky static int init = 0; 742335640Shselasky 743335640Shselasky if (!init) { 744335640Shselasky fp = fopen(PCAP_ETHERS_FILE, "r"); 745335640Shselasky ++init; 746335640Shselasky if (fp == NULL) 747335640Shselasky return (NULL); 748335640Shselasky } else if (fp == NULL) 749335640Shselasky return (NULL); 750335640Shselasky else 751335640Shselasky rewind(fp); 752335640Shselasky 753335640Shselasky while ((ep = pcap_next_etherent(fp)) != NULL) { 754335640Shselasky if (strcmp(ep->name, name) == 0) { 755335640Shselasky ap = (u_char *)malloc(6); 756335640Shselasky if (ap != NULL) { 757335640Shselasky memcpy(ap, ep->addr, 6); 758335640Shselasky return (ap); 759335640Shselasky } 760335640Shselasky break; 761335640Shselasky } 762335640Shselasky } 763335640Shselasky return (NULL); 764335640Shselasky} 765335640Shselasky#else 766335640Shselasky/* 767335640Shselasky * Use the OS-supplied routine. 768335640Shselasky * This *should* be thread-safe; the API doesn't have a static buffer. 769335640Shselasky */ 770335640Shselaskyu_char * 771335640Shselaskypcap_ether_hostton(const char *name) 772335640Shselasky{ 773335640Shselasky register u_char *ap; 774335640Shselasky u_char a[6]; 775335640Shselasky 776335640Shselasky ap = NULL; 777335640Shselasky if (ether_hostton(name, (struct ether_addr *)a) == 0) { 778335640Shselasky ap = (u_char *)malloc(6); 779335640Shselasky if (ap != NULL) 780335640Shselasky memcpy((char *)ap, (char *)a, 6); 781335640Shselasky } 782335640Shselasky return (ap); 783335640Shselasky} 784335640Shselasky#endif 785335640Shselasky 786335640Shselasky/* 787335640Shselasky * XXX - not guaranteed to be thread-safe! 788335640Shselasky */ 789335640Shselaskyint 790335640Shselasky#ifdef DECNETLIB 791335640Shselasky__pcap_nametodnaddr(const char *name, u_short *res) 792335640Shselasky{ 793335640Shselasky struct nodeent *getnodebyname(); 794335640Shselasky struct nodeent *nep; 795335640Shselasky 796335640Shselasky nep = getnodebyname(name); 797335640Shselasky if (nep == ((struct nodeent *)0)) 798335640Shselasky return(0); 799335640Shselasky 800335640Shselasky memcpy((char *)res, (char *)nep->n_addr, sizeof(unsigned short)); 801335640Shselasky return(1); 802335640Shselasky#else 803335640Shselasky__pcap_nametodnaddr(const char *name _U_, u_short *res _U_) 804335640Shselasky{ 805335640Shselasky return(0); 806335640Shselasky#endif 807335640Shselasky} 808