From 42c2e655758dd305315042a1d24342a2ac5b9013 Mon Sep 17 00:00:00 2001 From: Nataliia Korop Date: Wed, 13 Dec 2023 09:35:34 +0100 Subject: [PATCH 01/13] Packet capture prototype --- abi/include/abi/ipc/interfaces.h | 2 + uspace/app/meson.build | 1 + uspace/app/pcapctl/doc/doxygroups.h | 4 + uspace/app/pcapctl/main.c | 100 ++++++++++++++ uspace/app/pcapctl/meson.build | 29 ++++ uspace/drv/nic/e1k/e1k.c | 19 ++- uspace/drv/nic/e1k/meson.build | 2 +- uspace/lib/c/include/ipc/services.h | 2 +- uspace/lib/meson.build | 1 + uspace/lib/pcap/doc/doxygoups.h | 3 + uspace/lib/pcap/include/pcap.h | 103 +++++++++++++++ uspace/lib/pcap/include/pcap_iface.h | 55 ++++++++ uspace/lib/pcap/include/pcapctl_dump.h | 58 ++++++++ uspace/lib/pcap/include/pcapdump_iface.h | 55 ++++++++ uspace/lib/pcap/meson.build | 34 +++++ uspace/lib/pcap/src/pcap.c | 119 +++++++++++++++++ uspace/lib/pcap/src/pcap_iface.c | 107 +++++++++++++++ uspace/lib/pcap/src/pcapctl_dump.c | 138 +++++++++++++++++++ uspace/lib/pcap/src/pcapdump_iface.c | 161 +++++++++++++++++++++++ uspace/srv/locsrv/locsrv.c | 2 + 20 files changed, 992 insertions(+), 3 deletions(-) create mode 100644 uspace/app/pcapctl/doc/doxygroups.h create mode 100644 uspace/app/pcapctl/main.c create mode 100644 uspace/app/pcapctl/meson.build create mode 100644 uspace/lib/pcap/doc/doxygoups.h create mode 100644 uspace/lib/pcap/include/pcap.h create mode 100644 uspace/lib/pcap/include/pcap_iface.h create mode 100644 uspace/lib/pcap/include/pcapctl_dump.h create mode 100644 uspace/lib/pcap/include/pcapdump_iface.h create mode 100644 uspace/lib/pcap/meson.build create mode 100644 uspace/lib/pcap/src/pcap.c create mode 100644 uspace/lib/pcap/src/pcap_iface.c create mode 100644 uspace/lib/pcap/src/pcapctl_dump.c create mode 100644 uspace/lib/pcap/src/pcapdump_iface.c diff --git a/abi/include/abi/ipc/interfaces.h b/abi/include/abi/ipc/interfaces.h index 2d76f8cce9..ab2157b286 100644 --- a/abi/include/abi/ipc/interfaces.h +++ b/abi/include/abi/ipc/interfaces.h @@ -200,6 +200,8 @@ typedef enum { FOURCC_COMPACT('w', 'm', 'g', 't') | IFACE_EXCHANGE_SERIALIZE, INTERFACE_WNDMGT_CB = FOURCC_COMPACT('w', 'm', 'g', 't') | IFACE_EXCHANGE_SERIALIZE | IFACE_MOD_CALLBACK, + INTERFACE_PCAP_CONTROL = + FOURCC_COMPACT('p', 'c', 't', 'l') | IFACE_EXCHANGE_SERIALIZE, } iface_t; #endif diff --git a/uspace/app/meson.build b/uspace/app/meson.build index 01c04f6d2f..2a9e1b64e5 100644 --- a/uspace/app/meson.build +++ b/uspace/app/meson.build @@ -70,6 +70,7 @@ apps = [ 'netecho', 'nic', 'nterm', + 'pcapctl', 'pci', 'ping', 'pkg', diff --git a/uspace/app/pcapctl/doc/doxygroups.h b/uspace/app/pcapctl/doc/doxygroups.h new file mode 100644 index 0000000000..64f848ec60 --- /dev/null +++ b/uspace/app/pcapctl/doc/doxygroups.h @@ -0,0 +1,4 @@ +/** @addtogroup pcapctl pcapctl + * @brief Dump network packets + * @ingroup apps + */ diff --git a/uspace/app/pcapctl/main.c b/uspace/app/pcapctl/main.c new file mode 100644 index 0000000000..4c81889bb5 --- /dev/null +++ b/uspace/app/pcapctl/main.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023 Nataliia Korop + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** @addtogroup pcapctl + * @{ + */ +/** @file pcapctl app + */ + +#include +#include +#include + +#include "pcapctl_dump.h" + +#define NAME "pcapctl" + +#define LOGGER(msg, ...) \ + fprintf(stderr, \ + "[PCAP %s:%d]: " msg "\n", \ + __FILE__, __LINE__, \ + ##__VA_ARGS__\ + ) + +pcapctl_sess_t sess; + +static void start_dumping(const char *name) +{ + pcapctl_dump_start(name, &sess); +} + +static void stop_dumping(void) +{ + pcapctl_dump_stop(&sess); +} + +static void usage(const char *progname) +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s start : Packets will be written to \n", progname); + fprintf(stderr, " %s stop: Dumping stops\n", progname); + +} + +int main(int argc, char *argv[]) +{ + if (argc < 2) { + usage(argv[0]); + return 1; + } else { + errno_t rc = pcapctl_dump_init(&sess); + if (rc != EOK) { + fprintf(stderr, "Error initializing ...\n"); + return 1; + } + if (str_cmp(argv[1], "start") == 0) { + if (argc != 3) { + usage(argv[0]); + return 1; + } + start_dumping(argv[2]); + } else if (str_cmp(argv[1], "stop") == 0) { + stop_dumping(); + fprintf(stdout, "Dumping was stopped\n"); + return EOK; + } else { + usage(argv[0]); + return 1; + } + } + return 0; +} + +/** @} + */ diff --git a/uspace/app/pcapctl/meson.build b/uspace/app/pcapctl/meson.build new file mode 100644 index 0000000000..e9d54819e1 --- /dev/null +++ b/uspace/app/pcapctl/meson.build @@ -0,0 +1,29 @@ +# +# Copyright (c) 2023 Nataliia Korop +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# - The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +deps = ['pcap'] +src = files('main.c') \ No newline at end of file diff --git a/uspace/drv/nic/e1k/e1k.c b/uspace/drv/nic/e1k/e1k.c index d436b18610..f6df102bb9 100644 --- a/uspace/drv/nic/e1k/e1k.c +++ b/uspace/drv/nic/e1k/e1k.c @@ -50,6 +50,8 @@ #include #include "e1k.h" +#include "pcapdump_iface.h" +#include "pcap_iface.h" #define NAME "e1k" #define E1000_DEFAULT_INTERRUPT_INTERVAL_USEC 250 @@ -173,6 +175,10 @@ typedef struct { /** Lock for EEPROM access */ fibril_mutex_t eeprom_lock; + + /** Interface for dumping packets */ + pcap_iface_t pcapdump; + } e1000_t; /** Global mutex for work with shared irq structure */ @@ -1188,6 +1194,8 @@ static void e1000_receive_frames(nic_t *nic) nic_frame_t *frame = nic_alloc_frame(nic, frame_size); if (frame != NULL) { memcpy(frame->data, e1000->rx_frame_virt[next_tail], frame_size); + pcapdump_packet(&e1000->pcapdump, frame->data, frame->size); + nic_received_frame(nic, frame); } else { ddf_msg(LVL_ERROR, "Memory allocation failed. Frame dropped."); @@ -2202,6 +2210,15 @@ errno_t e1000_dev_add(ddf_dev_t *dev) if (rc != EOK) goto err_add_to_cat; + errno_t pcap_rc = pcapdump_init(&e1000->pcapdump); + + if (pcap_rc != EOK) { + printf("Failed creating pcapdump port\n"); + } + rc = ddf_fun_add_to_category(fun, "pcap"); + if (rc != EOK) + goto err_add_to_cat; + return EOK; err_add_to_cat: @@ -2365,7 +2382,7 @@ static void e1000_send_frame(nic_t *nic, void *data, size_t size) } memcpy(e1000->tx_frame_virt[tdt], data, size); - + pcapdump_packet(&e1000->pcapdump, data, size); tx_descriptor_addr->phys_addr = PTR_TO_U64(e1000->tx_frame_phys[tdt]); tx_descriptor_addr->length = size; diff --git a/uspace/drv/nic/e1k/meson.build b/uspace/drv/nic/e1k/meson.build index 847cb2e8c7..d6980678f7 100644 --- a/uspace/drv/nic/e1k/meson.build +++ b/uspace/drv/nic/e1k/meson.build @@ -26,5 +26,5 @@ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -deps = [ 'nic' ] +deps = [ 'nic' , 'pcap' ] src = files('e1k.c') diff --git a/uspace/lib/c/include/ipc/services.h b/uspace/lib/c/include/ipc/services.h index 34ed1531f1..e10b592090 100644 --- a/uspace/lib/c/include/ipc/services.h +++ b/uspace/lib/c/include/ipc/services.h @@ -66,7 +66,7 @@ typedef enum { #define SERVICE_NAME_TCP "net/tcp" #define SERVICE_NAME_VBD "vbd" #define SERVICE_NAME_VOLSRV "volsrv" - +#define SERVICE_NAME_DUMPPCAP "dumppcap" #endif /** @} diff --git a/uspace/lib/meson.build b/uspace/lib/meson.build index 12cbb7c2ab..26d6653880 100644 --- a/uspace/lib/meson.build +++ b/uspace/lib/meson.build @@ -71,6 +71,7 @@ libs = [ 'math', 'minix', 'nettl', + 'pcap', 'pcm', 'pcut', 'pixconv', diff --git a/uspace/lib/pcap/doc/doxygoups.h b/uspace/lib/pcap/doc/doxygoups.h new file mode 100644 index 0000000000..fe5d716a84 --- /dev/null +++ b/uspace/lib/pcap/doc/doxygoups.h @@ -0,0 +1,3 @@ +/** @addtogroup libpcap libpcap + * @ingroup libs + */ diff --git a/uspace/lib/pcap/include/pcap.h b/uspace/lib/pcap/include/pcap.h new file mode 100644 index 0000000000..c9cf50f3af --- /dev/null +++ b/uspace/lib/pcap/include/pcap.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2023 Nataliia Korop + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @addtogroup libpcap + * @{ + */ +/** + * @file + * @brief Headers and functions for .pcap file and packets to be dumped + */ + +#ifndef PCAP_H_ +#define PCAP_H_ + +#include +#include +#include +#include +#include +#include + +#define PCAP_MAGIC_MICRO 0xA1B2C3D4 +#define PCAP_MAGIC_NANO 0xA1B23C4D +#define PCAP_MAJOR_VERSION 0x0002 +#define PCAP_MINOR_VERSION 0x0004 +#define PCAP_SNAP_LEN 0x00040000 + +#define PCAP_LINKTYPE_ETHERNET 1 /* IEEE 802.3 Ethernet*/ + +/** Header of the .pcap file + */ +typedef struct { + uint32_t magic_number; + uint16_t major_v; + uint16_t minor_v; + uint32_t reserved1; + uint32_t reserved2; + uint32_t snaplen; + uint32_t additional; /** The LinkType and additional information field is in the form */ +} __attribute__((packed, aligned(4))) pcap_file_header_t; + +typedef struct pcap_packet_header { + uint32_t seconds_stamp; + uint32_t magic_stamp; + uint32_t captured_length; + uint32_t original_length; +} pcap_packet_header_t; + +typedef struct pcap_writer pcap_writer_t; + +typedef struct { + size_t (*write_u32)(struct pcap_writer *, uint32_t); + size_t (*write_u16)(struct pcap_writer *, uint16_t); + size_t (*write_buffer)(struct pcap_writer *, const void *, size_t); + void (*close)(struct pcap_writer *); + +} pcap_writer_ops_t; + +/** Interface for working with .pcap file + */ +typedef struct pcap_writer { + void *data; + pcap_writer_ops_t *ops; +} pcap_writer_t; + +errno_t pcap_writer_to_file_init(pcap_writer_t *writer, const char *filename); + +extern void pcap_writer_add_header(pcap_writer_t *); +extern void pcap_writer_add_packet( + pcap_writer_t *writer, const void *captured_packet, size_t size); + +extern void pcap_set_time(pcap_packet_header_t *header, bool nano); + +#endif + +/** @} + */ diff --git a/uspace/lib/pcap/include/pcap_iface.h b/uspace/lib/pcap/include/pcap_iface.h new file mode 100644 index 0000000000..ca660a3922 --- /dev/null +++ b/uspace/lib/pcap/include/pcap_iface.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 Nataliia Korop + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** @addtogroup libpcap + * @{ + */ +/** @file pcap interface + */ + +#ifndef PCAP_IFACE_H_ +#define PCAP_IFACE_H_ + +#include +#include "pcap.h" + +typedef struct pcap_iface { + bool to_dump; + errno_t (*init)(const char *); + void (*add_packet)(const void *data, size_t size); + void (*fini)(void); +} pcap_iface_t; + +extern void pcap_close_file(void); +extern errno_t pcap_iface_init(pcap_iface_t *); +extern errno_t pcap_init(const char *); +extern void pcap_add_packet(const void *data, size_t size); + +#endif +/** @} + */ diff --git a/uspace/lib/pcap/include/pcapctl_dump.h b/uspace/lib/pcap/include/pcapctl_dump.h new file mode 100644 index 0000000000..0655c80814 --- /dev/null +++ b/uspace/lib/pcap/include/pcapctl_dump.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 Nataliia Korop + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @addtogroup libpcap + * @{ + */ +/** + * @file + * + */ + +#ifndef _PCAPCTL_DUMP_H_ +#define _PCAPCTL_DUMP_H_ + +#include +#include +#include +#include +#include + +typedef struct { + async_sess_t *sess; +} pcapctl_sess_t; + +extern errno_t pcapctl_dump_init(pcapctl_sess_t *); +extern errno_t pcapctl_dump_start(const char *, pcapctl_sess_t *); +extern errno_t pcapctl_dump_stop(pcapctl_sess_t *); + +#endif + +/** @} + */ diff --git a/uspace/lib/pcap/include/pcapdump_iface.h b/uspace/lib/pcap/include/pcapdump_iface.h new file mode 100644 index 0000000000..8192dc0fa2 --- /dev/null +++ b/uspace/lib/pcap/include/pcapdump_iface.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 Nataliia Korop + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @addtogroup libpcap + * @{ + */ +/** + * @file + * + */ + +#ifndef _PCAPDUMP_IFACE_H_ +#define _PCAPDUMP_IFACE_H_ + +#include +#include "pcap_iface.h" + +typedef enum { + PCAP_CONTROL_SET_START = IPC_FIRST_USER_METHOD, + PCAP_CONTROL_SET_STOP +} pcap_request_t; + +extern errno_t pcapdump_init(pcap_iface_t *); +extern void pcapdump_packet(pcap_iface_t *, const void *, size_t); + +#endif + +/** @} + */ diff --git a/uspace/lib/pcap/meson.build b/uspace/lib/pcap/meson.build new file mode 100644 index 0000000000..bb70637845 --- /dev/null +++ b/uspace/lib/pcap/meson.build @@ -0,0 +1,34 @@ +# +# Copyright (c) 2023 Nataliia Korop +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# - The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +src = files( + 'src/pcap.c', + 'src/pcap_iface.c', + 'src/pcapdump_iface.c', + 'src/pcapctl_dump.c', +) diff --git a/uspace/lib/pcap/src/pcap.c b/uspace/lib/pcap/src/pcap.c new file mode 100644 index 0000000000..8bca9a4283 --- /dev/null +++ b/uspace/lib/pcap/src/pcap.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2023 Nataliia Korop + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @addtogroup libpcap + * @{ + */ +/** + * @file + * @brief Headers and functions for .pcap file and packets to be dumped + */ + +#define LOGGER(msg, ...) \ + fprintf(stderr, \ + "[PCAP %s:%d]: " msg "\n", \ + __FILE__, __LINE__, \ + ##__VA_ARGS__\ + ) + +#include "pcap.h" + +/** Set time in seconds and microseconds for the packet header . + * + * @param header Header of the packet to be dumped. + * + */ +void pcap_set_time(pcap_packet_header_t *header, bool nano) // maybe without bool nano as nano is in pcapng +{ + time_t sec = time(NULL); + header->seconds_stamp = (uint32_t)sec; + header->magic_stamp = nano ? header->seconds_stamp / 1000000000 : header->seconds_stamp / 1000000; +} + +/** Add pcap file header to the new .pcap file. + * + * @param writer + * + */ +void pcap_writer_add_header(pcap_writer_t *writer) +{ + pcap_file_header_t file_header = { PCAP_MAGIC_MICRO, PCAP_MAJOR_VERSION, PCAP_MINOR_VERSION, + 0x00000000, 0x00000000, (uint32_t)PCAP_SNAP_LEN, (uint32_t)PCAP_LINKTYPE_ETHERNET }; + writer->ops->write_buffer(writer, &file_header, sizeof(file_header)); +} + +/** Add packet to the .pcap file. + * + * @param writer + * @param captured_packet Packet to be dumped + * @param size Size of the captured packet + * + */ +void pcap_writer_add_packet(pcap_writer_t *writer, const void *captured_packet, size_t size) +{ + if (!writer->data) + return; + pcap_packet_header_t pcap_packet; + pcap_set_time(&pcap_packet, false); + pcap_packet.original_length = (uint32_t)size; + + if (PCAP_SNAP_LEN < size) { + pcap_packet.captured_length = PCAP_SNAP_LEN; + } else { + pcap_packet.captured_length = size; + } + writer->ops->write_buffer(writer, &pcap_packet, sizeof(pcap_packet)); + writer->ops->write_buffer(writer, captured_packet, pcap_packet.captured_length); + +} + +/** Initialize writing to .pcap file. + * + * @param writer Interface for working with .pcap file + * @param filename Name of the file for dumping packets + * @return EOK on success or an error code + * + */ +errno_t pcap_writer_to_file_init(pcap_writer_t *writer, const char *filename) +{ + errno_t rc; + writer->data = fopen(filename, "a"); + if (writer->data == NULL) { + rc = EINVAL; + LOGGER("Failed to create %s: %s.", filename, str_error(rc)); + return rc; + } + pcap_writer_add_header(writer); + + rc = EOK; + return rc; +} + +/** @} + */ diff --git a/uspace/lib/pcap/src/pcap_iface.c b/uspace/lib/pcap/src/pcap_iface.c new file mode 100644 index 0000000000..e27b423dc3 --- /dev/null +++ b/uspace/lib/pcap/src/pcap_iface.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2023 Nataliia Korop + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** @addtogroup libpcap + * @{ + */ +/** @file + * @brief pcap inteface: Dumping interface for the device which packets we want to dump + */ + +#include +#include "pcap_iface.h" + +static size_t pcap_file_w32(pcap_writer_t *writer, uint32_t data) +{ + return fwrite(&data, 1, 4, (FILE *)writer->data); +} + +static size_t pcap_file_w16(pcap_writer_t *writer, uint16_t data) +{ + return fwrite(&data, 1, 2, (FILE *)writer->data); +} + +static size_t pcap_file_wbuffer(pcap_writer_t *writer, const void *data, size_t size) +{ + return fwrite(data, 1, size, (FILE *)writer->data); +} + +static void pcap_file_close(pcap_writer_t *writer) +{ + fclose((FILE *)writer->data); +} + +static pcap_writer_ops_t file_ops = { + + .write_u32 = &pcap_file_w32, + .write_u16 = &pcap_file_w16, + .write_buffer = &pcap_file_wbuffer, + .close = &pcap_file_close +}; + +static pcap_writer_t pcap_writer = { + .ops = &file_ops, +}; + +errno_t pcap_init(const char *name) +{ + errno_t rc = pcap_writer_to_file_init(&pcap_writer, name); + return rc; +} + +void pcap_add_packet(const void *data, size_t size) +{ + if (&pcap_writer.data == NULL) + return; + pcap_writer_add_packet(&pcap_writer, data, size); +} + +void pcap_close_file() +{ + pcap_writer.ops->close(&pcap_writer); + pcap_writer.data = NULL; +} + +/** Initialize interface for dumping packets + * + * @param iface Device dumping interface + * + */ +errno_t pcap_iface_init(pcap_iface_t *iface) +{ + + iface->to_dump = false; + iface->add_packet = pcap_add_packet; + iface->init = pcap_init; + iface->fini = pcap_close_file; + + return EOK; +} + +/** @} + */ diff --git a/uspace/lib/pcap/src/pcapctl_dump.c b/uspace/lib/pcap/src/pcapctl_dump.c new file mode 100644 index 0000000000..aa2ce69b6a --- /dev/null +++ b/uspace/lib/pcap/src/pcapctl_dump.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2023 Nataliia Korop + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** @addtogroup libpcap + * @{ + */ +/** @file + * @brief Client side of the pcapctl. Functions are called from the app pcapctl + */ + +#include +#include +#include +#include + +#include "pcapctl_dump.h" +#include "pcapdump_iface.h" + +/** Finish an async exchange on the pcapctl session + * + * @param exch Exchange to be finished + */ +static void pcapctl_dump_exchange_end(async_exch_t *exch) +{ + async_exchange_end(exch); +} + +errno_t pcapctl_dump_init(pcapctl_sess_t *sess) +{ + errno_t rc; + char *svc_name; + category_id_t pcap_cat; + size_t count; + service_id_t *pcap_svcs = NULL; + + rc = loc_category_get_id("pcap", &pcap_cat, 0); + if (rc != EOK) { + printf("Error resolving category 'pcap'.\n"); + return rc; + } + + rc = loc_category_get_svcs(pcap_cat, &pcap_svcs, &count); + if (rc != EOK) { + printf("Error resolving list of pcap services.\n"); + return rc; + } + assert((count > 0) && "TODO: not implemented when no services are available\n"); + + rc = loc_service_get_name(pcap_svcs[0], &svc_name); // Note: for now [0], because only one driver is in pcap_svcs and there is no need to find particular + if (rc != EOK) { + printf("Error getting service name.\n"); + goto error; + } + printf("Using device: %s\n", svc_name); + + async_sess_t *new_session = loc_service_connect(pcap_svcs[0], INTERFACE_PCAP_CONTROL, 0); + if (new_session == NULL) { + printf("Error connecting to service.\n"); + rc = EREFUSED; + goto error; + } + sess->sess = new_session; + rc = EOK; +error: + free(pcap_svcs); + return rc; +} + +/** Starting a new session for pcapctl + * + * @param name Name of the file to dump packets to + * @param sess session to start + * @return EOK on success or an error code + */ +errno_t pcapctl_dump_start(const char *name, pcapctl_sess_t *sess) +{ + errno_t rc; + async_exch_t *exch = async_exchange_begin(sess->sess); + + size_t size = str_size(name); + aid_t req = async_send_0(exch, PCAP_CONTROL_SET_START, NULL); + + rc = async_data_write_start(exch, (void *) name, size); + + pcapctl_dump_exchange_end(exch); + + if (rc != EOK) { + async_forget(req); + return rc; + } + + errno_t retval; + async_wait_for(req, &retval); + return retval; +} + +/** Finish current session for pcapctl + * + * @param sess Session to finish + * @return EOK on success or an error code + */ +errno_t pcapctl_dump_stop(pcapctl_sess_t *sess) +{ + errno_t rc; + async_exch_t *exch = async_exchange_begin(sess->sess); + rc = async_req_0_0(exch, PCAP_CONTROL_SET_STOP); + + pcapctl_dump_exchange_end(exch); + return rc; +} + +/** @} + */ diff --git a/uspace/lib/pcap/src/pcapdump_iface.c b/uspace/lib/pcap/src/pcapdump_iface.c new file mode 100644 index 0000000000..0696ad289e --- /dev/null +++ b/uspace/lib/pcap/src/pcapdump_iface.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2023 Nataliia Korop + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @addtogroup libpcap + * @{ + */ +/** + * @file + * @brief Server side of the pcapctl + */ + +#include +#include +#include + +#include "pcapdump_iface.h" + +FIBRIL_MUTEX_INITIALIZE(to_dump_mutex); + +static void pcapdump_start_srv(ipc_call_t *icall, pcap_iface_t *iface) +{ + char *data; + size_t size; + errno_t rc = async_data_write_accept((void **) &data, false, 0, 0, 0, &size); + if (rc != EOK) { + async_answer_0(icall, rc); + return; + } + + /** When try to start when already started, close current and starts new */ + if (iface->to_dump == true) { + iface->fini(); + } + iface->init((const char *)data); + + fibril_mutex_lock(&to_dump_mutex); + iface->to_dump = true; + fibril_mutex_unlock(&to_dump_mutex); + + async_answer_0(icall, rc); +} + +static void pcapdump_stop_srv(ipc_call_t *icall, pcap_iface_t *iface) +{ + /** If want to stop, when already stopped, do nothing */ + if (iface->to_dump == false) { + async_answer_0(icall, EOK); + return; + } + + fibril_mutex_lock(&to_dump_mutex); + iface->to_dump = false; + fibril_mutex_unlock(&to_dump_mutex); + + iface->fini(); + async_answer_0(icall, EOK); +} + +static void pcapdump_conn(ipc_call_t *icall, void *arg) +{ + pcap_iface_t *iface = (pcap_iface_t *)arg; + + assert((iface != NULL) && "pcapdump requires pcap interface\n"); + + /* Accept connection */ + async_accept_0(icall); + + while (true) { + ipc_call_t call; + async_get_call(&call); + sysarg_t method = ipc_get_imethod(&call); + if (!method) { + /* The other side has hung up */ + async_answer_0(&call, EOK); + break; + } + switch (method) { + case PCAP_CONTROL_SET_START: + pcapdump_start_srv(&call, iface); + break; + case PCAP_CONTROL_SET_STOP: + pcapdump_stop_srv(&call, iface); + break; + default: + async_answer_0(&call, EINVAL); + break; + } + } +} + +errno_t pcapdump_init(pcap_iface_t *iface) +{ + port_id_t port; + errno_t rc; + + rc = pcap_iface_init(iface); + + if (rc != EOK) { + printf("Failed creating pcap interface: %s", str_error(rc)); + return rc; + } + + rc = async_create_port(INTERFACE_PCAP_CONTROL, + pcapdump_conn, iface, &port); + if (rc != EOK) { + return rc; + } + return EOK; +} + +/** Dumping function for driver + * + * Called every time, the packet is sent/recieved by the device + * + * @param iface Dumping interface + * @param data The packet + * @param size Size of the packet + * + */ +void pcapdump_packet(pcap_iface_t *iface, const void *data, size_t size) +{ + + if (iface == NULL) { + return; + } + + if (!iface->to_dump) { + return; + } + + iface->add_packet(data, size); +} + +/** @} + */ diff --git a/uspace/srv/locsrv/locsrv.c b/uspace/srv/locsrv/locsrv.c index 08887be3ee..b905d9bf30 100644 --- a/uspace/srv/locsrv/locsrv.c +++ b/uspace/srv/locsrv/locsrv.c @@ -1389,6 +1389,8 @@ static bool loc_init(void) cat = category_new("pci"); categ_dir_add_cat(&cdir, cat); + cat = category_new("pcap"); + categ_dir_add_cat(&cdir, cat); return true; } From 6b66de6b108b38a0d63af69d44b15b654b6d0126 Mon Sep 17 00:00:00 2001 From: Nataliia Korop Date: Tue, 19 Dec 2023 15:05:46 +0100 Subject: [PATCH 02/13] pcapdump moved to nic_t struct --- uspace/drv/nic/e1k/e1k.c | 8 +++----- uspace/lib/nic/include/nic.h | 5 +++++ uspace/lib/nic/include/nic_driver.h | 5 +++++ uspace/lib/nic/meson.build | 2 +- uspace/lib/nic/src/nic_driver.c | 5 +++++ 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/uspace/drv/nic/e1k/e1k.c b/uspace/drv/nic/e1k/e1k.c index f6df102bb9..03445fe438 100644 --- a/uspace/drv/nic/e1k/e1k.c +++ b/uspace/drv/nic/e1k/e1k.c @@ -176,8 +176,6 @@ typedef struct { /** Lock for EEPROM access */ fibril_mutex_t eeprom_lock; - /** Interface for dumping packets */ - pcap_iface_t pcapdump; } e1000_t; @@ -1194,7 +1192,7 @@ static void e1000_receive_frames(nic_t *nic) nic_frame_t *frame = nic_alloc_frame(nic, frame_size); if (frame != NULL) { memcpy(frame->data, e1000->rx_frame_virt[next_tail], frame_size); - pcapdump_packet(&e1000->pcapdump, frame->data, frame->size); + pcapdump_packet(nic_get_pcap_iface(nic), frame->data, frame->size); nic_received_frame(nic, frame); } else { @@ -2210,7 +2208,7 @@ errno_t e1000_dev_add(ddf_dev_t *dev) if (rc != EOK) goto err_add_to_cat; - errno_t pcap_rc = pcapdump_init(&e1000->pcapdump); + errno_t pcap_rc = pcapdump_init(nic_get_pcap_iface(nic)); if (pcap_rc != EOK) { printf("Failed creating pcapdump port\n"); @@ -2382,7 +2380,7 @@ static void e1000_send_frame(nic_t *nic, void *data, size_t size) } memcpy(e1000->tx_frame_virt[tdt], data, size); - pcapdump_packet(&e1000->pcapdump, data, size); + pcapdump_packet(nic_get_pcap_iface(nic), data, size); tx_descriptor_addr->phys_addr = PTR_TO_U64(e1000->tx_frame_phys[tdt]); tx_descriptor_addr->length = size; diff --git a/uspace/lib/nic/include/nic.h b/uspace/lib/nic/include/nic.h index fe832c71d0..a7f71bffee 100644 --- a/uspace/lib/nic/include/nic.h +++ b/uspace/lib/nic/include/nic.h @@ -44,6 +44,8 @@ #include #include +#include "pcap_iface.h" + #define DEVICE_CATEGORY_NIC "nic" struct nic; @@ -277,6 +279,9 @@ extern uint64_t nic_query_mcast_hash(nic_t *); extern void nic_sw_period_start(nic_t *); extern void nic_sw_period_stop(nic_t *); +/* pcapdump interface */ +extern pcap_iface_t* nic_get_pcap_iface(nic_t *); + #endif // __NIC_H__ /** @} diff --git a/uspace/lib/nic/include/nic_driver.h b/uspace/lib/nic/include/nic_driver.h index 019741ab4f..378817b5b4 100644 --- a/uspace/lib/nic/include/nic_driver.h +++ b/uspace/lib/nic/include/nic_driver.h @@ -49,6 +49,7 @@ #include "nic.h" #include "nic_rx_control.h" #include "nic_wol_virtues.h" +#include "pcap/include/pcapdump_iface.h" struct sw_poll_info { fid_t fibril; @@ -194,6 +195,10 @@ struct nic { * The implementation is optional. */ poll_request_handler on_poll_request; + + /** Interface for dumping packets */ + pcap_iface_t pcapdump; + /** Data specific for particular driver */ void *specific; }; diff --git a/uspace/lib/nic/meson.build b/uspace/lib/nic/meson.build index 5241065dad..0ec1788cd8 100644 --- a/uspace/lib/nic/meson.build +++ b/uspace/lib/nic/meson.build @@ -26,7 +26,7 @@ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -deps = [ 'drv' ] +deps = [ 'drv' , 'pcap' ] c_args = [ '-DLIBNIC_INTERNAL', ] src = files( 'src/nic_driver.c', diff --git a/uspace/lib/nic/src/nic_driver.c b/uspace/lib/nic/src/nic_driver.c index ba11079988..8d39010338 100644 --- a/uspace/lib/nic/src/nic_driver.c +++ b/uspace/lib/nic/src/nic_driver.c @@ -1132,5 +1132,10 @@ void nic_sw_period_stop(nic_t *nic_data) nic_data->sw_poll_info.running = 0; } +pcap_iface_t* nic_get_pcap_iface(nic_t *nic_data) { + + return &nic_data->pcapdump; +} + /** @} */ From 86f862c6ac16a1b9ea22e6f4142c06d1049c9b6e Mon Sep 17 00:00:00 2001 From: Nataliia Korop Date: Mon, 19 Feb 2024 07:27:40 +0100 Subject: [PATCH 03/13] small typos and ccheck --- uspace/drv/nic/e1k/e1k.c | 1 - uspace/lib/nic/include/nic.h | 2 +- uspace/lib/nic/src/nic_driver.c | 4 ++-- uspace/lib/pcap/src/pcap.c | 7 ++++--- uspace/lib/pcap/src/pcap_iface.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/uspace/drv/nic/e1k/e1k.c b/uspace/drv/nic/e1k/e1k.c index 03445fe438..c34b31127d 100644 --- a/uspace/drv/nic/e1k/e1k.c +++ b/uspace/drv/nic/e1k/e1k.c @@ -176,7 +176,6 @@ typedef struct { /** Lock for EEPROM access */ fibril_mutex_t eeprom_lock; - } e1000_t; /** Global mutex for work with shared irq structure */ diff --git a/uspace/lib/nic/include/nic.h b/uspace/lib/nic/include/nic.h index a7f71bffee..d751e788ed 100644 --- a/uspace/lib/nic/include/nic.h +++ b/uspace/lib/nic/include/nic.h @@ -280,7 +280,7 @@ extern void nic_sw_period_start(nic_t *); extern void nic_sw_period_stop(nic_t *); /* pcapdump interface */ -extern pcap_iface_t* nic_get_pcap_iface(nic_t *); +extern pcap_iface_t *nic_get_pcap_iface(nic_t *); #endif // __NIC_H__ diff --git a/uspace/lib/nic/src/nic_driver.c b/uspace/lib/nic/src/nic_driver.c index 8d39010338..ea1878efde 100644 --- a/uspace/lib/nic/src/nic_driver.c +++ b/uspace/lib/nic/src/nic_driver.c @@ -1132,8 +1132,8 @@ void nic_sw_period_stop(nic_t *nic_data) nic_data->sw_poll_info.running = 0; } -pcap_iface_t* nic_get_pcap_iface(nic_t *nic_data) { - +pcap_iface_t *nic_get_pcap_iface(nic_t *nic_data) +{ return &nic_data->pcapdump; } diff --git a/uspace/lib/pcap/src/pcap.c b/uspace/lib/pcap/src/pcap.c index 8bca9a4283..1bd6e58ffa 100644 --- a/uspace/lib/pcap/src/pcap.c +++ b/uspace/lib/pcap/src/pcap.c @@ -51,9 +51,10 @@ */ void pcap_set_time(pcap_packet_header_t *header, bool nano) // maybe without bool nano as nano is in pcapng { - time_t sec = time(NULL); - header->seconds_stamp = (uint32_t)sec; - header->magic_stamp = nano ? header->seconds_stamp / 1000000000 : header->seconds_stamp / 1000000; + struct timespec ts; + getrealtime(&ts); + header->seconds_stamp = (uint32_t)ts.tv_sec; + header->magic_stamp = (uint32_t)ts.tv_nsec / 1000; } /** Add pcap file header to the new .pcap file. diff --git a/uspace/lib/pcap/src/pcap_iface.c b/uspace/lib/pcap/src/pcap_iface.c index e27b423dc3..b160f676b3 100644 --- a/uspace/lib/pcap/src/pcap_iface.c +++ b/uspace/lib/pcap/src/pcap_iface.c @@ -76,7 +76,7 @@ errno_t pcap_init(const char *name) void pcap_add_packet(const void *data, size_t size) { - if (&pcap_writer.data == NULL) + if (pcap_writer.data == NULL) return; pcap_writer_add_packet(&pcap_writer, data, size); } From 192019fb0f0f9643b1e1e705d014b5fe3f29d1e9 Mon Sep 17 00:00:00 2001 From: Nataliia Korop Date: Sat, 24 Feb 2024 20:54:31 +0100 Subject: [PATCH 04/13] framework added to virtio-net --- uspace/drv/nic/virtio-net/virtio-net.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/uspace/drv/nic/virtio-net/virtio-net.c b/uspace/drv/nic/virtio-net/virtio-net.c index b86572c6fb..3659ab80a6 100644 --- a/uspace/drv/nic/virtio-net/virtio-net.c +++ b/uspace/drv/nic/virtio-net/virtio-net.c @@ -42,7 +42,8 @@ #include #include - +#include "pcapdump_iface.h" +#include "pcap_iface.h" #define NAME "virtio-net" #define VIRTIO_NET_NUM_QUEUES 3 @@ -91,6 +92,7 @@ static void virtio_net_irq_handler(ipc_call_t *icall, ddf_dev_t *dev) nic_frame_t *frame = nic_alloc_frame(nic, len - sizeof(*hdr)); if (frame) { memcpy(frame->data, &hdr[1], len - sizeof(*hdr)); + pcapdump_packet(nic_get_pcap_iface(nic), frame->data, frame->size); nic_received_frame(nic, frame); } else { ddf_msg(LVL_WARN, @@ -350,7 +352,7 @@ static void virtio_net_send(nic_t *nic, void *data, size_t size) /* Copy packet data into the buffer just past the header */ memcpy(&hdr[1], data, size); - + pcapdump_packet(nic_get_pcap_iface(nic), data, size); /* * Set the descriptor, put it into the virtqueue and notify the device */ @@ -430,6 +432,15 @@ static errno_t virtio_net_dev_add(ddf_dev_t *dev) ddf_msg(LVL_NOTE, "The %s device has been successfully initialized.", ddf_dev_get_name(dev)); + errno_t pcap_rc = pcapdump_init(nic_get_pcap_iface(nic)); + + if (pcap_rc != EOK) { + printf("Failed creating pcapdump port\n"); + } + rc = ddf_fun_add_to_category(fun, "pcap"); + if (rc != EOK) + goto unbind; + return EOK; unbind: From 325ea9c6759c593c8c6e9e86ea7c6abf745f8801 Mon Sep 17 00:00:00 2001 From: Nataliia Korop Date: Mon, 4 Mar 2024 09:47:50 +0100 Subject: [PATCH 05/13] long name without mapping ok --- uspace/app/pcapctl/main.c | 48 +++++++++++++----- uspace/lib/pcap/include/pcapctl_dump.h | 3 +- uspace/lib/pcap/include/pcapdump_iface.h | 3 +- uspace/lib/pcap/src/pcapctl_dump.c | 63 +++++++++++++++++++----- 4 files changed, 91 insertions(+), 26 deletions(-) diff --git a/uspace/app/pcapctl/main.c b/uspace/app/pcapctl/main.c index 4c81889bb5..2a82cc80fd 100644 --- a/uspace/app/pcapctl/main.c +++ b/uspace/app/pcapctl/main.c @@ -49,21 +49,38 @@ pcapctl_sess_t sess; -static void start_dumping(const char *name) +static errno_t start_dumping(const char *drv_name, const char *name) { + errno_t rc = pcapctl_dump_init(&sess, drv_name); + if (rc != EOK) { + //fprintf(stderr, "Error initializing ...\n"); + return 1; + } pcapctl_dump_start(name, &sess); + return EOK; } -static void stop_dumping(void) +/** Session might */ +static errno_t stop_dumping(const char *drv_name) { + errno_t rc = pcapctl_dump_init(&sess, drv_name); + if (rc != EOK) { + fprintf(stderr, "Error initializing ...\n"); + return 1; + } pcapctl_dump_stop(&sess); + return EOK; +} + +static void list_devs(void) { + pcapctl_list(); } static void usage(const char *progname) { fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s start : Packets will be written to \n", progname); - fprintf(stderr, " %s stop: Dumping stops\n", progname); + fprintf(stderr, " %s start : Packets dumped from will be written to \n", progname); + fprintf(stderr, " %s stop : Dumping from stops\n", progname); } @@ -73,19 +90,24 @@ int main(int argc, char *argv[]) usage(argv[0]); return 1; } else { - errno_t rc = pcapctl_dump_init(&sess); - if (rc != EOK) { - fprintf(stderr, "Error initializing ...\n"); - return 1; - } - if (str_cmp(argv[1], "start") == 0) { - if (argc != 3) { + if (str_cmp(argv[1], "--help") == 0 || str_cmp(argv[1], "-h") == 0) { + usage(argv[0]); + return 0; + } else if (str_cmp(argv[1], "list") == 0) { + list_devs(); + return 0; + } else if (str_cmp(argv[1], "start") == 0) { + if (argc != 4) { usage(argv[0]); return 1; } - start_dumping(argv[2]); + start_dumping(argv[2], argv[3]); } else if (str_cmp(argv[1], "stop") == 0) { - stop_dumping(); + if (argc != 3) { + usage(argv[0]); + return 1; + } + stop_dumping(argv[2]); fprintf(stdout, "Dumping was stopped\n"); return EOK; } else { diff --git a/uspace/lib/pcap/include/pcapctl_dump.h b/uspace/lib/pcap/include/pcapctl_dump.h index 0655c80814..09e926f386 100644 --- a/uspace/lib/pcap/include/pcapctl_dump.h +++ b/uspace/lib/pcap/include/pcapctl_dump.h @@ -48,9 +48,10 @@ typedef struct { async_sess_t *sess; } pcapctl_sess_t; -extern errno_t pcapctl_dump_init(pcapctl_sess_t *); +extern errno_t pcapctl_dump_init(pcapctl_sess_t *, const char *); extern errno_t pcapctl_dump_start(const char *, pcapctl_sess_t *); extern errno_t pcapctl_dump_stop(pcapctl_sess_t *); +extern errno_t pcapctl_list(void); #endif diff --git a/uspace/lib/pcap/include/pcapdump_iface.h b/uspace/lib/pcap/include/pcapdump_iface.h index 8192dc0fa2..8d64211652 100644 --- a/uspace/lib/pcap/include/pcapdump_iface.h +++ b/uspace/lib/pcap/include/pcapdump_iface.h @@ -43,7 +43,8 @@ typedef enum { PCAP_CONTROL_SET_START = IPC_FIRST_USER_METHOD, - PCAP_CONTROL_SET_STOP + PCAP_CONTROL_SET_STOP, + PCAP_CONTROL_GET_NAME } pcap_request_t; extern errno_t pcapdump_init(pcap_iface_t *); diff --git a/uspace/lib/pcap/src/pcapctl_dump.c b/uspace/lib/pcap/src/pcapctl_dump.c index aa2ce69b6a..be842065a1 100644 --- a/uspace/lib/pcap/src/pcapctl_dump.c +++ b/uspace/lib/pcap/src/pcapctl_dump.c @@ -50,10 +50,8 @@ static void pcapctl_dump_exchange_end(async_exch_t *exch) async_exchange_end(exch); } -errno_t pcapctl_dump_init(pcapctl_sess_t *sess) -{ +static errno_t pcapctl_cat_has_drv(const char *drv_name, service_id_t* svc) { errno_t rc; - char *svc_name; category_id_t pcap_cat; size_t count; service_id_t *pcap_svcs = NULL; @@ -69,25 +67,68 @@ errno_t pcapctl_dump_init(pcapctl_sess_t *sess) printf("Error resolving list of pcap services.\n"); return rc; } - assert((count > 0) && "TODO: not implemented when no services are available\n"); - rc = loc_service_get_name(pcap_svcs[0], &svc_name); // Note: for now [0], because only one driver is in pcap_svcs and there is no need to find particular + for (unsigned i = 0; i < count; ++i) { + char *name = NULL; + loc_service_get_name(pcap_svcs[i], &name); + if (!str_cmp(drv_name, name)) { + *svc = pcap_svcs[i]; + return EOK; + } + } + free(pcap_svcs); + return 1; +} + +extern errno_t pcapctl_list(void) { + + errno_t rc; + category_id_t pcap_cat; + size_t count; + service_id_t *pcap_svcs = NULL; + + rc = loc_category_get_id("pcap", &pcap_cat, 0); if (rc != EOK) { - printf("Error getting service name.\n"); - goto error; + printf("Error resolving category 'pcap'.\n"); + return rc; } - printf("Using device: %s\n", svc_name); - async_sess_t *new_session = loc_service_connect(pcap_svcs[0], INTERFACE_PCAP_CONTROL, 0); + rc = loc_category_get_svcs(pcap_cat, &pcap_svcs, &count); + if (rc != EOK) { + printf("Error resolving list of pcap services.\n"); + return rc; + } + + assert((count > 0) && "TODO: not implemented when no services are available\n"); + + fprintf(stdout, "Drivers:\n"); + for (unsigned i = 0; i < count; ++i) { + char *name = NULL; + loc_service_get_name(pcap_svcs[i], &name); + + fprintf(stdout, "driver: %s\n", name); + } + return EOK; +} + +errno_t pcapctl_dump_init(pcapctl_sess_t *sess, const char *drv_name) +{ + errno_t rc; + service_id_t svc; + rc = pcapctl_cat_has_drv(drv_name, &svc); + if (rc != EOK) { + fprintf(stderr, "No such driver was found.\n"); + return 1; + } + async_sess_t *new_session = loc_service_connect(svc, INTERFACE_PCAP_CONTROL, 0); if (new_session == NULL) { - printf("Error connecting to service.\n"); + fprintf(stderr, "Error connecting to service.\n"); rc = EREFUSED; goto error; } sess->sess = new_session; rc = EOK; error: - free(pcap_svcs); return rc; } From 6eab537d3c916127b5583625be8f310525b6a341 Mon Sep 17 00:00:00 2001 From: Nataliia Korop Date: Sun, 10 Mar 2024 10:38:44 +0100 Subject: [PATCH 06/13] moved to nic, fixed all except addressing --- uspace/app/pcapctl/main.c | 7 ------- uspace/drv/nic/e1k/e1k.c | 14 ++++---------- uspace/drv/nic/virtio-net/virtio-net.c | 16 ++++++---------- uspace/lib/nic/include/nic.h | 3 +-- uspace/lib/nic/src/nic_driver.c | 8 ++++++++ uspace/lib/nic/src/nic_impl.c | 3 ++- uspace/lib/pcap/include/pcap.h | 2 +- uspace/lib/pcap/src/pcap.c | 8 -------- uspace/lib/pcap/src/pcap_iface.c | 2 +- 9 files changed, 23 insertions(+), 40 deletions(-) diff --git a/uspace/app/pcapctl/main.c b/uspace/app/pcapctl/main.c index 4c81889bb5..e1f441a679 100644 --- a/uspace/app/pcapctl/main.c +++ b/uspace/app/pcapctl/main.c @@ -40,13 +40,6 @@ #define NAME "pcapctl" -#define LOGGER(msg, ...) \ - fprintf(stderr, \ - "[PCAP %s:%d]: " msg "\n", \ - __FILE__, __LINE__, \ - ##__VA_ARGS__\ - ) - pcapctl_sess_t sess; static void start_dumping(const char *name) diff --git a/uspace/drv/nic/e1k/e1k.c b/uspace/drv/nic/e1k/e1k.c index c34b31127d..5b9d02837b 100644 --- a/uspace/drv/nic/e1k/e1k.c +++ b/uspace/drv/nic/e1k/e1k.c @@ -48,10 +48,9 @@ #include #include #include +#include #include "e1k.h" -#include "pcapdump_iface.h" -#include "pcap_iface.h" #define NAME "e1k" #define E1000_DEFAULT_INTERRUPT_INTERVAL_USEC 250 @@ -1191,7 +1190,6 @@ static void e1000_receive_frames(nic_t *nic) nic_frame_t *frame = nic_alloc_frame(nic, frame_size); if (frame != NULL) { memcpy(frame->data, e1000->rx_frame_virt[next_tail], frame_size); - pcapdump_packet(nic_get_pcap_iface(nic), frame->data, frame->size); nic_received_frame(nic, frame); } else { @@ -2207,14 +2205,11 @@ errno_t e1000_dev_add(ddf_dev_t *dev) if (rc != EOK) goto err_add_to_cat; - errno_t pcap_rc = pcapdump_init(nic_get_pcap_iface(nic)); - - if (pcap_rc != EOK) { - printf("Failed creating pcapdump port\n"); - } rc = ddf_fun_add_to_category(fun, "pcap"); - if (rc != EOK) + if (rc != EOK) { + ddf_msg(LVL_ERROR, "Failed adding function to category pcap"); goto err_add_to_cat; + } return EOK; @@ -2379,7 +2374,6 @@ static void e1000_send_frame(nic_t *nic, void *data, size_t size) } memcpy(e1000->tx_frame_virt[tdt], data, size); - pcapdump_packet(nic_get_pcap_iface(nic), data, size); tx_descriptor_addr->phys_addr = PTR_TO_U64(e1000->tx_frame_phys[tdt]); tx_descriptor_addr->length = size; diff --git a/uspace/drv/nic/virtio-net/virtio-net.c b/uspace/drv/nic/virtio-net/virtio-net.c index 3659ab80a6..1cf69ea2b1 100644 --- a/uspace/drv/nic/virtio-net/virtio-net.c +++ b/uspace/drv/nic/virtio-net/virtio-net.c @@ -42,8 +42,8 @@ #include #include -#include "pcapdump_iface.h" -#include "pcap_iface.h" +#include + #define NAME "virtio-net" #define VIRTIO_NET_NUM_QUEUES 3 @@ -92,7 +92,6 @@ static void virtio_net_irq_handler(ipc_call_t *icall, ddf_dev_t *dev) nic_frame_t *frame = nic_alloc_frame(nic, len - sizeof(*hdr)); if (frame) { memcpy(frame->data, &hdr[1], len - sizeof(*hdr)); - pcapdump_packet(nic_get_pcap_iface(nic), frame->data, frame->size); nic_received_frame(nic, frame); } else { ddf_msg(LVL_WARN, @@ -352,7 +351,7 @@ static void virtio_net_send(nic_t *nic, void *data, size_t size) /* Copy packet data into the buffer just past the header */ memcpy(&hdr[1], data, size); - pcapdump_packet(nic_get_pcap_iface(nic), data, size); + /* * Set the descriptor, put it into the virtqueue and notify the device */ @@ -432,14 +431,11 @@ static errno_t virtio_net_dev_add(ddf_dev_t *dev) ddf_msg(LVL_NOTE, "The %s device has been successfully initialized.", ddf_dev_get_name(dev)); - errno_t pcap_rc = pcapdump_init(nic_get_pcap_iface(nic)); - - if (pcap_rc != EOK) { - printf("Failed creating pcapdump port\n"); - } rc = ddf_fun_add_to_category(fun, "pcap"); - if (rc != EOK) + if (rc != EOK) { + ddf_msg(LVL_ERROR, "Failed adding function to category pcap"); goto unbind; + } return EOK; diff --git a/uspace/lib/nic/include/nic.h b/uspace/lib/nic/include/nic.h index d751e788ed..470f9930f5 100644 --- a/uspace/lib/nic/include/nic.h +++ b/uspace/lib/nic/include/nic.h @@ -43,8 +43,7 @@ #include #include #include - -#include "pcap_iface.h" +#include #define DEVICE_CATEGORY_NIC "nic" diff --git a/uspace/lib/nic/src/nic_driver.c b/uspace/lib/nic/src/nic_driver.c index ea1878efde..9d670672e1 100644 --- a/uspace/lib/nic/src/nic_driver.c +++ b/uspace/lib/nic/src/nic_driver.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "nic_driver.h" #include "nic_ev.h" @@ -521,6 +522,7 @@ void nic_received_frame(nic_t *nic_data, nic_frame_t *frame) * Note: this function must not lock main lock, because loopback driver * calls it inside send_frame handler (with locked main lock) */ + pcapdump_packet(nic_get_pcap_iface(nic_data), frame->data, frame->size); fibril_rwlock_read_lock(&nic_data->rxc_lock); nic_frame_type_t frame_type; bool check = nic_rxc_check(&nic_data->rx_control, frame->data, @@ -559,6 +561,7 @@ void nic_received_frame(nic_t *nic_data, nic_frame_t *frame) } fibril_rwlock_write_unlock(&nic_data->stats_lock); } + //pcapdump_packet(nic_get_pcap_iface(nic_data), frame->data, frame->size); nic_release_frame(nic_data, frame); } @@ -646,6 +649,11 @@ nic_t *nic_create_and_bind(ddf_dev_t *device) return NULL; nic_data->dev = device; + errno_t pcap_rc = pcapdump_init(nic_get_pcap_iface(nic_data)); + + if (pcap_rc != EOK) { + printf("Failed creating pcapdump port\n"); + } return nic_data; } diff --git a/uspace/lib/nic/src/nic_impl.c b/uspace/lib/nic/src/nic_impl.c index d3595471be..e6285ab8bd 100644 --- a/uspace/lib/nic/src/nic_impl.c +++ b/uspace/lib/nic/src/nic_impl.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "nic_driver.h" #include "nic_ev.h" #include "nic_impl.h" @@ -178,7 +179,7 @@ errno_t nic_send_frame_impl(ddf_fun_t *fun, void *data, size_t size) fibril_rwlock_read_unlock(&nic_data->main_lock); return EBUSY; } - + pcapdump_packet(nic_get_pcap_iface(nic_data), data, size); nic_data->send_frame(nic_data, data, size); fibril_rwlock_read_unlock(&nic_data->main_lock); return EOK; diff --git a/uspace/lib/pcap/include/pcap.h b/uspace/lib/pcap/include/pcap.h index c9cf50f3af..1e8089fbb8 100644 --- a/uspace/lib/pcap/include/pcap.h +++ b/uspace/lib/pcap/include/pcap.h @@ -63,7 +63,7 @@ typedef struct { uint32_t reserved2; uint32_t snaplen; uint32_t additional; /** The LinkType and additional information field is in the form */ -} __attribute__((packed, aligned(4))) pcap_file_header_t; +} pcap_file_header_t; typedef struct pcap_packet_header { uint32_t seconds_stamp; diff --git a/uspace/lib/pcap/src/pcap.c b/uspace/lib/pcap/src/pcap.c index 1bd6e58ffa..cf8c791c6f 100644 --- a/uspace/lib/pcap/src/pcap.c +++ b/uspace/lib/pcap/src/pcap.c @@ -35,13 +35,6 @@ * @brief Headers and functions for .pcap file and packets to be dumped */ -#define LOGGER(msg, ...) \ - fprintf(stderr, \ - "[PCAP %s:%d]: " msg "\n", \ - __FILE__, __LINE__, \ - ##__VA_ARGS__\ - ) - #include "pcap.h" /** Set time in seconds and microseconds for the packet header . @@ -107,7 +100,6 @@ errno_t pcap_writer_to_file_init(pcap_writer_t *writer, const char *filename) writer->data = fopen(filename, "a"); if (writer->data == NULL) { rc = EINVAL; - LOGGER("Failed to create %s: %s.", filename, str_error(rc)); return rc; } pcap_writer_add_header(writer); diff --git a/uspace/lib/pcap/src/pcap_iface.c b/uspace/lib/pcap/src/pcap_iface.c index b160f676b3..3618eaddbf 100644 --- a/uspace/lib/pcap/src/pcap_iface.c +++ b/uspace/lib/pcap/src/pcap_iface.c @@ -81,7 +81,7 @@ void pcap_add_packet(const void *data, size_t size) pcap_writer_add_packet(&pcap_writer, data, size); } -void pcap_close_file() +void pcap_close_file(void) { pcap_writer.ops->close(&pcap_writer); pcap_writer.data = NULL; From e4cc2660086726ebabd608e31dc30bc295305e1a Mon Sep 17 00:00:00 2001 From: Nataliia Korop Date: Sun, 10 Mar 2024 12:40:30 +0100 Subject: [PATCH 07/13] ugly address --- uspace/app/pcapctl/main.c | 21 ++++++++------- uspace/lib/nic/include/nic_driver.h | 2 +- uspace/lib/nic/src/nic_driver.c | 2 +- uspace/lib/pcap/include/pcapctl_dump.h | 4 ++- uspace/lib/pcap/src/pcapctl_dump.c | 36 +++++++++++++++++--------- 5 files changed, 40 insertions(+), 25 deletions(-) diff --git a/uspace/app/pcapctl/main.c b/uspace/app/pcapctl/main.c index 716a1c597b..281dca2712 100644 --- a/uspace/app/pcapctl/main.c +++ b/uspace/app/pcapctl/main.c @@ -40,28 +40,29 @@ #define NAME "pcapctl" -pcapctl_sess_t sess; +pcapctl_sess_t* sess; -static errno_t start_dumping(const char *drv_name, const char *name) +static errno_t start_dumping(const char *svc_name, const char *name) { - errno_t rc = pcapctl_dump_init(&sess, drv_name); + errno_t rc = pcapctl_dump_open(svc_name, &sess); if (rc != EOK) { - //fprintf(stderr, "Error initializing ...\n"); return 1; } - pcapctl_dump_start(name, &sess); + pcapctl_dump_start(name, sess); + pcapctl_dump_close(sess); return EOK; } /** Session might */ -static errno_t stop_dumping(const char *drv_name) +static errno_t stop_dumping(const char *svc_name) { - errno_t rc = pcapctl_dump_init(&sess, drv_name); + errno_t rc = pcapctl_dump_open(svc_name, &sess); if (rc != EOK) { - fprintf(stderr, "Error initializing ...\n"); return 1; } - pcapctl_dump_stop(&sess); + + pcapctl_dump_stop(sess); + pcapctl_dump_close(sess); return EOK; } @@ -72,9 +73,9 @@ static void list_devs(void) { static void usage(const char *progname) { fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s list: List of devices\n", progname); fprintf(stderr, " %s start : Packets dumped from will be written to \n", progname); fprintf(stderr, " %s stop : Dumping from stops\n", progname); - } int main(int argc, char *argv[]) diff --git a/uspace/lib/nic/include/nic_driver.h b/uspace/lib/nic/include/nic_driver.h index 378817b5b4..f99e5a0746 100644 --- a/uspace/lib/nic/include/nic_driver.h +++ b/uspace/lib/nic/include/nic_driver.h @@ -45,11 +45,11 @@ #include #include #include +#include #include "nic.h" #include "nic_rx_control.h" #include "nic_wol_virtues.h" -#include "pcap/include/pcapdump_iface.h" struct sw_poll_info { fid_t fibril; diff --git a/uspace/lib/nic/src/nic_driver.c b/uspace/lib/nic/src/nic_driver.c index 9d670672e1..1437b86a27 100644 --- a/uspace/lib/nic/src/nic_driver.c +++ b/uspace/lib/nic/src/nic_driver.c @@ -649,8 +649,8 @@ nic_t *nic_create_and_bind(ddf_dev_t *device) return NULL; nic_data->dev = device; - errno_t pcap_rc = pcapdump_init(nic_get_pcap_iface(nic_data)); + errno_t pcap_rc = pcapdump_init(nic_get_pcap_iface(nic_data)); if (pcap_rc != EOK) { printf("Failed creating pcapdump port\n"); } diff --git a/uspace/lib/pcap/include/pcapctl_dump.h b/uspace/lib/pcap/include/pcapctl_dump.h index 09e926f386..e1241803f3 100644 --- a/uspace/lib/pcap/include/pcapctl_dump.h +++ b/uspace/lib/pcap/include/pcapctl_dump.h @@ -48,11 +48,13 @@ typedef struct { async_sess_t *sess; } pcapctl_sess_t; -extern errno_t pcapctl_dump_init(pcapctl_sess_t *, const char *); +extern errno_t pcapctl_dump_open(const char *svcname, pcapctl_sess_t **rsess); +extern errno_t pcapctl_dump_close(pcapctl_sess_t *sess); extern errno_t pcapctl_dump_start(const char *, pcapctl_sess_t *); extern errno_t pcapctl_dump_stop(pcapctl_sess_t *); extern errno_t pcapctl_list(void); + #endif /** @} diff --git a/uspace/lib/pcap/src/pcapctl_dump.c b/uspace/lib/pcap/src/pcapctl_dump.c index be842065a1..df524badfd 100644 --- a/uspace/lib/pcap/src/pcapctl_dump.c +++ b/uspace/lib/pcap/src/pcapctl_dump.c @@ -50,7 +50,7 @@ static void pcapctl_dump_exchange_end(async_exch_t *exch) async_exchange_end(exch); } -static errno_t pcapctl_cat_has_drv(const char *drv_name, service_id_t* svc) { +static errno_t pcapctl_cat_get_svc(const char *drv_name, service_id_t* svc) { errno_t rc; category_id_t pcap_cat; size_t count; @@ -89,36 +89,39 @@ extern errno_t pcapctl_list(void) { rc = loc_category_get_id("pcap", &pcap_cat, 0); if (rc != EOK) { - printf("Error resolving category 'pcap'.\n"); + printf("Error resolving category pcap.\n"); return rc; } rc = loc_category_get_svcs(pcap_cat, &pcap_svcs, &count); if (rc != EOK) { printf("Error resolving list of pcap services.\n"); + free(pcap_svcs); return rc; } - assert((count > 0) && "TODO: not implemented when no services are available\n"); - - fprintf(stdout, "Drivers:\n"); + fprintf(stdout, "Services:\n"); for (unsigned i = 0; i < count; ++i) { char *name = NULL; loc_service_get_name(pcap_svcs[i], &name); - - fprintf(stdout, "driver: %s\n", name); + fprintf(stdout, "service: %s\n", name); } + free(pcap_svcs); return EOK; } -errno_t pcapctl_dump_init(pcapctl_sess_t *sess, const char *drv_name) + +errno_t pcapctl_dump_open(const char *svcname, pcapctl_sess_t **rsess) { errno_t rc; service_id_t svc; - rc = pcapctl_cat_has_drv(drv_name, &svc); + pcapctl_sess_t *sess = calloc(1, sizeof(pcapctl_sess_t)); + if (sess == NULL) + return ENOMEM; + + rc = pcapctl_cat_get_svc(svcname, &svc); if (rc != EOK) { - fprintf(stderr, "No such driver was found.\n"); - return 1; + goto error; } async_sess_t *new_session = loc_service_connect(svc, INTERFACE_PCAP_CONTROL, 0); if (new_session == NULL) { @@ -126,12 +129,21 @@ errno_t pcapctl_dump_init(pcapctl_sess_t *sess, const char *drv_name) rc = EREFUSED; goto error; } + sess->sess = new_session; - rc = EOK; + *rsess = sess; + return EOK; error: + pcapctl_dump_close(sess); return rc; } +errno_t pcapctl_dump_close(pcapctl_sess_t *sess) +{ + free(sess); + return EOK; +} + /** Starting a new session for pcapctl * * @param name Name of the file to dump packets to From 78edb5e7bafe392fff14634b826f857ea1745cb1 Mon Sep 17 00:00:00 2001 From: Nataliia Korop Date: Tue, 19 Mar 2024 16:15:50 +0100 Subject: [PATCH 08/13] choose nic: without --device|-d --- uspace/app/pcapctl/main.c | 61 +++++++++++++++------- uspace/lib/pcap/src/pcapctl_dump.c | 81 ++++++++++++++++++++++++++++-- 2 files changed, 120 insertions(+), 22 deletions(-) diff --git a/uspace/app/pcapctl/main.c b/uspace/app/pcapctl/main.c index 281dca2712..39814e5e95 100644 --- a/uspace/app/pcapctl/main.c +++ b/uspace/app/pcapctl/main.c @@ -40,14 +40,16 @@ #define NAME "pcapctl" -pcapctl_sess_t* sess; +//pcapctl_sess_t* sess = NULL; static errno_t start_dumping(const char *svc_name, const char *name) { + pcapctl_sess_t* sess = NULL; errno_t rc = pcapctl_dump_open(svc_name, &sess); if (rc != EOK) { return 1; } + pcapctl_dump_start(name, sess); pcapctl_dump_close(sess); return EOK; @@ -56,11 +58,11 @@ static errno_t start_dumping(const char *svc_name, const char *name) /** Session might */ static errno_t stop_dumping(const char *svc_name) { + pcapctl_sess_t* sess = NULL; errno_t rc = pcapctl_dump_open(svc_name, &sess); if (rc != EOK) { return 1; } - pcapctl_dump_stop(sess); pcapctl_dump_close(sess); return EOK; @@ -70,42 +72,65 @@ static void list_devs(void) { pcapctl_list(); } -static void usage(const char *progname) +static void usage(void) { - fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s list: List of devices\n", progname); - fprintf(stderr, " %s start : Packets dumped from will be written to \n", progname); - fprintf(stderr, " %s stop : Dumping from stops\n", progname); + printf("Usage:\n" + NAME " list \n" + "\tList of devices\n" + NAME " start --device= | -d \n" + "\tPackets dumped from device will be written to \n" + NAME " stop --device= | -d \n" + "\tDumping from stops\n" + NAME " start \n" + "\tPackets dumped from the 1st device from the list will be written to \n" + NAME " --help | -h\n" + "\tShow this application help.\n"); } int main(int argc, char *argv[]) { if (argc < 2) { - usage(argv[0]); + usage(); return 1; } else { + /** help*/ if (str_cmp(argv[1], "--help") == 0 || str_cmp(argv[1], "-h") == 0) { - usage(argv[0]); + usage(); return 0; + /** list*/ } else if (str_cmp(argv[1], "list") == 0) { list_devs(); return 0; + /** start with/out devnum */ } else if (str_cmp(argv[1], "start") == 0) { - if (argc != 4) { - usage(argv[0]); + if (argc == 3) { + start_dumping((char *)"0", argv[2]); + return 0; + } + else if (argc == 4) { + start_dumping(argv[2], argv[3]); + return 0; + } else { + usage(); return 1; } - start_dumping(argv[2], argv[3]); + /** Stop with/out devnum */ } else if (str_cmp(argv[1], "stop") == 0) { - if (argc != 3) { - usage(argv[0]); + if (argc == 2) { + stop_dumping((char *)"0"); + fprintf(stdout, "Dumping was stopped\n"); + return 0; + } + else if (argc == 3) { + + stop_dumping(argv[2]); + fprintf(stdout, "Dumping was stopped\n"); + } else { + usage(); return 1; } - stop_dumping(argv[2]); - fprintf(stdout, "Dumping was stopped\n"); - return EOK; } else { - usage(argv[0]); + usage(); return 1; } } diff --git a/uspace/lib/pcap/src/pcapctl_dump.c b/uspace/lib/pcap/src/pcapctl_dump.c index df524badfd..5f4f1c51e8 100644 --- a/uspace/lib/pcap/src/pcapctl_dump.c +++ b/uspace/lib/pcap/src/pcapctl_dump.c @@ -37,10 +37,27 @@ #include #include #include - +#include +#include #include "pcapctl_dump.h" #include "pcapdump_iface.h" +//static service_id_t *pcap_svcs = NULL; ?? + +static errno_t str2num(const char* str, size_t* number) { + size_t num = 0; + if (*str == 0) + return ELIMIT; + if (!isdigit(*str)) + return EINVAL; + while (isdigit(*str)) { + num = num * 10 + ((*str) - '0'); + str++; + } + + *number = num; + return EOK; +} /** Finish an async exchange on the pcapctl session * * @param exch Exchange to be finished @@ -104,14 +121,60 @@ extern errno_t pcapctl_list(void) { for (unsigned i = 0; i < count; ++i) { char *name = NULL; loc_service_get_name(pcap_svcs[i], &name); - fprintf(stdout, "service: %s\n", name); + fprintf(stdout, "%d. %s\n", i, name); } free(pcap_svcs); return EOK; } -errno_t pcapctl_dump_open(const char *svcname, pcapctl_sess_t **rsess) +static errno_t pcapctl_get_name_from_number(const char* svcnum, const char** svcname) { + + errno_t rc; + category_id_t pcap_cat; + size_t count; + service_id_t *pcap_svcs = NULL; + + rc = loc_category_get_id("pcap", &pcap_cat, 0); + if (rc != EOK) { + printf("Error resolving category pcap.\n"); + return rc; + } + size_t num; + rc = str2num(svcnum, &num); + if (rc != EOK) { + printf("Error converting char* to size_t.\n"); + free(pcap_svcs); + return rc; + } + + rc = loc_category_get_svcs(pcap_cat, &pcap_svcs, &count); + if (rc != EOK) { + printf("Error resolving list of pcap services.\n"); + free(pcap_svcs); + return rc; + } + + if (num >= count) { + printf("Error finding device: no device with such number\n"); + free(pcap_svcs); + return EINVAL; + } + char *name = NULL; + rc = loc_service_get_name(pcap_svcs[num], &name); + if (rc != EOK) { + printf("Error resolving name"); + } + + *svcname = name; + printf("%s\n", *svcname); + return EOK; +} + +/** + * + */ +errno_t pcapctl_dump_open(const char *svcnum, pcapctl_sess_t **rsess) { errno_t rc; service_id_t svc; @@ -119,6 +182,14 @@ errno_t pcapctl_dump_open(const char *svcname, pcapctl_sess_t **rsess) if (sess == NULL) return ENOMEM; + + const char* svcname; + + rc = pcapctl_get_name_from_number(svcnum, &svcname); + if (rc != EOK) { + return rc; + } + rc = pcapctl_cat_get_svc(svcname, &svc); if (rc != EOK) { goto error; @@ -129,7 +200,6 @@ errno_t pcapctl_dump_open(const char *svcname, pcapctl_sess_t **rsess) rc = EREFUSED; goto error; } - sess->sess = new_session; *rsess = sess; return EOK; @@ -138,6 +208,9 @@ errno_t pcapctl_dump_open(const char *svcname, pcapctl_sess_t **rsess) return rc; } +/** + * + */ errno_t pcapctl_dump_close(pcapctl_sess_t *sess) { free(sess); From 8d9217d344740c9fa41e04a85b090a0b3b82a55b Mon Sep 17 00:00:00 2001 From: Nataliia Korop Date: Wed, 20 Mar 2024 18:06:29 +0100 Subject: [PATCH 09/13] nic, drvs, pcapctl --- uspace/app/pcapctl/main.c | 42 +++++++++++++------------- uspace/drv/nic/e1k/e1k.c | 24 +++++++++------ uspace/drv/nic/ne2k/ne2k.c | 7 +++++ uspace/drv/nic/rtl8139/driver.c | 7 +++++ uspace/lib/nic/include/nic.h | 2 ++ uspace/lib/nic/src/nic_impl.c | 19 ++++++++++++ uspace/lib/pcap/include/pcapctl_dump.h | 1 - uspace/lib/pcap/src/pcapctl_dump.c | 20 ++++++------ 8 files changed, 80 insertions(+), 42 deletions(-) diff --git a/uspace/app/pcapctl/main.c b/uspace/app/pcapctl/main.c index 39814e5e95..94b2e796f8 100644 --- a/uspace/app/pcapctl/main.c +++ b/uspace/app/pcapctl/main.c @@ -39,12 +39,13 @@ #include "pcapctl_dump.h" #define NAME "pcapctl" +#define DEFAULT_DEV_NUM 0 //pcapctl_sess_t* sess = NULL; static errno_t start_dumping(const char *svc_name, const char *name) { - pcapctl_sess_t* sess = NULL; + pcapctl_sess_t *sess = NULL; errno_t rc = pcapctl_dump_open(svc_name, &sess); if (rc != EOK) { return 1; @@ -58,7 +59,7 @@ static errno_t start_dumping(const char *svc_name, const char *name) /** Session might */ static errno_t stop_dumping(const char *svc_name) { - pcapctl_sess_t* sess = NULL; + pcapctl_sess_t *sess = NULL; errno_t rc = pcapctl_dump_open(svc_name, &sess); if (rc != EOK) { return 1; @@ -68,23 +69,24 @@ static errno_t stop_dumping(const char *svc_name) return EOK; } -static void list_devs(void) { +static void list_devs(void) +{ pcapctl_list(); } static void usage(void) { printf("Usage:\n" - NAME " list \n" - "\tList of devices\n" - NAME " start --device= | -d \n" - "\tPackets dumped from device will be written to \n" - NAME " stop --device= | -d \n" - "\tDumping from stops\n" - NAME " start \n" - "\tPackets dumped from the 1st device from the list will be written to \n" - NAME " --help | -h\n" - "\tShow this application help.\n"); + NAME " list \n" + "\tList of devices\n" + NAME " start --device= | -d \n" + "\tPackets dumped from device will be written to \n" + NAME " stop --device= | -d \n" + "\tDumping from stops\n" + NAME " start \n" + "\tPackets dumped from the 1st device from the list will be written to \n" + NAME " --help | -h\n" + "\tShow this application help.\n"); } int main(int argc, char *argv[]) @@ -93,35 +95,33 @@ int main(int argc, char *argv[]) usage(); return 1; } else { - /** help*/ + /** help */ if (str_cmp(argv[1], "--help") == 0 || str_cmp(argv[1], "-h") == 0) { usage(); return 0; - /** list*/ + /** list */ } else if (str_cmp(argv[1], "list") == 0) { list_devs(); return 0; - /** start with/out devnum */ + /** start with/out devnum */ } else if (str_cmp(argv[1], "start") == 0) { if (argc == 3) { start_dumping((char *)"0", argv[2]); return 0; - } - else if (argc == 4) { + } else if (argc == 4) { start_dumping(argv[2], argv[3]); return 0; } else { usage(); return 1; } - /** Stop with/out devnum */ + /** Stop with/out devnum */ } else if (str_cmp(argv[1], "stop") == 0) { if (argc == 2) { stop_dumping((char *)"0"); fprintf(stdout, "Dumping was stopped\n"); return 0; - } - else if (argc == 3) { + } else if (argc == 3) { stop_dumping(argv[2]); fprintf(stdout, "Dumping was stopped\n"); diff --git a/uspace/drv/nic/e1k/e1k.c b/uspace/drv/nic/e1k/e1k.c index 5b9d02837b..f4c724674c 100644 --- a/uspace/drv/nic/e1k/e1k.c +++ b/uspace/drv/nic/e1k/e1k.c @@ -2201,20 +2201,24 @@ errno_t e1000_dev_add(ddf_dev_t *dev) if (rc != EOK) goto err_fun_bind; - rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC); - if (rc != EOK) - goto err_add_to_cat; - - rc = ddf_fun_add_to_category(fun, "pcap"); + // rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC); + // if (rc != EOK) + // goto err_add_to_cat; + + // rc = ddf_fun_add_to_category(fun, "pcap"); + // if (rc != EOK) { + // ddf_msg(LVL_ERROR, "Failed adding function to category pcap"); + // goto err_add_to_cat; + // } + rc = nic_fun_add_to_cats(fun); if (rc != EOK) { - ddf_msg(LVL_ERROR, "Failed adding function to category pcap"); - goto err_add_to_cat; + ddf_msg(LVL_ERROR, "Failed adding function to categories"); + return rc; } - return EOK; -err_add_to_cat: - ddf_fun_unbind(fun); + // err_add_to_cat: + // ddf_fun_unbind(fun); err_fun_bind: err_rx_structure: e1000_uninitialize_rx_structure(nic); diff --git a/uspace/drv/nic/ne2k/ne2k.c b/uspace/drv/nic/ne2k/ne2k.c index 2e23b8a5fe..3792e59565 100644 --- a/uspace/drv/nic/ne2k/ne2k.c +++ b/uspace/drv/nic/ne2k/ne2k.c @@ -448,6 +448,13 @@ static errno_t ne2k_dev_add(ddf_dev_t *dev) ddf_fun_destroy(fun); return rc; } + rc = ddf_fun_add_to_category(fun, "pcap"); + if (rc != EOK) { + //ddf_msg(LVL_ERROR, "Failed adding function to category pcap"); + ddf_fun_unbind(fun); + ddf_fun_destroy(fun); + return rc; + } return EOK; } diff --git a/uspace/drv/nic/rtl8139/driver.c b/uspace/drv/nic/rtl8139/driver.c index 8b84564544..d4deeaa3b2 100644 --- a/uspace/drv/nic/rtl8139/driver.c +++ b/uspace/drv/nic/rtl8139/driver.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "defs.h" #include "driver.h" @@ -1312,6 +1313,12 @@ errno_t rtl8139_dev_add(ddf_dev_t *dev) goto err_fun_bind; } + rc = ddf_fun_add_to_category(fun, "pcap"); + if (rc != EOK) { + ddf_msg(LVL_ERROR, "Failed adding function to category pcap"); + goto err_fun_bind; + } + ddf_msg(LVL_NOTE, "The %s device has been successfully initialized.", ddf_dev_get_name(dev)); diff --git a/uspace/lib/nic/include/nic.h b/uspace/lib/nic/include/nic.h index 470f9930f5..9fb0b5637f 100644 --- a/uspace/lib/nic/include/nic.h +++ b/uspace/lib/nic/include/nic.h @@ -281,6 +281,8 @@ extern void nic_sw_period_stop(nic_t *); /* pcapdump interface */ extern pcap_iface_t *nic_get_pcap_iface(nic_t *); +extern errno_t nic_fun_add_to_cats(ddf_fun_t *fun); + #endif // __NIC_H__ /** @} diff --git a/uspace/lib/nic/src/nic_impl.c b/uspace/lib/nic/src/nic_impl.c index e6285ab8bd..d894d63f69 100644 --- a/uspace/lib/nic/src/nic_impl.c +++ b/uspace/lib/nic/src/nic_impl.c @@ -843,5 +843,24 @@ void nic_close_impl(ddf_fun_t *fun) { } +errno_t nic_fun_add_to_cats(ddf_fun_t *fun) +{ + errno_t rc; + rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC); + if (rc != EOK) + goto err_add_to_cat; + + rc = ddf_fun_add_to_category(fun, "pcap"); + if (rc != EOK) { + //ddf_msg(LVL_ERROR, "Failed adding function to category pcap"); + goto err_add_to_cat; + } + return EOK; + +err_add_to_cat: + ddf_fun_unbind(fun); + return rc; +} + /** @} */ diff --git a/uspace/lib/pcap/include/pcapctl_dump.h b/uspace/lib/pcap/include/pcapctl_dump.h index e1241803f3..e3a7d5dce6 100644 --- a/uspace/lib/pcap/include/pcapctl_dump.h +++ b/uspace/lib/pcap/include/pcapctl_dump.h @@ -54,7 +54,6 @@ extern errno_t pcapctl_dump_start(const char *, pcapctl_sess_t *); extern errno_t pcapctl_dump_stop(pcapctl_sess_t *); extern errno_t pcapctl_list(void); - #endif /** @} diff --git a/uspace/lib/pcap/src/pcapctl_dump.c b/uspace/lib/pcap/src/pcapctl_dump.c index 5f4f1c51e8..5e117a0f5f 100644 --- a/uspace/lib/pcap/src/pcapctl_dump.c +++ b/uspace/lib/pcap/src/pcapctl_dump.c @@ -44,7 +44,8 @@ //static service_id_t *pcap_svcs = NULL; ?? -static errno_t str2num(const char* str, size_t* number) { +static errno_t str2num(const char *str, size_t *number) +{ size_t num = 0; if (*str == 0) return ELIMIT; @@ -67,7 +68,8 @@ static void pcapctl_dump_exchange_end(async_exch_t *exch) async_exchange_end(exch); } -static errno_t pcapctl_cat_get_svc(const char *drv_name, service_id_t* svc) { +static errno_t pcapctl_cat_get_svc(const char *drv_name, service_id_t *svc) +{ errno_t rc; category_id_t pcap_cat; size_t count; @@ -97,8 +99,8 @@ static errno_t pcapctl_cat_get_svc(const char *drv_name, service_id_t* svc) { return 1; } -extern errno_t pcapctl_list(void) { - +errno_t pcapctl_list(void) +{ errno_t rc; category_id_t pcap_cat; size_t count; @@ -117,7 +119,7 @@ extern errno_t pcapctl_list(void) { return rc; } - fprintf(stdout, "Services:\n"); + fprintf(stdout, "Devices:\n"); for (unsigned i = 0; i < count; ++i) { char *name = NULL; loc_service_get_name(pcap_svcs[i], &name); @@ -127,9 +129,8 @@ extern errno_t pcapctl_list(void) { return EOK; } - -static errno_t pcapctl_get_name_from_number(const char* svcnum, const char** svcname) { - +static errno_t pcapctl_get_name_from_number(const char *svcnum, const char **svcname) +{ errno_t rc; category_id_t pcap_cat; size_t count; @@ -182,8 +183,7 @@ errno_t pcapctl_dump_open(const char *svcnum, pcapctl_sess_t **rsess) if (sess == NULL) return ENOMEM; - - const char* svcname; + const char *svcname; rc = pcapctl_get_name_from_number(svcnum, &svcname); if (rc != EOK) { From 384f0815137b8a85f18d5e4ce599706ccf7995af Mon Sep 17 00:00:00 2001 From: Nataliia Korop Date: Sun, 7 Apr 2024 11:32:59 +0200 Subject: [PATCH 10/13] app: read options ok --- uspace/app/pcapctl/main.c | 111 +++++++++++++++---------- uspace/lib/pcap/include/pcapctl_dump.h | 3 +- uspace/lib/pcap/src/pcapctl_dump.c | 90 ++++++-------------- 3 files changed, 92 insertions(+), 112 deletions(-) diff --git a/uspace/app/pcapctl/main.c b/uspace/app/pcapctl/main.c index 94b2e796f8..c004caf420 100644 --- a/uspace/app/pcapctl/main.c +++ b/uspace/app/pcapctl/main.c @@ -35,18 +35,18 @@ #include #include #include +#include +#include #include "pcapctl_dump.h" #define NAME "pcapctl" #define DEFAULT_DEV_NUM 0 -//pcapctl_sess_t* sess = NULL; - -static errno_t start_dumping(const char *svc_name, const char *name) +static errno_t start_dumping(int *dev_number, const char *name) { pcapctl_sess_t *sess = NULL; - errno_t rc = pcapctl_dump_open(svc_name, &sess); + errno_t rc = pcapctl_dump_open(dev_number, &sess); if (rc != EOK) { return 1; } @@ -56,11 +56,10 @@ static errno_t start_dumping(const char *svc_name, const char *name) return EOK; } -/** Session might */ -static errno_t stop_dumping(const char *svc_name) +static errno_t stop_dumping(int *dev_number) { pcapctl_sess_t *sess = NULL; - errno_t rc = pcapctl_dump_open(svc_name, &sess); + errno_t rc = pcapctl_dump_open(dev_number, &sess); if (rc != EOK) { return 1; } @@ -74,12 +73,25 @@ static void list_devs(void) pcapctl_list(); } +/** + * Array of supported commandline options + */ +static const struct option opts[] = { + { "device", required_argument, 0, 'd' }, + { "list", no_argument, 0, 'l' }, + { "help", no_argument, 0, 'h' }, + { "outfile", required_argument, 0, 'f' }, + { "start", no_argument, 0, 'r' }, + { "stop", no_argument, 0, 't' }, + { 0, 0, 0, 0 } +}; + static void usage(void) { printf("Usage:\n" - NAME " list \n" + NAME " --list | -l \n" "\tList of devices\n" - NAME " start --device= | -d \n" + NAME " start --device= | -d --outfile | -f \n" "\tPackets dumped from device will be written to \n" NAME " stop --device= | -d \n" "\tDumping from stops\n" @@ -91,49 +103,56 @@ static void usage(void) int main(int argc, char *argv[]) { - if (argc < 2) { + bool start = false; + bool stop = false; + int dev_number = DEFAULT_DEV_NUM; + const char *output_file_name; + int idx = 0; + int ret = 0; + if (argc == 1) { usage(); - return 1; - } else { - /** help */ - if (str_cmp(argv[1], "--help") == 0 || str_cmp(argv[1], "-h") == 0) { - usage(); - return 0; - /** list */ - } else if (str_cmp(argv[1], "list") == 0) { - list_devs(); - return 0; - /** start with/out devnum */ - } else if (str_cmp(argv[1], "start") == 0) { - if (argc == 3) { - start_dumping((char *)"0", argv[2]); - return 0; - } else if (argc == 4) { - start_dumping(argv[2], argv[3]); - return 0; - } else { - usage(); - return 1; - } - /** Stop with/out devnum */ - } else if (str_cmp(argv[1], "stop") == 0) { - if (argc == 2) { - stop_dumping((char *)"0"); - fprintf(stdout, "Dumping was stopped\n"); - return 0; - } else if (argc == 3) { - - stop_dumping(argv[2]); - fprintf(stdout, "Dumping was stopped\n"); - } else { - usage(); + return 0; + } + while (ret != -1) { + ret = getopt_long(argc, argv, "d:lhf:rt", opts, &idx); + switch (ret) { + case 'd': + char *rest; + long result = strtol(optarg, &rest, 10); + dev_number = (int)result; + errno_t rc = pcapctl_is_valid_device(&dev_number); + if (rc != EOK) { + printf("Device with index %d not found\n", dev_number); return 1; } - } else { + break; + case 'l': + list_devs(); + return 0; + case 'h': usage(); - return 1; + return 0; + case 'f': + output_file_name = optarg; + break; + case 'r': + start = true; + break; + case 't': + stop = true; + break; } } + + printf("%s: HelenOS Packet Dumping utility: device - %d\n", NAME, dev_number); + + if (start) { + // start with dev number and optional..name + start_dumping(&dev_number, output_file_name); + } else if (stop) { + //stop with dev number + stop_dumping(&dev_number); + } return 0; } diff --git a/uspace/lib/pcap/include/pcapctl_dump.h b/uspace/lib/pcap/include/pcapctl_dump.h index e3a7d5dce6..c15c3b66bc 100644 --- a/uspace/lib/pcap/include/pcapctl_dump.h +++ b/uspace/lib/pcap/include/pcapctl_dump.h @@ -48,11 +48,12 @@ typedef struct { async_sess_t *sess; } pcapctl_sess_t; -extern errno_t pcapctl_dump_open(const char *svcname, pcapctl_sess_t **rsess); +extern errno_t pcapctl_dump_open(int *, pcapctl_sess_t **rsess); extern errno_t pcapctl_dump_close(pcapctl_sess_t *sess); extern errno_t pcapctl_dump_start(const char *, pcapctl_sess_t *); extern errno_t pcapctl_dump_stop(pcapctl_sess_t *); extern errno_t pcapctl_list(void); +extern errno_t pcapctl_is_valid_device(int *); #endif diff --git a/uspace/lib/pcap/src/pcapctl_dump.c b/uspace/lib/pcap/src/pcapctl_dump.c index 5e117a0f5f..384a4e31ed 100644 --- a/uspace/lib/pcap/src/pcapctl_dump.c +++ b/uspace/lib/pcap/src/pcapctl_dump.c @@ -42,23 +42,6 @@ #include "pcapctl_dump.h" #include "pcapdump_iface.h" -//static service_id_t *pcap_svcs = NULL; ?? - -static errno_t str2num(const char *str, size_t *number) -{ - size_t num = 0; - if (*str == 0) - return ELIMIT; - if (!isdigit(*str)) - return EINVAL; - while (isdigit(*str)) { - num = num * 10 + ((*str) - '0'); - str++; - } - - *number = num; - return EOK; -} /** Finish an async exchange on the pcapctl session * * @param exch Exchange to be finished @@ -68,7 +51,7 @@ static void pcapctl_dump_exchange_end(async_exch_t *exch) async_exchange_end(exch); } -static errno_t pcapctl_cat_get_svc(const char *drv_name, service_id_t *svc) +static errno_t pcapctl_cat_get_svc(int *index, service_id_t *svc) { errno_t rc; category_id_t pcap_cat; @@ -84,22 +67,19 @@ static errno_t pcapctl_cat_get_svc(const char *drv_name, service_id_t *svc) rc = loc_category_get_svcs(pcap_cat, &pcap_svcs, &count); if (rc != EOK) { printf("Error resolving list of pcap services.\n"); + free(pcap_svcs); return rc; } - - for (unsigned i = 0; i < count; ++i) { - char *name = NULL; - loc_service_get_name(pcap_svcs[i], &name); - if (!str_cmp(drv_name, name)) { - *svc = pcap_svcs[i]; - return EOK; - } + if (*index < (int)count) { + *svc = pcap_svcs[*index]; + free(pcap_svcs); + return EOK; } - free(pcap_svcs); - return 1; + + return ENOENT; } -errno_t pcapctl_list(void) +errno_t pcapctl_is_valid_device(int *index) { errno_t rc; category_id_t pcap_cat; @@ -118,18 +98,16 @@ errno_t pcapctl_list(void) free(pcap_svcs); return rc; } - - fprintf(stdout, "Devices:\n"); - for (unsigned i = 0; i < count; ++i) { - char *name = NULL; - loc_service_get_name(pcap_svcs[i], &name); - fprintf(stdout, "%d. %s\n", i, name); + if (*index + 1 > (int)count || *index < 0) { + return EINVAL; } - free(pcap_svcs); return EOK; } -static errno_t pcapctl_get_name_from_number(const char *svcnum, const char **svcname) +/** + * + */ +errno_t pcapctl_list(void) { errno_t rc; category_id_t pcap_cat; @@ -141,13 +119,6 @@ static errno_t pcapctl_get_name_from_number(const char *svcnum, const char **svc printf("Error resolving category pcap.\n"); return rc; } - size_t num; - rc = str2num(svcnum, &num); - if (rc != EOK) { - printf("Error converting char* to size_t.\n"); - free(pcap_svcs); - return rc; - } rc = loc_category_get_svcs(pcap_cat, &pcap_svcs, &count); if (rc != EOK) { @@ -156,26 +127,20 @@ static errno_t pcapctl_get_name_from_number(const char *svcnum, const char **svc return rc; } - if (num >= count) { - printf("Error finding device: no device with such number\n"); - free(pcap_svcs); - return EINVAL; - } - char *name = NULL; - rc = loc_service_get_name(pcap_svcs[num], &name); - if (rc != EOK) { - printf("Error resolving name"); + fprintf(stdout, "Devices:\n"); + for (unsigned i = 0; i < count; ++i) { + char *name = NULL; + loc_service_get_name(pcap_svcs[i], &name); + fprintf(stdout, "%d. %s\n", i, name); } - - *svcname = name; - printf("%s\n", *svcname); + free(pcap_svcs); return EOK; } /** * */ -errno_t pcapctl_dump_open(const char *svcnum, pcapctl_sess_t **rsess) +errno_t pcapctl_dump_open(int *index, pcapctl_sess_t **rsess) { errno_t rc; service_id_t svc; @@ -183,17 +148,12 @@ errno_t pcapctl_dump_open(const char *svcnum, pcapctl_sess_t **rsess) if (sess == NULL) return ENOMEM; - const char *svcname; - - rc = pcapctl_get_name_from_number(svcnum, &svcname); - if (rc != EOK) { - return rc; - } - - rc = pcapctl_cat_get_svc(svcname, &svc); + rc = pcapctl_cat_get_svc(index, &svc); if (rc != EOK) { + printf("Error finding the device with index: %d\n", *index); goto error; } + async_sess_t *new_session = loc_service_connect(svc, INTERFACE_PCAP_CONTROL, 0); if (new_session == NULL) { fprintf(stderr, "Error connecting to service.\n"); From 6c1e7c09ca4ee029111d3871ef9c8c35eee7f69d Mon Sep 17 00:00:00 2001 From: Nataliia Korop Date: Sun, 7 Apr 2024 11:52:09 +0200 Subject: [PATCH 11/13] fix app help --- uspace/app/pcapctl/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/uspace/app/pcapctl/main.c b/uspace/app/pcapctl/main.c index c004caf420..e81bb8c0bb 100644 --- a/uspace/app/pcapctl/main.c +++ b/uspace/app/pcapctl/main.c @@ -91,12 +91,12 @@ static void usage(void) printf("Usage:\n" NAME " --list | -l \n" "\tList of devices\n" - NAME " start --device= | -d --outfile | -f \n" + NAME " --start | -r --device= | -d --outfile= | -f \n" "\tPackets dumped from device will be written to \n" - NAME " stop --device= | -d \n" + NAME " --stop | -t --device= | -d \n" "\tDumping from stops\n" - NAME " start \n" - "\tPackets dumped from the 1st device from the list will be written to \n" + NAME " --start | -s --outfile= | -f \n" + "\tPackets dumped from the 0. device from the list will be written to \n" NAME " --help | -h\n" "\tShow this application help.\n"); } From e55d2c15dfef177ecdff9b2dda527a31ec9cad50 Mon Sep 17 00:00:00 2001 From: Nataliia Korop Date: Sun, 7 Apr 2024 14:53:23 +0200 Subject: [PATCH 12/13] add_to_cat func in lib --- uspace/drv/nic/e1k/e1k.c | 10 +--------- uspace/drv/nic/ne2k/ne2k.c | 13 ++++--------- uspace/drv/nic/rtl8139/driver.c | 16 ++++++---------- uspace/drv/nic/rtl8169/driver.c | 11 ++++++----- uspace/drv/nic/virtio-net/virtio-net.c | 17 ++++++----------- 5 files changed, 23 insertions(+), 44 deletions(-) diff --git a/uspace/drv/nic/e1k/e1k.c b/uspace/drv/nic/e1k/e1k.c index f4c724674c..3a49be6416 100644 --- a/uspace/drv/nic/e1k/e1k.c +++ b/uspace/drv/nic/e1k/e1k.c @@ -2201,18 +2201,10 @@ errno_t e1000_dev_add(ddf_dev_t *dev) if (rc != EOK) goto err_fun_bind; - // rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC); - // if (rc != EOK) - // goto err_add_to_cat; - - // rc = ddf_fun_add_to_category(fun, "pcap"); - // if (rc != EOK) { - // ddf_msg(LVL_ERROR, "Failed adding function to category pcap"); - // goto err_add_to_cat; - // } rc = nic_fun_add_to_cats(fun); if (rc != EOK) { ddf_msg(LVL_ERROR, "Failed adding function to categories"); + ddf_fun_unbind(fun); return rc; } return EOK; diff --git a/uspace/drv/nic/ne2k/ne2k.c b/uspace/drv/nic/ne2k/ne2k.c index 3792e59565..7de396e22d 100644 --- a/uspace/drv/nic/ne2k/ne2k.c +++ b/uspace/drv/nic/ne2k/ne2k.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "dp8390.h" #define NAME "ne2k" @@ -442,17 +443,10 @@ static errno_t ne2k_dev_add(ddf_dev_t *dev) return rc; } - rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC); + rc = nic_fun_add_to_cats(fun); if (rc != EOK) { + ddf_msg(LVL_ERROR, "Failed adding function to categories"); ddf_fun_unbind(fun); - ddf_fun_destroy(fun); - return rc; - } - rc = ddf_fun_add_to_category(fun, "pcap"); - if (rc != EOK) { - //ddf_msg(LVL_ERROR, "Failed adding function to category pcap"); - ddf_fun_unbind(fun); - ddf_fun_destroy(fun); return rc; } @@ -482,6 +476,7 @@ int main(int argc, char *argv[]) nic_driver_init(NAME); nic_driver_implement(&ne2k_driver_ops, &ne2k_dev_ops, &ne2k_nic_iface); + ddf_log_init(NAME); return ddf_driver_main(&ne2k_driver); } diff --git a/uspace/drv/nic/rtl8139/driver.c b/uspace/drv/nic/rtl8139/driver.c index d4deeaa3b2..545c13cc61 100644 --- a/uspace/drv/nic/rtl8139/driver.c +++ b/uspace/drv/nic/rtl8139/driver.c @@ -1307,16 +1307,12 @@ errno_t rtl8139_dev_add(ddf_dev_t *dev) ddf_msg(LVL_ERROR, "Failed binding device function"); goto err_fun_create; } - rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC); - if (rc != EOK) { - ddf_msg(LVL_ERROR, "Failed adding function to category"); - goto err_fun_bind; - } - rc = ddf_fun_add_to_category(fun, "pcap"); + rc = nic_fun_add_to_cats(fun); if (rc != EOK) { - ddf_msg(LVL_ERROR, "Failed adding function to category pcap"); - goto err_fun_bind; + ddf_msg(LVL_ERROR, "Failed adding function to categories"); + ddf_fun_unbind(fun); + return rc; } ddf_msg(LVL_NOTE, "The %s device has been successfully initialized.", @@ -1324,8 +1320,8 @@ errno_t rtl8139_dev_add(ddf_dev_t *dev) return EOK; -err_fun_bind: - ddf_fun_unbind(fun); + // err_fun_bind: + // ddf_fun_unbind(fun); err_fun_create: ddf_fun_destroy(fun); err_srv: diff --git a/uspace/drv/nic/rtl8169/driver.c b/uspace/drv/nic/rtl8169/driver.c index 1b371140aa..e571f81d28 100644 --- a/uspace/drv/nic/rtl8169/driver.c +++ b/uspace/drv/nic/rtl8169/driver.c @@ -456,18 +456,19 @@ static errno_t rtl8169_dev_add(ddf_dev_t *dev) goto err_fun_create; } - rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC); + rc = nic_fun_add_to_cats(fun); if (rc != EOK) { - ddf_msg(LVL_ERROR, "Failed adding function to category"); - goto err_fun_bind; + ddf_msg(LVL_ERROR, "Failed adding function to categories"); + ddf_fun_unbind(fun); + return rc; } ddf_msg(LVL_NOTE, "The %s device has been successfully initialized.", ddf_dev_get_name(dev)); return EOK; -err_fun_bind: - ddf_fun_unbind(fun); + // err_fun_bind: + // ddf_fun_unbind(fun); err_fun_create: ddf_fun_destroy(fun); err_srv: diff --git a/uspace/drv/nic/virtio-net/virtio-net.c b/uspace/drv/nic/virtio-net/virtio-net.c index 1cf69ea2b1..6642094c23 100644 --- a/uspace/drv/nic/virtio-net/virtio-net.c +++ b/uspace/drv/nic/virtio-net/virtio-net.c @@ -422,25 +422,20 @@ static errno_t virtio_net_dev_add(ddf_dev_t *dev) goto destroy; } - rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC); + rc = nic_fun_add_to_cats(fun); if (rc != EOK) { - ddf_msg(LVL_ERROR, "Failed adding function to category"); - goto unbind; + ddf_msg(LVL_ERROR, "Failed adding function to categories"); + ddf_fun_unbind(fun); + return rc; } ddf_msg(LVL_NOTE, "The %s device has been successfully initialized.", ddf_dev_get_name(dev)); - rc = ddf_fun_add_to_category(fun, "pcap"); - if (rc != EOK) { - ddf_msg(LVL_ERROR, "Failed adding function to category pcap"); - goto unbind; - } - return EOK; -unbind: - ddf_fun_unbind(fun); + // unbind: + // ddf_fun_unbind(fun); destroy: ddf_fun_destroy(fun); uninitialize: From 2a0c827c42eafb070de3bbe3c98a1d8a2b77d719 Mon Sep 17 00:00:00 2001 From: Nataliia Korop Date: Sun, 7 Apr 2024 15:05:38 +0200 Subject: [PATCH 13/13] nic_device_added_impl decl delete --- uspace/lib/nic/include/nic_impl.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/uspace/lib/nic/include/nic_impl.h b/uspace/lib/nic/include/nic_impl.h index d09de679c1..72a43e121c 100644 --- a/uspace/lib/nic/include/nic_impl.h +++ b/uspace/lib/nic/include/nic_impl.h @@ -86,8 +86,6 @@ extern void nic_default_handler_impl(ddf_fun_t *dev_fun, ipc_call_t *call); extern errno_t nic_open_impl(ddf_fun_t *fun); extern void nic_close_impl(ddf_fun_t *fun); -extern void nic_device_added_impl(ddf_dev_t *dev); - #endif /** @}