LATER... ei_kerberos_kdc_session_key ...
[wireshark-sm.git] / extcap / wifidump.c
blob57a9c07a7e86493815ff8f5a1e1dfc49fe33f265
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 #ifdef _WIN32
36 #define DEFAULT_WIFIDUMP_EXTCAP_INTERFACE "wifidump.exe"
37 #else
38 #define DEFAULT_WIFIDUMP_EXTCAP_INTERFACE "wifidump"
39 #endif
41 #define WIFIDUMP_VERSION_MAJOR "1"
42 #define WIFIDUMP_VERSION_MINOR "0"
43 #define WIFIDUMP_VERSION_RELEASE "0"
45 #define SSH_READ_BLOCK_SIZE 256
47 enum {
48 EXTCAP_BASE_OPTIONS_ENUM,
49 OPT_HELP,
50 OPT_VERSION,
51 OPT_REMOTE_HOST,
52 OPT_REMOTE_PORT,
53 OPT_REMOTE_USERNAME,
54 OPT_REMOTE_PASSWORD,
55 OPT_REMOTE_INTERFACE,
56 OPT_REMOTE_CHANNEL_FREQUENCY,
57 OPT_REMOTE_CHANNEL_WIDTH,
58 OPT_REMOTE_FILTER,
59 OPT_SSHKEY,
60 OPT_SSHKEY_PASSPHRASE,
61 OPT_PROXYCOMMAND,
62 OPT_SSH_SHA1,
63 OPT_REMOTE_COUNT
66 static const struct ws_option longopts[] = {
67 EXTCAP_BASE_OPTIONS,
68 { "help", ws_no_argument, NULL, OPT_HELP},
69 { "version", ws_no_argument, NULL, OPT_VERSION},
70 SSH_BASE_OPTIONS,
71 { "remote-channel-frequency", ws_required_argument, NULL, OPT_REMOTE_CHANNEL_FREQUENCY},
72 { "remote-channel-width", ws_required_argument, NULL, OPT_REMOTE_CHANNEL_WIDTH},
73 { 0, 0, 0, 0}
76 static const char * remote_capture_functions =
77 "\n"
78 "function iface_down {\n"
79 " local iface=$1\n"
80 " sudo ip link set $iface down > /dev/null 2>&1\n"
81 "}\n"
82 "\n"
83 "function iface_up {\n"
84 " local iface=$1\n"
85 " sudo ip link set $iface up > /dev/null 2>&1\n"
86 "}\n"
87 "\n"
88 "function iface_monitor {\n"
89 " local iface=$1\n"
90 " sudo iw dev $iface set monitor control otherbss > /dev/null 2>&1 ||\n"
91 " sudo iw dev $iface set type monitor control otherbss > /dev/null 2>&1\n"
92 "}\n"
93 "\n"
94 "function iface_scan {\n"
95 " local iface=$1\n"
96 " iface_down $iface &&\n"
97 " sudo iw dev $iface set type managed > /dev/null 2>&1 &&\n"
98 " iface_up $iface &&\n"
99 " sudo iw dev $iface scan > /dev/null 2>&1\n"
100 "}\n"
101 "\n"
102 "function iface_config {\n"
103 " local iface=$1\n"
104 " local freq=$2\n"
105 " local ch_width=$3\n"
106 " local center_freq=$4\n"
107 " if [ $freq -eq $center_freq ]; then\n"
108 " sudo iw dev $1 set freq $freq $ch_width 2>&1\n"
109 " else\n"
110 " sudo iw dev $1 set freq $freq $ch_width $center_freq 2>&1\n"
111 " fi\n"
112 "}\n"
113 "\n"
114 "function iface_start {\n"
115 " local iface=$1\n"
116 " local count=$2\n"
117 " local filter=\"${@:3}\"\n"
118 " if [ $count -gt 0 ]; then\n"
119 " sudo tcpdump -i $iface -U -w - -c $count $filter\n"
120 " else\n"
121 " sudo tcpdump -i $iface -U -w - $filter\n"
122 " fi\n"
123 "}\n"
124 "\n"
125 "function capture_generic {\n"
126 " local iface=$1\n"
127 " local freq=$2\n"
128 " local ch_width=$3\n"
129 " local center_freq=$4\n"
130 " local count=$5\n"
131 " local filter=\"${@:6}\"\n"
132 " if ! { iwconfig $iface | grep Monitor > /dev/null 2>&1; }; then\n"
133 " iface_down $iface &&\n"
134 " iface_monitor $iface &&\n"
135 " iface_up $iface\n"
136 " else\n"
137 " iface_monitor $iface\n"
138 " fi\n"
139 " iface_config $iface $freq $ch_width $center_freq &&\n"
140 " iface_start $iface $count $filter\n"
141 "}\n"
142 "\n"
143 "function capture_iwlwifi {\n"
144 " local iface=$1\n"
145 " local freq=$2\n"
146 " local ch_width=$3\n"
147 " local center_freq=$4\n"
148 " local count=$5\n"
149 " local filter=\"${@:6}\"\n"
150 " INDEX=`sudo iw dev $iface info | grep wiphy | grep -Eo '[0-9]+'`\n"
151 " sudo iw phy phy${INDEX} channels | grep $freq | grep -i disabled > /dev/null 2>&1 &&\n"
152 " iface_scan $iface\n"
153 " MON=${iface}mon\n"
154 " sudo iw $iface interface add $MON type monitor flags none > /dev/null 2>&1\n"
155 " iface_up $MON &&\n"
156 " iface_down $iface &&\n"
157 " iface_config $MON $freq $ch_width $center_freq &&\n"
158 " iface_start $MON $count $filter\n"
159 "}\n"
160 "\n"
161 "function capture {\n"
162 " local iface=$1\n"
163 " local freq=$2\n"
164 " local ch_width=$3\n"
165 " local center_freq=$4\n"
166 " local count=$5\n"
167 " local filter=\"${@:6}\"\n"
168 " if [ \"$iface\" == \"auto\" ]; then\n"
169 " iface=`sudo iw dev | grep -i interface | awk '{ print $2 }' | sort | head -n 1`\n"
170 " fi\n"
171 " local driver=`/usr/sbin/ethtool -i $iface | grep driver | awk '{ print $2 }'`\n"
172 " if [ $driver = \"iwlwifi\" ]; then\n"
173 " capture_iwlwifi $iface $freq $ch_width $center_freq $count $filter\n"
174 " else\n"
175 " capture_generic $iface $freq $ch_width $center_freq $count $filter\n"
176 " fi\n"
177 "}\n"
178 "\n";
180 static unsigned int wifi_freqs_2dot4_5ghz[] = {
181 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
182 2467, 2472, 2484,
183 5180, 5200, 5220, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, 5580,
184 5600, 5620, 5640, 5660, 5680, 5700, 5720, 5745, 5765, 5785, 5805, 5825,
188 static unsigned int freq_to_channel(unsigned int freq_mhz) {
189 if (freq_mhz == 2484)
190 return 14;
191 else if (freq_mhz >= 2412 && freq_mhz <= 2484)
192 return ((freq_mhz - 2412) / 5) + 1;
193 else if (freq_mhz >= 5160 && freq_mhz <= 5885)
194 return ((freq_mhz - 5180) / 5) + 36;
195 else if (freq_mhz >= 5955 && freq_mhz <= 7115)
196 return ((freq_mhz - 5955) / 5) + 1;
197 else
198 return 0;
201 static const char *freq_to_band(unsigned int freq_mhz)
203 if (freq_mhz >= 2412 && freq_mhz <= 2484)
204 return "2.4 GHz";
205 else if (freq_mhz >= 5160 && freq_mhz <= 5885)
206 return "5 GHz";
207 else if (freq_mhz >= 5955 && freq_mhz <= 7115)
208 return "6 GHz";
209 else
210 return NULL;
213 static unsigned int center_freq(unsigned int freq_mhz, unsigned int ch_width_mhz) {
215 unsigned int start_freq;
217 if (ch_width_mhz == 20) {
218 return freq_mhz;
220 else if (ch_width_mhz == 40) {
221 if (freq_mhz >= 5180 && freq_mhz <= 5720) {
222 for (start_freq = 5180; start_freq <= 5700; start_freq += ch_width_mhz) {
223 if (freq_mhz >= start_freq && freq_mhz <= (start_freq + 20))
224 return ((start_freq * 2) + 20) / 2;
227 else if (freq_mhz >= 5745 && freq_mhz <= 5765)
228 return 5755;
229 else if (freq_mhz >= 5785 && freq_mhz <= 5805)
230 return 5795;
231 else if (freq_mhz >= 5955 && freq_mhz <= 7095) {
232 for (start_freq = 5955; start_freq <= 7075; start_freq += ch_width_mhz) {
233 if (freq_mhz >= start_freq && freq_mhz <= (start_freq + 20))
234 return ((start_freq * 2) + 20) / 2;
238 else if (ch_width_mhz == 80) {
239 if (freq_mhz >= 5180 && freq_mhz <= 5660) {
240 for (start_freq = 5180; start_freq <= 5660; start_freq += ch_width_mhz) {
241 if (freq_mhz >= start_freq && freq_mhz <= (start_freq + 60))
242 return ((start_freq * 2) + 60) / 2;
245 else if (freq_mhz >= 5745 && freq_mhz <= 5805)
246 return 5775;
247 else if (freq_mhz >= 5955 && freq_mhz <= 7055) {
248 for (start_freq = 5955; start_freq <= 6995; start_freq += ch_width_mhz) {
249 if (freq_mhz >= start_freq && freq_mhz <= (start_freq + 60))
250 return ((start_freq * 2) + 60) / 2;
254 else if (ch_width_mhz == 160) {
255 if (freq_mhz >= 5180 && freq_mhz <= 5640) {
256 for (start_freq = 5180; start_freq <= 5500; start_freq += ch_width_mhz) {
257 if (freq_mhz >= start_freq && freq_mhz <= (start_freq + 140))
258 return ((start_freq * 2) + 140) / 2;
261 else if (freq_mhz >= 5955 && freq_mhz <= 7055) {
262 for (start_freq = 5955; start_freq <= 6915; start_freq += ch_width_mhz) {
263 if (freq_mhz >= start_freq && freq_mhz <= (start_freq + 140))
264 return ((start_freq * 2) + 140) / 2;
269 return -1;
272 static int ssh_loop_read(ssh_channel channel, FILE* fp)
274 int nbytes;
275 int ret = EXIT_SUCCESS;
276 char buffer[SSH_READ_BLOCK_SIZE];
278 /* read from stdin until data are available */
279 while (ssh_channel_is_open(channel) && !ssh_channel_is_eof(channel)) {
280 nbytes = ssh_channel_read(channel, buffer, SSH_READ_BLOCK_SIZE, 0);
281 if (nbytes < 0) {
282 ws_warning("Error reading from channel");
283 goto end;
285 if (nbytes == 0) {
286 break;
288 if (fwrite(buffer, 1, nbytes, fp) != (unsigned)nbytes) {
289 ws_warning("Error writing to fifo");
290 ret = EXIT_FAILURE;
291 goto end;
293 fflush(fp);
296 /* read loop finished... maybe something wrong happened. Read from stderr */
297 while (ssh_channel_is_open(channel) && !ssh_channel_is_eof(channel)) {
298 nbytes = ssh_channel_read(channel, buffer, SSH_READ_BLOCK_SIZE, 1);
299 if (nbytes < 0) {
300 ws_warning("Error reading from channel");
301 goto end;
303 if (fwrite(buffer, 1, nbytes, stderr) != (unsigned)nbytes) {
304 ws_warning("Error writing to stderr");
305 break;
309 end:
310 if (ssh_channel_send_eof(channel) != SSH_OK) {
311 ws_warning("Error sending EOF in ssh channel");
312 ret = EXIT_FAILURE;
314 return ret;
317 static ssh_channel run_ssh_command(ssh_session sshs, const char* capture_functions,
318 const char* iface, const uint16_t channel_frequency, const uint16_t channel_width,
319 const uint16_t center_frequency, const char* cfilter, const uint32_t count)
321 char* cmdline;
322 ssh_channel channel;
323 char* quoted_iface = NULL;
324 char* quoted_filter = NULL;
325 char* count_str = NULL;
326 unsigned int remote_port = 22;
328 channel = ssh_channel_new(sshs);
329 if (!channel) {
330 ws_warning("Can't create channel");
331 return NULL;
334 if (ssh_channel_open_session(channel) != SSH_OK) {
335 ws_warning("Can't open session");
336 ssh_channel_free(channel);
337 return NULL;
340 ssh_options_get_port(sshs, &remote_port);
342 quoted_iface = iface ? g_shell_quote(iface) : NULL;
343 quoted_filter = g_shell_quote(cfilter ? cfilter : "");
344 cmdline = ws_strdup_printf("%s capture %s %u %u %u %u %s",
345 capture_functions,
346 quoted_iface ? quoted_iface : "auto",
347 channel_frequency,
348 channel_width,
349 center_frequency,
350 count,
351 quoted_filter);
353 ws_debug("Running: %s", cmdline);
354 if (ssh_channel_request_exec(channel, cmdline) != SSH_OK) {
355 ws_warning("Can't request exec");
356 ssh_channel_close(channel);
357 ssh_channel_free(channel);
358 channel = NULL;
361 g_free(quoted_iface);
362 g_free(quoted_filter);
363 g_free(cmdline);
364 g_free(count_str);
366 return channel;
369 static int ssh_open_remote_connection(const ssh_params_t* params, const char* capture_functions,
370 const char* iface, const uint16_t channel_frequency, const uint16_t channel_width,
371 const uint16_t center_frequency, const char* cfilter, const uint32_t count, const char* fifo)
373 ssh_session sshs = NULL;
374 ssh_channel channel = NULL;
375 FILE* fp = stdout;
376 int ret = EXIT_FAILURE;
377 char* err_info = NULL;
379 if (g_strcmp0(fifo, "-")) {
380 /* Open or create the output file */
381 fp = fopen(fifo, "wb");
382 if (fp == NULL) {
383 ws_warning("Error creating output file: %s (%s)", fifo, g_strerror(errno));
384 return EXIT_FAILURE;
388 sshs = create_ssh_connection(params, &err_info);
390 if (!sshs) {
391 ws_warning("Error creating connection.");
392 goto cleanup;
395 channel = run_ssh_command(sshs, capture_functions, iface, channel_frequency,
396 channel_width, center_frequency, cfilter, count);
398 if (!channel) {
399 ws_warning("Can't run ssh command.");
400 goto cleanup;
403 /* read from channel and write into fp */
404 if (ssh_loop_read(channel, fp) != EXIT_SUCCESS) {
405 ws_warning("Error in read loop.");
406 ret = EXIT_FAILURE;
407 goto cleanup;
410 ret = EXIT_SUCCESS;
411 cleanup:
412 if (err_info)
413 ws_warning("%s", err_info);
414 g_free(err_info);
416 /* clean up and exit */
417 ssh_cleanup(&sshs, &channel);
419 if (g_strcmp0(fifo, "-"))
420 fclose(fp);
421 return ret;
424 static int list_config(char *interface)
426 unsigned inc = 0;
427 int i, psc;
429 if (!interface) {
430 ws_warning("ERROR: No interface specified.");
431 return EXIT_FAILURE;
434 if (g_strcmp0(interface, wifidump_extcap_interface)) {
435 ws_warning("ERROR: interface must be %s", wifidump_extcap_interface);
436 return EXIT_FAILURE;
439 // Server tab
440 printf("arg {number=%u}{call=--remote-host}{display=Remote SSH server address}"
441 "{type=string}{tooltip=The remote SSH host. It can be both "
442 "an IP address or a hostname}{required=true}{group=Server}\n", inc++);
443 printf("arg {number=%u}{call=--remote-port}{display=Remote SSH server port}"
444 "{type=unsigned}{tooltip=The remote SSH host port (1-65535)}"
445 "{range=1,65535}{group=Server}\n", inc++);
447 // Authentication tab
448 printf("arg {number=%u}{call=--remote-username}{display=Remote SSH server username}"
449 "{type=string}{tooltip=The remote SSH username. If not provided, "
450 "the current user will be used}{group=Authentication}\n", inc++);
451 printf("arg {number=%u}{call=--remote-password}{display=Remote SSH server password}"
452 "{type=password}{tooltip=The SSH password, used when other methods (SSH agent "
453 "or key files) are unavailable.}{group=Authentication}\n", inc++);
454 printf("arg {number=%u}{call=--sshkey}{display=Path to SSH private key}"
455 "{type=fileselect}{tooltip=The path on the local filesystem of the private ssh key}"
456 "{mustexist=true}{group=Authentication}\n", inc++);
457 printf("arg {number=%u}{call=--sshkey-passphrase}{display=SSH key passphrase}"
458 "{type=password}{tooltip=Passphrase to unlock the SSH private key}{group=Authentication}\n",
459 inc++);
460 printf("arg {number=%u}{call=--ssh-sha1}{display=Support SHA-1 keys (deprecated)}"
461 "{type=boolflag}{tooltip=Support keys and key exchange algorithms using SHA-1 (deprecated)}{group=Authentication}"
462 "\n", inc++);
465 // Capture tab
466 printf("arg {number=%u}{call=--remote-interface}{display=Remote interface}"
467 "{type=string}{tooltip=The remote network interface used to capture"
468 "}{default=auto}{group=Capture}\n", inc++);
469 printf("arg {number=%u}{call=--remote-channel-frequency}{display=Remote channel}"
470 "{type=selector}{tooltip=The remote channel used to capture}{group=Capture}\n", inc);
472 unsigned int freq = 0;
473 for (i = 0; (freq = wifi_freqs_2dot4_5ghz[i]); i++) {
474 printf("value {arg=%u}{value=%u}{display=%s, Channel %u}\n", inc, freq, freq_to_band(freq), freq_to_channel(freq));
477 for (freq = 5955, psc = 3; freq <= 7115; freq += 20, psc++) {
478 printf("value {arg=%u}{value=%u}{display=%s, Channel %u%s}\n", inc, freq,
479 freq_to_band(freq), freq_to_channel(freq), (psc % 4 == 0) ? " (PSC)" : "");
481 inc++;
483 printf("arg {number=%u}{call=--remote-channel-width}{display=Remote channel width}"
484 "{type=selector}{tooltip=The remote channel width used to capture}"
485 "{group=Capture}\n", inc);
486 printf("value {arg=%u}{value=20}{display=20 MHz}\n", inc);
487 printf("value {arg=%u}{value=40}{display=40 MHz}\n", inc);
488 printf("value {arg=%u}{value=80}{display=80 MHz}\n", inc);
489 printf("value {arg=%u}{value=160}{display=160 MHz}\n", inc);
490 inc++;
492 printf("arg {number=%u}{call=--remote-filter}{display=Remote capture filter}{type=string}"
493 "{tooltip=The remote capture filter}{group=Capture}\n", inc++);
494 printf("arg {number=%u}{call=--remote-count}{display=Frames to capture}"
495 "{type=unsigned}{tooltip=The number of remote frames to capture.}"
496 "{group=Capture}\n", inc++);
498 extcap_config_debug(&inc);
500 return EXIT_SUCCESS;
503 static char* concat_filters(const char* extcap_filter, const char* remote_filter)
505 if (!extcap_filter && remote_filter)
506 return g_strdup(remote_filter);
508 if (!remote_filter && extcap_filter)
509 return g_strdup(extcap_filter);
511 if (!remote_filter && !extcap_filter)
512 return NULL;
514 return ws_strdup_printf("(%s) and (%s)", extcap_filter, remote_filter);
517 int main(int argc, char *argv[])
519 char* err_msg;
520 int result;
521 int option_idx = 0;
522 ssh_params_t* ssh_params = ssh_params_new();
523 char* remote_interface = NULL;
524 uint16_t remote_channel_frequency = 0;
525 uint16_t remote_channel_width = 0;
526 uint16_t remote_center_frequency = 0;
527 char* remote_filter = NULL;
528 uint32_t count = 0;
529 int ret = EXIT_FAILURE;
530 extcap_parameters* extcap_conf = g_new0(extcap_parameters, 1);
531 char* help_url;
532 char* help_header = NULL;
533 char* interface_description = g_strdup("Wi-Fi remote capture");
535 /* Initialize log handler early so we can have proper logging during startup. */
536 extcap_log_init("wifidump");
538 wifidump_extcap_interface = g_path_get_basename(argv[0]);
541 * Get credential information for later use.
543 init_process_policies();
546 * Attempt to get the pathname of the directory containing the
547 * executable file.
549 err_msg = configuration_init(argv[0], NULL);
550 if (err_msg != NULL) {
551 ws_warning("Can't get pathname of directory containing the extcap program: %s.",
552 err_msg);
553 g_free(err_msg);
556 help_url = data_file_url("wifidump.html");
557 extcap_base_set_util_info(extcap_conf, argv[0], WIFIDUMP_VERSION_MAJOR, WIFIDUMP_VERSION_MINOR,
558 WIFIDUMP_VERSION_RELEASE, help_url);
559 g_free(help_url);
560 add_libssh_info(extcap_conf);
561 if (g_strcmp0(wifidump_extcap_interface, DEFAULT_WIFIDUMP_EXTCAP_INTERFACE)) {
562 char* temp = interface_description;
563 interface_description = ws_strdup_printf("%s, custom version", interface_description);
564 g_free(temp);
566 extcap_base_register_interface(extcap_conf, wifidump_extcap_interface, interface_description, 147, "Remote capture dependent DLT");
567 g_free(interface_description);
569 help_header = ws_strdup_printf(
570 " %s --extcap-interfaces\n"
571 " %s --extcap-interface=%s --extcap-dlts\n"
572 " %s --extcap-interface=%s --extcap-config\n"
573 " %s --extcap-interface=%s --remote-host myhost --remote-port 22222 "
574 "--remote-username myuser --remote-interface wlan0 --remote-channel-frequency 5180 "
575 "--remote-channel-width 40 --fifo=FILENAME --capture\n", argv[0], argv[0], wifidump_extcap_interface, argv[0],
576 wifidump_extcap_interface, argv[0], wifidump_extcap_interface);
577 extcap_help_add_header(extcap_conf, help_header);
578 g_free(help_header);
579 extcap_help_add_option(extcap_conf, "--help", "print this help");
580 extcap_help_add_option(extcap_conf, "--version", "print the version");
581 extcap_help_add_option(extcap_conf, "--remote-host <host>", "the remote SSH host");
582 extcap_help_add_option(extcap_conf, "--remote-port <port>", "the remote SSH port");
583 extcap_help_add_option(extcap_conf, "--remote-username <username>", "the remote SSH username");
584 extcap_help_add_option(extcap_conf, "--remote-password <password>", "the remote SSH password. If not specified, ssh-agent and ssh-key are used");
585 extcap_help_add_option(extcap_conf, "--sshkey <public key path>", "the path of the ssh key");
586 extcap_help_add_option(extcap_conf, "--sshkey-passphrase <public key passphrase>", "the passphrase to unlock public ssh");
587 extcap_help_add_option(extcap_conf, "--ssh-sha1", "support keys and key exchange using SHA-1 (deprecated)");
588 extcap_help_add_option(extcap_conf, "--remote-interface <iface>", "the remote capture interface");
589 extcap_help_add_option(extcap_conf, "--remote-channel-frequency <channel_frequency>", "the remote channel frequency in MHz");
590 extcap_help_add_option(extcap_conf, "--remote-channel-width <channel_width>", "the remote channel width in MHz");
591 extcap_help_add_option(extcap_conf, "--remote-filter <filter>", "a filter for remote capture");
592 extcap_help_add_option(extcap_conf, "--remote-count <count>", "the number of frames to capture");
594 ws_opterr = 0;
595 ws_optind = 0;
597 if (argc == 1) {
598 extcap_help_print(extcap_conf);
599 goto end;
602 while ((result = ws_getopt_long(argc, argv, ":", longopts, &option_idx)) != -1) {
604 switch (result) {
606 case OPT_HELP:
607 extcap_help_print(extcap_conf);
608 ret = EXIT_SUCCESS;
609 goto end;
611 case OPT_VERSION:
612 extcap_version_print(extcap_conf);
613 ret = EXIT_SUCCESS;
614 goto end;
616 case OPT_REMOTE_HOST:
617 g_free(ssh_params->host);
618 ssh_params->host = g_strdup(ws_optarg);
619 break;
621 case OPT_REMOTE_PORT:
622 if (!ws_strtou16(ws_optarg, NULL, &ssh_params->port) || ssh_params->port == 0) {
623 ws_warning("Invalid port: %s", ws_optarg);
624 goto end;
626 break;
628 case OPT_REMOTE_USERNAME:
629 g_free(ssh_params->username);
630 ssh_params->username = g_strdup(ws_optarg);
631 break;
633 case OPT_REMOTE_PASSWORD:
634 g_free(ssh_params->password);
635 ssh_params->password = g_strdup(ws_optarg);
636 memset(ws_optarg, 'X', strlen(ws_optarg));
637 break;
639 case OPT_SSHKEY:
640 g_free(ssh_params->sshkey_path);
641 ssh_params->sshkey_path = g_strdup(ws_optarg);
642 break;
644 case OPT_SSHKEY_PASSPHRASE:
645 g_free(ssh_params->sshkey_passphrase);
646 ssh_params->sshkey_passphrase = g_strdup(ws_optarg);
647 memset(ws_optarg, 'X', strlen(ws_optarg));
648 break;
650 case OPT_SSH_SHA1:
651 ssh_params->ssh_sha1 = true;
652 break;
654 case OPT_REMOTE_INTERFACE:
655 g_free(remote_interface);
656 remote_interface = g_strdup(ws_optarg);
657 break;
659 case OPT_REMOTE_CHANNEL_FREQUENCY:
660 if (!ws_strtou16(ws_optarg, NULL, &remote_channel_frequency)) {
661 ws_warning("Invalid channel frequency: %s", ws_optarg);
662 goto end;
664 break;
666 case OPT_REMOTE_CHANNEL_WIDTH:
667 if (!ws_strtou16(ws_optarg, NULL, &remote_channel_width)) {
668 ws_warning("Invalid channel width: %s", ws_optarg);
669 goto end;
671 break;
673 case OPT_REMOTE_FILTER:
674 g_free(remote_filter);
675 remote_filter = g_strdup(ws_optarg);
676 break;
678 case OPT_REMOTE_COUNT:
679 if (!ws_strtou32(ws_optarg, NULL, &count)) {
680 ws_warning("Invalid value for count: %s", ws_optarg);
681 goto end;
683 break;
685 case ':':
686 /* missing option argument */
687 ws_warning("Option '%s' requires an argument", argv[ws_optind - 1]);
688 break;
690 default:
691 if (!extcap_base_parse_options(extcap_conf, result - EXTCAP_OPT_LIST_INTERFACES, ws_optarg)) {
692 ws_warning("Invalid option: %s", argv[ws_optind - 1]);
693 goto end;
698 extcap_cmdline_debug(argv, argc);
700 if (extcap_base_handle_interface(extcap_conf)) {
701 ret = EXIT_SUCCESS;
702 goto end;
705 if (extcap_conf->show_config) {
706 ret = list_config(extcap_conf->interface);
707 goto end;
710 err_msg = ws_init_sockets();
711 if (err_msg != NULL) {
712 ws_warning("ERROR: %s", err_msg);
713 g_free(err_msg);
714 ws_warning("%s", please_report_bug());
715 goto end;
718 if (extcap_conf->capture) {
719 char* filter;
721 if (!ssh_params->host) {
722 ws_warning("Missing parameter: --remote-host");
723 goto end;
725 remote_center_frequency = center_freq(remote_channel_frequency, remote_channel_width);
726 filter = concat_filters(extcap_conf->capture_filter, remote_filter);
727 ssh_params_set_log_level(ssh_params, extcap_conf->debug);
728 ret = ssh_open_remote_connection(ssh_params, remote_capture_functions,
729 remote_interface, remote_channel_frequency, remote_channel_width, remote_center_frequency,
730 filter, count, extcap_conf->fifo);
731 g_free(filter);
732 } else {
733 ws_debug("You should not come here... maybe some parameter missing?");
734 ret = EXIT_FAILURE;
737 end:
738 /* clean up stuff */
739 ssh_params_free(ssh_params);
740 g_free(remote_interface);
741 g_free(remote_filter);
742 extcap_base_cleanup(&extcap_conf);
743 return ret;
747 * Editor modelines - https://www.wireshark.org/tools/modelines.html
749 * Local variables:
750 * c-basic-offset: 8
751 * tab-width: 8
752 * indent-tabs-mode: t
753 * End:
755 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
756 * :indentSize=8:tabSize=8:noTabs=false: