Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / extcap / wifidump.c
blob01492b2a91bf898bb549b3fda15118556d11b1f6
1 /* wifidump.c
2 * wifidump is an extcap tool used to capture Wi-Fi frames using a remote ssh host
4 * Adapted from sshdump.
6 * Copyright 2022, Adrian Granados <adrian@intuitibits.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "config.h"
16 #define WS_LOG_DOMAIN "wifidump"
18 #include <extcap/extcap-base.h>
19 #include <extcap/ssh-base.h>
20 #include <wsutil/interface.h>
21 #include <wsutil/file_util.h>
22 #include <wsutil/strtoi.h>
23 #include <wsutil/filesystem.h>
24 #include <wsutil/privileges.h>
25 #include <wsutil/please_report_bug.h>
26 #include <wsutil/wslog.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <fcntl.h>
32 #include <cli_main.h>
34 static char* wifidump_extcap_interface;
35 #define DEFAULT_WIFIDUMP_EXTCAP_INTERFACE "wifidump"
37 #define WIFIDUMP_VERSION_MAJOR "1"
38 #define WIFIDUMP_VERSION_MINOR "0"
39 #define WIFIDUMP_VERSION_RELEASE "0"
41 #define SSH_READ_BLOCK_SIZE 256
43 enum {
44 EXTCAP_BASE_OPTIONS_ENUM,
45 OPT_HELP,
46 OPT_VERSION,
47 OPT_REMOTE_HOST,
48 OPT_REMOTE_PORT,
49 OPT_REMOTE_USERNAME,
50 OPT_REMOTE_PASSWORD,
51 OPT_REMOTE_INTERFACE,
52 OPT_REMOTE_CHANNEL_FREQUENCY,
53 OPT_REMOTE_CHANNEL_WIDTH,
54 OPT_REMOTE_FILTER,
55 OPT_SSHKEY,
56 OPT_SSHKEY_PASSPHRASE,
57 OPT_PROXYCOMMAND,
58 OPT_SSH_SHA1,
59 OPT_REMOTE_COUNT
62 static const struct ws_option longopts[] = {
63 EXTCAP_BASE_OPTIONS,
64 { "help", ws_no_argument, NULL, OPT_HELP},
65 { "version", ws_no_argument, NULL, OPT_VERSION},
66 SSH_BASE_PACKET_OPTIONS,
67 { "remote-channel-frequency", ws_required_argument, NULL, OPT_REMOTE_CHANNEL_FREQUENCY},
68 { "remote-channel-width", ws_required_argument, NULL, OPT_REMOTE_CHANNEL_WIDTH},
69 { 0, 0, 0, 0}
72 static const char * remote_capture_functions =
73 "\n"
74 "function iface_down {\n"
75 " local iface=$1\n"
76 " sudo ip link set $iface down > /dev/null 2>&1\n"
77 "}\n"
78 "\n"
79 "function iface_up {\n"
80 " local iface=$1\n"
81 " sudo ip link set $iface up > /dev/null 2>&1\n"
82 "}\n"
83 "\n"
84 "function iface_monitor {\n"
85 " local iface=$1\n"
86 " sudo iw dev $iface set monitor control otherbss > /dev/null 2>&1 ||\n"
87 " sudo iw dev $iface set type monitor control otherbss > /dev/null 2>&1\n"
88 "}\n"
89 "\n"
90 "function iface_scan {\n"
91 " local iface=$1\n"
92 " iface_down $iface &&\n"
93 " sudo iw dev $iface set type managed > /dev/null 2>&1 &&\n"
94 " iface_up $iface &&\n"
95 " sudo iw dev $iface scan > /dev/null 2>&1\n"
96 "}\n"
97 "\n"
98 "function iface_config {\n"
99 " local iface=$1\n"
100 " local freq=$2\n"
101 " local ch_width=$3\n"
102 " local center_freq=$4\n"
103 " if [ $freq -eq $center_freq ]; then\n"
104 " sudo iw dev $1 set freq $freq $ch_width 2>&1\n"
105 " else\n"
106 " sudo iw dev $1 set freq $freq $ch_width $center_freq 2>&1\n"
107 " fi\n"
108 "}\n"
109 "\n"
110 "function iface_start {\n"
111 " local iface=$1\n"
112 " local count=$2\n"
113 " local filter=\"${@:3}\"\n"
114 " if [ $count -gt 0 ]; then\n"
115 " sudo tcpdump -i $iface -U -w - -c $count $filter\n"
116 " else\n"
117 " sudo tcpdump -i $iface -U -w - $filter\n"
118 " fi\n"
119 "}\n"
120 "\n"
121 "function capture_generic {\n"
122 " local iface=$1\n"
123 " local freq=$2\n"
124 " local ch_width=$3\n"
125 " local center_freq=$4\n"
126 " local count=$5\n"
127 " local filter=\"${@:6}\"\n"
128 " if ! { iwconfig $iface | grep Monitor > /dev/null 2>&1; }; then\n"
129 " iface_down $iface &&\n"
130 " iface_monitor $iface &&\n"
131 " iface_up $iface\n"
132 " else\n"
133 " iface_monitor $iface\n"
134 " fi\n"
135 " iface_config $iface $freq $ch_width $center_freq &&\n"
136 " iface_start $iface $count $filter\n"
137 "}\n"
138 "\n"
139 "function capture_iwlwifi {\n"
140 " local iface=$1\n"
141 " local freq=$2\n"
142 " local ch_width=$3\n"
143 " local center_freq=$4\n"
144 " local count=$5\n"
145 " local filter=\"${@:6}\"\n"
146 " INDEX=`sudo iw dev $iface info | grep wiphy | grep -Eo '[0-9]+'`\n"
147 " sudo iw phy phy${INDEX} channels | grep $freq | grep -i disabled > /dev/null 2>&1 &&\n"
148 " iface_scan $iface\n"
149 " MON=${iface}mon\n"
150 " sudo iw $iface interface add $MON type monitor flags none > /dev/null 2>&1\n"
151 " iface_up $MON &&\n"
152 " iface_down $iface &&\n"
153 " iface_config $MON $freq $ch_width $center_freq &&\n"
154 " iface_start $MON $count $filter\n"
155 "}\n"
156 "\n"
157 "function capture {\n"
158 " local iface=$1\n"
159 " local freq=$2\n"
160 " local ch_width=$3\n"
161 " local center_freq=$4\n"
162 " local count=$5\n"
163 " local filter=\"${@:6}\"\n"
164 " if [ \"$iface\" == \"auto\" ]; then\n"
165 " iface=`sudo iw dev | grep -i interface | awk '{ print $2 }' | sort | head -n 1`\n"
166 " fi\n"
167 " local driver=`/usr/sbin/ethtool -i $iface | grep driver | awk '{ print $2 }'`\n"
168 " if [ $driver = \"iwlwifi\" ]; then\n"
169 " capture_iwlwifi $iface $freq $ch_width $center_freq $count $filter\n"
170 " else\n"
171 " capture_generic $iface $freq $ch_width $center_freq $count $filter\n"
172 " fi\n"
173 "}\n"
174 "\n";
176 static unsigned int wifi_freqs_2dot4_5ghz[] = {
177 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
178 2467, 2472, 2484,
179 5180, 5200, 5220, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, 5580,
180 5600, 5620, 5640, 5660, 5680, 5700, 5720, 5745, 5765, 5785, 5805, 5825,
184 static unsigned int freq_to_channel(unsigned int freq_mhz) {
185 if (freq_mhz == 2484)
186 return 14;
187 else if (freq_mhz >= 2412 && freq_mhz <= 2484)
188 return ((freq_mhz - 2412) / 5) + 1;
189 else if (freq_mhz >= 5160 && freq_mhz <= 5885)
190 return ((freq_mhz - 5180) / 5) + 36;
191 else if (freq_mhz >= 5955 && freq_mhz <= 7115)
192 return ((freq_mhz - 5955) / 5) + 1;
193 else
194 return 0;
197 static const char *freq_to_band(unsigned int freq_mhz)
199 if (freq_mhz >= 2412 && freq_mhz <= 2484)
200 return "2.4 GHz";
201 else if (freq_mhz >= 5160 && freq_mhz <= 5885)
202 return "5 GHz";
203 else if (freq_mhz >= 5955 && freq_mhz <= 7115)
204 return "6 GHz";
205 else
206 return NULL;
209 static unsigned int center_freq(unsigned int freq_mhz, unsigned int ch_width_mhz) {
211 unsigned int start_freq;
213 if (ch_width_mhz == 20) {
214 return freq_mhz;
216 else if (ch_width_mhz == 40) {
217 if (freq_mhz >= 5180 && freq_mhz <= 5720) {
218 for (start_freq = 5180; start_freq <= 5700; start_freq += ch_width_mhz) {
219 if (freq_mhz >= start_freq && freq_mhz <= (start_freq + 20))
220 return ((start_freq * 2) + 20) / 2;
223 else if (freq_mhz >= 5745 && freq_mhz <= 5765)
224 return 5755;
225 else if (freq_mhz >= 5785 && freq_mhz <= 5805)
226 return 5795;
227 else if (freq_mhz >= 5955 && freq_mhz <= 7095) {
228 for (start_freq = 5955; start_freq <= 7075; start_freq += ch_width_mhz) {
229 if (freq_mhz >= start_freq && freq_mhz <= (start_freq + 20))
230 return ((start_freq * 2) + 20) / 2;
234 else if (ch_width_mhz == 80) {
235 if (freq_mhz >= 5180 && freq_mhz <= 5660) {
236 for (start_freq = 5180; start_freq <= 5660; start_freq += ch_width_mhz) {
237 if (freq_mhz >= start_freq && freq_mhz <= (start_freq + 60))
238 return ((start_freq * 2) + 60) / 2;
241 else if (freq_mhz >= 5745 && freq_mhz <= 5805)
242 return 5775;
243 else if (freq_mhz >= 5955 && freq_mhz <= 7055) {
244 for (start_freq = 5955; start_freq <= 6995; start_freq += ch_width_mhz) {
245 if (freq_mhz >= start_freq && freq_mhz <= (start_freq + 60))
246 return ((start_freq * 2) + 60) / 2;
250 else if (ch_width_mhz == 160) {
251 if (freq_mhz >= 5180 && freq_mhz <= 5640) {
252 for (start_freq = 5180; start_freq <= 5500; start_freq += ch_width_mhz) {
253 if (freq_mhz >= start_freq && freq_mhz <= (start_freq + 140))
254 return ((start_freq * 2) + 140) / 2;
257 else if (freq_mhz >= 5955 && freq_mhz <= 7055) {
258 for (start_freq = 5955; start_freq <= 6915; start_freq += ch_width_mhz) {
259 if (freq_mhz >= start_freq && freq_mhz <= (start_freq + 140))
260 return ((start_freq * 2) + 140) / 2;
265 return -1;
268 static int ssh_loop_read(ssh_channel channel, FILE* fp)
270 int nbytes;
271 int ret = EXIT_SUCCESS;
272 char buffer[SSH_READ_BLOCK_SIZE];
274 /* read from stdin until data are available */
275 while (ssh_channel_is_open(channel) && !ssh_channel_is_eof(channel)) {
276 nbytes = ssh_channel_read(channel, buffer, SSH_READ_BLOCK_SIZE, 0);
277 if (nbytes < 0) {
278 ws_warning("Error reading from channel");
279 goto end;
281 if (nbytes == 0) {
282 break;
284 if (fwrite(buffer, 1, nbytes, fp) != (unsigned)nbytes) {
285 ws_warning("Error writing to fifo");
286 ret = EXIT_FAILURE;
287 goto end;
289 fflush(fp);
292 /* read loop finished... maybe something wrong happened. Read from stderr */
293 while (ssh_channel_is_open(channel) && !ssh_channel_is_eof(channel)) {
294 nbytes = ssh_channel_read(channel, buffer, SSH_READ_BLOCK_SIZE, 1);
295 if (nbytes < 0) {
296 ws_warning("Error reading from channel");
297 goto end;
299 if (fwrite(buffer, 1, nbytes, stderr) != (unsigned)nbytes) {
300 ws_warning("Error writing to stderr");
301 break;
305 end:
306 if (ssh_channel_send_eof(channel) != SSH_OK) {
307 ws_warning("Error sending EOF in ssh channel");
308 ret = EXIT_FAILURE;
310 return ret;
313 static ssh_channel run_ssh_command(ssh_session sshs, const char* capture_functions,
314 const char* iface, const uint16_t channel_frequency, const uint16_t channel_width,
315 const uint16_t center_frequency, const char* cfilter, const uint32_t count)
317 char* cmdline;
318 ssh_channel channel;
319 char* quoted_iface = NULL;
320 char* quoted_filter = NULL;
321 char* count_str = NULL;
322 unsigned int remote_port = 22;
324 channel = ssh_channel_new(sshs);
325 if (!channel) {
326 ws_warning("Can't create channel");
327 return NULL;
330 if (ssh_channel_open_session(channel) != SSH_OK) {
331 ws_warning("Can't open session");
332 ssh_channel_free(channel);
333 return NULL;
336 ssh_options_get_port(sshs, &remote_port);
338 quoted_iface = iface ? g_shell_quote(iface) : NULL;
339 quoted_filter = g_shell_quote(cfilter ? cfilter : "");
340 cmdline = ws_strdup_printf("%s capture %s %u %u %u %u %s",
341 capture_functions,
342 quoted_iface ? quoted_iface : "auto",
343 channel_frequency,
344 channel_width,
345 center_frequency,
346 count,
347 quoted_filter);
349 ws_debug("Running: %s", cmdline);
350 if (ssh_channel_request_exec(channel, cmdline) != SSH_OK) {
351 ws_warning("Can't request exec");
352 ssh_channel_close(channel);
353 ssh_channel_free(channel);
354 channel = NULL;
357 g_free(quoted_iface);
358 g_free(quoted_filter);
359 g_free(cmdline);
360 g_free(count_str);
362 return channel;
365 static int ssh_open_remote_connection(const ssh_params_t* params, const char* capture_functions,
366 const char* iface, const uint16_t channel_frequency, const uint16_t channel_width,
367 const uint16_t center_frequency, const char* cfilter, const uint32_t count, const char* fifo)
369 ssh_session sshs = NULL;
370 ssh_channel channel = NULL;
371 FILE* fp = stdout;
372 int ret = EXIT_FAILURE;
373 char* err_info = NULL;
375 if (g_strcmp0(fifo, "-")) {
376 /* Open or create the output file */
377 fp = fopen(fifo, "wb");
378 if (fp == NULL) {
379 ws_warning("Error creating output file: %s (%s)", fifo, g_strerror(errno));
380 return EXIT_FAILURE;
384 sshs = create_ssh_connection(params, &err_info);
386 if (!sshs) {
387 ws_warning("Error creating connection.");
388 goto cleanup;
391 channel = run_ssh_command(sshs, capture_functions, iface, channel_frequency,
392 channel_width, center_frequency, cfilter, count);
394 if (!channel) {
395 ws_warning("Can't run ssh command.");
396 goto cleanup;
399 /* read from channel and write into fp */
400 if (ssh_loop_read(channel, fp) != EXIT_SUCCESS) {
401 ws_warning("Error in read loop.");
402 ret = EXIT_FAILURE;
403 goto cleanup;
406 ret = EXIT_SUCCESS;
407 cleanup:
408 if (err_info)
409 ws_warning("%s", err_info);
410 g_free(err_info);
412 /* clean up and exit */
413 ssh_cleanup(&sshs, &channel);
415 if (g_strcmp0(fifo, "-"))
416 fclose(fp);
417 return ret;
420 static int list_config(char *interface)
422 unsigned inc = 0;
423 int i, psc;
425 if (!interface) {
426 ws_warning("ERROR: No interface specified.");
427 return EXIT_FAILURE;
430 if (g_strcmp0(interface, wifidump_extcap_interface)) {
431 ws_warning("ERROR: interface must be %s", wifidump_extcap_interface);
432 return EXIT_FAILURE;
435 // Server tab
436 printf("arg {number=%u}{call=--remote-host}{display=Remote SSH server address}"
437 "{type=string}{tooltip=The remote SSH host. It can be both "
438 "an IP address or a hostname}{required=true}{group=Server}\n", inc++);
439 printf("arg {number=%u}{call=--remote-port}{display=Remote SSH server port}"
440 "{type=unsigned}{tooltip=The remote SSH host port (1-65535)}"
441 "{range=1,65535}{group=Server}\n", inc++);
443 // Authentication tab
444 printf("arg {number=%u}{call=--remote-username}{display=Remote SSH server username}"
445 "{type=string}{tooltip=The remote SSH username. If not provided, "
446 "the current user will be used}{group=Authentication}\n", inc++);
447 printf("arg {number=%u}{call=--remote-password}{display=Remote SSH server password}"
448 "{type=password}{tooltip=The SSH password, used when other methods (SSH agent "
449 "or key files) are unavailable.}{group=Authentication}\n", inc++);
450 printf("arg {number=%u}{call=--sshkey}{display=Path to SSH private key}"
451 "{type=fileselect}{tooltip=The path on the local filesystem of the private ssh key}"
452 "{mustexist=true}{group=Authentication}\n", inc++);
453 printf("arg {number=%u}{call=--sshkey-passphrase}{display=SSH key passphrase}"
454 "{type=password}{tooltip=Passphrase to unlock the SSH private key}{group=Authentication}\n",
455 inc++);
456 printf("arg {number=%u}{call=--ssh-sha1}{display=Support SHA-1 keys (deprecated)}"
457 "{type=boolflag}{tooltip=Support keys and key exchange algorithms using SHA-1 (deprecated)}{group=Authentication}"
458 "\n", inc++);
461 // Capture tab
462 printf("arg {number=%u}{call=--remote-interface}{display=Remote interface}"
463 "{type=string}{tooltip=The remote network interface used to capture"
464 "}{default=auto}{group=Capture}\n", inc++);
465 printf("arg {number=%u}{call=--remote-channel-frequency}{display=Remote channel}"
466 "{type=selector}{tooltip=The remote channel used to capture}{group=Capture}\n", inc);
468 unsigned int freq = 0;
469 for (i = 0; (freq = wifi_freqs_2dot4_5ghz[i]); i++) {
470 printf("value {arg=%u}{value=%u}{display=%s, Channel %u}\n", inc, freq, freq_to_band(freq), freq_to_channel(freq));
473 for (freq = 5955, psc = 3; freq <= 7115; freq += 20, psc++) {
474 printf("value {arg=%u}{value=%u}{display=%s, Channel %u%s}\n", inc, freq,
475 freq_to_band(freq), freq_to_channel(freq), (psc % 4 == 0) ? " (PSC)" : "");
477 inc++;
479 printf("arg {number=%u}{call=--remote-channel-width}{display=Remote channel width}"
480 "{type=selector}{tooltip=The remote channel width used to capture}"
481 "{group=Capture}\n", inc);
482 printf("value {arg=%u}{value=20}{display=20 MHz}\n", inc);
483 printf("value {arg=%u}{value=40}{display=40 MHz}\n", inc);
484 printf("value {arg=%u}{value=80}{display=80 MHz}\n", inc);
485 printf("value {arg=%u}{value=160}{display=160 MHz}\n", inc);
486 inc++;
488 printf("arg {number=%u}{call=--remote-filter}{display=Remote capture filter}{type=string}"
489 "{tooltip=The remote capture filter}{group=Capture}\n", inc++);
490 printf("arg {number=%u}{call=--remote-count}{display=Frames to capture}"
491 "{type=unsigned}{tooltip=The number of remote frames to capture.}"
492 "{group=Capture}\n", inc++);
494 extcap_config_debug(&inc);
496 return EXIT_SUCCESS;
499 static char* concat_filters(const char* extcap_filter, const char* remote_filter)
501 if (!extcap_filter && remote_filter)
502 return g_strdup(remote_filter);
504 if (!remote_filter && extcap_filter)
505 return g_strdup(extcap_filter);
507 if (!remote_filter && !extcap_filter)
508 return NULL;
510 return ws_strdup_printf("(%s) and (%s)", extcap_filter, remote_filter);
513 int main(int argc, char *argv[])
515 char* err_msg;
516 int result;
517 int option_idx = 0;
518 ssh_params_t* ssh_params = ssh_params_new();
519 char* remote_interface = NULL;
520 uint16_t remote_channel_frequency = 0;
521 uint16_t remote_channel_width = 0;
522 uint16_t remote_center_frequency = 0;
523 char* remote_filter = NULL;
524 uint32_t count = 0;
525 int ret = EXIT_FAILURE;
526 extcap_parameters* extcap_conf = g_new0(extcap_parameters, 1);
527 char* help_url;
528 char* help_header = NULL;
529 char* interface_description = g_strdup("Wi-Fi remote capture");
531 /* Set the program name. */
532 g_set_prgname("wifidump");
534 /* Initialize log handler early so we can have proper logging during startup. */
535 extcap_log_init();
537 wifidump_extcap_interface = g_path_get_basename(argv[0]);
538 if (g_str_has_suffix(wifidump_extcap_interface, ".exe")) {
539 wifidump_extcap_interface[strlen(wifidump_extcap_interface) - 4] = '\0';
543 * Get credential information for later use.
545 init_process_policies();
548 * Attempt to get the pathname of the directory containing the
549 * executable file.
551 err_msg = configuration_init(argv[0]);
552 if (err_msg != NULL) {
553 ws_warning("Can't get pathname of directory containing the extcap program: %s.",
554 err_msg);
555 g_free(err_msg);
558 help_url = data_file_url("wifidump.html");
559 extcap_base_set_util_info(extcap_conf, argv[0], WIFIDUMP_VERSION_MAJOR, WIFIDUMP_VERSION_MINOR,
560 WIFIDUMP_VERSION_RELEASE, help_url);
561 g_free(help_url);
562 add_libssh_info(extcap_conf);
563 if (g_strcmp0(wifidump_extcap_interface, DEFAULT_WIFIDUMP_EXTCAP_INTERFACE)) {
564 char* temp = interface_description;
565 interface_description = ws_strdup_printf("%s, custom version", interface_description);
566 g_free(temp);
568 extcap_base_register_interface(extcap_conf, wifidump_extcap_interface, interface_description, 147, "Remote capture dependent DLT");
569 g_free(interface_description);
571 help_header = ws_strdup_printf(
572 " %s --extcap-interfaces\n"
573 " %s --extcap-interface=%s --extcap-dlts\n"
574 " %s --extcap-interface=%s --extcap-config\n"
575 " %s --extcap-interface=%s --remote-host myhost --remote-port 22222 "
576 "--remote-username myuser --remote-interface wlan0 --remote-channel-frequency 5180 "
577 "--remote-channel-width 40 --fifo=FILENAME --capture\n", argv[0], argv[0], wifidump_extcap_interface, argv[0],
578 wifidump_extcap_interface, argv[0], wifidump_extcap_interface);
579 extcap_help_add_header(extcap_conf, help_header);
580 g_free(help_header);
581 extcap_help_add_option(extcap_conf, "--help", "print this help");
582 extcap_help_add_option(extcap_conf, "--version", "print the version");
583 extcap_help_add_option(extcap_conf, "--remote-host <host>", "the remote SSH host");
584 extcap_help_add_option(extcap_conf, "--remote-port <port>", "the remote SSH port");
585 extcap_help_add_option(extcap_conf, "--remote-username <username>", "the remote SSH username");
586 extcap_help_add_option(extcap_conf, "--remote-password <password>", "the remote SSH password. If not specified, ssh-agent and ssh-key are used");
587 extcap_help_add_option(extcap_conf, "--sshkey <public key path>", "the path of the ssh key");
588 extcap_help_add_option(extcap_conf, "--sshkey-passphrase <public key passphrase>", "the passphrase to unlock public ssh");
589 extcap_help_add_option(extcap_conf, "--ssh-sha1", "support keys and key exchange using SHA-1 (deprecated)");
590 extcap_help_add_option(extcap_conf, "--remote-interface <iface>", "the remote capture interface");
591 extcap_help_add_option(extcap_conf, "--remote-channel-frequency <channel_frequency>", "the remote channel frequency in MHz");
592 extcap_help_add_option(extcap_conf, "--remote-channel-width <channel_width>", "the remote channel width in MHz");
593 extcap_help_add_option(extcap_conf, "--remote-filter <filter>", "a filter for remote capture");
594 extcap_help_add_option(extcap_conf, "--remote-count <count>", "the number of frames to capture");
596 ws_opterr = 0;
597 ws_optind = 0;
599 if (argc == 1) {
600 extcap_help_print(extcap_conf);
601 goto end;
604 while ((result = ws_getopt_long(argc, argv, ":", longopts, &option_idx)) != -1) {
606 switch (result) {
608 case OPT_HELP:
609 extcap_help_print(extcap_conf);
610 ret = EXIT_SUCCESS;
611 goto end;
613 case OPT_VERSION:
614 extcap_version_print(extcap_conf);
615 ret = EXIT_SUCCESS;
616 goto end;
618 case OPT_REMOTE_HOST:
619 g_free(ssh_params->host);
620 ssh_params->host = g_strdup(ws_optarg);
621 break;
623 case OPT_REMOTE_PORT:
624 if (!ws_strtou16(ws_optarg, NULL, &ssh_params->port) || ssh_params->port == 0) {
625 ws_warning("Invalid port: %s", ws_optarg);
626 goto end;
628 break;
630 case OPT_REMOTE_USERNAME:
631 g_free(ssh_params->username);
632 ssh_params->username = g_strdup(ws_optarg);
633 break;
635 case OPT_REMOTE_PASSWORD:
636 g_free(ssh_params->password);
637 ssh_params->password = g_strdup(ws_optarg);
638 memset(ws_optarg, 'X', strlen(ws_optarg));
639 break;
641 case OPT_SSHKEY:
642 g_free(ssh_params->sshkey_path);
643 ssh_params->sshkey_path = g_strdup(ws_optarg);
644 break;
646 case OPT_SSHKEY_PASSPHRASE:
647 g_free(ssh_params->sshkey_passphrase);
648 ssh_params->sshkey_passphrase = g_strdup(ws_optarg);
649 memset(ws_optarg, 'X', strlen(ws_optarg));
650 break;
652 case OPT_SSH_SHA1:
653 ssh_params->ssh_sha1 = true;
654 break;
656 case OPT_REMOTE_INTERFACE:
657 g_free(remote_interface);
658 remote_interface = g_strdup(ws_optarg);
659 break;
661 case OPT_REMOTE_CHANNEL_FREQUENCY:
662 if (!ws_strtou16(ws_optarg, NULL, &remote_channel_frequency)) {
663 ws_warning("Invalid channel frequency: %s", ws_optarg);
664 goto end;
666 break;
668 case OPT_REMOTE_CHANNEL_WIDTH:
669 if (!ws_strtou16(ws_optarg, NULL, &remote_channel_width)) {
670 ws_warning("Invalid channel width: %s", ws_optarg);
671 goto end;
673 break;
675 case OPT_REMOTE_FILTER:
676 g_free(remote_filter);
677 remote_filter = g_strdup(ws_optarg);
678 break;
680 case OPT_REMOTE_COUNT:
681 if (!ws_strtou32(ws_optarg, NULL, &count)) {
682 ws_warning("Invalid value for count: %s", ws_optarg);
683 goto end;
685 break;
687 case ':':
688 /* missing option argument */
689 ws_warning("Option '%s' requires an argument", argv[ws_optind - 1]);
690 break;
692 default:
693 if (!extcap_base_parse_options(extcap_conf, result - EXTCAP_OPT_LIST_INTERFACES, ws_optarg)) {
694 ws_warning("Invalid option: %s", argv[ws_optind - 1]);
695 goto end;
700 extcap_cmdline_debug(argv, argc);
702 if (extcap_base_handle_interface(extcap_conf)) {
703 ret = EXIT_SUCCESS;
704 goto end;
707 if (extcap_conf->show_config) {
708 ret = list_config(extcap_conf->interface);
709 goto end;
712 err_msg = ws_init_sockets();
713 if (err_msg != NULL) {
714 ws_warning("ERROR: %s", err_msg);
715 g_free(err_msg);
716 ws_warning("%s", please_report_bug());
717 goto end;
720 if (extcap_conf->capture) {
721 char* filter;
723 if (!ssh_params->host) {
724 ws_warning("Missing parameter: --remote-host");
725 goto end;
727 remote_center_frequency = center_freq(remote_channel_frequency, remote_channel_width);
728 filter = concat_filters(extcap_conf->capture_filter, remote_filter);
729 ssh_params_set_log_level(ssh_params, extcap_conf->debug);
730 ret = ssh_open_remote_connection(ssh_params, remote_capture_functions,
731 remote_interface, remote_channel_frequency, remote_channel_width, remote_center_frequency,
732 filter, count, extcap_conf->fifo);
733 g_free(filter);
734 } else {
735 ws_debug("You should not come here... maybe some parameter missing?");
736 ret = EXIT_FAILURE;
739 end:
740 /* clean up stuff */
741 ssh_params_free(ssh_params);
742 g_free(remote_interface);
743 g_free(remote_filter);
744 extcap_base_cleanup(&extcap_conf);
745 return ret;
749 * Editor modelines - https://www.wireshark.org/tools/modelines.html
751 * Local variables:
752 * c-basic-offset: 8
753 * tab-width: 8
754 * indent-tabs-mode: t
755 * End:
757 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
758 * :indentSize=8:tabSize=8:noTabs=false: