summaryrefslogtreecommitdiff
path: root/epan/addr_resolv.c
diff options
context:
space:
mode:
authorUlf Lamping <ulf.lamping@web.de>2007-08-06 08:44:26 +0000
committerUlf Lamping <ulf.lamping@web.de>2007-08-06 08:44:26 +0000
commit2aef54275aa1ce7b0f93536a11443bb8b91b64ea (patch)
tree6424bf08fe6f8d6ceb7a2bd01859056eff96f9e3 /epan/addr_resolv.c
parent0f1ad4138aa7b698de7d5ac1bd1fe9589c877065 (diff)
downloadwireshark-2aef54275aa1ce7b0f93536a11443bb8b91b64ea.tar.gz
add a way to read a personal /etc/services file for TCP/UDP/... port service name resolution.
svn path=/trunk/; revision=22457
Diffstat (limited to 'epan/addr_resolv.c')
-rw-r--r--epan/addr_resolv.c230
1 files changed, 188 insertions, 42 deletions
diff --git a/epan/addr_resolv.c b/epan/addr_resolv.c
index 1ba17a55c8..87859e5069 100644
--- a/epan/addr_resolv.c
+++ b/epan/addr_resolv.c
@@ -128,6 +128,7 @@
#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
@@ -231,6 +232,7 @@ static hashipxnet_t *ipxnet_table[HASHIPXNETSIZE];
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);
@@ -249,6 +251,8 @@ gchar *g_ethers_path = NULL; /* global ethers file */
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 */
@@ -274,10 +278,188 @@ GList *adns_queue_head = NULL;
#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;
+
+ strncpy(tp->name, service_name, MAXNAMELEN);
+ tp->name[MAXNAMELEN-1] = '\0';
+}
+
+
+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)
+{
+ FILE *serv_p = NULL;
+
+
+ /* 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);
+
+ 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;
@@ -286,6 +468,12 @@ static gchar *serv_name_lookup(guint port, port_type proto)
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;
@@ -562,48 +750,6 @@ static const gchar *solve_address_to_name(address *addr)
/*
- * 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 */
-
-
-/*
* Ethernet / manufacturer resolution
*
* The following functions implement ethernet address resolution and