diff options
author | Stefano Brivio <sbrivio@redhat.com> | 2021-05-21 11:14:48 +0200 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2021-05-21 11:14:48 +0200 |
commit | 17337a736ff0e7ebd7d5272eba7466a627795215 (patch) | |
tree | c1ebb233dbec7a926315f354eb9f9feb709da07b | |
parent | 59182924f01e4d2e8f6d8af27c355c191f332eba (diff) | |
download | passt-17337a736ff0e7ebd7d5272eba7466a627795215.tar passt-17337a736ff0e7ebd7d5272eba7466a627795215.tar.gz passt-17337a736ff0e7ebd7d5272eba7466a627795215.tar.bz2 passt-17337a736ff0e7ebd7d5272eba7466a627795215.tar.lz passt-17337a736ff0e7ebd7d5272eba7466a627795215.tar.xz passt-17337a736ff0e7ebd7d5272eba7466a627795215.tar.zst passt-17337a736ff0e7ebd7d5272eba7466a627795215.zip |
passt: Introduce packet capture implementation
With -DDEBUG, passt now saves guest-side traffic captures in
pcap format at /tmp/passt_<ISO8601 timestamp>.pcap. The timestamp
refers to time and date of start-up.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | passt.c | 5 | ||||
-rw-r--r-- | pcap.c | 108 | ||||
-rw-r--r-- | pcap.h | 2 | ||||
-rw-r--r-- | tap.c | 3 |
5 files changed, 120 insertions, 2 deletions
@@ -2,8 +2,8 @@ CFLAGS += -Wall -Wextra -pedantic all: passt qrap -passt: passt.c passt.h arp.c arp.h dhcp.c dhcp.h dhcpv6.c dhcpv6.h ndp.c ndp.h siphash.c siphash.h tap.c tap.h icmp.c icmp.h tcp.c tcp.h udp.c udp.h util.c util.h - $(CC) $(CFLAGS) passt.c arp.c dhcp.c dhcpv6.c ndp.c siphash.c tap.c icmp.c tcp.c udp.c util.c -o passt +passt: passt.c passt.h arp.c arp.h dhcp.c dhcp.h dhcpv6.c dhcpv6.h pcap.c pcap.h ndp.c ndp.h siphash.c siphash.h tap.c tap.h icmp.c icmp.h tcp.c tcp.h udp.c udp.h util.c util.h + $(CC) $(CFLAGS) passt.c arp.c dhcp.c dhcpv6.c pcap.c ndp.c siphash.c tap.c icmp.c tcp.c udp.c util.c -o passt qrap: qrap.c passt.h $(CC) $(CFLAGS) -DARCH=\"$(shell uname -m)\" qrap.c -o qrap @@ -53,6 +53,7 @@ #include "icmp.h" #include "tcp.h" #include "udp.h" +#include "pcap.h" #define EPOLL_EVENTS 10 @@ -601,6 +602,8 @@ static int tap_handler(struct ctx *c, struct timespec *now) return 0; } + pcap(p, len); + msg[msg_count].start = p; msg[msg_count++].len = len; @@ -792,6 +795,8 @@ int main(int argc, char **argv) memset(&c.mac_guest, 0xff, sizeof(c.mac_guest)); + pcap_init(); + if (c.v4) { info("ARP:"); info(" address: %02x:%02x:%02x:%02x:%02x:%02x from %s", @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later + +/* PASST - Plug A Simple Socket Transport + * + * pcap.c - Packet capture for PASST + * + * Copyright (c) 2021 Red Hat GmbH + * Author: Stefano Brivio <sbrivio@redhat.com> + * + */ + +#include <stdio.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <time.h> +#include <net/ethernet.h> +#include <unistd.h> + +#ifdef DEBUG + +#define PCAP_PREFIX "/tmp/passt_" +#define PCAP_ISO8601_FORMAT "%FT%H:%M:%SZ" +#define PCAP_ISO8601_STR "YYYY-MM-ddTHH:mm:ssZ" + +#define PCAP_VERSION_MINOR 4 + +static int pcap_fd = 1; + +/* See pcap.h from libpcap, or pcap-savefile(5) */ +static struct { + uint32_t magic; +#define PCAP_MAGIC 0xa1b2c3d4 + + uint16_t major; +#define PCAP_VERSION_MAJOR 2 + + uint16_t minor; +#define PCAP_VERSION_MINOR 4 + + int32_t thiszone; + uint32_t sigfigs; + uint32_t snaplen; + + uint32_t linktype; +#define PCAP_LINKTYPE_ETHERNET 1 +} pcap_hdr = { + PCAP_MAGIC, PCAP_VERSION_MAJOR, PCAP_VERSION_MINOR, 0, 0, ETH_MAX_MTU, + PCAP_LINKTYPE_ETHERNET +}; + +struct pcap_pkthdr { + uint32_t tv_sec; + uint32_t tv_usec; + uint32_t caplen; + uint32_t len; +}; + +void pcap(char *pkt, size_t len) +{ + struct pcap_pkthdr h; + struct timeval tv; + + if (pcap_fd == -1) + return; + + gettimeofday(&tv, NULL); + h.tv_sec = tv.tv_sec; + h.tv_usec = tv.tv_usec; + h.caplen = h.len = len; + + write(pcap_fd, &h, sizeof(h)); + write(pcap_fd, pkt, len); +} + +void pcap_init(void) +{ + char name[] = PCAP_PREFIX PCAP_ISO8601_STR ".pcap"; + struct timeval tv; + struct tm *tm; + + gettimeofday(&tv, NULL); + tm = localtime(&tv.tv_sec); + strftime(name + strlen(PCAP_PREFIX), sizeof(PCAP_ISO8601_STR) - 1, + PCAP_ISO8601_FORMAT, tm); + + pcap_fd = open(name, O_WRONLY | O_CREAT | O_APPEND | O_DSYNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (pcap_fd == -1) { + perror("open"); + return; + } + + write(pcap_fd, &pcap_hdr, sizeof(pcap_hdr)); +} + +#else /* DEBUG */ +void pcap(char *pkt, size_t len) { + (void)pkt; + (void)len; +} + +void pcap_init(void) { } +#endif @@ -0,0 +1,2 @@ +void pcap(char *pkt, size_t len); +void pcap_init(void); @@ -25,6 +25,7 @@ #include "passt.h" #include "util.h" +#include "pcap.h" /** * tap_send() - Send frame and qemu socket header with indication of length @@ -39,6 +40,8 @@ int tap_send(int fd, void *data, size_t len, int flags) uint32_t vnet_len = htonl(len); send(fd, &vnet_len, 4, MSG_DONTWAIT | MSG_NOSIGNAL); + pcap(data, len); + return send(fd, data, len, flags | MSG_DONTWAIT | MSG_NOSIGNAL); } |