nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* capture_opts.c |
2 | * Routines for capture options setting |
||
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 | #include <stdio.h> |
||
26 | #include <stdlib.h> |
||
27 | |||
28 | #ifdef HAVE_LIBPCAP |
||
29 | |||
30 | #include <string.h> |
||
31 | |||
32 | #include <errno.h> |
||
33 | |||
34 | #include <glib.h> |
||
35 | |||
36 | #include "capture_opts.h" |
||
37 | #include "ringbuffer.h" |
||
38 | |||
39 | #include <wsutil/clopts_common.h> |
||
40 | #include <wsutil/cmdarg_err.h> |
||
41 | #include <wsutil/file_util.h> |
||
42 | |||
43 | #include "caputils/capture_ifinfo.h" |
||
44 | #include "caputils/capture-pcap-util.h" |
||
45 | |||
46 | #include "filter_files.h" |
||
47 | |||
48 | static gboolean capture_opts_output_to_pipe(const char *save_file, gboolean *is_pipe); |
||
49 | |||
50 | |||
51 | void |
||
52 | capture_opts_init(capture_options *capture_opts) |
||
53 | { |
||
54 | capture_opts->ifaces = g_array_new(FALSE, FALSE, sizeof(interface_options)); |
||
55 | capture_opts->all_ifaces = g_array_new(FALSE, FALSE, sizeof(interface_t)); |
||
56 | capture_opts->num_selected = 0; |
||
57 | capture_opts->default_options.name = NULL; |
||
58 | capture_opts->default_options.descr = NULL; |
||
59 | capture_opts->default_options.cfilter = NULL; |
||
60 | capture_opts->default_options.has_snaplen = FALSE; |
||
61 | capture_opts->default_options.snaplen = WTAP_MAX_PACKET_SIZE; |
||
62 | capture_opts->default_options.linktype = -1; /* use interface default */ |
||
63 | capture_opts->default_options.promisc_mode = TRUE; |
||
64 | capture_opts->default_options.if_type = IF_WIRED; |
||
65 | #ifdef HAVE_EXTCAP |
||
66 | capture_opts->default_options.extcap = NULL; |
||
67 | capture_opts->default_options.extcap_fifo = NULL; |
||
68 | capture_opts->default_options.extcap_args = NULL; |
||
69 | capture_opts->default_options.extcap_userdata = NULL; |
||
70 | capture_opts->default_options.extcap_pid = INVALID_EXTCAP_PID; |
||
71 | #endif |
||
72 | #ifdef CAN_SET_CAPTURE_BUFFER_SIZE |
||
73 | capture_opts->default_options.buffer_size = DEFAULT_CAPTURE_BUFFER_SIZE; |
||
74 | #endif |
||
75 | capture_opts->default_options.monitor_mode = FALSE; |
||
76 | #ifdef HAVE_PCAP_REMOTE |
||
77 | capture_opts->default_options.src_type = CAPTURE_IFLOCAL; |
||
78 | capture_opts->default_options.remote_host = NULL; |
||
79 | capture_opts->default_options.remote_port = NULL; |
||
80 | capture_opts->default_options.auth_type = CAPTURE_AUTH_NULL; |
||
81 | capture_opts->default_options.auth_username = NULL; |
||
82 | capture_opts->default_options.auth_password = NULL; |
||
83 | capture_opts->default_options.datatx_udp = FALSE; |
||
84 | capture_opts->default_options.nocap_rpcap = TRUE; |
||
85 | capture_opts->default_options.nocap_local = FALSE; |
||
86 | #endif |
||
87 | #ifdef HAVE_PCAP_SETSAMPLING |
||
88 | capture_opts->default_options.sampling_method = CAPTURE_SAMP_NONE; |
||
89 | capture_opts->default_options.sampling_param = 0; |
||
90 | #endif |
||
91 | capture_opts->saving_to_file = FALSE; |
||
92 | capture_opts->save_file = NULL; |
||
93 | capture_opts->group_read_access = FALSE; |
||
94 | #ifdef PCAP_NG_DEFAULT |
||
95 | capture_opts->use_pcapng = TRUE; /* Save as pcap-ng by default */ |
||
96 | #else |
||
97 | capture_opts->use_pcapng = FALSE; /* Save as pcap by default */ |
||
98 | #endif |
||
99 | capture_opts->real_time_mode = TRUE; |
||
100 | capture_opts->show_info = TRUE; |
||
101 | capture_opts->restart = FALSE; |
||
102 | capture_opts->orig_save_file = NULL; |
||
103 | |||
104 | capture_opts->multi_files_on = FALSE; |
||
105 | capture_opts->has_file_duration = FALSE; |
||
106 | capture_opts->file_duration = 60; /* 1 min */ |
||
107 | capture_opts->has_ring_num_files = FALSE; |
||
108 | capture_opts->ring_num_files = RINGBUFFER_MIN_NUM_FILES; |
||
109 | |||
110 | capture_opts->has_autostop_files = FALSE; |
||
111 | capture_opts->autostop_files = 1; |
||
112 | capture_opts->has_autostop_packets = FALSE; |
||
113 | capture_opts->autostop_packets = 0; |
||
114 | capture_opts->has_autostop_filesize = FALSE; |
||
115 | capture_opts->autostop_filesize = 1000; /* 1 MB */ |
||
116 | capture_opts->has_autostop_duration = FALSE; |
||
117 | capture_opts->autostop_duration = 60; /* 1 min */ |
||
118 | capture_opts->capture_comment = NULL; |
||
119 | |||
120 | capture_opts->output_to_pipe = FALSE; |
||
121 | capture_opts->capture_child = FALSE; |
||
122 | } |
||
123 | |||
124 | |||
125 | /* log content of capture_opts */ |
||
126 | void |
||
127 | capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_options *capture_opts) { |
||
128 | guint i; |
||
129 | |||
130 | g_log(log_domain, log_level, "CAPTURE OPTIONS :"); |
||
131 | |||
132 | for (i = 0; i < capture_opts->ifaces->len; i++) { |
||
133 | interface_options interface_opts; |
||
134 | |||
135 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, i); |
||
136 | g_log(log_domain, log_level, "Interface name[%02d] : %s", i, interface_opts.name ? interface_opts.name : "(unspecified)"); |
||
137 | g_log(log_domain, log_level, "Interface description[%02d] : %s", i, interface_opts.descr ? interface_opts.descr : "(unspecified)"); |
||
138 | g_log(log_domain, log_level, "Console display name[%02d]: %s", i, interface_opts.console_display_name ? interface_opts.console_display_name : "(unspecified)"); |
||
139 | g_log(log_domain, log_level, "Capture filter[%02d] : %s", i, interface_opts.cfilter ? interface_opts.cfilter : "(unspecified)"); |
||
140 | g_log(log_domain, log_level, "Snap length[%02d] (%u) : %d", i, interface_opts.has_snaplen, interface_opts.snaplen); |
||
141 | g_log(log_domain, log_level, "Link Type[%02d] : %d", i, interface_opts.linktype); |
||
142 | g_log(log_domain, log_level, "Promiscuous Mode[%02d]: %s", i, interface_opts.promisc_mode?"TRUE":"FALSE"); |
||
143 | #ifdef HAVE_EXTCAP |
||
144 | g_log(log_domain, log_level, "Extcap[%02d] : %s", i, interface_opts.extcap ? interface_opts.extcap : "(unspecified)"); |
||
145 | g_log(log_domain, log_level, "Extcap FIFO[%02d] : %s", i, interface_opts.extcap_fifo ? interface_opts.extcap_fifo : "(unspecified)"); |
||
146 | g_log(log_domain, log_level, "Extcap PID[%02d] : %d", i, interface_opts.extcap_pid); |
||
147 | #endif |
||
148 | #ifdef CAN_SET_CAPTURE_BUFFER_SIZE |
||
149 | g_log(log_domain, log_level, "Buffer size[%02d] : %d (MB)", i, interface_opts.buffer_size); |
||
150 | #endif |
||
151 | g_log(log_domain, log_level, "Monitor Mode[%02d] : %s", i, interface_opts.monitor_mode?"TRUE":"FALSE"); |
||
152 | #ifdef HAVE_PCAP_REMOTE |
||
153 | g_log(log_domain, log_level, "Capture source[%02d] : %s", i, |
||
154 | interface_opts.src_type == CAPTURE_IFLOCAL ? "Local interface" : |
||
155 | interface_opts.src_type == CAPTURE_IFREMOTE ? "Remote interface" : |
||
156 | "Unknown"); |
||
157 | if (interface_opts.src_type == CAPTURE_IFREMOTE) { |
||
158 | g_log(log_domain, log_level, "Remote host[%02d] : %s", i, interface_opts.remote_host ? interface_opts.remote_host : "(unspecified)"); |
||
159 | g_log(log_domain, log_level, "Remote port[%02d] : %s", i, interface_opts.remote_port ? interface_opts.remote_port : "(unspecified)"); |
||
160 | } |
||
161 | g_log(log_domain, log_level, "Authentication[%02d] : %s", i, |
||
162 | interface_opts.auth_type == CAPTURE_AUTH_NULL ? "Null" : |
||
163 | interface_opts.auth_type == CAPTURE_AUTH_PWD ? "By username/password" : |
||
164 | "Unknown"); |
||
165 | if (interface_opts.auth_type == CAPTURE_AUTH_PWD) { |
||
166 | g_log(log_domain, log_level, "Auth username[%02d] : %s", i, interface_opts.auth_username ? interface_opts.auth_username : "(unspecified)"); |
||
167 | g_log(log_domain, log_level, "Auth password[%02d] : <hidden>", i); |
||
168 | } |
||
169 | g_log(log_domain, log_level, "UDP data tfer[%02d] : %u", i, interface_opts.datatx_udp); |
||
170 | g_log(log_domain, log_level, "No cap. RPCAP[%02d] : %u", i, interface_opts.nocap_rpcap); |
||
171 | g_log(log_domain, log_level, "No cap. local[%02d] : %u", i, interface_opts.nocap_local); |
||
172 | #endif |
||
173 | #ifdef HAVE_PCAP_SETSAMPLING |
||
174 | g_log(log_domain, log_level, "Sampling meth.[%02d] : %d", i, interface_opts.sampling_method); |
||
175 | g_log(log_domain, log_level, "Sampling param.[%02d] : %d", i, interface_opts.sampling_param); |
||
176 | #endif |
||
177 | } |
||
178 | g_log(log_domain, log_level, "Interface name[df] : %s", capture_opts->default_options.name ? capture_opts->default_options.name : "(unspecified)"); |
||
179 | g_log(log_domain, log_level, "Interface Descr[df] : %s", capture_opts->default_options.descr ? capture_opts->default_options.descr : "(unspecified)"); |
||
180 | g_log(log_domain, log_level, "Capture filter[df] : %s", capture_opts->default_options.cfilter ? capture_opts->default_options.cfilter : "(unspecified)"); |
||
181 | g_log(log_domain, log_level, "Snap length[df] (%u) : %d", capture_opts->default_options.has_snaplen, capture_opts->default_options.snaplen); |
||
182 | g_log(log_domain, log_level, "Link Type[df] : %d", capture_opts->default_options.linktype); |
||
183 | g_log(log_domain, log_level, "Promiscuous Mode[df]: %s", capture_opts->default_options.promisc_mode?"TRUE":"FALSE"); |
||
184 | #ifdef HAVE_EXTCAP |
||
185 | g_log(log_domain, log_level, "Extcap[df] : %s", capture_opts->default_options.extcap ? capture_opts->default_options.extcap : "(unspecified)"); |
||
186 | g_log(log_domain, log_level, "Extcap FIFO[df] : %s", capture_opts->default_options.extcap_fifo ? capture_opts->default_options.extcap_fifo : "(unspecified)"); |
||
187 | #endif |
||
188 | #ifdef CAN_SET_CAPTURE_BUFFER_SIZE |
||
189 | g_log(log_domain, log_level, "Buffer size[df] : %d (MB)", capture_opts->default_options.buffer_size); |
||
190 | #endif |
||
191 | g_log(log_domain, log_level, "Monitor Mode[df] : %s", capture_opts->default_options.monitor_mode?"TRUE":"FALSE"); |
||
192 | #ifdef HAVE_PCAP_REMOTE |
||
193 | g_log(log_domain, log_level, "Capture source[df] : %s", |
||
194 | capture_opts->default_options.src_type == CAPTURE_IFLOCAL ? "Local interface" : |
||
195 | capture_opts->default_options.src_type == CAPTURE_IFREMOTE ? "Remote interface" : |
||
196 | "Unknown"); |
||
197 | if (capture_opts->default_options.src_type == CAPTURE_IFREMOTE) { |
||
198 | g_log(log_domain, log_level, "Remote host[df] : %s", capture_opts->default_options.remote_host ? capture_opts->default_options.remote_host : "(unspecified)"); |
||
199 | g_log(log_domain, log_level, "Remote port[df] : %s", capture_opts->default_options.remote_port ? capture_opts->default_options.remote_port : "(unspecified)"); |
||
200 | } |
||
201 | g_log(log_domain, log_level, "Authentication[df] : %s", |
||
202 | capture_opts->default_options.auth_type == CAPTURE_AUTH_NULL ? "Null" : |
||
203 | capture_opts->default_options.auth_type == CAPTURE_AUTH_PWD ? "By username/password" : |
||
204 | "Unknown"); |
||
205 | if (capture_opts->default_options.auth_type == CAPTURE_AUTH_PWD) { |
||
206 | g_log(log_domain, log_level, "Auth username[df] : %s", capture_opts->default_options.auth_username ? capture_opts->default_options.auth_username : "(unspecified)"); |
||
207 | g_log(log_domain, log_level, "Auth password[df] : <hidden>"); |
||
208 | } |
||
209 | g_log(log_domain, log_level, "UDP data tfer[df] : %u", capture_opts->default_options.datatx_udp); |
||
210 | g_log(log_domain, log_level, "No cap. RPCAP[df] : %u", capture_opts->default_options.nocap_rpcap); |
||
211 | g_log(log_domain, log_level, "No cap. local[df] : %u", capture_opts->default_options.nocap_local); |
||
212 | #endif |
||
213 | #ifdef HAVE_PCAP_SETSAMPLING |
||
214 | g_log(log_domain, log_level, "Sampling meth. [df] : %d", capture_opts->default_options.sampling_method); |
||
215 | g_log(log_domain, log_level, "Sampling param.[df] : %d", capture_opts->default_options.sampling_param); |
||
216 | #endif |
||
217 | g_log(log_domain, log_level, "SavingToFile : %u", capture_opts->saving_to_file); |
||
218 | g_log(log_domain, log_level, "SaveFile : %s", (capture_opts->save_file) ? capture_opts->save_file : ""); |
||
219 | g_log(log_domain, log_level, "GroupReadAccess : %u", capture_opts->group_read_access); |
||
220 | g_log(log_domain, log_level, "Fileformat : %s", (capture_opts->use_pcapng) ? "PCAPNG" : "PCAP"); |
||
221 | g_log(log_domain, log_level, "RealTimeMode : %u", capture_opts->real_time_mode); |
||
222 | g_log(log_domain, log_level, "ShowInfo : %u", capture_opts->show_info); |
||
223 | |||
224 | g_log(log_domain, log_level, "MultiFilesOn : %u", capture_opts->multi_files_on); |
||
225 | g_log(log_domain, log_level, "FileDuration (%u) : %u", capture_opts->has_file_duration, capture_opts->file_duration); |
||
226 | g_log(log_domain, log_level, "RingNumFiles (%u) : %u", capture_opts->has_ring_num_files, capture_opts->ring_num_files); |
||
227 | |||
228 | g_log(log_domain, log_level, "AutostopFiles (%u) : %u", capture_opts->has_autostop_files, capture_opts->autostop_files); |
||
229 | g_log(log_domain, log_level, "AutostopPackets (%u) : %u", capture_opts->has_autostop_packets, capture_opts->autostop_packets); |
||
230 | g_log(log_domain, log_level, "AutostopFilesize(%u) : %u (KB)", capture_opts->has_autostop_filesize, capture_opts->autostop_filesize); |
||
231 | g_log(log_domain, log_level, "AutostopDuration(%u) : %u", capture_opts->has_autostop_duration, capture_opts->autostop_duration); |
||
232 | } |
||
233 | |||
234 | /* |
||
235 | * Given a string of the form "<autostop criterion>:<value>", as might appear |
||
236 | * as an argument to a "-a" option, parse it and set the criterion in |
||
237 | * question. Return an indication of whether it succeeded or failed |
||
238 | * in some fashion. |
||
239 | */ |
||
240 | static gboolean |
||
241 | set_autostop_criterion(capture_options *capture_opts, const char *autostoparg) |
||
242 | { |
||
243 | gchar *p, *colonp; |
||
244 | |||
245 | colonp = strchr(autostoparg, ':'); |
||
246 | if (colonp == NULL) |
||
247 | return FALSE; |
||
248 | |||
249 | p = colonp; |
||
250 | *p++ = '\0'; |
||
251 | |||
252 | /* |
||
253 | * Skip over any white space (there probably won't be any, but |
||
254 | * as we allow it in the preferences file, we might as well |
||
255 | * allow it here). |
||
256 | */ |
||
257 | while (g_ascii_isspace(*p)) |
||
258 | p++; |
||
259 | if (*p == '\0') { |
||
260 | /* |
||
261 | * Put the colon back, so if our caller uses, in an |
||
262 | * error message, the string they passed us, the message |
||
263 | * looks correct. |
||
264 | */ |
||
265 | *colonp = ':'; |
||
266 | return FALSE; |
||
267 | } |
||
268 | if (strcmp(autostoparg,"duration") == 0) { |
||
269 | capture_opts->has_autostop_duration = TRUE; |
||
270 | capture_opts->autostop_duration = get_positive_int(p,"autostop duration"); |
||
271 | } else if (strcmp(autostoparg,"filesize") == 0) { |
||
272 | capture_opts->has_autostop_filesize = TRUE; |
||
273 | capture_opts->autostop_filesize = get_positive_int(p,"autostop filesize"); |
||
274 | } else if (strcmp(autostoparg,"files") == 0) { |
||
275 | capture_opts->multi_files_on = TRUE; |
||
276 | capture_opts->has_autostop_files = TRUE; |
||
277 | capture_opts->autostop_files = get_positive_int(p,"autostop files"); |
||
278 | } else { |
||
279 | return FALSE; |
||
280 | } |
||
281 | *colonp = ':'; /* put the colon back */ |
||
282 | return TRUE; |
||
283 | } |
||
284 | |||
285 | static gboolean get_filter_arguments(capture_options* capture_opts, const char* arg) |
||
286 | { |
||
287 | char* colonp; |
||
288 | char* val; |
||
289 | char* filter_exp = NULL; |
||
290 | |||
291 | colonp = strchr(arg, ':'); |
||
292 | if (colonp) { |
||
293 | val = colonp; |
||
294 | *val = '\0'; |
||
295 | val++; |
||
296 | if (strcmp(arg, "predef") == 0) { |
||
297 | GList* filterItem; |
||
298 | |||
299 | filterItem = get_filter_list_first(CFILTER_LIST); |
||
300 | while (filterItem != NULL) { |
||
301 | filter_def *filterDef; |
||
302 | |||
303 | filterDef = (filter_def*)filterItem->data; |
||
304 | if (strcmp(val, filterDef->name) == 0) { |
||
305 | filter_exp = g_strdup(filterDef->strval); |
||
306 | break; |
||
307 | } |
||
308 | filterItem = filterItem->next; |
||
309 | } |
||
310 | } |
||
311 | } |
||
312 | |||
313 | if (filter_exp == NULL) { |
||
314 | /* No filter expression found yet; fallback to previous implemention |
||
315 | and assume the arg contains a filter expression */ |
||
316 | if (colonp) { |
||
317 | *colonp = ':'; /* restore colon */ |
||
318 | } |
||
319 | filter_exp = g_strdup(arg); |
||
320 | } |
||
321 | |||
322 | if (capture_opts->ifaces->len > 0) { |
||
323 | interface_options interface_opts; |
||
324 | |||
325 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, capture_opts->ifaces->len - 1); |
||
326 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, capture_opts->ifaces->len - 1); |
||
327 | g_free(interface_opts.cfilter); |
||
328 | interface_opts.cfilter = filter_exp; |
||
329 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
330 | return TRUE; |
||
331 | } |
||
332 | else { |
||
333 | g_free(capture_opts->default_options.cfilter); |
||
334 | capture_opts->default_options.cfilter = filter_exp; |
||
335 | return TRUE; |
||
336 | } |
||
337 | } |
||
338 | |||
339 | /* |
||
340 | * Given a string of the form "<ring buffer file>:<duration>", as might appear |
||
341 | * as an argument to a "-b" option, parse it and set the arguments in |
||
342 | * question. Return an indication of whether it succeeded or failed |
||
343 | * in some fashion. |
||
344 | */ |
||
345 | static gboolean |
||
346 | get_ring_arguments(capture_options *capture_opts, const char *arg) |
||
347 | { |
||
348 | gchar *p = NULL, *colonp; |
||
349 | |||
350 | colonp = strchr(arg, ':'); |
||
351 | if (colonp == NULL) |
||
352 | return FALSE; |
||
353 | |||
354 | p = colonp; |
||
355 | *p++ = '\0'; |
||
356 | |||
357 | /* |
||
358 | * Skip over any white space (there probably won't be any, but |
||
359 | * as we allow it in the preferences file, we might as well |
||
360 | * allow it here). |
||
361 | */ |
||
362 | while (g_ascii_isspace(*p)) |
||
363 | p++; |
||
364 | if (*p == '\0') { |
||
365 | /* |
||
366 | * Put the colon back, so if our caller uses, in an |
||
367 | * error message, the string they passed us, the message |
||
368 | * looks correct. |
||
369 | */ |
||
370 | *colonp = ':'; |
||
371 | return FALSE; |
||
372 | } |
||
373 | |||
374 | if (strcmp(arg,"files") == 0) { |
||
375 | capture_opts->has_ring_num_files = TRUE; |
||
376 | capture_opts->ring_num_files = get_positive_int(p, "number of ring buffer files"); |
||
377 | } else if (strcmp(arg,"filesize") == 0) { |
||
378 | capture_opts->has_autostop_filesize = TRUE; |
||
379 | capture_opts->autostop_filesize = get_positive_int(p, "ring buffer filesize"); |
||
380 | } else if (strcmp(arg,"duration") == 0) { |
||
381 | capture_opts->has_file_duration = TRUE; |
||
382 | capture_opts->file_duration = get_positive_int(p, "ring buffer duration"); |
||
383 | } |
||
384 | |||
385 | *colonp = ':'; /* put the colon back */ |
||
386 | return TRUE; |
||
387 | } |
||
388 | |||
389 | #ifdef HAVE_PCAP_SETSAMPLING |
||
390 | /* |
||
391 | * Given a string of the form "<sampling type>:<value>", as might appear |
||
392 | * as an argument to a "-m" option, parse it and set the arguments in |
||
393 | * question. Return an indication of whether it succeeded or failed |
||
394 | * in some fashion. |
||
395 | */ |
||
396 | static gboolean |
||
397 | get_sampling_arguments(capture_options *capture_opts, const char *arg) |
||
398 | { |
||
399 | gchar *p = NULL, *colonp; |
||
400 | |||
401 | colonp = strchr(arg, ':'); |
||
402 | if (colonp == NULL) |
||
403 | return FALSE; |
||
404 | |||
405 | p = colonp; |
||
406 | *p++ = '\0'; |
||
407 | |||
408 | while (g_ascii_isspace(*p)) |
||
409 | p++; |
||
410 | if (*p == '\0') { |
||
411 | *colonp = ':'; |
||
412 | return FALSE; |
||
413 | } |
||
414 | |||
415 | if (strcmp(arg, "count") == 0) { |
||
416 | if (capture_opts->ifaces->len > 0) { |
||
417 | interface_options interface_opts; |
||
418 | |||
419 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, capture_opts->ifaces->len - 1); |
||
420 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, capture_opts->ifaces->len - 1); |
||
421 | interface_opts.sampling_method = CAPTURE_SAMP_BY_COUNT; |
||
422 | interface_opts.sampling_param = get_positive_int(p, "sampling count"); |
||
423 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
424 | } else { |
||
425 | capture_opts->default_options.sampling_method = CAPTURE_SAMP_BY_COUNT; |
||
426 | capture_opts->default_options.sampling_param = get_positive_int(p, "sampling count"); |
||
427 | } |
||
428 | } else if (strcmp(arg, "timer") == 0) { |
||
429 | if (capture_opts->ifaces->len > 0) { |
||
430 | interface_options interface_opts; |
||
431 | |||
432 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, capture_opts->ifaces->len - 1); |
||
433 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, capture_opts->ifaces->len - 1); |
||
434 | interface_opts.sampling_method = CAPTURE_SAMP_BY_TIMER; |
||
435 | interface_opts.sampling_param = get_positive_int(p, "sampling timer"); |
||
436 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
437 | } else { |
||
438 | capture_opts->default_options.sampling_method = CAPTURE_SAMP_BY_TIMER; |
||
439 | capture_opts->default_options.sampling_param = get_positive_int(p, "sampling timer"); |
||
440 | } |
||
441 | } |
||
442 | *colonp = ':'; |
||
443 | return TRUE; |
||
444 | } |
||
445 | #endif |
||
446 | |||
447 | #ifdef HAVE_PCAP_REMOTE |
||
448 | /* |
||
449 | * Given a string of the form "<username>:<password>", as might appear |
||
450 | * as an argument to a "-A" option, parse it and set the arguments in |
||
451 | * question. Return an indication of whether it succeeded or failed |
||
452 | * in some fashion. |
||
453 | */ |
||
454 | static gboolean |
||
455 | get_auth_arguments(capture_options *capture_opts, const char *arg) |
||
456 | { |
||
457 | gchar *p = NULL, *colonp; |
||
458 | |||
459 | colonp = strchr(arg, ':'); |
||
460 | if (colonp == NULL) |
||
461 | return FALSE; |
||
462 | |||
463 | p = colonp; |
||
464 | *p++ = '\0'; |
||
465 | |||
466 | while (g_ascii_isspace(*p)) |
||
467 | p++; |
||
468 | |||
469 | if (capture_opts->ifaces->len > 0) { |
||
470 | interface_options interface_opts; |
||
471 | |||
472 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, capture_opts->ifaces->len - 1); |
||
473 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, capture_opts->ifaces->len - 1); |
||
474 | interface_opts.auth_type = CAPTURE_AUTH_PWD; |
||
475 | interface_opts.auth_username = g_strdup(arg); |
||
476 | interface_opts.auth_password = g_strdup(p); |
||
477 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
478 | } else { |
||
479 | capture_opts->default_options.auth_type = CAPTURE_AUTH_PWD; |
||
480 | capture_opts->default_options.auth_username = g_strdup(arg); |
||
481 | capture_opts->default_options.auth_password = g_strdup(p); |
||
482 | } |
||
483 | *colonp = ':'; |
||
484 | return TRUE; |
||
485 | } |
||
486 | #endif |
||
487 | |||
488 | static int |
||
489 | capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg_str_p) |
||
490 | { |
||
491 | long adapter_index; |
||
492 | char *p; |
||
493 | GList *if_list; |
||
494 | if_info_t *if_info; |
||
495 | int err; |
||
496 | gchar *err_str; |
||
497 | interface_options interface_opts; |
||
498 | |||
499 | /* |
||
500 | * If the argument is a number, treat it as an index into the list |
||
501 | * of adapters, as printed by "tshark -D". |
||
502 | * |
||
503 | * This should be OK on UNIX systems, as interfaces shouldn't have |
||
504 | * names that begin with digits. It can be useful on Windows, where |
||
505 | * more than one interface can have the same name. |
||
506 | */ |
||
507 | adapter_index = strtol(optarg_str_p, &p, 10); |
||
508 | if (p != NULL && *p == '\0') { |
||
509 | if (adapter_index < 0) { |
||
510 | cmdarg_err("The specified adapter index is a negative number"); |
||
511 | return 1; |
||
512 | } |
||
513 | if (adapter_index > INT_MAX) { |
||
514 | cmdarg_err("The specified adapter index is too large (greater than %d)", |
||
515 | INT_MAX); |
||
516 | return 1; |
||
517 | } |
||
518 | if (adapter_index == 0) { |
||
519 | cmdarg_err("There is no interface with that adapter index"); |
||
520 | return 1; |
||
521 | } |
||
522 | if_list = capture_interface_list(&err, &err_str, NULL); |
||
523 | if (if_list == NULL) { |
||
524 | if (err == 0) |
||
525 | cmdarg_err("There are no interfaces on which a capture can be done"); |
||
526 | else { |
||
527 | cmdarg_err("%s", err_str); |
||
528 | g_free(err_str); |
||
529 | } |
||
530 | return 2; |
||
531 | } |
||
532 | if_info = (if_info_t *)g_list_nth_data(if_list, (int)(adapter_index - 1)); |
||
533 | if (if_info == NULL) { |
||
534 | cmdarg_err("There is no interface with that adapter index"); |
||
535 | return 1; |
||
536 | } |
||
537 | interface_opts.name = g_strdup(if_info->name); |
||
538 | if (if_info->friendly_name != NULL) { |
||
539 | /* |
||
540 | * We have a friendly name for the interface, so display that |
||
541 | * instead of the interface name/guid. |
||
542 | * |
||
543 | * XXX - on UN*X, the interface name is not quite so ugly, |
||
544 | * and might be more familiar to users; display them both? |
||
545 | */ |
||
546 | interface_opts.console_display_name = g_strdup(if_info->friendly_name); |
||
547 | } else { |
||
548 | /* fallback to the interface name */ |
||
549 | interface_opts.console_display_name = g_strdup(if_info->name); |
||
550 | } |
||
551 | interface_opts.if_type = if_info->type; |
||
552 | #ifdef HAVE_EXTCAP |
||
553 | interface_opts.extcap = g_strdup(if_info->extcap); |
||
554 | #endif |
||
555 | free_interface_list(if_list); |
||
556 | } else if (capture_opts->capture_child) { |
||
557 | /* In Wireshark capture child mode, thus proper device name is supplied. */ |
||
558 | /* No need for trying to match it for friendly names. */ |
||
559 | interface_opts.name = g_strdup(optarg_str_p); |
||
560 | interface_opts.console_display_name = g_strdup(optarg_str_p); |
||
561 | interface_opts.if_type = capture_opts->default_options.if_type; |
||
562 | #ifdef HAVE_EXTCAP |
||
563 | interface_opts.extcap = g_strdup(capture_opts->default_options.extcap); |
||
564 | #endif |
||
565 | } else { |
||
566 | /* |
||
567 | * Retrieve the interface list so that we can search for the |
||
568 | * specified option amongst both the interface names and the |
||
569 | * friendly names and so that we find the friendly name even |
||
570 | * if an interface name was specified. |
||
571 | * |
||
572 | * If we can't get the list, just use the specified option as |
||
573 | * the interface name, so that the user can try specifying an |
||
574 | * interface explicitly for testing purposes. |
||
575 | */ |
||
576 | if_list = capture_interface_list(&err, NULL, NULL); |
||
577 | if (if_list != NULL) { |
||
578 | /* try and do an exact match (case insensitive) */ |
||
579 | GList *if_entry; |
||
580 | gboolean matched; |
||
581 | |||
582 | matched = FALSE; |
||
583 | for (if_entry = g_list_first(if_list); if_entry != NULL; |
||
584 | if_entry = g_list_next(if_entry)) |
||
585 | { |
||
586 | if_info = (if_info_t *)if_entry->data; |
||
587 | /* exact name check */ |
||
588 | if (g_ascii_strcasecmp(if_info->name, optarg_str_p) == 0) { |
||
589 | /* exact match on the interface name, use that for displaying etc */ |
||
590 | interface_opts.name = g_strdup(if_info->name); |
||
591 | |||
592 | if (if_info->friendly_name != NULL) { |
||
593 | /* |
||
594 | * If we have a friendly name, use that for the |
||
595 | * console display name, as it is the basis for |
||
596 | * the auto generated temp filename. |
||
597 | */ |
||
598 | interface_opts.console_display_name = g_strdup(if_info->friendly_name); |
||
599 | } else { |
||
600 | interface_opts.console_display_name = g_strdup(if_info->name); |
||
601 | } |
||
602 | interface_opts.if_type = if_info->type; |
||
603 | #ifdef HAVE_EXTCAP |
||
604 | interface_opts.extcap = g_strdup(if_info->extcap); |
||
605 | #endif |
||
606 | matched = TRUE; |
||
607 | break; |
||
608 | } |
||
609 | |||
610 | /* exact friendly name check */ |
||
611 | if (if_info->friendly_name != NULL && |
||
612 | g_ascii_strcasecmp(if_info->friendly_name, optarg_str_p) == 0) { |
||
613 | /* exact match - use the friendly name for display */ |
||
614 | interface_opts.name = g_strdup(if_info->name); |
||
615 | interface_opts.console_display_name = g_strdup(if_info->friendly_name); |
||
616 | interface_opts.if_type = if_info->type; |
||
617 | #ifdef HAVE_EXTCAP |
||
618 | interface_opts.extcap = g_strdup(if_info->extcap); |
||
619 | #endif |
||
620 | matched = TRUE; |
||
621 | break; |
||
622 | } |
||
623 | } |
||
624 | |||
625 | /* didn't find, attempt a case insensitive prefix match of the friendly name*/ |
||
626 | if (!matched) { |
||
627 | size_t prefix_length; |
||
628 | |||
629 | prefix_length = strlen(optarg_str_p); |
||
630 | for (if_entry = g_list_first(if_list); if_entry != NULL; |
||
631 | if_entry = g_list_next(if_entry)) |
||
632 | { |
||
633 | if_info = (if_info_t *)if_entry->data; |
||
634 | |||
635 | if (if_info->friendly_name != NULL && |
||
636 | g_ascii_strncasecmp(if_info->friendly_name, optarg_str_p, prefix_length) == 0) { |
||
637 | /* prefix match - use the friendly name for display */ |
||
638 | interface_opts.name = g_strdup(if_info->name); |
||
639 | interface_opts.console_display_name = g_strdup(if_info->friendly_name); |
||
640 | interface_opts.if_type = if_info->type; |
||
641 | #ifdef HAVE_EXTCAP |
||
642 | interface_opts.extcap = g_strdup(if_info->extcap); |
||
643 | #endif |
||
644 | matched = TRUE; |
||
645 | break; |
||
646 | } |
||
647 | } |
||
648 | } |
||
649 | if (!matched) { |
||
650 | /* |
||
651 | * We didn't find the interface in the list; just use |
||
652 | * the specified name, so that, for example, if an |
||
653 | * interface doesn't show up in the list for some |
||
654 | * reason, the user can try specifying it explicitly |
||
655 | * for testing purposes. |
||
656 | */ |
||
657 | interface_opts.name = g_strdup(optarg_str_p); |
||
658 | interface_opts.console_display_name = g_strdup(optarg_str_p); |
||
659 | interface_opts.if_type = capture_opts->default_options.if_type; |
||
660 | #ifdef HAVE_EXTCAP |
||
661 | interface_opts.extcap = g_strdup(capture_opts->default_options.extcap); |
||
662 | #endif |
||
663 | } |
||
664 | free_interface_list(if_list); |
||
665 | } else { |
||
666 | interface_opts.name = g_strdup(optarg_str_p); |
||
667 | interface_opts.console_display_name = g_strdup(optarg_str_p); |
||
668 | interface_opts.if_type = capture_opts->default_options.if_type; |
||
669 | #ifdef HAVE_EXTCAP |
||
670 | interface_opts.extcap = g_strdup(capture_opts->default_options.extcap); |
||
671 | #endif |
||
672 | } |
||
673 | } |
||
674 | |||
675 | /* We don't set iface_descr here because doing so requires |
||
676 | * capture_ui_utils.c which requires epan/prefs.c which is |
||
677 | * probably a bit too much dependency for here... |
||
678 | */ |
||
679 | interface_opts.descr = g_strdup(capture_opts->default_options.descr); |
||
680 | interface_opts.cfilter = g_strdup(capture_opts->default_options.cfilter); |
||
681 | interface_opts.snaplen = capture_opts->default_options.snaplen; |
||
682 | interface_opts.has_snaplen = capture_opts->default_options.has_snaplen; |
||
683 | interface_opts.linktype = capture_opts->default_options.linktype; |
||
684 | interface_opts.promisc_mode = capture_opts->default_options.promisc_mode; |
||
685 | #ifdef HAVE_EXTCAP |
||
686 | interface_opts.extcap_fifo = g_strdup(capture_opts->default_options.extcap_fifo); |
||
687 | interface_opts.extcap_args = NULL; |
||
688 | interface_opts.extcap_pid = INVALID_EXTCAP_PID; |
||
689 | interface_opts.extcap_userdata = NULL; |
||
690 | #endif |
||
691 | #ifdef CAN_SET_CAPTURE_BUFFER_SIZE |
||
692 | interface_opts.buffer_size = capture_opts->default_options.buffer_size; |
||
693 | #endif |
||
694 | interface_opts.monitor_mode = capture_opts->default_options.monitor_mode; |
||
695 | #ifdef HAVE_PCAP_REMOTE |
||
696 | interface_opts.src_type = capture_opts->default_options.src_type; |
||
697 | interface_opts.remote_host = g_strdup(capture_opts->default_options.remote_host); |
||
698 | interface_opts.remote_port = g_strdup(capture_opts->default_options.remote_port); |
||
699 | interface_opts.auth_type = capture_opts->default_options.auth_type; |
||
700 | interface_opts.auth_username = g_strdup(capture_opts->default_options.auth_username); |
||
701 | interface_opts.auth_password = g_strdup(capture_opts->default_options.auth_password); |
||
702 | interface_opts.datatx_udp = capture_opts->default_options.datatx_udp; |
||
703 | interface_opts.nocap_rpcap = capture_opts->default_options.nocap_rpcap; |
||
704 | interface_opts.nocap_local = capture_opts->default_options.nocap_local; |
||
705 | #endif |
||
706 | #ifdef HAVE_PCAP_SETSAMPLING |
||
707 | interface_opts.sampling_method = capture_opts->default_options.sampling_method; |
||
708 | interface_opts.sampling_param = capture_opts->default_options.sampling_param; |
||
709 | #endif |
||
710 | |||
711 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
712 | |||
713 | return 0; |
||
714 | } |
||
715 | |||
716 | |||
717 | int |
||
718 | capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg_str_p, gboolean *start_capture) |
||
719 | { |
||
720 | int status, snaplen; |
||
721 | |||
722 | switch(opt) { |
||
723 | case LONGOPT_NUM_CAP_COMMENT: /* capture comment */ |
||
724 | if (capture_opts->capture_comment) { |
||
725 | cmdarg_err("--capture-comment can be set only once per file"); |
||
726 | return 1; |
||
727 | } |
||
728 | capture_opts->capture_comment = g_strdup(optarg_str_p); |
||
729 | break; |
||
730 | case 'a': /* autostop criteria */ |
||
731 | if (set_autostop_criterion(capture_opts, optarg_str_p) == FALSE) { |
||
732 | cmdarg_err("Invalid or unknown -a flag \"%s\"", optarg_str_p); |
||
733 | return 1; |
||
734 | } |
||
735 | break; |
||
736 | #ifdef HAVE_PCAP_REMOTE |
||
737 | case 'A': |
||
738 | if (get_auth_arguments(capture_opts, optarg_str_p) == FALSE) { |
||
739 | cmdarg_err("Invalid or unknown -A arg \"%s\"", optarg_str_p); |
||
740 | return 1; |
||
741 | } |
||
742 | break; |
||
743 | #endif |
||
744 | case 'b': /* Ringbuffer option */ |
||
745 | capture_opts->multi_files_on = TRUE; |
||
746 | if (get_ring_arguments(capture_opts, optarg_str_p) == FALSE) { |
||
747 | cmdarg_err("Invalid or unknown -b arg \"%s\"", optarg_str_p); |
||
748 | return 1; |
||
749 | } |
||
750 | break; |
||
751 | #ifdef CAN_SET_CAPTURE_BUFFER_SIZE |
||
752 | case 'B': /* Buffer size */ |
||
753 | if (capture_opts->ifaces->len > 0) { |
||
754 | interface_options interface_opts; |
||
755 | |||
756 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, capture_opts->ifaces->len - 1); |
||
757 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, capture_opts->ifaces->len - 1); |
||
758 | interface_opts.buffer_size = get_positive_int(optarg_str_p, "buffer size"); |
||
759 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
760 | } else { |
||
761 | capture_opts->default_options.buffer_size = get_positive_int(optarg_str_p, "buffer size"); |
||
762 | } |
||
763 | break; |
||
764 | #endif |
||
765 | case 'c': /* Capture n packets */ |
||
766 | capture_opts->has_autostop_packets = TRUE; |
||
767 | capture_opts->autostop_packets = get_positive_int(optarg_str_p, "packet count"); |
||
768 | break; |
||
769 | case 'f': /* capture filter */ |
||
770 | get_filter_arguments(capture_opts, optarg_str_p); |
||
771 | break; |
||
772 | case 'g': /* enable group read access on the capture file(s) */ |
||
773 | capture_opts->group_read_access = TRUE; |
||
774 | break; |
||
775 | case 'H': /* Hide capture info dialog box */ |
||
776 | capture_opts->show_info = FALSE; |
||
777 | break; |
||
778 | case 'i': /* Use interface x */ |
||
779 | status = capture_opts_add_iface_opt(capture_opts, optarg_str_p); |
||
780 | if (status != 0) { |
||
781 | return status; |
||
782 | } |
||
783 | break; |
||
784 | #ifdef HAVE_PCAP_CREATE |
||
785 | case 'I': /* Capture in monitor mode */ |
||
786 | if (capture_opts->ifaces->len > 0) { |
||
787 | interface_options interface_opts; |
||
788 | |||
789 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, capture_opts->ifaces->len - 1); |
||
790 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, capture_opts->ifaces->len - 1); |
||
791 | interface_opts.monitor_mode = TRUE; |
||
792 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
793 | } else { |
||
794 | capture_opts->default_options.monitor_mode = TRUE; |
||
795 | } |
||
796 | break; |
||
797 | #endif |
||
798 | case 'k': /* Start capture immediately */ |
||
799 | *start_capture = TRUE; |
||
800 | break; |
||
801 | /*case 'l':*/ /* Automatic scrolling in live capture mode */ |
||
802 | #ifdef HAVE_PCAP_SETSAMPLING |
||
803 | case 'm': |
||
804 | if (get_sampling_arguments(capture_opts, optarg_str_p) == FALSE) { |
||
805 | cmdarg_err("Invalid or unknown -m arg \"%s\"", optarg_str_p); |
||
806 | return 1; |
||
807 | } |
||
808 | break; |
||
809 | #endif |
||
810 | case 'n': /* Use pcapng format */ |
||
811 | capture_opts->use_pcapng = TRUE; |
||
812 | break; |
||
813 | case 'p': /* Don't capture in promiscuous mode */ |
||
814 | if (capture_opts->ifaces->len > 0) { |
||
815 | interface_options interface_opts; |
||
816 | |||
817 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, capture_opts->ifaces->len - 1); |
||
818 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, capture_opts->ifaces->len - 1); |
||
819 | interface_opts.promisc_mode = FALSE; |
||
820 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
821 | } else { |
||
822 | capture_opts->default_options.promisc_mode = FALSE; |
||
823 | } |
||
824 | break; |
||
825 | case 'P': /* Use pcap format */ |
||
826 | capture_opts->use_pcapng = FALSE; |
||
827 | break; |
||
828 | #ifdef HAVE_PCAP_REMOTE |
||
829 | case 'r': |
||
830 | if (capture_opts->ifaces->len > 0) { |
||
831 | interface_options interface_opts; |
||
832 | |||
833 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, capture_opts->ifaces->len - 1); |
||
834 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, capture_opts->ifaces->len - 1); |
||
835 | interface_opts.nocap_rpcap = FALSE; |
||
836 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
837 | } else { |
||
838 | capture_opts->default_options.nocap_rpcap = FALSE; |
||
839 | } |
||
840 | break; |
||
841 | #endif |
||
842 | case 's': /* Set the snapshot (capture) length */ |
||
843 | snaplen = get_natural_int(optarg_str_p, "snapshot length"); |
||
844 | /* |
||
845 | * Make a snapshot length of 0 equivalent to the maximum packet |
||
846 | * length, mirroring what tcpdump does. |
||
847 | */ |
||
848 | if (snaplen == 0) |
||
849 | snaplen = WTAP_MAX_PACKET_SIZE; |
||
850 | if (capture_opts->ifaces->len > 0) { |
||
851 | interface_options interface_opts; |
||
852 | |||
853 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, capture_opts->ifaces->len - 1); |
||
854 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, capture_opts->ifaces->len - 1); |
||
855 | interface_opts.has_snaplen = TRUE; |
||
856 | interface_opts.snaplen = snaplen; |
||
857 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
858 | } else { |
||
859 | capture_opts->default_options.snaplen = snaplen; |
||
860 | capture_opts->default_options.has_snaplen = TRUE; |
||
861 | } |
||
862 | break; |
||
863 | case 'S': /* "Real-Time" mode: used for following file ala tail -f */ |
||
864 | capture_opts->real_time_mode = TRUE; |
||
865 | break; |
||
866 | #ifdef HAVE_PCAP_REMOTE |
||
867 | case 'u': |
||
868 | if (capture_opts->ifaces->len > 0) { |
||
869 | interface_options interface_opts; |
||
870 | |||
871 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, capture_opts->ifaces->len - 1); |
||
872 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, capture_opts->ifaces->len - 1); |
||
873 | interface_opts.datatx_udp = TRUE; |
||
874 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
875 | } else { |
||
876 | capture_opts->default_options.datatx_udp = TRUE; |
||
877 | } |
||
878 | break; |
||
879 | #endif |
||
880 | case 'w': /* Write to capture file x */ |
||
881 | capture_opts->saving_to_file = TRUE; |
||
882 | g_free(capture_opts->save_file); |
||
883 | capture_opts->save_file = g_strdup(optarg_str_p); |
||
884 | status = capture_opts_output_to_pipe(capture_opts->save_file, &capture_opts->output_to_pipe); |
||
885 | return status; |
||
886 | case 'y': /* Set the pcap data link type */ |
||
887 | if (capture_opts->ifaces->len > 0) { |
||
888 | interface_options interface_opts; |
||
889 | |||
890 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, capture_opts->ifaces->len - 1); |
||
891 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, capture_opts->ifaces->len - 1); |
||
892 | interface_opts.linktype = linktype_name_to_val(optarg_str_p); |
||
893 | if (interface_opts.linktype == -1) { |
||
894 | cmdarg_err("The specified data link type \"%s\" isn't valid", |
||
895 | optarg_str_p); |
||
896 | return 1; |
||
897 | } |
||
898 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
899 | } else { |
||
900 | capture_opts->default_options.linktype = linktype_name_to_val(optarg_str_p); |
||
901 | if (capture_opts->default_options.linktype == -1) { |
||
902 | cmdarg_err("The specified data link type \"%s\" isn't valid", |
||
903 | optarg_str_p); |
||
904 | return 1; |
||
905 | } |
||
906 | } |
||
907 | break; |
||
908 | default: |
||
909 | /* the caller is responsible to send us only the right opt's */ |
||
910 | g_assert_not_reached(); |
||
911 | } |
||
912 | |||
913 | return 0; |
||
914 | } |
||
915 | |||
916 | void |
||
917 | capture_opts_print_if_capabilities(if_capabilities_t *caps, char *name, |
||
918 | gboolean monitor_mode) |
||
919 | { |
||
920 | GList *lt_entry; |
||
921 | data_link_info_t *data_link_info; |
||
922 | |||
923 | if (caps->can_set_rfmon) |
||
924 | printf("Data link types of interface %s when %sin monitor mode (use option -y to set):\n", |
||
925 | name, monitor_mode ? "" : "not "); |
||
926 | else |
||
927 | printf("Data link types of interface %s (use option -y to set):\n", name); |
||
928 | for (lt_entry = caps->data_link_types; lt_entry != NULL; |
||
929 | lt_entry = g_list_next(lt_entry)) { |
||
930 | data_link_info = (data_link_info_t *)lt_entry->data; |
||
931 | printf(" %s", data_link_info->name); |
||
932 | if (data_link_info->description != NULL) |
||
933 | printf(" (%s)", data_link_info->description); |
||
934 | else |
||
935 | printf(" (not supported)"); |
||
936 | printf("\n"); |
||
937 | } |
||
938 | } |
||
939 | |||
940 | /* Print an ASCII-formatted list of interfaces. */ |
||
941 | void |
||
942 | capture_opts_print_interfaces(GList *if_list) |
||
943 | { |
||
944 | int i; |
||
945 | GList *if_entry; |
||
946 | if_info_t *if_info; |
||
947 | |||
948 | i = 1; /* Interface id number */ |
||
949 | for (if_entry = g_list_first(if_list); if_entry != NULL; |
||
950 | if_entry = g_list_next(if_entry)) { |
||
951 | if_info = (if_info_t *)if_entry->data; |
||
952 | printf("%d. %s", i++, if_info->name); |
||
953 | |||
954 | /* Print the interface friendly name, if it exists; |
||
955 | if not fall back to vendor description, if it exists. */ |
||
956 | if (if_info->friendly_name != NULL){ |
||
957 | printf(" (%s)", if_info->friendly_name); |
||
958 | } else { |
||
959 | if (if_info->vendor_description != NULL) |
||
960 | printf(" (%s)", if_info->vendor_description); |
||
961 | } |
||
962 | printf("\n"); |
||
963 | } |
||
964 | } |
||
965 | |||
966 | |||
967 | void |
||
968 | capture_opts_trim_snaplen(capture_options *capture_opts, int snaplen_min) |
||
969 | { |
||
970 | guint i; |
||
971 | interface_options interface_opts; |
||
972 | |||
973 | if (capture_opts->ifaces->len > 0) { |
||
974 | for (i = 0; i < capture_opts->ifaces->len; i++) { |
||
975 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, 0); |
||
976 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, 0); |
||
977 | if (interface_opts.snaplen < 1) |
||
978 | interface_opts.snaplen = WTAP_MAX_PACKET_SIZE; |
||
979 | else if (interface_opts.snaplen < snaplen_min) |
||
980 | interface_opts.snaplen = snaplen_min; |
||
981 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
982 | } |
||
983 | } else { |
||
984 | if (capture_opts->default_options.snaplen < 1) |
||
985 | capture_opts->default_options.snaplen = WTAP_MAX_PACKET_SIZE; |
||
986 | else if (capture_opts->default_options.snaplen < snaplen_min) |
||
987 | capture_opts->default_options.snaplen = snaplen_min; |
||
988 | } |
||
989 | } |
||
990 | |||
991 | |||
992 | void |
||
993 | capture_opts_trim_ring_num_files(capture_options *capture_opts) |
||
994 | { |
||
995 | /* Check the value range of the ring_num_files parameter */ |
||
996 | if (capture_opts->ring_num_files > RINGBUFFER_MAX_NUM_FILES) { |
||
997 | cmdarg_err("Too many ring buffer files (%u). Reducing to %u.\n", capture_opts->ring_num_files, RINGBUFFER_MAX_NUM_FILES); |
||
998 | capture_opts->ring_num_files = RINGBUFFER_MAX_NUM_FILES; |
||
999 | } else if (capture_opts->ring_num_files > RINGBUFFER_WARN_NUM_FILES) { |
||
1000 | cmdarg_err("%u is a lot of ring buffer files.\n", capture_opts->ring_num_files); |
||
1001 | } |
||
1002 | #if RINGBUFFER_MIN_NUM_FILES > 0 |
||
1003 | else if (capture_opts->ring_num_files < RINGBUFFER_MIN_NUM_FILES) |
||
1004 | cmdarg_err("Too few ring buffer files (%u). Increasing to %u.\n", capture_opts->ring_num_files, RINGBUFFER_MIN_NUM_FILES); |
||
1005 | capture_opts->ring_num_files = RINGBUFFER_MIN_NUM_FILES; |
||
1006 | #endif |
||
1007 | } |
||
1008 | |||
1009 | /* |
||
1010 | * If no interface was specified explicitly, pick a default. |
||
1011 | */ |
||
1012 | int |
||
1013 | capture_opts_default_iface_if_necessary(capture_options *capture_opts, |
||
1014 | const char *capture_device) |
||
1015 | { |
||
1016 | int status; |
||
1017 | |||
1018 | /* Did the user specify an interface to use? */ |
||
1019 | if (capture_opts->num_selected != 0 || capture_opts->ifaces->len != 0) { |
||
1020 | /* yes they did, return immediately - nothing further to do here */ |
||
1021 | return 0; |
||
1022 | } |
||
1023 | |||
1024 | /* No - is a default specified in the preferences file? */ |
||
1025 | if (capture_device != NULL) { |
||
1026 | /* Yes - use it. */ |
||
1027 | status = capture_opts_add_iface_opt(capture_opts, capture_device); |
||
1028 | return status; |
||
1029 | } |
||
1030 | /* No default in preferences file, just pick the first interface from the list of interfaces. */ |
||
1031 | return capture_opts_add_iface_opt(capture_opts, "1"); |
||
1032 | } |
||
1033 | |||
1034 | #ifndef S_IFIFO |
||
1035 | #define S_IFIFO _S_IFIFO |
||
1036 | #endif |
||
1037 | #ifndef S_ISFIFO |
||
1038 | #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) |
||
1039 | #endif |
||
1040 | |||
1041 | /* copied from filesystem.c */ |
||
1042 | static int |
||
1043 | capture_opts_test_for_fifo(const char *path) |
||
1044 | { |
||
1045 | ws_statb64 statb; |
||
1046 | |||
1047 | if (ws_stat64(path, &statb) < 0) |
||
1048 | return errno; |
||
1049 | |||
1050 | if (S_ISFIFO(statb.st_mode)) |
||
1051 | return ESPIPE; |
||
1052 | else |
||
1053 | return 0; |
||
1054 | } |
||
1055 | |||
1056 | static gboolean |
||
1057 | capture_opts_output_to_pipe(const char *save_file, gboolean *is_pipe) |
||
1058 | { |
||
1059 | int err; |
||
1060 | |||
1061 | *is_pipe = FALSE; |
||
1062 | |||
1063 | if (save_file != NULL) { |
||
1064 | /* We're writing to a capture file. */ |
||
1065 | if (strcmp(save_file, "-") == 0) { |
||
1066 | /* Writing to stdout. */ |
||
1067 | /* XXX - should we check whether it's a pipe? It's arguably |
||
1068 | silly to do "-w - >output_file" rather than "-w output_file", |
||
1069 | but by not checking we might be violating the Principle Of |
||
1070 | Least Astonishment. */ |
||
1071 | *is_pipe = TRUE; |
||
1072 | } else { |
||
1073 | /* not writing to stdout, test for a FIFO (aka named pipe) */ |
||
1074 | err = capture_opts_test_for_fifo(save_file); |
||
1075 | switch (err) { |
||
1076 | |||
1077 | case ENOENT: /* it doesn't exist, so we'll be creating it, |
||
1078 | and it won't be a FIFO */ |
||
1079 | case 0: /* found it, but it's not a FIFO */ |
||
1080 | break; |
||
1081 | |||
1082 | case ESPIPE: /* it is a FIFO */ |
||
1083 | *is_pipe = TRUE; |
||
1084 | break; |
||
1085 | |||
1086 | default: /* couldn't stat it */ |
||
1087 | break; /* ignore: later attempt to open */ |
||
1088 | /* will generate a nice msg */ |
||
1089 | } |
||
1090 | } |
||
1091 | } |
||
1092 | |||
1093 | return 0; |
||
1094 | } |
||
1095 | |||
1096 | void |
||
1097 | capture_opts_del_iface(capture_options *capture_opts, guint if_index) |
||
1098 | { |
||
1099 | interface_options interface_opts; |
||
1100 | |||
1101 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, if_index); |
||
1102 | /* XXX - check if found? */ |
||
1103 | |||
1104 | g_free(interface_opts.name); |
||
1105 | g_free(interface_opts.descr); |
||
1106 | if (interface_opts.console_display_name != NULL) |
||
1107 | g_free(interface_opts.console_display_name); |
||
1108 | g_free(interface_opts.cfilter); |
||
1109 | #ifdef HAVE_EXTCAP |
||
1110 | g_free(interface_opts.extcap); |
||
1111 | g_free(interface_opts.extcap_fifo); |
||
1112 | if (interface_opts.extcap_args) |
||
1113 | g_hash_table_unref(interface_opts.extcap_args); |
||
1114 | if (interface_opts.extcap_pid != INVALID_EXTCAP_PID) |
||
1115 | g_spawn_close_pid(interface_opts.extcap_pid); |
||
1116 | g_free(interface_opts.extcap_userdata); |
||
1117 | #endif |
||
1118 | #ifdef HAVE_PCAP_REMOTE |
||
1119 | if (interface_opts.src_type == CAPTURE_IFREMOTE) { |
||
1120 | g_free(interface_opts.remote_host); |
||
1121 | g_free(interface_opts.remote_port); |
||
1122 | g_free(interface_opts.auth_username); |
||
1123 | g_free(interface_opts.auth_password); |
||
1124 | } |
||
1125 | #endif |
||
1126 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, if_index); |
||
1127 | } |
||
1128 | |||
1129 | |||
1130 | |||
1131 | /* |
||
1132 | * Add all non-hidden selected interfaces in the "all interfaces" list |
||
1133 | * to the list of interfaces for the capture. |
||
1134 | */ |
||
1135 | void |
||
1136 | collect_ifaces(capture_options *capture_opts) |
||
1137 | { |
||
1138 | guint i; |
||
1139 | interface_t device; |
||
1140 | interface_options interface_opts; |
||
1141 | |||
1142 | /* Empty out the existing list of interfaces. */ |
||
1143 | for (i = capture_opts->ifaces->len; i != 0; i--) |
||
1144 | capture_opts_del_iface(capture_opts, i-1); |
||
1145 | |||
1146 | /* Now fill the list up again. */ |
||
1147 | for (i = 0; i < capture_opts->all_ifaces->len; i++) { |
||
1148 | device = g_array_index(capture_opts->all_ifaces, interface_t, i); |
||
1149 | if (!device.hidden && device.selected) { |
||
1150 | interface_opts.name = g_strdup(device.name); |
||
1151 | interface_opts.descr = g_strdup(device.display_name); |
||
1152 | interface_opts.console_display_name = g_strdup(device.name); |
||
1153 | interface_opts.linktype = device.active_dlt; |
||
1154 | interface_opts.cfilter = g_strdup(device.cfilter); |
||
1155 | interface_opts.snaplen = device.snaplen; |
||
1156 | interface_opts.has_snaplen = device.has_snaplen; |
||
1157 | interface_opts.promisc_mode = device.pmode; |
||
1158 | interface_opts.if_type = device.if_info.type; |
||
1159 | #ifdef HAVE_EXTCAP |
||
1160 | interface_opts.extcap = g_strdup(device.if_info.extcap); |
||
1161 | interface_opts.extcap_fifo = NULL; |
||
1162 | interface_opts.extcap_userdata = NULL; |
||
1163 | interface_opts.extcap_args = device.external_cap_args_settings; |
||
1164 | interface_opts.extcap_pid = INVALID_EXTCAP_PID; |
||
1165 | if (interface_opts.extcap_args) |
||
1166 | g_hash_table_ref(interface_opts.extcap_args); |
||
1167 | interface_opts.extcap_userdata = NULL; |
||
1168 | #endif |
||
1169 | #ifdef CAN_SET_CAPTURE_BUFFER_SIZE |
||
1170 | interface_opts.buffer_size = device.buffer; |
||
1171 | #endif |
||
1172 | #ifdef HAVE_PCAP_CREATE |
||
1173 | interface_opts.monitor_mode = device.monitor_mode_enabled; |
||
1174 | #endif |
||
1175 | #ifdef HAVE_PCAP_REMOTE |
||
1176 | interface_opts.src_type = CAPTURE_IFREMOTE; |
||
1177 | interface_opts.remote_host = g_strdup(device.remote_opts.remote_host_opts.remote_host); |
||
1178 | interface_opts.remote_port = g_strdup(device.remote_opts.remote_host_opts.remote_port); |
||
1179 | interface_opts.auth_type = device.remote_opts.remote_host_opts.auth_type; |
||
1180 | interface_opts.auth_username = g_strdup(device.remote_opts.remote_host_opts.auth_username); |
||
1181 | interface_opts.auth_password = g_strdup(device.remote_opts.remote_host_opts.auth_password); |
||
1182 | interface_opts.datatx_udp = device.remote_opts.remote_host_opts.datatx_udp; |
||
1183 | interface_opts.nocap_rpcap = device.remote_opts.remote_host_opts.nocap_rpcap; |
||
1184 | interface_opts.nocap_local = device.remote_opts.remote_host_opts.nocap_local; |
||
1185 | #endif |
||
1186 | #ifdef HAVE_PCAP_SETSAMPLING |
||
1187 | interface_opts.sampling_method = device.remote_opts.sampling_method; |
||
1188 | interface_opts.sampling_param = device.remote_opts.sampling_param; |
||
1189 | #endif |
||
1190 | g_array_append_val(capture_opts->ifaces, interface_opts); |
||
1191 | } else { |
||
1192 | continue; |
||
1193 | } |
||
1194 | } |
||
1195 | } |
||
1196 | |||
1197 | static void |
||
1198 | capture_opts_free_interface_t_links(gpointer elem, gpointer unused _U_) |
||
1199 | { |
||
1200 | link_row* e = (link_row*)elem; |
||
1201 | if (e != NULL) |
||
1202 | g_free(e->name); |
||
1203 | g_free(elem); |
||
1204 | } |
||
1205 | |||
1206 | static void |
||
1207 | capture_opts_free_interface_t_addrs(gpointer elem, gpointer unused _U_) |
||
1208 | { |
||
1209 | g_free(elem); |
||
1210 | } |
||
1211 | |||
1212 | void |
||
1213 | capture_opts_free_interface_t(interface_t *device) |
||
1214 | { |
||
1215 | if (device != NULL) { |
||
1216 | g_free(device->name); |
||
1217 | g_free(device->display_name); |
||
1218 | g_free(device->friendly_name); |
||
1219 | g_free(device->addresses); |
||
1220 | g_free(device->cfilter); |
||
1221 | g_list_foreach(device->links, |
||
1222 | capture_opts_free_interface_t_links, NULL); |
||
1223 | g_list_free(device->links); |
||
1224 | #ifdef HAVE_PCAP_REMOTE |
||
1225 | g_free(device->remote_opts.remote_host_opts.remote_host); |
||
1226 | g_free(device->remote_opts.remote_host_opts.remote_port); |
||
1227 | g_free(device->remote_opts.remote_host_opts.auth_username); |
||
1228 | g_free(device->remote_opts.remote_host_opts.auth_password); |
||
1229 | #endif |
||
1230 | g_free(device->if_info.name); |
||
1231 | g_free(device->if_info.friendly_name); |
||
1232 | g_free(device->if_info.vendor_description); |
||
1233 | g_slist_foreach(device->if_info.addrs, |
||
1234 | capture_opts_free_interface_t_addrs, NULL); |
||
1235 | g_slist_free(device->if_info.addrs); |
||
1236 | #ifdef HAVE_EXTCAP |
||
1237 | g_free(device->if_info.extcap); |
||
1238 | #endif |
||
1239 | } |
||
1240 | } |
||
1241 | |||
1242 | #endif /* HAVE_LIBPCAP */ |
||
1243 | |||
1244 | /* |
||
1245 | * Editor modelines - http://www.wireshark.org/tools/modelines.html |
||
1246 | * |
||
1247 | * Local variables: |
||
1248 | * c-basic-offset: 4 |
||
1249 | * tab-width: 8 |
||
1250 | * indent-tabs-mode: nil |
||
1251 | * End: |
||
1252 | * |
||
1253 | * vi: set shiftwidth=4 tabstop=8 expandtab: |
||
1254 | * :indentSize=4:tabSize=8:noTabs=true: |
||
1255 | */ |