diff --git a/Makefile b/Makefile index 213020b..fb4494a 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/passt.c b/passt.c index d0dcb26..6b6a317 100644 --- a/passt.c +++ b/passt.c @@ -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", diff --git a/pcap.c b/pcap.c new file mode 100644 index 0000000..2767b53 --- /dev/null +++ b/pcap.c @@ -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 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 diff --git a/pcap.h b/pcap.h new file mode 100644 index 0000000..00bafee --- /dev/null +++ b/pcap.h @@ -0,0 +1,2 @@ +void pcap(char *pkt, size_t len); +void pcap_init(void); diff --git a/tap.c b/tap.c index 5d2201a..70e4774 100644 --- a/tap.c +++ b/tap.c @@ -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); }