Fix for bug 8548:
[metze/wireshark/wip.git] / capture_ui_utils.c
1 /* capture_ui_utils.c
2  * Utilities for capture user interfaces
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #include "config.h"
26
27 #ifdef HAVE_LIBPCAP
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <glib.h>
34
35 #include "epan/prefs.h"
36 #include "epan/ex-opt.h"
37 #include "capture_ifinfo.h"
38 #include "capture_ui_utils.h"
39 #include "ui/simple_dialog.h"
40 #include "wiretap/wtap.h"
41 #include "epan/to_str.h"
42
43 /*
44  * Find user-specified capture device description that matches interface
45  * name, if any.
46  */
47 char *
48 capture_dev_user_descr_find(const gchar *if_name)
49 {
50   char *p;
51   char *p2 = NULL;
52   char *descr = NULL;
53   int lp = 0;
54   int ct = 0;
55
56   if ((prefs.capture_devices_descr == NULL) ||
57       (*prefs.capture_devices_descr == '\0')) {
58     /* There are no descriptions. */
59     return NULL;
60   }
61
62   if ((p = strstr(prefs.capture_devices_descr, if_name)) == NULL) {
63     /* There are, but there isn't one for this interface. */
64     return NULL;
65   }
66
67   while (*p != '\0') {
68     /* error: ran into next interface description */
69     if (*p == ',')
70       return NULL;
71     /* found left parenthesis, start of description */
72     else if (*p == '(') {
73       ct = 0;
74       lp++;
75       /* skip over left parenthesis */
76       p++;
77       /* save pointer to beginning of description */
78       p2 = p;
79       continue;
80     }
81     else if (*p == ')') {
82       /* end of description */
83       break;
84     }
85     else {
86         p++;
87         ct++;
88     }
89   }
90
91   if ((lp == 1) && (ct > 0) && (p2 != NULL)) {
92     /* Allocate enough space to return the string,
93        which runs from p2 to p, plus a terminating
94        '\0'. */
95     descr = (char *)g_malloc(p - p2 + 1);
96     memcpy(descr, p2, p - p2);
97     descr[p - p2] = '\0';
98     return descr;
99   }
100   else
101     return NULL;
102 }
103
104 gint
105 capture_dev_user_linktype_find(const gchar *if_name)
106 {
107   gchar *p, *next;
108   long linktype;
109
110   if ((prefs.capture_devices_linktypes == NULL) ||
111       (*prefs.capture_devices_linktypes == '\0')) {
112     /* There are no link-layer header types */
113     return -1;
114   }
115
116   if ((p = strstr(prefs.capture_devices_linktypes, if_name)) == NULL) {
117     /* There are, but there isn't one for this interface. */
118     return -1;
119   }
120
121   p += strlen(if_name) + 1;
122   linktype = strtol(p, &next, 10);
123   if (next == p || *next != ')' || linktype < 0) {
124     /* Syntax error */
125     return -1;
126   }
127   if (linktype > G_MAXINT) {
128     /* Value doesn't fit in a gint */
129     return -1;
130   }
131
132   return (gint)linktype;
133 }
134
135 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
136 gint
137 capture_dev_user_buffersize_find(const gchar *if_name)
138 {
139   gchar *p, *next;
140   gint buffersize;
141
142   if ((prefs.capture_devices_buffersize == NULL) ||
143       (*prefs.capture_devices_buffersize == '\0')) {
144     /* There are no buffersizes defined */
145     return -1;
146   }
147
148   if ((p = strstr(prefs.capture_devices_buffersize, if_name)) == NULL) {
149     /* There are, but there isn't one for this interface. */
150     return -1;
151   }
152
153   p += strlen(if_name) + 1;
154   buffersize = (gint)strtol(p, &next, 10);
155   if (next == p || *next != ')' || buffersize < 0) {
156     /* Syntax error */
157     return -1;
158   }
159   if (buffersize > G_MAXINT) {
160     /* Value doesn't fit in a gint */
161     return -1;
162   }
163
164   return (gint)buffersize;
165 }
166 #endif
167
168 gint
169 capture_dev_user_snaplen_find(const gchar *if_name)
170 {
171   gchar *p, *next;
172   gint snaplen;
173
174   if ((prefs.capture_devices_snaplen == NULL) ||
175       (*prefs.capture_devices_snaplen == '\0')) {
176     /* There is no snap length defined */
177     return -1;
178   }
179
180   if ((p = strstr(prefs.capture_devices_snaplen, if_name)) == NULL) {
181     /* There are, but there isn't one for this interface. */
182     return -1;
183   }
184
185   p += strlen(if_name) + 3;
186   snaplen = (gint)strtol(p, &next, 10);
187   if (next == p || *next != ')' || snaplen < 0) {
188     /* Syntax error */
189     return -1;
190   }
191   if (snaplen > WTAP_MAX_PACKET_SIZE) {
192     /* Value doesn't fit in a gint */
193     return -1;
194   }
195
196   return (gint)snaplen;
197 }
198
199 gboolean
200 capture_dev_user_hassnap_find(const gchar *if_name)
201 {
202   gchar *p, *next;
203   gboolean hassnap;
204
205   if ((prefs.capture_devices_snaplen == NULL) ||
206       (*prefs.capture_devices_snaplen == '\0')) {
207     /* There is no snap length defined */
208     return -1;
209   }
210
211   if ((p = strstr(prefs.capture_devices_snaplen, if_name)) == NULL) {
212     /* There are, but there isn't one for this interface. */
213     return -1;
214   }
215
216   p += strlen(if_name) + 1;
217   hassnap = (gboolean)strtol(p, &next, 10);
218   if (next == p || *next != '(') {
219     /* Syntax error */
220     return -1;
221   }
222
223   return (gboolean)hassnap;
224 }
225
226 gboolean
227 capture_dev_user_pmode_find(const gchar *if_name)
228 {
229   gchar *p, *next;
230   gboolean pmode;
231
232   if ((prefs.capture_devices_pmode == NULL) ||
233       (*prefs.capture_devices_pmode == '\0')) {
234     /* There is no promiscuous mode defined */
235     return -1;
236   }
237
238   if ((p = strstr(prefs.capture_devices_pmode, if_name)) == NULL) {
239     /* There are, but there isn't one for this interface. */
240     return -1;
241   }
242
243   p += strlen(if_name) + 1;
244   pmode = (gboolean)strtol(p, &next, 10);
245   if (next == p || *next != ')') {
246     /* Syntax error */
247     return -1;
248   }
249   return (gboolean)pmode;
250 }
251
252 /*
253  * Return as descriptive a name for an interface as we can get.
254  * If the user has specified a comment, use that.  Otherwise,
255  * if capture_interface_list() supplies a description, use that,
256  * otherwise use the interface name.
257  *
258  * The result must be g_free()'d when you're done with it.
259  *
260  * Note: given that this calls capture_interface_list(), which attempts to
261  * open all adapters it finds in order to check whether they can be
262  * captured on, this is an expensive routine to call, so don't call it
263  * frequently.
264  */
265 char *
266 get_interface_descriptive_name(const char *if_name)
267 {
268   char *descr;
269   GList *if_list;
270   GList *if_entry;
271   if_info_t *if_info;
272   int err;
273
274   /* Do we have a user-supplied description? */
275   descr = capture_dev_user_descr_find(if_name);
276   if (descr != NULL) {
277     /* Yes - make a copy of that. */
278     descr = g_strdup(descr);
279   } else if (strcmp(if_name, "-") == 0) {
280     /*
281      * Strictly speaking, -X (extension) options are for modules, e.g. Lua
282      * and using one here stretches that definition. However, this doesn't
283      * waste a single-letter option on something that might be rarely used
284      * and is backward-compatible to 1.0.
285      */
286     descr = g_strdup(ex_opt_get_nth("stdin_descr", 0));
287     if (!descr) {
288       descr = g_strdup("Standard input");
289     }
290   } else {
291     /* No, we don't have a user-supplied description; did we get
292        one from the OS or libpcap? */
293     descr = NULL;
294     if_list = capture_interface_list(&err, NULL);
295     if (if_list != NULL) {
296       if_entry = if_list;
297       do {
298         if_info = (if_info_t *)if_entry->data;
299         if (strcmp(if_info->name, if_name) == 0) {
300           if (if_info->friendly_name != NULL) {
301               /* We have a "friendly name"; return a copy of that
302                  as the description - when we free the interface
303                  list, that'll also free up the strings to which
304                  it refers. */
305               descr = g_strdup(if_info->friendly_name);
306           } else if (if_info->vendor_description != NULL) {
307             /* We have no "friendly name", but we have a vendor
308                description; return a copy of that - when we free
309                the interface list, that'll also free up the strings
310                to which it refers. */
311             descr = g_strdup(if_info->vendor_description);
312           }
313           break;
314         }
315       } while ((if_entry = g_list_next(if_entry)) != NULL);
316     }
317     free_interface_list(if_list);
318
319     if (descr == NULL) {
320       /* The interface name is all we have, so just return a copy of that. */
321       descr = g_strdup(if_name);
322     }
323   }
324
325   return descr;
326 }
327
328
329 /* search interface info by interface name */
330 static if_info_t *
331 search_info(GList *if_list, gchar *if_name)
332 {
333   GList *if_entry;
334   if_info_t *if_info;
335
336
337   for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
338     if_info = (if_info_t *)if_entry->data;
339
340     if(strcmp(if_name, if_info->name) == 0) {
341       return if_info;
342     }
343   }
344
345   return NULL;
346 }
347
348
349 /* build the string to display in the combo box for the given interface */
350 char *
351 build_capture_combo_name(GList *if_list, gchar *if_name)
352 {
353   gchar *descr;
354   char *if_string;
355   if_info_t *if_info;
356
357   /* Do we have a user-supplied description? */
358   descr = capture_dev_user_descr_find(if_name);
359   if (descr != NULL) {
360     /* Yes, we have a user-supplied description; use it. */
361     if_string = g_strdup_printf("%s: %s", descr, if_name);
362     g_free(descr);
363   } else {
364     /* No, we don't have a user-supplied description; did we get
365      one from the OS or libpcap? */
366     if_info = search_info(if_list, if_name);
367     if (if_info != NULL && if_info->vendor_description != NULL) {
368       /* Yes - use it. */
369       if_string = g_strdup_printf("%s: %s", if_info->vendor_description,
370                                   if_info->name);
371     } else {
372       /* No. */
373       if_string = g_strdup(if_name);
374     }
375   }
376
377   return if_string;
378 }
379
380
381 GList *
382 build_capture_combo_list(GList *if_list, gboolean do_hide)
383 {
384   GList *combo_list;
385   GList *if_entry;
386   if_info_t *if_info;
387   char *if_string;
388   gchar *descr;
389
390   combo_list = NULL;
391   if (if_list != NULL) {
392     /* Scan through the list and build a list of strings to display. */
393     for (if_entry = if_list; if_entry != NULL;
394          if_entry = g_list_next(if_entry)) {
395       if_info = (if_info_t *)if_entry->data;
396
397       /* Is this interface hidden and, if so, should we include it
398          anyway? */
399       if (!prefs_is_capture_device_hidden(if_info->name) || !do_hide) {
400         /* It's not hidden, or it is but we should include it in the list. */
401
402         /* Do we have a user-supplied description? */
403         descr = capture_dev_user_descr_find(if_info->name);
404         if (descr != NULL) {
405           /* Yes, we have a user-supplied description; use it. */
406           if_string = g_strdup_printf("%s: %s", descr, if_info->name);
407           g_free(descr);
408         } else {
409           /* No, we don't have a user-supplied description; did we get
410              one from the OS or libpcap? */
411           if (if_info->vendor_description != NULL) {
412             /* Yes - use it. */
413             if_string = g_strdup_printf("%s: %s",
414                                         if_info->vendor_description,
415                                         if_info->name);
416           } else {
417             /* No. */
418             if_string = g_strdup(if_info->name);
419           }
420         }
421         combo_list = g_list_append(combo_list, if_string);
422       }
423     }/*for*/
424   }
425   return combo_list;
426 }
427
428 static void
429 free_if_string(gpointer data, gpointer user_data _U_)
430 {
431   g_free(data);
432 }
433
434 void
435 free_capture_combo_list(GList *combo_list)
436 {
437   if (combo_list != NULL) {
438     g_list_foreach(combo_list, free_if_string, NULL);
439     g_list_free(combo_list);
440   }
441 }
442
443 /*
444  * Given text that contains an interface name possibly prefixed by an
445  * interface description, extract the interface name.
446  */
447 const char *
448 get_if_name(const char *if_text)
449 {
450   const char *if_name;
451
452 #ifdef _WIN32
453   /*
454    * We cannot assume that the interface name doesn't contain a space;
455    * some names on Windows OT do.
456    *
457    * We also can't assume it begins with "\Device\", either, as, on
458    * Windows OT, WinPcap doesn't put "\Device\" in front of the name.
459    *
460    * As I remember, we can't assume that the interface description
461    * doesn't contain a colon, either; I think some do.
462    *
463    * We can probably assume that the interface *name* doesn't contain
464    * a colon, however; if any interface name does contain a colon on
465    * Windows, it'll be time to just get rid of the damn interface
466    * descriptions in the drop-down list, have just the names in the
467    * drop-down list, and have a "Browse..." button to browse for interfaces,
468    * with names, descriptions, IP addresses, blah blah blah available when
469    * possible.
470    *
471    * So we search backwards for a colon.  If we don't find it, just
472    * return the entire string; otherwise, skip the colon and any blanks
473    * after it, and return that string.
474    */
475    if_name = if_text + strlen(if_text);
476    for (;;) {
477      if (if_name == if_text) {
478        /* We're at the beginning of the string; return it. */
479        break;
480      }
481      if_name--;
482      if (*if_name == ':') {
483        /*
484         * We've found a colon.
485         * Unfortunately, a colon is used in the string "rpcap://",
486         * which is used in case of a remote capture.
487         * So we'll check to make sure the colon isn't followed by "//";
488         * it'll be followed by a blank if it separates the description
489         * and the interface name.  (We don't wire in "rpcap", in case we
490         * support other protocols in the same syntax.)
491         * Unfortunately, another colon can be used in "rpcap://host:port/"
492         * before port. Check if colon is followed by digit.
493         */
494        if ((strncmp(if_name, "://", 3) != 0) && !isdigit(if_name[1])) {
495          /*
496           * OK, we've found a colon followed neither by "//" nor by digit.  
497           * Skip blanks following it.
498           */
499          if_name++;
500          while (*if_name == ' ')
501            if_name++;
502          break;
503        }
504      }
505      /* Keep looking for a colon not followed by "//". */
506    }
507 #else
508   /*
509    * There's a space between the interface description and name, and
510    * the interface name shouldn't have a space in it (it doesn't, on
511    * UNIX systems); look backwards in the string for a space.
512    *
513    * (An interface name might, however, contain a colon in it, which
514    * is why we don't use the colon search on UNIX.)
515    */
516   if_name = strrchr(if_text, ' ');
517   if (if_name == NULL) {
518     if_name = if_text;
519   } else {
520     if_name++;
521   }
522 #endif
523   return if_name;
524 }
525
526 /*  Return interface_opts->descr (after setting it if it is not set)
527  *  This is necessary because capture_opts.c can't set descr (at least
528  *  not without adding significant dependencies there).
529  */
530 const char *
531 get_iface_description_for_interface(capture_options *capture_opts, guint i)
532 {
533   interface_options interface_opts;
534
535   if (i < capture_opts->ifaces->len) {
536     interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
537     if (!interface_opts.descr && interface_opts.name) {
538       interface_opts.descr = get_interface_descriptive_name(interface_opts.name);
539       capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, i);
540       g_array_insert_val(capture_opts->ifaces, i, interface_opts);
541     }
542     return (interface_opts.descr);
543   } else {
544     return (NULL);
545   }
546 }
547
548 #endif /* HAVE_LIBPCAP */