forked from osmocom/wireshark
extcap: add udpdump.
Udpdump is a generic UDP receiver that exports datagram in PCAP format. Change-Id: I52620a92b12530b6f9b5449c43e692663acdfc14 Reviewed-on: https://code.wireshark.org/review/17195 Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com> Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Roland Knall <rknall@gmail.com>
This commit is contained in:
parent
1cd3587b73
commit
47650d357e
|
@ -111,6 +111,7 @@ text2pcap
|
|||
tfshark
|
||||
tshark
|
||||
tvbtest
|
||||
udpdump
|
||||
wireshark
|
||||
wmem_test
|
||||
ylwrap
|
||||
|
|
|
@ -1399,6 +1399,7 @@ set(INSTALL_FILES
|
|||
${CMAKE_BINARY_DIR}/doc/AUTHORS-SHORT
|
||||
${CMAKE_BINARY_DIR}/doc/asn2deb.html
|
||||
${CMAKE_BINARY_DIR}/doc/androiddump.html
|
||||
${CMAKE_BINARY_DIR}/doc/udpdump.html
|
||||
${CMAKE_BINARY_DIR}/doc/capinfos.html
|
||||
${CMAKE_BINARY_DIR}/doc/captype.html
|
||||
${CMAKE_BINARY_DIR}/doc/ciscodump.html
|
||||
|
@ -2507,6 +2508,24 @@ elseif (BUILD_ciscodump)
|
|||
#message( WARNING "Cannot find libssh, cannot build ciscodump" )
|
||||
endif()
|
||||
|
||||
if(ENABLE_EXTCAP AND BUILD_udpdump)
|
||||
set(udpdump_LIBS
|
||||
${GLIB2_LIBRARIES}
|
||||
${CMAKE_DL_LIBS}
|
||||
${LIBEPAN_LIBS}
|
||||
writecap
|
||||
)
|
||||
set(udpdump_FILES
|
||||
extcap/udpdump.c
|
||||
extcap/extcap-base.c
|
||||
)
|
||||
|
||||
add_executable(udpdump WIN32 ${udpdump_FILES})
|
||||
set_extcap_executable_properties(udpdump)
|
||||
target_link_libraries(udpdump ${udpdump_LIBS})
|
||||
install(TARGETS udpdump RUNTIME DESTINATION ${EXTCAP_DIR})
|
||||
endif()
|
||||
|
||||
if(ENABLE_EXTCAP AND BUILD_randpktdump)
|
||||
set(randpktdump_LIBS
|
||||
randpkt_core
|
||||
|
@ -2589,6 +2608,7 @@ set(CLEAN_FILES
|
|||
${dftest_FILES}
|
||||
${randpkt_FILES}
|
||||
${randpktdump_FILES}
|
||||
${udpdump_FILES}
|
||||
${text2pcap_CLEAN_FILES}
|
||||
${mergecap_FILES}
|
||||
${capinfos_FILES}
|
||||
|
@ -2598,6 +2618,7 @@ set(CLEAN_FILES
|
|||
${androiddump_FILES}
|
||||
${sshdump_FILES}
|
||||
${ciscodump_FILES}
|
||||
${udpdump_FILES}
|
||||
)
|
||||
|
||||
if (WERROR_COMMON_FLAGS)
|
||||
|
|
|
@ -18,6 +18,7 @@ option(BUILD_androiddump "Build androiddump" ON)
|
|||
option(BUILD_sshdump "Build sshdump" ON)
|
||||
option(BUILD_ciscodump "Build ciscodump" ON)
|
||||
option(BUILD_randpktdump "Build randpktdump" ON)
|
||||
option(BUILD_udpdump "Build udpdump" ON)
|
||||
|
||||
option(DISABLE_WERROR "Do not treat warnings as errors" OFF)
|
||||
option(EXTCAP_ANDROIDDUMP_LIBPCAP "Build androiddump using libpcap" OFF)
|
||||
|
|
28
configure.ac
28
configure.ac
|
@ -2613,6 +2613,33 @@ fi
|
|||
AC_SUBST(randpktdump_bin)
|
||||
AC_SUBST(randpktdump_man)
|
||||
|
||||
dnl udpdump check
|
||||
AC_MSG_CHECKING(whether to build udpdump)
|
||||
|
||||
AC_ARG_ENABLE(udpdump,
|
||||
AC_HELP_STRING( [--enable-udpdump],
|
||||
[build udpdump @<:@default=yes@:>@]),
|
||||
[],[enable_udpdump=yes])
|
||||
|
||||
if test "x$have_extcap" != xyes; then
|
||||
AC_MSG_RESULT([no, extcap disabled])
|
||||
enable_udpdump=no
|
||||
elif test "x$enable_udpdump" = "xyes" ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
if test "x$enable_udpdump" = "xyes" ; then
|
||||
udpdump_bin="udpdump\$(EXEEXT)"
|
||||
udpdump_man="udpdump.1"
|
||||
else
|
||||
udpdump_bin=""
|
||||
udpdump_man=""
|
||||
fi
|
||||
AC_SUBST(udpdump_bin)
|
||||
AC_SUBST(udpdump_man)
|
||||
|
||||
AM_CONDITIONAL(ENABLE_STATIC, test x$enable_static = xyes)
|
||||
if test x$enable_static = xyes -a x$have_plugins = xyes
|
||||
then
|
||||
|
@ -2981,6 +3008,7 @@ echo " Build androiddump : $enable_androiddump"
|
|||
echo " Build sshdump : $enable_sshdump"
|
||||
echo " Build ciscodump : $enable_ciscodump"
|
||||
echo " Build randpktdump : $enable_randpktdump"
|
||||
echo " Build udpdump : $enable_udpdump"
|
||||
echo " Build echld : $have_echld"
|
||||
echo ""
|
||||
echo " Save files as pcap-ng by default : $enable_pcap_ng_default"
|
||||
|
|
|
@ -71,6 +71,7 @@ endif()
|
|||
|
||||
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/androiddump 1)
|
||||
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/asn2deb 1)
|
||||
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/udpdump 1)
|
||||
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/capinfos 1)
|
||||
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/captype 1)
|
||||
pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/dftest 1)
|
||||
|
@ -95,6 +96,7 @@ pod2manhtml(${CMAKE_CURRENT_SOURCE_DIR}/wireshark-filter 4)
|
|||
set(MAN1_INSTALL_FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/asn2deb.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/androiddump.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/udpdump.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/capinfos.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/captype.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ciscodump.1
|
||||
|
@ -123,6 +125,7 @@ set(MAN4_INSTALL_FILES
|
|||
set(HTML_INSTALL_FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/asn2deb.html
|
||||
${CMAKE_CURRENT_BINARY_DIR}/androiddump.html
|
||||
${CMAKE_CURRENT_BINARY_DIR}/udpdump.html
|
||||
${CMAKE_CURRENT_BINARY_DIR}/capinfos.html
|
||||
${CMAKE_CURRENT_BINARY_DIR}/captype.html
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ciscodump.html
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
|
||||
=head1 NAME
|
||||
|
||||
udpdump - Provide an UDP receiver that gets packets from network devices (like Aruba routers) and exports them in PCAP format.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<udpdump>
|
||||
S<[ B<--help> ]>
|
||||
S<[ B<--version> ]>
|
||||
S<[ B<--extcap-interfaces> ]>
|
||||
S<[ B<--extcap-dlts> ]>
|
||||
S<[ B<--extcap-interface>=E<lt>interfaceE<gt> ]>
|
||||
S<[ B<--extcap-config> ]>
|
||||
S<[ B<--capture> ]>
|
||||
S<[ B<--fifo>=E<lt>path to file or pipeE<gt> ]>
|
||||
S<[ B<--port>=E<lt>portE<gt> ]>
|
||||
S<[ B<--payload>=E<lt>typeE<gt> ]>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<udpdump> is a extcap tool that provides an UDP receiver that listens for exported datagrams coming from
|
||||
any source (like Aruba routers) and exports them in PCAP format. This provides the user two basic
|
||||
functionalities: the first one is to have a listener that prevents the localhost to send back an ICMP
|
||||
port-unreachable packet. The second one is to strip out the lower layers (layer 2, IP, UDP) that are useless
|
||||
(are used just as export vector). The format of the exported datagrams are EXPORTED_PDU, as specified in
|
||||
https://code.wireshark.org/review/gitweb?p=wireshark.git;a=blob;f=epan/exported_pdu.h;hb=refs/heads/master
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 4
|
||||
|
||||
=item --help
|
||||
|
||||
Print program arguments.
|
||||
|
||||
=item --version
|
||||
|
||||
Print program version.
|
||||
|
||||
=item --extcap-interfaces
|
||||
|
||||
List available interfaces.
|
||||
|
||||
=item --extcap-interface=E<lt>interfaceE<gt>
|
||||
|
||||
Use specified interfaces.
|
||||
|
||||
=item --extcap-dlts
|
||||
|
||||
List DLTs of specified interface.
|
||||
|
||||
=item --extcap-config
|
||||
|
||||
List configuration options of specified interface.
|
||||
|
||||
=item --capture
|
||||
|
||||
Start capturing from specified interface save saved it in place specified by --fifo.
|
||||
|
||||
=item --fifo=E<lt>path to file or pipeE<gt>
|
||||
|
||||
Save captured packet to file or send it through pipe.
|
||||
|
||||
=item --port=E<lt>portE<gt>
|
||||
|
||||
Set the listerner port. Port 5555 is the default.
|
||||
|
||||
=item --payload=E<lt>typeE<gt>
|
||||
|
||||
Set the payload of the exported PDU. Default: data.
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
To see program arguments:
|
||||
|
||||
udpdump --help
|
||||
|
||||
To see program version:
|
||||
|
||||
udpdump --version
|
||||
|
||||
To see interfaces:
|
||||
|
||||
udpdump --extcap-interfaces
|
||||
|
||||
Example output:
|
||||
interface {value=udpdump}{display=UDP Listener remote capture}
|
||||
|
||||
To see interface DLTs:
|
||||
|
||||
udpdump --extcap-interface=udpdump --extcap-dlts
|
||||
|
||||
Example output:
|
||||
dlt {number=252}{name=udpdump}{display=Exported PDUs}
|
||||
|
||||
To see interface configuration options:
|
||||
|
||||
udpdump --extcap-interface=udpdump --extcap-config
|
||||
|
||||
Example output:
|
||||
arg {number=0}{call=--port}{display=Listen port}{type=unsigned}{range=1,65535}{default=5555}{tooltip=The port the receiver listens on}
|
||||
|
||||
To capture:
|
||||
|
||||
udpdump --extcap-interface=randpkt --fifo=/tmp/randpkt.pcapng --capture
|
||||
|
||||
NOTE: To stop capturing CTRL+C/kill/terminate application.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
wireshark(1), tshark(1), dumpcap(1), extcap(4)
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
B<udpdump> is part of the B<Wireshark> distribution. The latest version
|
||||
of B<Wireshark> can be found at L<https://www.wireshark.org>.
|
||||
|
||||
HTML versions of the Wireshark project man pages are available at:
|
||||
L<https://www.wireshark.org/docs/man-pages>.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Original Author
|
||||
---------------
|
||||
Dario Lombardo <lomato[AT]gmail.com>
|
|
@ -33,9 +33,10 @@ extcap_PROGRAMS = \
|
|||
@androiddump_bin@ \
|
||||
@randpktdump_bin@ \
|
||||
@sshdump_bin@ \
|
||||
@ciscodump_bin@
|
||||
@ciscodump_bin@ \
|
||||
@udpdump_bin@
|
||||
|
||||
EXTRA_PROGRAMS = androiddump randpktdump sshdump ciscodump
|
||||
EXTRA_PROGRAMS = androiddump randpktdump sshdump ciscodump udpdump
|
||||
|
||||
androiddump_SOURCES = \
|
||||
androiddump.c \
|
||||
|
@ -106,6 +107,23 @@ ciscodump_LDADD = \
|
|||
@GLIB_LIBS@ \
|
||||
@LIBSSH_LIBS@
|
||||
|
||||
udpdump_SOURCES = \
|
||||
udpdump.c \
|
||||
extcap-base.c
|
||||
|
||||
if ENABLE_STATIC
|
||||
udpdump_LDFLAGS = -Wl,-static -all-static
|
||||
else
|
||||
udpdump_LDFLAGS = -export-dynamic
|
||||
endif
|
||||
|
||||
# Libraries and plugin flags with which to link udpdump.
|
||||
udpdump_LDADD = \
|
||||
../writecap/libwritecap.a \
|
||||
../wsutil/libwsutil.la \
|
||||
../epan/libwireshark.la \
|
||||
@GLIB_LIBS@
|
||||
|
||||
noinst_HEADERS = \
|
||||
extcap-base.h \
|
||||
ssh-base.h
|
||||
|
|
|
@ -0,0 +1,416 @@
|
|||
/* udpdump.c
|
||||
* udpdump is an extcap tool used to get packets exported from a source (like a network device or a GSMTAP producer) that
|
||||
* are dumped to a pcap file
|
||||
*
|
||||
* Copyright 2016, Dario Lombardo <lomato@gmail.com>
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <extcap/extcap-base.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include <writecap/pcapio.h>
|
||||
#include <wiretap/wtap.h>
|
||||
#include <epan/tvbuff.h>
|
||||
#include <epan/packet_info.h>
|
||||
#include <epan/exported_pdu.h>
|
||||
#include <wsutil/strtoi.h>
|
||||
#include <wsutil/inet_addr.h>
|
||||
|
||||
#define PCAP_SNAPLEN 0xffff
|
||||
|
||||
#define UDPDUMP_DEFAULT_PORT 5555
|
||||
|
||||
#define UDPDUMP_EXTCAP_INTERFACE "udpdump"
|
||||
#define UDPDUMP_VERSION_MAJOR "0"
|
||||
#define UDPDUMP_VERSION_MINOR "1"
|
||||
#define UDPDUMP_VERSION_RELEASE "0"
|
||||
|
||||
#define PKT_BUF_SIZE 65535
|
||||
|
||||
static gboolean run_loop = TRUE;
|
||||
|
||||
enum {
|
||||
EXTCAP_BASE_OPTIONS_ENUM,
|
||||
OPT_HELP,
|
||||
OPT_VERSION,
|
||||
OPT_PORT,
|
||||
OPT_PAYLOAD
|
||||
};
|
||||
|
||||
static struct option longopts[] = {
|
||||
EXTCAP_BASE_OPTIONS,
|
||||
/* Generic application options */
|
||||
{ "help", no_argument, NULL, OPT_HELP},
|
||||
{ "version", no_argument, NULL, OPT_VERSION},
|
||||
/* Interfaces options */
|
||||
{ "port", required_argument, NULL, OPT_PORT},
|
||||
{ "payload", required_argument, NULL, OPT_PAYLOAD},
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static int list_config(char *interface)
|
||||
{
|
||||
unsigned inc = 0;
|
||||
|
||||
if (!interface) {
|
||||
g_warning("No interface specified.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("arg {number=%u}{call=--port}{display=Listen port}"
|
||||
"{type=unsigned}{range=1,65535}{default=%u}{tooltip=The port the receiver listens on}\n",
|
||||
inc++, UDPDUMP_DEFAULT_PORT);
|
||||
printf("arg {number=%u}{call=--payload}{display=Payload type}"
|
||||
"{type=string}{default=data}{tooltip=The type used to describe the payload in the exported pdu format}\n",
|
||||
inc++);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int setup_listener(const guint16 port, int* sockfd)
|
||||
{
|
||||
int optval;
|
||||
struct sockaddr_in serveraddr;
|
||||
struct timeval timeout = { 1, 0 };
|
||||
|
||||
*sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (*sockfd < 0) {
|
||||
g_warning("Error opening socket: %s", strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
optval = 1;
|
||||
if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(int)) < 0) {
|
||||
g_warning("Can't set socket option SO_REUSEADDR: %s", strerror(errno));
|
||||
goto cleanup_setup_listener;
|
||||
}
|
||||
|
||||
if (setsockopt (*sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0) {
|
||||
g_warning("Can't set socket option SO_RCVTIMEO: %s", strerror(errno));
|
||||
goto cleanup_setup_listener;
|
||||
}
|
||||
|
||||
memset(&serveraddr, 0x0, sizeof(serveraddr));
|
||||
serveraddr.sin_family = AF_INET;
|
||||
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
serveraddr.sin_port = htons(port);
|
||||
|
||||
if (bind(*sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) {
|
||||
g_warning("Error on binding: %s", strerror(errno));
|
||||
goto cleanup_setup_listener;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
cleanup_setup_listener:
|
||||
closesocket(*sockfd);
|
||||
return EXIT_FAILURE;
|
||||
|
||||
}
|
||||
|
||||
static void exit_from_loop(int signo _U_)
|
||||
{
|
||||
g_warning("Exiting from main loop");
|
||||
run_loop = FALSE;
|
||||
}
|
||||
|
||||
static int setup_dumpfile(const char* fifo, FILE** fp)
|
||||
{
|
||||
guint64 bytes_written = 0;
|
||||
int err;
|
||||
|
||||
if (!g_strcmp0(fifo, "-")) {
|
||||
*fp = stdout;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
*fp = fopen(fifo, "w");
|
||||
if (!fp) {
|
||||
g_warning("Error creating output file: %s", g_strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!libpcap_write_file_header(*fp, 252, PCAP_SNAPLEN, FALSE, &bytes_written, &err)) {
|
||||
g_warning("Can't write pcap file header");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int dump_packet(const char* proto_name, const guint16 listenport, const char* buf,
|
||||
const ssize_t buflen, const struct sockaddr_in clientaddr, FILE* fp)
|
||||
{
|
||||
time_t curtime = time(NULL);
|
||||
guint64 bytes_written = 0;
|
||||
char srcaddr[INET_ADDRSTRLEN];
|
||||
int err;
|
||||
int ret = EXIT_SUCCESS;
|
||||
packet_info pinfo;
|
||||
char* mbuf;
|
||||
exp_pdu_data_t* exp_pdu_data;
|
||||
const uint32_t localhost = inet_addr("127.0.0.1");
|
||||
const exp_pdu_data_item_t* user_encap_exp_pdu_items[] = {
|
||||
&exp_pdu_data_src_ip,
|
||||
&exp_pdu_data_dst_ip,
|
||||
&exp_pdu_data_src_port,
|
||||
&exp_pdu_data_dst_port,
|
||||
NULL
|
||||
};
|
||||
|
||||
g_debug("Incoming packet from %s:%u, size: %lu", ws_inet_ntop4(&clientaddr.sin_addr.s_addr,
|
||||
srcaddr, INET_ADDRSTRLEN), ntohs(clientaddr.sin_port), buflen);
|
||||
|
||||
pinfo.net_src.type = AT_IPv4;
|
||||
pinfo.net_src.data = &clientaddr.sin_addr.s_addr;
|
||||
pinfo.net_dst.type = AT_IPv4;
|
||||
pinfo.net_dst.data = &localhost;
|
||||
pinfo.srcport = clientaddr.sin_port;
|
||||
pinfo.destport = listenport;
|
||||
|
||||
exp_pdu_data = export_pdu_create_tags(&pinfo, proto_name, EXP_PDU_TAG_PROTO_NAME, user_encap_exp_pdu_items);
|
||||
|
||||
mbuf = (char*)g_malloc(buflen + exp_pdu_data->tlv_buffer_len);
|
||||
|
||||
memcpy(mbuf, exp_pdu_data->tlv_buffer, exp_pdu_data->tlv_buffer_len);
|
||||
memcpy(mbuf + exp_pdu_data->tlv_buffer_len, buf, buflen);
|
||||
|
||||
if (!libpcap_write_packet(fp, curtime, (guint32)(curtime / 1000), (guint)buflen + exp_pdu_data->tlv_buffer_len,
|
||||
(guint)buflen + exp_pdu_data->tlv_buffer_len, mbuf, &bytes_written, &err)) {
|
||||
g_warning("Can't write packet");
|
||||
ret = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fflush(fp);
|
||||
|
||||
g_free(mbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void run_listener(const char* fifo, const guint16 port, const char* proto_name)
|
||||
{
|
||||
struct sockaddr_in clientaddr;
|
||||
int clientlen;
|
||||
int sockfd;
|
||||
char buf[PKT_BUF_SIZE];
|
||||
ssize_t buflen;
|
||||
FILE* fp;
|
||||
|
||||
if (signal(SIGINT, exit_from_loop) == SIG_ERR) {
|
||||
g_warning("Can't set signal handler");
|
||||
return;
|
||||
}
|
||||
|
||||
if (setup_dumpfile(fifo, &fp) == EXIT_FAILURE)
|
||||
return;
|
||||
|
||||
if (setup_listener(port, &sockfd) == EXIT_FAILURE)
|
||||
return;
|
||||
|
||||
g_debug("Listener running on port %u", port);
|
||||
|
||||
while(run_loop == TRUE) {
|
||||
memset(buf, 0x0, PKT_BUF_SIZE);
|
||||
|
||||
buflen = recvfrom(sockfd, buf, PKT_BUF_SIZE, 0, (struct sockaddr *)&clientaddr, &clientlen);
|
||||
if (buflen < 0) {
|
||||
switch(errno) {
|
||||
case EAGAIN:
|
||||
case EINTR:
|
||||
break;
|
||||
default:
|
||||
g_warning("Error in recvfrom: %s %d", strerror(errno), errno);
|
||||
run_loop = FALSE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (dump_packet(proto_name, port, buf, buflen, clientaddr, fp) == EXIT_FAILURE)
|
||||
run_loop = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
closesocket(sockfd);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int option_idx = 0;
|
||||
int result;
|
||||
guint16 port = 0;
|
||||
int ret = EXIT_FAILURE;
|
||||
extcap_parameters* extcap_conf = g_new0(extcap_parameters, 1);
|
||||
char* help_header = NULL;
|
||||
char* payload = NULL;
|
||||
char* port_msg = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
attach_parent_console();
|
||||
#endif /* _WIN32 */
|
||||
|
||||
extcap_base_set_util_info(extcap_conf, argv[0], UDPDUMP_VERSION_MAJOR, UDPDUMP_VERSION_MINOR,UDPDUMP_VERSION_RELEASE, NULL);
|
||||
extcap_base_register_interface(extcap_conf, UDPDUMP_EXTCAP_INTERFACE, "UDP Listener remote capture", 252, "Exported PDUs");
|
||||
|
||||
help_header = g_strdup_printf(
|
||||
" %s --extcap-interfaces\n"
|
||||
" %s --extcap-interface=%s --extcap-dlts\n"
|
||||
" %s --extcap-interface=%s --extcap-config\n"
|
||||
" %s --extcap-interface=%s --port 5555",
|
||||
argv[0], argv[0], UDPDUMP_EXTCAP_INTERFACE, argv[0], UDPDUMP_EXTCAP_INTERFACE, argv[0], UDPDUMP_EXTCAP_INTERFACE);
|
||||
extcap_help_add_header(extcap_conf, help_header);
|
||||
g_free(help_header);
|
||||
extcap_help_add_option(extcap_conf, "--help", "print this help");
|
||||
extcap_help_add_option(extcap_conf, "--version", "print the version");
|
||||
extcap_help_add_option(extcap_conf, "--verbose", "print more messages");
|
||||
port_msg = g_strdup_printf("the port to listens on. Default: %u", UDPDUMP_DEFAULT_PORT);
|
||||
extcap_help_add_option(extcap_conf, "--port <port>", port_msg);
|
||||
g_free(port_msg);
|
||||
|
||||
opterr = 0;
|
||||
optind = 0;
|
||||
|
||||
if (argc == 1) {
|
||||
extcap_help_print(extcap_conf);
|
||||
goto end;
|
||||
}
|
||||
|
||||
while ((result = getopt_long(argc, argv, ":", longopts, &option_idx)) != -1) {
|
||||
switch (result) {
|
||||
|
||||
case OPT_HELP:
|
||||
extcap_help_print(extcap_conf);
|
||||
ret = EXIT_SUCCESS;
|
||||
goto end;
|
||||
|
||||
case OPT_VERSION:
|
||||
printf("%s\n", extcap_conf->version);
|
||||
goto end;
|
||||
|
||||
case OPT_PORT:
|
||||
if (!ws_strtou16(optarg, &port)) {
|
||||
g_warning("Invalid port: %s", optarg);
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_PAYLOAD:
|
||||
g_free(payload);
|
||||
payload = g_strdup(optarg);
|
||||
break;
|
||||
|
||||
case ':':
|
||||
/* missing option argument */
|
||||
g_warning("Option '%s' requires an argument", argv[optind - 1]);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!extcap_base_parse_options(extcap_conf, result - EXTCAP_OPT_LIST_INTERFACES, optarg)) {
|
||||
g_warning("Invalid option: %s", argv[optind - 1]);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (optind != argc) {
|
||||
g_warning("Unexpected extra option: %s", argv[optind]);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (extcap_base_handle_interface(extcap_conf)) {
|
||||
ret = EXIT_SUCCESS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (extcap_conf->show_config) {
|
||||
ret = list_config(extcap_conf->interface);
|
||||
goto end;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
result = WSAStartup(MAKEWORD(1,1), &wsaData);
|
||||
if (result != 0) {
|
||||
g_warning("Error: WSAStartup failed with error: %d", result);
|
||||
goto end;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
if (port == 0)
|
||||
port = UDPDUMP_DEFAULT_PORT;
|
||||
|
||||
if (extcap_conf->capture)
|
||||
run_listener(extcap_conf->fifo, port, payload);
|
||||
|
||||
end:
|
||||
/* clean up stuff */
|
||||
extcap_base_cleanup(&extcap_conf);
|
||||
g_free(payload);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
int _stdcall
|
||||
WinMain (struct HINSTANCE__ *hInstance,
|
||||
struct HINSTANCE__ *hPrevInstance,
|
||||
char *lpszCmdLine,
|
||||
int nCmdShow)
|
||||
{
|
||||
return main(__argc, __argv);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
||||
* :indentSize=8:tabSize=8:noTabs=false:
|
||||
*/
|
Loading…
Reference in New Issue