Support monitor mode in the capture preferences.
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 15 May 2010 19:38:13 +0000 (19:38 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 15 May 2010 19:38:13 +0000 (19:38 +0000)
Use prefs_is_capture_device_hidden() to find out whether a device should
be hidden - don't scan the list of hidden devices ourselves.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@32820 f5534014-38df-0310-8fa8-9805f1628bb7

epan/prefs.c
epan/prefs.h
gtk/capture_dlg.c
gtk/capture_dlg.h
gtk/main_welcome.c
gtk/prefs_capture.c

index a33e80672f1c5b4c9429e248cb8d448ee76e5b83..1465bb99767194c049ec4fdc87713e03ec2a0898 100644 (file)
@@ -1194,24 +1194,25 @@ init_prefs(void) {
       G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR;
 
 /* set the default values for the capture dialog box */
-  prefs.capture_device           = NULL;
-  prefs.capture_devices_linktypes= NULL;
-  prefs.capture_devices_descr    = NULL;
-  prefs.capture_devices_hide     = NULL;
-  prefs.capture_prom_mode        = TRUE;
-  prefs.capture_pcap_ng          = FALSE;
-  prefs.capture_real_time        = TRUE;
-  prefs.capture_auto_scroll      = TRUE;
-  prefs.capture_show_info        = FALSE;
+  prefs.capture_device                = NULL;
+  prefs.capture_devices_linktypes     = NULL;
+  prefs.capture_devices_descr         = NULL;
+  prefs.capture_devices_hide          = NULL;
+  prefs.capture_devices_monitor_mode  = NULL;
+  prefs.capture_prom_mode             = TRUE;
+  prefs.capture_pcap_ng               = FALSE;
+  prefs.capture_real_time             = TRUE;
+  prefs.capture_auto_scroll           = TRUE;
+  prefs.capture_show_info             = FALSE;
 
 /* set the default values for the name resolution dialog box */
   prefs.name_resolve             = RESOLV_ALL ^ RESOLV_NETWORK;
   prefs.name_resolve_concurrency = 500;
   prefs.load_smi_modules         = FALSE;
-  prefs.suppress_smi_errors         = FALSE;
+  prefs.suppress_smi_errors     = FALSE;
 
 /* set the default values for the tap/statistics dialog box */
-  prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL;
+  prefs.tap_update_interval    = TAP_UPDATE_DEFAULT_INTERVAL;
   prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE;
 
   prefs.display_hidden_proto_items = FALSE;
@@ -1239,6 +1240,7 @@ prefs_reset(void)
   g_free(prefs.capture_devices_linktypes);
   g_free(prefs.capture_devices_descr);
   g_free(prefs.capture_devices_hide);
+  g_free(prefs.capture_devices_monitor_mode);
 
   uat_unload_all();
   oids_cleanup();
@@ -1622,6 +1624,30 @@ prefs_is_capture_device_hidden(const char *name)
        return FALSE;
 }
 
+/*
+ * Returns TRUE if the given device should capture in monitor mode by default
+ */
+gboolean
+prefs_capture_device_monitor_mode(const char *name)
+{
+       gchar *tok, *devices;
+       size_t len;
+
+       if (prefs.capture_devices_monitor_mode && name) {
+               devices = g_strdup (prefs.capture_devices_monitor_mode);
+               len = strlen (name);
+               for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
+                       if (strlen (tok) == len && strcmp (name, tok) == 0) {
+                               g_free (devices);
+                               return TRUE;
+                       }
+               }
+               g_free (devices);
+       }
+
+       return FALSE;
+}
+
 #define PRS_PRINT_FMT                    "print.format"
 #define PRS_PRINT_DEST                   "print.destination"
 #define PRS_PRINT_FILE                   "print.file"
@@ -1692,15 +1718,16 @@ prefs_is_capture_device_hidden(const char *name)
 #define PRS_CAP_NAME_RESOLVE "capture.name_resolve"
 
 /*  values for the capture dialog box */
-#define PRS_CAP_DEVICE        "capture.device"
-#define PRS_CAP_DEVICES_LINKTYPES "capture.devices_linktypes"
-#define PRS_CAP_DEVICES_DESCR "capture.devices_descr"
-#define PRS_CAP_DEVICES_HIDE  "capture.devices_hide"
-#define PRS_CAP_PROM_MODE     "capture.prom_mode"
-#define PRS_CAP_PCAP_NG       "capture.pcap_ng"
-#define PRS_CAP_REAL_TIME     "capture.real_time_update"
-#define PRS_CAP_AUTO_SCROLL   "capture.auto_scroll"
-#define PRS_CAP_SHOW_INFO     "capture.show_info"
+#define PRS_CAP_DEVICE               "capture.device"
+#define PRS_CAP_DEVICES_LINKTYPES    "capture.devices_linktypes"
+#define PRS_CAP_DEVICES_DESCR        "capture.devices_descr"
+#define PRS_CAP_DEVICES_HIDE         "capture.devices_hide"
+#define PRS_CAP_DEVICES_MONITOR_MODE "capture.devices_monitor_mode"
+#define PRS_CAP_PROM_MODE            "capture.prom_mode"
+#define PRS_CAP_PCAP_NG              "capture.pcap_ng"
+#define PRS_CAP_REAL_TIME            "capture.real_time_update"
+#define PRS_CAP_AUTO_SCROLL          "capture.auto_scroll"
+#define PRS_CAP_SHOW_INFO            "capture.show_info"
 
 #define RED_COMPONENT(x)   (guint16) (((((x) >> 16) & 0xff) * 65535 / 255))
 #define GREEN_COMPONENT(x) (guint16) (((((x) >>  8) & 0xff) * 65535 / 255))
@@ -2162,11 +2189,14 @@ set_pref(gchar *pref_name, gchar *value, void *private_data _U_)
   } else if (strcmp(pref_name, PRS_CAP_DEVICES_HIDE) == 0) {
     g_free(prefs.capture_devices_hide);
     prefs.capture_devices_hide = g_strdup(value);
+  } else if (strcmp(pref_name, PRS_CAP_DEVICES_MONITOR_MODE) == 0) {
+    g_free(prefs.capture_devices_monitor_mode);
+    prefs.capture_devices_monitor_mode = g_strdup(value);
   } else if (strcmp(pref_name, PRS_CAP_PROM_MODE) == 0) {
     prefs.capture_prom_mode = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
-   } else if (strcmp(pref_name, PRS_CAP_PCAP_NG) == 0) {
+  } else if (strcmp(pref_name, PRS_CAP_PCAP_NG) == 0) {
     prefs.capture_pcap_ng = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
- } else if (strcmp(pref_name, PRS_CAP_REAL_TIME) == 0) {
 } else if (strcmp(pref_name, PRS_CAP_REAL_TIME) == 0) {
     prefs.capture_real_time = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
   } else if (strcmp(pref_name, PRS_CAP_AUTO_SCROLL) == 0) {
     prefs.capture_auto_scroll = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
@@ -3023,6 +3053,12 @@ write_prefs(char **pf_path_return)
     fprintf(pf, PRS_CAP_DEVICES_HIDE ": %s\n", prefs.capture_devices_hide);
   }
 
+  if (prefs.capture_devices_monitor_mode != NULL) {
+    fprintf(pf, "\n# By default, capture in monitor mode on interface?\n");
+    fprintf(pf, "# Ex: eth0,eth3,...\n");
+    fprintf(pf, PRS_CAP_DEVICES_MONITOR_MODE ": %s\n", prefs.capture_devices_monitor_mode);
+  }
+
   fprintf(pf, "\n# Capture in promiscuous mode?\n");
   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
   fprintf(pf, PRS_CAP_PROM_MODE ": %s\n",
@@ -3183,6 +3219,7 @@ copy_prefs(e_prefs *dest, e_prefs *src)
   dest->capture_devices_linktypes = g_strdup(src->capture_devices_linktypes);
   dest->capture_devices_descr = g_strdup(src->capture_devices_descr);
   dest->capture_devices_hide = g_strdup(src->capture_devices_hide);
+  dest->capture_devices_monitor_mode = g_strdup(src->capture_devices_monitor_mode);
   dest->capture_prom_mode = src->capture_prom_mode;
   dest->capture_pcap_ng = src->capture_pcap_ng;
   dest->capture_real_time = src->capture_real_time;
@@ -3241,6 +3278,10 @@ free_prefs(e_prefs *pr)
     g_free(pr->capture_devices_hide);
     pr->capture_devices_hide = NULL;
   }
+  if (pr->capture_devices_monitor_mode != NULL) {
+    g_free(pr->capture_devices_monitor_mode);
+    pr->capture_devices_monitor_mode = NULL;
+  }
 }
 
 static void
@@ -3260,5 +3301,3 @@ free_col_info(e_prefs *pr)
   g_list_free(pr->col_list);
   pr->col_list = NULL;
 }
-
-
index 68c97cbc1454b0b9bb19e75ba7af8dc9a4d55b72..c15b966afaba0c019868600b241a41cf5838d56e 100644 (file)
@@ -153,6 +153,7 @@ typedef struct _e_prefs {
   gchar   *capture_devices_linktypes;
   gchar   *capture_devices_descr;
   gchar   *capture_devices_hide;
+  gchar   *capture_devices_monitor_mode;
   gboolean capture_prom_mode;
   gboolean capture_pcap_ng;
   gboolean capture_real_time;
@@ -447,4 +448,9 @@ extern prefs_set_pref_e prefs_set_pref(char *prefarg);
  */
 extern gboolean prefs_is_capture_device_hidden(const char *name);
 
+/*
+ * Returns TRUE if the given device should capture in monitor mode by default
+ */
+extern gboolean prefs_capture_device_monitor_mode(const char *name);
+
 #endif /* prefs.h */
index 0c948831443ffcbd5c7f9c69d66cd9029ff763d6..50d9d2b13b8093183765ec995b21b54c74ce11c6 100644 (file)
  */
 static GtkWidget *cap_open_w;
 static GtkWidget * dl_hdr_menu=NULL;
-static GHashTable *linktype_history=NULL;
+static GHashTable *cap_settings_history=NULL;
 
 #ifdef HAVE_PCAP_REMOTE
 static GHashTable *remote_host_list=NULL;
@@ -227,24 +227,25 @@ capture_restart_cb(GtkWidget *w _U_, gpointer d _U_)
     capture_restart(&global_capture_opts);
 }
 
-gint
-capture_get_linktype (gchar *if_name)
+cap_settings_t
+capture_get_cap_settings (gchar *if_name)
 {
-  gint linktype, *linktype_p;
+  cap_settings_t cap_settings, *cap_settings_p;
 
-  if (linktype_history) {
-    linktype_p = g_hash_table_lookup(linktype_history, if_name);
+  if (cap_settings_history) {
+    cap_settings_p = g_hash_table_lookup(cap_settings_history, if_name);
   } else {
-    linktype_p = NULL;
+    cap_settings_p = NULL;
   }
 
-  if (linktype_p) {
-    linktype = *linktype_p;
+  if (cap_settings_p) {
+    cap_settings = *cap_settings_p;
   } else {
-    linktype = capture_dev_user_linktype_find(if_name);
+    cap_settings.monitor_mode = prefs_capture_device_monitor_mode(if_name);
+    cap_settings.linktype = capture_dev_user_linktype_find(if_name);;
   }
 
-  return linktype;
+  return cap_settings;
 }
 
 /*
@@ -255,7 +256,7 @@ capture_get_linktype (gchar *if_name)
  * it will be disabled.
  */
 static void
-set_if_capabilities(void)
+set_if_capabilities(gboolean monitor_mode_changed)
 {
   gchar *entry_text;
   gchar *if_text;
@@ -267,7 +268,8 @@ set_if_capabilities(void)
   int err;
   GtkWidget *lt_menu, *lt_menu_item;
   GList *lt_entry;
-  gint linktype, linktype_select, linktype_count;
+  cap_settings_t cap_settings;
+  gint linktype_select, linktype_count;
   data_link_info_t *data_link_info;
   gchar *linktype_menu_label;
   guint num_supported_link_types;
@@ -287,7 +289,6 @@ set_if_capabilities(void)
 #ifdef HAVE_PCAP_CREATE
   GtkWidget *monitor_cb = (GtkWidget *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_MONITOR_KEY);
 #endif
-  gboolean monitor_mode;
 #ifdef HAVE_AIRPCAP
   GtkWidget *advanced_bt;
 #endif
@@ -301,7 +302,16 @@ set_if_capabilities(void)
   entry_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
   if_text = g_strstrip(entry_text);
   if_name = g_strdup(get_if_name(if_text));
-  linktype = capture_get_linktype(if_name);
+  cap_settings = capture_get_cap_settings(if_name);
+  if (monitor_mode_changed) {
+#ifdef HAVE_PCAP_CREATE
+    /* Get the new setting of the monitor mode button. */
+    cap_settings.monitor_mode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(monitor_cb));
+#else
+    /* No monitor-mode support. */
+    cap_settings.monitor_mode = FALSE;
+#endif
+  }
 
 #ifdef HAVE_AIRPCAP
   /* is it an airpcap interface??? */
@@ -354,18 +364,16 @@ set_if_capabilities(void)
        if (strcmp(if_info->name, if_name) == 0) {
          /*
           * It's in the list.
-          * Get the list of link-layer types for it.
+          * Get the interface capabilities for it.
           */
 #ifdef HAVE_PCAP_REMOTE
-          if (iftype == CAPTURE_IFLOCAL)
-            /* Not able to get link-layer for remote interfaces */
-#endif
-#ifdef HAVE_PCAP_CREATE
-          monitor_mode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(monitor_cb));
-#else
-          monitor_mode = FALSE;
+          if (iftype == CAPTURE_IFREMOTE) {
+            /* Not able to get interface capabilities for remote interfaces */
+            caps = NULL;
+          } else
 #endif
-         caps = capture_get_if_capabilities(if_name, monitor_mode, NULL);
+          caps = capture_get_if_capabilities(if_name, cap_settings.monitor_mode,
+                                             NULL);
 
          /* create string of list of IP addresses of this interface */
          for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) {
@@ -428,8 +436,8 @@ set_if_capabilities(void)
         lt_menu_item = gtk_menu_item_new_with_label(linktype_menu_label);
         g_free(linktype_menu_label);
       }
-      if (data_link_info->dlt == linktype) {
-        /* Found a matching dlt, selecth this */
+      if (data_link_info->dlt == cap_settings.linktype) {
+        /* Found a matching dlt, select this */
         linktype_select = linktype_count;
       }
       gtk_menu_shell_append(GTK_MENU_SHELL(lt_menu), lt_menu_item);
@@ -451,9 +459,15 @@ set_if_capabilities(void)
   gtk_widget_set_sensitive(linktype_lb, num_supported_link_types >= 2);
   gtk_widget_set_sensitive(linktype_om, num_supported_link_types >= 2);
 
-  g_object_set_data(G_OBJECT(linktype_om), E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(linktype));
+  g_object_set_data(G_OBJECT(linktype_om), E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(cap_settings.linktype));
   global_capture_opts.linktype = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(linktype_om), E_CAP_OM_LT_VALUE_KEY));
 
+#ifdef HAVE_PCAP_CREATE
+  /* Set the monitor-mode checkbox to the appropriate value */
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(monitor_cb),
+                               cap_settings.monitor_mode);
+#endif
+
   /* Restore the menu to the last index used */
   gtk_option_menu_set_history(GTK_OPTION_MENU(linktype_om),linktype_select);
   if_ip_lb = g_object_get_data(G_OBJECT(linktype_om), E_CAP_IFACE_KEY);
@@ -486,31 +500,31 @@ static GtkWidget *time_unit_combo_box_new(guint32 value) {
     GtkWidget *unit_combo_box;
     int i;
 
-       unit_combo_box = gtk_combo_box_new_text ();
-       for(i=0;i<MAX_TIME_UNITS;i++){
-               gtk_combo_box_append_text (GTK_COMBO_BOX (unit_combo_box), time_unit_name[i]);
-       }
+    unit_combo_box = gtk_combo_box_new_text ();
+    for(i = 0; i < MAX_TIME_UNITS; i++) {
+        gtk_combo_box_append_text (GTK_COMBO_BOX (unit_combo_box), time_unit_name[i]);
+    }
     /* the selected combo_box item can't be changed, once the combo_box
        is created, so set the matching combo_box item now */
     /* days */
     if(value >= 60 * 60 * 24) {
-                gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_DAY);
+         gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_DAY);
     } else {
         /* hours */
         if(value >= 60 * 60) {
-                       gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_HOUR);
+            gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_HOUR);
         } else {
             /* minutes */
             if(value >= 60) {
-                               gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_MINUTE);
+                gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_MINUTE);
             } else {
                 /* seconds */
-                               gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_SECOND);
+                gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_SECOND);
             }
         }
     }
 
-       return unit_combo_box;
+    return unit_combo_box;
 }
 
 /* convert time value from raw to displayed (e.g. 60s -> 1min) */
@@ -1716,8 +1730,8 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
   /* g_object_set_data(G_OBJECT(linktype_om), E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(-1)); */
   g_object_set_data(G_OBJECT(linktype_om), E_CAP_IFACE_KEY, if_ip_lb);
   dl_hdr_menu=NULL;
-  if (linktype_history == NULL) {
-    linktype_history = g_hash_table_new(g_str_hash, g_str_equal);
+  if (cap_settings_history == NULL) {
+    cap_settings_history = g_hash_table_new(g_str_hash, g_str_equal);
   }
   /*
    * XXX - in some cases, this is "multiple link-layer header types", e.g.
@@ -1780,7 +1794,7 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
    * you have it, the monitor mode checkbox.  That's why we do this
    * now.
    */
-  set_if_capabilities();
+  set_if_capabilities(FALSE);
 
   /* Pcap-NG row */
   pcap_ng_cb = gtk_check_button_new_with_mnemonic("Capture packets in pcap-ng format (experimental)");
@@ -2392,7 +2406,7 @@ capture_start_cb(GtkWidget *w _U_, gpointer d _U_)
 {
   gpointer  dialog;
   gchar *if_name;
-  gint *linktype_p = NULL;
+  cap_settings_t *cap_settings_p = NULL;
 
 #ifdef HAVE_AIRPCAP
   airpcap_if_active = airpcap_if_selected;
@@ -2433,16 +2447,18 @@ capture_start_cb(GtkWidget *w _U_, gpointer d _U_)
     if_name = g_strdup(global_capture_opts.iface);
   }
 
-  if (linktype_history != NULL) {
-    linktype_p = g_hash_table_lookup(linktype_history, if_name);
-    if (linktype_p == NULL) {
-      linktype_p = g_malloc(sizeof (int));
-      g_hash_table_insert(linktype_history, if_name, linktype_p);
+  if (cap_settings_history != NULL) {
+    cap_settings_p = g_hash_table_lookup(cap_settings_history, if_name);
+    if (cap_settings_p == NULL) {
+      cap_settings_p = g_malloc(sizeof (cap_settings_t));
+      g_hash_table_insert(cap_settings_history, if_name, cap_settings_p);
     } else {
       g_free(if_name);
     }
-    *linktype_p = global_capture_opts.linktype;
+    cap_settings_p->monitor_mode = global_capture_opts.monitor_mode;
+    cap_settings_p->linktype = global_capture_opts.linktype;
   } else {
+    global_capture_opts.monitor_mode = prefs_capture_device_monitor_mode(if_name);
     global_capture_opts.linktype = capture_dev_user_linktype_find(if_name);
     g_free(if_name);
   }
@@ -2919,7 +2935,7 @@ capture_prep_destroy_cb(GtkWidget *win, gpointer user_data _U_)
 static void
 capture_prep_interface_changed_cb(GtkWidget *entry _U_, gpointer argp _U_)
 {
-  set_if_capabilities();
+  set_if_capabilities(FALSE);
 }
 
 #ifdef HAVE_PCAP_CREATE
@@ -2927,7 +2943,7 @@ capture_prep_interface_changed_cb(GtkWidget *entry _U_, gpointer argp _U_)
 static void
 capture_prep_monitor_changed_cb(GtkWidget *monitor _U_, gpointer argp _U_)
 {
-  set_if_capabilities();
+  set_if_capabilities(TRUE);
 }
 #endif
 
index 96a8e4e878241546486081fbc90f35940a598fa4..c74792c43f3ad71645bb684c45e9fe1ed3b91589 100644 (file)
@@ -71,12 +71,26 @@ void capture_start_confirmed(void);
 void
 capture_air_cb(GtkWidget *widget, gpointer data);
 
-/** Get linktype for interface
+/*
+ * We remember the capture settings for each interface when a capture
+ * is started on it; the next time we select that interface we start
+ * out with those settings.
+ *
+ * XXX - we currently only do that for monitor mode and the link-layer
+ * type; arguably we should do it for the snapshot length, and perhaps
+ * promiscuous mode.
+ */
+typedef struct {
+       gboolean        monitor_mode;
+       int             linktype;
+} cap_settings_t;
+
+/** Get capture settings for interface
  *
  * @param if_name interface name
  */
-gint
-capture_get_linktype (gchar *if_name);
+cap_settings_t
+capture_get_cap_settings (gchar *if_name);
 
 
 #ifdef HAVE_PCAP_REMOTE
index 3a72f559800abefbbd465f9ddfdd4664fc553e0a..0ea601ed94e1f5ae06b8df31252f5dbffa5e336a 100644 (file)
@@ -540,6 +540,8 @@ main_welcome_add_recent_capture_files(const char *widget_cf_name)
 static gboolean
 welcome_if_press_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data)
 {
+    cap_settings_t cap_settings;
+
     g_free(global_capture_opts.iface);
     g_free(global_capture_opts.iface_descr);
 
@@ -547,7 +549,9 @@ welcome_if_press_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data)
     global_capture_opts.iface_descr = NULL;
     /* XXX - fix this */
     /*global_capture_opts.iface_descr = get_interface_descriptive_name(global_capture_opts.iface);*/
-    global_capture_opts.linktype = capture_get_linktype (global_capture_opts.iface);
+    cap_settings = capture_get_cap_settings (global_capture_opts.iface);;
+    global_capture_opts.monitor_mode = cap_settings.monitor_mode;
+    global_capture_opts.linktype = cap_settings.linktype;
 
     /* XXX - remove this? */
     if (global_capture_opts.save_file) {
index 6debfe3ae985d5c8bb3ebc357ab38cac3a9b079c..b94e1f2088aa60bbc4da306d6273990168281d22 100644 (file)
@@ -67,6 +67,9 @@
 
 /* interface options dialog */
 static GtkWidget *cur_list, *if_dev_lb, *if_name_lb, *if_linktype_cb, *if_descr_te, *if_hide_cb;
+#ifdef HAVE_PCAP_CREATE
+static GtkWidget *if_monitor_cb;
+#endif
 static GtkTreeSelection *if_selection; /* current interface row selected */
 static int num_linktypes;
 static gboolean interfaces_info_nochange;  /* TRUE to ignore Interface Options Properties */
@@ -76,12 +79,18 @@ static void ifopts_edit_cb(GtkWidget *w, gpointer data);
 static void ifopts_edit_ok_cb(GtkWidget *w, gpointer parent_w);
 static void ifopts_edit_destroy_cb(GtkWidget *win, gpointer data);
 static void ifopts_edit_ifsel_cb(GtkTreeSelection *selection, gpointer data);
+#ifdef HAVE_PCAP_CREATE
+static void ifopts_edit_monitor_changed_cb(GtkToggleButton *tbt, gpointer udata);
+#endif
 static void ifopts_edit_linktype_changed_cb(GtkComboBox *ed, gpointer udata);
 static void ifopts_edit_descr_changed_cb(GtkEditable *ed, gpointer udata);
 static void ifopts_edit_hide_changed_cb(GtkToggleButton *tbt, gpointer udata);
 static void ifopts_options_add(GtkListStore *list_store, if_info_t *if_info);
 static void ifopts_options_free(gchar *text[]);
 static void ifopts_if_liststore_add(void);
+#ifdef HAVE_PCAP_CREATE
+static void ifopts_write_new_monitor_mode(void);
+#endif
 static void ifopts_write_new_linklayer(void);
 static void ifopts_write_new_descr(void);
 static void ifopts_write_new_hide(void);
@@ -273,6 +282,9 @@ enum
 {
        DEVICE_COLUMN,
        DESC_COLUMN,
+#ifdef HAVE_PCAP_CREATE
+       DEF_MONITOR_MODE_COLUMN,
+#endif
        DEF_LINK_LAYER_COLUMN,
        COMMENT_COLUMN,
        HIDE_COLUMN,
@@ -285,7 +297,11 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
 {
        GtkWidget         *ifopts_edit_dlg, *cur_scr_win, *main_hb, *main_tb,
                          *cur_opts_fr, *ed_opts_fr, *main_vb,
-                         *if_linktype_lb, *if_descr_lb, *if_hide_lb,
+                         *if_linktype_lb, *if_descr_lb,
+#ifdef HAVE_PCAP_CREATE
+                         *if_monitor_lb,
+#endif
+                         *if_hide_lb,
                          *bbox, *ok_bt, *cancel_bt, *help_bt;
 
        GtkListStore      *list_store;
@@ -311,7 +327,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
 
        /* create a new dialog */
        ifopts_edit_dlg = dlg_conf_window_new("Wireshark: Preferences: Interface Options");
-       gtk_window_set_default_size(GTK_WINDOW(ifopts_edit_dlg), DEF_WIDTH, 440);
+       gtk_window_set_default_size(GTK_WINDOW(ifopts_edit_dlg), 1000, 440);
 
        main_vb = gtk_vbox_new(FALSE, 1);
        gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
@@ -335,6 +351,9 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
        list_store = gtk_list_store_new(N_COLUMN,       /* Total number of columns XXX  */
                                        G_TYPE_STRING,  /* Device                       */
                                        G_TYPE_STRING,  /* Description                  */
+#ifdef HAVE_PCAP_CREATE
+                                       G_TYPE_BOOLEAN, /* Monitor mode         */
+#endif
                                        G_TYPE_STRING,  /* Default link-layer           */
                                        G_TYPE_STRING,  /* Comment                      */
                                        G_TYPE_BOOLEAN, /* Hide?                        */
@@ -366,6 +385,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
        /* Add the column to the view. */
        gtk_tree_view_append_column (list_view, column);
 
+       renderer = gtk_cell_renderer_text_new ();
        column = gtk_tree_view_column_new_with_attributes ("Description", renderer, 
                                                           "text", DESC_COLUMN, 
                                                           NULL);
@@ -376,6 +396,22 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
        /* Add the column to the view. */
        gtk_tree_view_append_column (list_view, column);
 
+#ifdef HAVE_PCAP_CREATE
+       /*
+        * XXX - for some reason, this doesn't show up.
+        */
+       renderer = gtk_cell_renderer_toggle_new ();
+       column = gtk_tree_view_column_new_with_attributes ("Default to monitor mode", renderer, 
+                                                          "active", DEF_MONITOR_MODE_COLUMN,
+                                                          NULL);
+
+       gtk_tree_view_column_set_resizable(column, FALSE);
+       gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+       /* Add the column to the view. */
+       gtk_tree_view_append_column (list_view, column);
+#endif
+
+       renderer = gtk_cell_renderer_text_new ();
        column = gtk_tree_view_column_new_with_attributes ("Default link-layer", renderer, 
                                                           "text", DEF_LINK_LAYER_COLUMN, 
                                                           NULL);
@@ -386,6 +422,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
        /* Add the column to the view. */
        gtk_tree_view_append_column (list_view, column);
 
+       renderer = gtk_cell_renderer_text_new ();
        column = gtk_tree_view_column_new_with_attributes ("Comment", renderer, 
                                                           "text", COMMENT_COLUMN, 
                                                           NULL);
@@ -408,6 +445,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
 
 #if 0
        /* Don't show the DLT column */
+       renderer = gtk_cell_renderer_text_new ();
        column = gtk_tree_view_column_new_with_attributes ("DLT", renderer, 
                                                           "text", DLT_COLUMN, 
                                                           NULL);
@@ -475,6 +513,21 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
        gtk_widget_show(if_name_lb);
        row++;
 
+#ifdef HAVE_PCAP_CREATE
+       /* create "monitor mode" label and button */
+       if_monitor_lb = gtk_label_new("Monitor mode:");
+       gtk_table_attach_defaults(GTK_TABLE(main_tb), if_monitor_lb, 0, 1, row, row+1);
+       gtk_misc_set_alignment(GTK_MISC(if_monitor_lb), 1.0f, 0.5f);
+       gtk_widget_show(if_monitor_lb);
+
+       if_monitor_cb = gtk_check_button_new();
+       g_signal_connect(if_monitor_cb, "toggled", G_CALLBACK(ifopts_edit_monitor_changed_cb),
+                       cur_list);
+       gtk_table_attach_defaults(GTK_TABLE(main_tb), if_monitor_cb, 1, 2, row, row+1);
+       gtk_widget_show(if_monitor_cb);
+        row++;
+#endif
+
        if_linktype_lb = gtk_label_new("Default link-layer header type:");
        gtk_table_attach_defaults(GTK_TABLE(main_tb), if_linktype_lb, 0, 1, row, row+1);
        gtk_misc_set_alignment(GTK_MISC(if_linktype_lb), 1.0f, 0.5f);
@@ -561,6 +614,11 @@ static void
 ifopts_edit_ok_cb(GtkWidget *w _U_, gpointer parent_w)
 {
        if (if_selection){ /* XXX: Cannot be NULL ?? */
+#ifdef HAVE_PCAP_CREATE
+               /* create/write new monitor-mode interfaces string */
+               ifopts_write_new_monitor_mode();
+#endif
+
                /* create/write new interfaces link-layer string */
                ifopts_write_new_linklayer();
 
@@ -596,12 +654,13 @@ ifopts_edit_destroy_cb(GtkWidget *win, gpointer data _U_)
 }
 
 static gint
-ifopts_description_to_val (const char *if_name, const char *descr) 
+ifopts_description_to_val (const char *if_name, gboolean monitor_mode,
+    const char *descr) 
 {
        if_capabilities_t *caps;
        int dlt = -1;
 
-       caps = capture_get_if_capabilities(if_name, FALSE, NULL);
+       caps = capture_get_if_capabilities(if_name, monitor_mode, NULL);
        if (caps != NULL) {
                if (caps->data_link_types != NULL) {
                        GList  *lt_entry;
@@ -639,8 +698,11 @@ ifopts_edit_ifsel_cb(GtkTreeSelection      *selection _U_,
        GtkTreeModel       *model;
        gchar              *desc, *comment, *text;
        gchar              *if_name, *linktype;
+#ifdef HAVE_PCAP_CREATE
+       gboolean            monitor_mode;
+#endif
        gboolean            hide;
-       if_capabilities_t *caps;
+       if_capabilities_t  *caps;
        gint                selected = 0;
 
        /* Get list_store data for currently selected interface */
@@ -648,11 +710,14 @@ ifopts_edit_ifsel_cb(GtkTreeSelection     *selection _U_,
                return;
        }
        gtk_tree_model_get(model, &iter, 
-                          DEVICE_COLUMN,  &if_name,
-                          DESC_COLUMN,    &desc,
-                          DEF_LINK_LAYER_COLUMN, &linktype,
-                          COMMENT_COLUMN, &comment,
-                          HIDE_COLUMN,    &hide,
+                          DEVICE_COLUMN,             &if_name,
+                          DESC_COLUMN,               &desc,
+#ifdef HAVE_PCAP_CREATE
+                          DEF_MONITOR_MODE_COLUMN,   &monitor_mode,
+#endif
+                          DEF_LINK_LAYER_COLUMN,     &linktype,
+                          COMMENT_COLUMN,            &comment,
+                          HIDE_COLUMN,               &hide,
                           -1);
 
        /* display  the interface device from current interfaces selection */
@@ -671,9 +736,20 @@ ifopts_edit_ifsel_cb(GtkTreeSelection      *selection _U_,
                gtk_combo_box_remove_text (GTK_COMBO_BOX(if_linktype_cb), num_linktypes);
        }
 
-        /*  -- build and add to the ComboBox a linktype list for the current interfaces selection */
+        /*
+        * -- set the sensitivity of the monitor-mode checkbox, and
+        * build and add to the ComboBox a linktype list for the current
+        * interfaces selection, based on the interface capabilities
+        */
+#ifdef HAVE_PCAP_CREATE
+       caps = capture_get_if_capabilities(if_name, monitor_mode, NULL);
+#else
        caps = capture_get_if_capabilities(if_name, FALSE, NULL);
+#endif
        if (caps != NULL) {
+#ifdef HAVE_PCAP_CREATE
+               gtk_widget_set_sensitive(if_monitor_cb, caps->can_set_rfmon);
+#endif
                if (caps->data_link_types != NULL) {
                        GList *lt_entry;
                        for (lt_entry = caps->data_link_types; lt_entry != NULL;
@@ -691,6 +767,10 @@ ifopts_edit_ifsel_cb(GtkTreeSelection      *selection _U_,
                }
                free_if_capabilities(caps);
        }
+#ifdef HAVE_PCAP_CREATE
+       else
+               gtk_widget_set_sensitive(if_monitor_cb, FALSE);
+#endif
 
        /* display the interface description from current interfaces selection */
        gtk_entry_set_text(GTK_ENTRY(if_descr_te), comment);
@@ -709,6 +789,93 @@ ifopts_edit_ifsel_cb(GtkTreeSelection      *selection _U_,
        g_free(comment);
 }
 
+#ifdef HAVE_PCAP_CREATE
+/*
+ * Monitor-mode toggle button changed callback; update displayed widgets
+ * (the list of link-layer types might change) and list_store for currently
+ * selected interface.
+ */
+static void
+ifopts_edit_monitor_changed_cb(GtkToggleButton *tbt, gpointer udata)
+{
+       GtkTreeModel      *list_model;
+       GtkTreeIter        list_iter;
+       GtkListStore      *list_store;
+       gchar             *if_name, *text;
+       gboolean           monitor_mode;
+       if_capabilities_t *caps;
+
+       if (interfaces_info_nochange)
+               return;
+
+       if (if_selection == NULL) /* XXX: Cannot be NULL ?? */
+               return;
+
+       if (!gtk_tree_selection_get_selected (if_selection, &list_model, &list_iter)){
+               return;
+       }
+       gtk_tree_model_get(list_model, &list_iter, 
+                          DEVICE_COLUMN,  &if_name,
+                          -1);
+
+       /* Ignore "changed" callbacks while we update the Properties widgets */
+       interfaces_info_nochange = TRUE;
+
+       /* display the link-layer header type from current interfaces selection */
+        /*  -- remove old linktype list (if any) from the ComboBox */
+       while (num_linktypes > 0) {
+               num_linktypes--;
+               gtk_combo_box_remove_text (GTK_COMBO_BOX(if_linktype_cb), num_linktypes);
+       }
+
+       list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (udata))); /* Get store */
+
+#ifdef HAVE_PCAP_CREATE
+       /* get "monitor mode" button state and set status in list_store for currently selected interface */
+       monitor_mode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tbt));
+       gtk_list_store_set  (list_store, &list_iter,
+                            DEF_MONITOR_MODE_COLUMN, monitor_mode,
+                            -1);
+       caps = capture_get_if_capabilities(if_name, monitor_mode, NULL);
+#else
+       /* no monitor-mode support */
+       caps = capture_get_if_capabilities(if_name, FALSE, NULL);
+#endif
+
+        /*
+        * -- set the sensitivity of the monitor-mode checkbox, and
+        * build and add to the ComboBox a linktype list for the current
+        * interfaces selection, based on the interface capabilities
+        */
+       if (caps != NULL) {
+#ifdef HAVE_PCAP_CREATE
+               gtk_widget_set_sensitive(if_monitor_cb, caps->can_set_rfmon);
+#endif
+               if (caps->data_link_types != NULL) {
+                       GList *lt_entry;
+                       for (lt_entry = caps->data_link_types; lt_entry != NULL;
+                           lt_entry = g_list_next(lt_entry)) {
+                               data_link_info_t *dli_p = lt_entry->data;
+                               text = (dli_p->description != NULL) ? dli_p->description : dli_p->name;
+                               gtk_combo_box_append_text(GTK_COMBO_BOX(if_linktype_cb), text);
+                               num_linktypes++;
+                       }
+                       gtk_widget_set_sensitive(if_linktype_cb, num_linktypes >= 2);
+                       gtk_combo_box_set_active(GTK_COMBO_BOX(if_linktype_cb), 0);
+               }
+               free_if_capabilities(caps);
+       }
+#ifdef HAVE_PCAP_CREATE
+       else
+               gtk_widget_set_sensitive(if_monitor_cb, FALSE);
+#endif
+
+       interfaces_info_nochange = FALSE;
+
+       g_free(if_name);
+}
+#endif
+
 /*
  * Link-layer entry changed callback; update list_store for currently selected interface.
  */
@@ -716,6 +883,9 @@ static void
 ifopts_edit_linktype_changed_cb(GtkComboBox *cb, gpointer udata)
 {
        gchar        *ifnm, *text;
+#ifdef HAVE_PCAP_CREATE
+       gboolean      monitor_mode;
+#endif
        gint          linktype;
        GtkTreeModel *list_model;
 #if ! GTK_CHECK_VERSION(2,6,0)
@@ -736,7 +906,10 @@ ifopts_edit_linktype_changed_cb(GtkComboBox *cb, gpointer udata)
        }
        
        gtk_tree_model_get(list_model, &list_iter, 
-               DEVICE_COLUMN, &ifnm,
+               DEVICE_COLUMN,           &ifnm,
+#ifdef HAVE_PCAP_CREATE
+               DEF_MONITOR_MODE_COLUMN, &monitor_mode,
+#endif
                -1);
 
        /* get current description text and set value in list_store for currently selected interface */
@@ -748,7 +921,11 @@ ifopts_edit_linktype_changed_cb(GtkComboBox *cb, gpointer udata)
                model = gtk_combo_box_get_model(GTK_COMBO_BOX(cb));
                gtk_tree_model_get(model, &iter, 0, &text, -1);
 #endif
-               linktype = ifopts_description_to_val(ifnm, text);
+#ifdef HAVE_PCAP_CREATE
+               linktype = ifopts_description_to_val(ifnm, monitor_mode, text);
+#else
+               linktype = ifopts_description_to_val(ifnm, FALSE, text);
+#endif
                list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (udata))); /* Get store */
                gtk_list_store_set  (list_store, &list_iter,
                                     DEF_LINK_LAYER_COLUMN, text,
@@ -842,6 +1019,9 @@ ifopts_options_add(GtkListStore *list_store, if_info_t *if_info)
        gchar   *pr_descr;
        gchar   *text[] = { NULL, NULL, NULL, NULL };
        if_capabilities_t *caps;
+#ifdef HAVE_PCAP_CREATE
+       gboolean monitor_mode;
+#endif
        gint     linktype;
        gboolean hide;
        GtkTreeIter  iter;
@@ -855,9 +1035,17 @@ ifopts_options_add(GtkListStore *list_store, if_info_t *if_info)
        else
                text[1] = g_strdup("");
 
+#ifdef HAVE_PCAP_CREATE
+       /* get default monitor mode setting */
+       monitor_mode = prefs_capture_device_monitor_mode(if_info->name);
+       caps = capture_get_if_capabilities(if_info->name, monitor_mode, NULL);
+#else
+       /* no monitor-mode support */
+       caps = capture_get_if_capabilities(if_info->name, FALSE, NULL);
+#endif
+
        /* set default link-layer header type */
        linktype = capture_dev_user_linktype_find(if_info->name);
-       caps = capture_get_if_capabilities(if_info->name, FALSE, NULL);
        if (caps != NULL) {
                if (caps->data_link_types != NULL) {
                        GList  *lt_entry;
@@ -930,11 +1118,7 @@ ifopts_options_add(GtkListStore *list_store, if_info_t *if_info)
                text[3] = g_strdup("");
 
        /* check if interface is "hidden" */
-       if ((prefs.capture_devices_hide != NULL) &&
-           (strstr(prefs.capture_devices_hide, if_info->name) != NULL))
-               hide = TRUE;
-       else
-               hide = FALSE;
+       hide = prefs_is_capture_device_hidden(if_info->name);
 
        /* add row to ListStore */
 
@@ -944,12 +1128,15 @@ ifopts_options_add(GtkListStore *list_store, if_info_t *if_info)
        gtk_list_store_append  (list_store, &iter);
        gtk_list_store_set  (list_store, &iter,
 #endif
-                            DEVICE_COLUMN,  text[0],
-                            DESC_COLUMN,    text[1],
-                            DEF_LINK_LAYER_COLUMN, text[2],
-                            COMMENT_COLUMN, text[3],
-                            HIDE_COLUMN,    hide,
-                            DLT_COLUMN,     linktype,
+                            DEVICE_COLUMN,           text[0],
+                            DESC_COLUMN,             text[1],
+#ifdef HAVE_PCAP_CREATE
+                            DEF_MONITOR_MODE_COLUMN, monitor_mode,
+#endif
+                            DEF_LINK_LAYER_COLUMN,   text[2],
+                            COMMENT_COLUMN,          text[3],
+                            HIDE_COLUMN,             hide,
+                            DLT_COLUMN,              linktype,
                             -1);
 
        ifopts_options_free(text);
@@ -1000,6 +1187,69 @@ ifopts_if_liststore_add(void)
        free_interface_list(if_list);
 }
 
+#ifdef HAVE_PCAP_CREATE
+/*
+ * Create/write new "monitor mode" interfaces string based on current CList.
+ * Put it into the preferences value.
+ */
+static void
+ifopts_write_new_monitor_mode(void)
+{
+       GtkListStore    *store;
+       GtkTreeIter      iter;
+       GtkTreeModel    *model;
+       gboolean         more_items = TRUE;
+       gint             first_if = TRUE;       /* flag to check if first in list */
+       gchar           *ifnm;
+       gboolean         monitor_mode;
+       gchar           *new_monitor_mode;
+
+       /* new preferences "monitor mode" interfaces string */
+       new_monitor_mode = g_malloc0(MAX_VAL_LEN);
+
+       /* get "monitor mode" flag text for each row (interface) */
+       model = gtk_tree_view_get_model(GTK_TREE_VIEW(cur_list));
+       store = GTK_LIST_STORE(model);
+       if( gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter) ) {
+               while (more_items) {
+                       gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
+                                          DEVICE_COLUMN,           &ifnm,
+                                          DEF_MONITOR_MODE_COLUMN, &monitor_mode,
+                                          -1);
+
+                       /* if flag text is "No", skip this interface */
+                       if (!monitor_mode){
+                               more_items = gtk_tree_model_iter_next (model,&iter);
+                               continue;
+                       }
+
+                       /*
+                        * create/cat interface to new string
+                        */
+                       if (first_if != TRUE)
+                               g_strlcat (new_monitor_mode, ",", MAX_VAL_LEN);
+                       g_strlcat (new_monitor_mode, ifnm, MAX_VAL_LEN);
+
+                       /* set first-in-list flag to false */
+                       first_if = FALSE;
+                       more_items = gtk_tree_model_iter_next (model,&iter);
+               }
+
+               /* write new "hidden" string to preferences */
+               if (strlen(new_monitor_mode) > 0) {
+                       g_free(prefs.capture_devices_monitor_mode);
+                       prefs.capture_devices_monitor_mode = new_monitor_mode;
+               }
+               /* no "hidden" interfaces */
+               else {
+                       g_free(prefs.capture_devices_monitor_mode);
+                       g_free(new_monitor_mode);
+                       prefs.capture_devices_monitor_mode = NULL;
+               }
+       }
+}
+#endif
+
 /*
  * Create/write new interfaces link-layer string based on current CList.
  * Put it into the preferences value.