Move the tap infrastructure to the epan directory.
[obnox/wireshark/wip.git] / capture_combo_utils.c
1 /* capture_combo_utils.c
2  * Utilities for combo box of interface names
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 /* With MSVC and a libethereal.dll this file needs to import some variables
26    in a special way. Therefore _NEED_VAR_IMPORT_ is defined. */
27 #define _NEED_VAR_IMPORT_
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #ifdef HAVE_LIBPCAP
34
35 #include <pcap.h>
36 #include <string.h>
37 #include <glib.h>
38
39 #include <epan/prefs.h>
40 #include "pcap-util.h"
41 #include "capture_combo_utils.h"
42
43 /*
44  * Find capture device description that matches interface name.
45  */
46 static char *
47 capture_dev_descr_find(const gchar *if_name)
48 {
49         char    *p;
50         char    *p2 = NULL;
51         char    *descr = NULL;
52         int             lp = 0;
53         int             ct = 0;
54
55         if (prefs.capture_devices_descr == NULL) {
56                 /* There are no descriptions. */
57                 return NULL;
58         }
59
60         if ((p = strstr(prefs.capture_devices_descr, if_name)) == NULL) {
61                 /* There are, but there isn't one for this interface. */
62                 return NULL;
63         }
64
65         while (*p != '\0') {
66                 /* error: ran into next interface description */
67                 if (*p == ',')
68                         return NULL;
69                 /* found left parenthesis, start of description */
70                 else if (*p == '(') {
71                         ct = 0;
72                         lp++;
73                         /* skip over left parenthesis */
74                         p++;
75                         /* save pointer to beginning of description */
76                         p2 = p;
77                         continue;
78                 }
79                 else if (*p == ')') {
80                         /* end of description */
81                         break;
82                 }
83                 else {
84                         p++;
85                         ct++;
86                 }
87         }
88
89         if ((lp == 1) && (ct > 0) && (p2 != NULL)) {
90                 /* Allocate enough space to return the string,
91                    which runs from p2 to p, plus a terminating
92                    '\0'. */
93                 descr = g_malloc(p - p2 + 1);
94                 memcpy(descr, p2, p - p2);
95                 descr[p - p2] = '\0';
96                 return descr;
97         }
98         else
99                 return NULL;
100 }
101
102 GList *
103 build_capture_combo_list(GList *if_list, gboolean do_hide)
104 {
105   GList *combo_list;
106   GList *if_entry;
107   if_info_t *if_info;
108   char *if_string;
109   gchar *descr;
110
111   combo_list = NULL;
112   if (if_list != NULL) {
113     /* Scan through the list and build a list of strings to display. */
114     for (if_entry = if_list; if_entry != NULL;
115          if_entry = g_list_next(if_entry)) {
116       if_info = if_entry->data;
117
118       /* Is this interface hidden and, if so, should we include it
119          anyway? */
120       if (prefs.capture_devices_hide == NULL ||
121           strstr(prefs.capture_devices_hide, if_info->name) == NULL ||
122           !do_hide) {
123         /* It's not hidden, or it is but we should include it in the list. */
124
125         /* Do we have a user-supplied description? */
126         descr = capture_dev_descr_find(if_info->name);
127         if (descr != NULL) {
128           /* Yes, we have a user-supplied description; use it. */
129           if_string = g_strdup_printf("%s: %s", descr, if_info->name);
130           g_free(descr);
131         } else {
132           /* No, we don't have a user-supplied description; did we get
133              one from the OS or libpcap? */
134           if (if_info->description != NULL) {
135             /* Yes - use it. */
136             if_string = g_strdup_printf("%s: %s", if_info->description,
137                                         if_info->name);
138           } else {
139             /* No. */
140             if_string = g_strdup(if_info->name);
141           }
142         }
143         combo_list = g_list_append(combo_list, if_string);
144       }
145     }
146   }
147   return combo_list;
148 }
149
150 static void
151 free_if_string(gpointer data, gpointer user_data _U_)
152 {
153   g_free(data);
154 }
155
156 void
157 free_capture_combo_list(GList *combo_list)
158 {
159   if (combo_list != NULL) {
160     g_list_foreach(combo_list, free_if_string, NULL);
161     g_list_free(combo_list);
162   }
163 }
164
165 /*
166  * Given text that contains an interface name possibly prefixed by an
167  * interface description, extract the interface name.
168  */
169 char *
170 get_if_name(char *if_text)
171 {
172   char *if_name;
173
174 #ifdef _WIN32
175   /*
176    * We cannot assume that the interface name doesn't contain a space;
177    * some names on Windows OT do.
178    *
179    * We also can't assume it begins with "\Device\", either, as, on
180    * Windows OT, WinPcap doesn't put "\Device\" in front of the name.
181    *
182    * As I remember, we can't assume that the interface description
183    * doesn't contain a colon, either; I think some do.
184    *
185    * We can probably assume that the interface *name* doesn't contain
186    * a colon, however; if any interface name does contain a colon on
187    * Windows, it'll be time to just get rid of the damn interface
188    * descriptions in the drop-down list, have just the names in the
189    * drop-down list, and have a "Browse..." button to browse for interfaces,
190    * with names, descriptions, IP addresses, blah blah blah available when
191    * possible.
192    *
193    * So we search backwards for a colon.  If we don't find it, just
194    * return the entire string; otherwise, skip the colon and any blanks
195    * after it, and return that string.
196    */
197    if_name = if_text + strlen(if_text);
198    for (;;) {
199      if (if_name == if_text) {
200        /* We're at the beginning of the string; return it. */
201        break;
202      }
203      if_name--;
204      if (*if_name == ':') {
205        /*
206         * We've found a colon.
207         * Unfortunately, a colon is used in the string "rpcap://",
208         * which is used in case of a remote capture.
209         * So we'll check to make sure the colon isn't followed by "//";
210         * it'll be followed by a blank if it separates the description
211         * and the interface name.  (We don't wire in "rpcap", in case we
212         * support other protocols in the same syntax.)
213         */
214        if (strncmp(if_name, "://", 3) != 0) {
215          /*
216           * OK, we've found a colon not followed by "//".  Skip blanks
217           * following it.
218           */
219          if_name++;
220          while (*if_name == ' ')
221            if_name++;
222          break;
223        }
224      }
225      /* Keep looking for a colon not followed by "//". */
226    }
227 #else
228   /*
229    * There's a space between the interface description and name, and
230    * the interface name shouldn't have a space in it (it doesn't, on
231    * UNIX systems); look backwards in the string for a space.
232    *
233    * (An interface name might, however, contain a colon in it, which
234    * is why we don't use the colon search on UNIX.)
235    */
236   if_name = strrchr(if_text, ' ');
237   if (if_name == NULL) {
238     if_name = if_text;
239   } else {
240     if_name++;
241   }
242 #endif
243   return if_name;
244 }
245
246
247
248 #endif /* HAVE_LIBPCAP */