diff options
Diffstat (limited to 'missing/win_ether_ntohost.c')
-rw-r--r-- | missing/win_ether_ntohost.c | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/missing/win_ether_ntohost.c b/missing/win_ether_ntohost.c new file mode 100644 index 00000000..05930923 --- /dev/null +++ b/missing/win_ether_ntohost.c @@ -0,0 +1,216 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * tcpdump/Win32 functions for reading and parsing system's Ethernet + * address file: + * '%SystemRoot%/drivers/etc/ethers' (Win-NT+) + * or '%Windir%/etc/ethers' (Win-9x/ME) + * + * G. Vanem <gvanem@yahoo.no> 2012. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <netdissect-stdinc.h> + +#include "missing/win_ether_ntohost.h" + +#include "netdissect.h" +#include "addrtoname.h" + +typedef struct ether_entry { + ether_address eth_addr; /* MAC address */ + char *name; /* name of MAC-address */ + struct ether_entry *next; + } ether_entry; + +static struct ether_entry *eth0 = NULL; + +/* + * The reason to avoid using 'pcap_next_etherent()' in addrtoname.c + * are several: + * 1) wpcap.dll and 'pcap_next_etherent()' could have been built in + * debug-mode (-MDd) or release-mode (-MD) and tcpdump in + * the opposite model. + * 2) If this is built by MSVC, wpcap.dll could have been built by + * MingW. It has no debug-model. + * 3) It may not have been exported from wpcap.dll (present in wpcap.def). + * + * So we shoe-horn the building of tcpdump with '-DUSE_ETHER_NTOHOST' to + * make 'init_etherarray()' call the below 'ether_ntohost()' instead. + */ +#if !defined(USE_ETHER_NTOHOST) +#error "'-DUSE_ETHER_NTOHOST' must be set" +#endif + +/* + * Return TRUE if running under Win-95/98/ME. + */ +static BOOL is_win9x (void) +{ + OSVERSIONINFO ovi; + DWORD os_ver = GetVersion(); + DWORD major_ver = LOBYTE (LOWORD(os_ver)); + + return (os_ver >= 0x80000000 && major_ver >= 4); +} + +/* + * Return path to "%SystemRoot%/drivers/etc/<file>" (Win-NT+) + * or to "%Windir%/etc/<file>" (Win-9x/ME) + */ +const char *etc_path (const char *file) +{ + BOOL win9x = is_win9x(); + const char *env = win9x ? getenv("WinDir") : getenv("SystemRoot"); + static char path[MAX_PATH]; + + if (!env) + return (file); + + if (win9x) + snprintf (path, sizeof(path), "%s\\etc\\%s", env, file); + else + snprintf (path, sizeof(path), "%s\\system32\\drivers\\etc\\%s", env, file); + + return (path); +} + +/* + * Parse a string-buf containing an MAC address and name. + * Accepts MAC addresses on both "xx:xx:xx.." and "xx-xx-xx.." forms. + * + * We could have used pcap_ether_aton(), but problem 3) above could apply. + * or we could have cut & pasted 'pcap_next_etherent(FILE *fp)' below. + */ +#define MIN_LEN sizeof("0:0:0:0:0:0 X") + +static +int parse_ether_buf (const char *buf, char **result, struct ether_addr *e) +{ + const char *fmt; + char *name; + char *str = (char*)buf; + unsigned eth [sizeof(*e)]; + int i; + + /* Find first non-blank in 'buf' */ + while (str[0] && str[1] && isspace((int)str[0])) + str++; + + if (*str == '#' || *str == ';' || *str == '\n' || strlen(str) < MIN_LEN) + return (0); + + if (str[2] == ':') + fmt = "%02x:%02x:%02x:%02x:%02x:%02x"; + else + fmt = "%02x-%02x-%02x-%02x-%02x-%02x"; + + if (sscanf(str, fmt, ð[0], ð[1], ð[2], ð[3], ð[4], ð[5]) != MAC_ADDR_LEN) + return (0); + + str = strtok (str, " \t"); + name = strtok (NULL, " #\t\n"); + + if (!str || !name || strlen(name) < 1) + return (0); + + *result = name; + + for (i = 0; i < MAC_ADDR_LEN; i++) + e->octet[i] = eth[i]; + + return (1); +} + +static void free_ethers (void) +{ + struct ether_entry *e, *next; + + for (e = eth0; e; e = next) { + next = e->next; + free(e->name); + free(e); + } + eth0 = NULL; +} + +static int init_ethers (void) +{ + char buf[BUFSIZE]; + FILE *fp = fopen (etc_path("ethers"), "r"); + + if (!fp) + return (0); + + while (fgets(buf,sizeof(buf),fp)) + { + struct ether_entry *e; + char *name; + ether_address eth; + + if (!parse_ether_buf(buf,&name,ð)) + continue; + + e = calloc (sizeof(*e), 1); + if (!e) + break; + + memcpy(&e->eth_addr, ð, MAC_ADDR_LEN); + e->name = strdup(name); + if (!e->name) { + free(e); + break; + } + + e->next = eth0; + eth0 = e; + } + fclose(fp); + atexit(free_ethers); + return (1); +} + +/* + * Map an ethernet address 'e' to a 'name'. + * Returns 0 on success. + * + * This function is called at startup by init_etherarray() and then + * by etheraddr_string() as needed. To avoid doing an expensive fopen() + * on each call, the contents of 'etc_path("ethers")' is cached here in + * a linked-list 'eth0'. + */ +int ether_ntohost (char *name, struct ether_addr *e) +{ + const struct ether_entry *cache; + static int init = 0; + + if (!init) { + init_ethers(); + init = 1; + } + + for (cache = eth0; cache; cache = cache->next) + if (!memcmp(&e->octet, &cache->eth_addr, MAC_ADDR_LEN)) { + strcpy (name,cache->name); + return (0); + } + return (1); +} + |