* sites still using NIS rather than DNS for that....)
*/
+#ifdef HAVE_GNU_ADNS
+# include <errno.h>
+# include <adns.h>
+# ifdef inet_aton
+# undef inet_aton
+# endif
+#endif
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
# include "inet_v6defs.h"
#endif
-#ifdef HAVE_GNU_ADNS
-# include <errno.h>
-# include <adns.h>
-# ifdef inet_aton
-# undef inet_aton
-# endif
-#endif
-
#if defined(_WIN32) && defined(INET6)
# include <ws2tcpip.h>
#endif
#include "ipv6-utils.h"
#include "addr_resolv.h"
#include "filesystem.h"
+
+#include <epan/strutil.h>
#include <wiretap/file_util.h>
#include <epan/prefs.h>
#include <epan/emem.h>
#define ENAME_ETHERS "ethers"
#define ENAME_IPXNETS "ipxnets"
#define ENAME_MANUF "manuf"
+#define ENAME_SERVICES "services"
#define MAXMANUFLEN 9 /* max vendor name length with ending '\0' */
#define HASHETHSIZE 1024
static int eth_resolution_initialized = 0;
static int ipxnet_resolution_initialized = 0;
+static int service_resolution_initialized = 0;
static hashether_t *add_eth_name(const guint8 *addr, const gchar *name);
gchar *g_pethers_path = NULL; /* personal ethers file */
gchar *g_ipxnets_path = NULL; /* global ipxnets file */
gchar *g_pipxnets_path = NULL; /* personal ipxnets file */
+gchar *g_services_path = NULL; /* global services file */
+gchar *g_pservices_path = NULL; /* personal services file */
/* first resolving call */
/* GNU ADNS */
#endif /* HAVE_GNU_ADNS */
+
+/*
+ * Miscellaneous functions
+ */
+
+static int fgetline(char **buf, int *size, FILE *fp)
+{
+ int len;
+ int c;
+
+ if (fp == NULL)
+ return -1;
+
+ if (*buf == NULL) {
+ if (*size == 0)
+ *size = BUFSIZ;
+
+ if ((*buf = g_malloc(*size)) == NULL)
+ return -1;
+ }
+
+ if (feof(fp))
+ return -1;
+
+ len = 0;
+ while ((c = getc(fp)) != EOF && c != '\r' && c != '\n') {
+ if (len+1 >= *size) {
+ if ((*buf = g_realloc(*buf, *size += BUFSIZ)) == NULL)
+ return -1;
+ }
+ (*buf)[len++] = c;
+ }
+
+ if (len == 0 && c == EOF)
+ return -1;
+
+ (*buf)[len] = '\0';
+
+ return len;
+
+} /* fgetline */
+
+
/*
* Local function definitions
*/
+
+static void add_service_name(hashport_t **proto_table, guint port, const char *service_name)
+{
+ int hash_idx;
+ hashport_t *tp;
+
+
+ hash_idx = HASH_PORT(port);
+ tp = proto_table[hash_idx];
+
+ if( tp == NULL ) {
+ tp = proto_table[hash_idx] = (hashport_t *)g_malloc(sizeof(hashport_t));
+ } else {
+ while(1) {
+ if( tp->port == port ) {
+ return;
+ }
+ if (tp->next == NULL) {
+ tp->next = (hashport_t *)g_malloc(sizeof(hashport_t));
+ tp = tp->next;
+ break;
+ }
+ tp = tp->next;
+ }
+ }
+
+ /* fill in a new entry */
+ tp->port = port;
+ tp->next = NULL;
+
+ g_strlcpy(tp->name, service_name, MAXNAMELEN);
+}
+
+
+static void parse_service_line (char *line)
+{
+ /*
+ * See the services(4) or services(5) man page for services file format
+ * (not available on all systems).
+ */
+
+ gchar *cp;
+ gchar *service;
+ gchar *port;
+
+
+ if ((cp = strchr(line, '#')))
+ *cp = '\0';
+
+ if ((cp = strtok(line, " \t")) == NULL)
+ return;
+
+ service = cp;
+
+ if ((cp = strtok(NULL, " \t")) == NULL)
+ return;
+
+ port = cp;
+
+ if ((cp = strtok(cp, "/")) == NULL)
+ return;
+
+ if ((cp = strtok(NULL, "/")) == NULL)
+ return;
+
+ /* seems we got all interesting things from the file */
+ if(strcmp(cp, "tcp") == 0) {
+ add_service_name(tcp_port_table, atoi(port), service);
+ return;
+ }
+
+ if(strcmp(cp, "udp") == 0) {
+ add_service_name(udp_port_table, atoi(port), service);
+ return;
+ }
+
+ if(strcmp(cp, "sctp") == 0) {
+ add_service_name(sctp_port_table, atoi(port), service);
+ return;
+ }
+
+ if(strcmp(cp, "dcp") == 0) {
+ add_service_name(dccp_port_table, atoi(port), service);
+ return;
+ }
+
+} /* parse_service_line */
+
+
+
+static void parse_services_file(const char * path)
+{
+ FILE *serv_p;
+ static int size = 0;
+ static char *buf = NULL;
+
+ /* services hash table initialization */
+ serv_p = eth_fopen(path, "r");
+
+ if (serv_p == NULL)
+ return;
+
+ while (fgetline(&buf, &size, serv_p) >= 0) {
+ parse_service_line (buf);
+ }
+
+ fclose(serv_p);
+}
+
+
+static void initialize_services(void)
+{
+
+ /* the hash table won't ignore duplicates, so use the personal path first */
+
+ /* set personal services path */
+ if (g_pservices_path == NULL)
+ g_pservices_path = get_persconffile_path(ENAME_SERVICES, FALSE, FALSE);
+
+ parse_services_file(g_pservices_path);
+
+ /* Compute the pathname of the services file. */
+ if (g_services_path == NULL) {
+ g_services_path = get_datafile_path(ENAME_SERVICES);
+ }
+
+ parse_services_file(g_services_path);
+
+} /* initialize_services */
+
+
+
static gchar *serv_name_lookup(guint port, port_type proto)
{
int hash_idx;
const char *serv_proto = NULL;
struct servent *servp;
+
+ if (!service_resolution_initialized) {
+ initialize_services();
+ service_resolution_initialized = 1;
+ }
+
switch(proto) {
case PT_UDP:
table = udp_port_table;
/* not yet implemented */
return NULL;
/*NOTREACHED*/
- break;
} /* proto */
hash_idx = HASH_PORT(port);
/* unknown port */
g_snprintf(tp->name, MAXNAMELEN, "%d", port);
} else {
- strncpy(tp->name, servp->s_name, MAXNAMELEN);
- tp->name[MAXNAMELEN-1] = '\0';
+ g_strlcpy(tp->name, servp->s_name, MAXNAMELEN);
}
return (tp->name);
adns_queue_head = g_list_append(adns_queue_head, (gpointer) qmsg);
tp->is_dummy_entry = TRUE;
- ip_to_str_buf((guint8 *)&addr, tp->name);
+ ip_to_str_buf((guint8 *)&addr, tp->name, MAXNAMELEN);
return tp->name;
}
#endif /* HAVE_GNU_ADNS */
# endif /* AVOID_DNS_TIMEOUT */
if (hostp != NULL) {
- strncpy(tp->name, hostp->h_name, MAXNAMELEN);
- tp->name[MAXNAMELEN-1] = '\0';
+ g_strlcpy(tp->name, hostp->h_name, MAXNAMELEN);
tp->is_dummy_entry = FALSE;
return tp->name;
}
/* unknown host or DNS timeout */
- ip_to_str_buf((guint8 *)&addr, tp->name);
+ ip_to_str_buf((guint8 *)&addr, tp->name, MAXNAMELEN);
tp->is_dummy_entry = TRUE;
*found = FALSE;
# endif /* AVOID_DNS_TIMEOUT */
if (hostp != NULL) {
- strncpy(tp->name, hostp->h_name, MAXNAMELEN);
- tp->name[MAXNAMELEN-1] = '\0';
+ g_strlcpy(tp->name, hostp->h_name, MAXNAMELEN);
tp->is_dummy_entry = FALSE;
return tp->name;
}
} /* solve_address_to_name */
-/*
- * Miscellaneous functions
- */
-
-static int fgetline(char **buf, int *size, FILE *fp)
-{
- int len;
- int c;
-
- if (fp == NULL)
- return -1;
-
- if (*buf == NULL) {
- if (*size == 0)
- *size = BUFSIZ;
-
- if ((*buf = g_malloc(*size)) == NULL)
- return -1;
- }
-
- if (feof(fp))
- return -1;
-
- len = 0;
- while ((c = getc(fp)) != EOF && c != '\n') {
- if (len+1 >= *size) {
- if ((*buf = g_realloc(*buf, *size += BUFSIZ)) == NULL)
- return -1;
- }
- (*buf)[len++] = c;
- }
-
- if (len == 0 && c == EOF)
- return -1;
-
- (*buf)[len] = '\0';
-
- return len;
-
-} /* fgetline */
-
-
/*
* Ethernet / manufacturer resolution
*
* See the ethers(4) or ethers(5) man page for ethers file format
* (not available on all systems).
* We allow both ethernet address separators (':' and '-'),
- * as well as Ethereal's '.' separator.
+ * as well as Wireshark's '.' separator.
*/
gchar *cp;
if ((cp = strtok(NULL, " \t")) == NULL)
return -1;
- strncpy(eth->name, cp, MAXNAMELEN);
- eth->name[MAXNAMELEN-1] = '\0';
+ g_strlcpy(eth->name, cp, MAXNAMELEN);
return 0;
}
memcpy(tp->addr, addr, sizeof(tp->addr));
- strncpy(tp->name, name, MAXMANUFLEN);
- tp->name[MAXMANUFLEN-1] = '\0';
+ g_strlcpy(tp->name, name, MAXMANUFLEN);
tp->next = NULL;
return;
}
}
memcpy(etp->addr, addr, sizeof(etp->addr));
- strncpy(etp->name, name, MAXNAMELEN);
- etp->name[MAXNAMELEN-1] = '\0';
+ g_strlcpy(etp->name, name, MAXNAMELEN);
etp->next = NULL;
etp->is_dummy_entry = FALSE;
{
int hash_idx;
hashmanuf_t *tp;
+ guint8 stripped_addr[3];
hash_idx = HASH_ETH_MANUF(addr);
+ /* first try to find a "perfect match" */
tp = manuf_table[hash_idx];
-
while(tp != NULL) {
if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
return tp;
tp = tp->next;
}
+ /* Mask out the broadcast/multicast flag but not the locally
+ * administered flag as localy administered means: not assigend
+ * by the IEEE but the local administrator instead.
+ * 0x01 multicast / broadcast bit
+ * 0x02 locally administered bit */
+ memcpy(stripped_addr, addr, 3);
+ stripped_addr[0] &= 0xFE;
+
+ tp = manuf_table[hash_idx];
+ while(tp != NULL) {
+ if (memcmp(tp->addr, stripped_addr, sizeof(tp->addr)) == 0) {
+ return tp;
+ }
+ tp = tp->next;
+ }
+
return NULL;
} /* manuf_name_lookup */
* with it. It's used in get_ethbyname() and get_ethbyaddr()
*/
if (g_pethers_path == NULL)
- g_pethers_path = get_persconffile_path(ENAME_ETHERS, FALSE);
+ g_pethers_path = get_persconffile_path(ENAME_ETHERS, FALSE, FALSE);
/* manuf hash table initialization */
}
}
- strncpy(tp->name, name, MAXNAMELEN);
- tp->name[MAXNAMELEN-1] = '\0';
+ g_strlcpy(tp->name, name, MAXNAMELEN);
if (new_one) {
memcpy(tp->addr, addr, sizeof(tp->addr));
tp->next = NULL;
tp->is_dummy_entry = TRUE;
} else {
- strncpy(tp->name, eth->name, MAXNAMELEN);
- tp->name[MAXNAMELEN-1] = '\0';
+ g_strlcpy(tp->name, eth->name, MAXNAMELEN);
tp->is_dummy_entry = FALSE;
}
ipxnet->addr = (a0 << 24) | (a1 << 16) | (a2 << 8) | a3;
}
- strncpy(ipxnet->name, cp, MAXNAMELEN);
- ipxnet->name[MAXNAMELEN-1] = '\0';
+ g_strlcpy(ipxnet->name, cp, MAXNAMELEN);
return 0;
* with it. It's used in get_ipxnetbyname() and get_ipxnetbyaddr()
*/
if (g_pipxnets_path == NULL)
- g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS, FALSE);
+ g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS, FALSE, FALSE);
} /* initialize_ipxnets */
}
tp->addr = addr;
- strncpy(tp->name, name, MAXNAMELEN);
- tp->name[MAXNAMELEN-1] = '\0';
+ g_strlcpy(tp->name, name, MAXNAMELEN);
tp->next = NULL;
return tp;
g_snprintf(tp->name, MAXNAMELEN, "%X", addr);
} else {
- strncpy(tp->name, ipxnet->name, MAXNAMELEN);
- tp->name[MAXNAMELEN-1] = '\0';
+ g_strlcpy(tp->name, ipxnet->name, MAXNAMELEN);
}
return (tp->name);
char *hostspath;
#ifdef HAVE_GNU_ADNS
-#ifdef WIN32
+#ifdef _WIN32
char *sysroot;
static char rootpath_nt[] = "\\system32\\drivers\\etc\\hosts";
static char rootpath_ot[] = "\\hosts";
-#endif /* WIN32 */
+#endif /* _WIN32 */
#endif /*GNU_ADNS */
/*
* Load the user's hosts file, if they have one.
*/
- hostspath = get_persconffile_path(ENAME_HOSTS, FALSE);
+ hostspath = get_persconffile_path(ENAME_HOSTS, FALSE, FALSE);
if (!read_hosts_file(hostspath) && errno != ENOENT) {
report_open_failure(hostspath, errno, FALSE);
}
* We're using GNU ADNS, which doesn't check the system hosts file;
* we load that file ourselves.
*/
-#ifdef WIN32
+#ifdef _WIN32
sysroot = getenv_utf8("WINDIR");
if (sysroot != NULL) {
}
g_free(hostspath);
}
-#else /* WIN32 */
+#else /* _WIN32 */
read_hosts_file("/etc/hosts");
-#endif /* WIN32 */
+#endif /* _WIN32 */
/* XXX - Any flags we should be using? */
/* XXX - We could provide config settings for DNS servers, and
}
}
- strncpy(tp->name, name, MAXNAMELEN);
- tp->name[MAXNAMELEN-1] = '\0';
+ g_strlcpy(tp->name, name, MAXNAMELEN);
if (new_one) {
tp->addr = addr;
tp->next = NULL;
}
}
- strncpy(tp->name, name, MAXNAMELEN);
- tp->name[MAXNAMELEN-1] = '\0';
+ g_strlcpy(tp->name, name, MAXNAMELEN);
if (new_one) {
tp->addr = *addrp;
tp->next = NULL;
} /* add_ipv6_name */
+/* -----------------
+ * unsigned integer to ascii
+*/
+static gchar *ep_utoa(guint port)
+{
+ gchar *bp = ep_alloc(MAXNAMELEN);
+
+ bp = &bp[MAXNAMELEN -1];
+
+ *bp = 0;
+ do {
+ *--bp = (port % 10) +'0';
+ } while ((port /= 10) != 0);
+ return bp;
+}
+
+
extern gchar *get_udp_port(guint port)
{
- gchar *cur;
if (!(g_resolv_flags & RESOLV_TRANSPORT)) {
- cur=ep_alloc(MAXNAMELEN);
- g_snprintf(cur, MAXNAMELEN, "%u", port);
- return cur;
+ return ep_utoa(port);
}
return serv_name_lookup(port, PT_UDP);
extern gchar *get_dccp_port(guint port)
{
- gchar *cur;
if (!(g_resolv_flags & RESOLV_TRANSPORT)) {
- cur=ep_alloc(MAXNAMELEN);
- g_snprintf(cur, MAXNAMELEN, "%u", port);
- return cur;
+ return ep_utoa(port);
}
return serv_name_lookup(port, PT_DCCP);
extern gchar *get_tcp_port(guint port)
{
- gchar *cur;
if (!(g_resolv_flags & RESOLV_TRANSPORT)) {
- cur=ep_alloc(MAXNAMELEN);
- g_snprintf(cur, MAXNAMELEN, "%u", port);
- return cur;
+ return ep_utoa(port);
}
return serv_name_lookup(port, PT_TCP);
extern gchar *get_sctp_port(guint port)
{
- gchar *cur;
if (!(g_resolv_flags & RESOLV_TRANSPORT)) {
- cur=ep_alloc(MAXNAMELEN);
- g_snprintf(cur, MAXNAMELEN, "%u", port);
- return cur;
+ return ep_utoa(port);
}
return serv_name_lookup(port, PT_SCTP);
void get_addr_name_buf(address *addr, gchar *buf, guint size)
{
- const gchar *result;
-
- result = get_addr_name(addr);
-
- strncpy(buf,result,size);
- buf[size]='\0';
- return;
+ const gchar *result = get_addr_name(addr);
+ g_snprintf(buf, size, "%s", result);
} /* get_addr_name_buf */