Change the formatting strings used to create the Conversation Filter submenu
[metze/wireshark/wip.git] / ui / capture_ui_utils.c
1 /* capture_ui_utils.c
2  * Utilities for capture user interfaces
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "config.h"
24
25 #ifdef HAVE_LIBPCAP
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <glib.h>
31
32 #include "epan/prefs.h"
33 #include "epan/ex-opt.h"
34 #include "caputils/capture_ifinfo.h"
35 #include "ui/capture_ui_utils.h"
36 #include "ui/capture_globals.h"
37 #include "wiretap/wtap.h"
38 #include "epan/to_str.h"
39
40 /*
41  * In a list of interface information, in the form of a comma-separated
42  * list of {name}({property}) items, find the entry for a particular
43  * interface, and return a pointer a g_malloced string containing
44  * the property.
45  */
46 static char *
47 capture_dev_get_if_property(const gchar *pref, const gchar *if_name)
48 {
49   gchar **if_tokens;
50   gchar *property = NULL;
51   int i;
52
53   if (if_name == NULL || strlen(if_name) < 1) {
54     return NULL;
55   }
56
57   if (pref == NULL || strlen(pref) < 1) {
58     /* There is no interface information list. */
59     return NULL;
60   }
61
62   /*
63    * Split the list into a sequence of items.
64    *
65    * XXX - this relies on the items not themselves containing commas.
66    */
67   if_tokens = g_strsplit(pref, ",", -1);
68   for (i = 0; if_tokens[i] != NULL; i++) {
69     gchar *opening_parenp, *closing_parenp;
70
71     /*
72      * Separate this item into name and property.
73      * The first opening parenthesis and the last closing parenthesis
74      * surround the property.  Any other parentheses are part of
75      * the property.
76      */
77     opening_parenp = strchr(if_tokens[i], '(');
78     if (opening_parenp == NULL) {
79       /* No opening parenthesis. Give up. */
80       break;
81     }
82     closing_parenp = strrchr(if_tokens[i], ')');
83     if (closing_parenp == NULL || closing_parenp <= opening_parenp) {
84       /* No closing parenthesis or invalid input. Give up. */
85       break;
86     }
87     *opening_parenp = '\0'; /* Split {name} from what follows */
88     *closing_parenp = '\0'; /* Terminate {property} */
89     if (strcmp(if_tokens[i], if_name) == 0) {
90       if (strlen(opening_parenp + 1) > 0) {
91         property = g_strdup(opening_parenp + 1);
92       }
93       break;
94     }
95   }
96   g_strfreev(if_tokens);
97
98   return property;
99 }
100
101 /*
102  * Find a property that should be an integral value, and return the
103  * value or, if it's not found or not a valid integral value, -1.
104  */
105 static gint
106 capture_dev_get_if_int_property(const gchar *pref, const gchar *if_name)
107 {
108   gchar *property_string, *next;
109   long property;
110
111   property_string = capture_dev_get_if_property(pref, if_name);
112   if (property_string == NULL) {
113     /* No property found for this interface. */
114     return -1;
115   }
116   property = strtol(property_string, &next, 10);
117   if (next == property_string || *next != '\0' || property < 0) {
118     /* Syntax error */
119     g_free(property_string);
120     return -1;
121   }
122   if (property > G_MAXINT) {
123     /* Value doesn't fit in a gint */
124     g_free(property_string);
125     return -1;
126   }
127
128   g_free(property_string);
129   return (gint)property;
130 }
131
132 /*
133  * Find user-specified capture device description that matches interface
134  * name, if any.
135  */
136 char *
137 capture_dev_user_descr_find(const gchar *if_name)
138 {
139   return capture_dev_get_if_property(prefs.capture_devices_descr, if_name);
140 }
141
142 gint
143 capture_dev_user_linktype_find(const gchar *if_name)
144 {
145   return capture_dev_get_if_int_property(prefs.capture_devices_linktypes, if_name);
146 }
147
148 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
149 gint
150 capture_dev_user_buffersize_find(const gchar *if_name)
151 {
152   return capture_dev_get_if_int_property(prefs.capture_devices_buffersize, if_name);
153 }
154 #endif
155
156 gboolean
157 capture_dev_user_snaplen_find(const gchar *if_name, gboolean *hassnap, int *snaplen)
158 {
159   gboolean found = FALSE;
160   gchar **if_tokens;
161   int i;
162
163   if (if_name == NULL || strlen(if_name) < 1) {
164     return FALSE;
165   }
166
167   if ((prefs.capture_devices_snaplen == NULL) ||
168       (*prefs.capture_devices_snaplen == '\0')) {
169     /* There are no snap lengths defined */
170     return FALSE;
171   }
172
173   /*
174    * Split the list into a sequence of items.
175    *
176    * XXX - this relies on the items not themselves containing commas.
177    */
178   if_tokens = g_strsplit(prefs.capture_devices_snaplen, ",", -1);
179   for (i = 0; if_tokens[i] != NULL; i++) {
180     gchar *colonp, *next;
181     long value;
182
183     /*
184      * This one's a bit ugly.
185      * The syntax of the item is {name}:{hassnap}({snaplen}),
186      * where {hassnap} is 0 if the interface shouldn't have a snapshot
187      * length and 1 if it should, and {snaplen} is the maximum snapshot
188      * length if {hassnap} is 0 and the specified snapshot length if
189      * {hassnap} is 1.
190      *
191      * Sadly, : was a bad choice of separator, given that, on some OSes,
192      * an interface can have a colon in its name.
193      *
194      * So we look for the *last* colon in the string.
195      */
196     colonp = strrchr(if_tokens[i], ':');
197     if (colonp == NULL) {
198       /* No separating colon. Give up. */
199       break;
200     }
201     *colonp = '\0'; /* Split {name} from what follows */
202     if (strcmp(if_tokens[i], if_name) == 0) {
203       /* OK, this matches. */
204       if (*(colonp + 1) == '0') {
205         /* {hassnap} is false, so just set the snaplen to WTAP_MAX_PACKET_SIZE. */
206         found = TRUE;
207         *hassnap = FALSE;
208         *snaplen = WTAP_MAX_PACKET_SIZE;
209       } else if (*(colonp + 1) == '1') {
210         /* {hassnap} is true, so extract {snaplen} */
211         if (*(colonp + 2) != '(') {
212           /* Not followed by a parenthesis. Give up. */
213           break;
214         }
215         value = strtol(colonp + 3, &next, 10);
216         if (next == colonp + 3 || *next != ')' || value < 0) {
217           /* Syntax error. Give up. */
218           break;
219         }
220         if (value > G_MAXINT) {
221           /* Value doesn't fit in a gint. Give up. */
222           break;
223         }
224         found = TRUE;
225         *hassnap = TRUE;
226         *snaplen = (gint)value;
227       } else {
228         /* Bad {hassnap}. Give up. */
229         break;
230       }
231       break;
232     }
233   }
234   g_strfreev(if_tokens);
235
236   return found;
237 }
238
239 gboolean
240 capture_dev_user_pmode_find(const gchar *if_name, gboolean *pmode)
241 {
242   int value;
243
244   value = capture_dev_get_if_int_property(prefs.capture_devices_pmode, if_name);
245   if (value == -1) {
246     /* Not found or bad. */
247     return FALSE;
248   }
249   *pmode = (value != 0);
250   return TRUE;
251 }
252
253 gchar*
254 capture_dev_user_cfilter_find(const gchar *if_name)
255 {
256   return capture_dev_get_if_property(prefs.capture_devices_filter, if_name);
257 }
258
259 /*
260  * Return as descriptive a name for an interface as we can get.
261  * If the user has specified a comment, use that.  Otherwise,
262  * if capture_interface_list() supplies a description, use that,
263  * otherwise use the interface name.
264  *
265  * The result must be g_free()'d when you're done with it.
266  *
267  * Note: given that this calls capture_interface_list(), which attempts to
268  * open all adapters it finds in order to check whether they can be
269  * captured on, this is an expensive routine to call, so don't call it
270  * frequently.
271  */
272 char *
273 get_interface_descriptive_name(const char *if_name)
274 {
275   char *descr;
276   GList *if_list;
277   GList *if_entry;
278   if_info_t *if_info;
279   int err;
280
281   /* Do we have a user-supplied description? */
282   descr = capture_dev_user_descr_find(if_name);
283   if (descr == NULL) {
284     /* No; try to construct a descriptive name. */
285     if (strcmp(if_name, "-") == 0) {
286       /*
287        * Strictly speaking, -X (extension) options are for modules, e.g. Lua
288        * and using one here stretches that definition. However, this doesn't
289        * waste a single-letter option on something that might be rarely used
290        * and is backward-compatible to 1.0.
291        */
292       descr = g_strdup(ex_opt_get_nth("stdin_descr", 0));
293       if (!descr) {
294         descr = g_strdup("Standard input");
295       }
296     } else {
297       /* No, we don't have a user-supplied description; did we get
298          one from the OS or libpcap? */
299       descr = NULL;
300       if_list = capture_interface_list(&err, NULL, NULL);
301       if (if_list != NULL) {
302         if_entry = if_list;
303         do {
304           if_info = (if_info_t *)if_entry->data;
305           if (strcmp(if_info->name, if_name) == 0) {
306             if (if_info->friendly_name != NULL) {
307                 /* We have a "friendly name"; return a copy of that
308                    as the description - when we free the interface
309                    list, that'll also free up the strings to which
310                    it refers. */
311                 descr = g_strdup(if_info->friendly_name);
312             } else if (if_info->vendor_description != NULL) {
313               /* We have no "friendly name", but we have a vendor
314                  description; return a copy of that - when we free
315                  the interface list, that'll also free up the strings
316                  to which it refers. */
317               descr = g_strdup(if_info->vendor_description);
318             }
319             break;
320           }
321         } while ((if_entry = g_list_next(if_entry)) != NULL);
322       }
323       free_interface_list(if_list);
324
325       if (descr == NULL) {
326         /* The interface name is all we have, so just return a copy of that. */
327         descr = g_strdup(if_name);
328       }
329     }
330   }
331
332   return descr;
333 }
334
335 GList *
336 build_capture_combo_list(GList *if_list, gboolean do_hide)
337 {
338   GList *combo_list;
339   GList *if_entry;
340   if_info_t *if_info;
341   char *if_string;
342   gchar *descr;
343
344   combo_list = NULL;
345   if (if_list != NULL) {
346     /* Scan through the list and build a list of strings to display. */
347     for (if_entry = if_list; if_entry != NULL;
348          if_entry = g_list_next(if_entry)) {
349       if_info = (if_info_t *)if_entry->data;
350
351       /* Is this interface hidden and, if so, should we include it
352          anyway? */
353       if (!prefs_is_capture_device_hidden(if_info->name) || !do_hide) {
354         /* It's not hidden, or it is but we should include it in the list. */
355
356         /* Do we have a user-supplied description? */
357         descr = capture_dev_user_descr_find(if_info->name);
358         if (descr != NULL) {
359           /* Yes, we have a user-supplied description; use it. */
360           if_string = g_strdup_printf("%s: %s", descr, if_info->name);
361           g_free(descr);
362         } else {
363           /* No, we don't have a user-supplied description; did we get
364              one from the OS or libpcap? */
365           if (if_info->vendor_description != NULL) {
366             /* Yes - use it. */
367             if_string = g_strdup_printf("%s: %s",
368                                         if_info->vendor_description,
369                                         if_info->name);
370           } else {
371             /* No. */
372             if_string = g_strdup(if_info->name);
373           }
374         }
375         combo_list = g_list_append(combo_list, if_string);
376       }
377     }/*for*/
378   }
379   return combo_list;
380 }
381
382 static void
383 free_if_string(gpointer data, gpointer user_data _U_)
384 {
385   g_free(data);
386 }
387
388 void
389 free_capture_combo_list(GList *combo_list)
390 {
391   if (combo_list != NULL) {
392     g_list_foreach(combo_list, free_if_string, NULL);
393     g_list_free(combo_list);
394   }
395 }
396
397 /*
398  * Given text that contains an interface name possibly prefixed by an
399  * interface description, extract the interface name.
400  */
401 const char *
402 get_if_name(const char *if_text)
403 {
404   const char *if_name;
405
406 #ifdef _WIN32
407   /*
408    * We cannot assume that the interface name doesn't contain a space;
409    * some names on Windows OT do.
410    *
411    * We also can't assume it begins with "\Device\", either, as, on
412    * Windows OT, WinPcap doesn't put "\Device\" in front of the name.
413    *
414    * As I remember, we can't assume that the interface description
415    * doesn't contain a colon, either; I think some do.
416    *
417    * We can probably assume that the interface *name* doesn't contain
418    * a colon, however; if any interface name does contain a colon on
419    * Windows, it'll be time to just get rid of the damn interface
420    * descriptions in the drop-down list, have just the names in the
421    * drop-down list, and have a "Browse..." button to browse for interfaces,
422    * with names, descriptions, IP addresses, blah blah blah available when
423    * possible.
424    *
425    * So we search backwards for a colon.  If we don't find it, just
426    * return the entire string; otherwise, skip the colon and any blanks
427    * after it, and return that string.
428    */
429    if_name = if_text + strlen(if_text);
430    for (;;) {
431      if (if_name == if_text) {
432        /* We're at the beginning of the string; return it. */
433        break;
434      }
435      if_name--;
436      if (*if_name == ':') {
437        /*
438         * We've found a colon.
439         * Unfortunately, a colon is used in the string "rpcap://",
440         * which is used in case of a remote capture.
441         * So we'll check to make sure the colon isn't followed by "//";
442         * it'll be followed by a blank if it separates the description
443         * and the interface name.  (We don't wire in "rpcap", in case we
444         * support other protocols in the same syntax.)
445         * Unfortunately, another colon can be used in "rpcap://host:port/"
446         * before port. Check if colon is followed by digit.
447         */
448        if ((strncmp(if_name, "://", 3) != 0) && !g_ascii_isdigit(if_name[1])) {
449          /*
450           * OK, we've found a colon followed neither by "//" nor by digit.
451           * Skip blanks following it.
452           */
453          if_name++;
454          while (*if_name == ' ')
455            if_name++;
456          break;
457        }
458      }
459      /* Keep looking for a colon not followed by "//". */
460    }
461 #else
462   /*
463    * There's a space between the interface description and name, and
464    * the interface name shouldn't have a space in it (it doesn't, on
465    * UNIX systems); look backwards in the string for a space.
466    *
467    * (An interface name might, however, contain a colon in it, which
468    * is why we don't use the colon search on UNIX.)
469    */
470   if_name = strrchr(if_text, ' ');
471   if (if_name == NULL) {
472     if_name = if_text;
473   } else {
474     if_name++;
475   }
476 #endif
477   return if_name;
478 }
479
480 /*  Return interface_opts->descr (after setting it if it is not set)
481  *  This is necessary because capture_opts.c can't set descr (at least
482  *  not without adding significant dependencies there).
483  */
484 const char *
485 get_iface_description_for_interface(capture_options *capture_opts, guint i)
486 {
487   interface_options interface_opts;
488
489   if (i < capture_opts->ifaces->len) {
490     interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
491     if (!interface_opts.descr && interface_opts.name) {
492       interface_opts.descr = get_interface_descriptive_name(interface_opts.name);
493       capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, i);
494       g_array_insert_val(capture_opts->ifaces, i, interface_opts);
495     }
496     return (interface_opts.descr);
497   } else {
498     return (NULL);
499   }
500 }
501
502 /*
503  * Set the active DLT for a device appropriately.
504  */
505 void
506 set_active_dlt(interface_t *device, int global_default_dlt)
507 {
508   GList    *list;
509   gboolean  found_active_dlt;
510   link_row *link;
511
512   /*
513    * If there's a preference for the link-layer header type for
514    * this interface, use it.  If not, use the all-interface
515    * default; if that's not set on the command line, that will
516    * be -1, meaning "use per-interface defaults", otherwise
517    * we'll fail if it's not one of the types the interface
518    * supports.
519    */
520   if ((device->active_dlt = capture_dev_user_linktype_find(device->name)) == -1) {
521     device->active_dlt = global_default_dlt;
522   }
523
524   /*
525    * Is that one of the supported link-layer header types?
526    * If not, set it to -1, so we'll fall back on the first supported
527    * link-layer header type.
528    */
529   found_active_dlt = FALSE;
530   for (list = device->links; list != NULL; list = g_list_next(list)) {
531     link = (link_row *)(list->data);
532     if (link->dlt != -1 && link->dlt == device->active_dlt) {
533       found_active_dlt = TRUE;
534       break;
535     }
536   }
537   if (!found_active_dlt) {
538     device->active_dlt = -1;
539   }
540   if (device->active_dlt == -1) {
541     /* Fall back on the first supported DLT, if we have one. */
542     for (list = device->links; list != NULL; list = g_list_next(list)) {
543       link = (link_row *)(list->data);
544       if (link->dlt != -1) {
545         device->active_dlt = link->dlt;
546         break;
547       }
548     }
549   }
550 }
551
552 GString *
553 get_iface_list_string(capture_options *capture_opts, guint32 style)
554 {
555   GString *iface_list_string = g_string_new("");
556   guint i;
557
558   /*
559    * If we have a descriptive name for the interface, show that,
560    * rather than its raw name.  On NT 5.x (2K/XP/Server2K3), the
561    * interface name is something like "\Device\NPF_{242423..."
562    * which is pretty useless to the normal user.  On other platforms,
563    * it might be less cryptic, but if a more descriptive name is
564    * available, we should still use that.
565    */
566 #ifdef _WIN32
567   if (capture_opts->ifaces->len < 2) {
568 #else
569   if (capture_opts->ifaces->len < 4) {
570 #endif
571     for (i = 0; i < capture_opts->ifaces->len; i++) {
572       if (i > 0) {
573         if (capture_opts->ifaces->len > 2) {
574           g_string_append_printf(iface_list_string, ",");
575         }
576         g_string_append_printf(iface_list_string, " ");
577         if (i == capture_opts->ifaces->len - 1) {
578           g_string_append_printf(iface_list_string, "and ");
579         }
580       }
581       if (style & IFLIST_QUOTE_IF_DESCRIPTION)
582         g_string_append_printf(iface_list_string, "'");
583       g_string_append_printf(iface_list_string, "%s", get_iface_description_for_interface(capture_opts, i));
584       if (style & IFLIST_QUOTE_IF_DESCRIPTION)
585         g_string_append_printf(iface_list_string, "'");
586       if (style & IFLIST_SHOW_FILTER) {
587         interface_options interface_opts;
588
589         interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
590         if (interface_opts.cfilter != NULL &&
591             strlen(interface_opts.cfilter) > 0) {
592           g_string_append_printf(iface_list_string, " (%s)", interface_opts.cfilter);
593         }
594       }
595     }
596   } else {
597     g_string_append_printf(iface_list_string, "%u interfaces", capture_opts->ifaces->len);
598   }
599   return iface_list_string;
600 }
601
602 #endif /* HAVE_LIBPCAP */
603
604 /*
605  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
606  *
607  * Local Variables:
608  * c-basic-offset: 2
609  * tab-width: 8
610  * indent-tabs-mode: nil
611  * End:
612  *
613  * ex: set shiftwidth=2 tabstop=8 expandtab:
614  * :indentSize=2:tabSize=8:noTabs=true:
615  */