Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package passt for openSUSE:Factory checked in at 2024-06-24 20:50:33 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/passt (Old) and /work/SRC/openSUSE:Factory/.passt.new.18349 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "passt" Mon Jun 24 20:50:33 2024 rev:8 rq:1182961 version:20240607.8a83b53 Changes: -------- --- /work/SRC/openSUSE:Factory/passt/passt.changes 2024-05-28 17:27:18.736702202 +0200 +++ /work/SRC/openSUSE:Factory/.passt.new.18349/passt.changes 2024-06-24 20:51:19.103977619 +0200 @@ -1,0 +2,19 @@ +Mon Jun 17 07:57:52 UTC 2024 - dcer...@suse.com + +- Update to version 20240607.8a83b53: + * selinux: Allow access to user_devpts + * tcp, flow: Fix some error paths which didn't clean up flows properly + * util: Use 'long' to represent millisecond durations + * lineread: Use ssize_t for line lengths + * conf: Safer parsing of MAC addresses + * util: Use unsigned indices for bits in bitmaps + * clang-tidy: Enable the bugprone-macro-parentheses check + * Remove pointless macro parameters in CALL_PROTO_HANDLER + * udp: Make rport calculation more local + * tcp: Make pointer const in tcp_revert_seq + * log: Remove log_to_stdout option + * conf: Don't print usage via the logging subsystem + * conf: Remove unhelpful usage() wrapper + * tcp: move seq_to_tap update to when frame is queued + +------------------------------------------------------------------- Old: ---- passt-20240523.765eb0b.tar.zst New: ---- passt-20240607.8a83b53.tar.zst ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ passt.spec ++++++ --- /var/tmp/diff_new_pack.yS4Hq5/_old 2024-06-24 20:51:19.872005693 +0200 +++ /var/tmp/diff_new_pack.yS4Hq5/_new 2024-06-24 20:51:19.876005839 +0200 @@ -44,7 +44,7 @@ %endif Name: passt -Version: 20240523.765eb0b +Version: 20240607.8a83b53 Release: 0 Summary: User-mode networking daemons for virtual machines and namespaces License: GPL-2.0-or-later AND BSD-3-Clause ++++++ _service ++++++ --- /var/tmp/diff_new_pack.yS4Hq5/_old 2024-06-24 20:51:19.908007009 +0200 +++ /var/tmp/diff_new_pack.yS4Hq5/_new 2024-06-24 20:51:19.912007156 +0200 @@ -4,7 +4,7 @@ <param name="scm">git</param> <param name="changesgenerate">enable</param> <param name="versionformat">%cs.%h</param> - <param name="revision">2024_05_23.765eb0b</param> + <param name="revision">2024_06_07.8a83b53</param> </service> <service mode="manual" name="recompress"> <param name="file">*.tar</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.yS4Hq5/_old 2024-06-24 20:51:19.932007887 +0200 +++ /var/tmp/diff_new_pack.yS4Hq5/_new 2024-06-24 20:51:19.932007887 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://passt.top/passt</param> - <param name="changesrevision">765eb0bf1651d20ca319eeb8b41ff35f52f2a29c</param></service></servicedata> + <param name="changesrevision">8a83b530feeac1a9812fe457e86257430f6b2fed</param></service></servicedata> (No newline at EOF) ++++++ passt-20240523.765eb0b.tar.zst -> passt-20240607.8a83b53.tar.zst ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/Makefile new/passt-20240607.8a83b53/Makefile --- old/passt-20240523.765eb0b/Makefile 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/Makefile 2024-06-07 20:44:44.000000000 +0200 @@ -192,7 +192,6 @@ # - llvmlibc-restrict-system-libc-headers # TODO: this is Linux-only for the moment, nice to fix eventually # -# - bugprone-macro-parentheses # - google-readability-braces-around-statements # - hicpp-braces-around-statements # - readability-braces-around-statements @@ -269,7 +268,6 @@ -clang-analyzer-valist.Uninitialized,\ -cppcoreguidelines-init-variables,\ -bugprone-assignment-in-if-condition,\ - -bugprone-macro-parentheses,\ -google-readability-braces-around-statements,\ -hicpp-braces-around-statements,\ -readability-braces-around-statements,\ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/conf.c new/passt-20240607.8a83b53/conf.c --- old/passt-20240523.765eb0b/conf.c 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/conf.c 2024-06-07 20:44:44.000000000 +0200 @@ -401,9 +401,9 @@ struct fqdn *s = c->dns_search; struct lineread resolvconf; unsigned int added = 0; + ssize_t line_len; char *line, *end; const char *p; - int line_len; dns4_set = !c->ifi4 || !IN4_IS_ADDR_UNSPECIFIED(dns4); dns6_set = !c->ifi6 || !IN6_IS_ADDR_UNSPECIFIED(dns6); @@ -704,209 +704,207 @@ } /** - * print_usage() - Print usage, exit with given status code + * usage() - Print usage, exit with given status code * @name: Executable name + * @f: Stream to print usage info to * @status: Status code for exit() */ -static void print_usage(const char *name, int status) +static void usage(const char *name, FILE *f, int status) { if (strstr(name, "pasta")) { - info("Usage: %s [OPTION]... [COMMAND] [ARGS]...", name); - info(" %s [OPTION]... PID", name); - info(" %s [OPTION]... --netns [PATH|NAME]", name); - info(""); - info("Without PID or --netns, run the given command or a"); - info("default shell in a new network and user namespace, and"); - info("connect it via pasta."); + fprintf(f, "Usage: %s [OPTION]... [COMMAND] [ARGS]...\n", name); + fprintf(f, " %s [OPTION]... PID\n", name); + fprintf(f, " %s [OPTION]... --netns [PATH|NAME]\n", name); + fprintf(f, + "\n" + "Without PID or --netns, run the given command or a\n" + "default shell in a new network and user namespace, and\n" + "connect it via pasta.\n"); } else { - info("Usage: %s [OPTION]...", name); + fprintf(f, "Usage: %s [OPTION]...\n", name); } - info(""); - - info( " -d, --debug Be verbose"); - info( " --trace Be extra verbose, implies --debug"); - info( " -q, --quiet Don't print informational messages"); - info( " -f, --foreground Don't run in background"); - info( " default: run in background if started from a TTY"); - info( " -e, --stderr Log to stderr too"); - info( " default: log to system logger only if started from a TTY"); - info( " -l, --log-file PATH Log (only) to given file"); - info( " --log-size BYTES Maximum size of log file"); - info( " default: 1 MiB"); - info( " --runas UID|UID:GID Run as given UID, GID, which can be"); - info( " numeric, or login and group names"); - info( " default: drop to user \"nobody\""); - info( " -h, --help Display this help message and exit"); - info( " --version Show version and exit"); + fprintf(f, + "\n" + " -d, --debug Be verbose\n" + " --trace Be extra verbose, implies --debug\n" + " -q, --quiet Don't print informational messages\n" + " -f, --foreground Don't run in background\n" + " default: run in background if started from a TTY\n" + " -e, --stderr Log to stderr too\n" + " default: log to system logger only if started from a TTY\n" + " -l, --log-file PATH Log (only) to given file\n" + " --log-size BYTES Maximum size of log file\n" + " default: 1 MiB\n" + " --runas UID|UID:GID Run as given UID, GID, which can be\n" + " numeric, or login and group names\n" + " default: drop to user \"nobody\"\n" + " -h, --help Display this help message and exit\n" + " --version Show version and exit\n"); if (strstr(name, "pasta")) { - info( " -I, --ns-ifname NAME namespace interface name"); - info( " default: same interface name as external one"); + fprintf(f, + " -I, --ns-ifname NAME namespace interface name\n" + " default: same interface name as external one\n"); } else { - info( " -s, --socket PATH UNIX domain socket path"); - info( " default: probe free path starting from " - UNIX_SOCK_PATH, 1); - } - - info( " -F, --fd FD Use FD as pre-opened connected socket"); - info( " -p, --pcap FILE Log tap-facing traffic to pcap file"); - info( " -P, --pid FILE Write own PID to the given file"); - info( " -m, --mtu MTU Assign MTU via DHCP/NDP"); - info( " a zero value disables assignment"); - info( " default: 65520: maximum 802.3 MTU minus 802.3 header"); - info( " length, rounded to 32 bits (IPv4 words)"); - info( " -a, --address ADDR Assign IPv4 or IPv6 address ADDR"); - info( " can be specified zero to two times (for IPv4 and IPv6)"); - info( " default: use addresses from interface with default route"); - info( " -n, --netmask MASK Assign IPv4 MASK, dot-decimal or bits"); - info( " default: netmask from matching address on the host"); - info( " -M, --mac-addr ADDR Use source MAC address ADDR"); - info( " default: MAC address from interface with default route"); - info( " -g, --gateway ADDR Pass IPv4 or IPv6 address as gateway"); - info( " default: gateway from interface with default route"); - info( " -i, --interface NAME Interface for addresses and routes"); - info( " default: from --outbound-if4 and --outbound-if6, if any"); - info( " otherwise interface with first default route"); - info( " -o, --outbound ADDR Bind to address as outbound source"); - info( " can be specified zero to two times (for IPv4 and IPv6)"); - info( " default: use source address from routing tables"); - info( " --outbound-if4 NAME Bind to outbound interface for IPv4"); - info( " default: use interface from default route"); - info( " --outbound-if6 NAME Bind to outbound interface for IPv6"); - info( " default: use interface from default route"); - info( " -D, --dns ADDR Use IPv4 or IPv6 address as DNS"); - info( " can be specified multiple times"); - info( " a single, empty option disables DNS information"); + fprintf(f, + " -s, --socket PATH UNIX domain socket path\n" + " default: probe free path starting from " + UNIX_SOCK_PATH "\n", 1); + } + + fprintf(f, + " -F, --fd FD Use FD as pre-opened connected socket\n" + " -p, --pcap FILE Log tap-facing traffic to pcap file\n" + " -P, --pid FILE Write own PID to the given file\n" + " -m, --mtu MTU Assign MTU via DHCP/NDP\n" + " a zero value disables assignment\n" + " default: 65520: maximum 802.3 MTU minus 802.3 header\n" + " length, rounded to 32 bits (IPv4 words)\n" + " -a, --address ADDR Assign IPv4 or IPv6 address ADDR\n" + " can be specified zero to two times (for IPv4 and IPv6)\n" + " default: use addresses from interface with default route\n" + " -n, --netmask MASK Assign IPv4 MASK, dot-decimal or bits\n" + " default: netmask from matching address on the host\n" + " -M, --mac-addr ADDR Use source MAC address ADDR\n" + " default: MAC address from interface with default route\n" + " -g, --gateway ADDR Pass IPv4 or IPv6 address as gateway\n" + " default: gateway from interface with default route\n" + " -i, --interface NAME Interface for addresses and routes\n" + " default: from --outbound-if4 and --outbound-if6, if any\n" + " otherwise interface with first default route\n" + " -o, --outbound ADDR Bind to address as outbound source\n" + " can be specified zero to two times (for IPv4 and IPv6)\n" + " default: use source address from routing tables\n" + " --outbound-if4 NAME Bind to outbound interface for IPv4\n" + " default: use interface from default route\n" + " --outbound-if6 NAME Bind to outbound interface for IPv6\n" + " default: use interface from default route\n" + " -D, --dns ADDR Use IPv4 or IPv6 address as DNS\n" + " can be specified multiple times\n" + " a single, empty option disables DNS information\n"); if (strstr(name, "pasta")) - info( " default: don't use any addresses"); + fprintf(f, " default: don't use any addresses\n"); else - info( " default: use addresses from /etc/resolv.conf"); - - info( " -S, --search LIST Space-separated list, search domains"); - info( " a single, empty option disables the DNS search list"); + fprintf(f, " default: use addresses from /etc/resolv.conf\n"); + fprintf(f, + " -S, --search LIST Space-separated list, search domains\n" + " a single, empty option disables the DNS search list\n"); if (strstr(name, "pasta")) - info( " default: don't use any search list"); + fprintf(f, " default: don't use any search list\n"); else - info( " default: use search list from /etc/resolv.conf"); + fprintf(f, " default: use search list from /etc/resolv.conf\n"); if (strstr(name, "pasta")) - info(" --dhcp-dns \tPass DNS list via DHCP/DHCPv6/NDP"); + fprintf(f, " --dhcp-dns \tPass DNS list via DHCP/DHCPv6/NDP\n"); else - info(" --no-dhcp-dns No DNS list in DHCP/DHCPv6/NDP"); + fprintf(f, " --no-dhcp-dns No DNS list in DHCP/DHCPv6/NDP\n"); if (strstr(name, "pasta")) - info(" --dhcp-search Pass list via DHCP/DHCPv6/NDP"); + fprintf(f, " --dhcp-search Pass list via DHCP/DHCPv6/NDP\n"); else - info(" --no-dhcp-search No list in DHCP/DHCPv6/NDP"); + fprintf(f, " --no-dhcp-search No list in DHCP/DHCPv6/NDP\n"); - info( " --dns-forward ADDR Forward DNS queries sent to ADDR"); - info( " can be specified zero to two times (for IPv4 and IPv6)"); - info( " default: don't forward DNS queries"); - - info( " --no-tcp Disable TCP protocol handler"); - info( " --no-udp Disable UDP protocol handler"); - info( " --no-icmp Disable ICMP/ICMPv6 protocol handler"); - info( " --no-dhcp Disable DHCP server"); - info( " --no-ndp Disable NDP responses"); - info( " --no-dhcpv6 Disable DHCPv6 server"); - info( " --no-ra Disable router advertisements"); - info( " --no-map-gw Don't map gateway address to host"); - info( " -4, --ipv4-only Enable IPv4 operation only"); - info( " -6, --ipv6-only Enable IPv6 operation only"); + fprintf(f, + " --dns-forward ADDR Forward DNS queries sent to ADDR\n" + " can be specified zero to two times (for IPv4 and IPv6)\n" + " default: don't forward DNS queries\n" + " --no-tcp Disable TCP protocol handler\n" + " --no-udp Disable UDP protocol handler\n" + " --no-icmp Disable ICMP/ICMPv6 protocol handler\n" + " --no-dhcp Disable DHCP server\n" + " --no-ndp Disable NDP responses\n" + " --no-dhcpv6 Disable DHCPv6 server\n" + " --no-ra Disable router advertisements\n" + " --no-map-gw Don't map gateway address to host\n" + " -4, --ipv4-only Enable IPv4 operation only\n" + " -6, --ipv6-only Enable IPv6 operation only\n"); if (strstr(name, "pasta")) goto pasta_opts; - info( " -1, --one-off Quit after handling one single client"); - info( " -t, --tcp-ports SPEC TCP port forwarding to guest"); - info( " can be specified multiple times"); - info( " SPEC can be:"); - info( " 'none': don't forward any ports"); - info( " 'all': forward all unbound, non-ephemeral ports"); - info( " a comma-separated list, optionally ranged with '-'"); - info( " and optional target ports after ':', with optional"); - info( " address specification suffixed by '/' and optional"); - info( " interface prefixed by '%%'. Ranges can be reduced by"); - info( " excluding ports or ranges prefixed by '~'"); - info( " Examples:"); - info( " -t 22 Forward local port 22 to 22 on guest"); - info( " -t 22:23 Forward local port 22 to 23 on guest"); - info( " -t 22,25 Forward ports 22, 25 to ports 22, 25"); - info( " -t 22-80 Forward ports 22 to 80"); - info( " -t 22-80:32-90 Forward ports 22 to 80 to"); - info( " corresponding port numbers plus 10"); - info( " -t 192.0.2.1/5 Bind port 5 of 192.0.2.1 to guest"); - info( " -t 5-25,~10-20 Forward ports 5 to 9, and 21 to 25"); - info( " -t ~25 Forward all ports except for 25"); - info( " default: none"); - info( " -u, --udp-ports SPEC UDP port forwarding to guest"); - info( " SPEC is as described for TCP above"); - info( " default: none"); + fprintf(f, + " -1, --one-off Quit after handling one single client\n" + " -t, --tcp-ports SPEC TCP port forwarding to guest\n" + " can be specified multiple times\n" + " SPEC can be:\n" + " 'none': don't forward any ports\n" + " 'all': forward all unbound, non-ephemeral ports\n" + " a comma-separated list, optionally ranged with '-'\n" + " and optional target ports after ':', with optional\n" + " address specification suffixed by '/' and optional\n" + " interface prefixed by '%%'. Ranges can be reduced by\n" + " excluding ports or ranges prefixed by '~'\n" + " Examples:\n" + " -t 22 Forward local port 22 to 22 on guest\n" + " -t 22:23 Forward local port 22 to 23 on guest\n" + " -t 22,25 Forward ports 22, 25 to ports 22, 25\n" + " -t 22-80 Forward ports 22 to 80\n" + " -t 22-80:32-90 Forward ports 22 to 80 to\n" + " corresponding port numbers plus 10\n" + " -t 192.0.2.1/5 Bind port 5 of 192.0.2.1 to guest\n" + " -t 5-25,~10-20 Forward ports 5 to 9, and 21 to 25\n" + " -t ~25 Forward all ports except for 25\n" + " default: none\n" + " -u, --udp-ports SPEC UDP port forwarding to guest\n" + " SPEC is as described for TCP above\n" + " default: none\n"); exit(status); pasta_opts: - info( " -t, --tcp-ports SPEC TCP port forwarding to namespace"); - info( " can be specified multiple times"); - info( " SPEC can be:"); - info( " 'none': don't forward any ports"); - info( " 'auto': forward all ports currently bound in namespace"); - info( " a comma-separated list, optionally ranged with '-'"); - info( " and optional target ports after ':', with optional"); - info( " address specification suffixed by '/' and optional"); - info( " interface prefixed by '%%'. Examples:"); - info( " -t 22 Forward local port 22 to port 22 in netns"); - info( " -t 22:23 Forward local port 22 to port 23"); - info( " -t 22,25 Forward ports 22, 25 to ports 22, 25"); - info( " -t 22-80 Forward ports 22 to 80"); - info( " -t 22-80:32-90 Forward ports 22 to 80 to"); - info( " corresponding port numbers plus 10"); - info( " -t 192.0.2.1/5 Bind port 5 of 192.0.2.1 to namespace"); - info( " -t 5-25,~10-20 Forward ports 5 to 9, and 21 to 25"); - info( " -t ~25 Forward all bound ports except for 25"); - info( " default: auto"); - info( " IPv6 bound ports are also forwarded for IPv4"); - info( " -u, --udp-ports SPEC UDP port forwarding to namespace"); - info( " SPEC is as described for TCP above"); - info( " default: auto"); - info( " IPv6 bound ports are also forwarded for IPv4"); - info( " unless specified, with '-t auto', UDP ports with numbers"); - info( " corresponding to forwarded TCP port numbers are"); - info( " forwarded too"); - info( " -T, --tcp-ns SPEC TCP port forwarding to init namespace"); - info( " SPEC is as described above"); - info( " default: auto"); - info( " -U, --udp-ns SPEC UDP port forwarding to init namespace"); - info( " SPEC is as described above"); - info( " default: auto"); - info( " --userns NSPATH Target user namespace to join"); - info( " --netns PATH|NAME Target network namespace to join"); - info( " --netns-only Don't join existing user namespace"); - info( " implied if PATH or NAME are given without --userns"); - info( " --no-netns-quit Don't quit if filesystem-bound target"); - info( " network namespace is deleted"); - info( " --config-net Configure tap interface in namespace"); - info( " --no-copy-routes DEPRECATED:"); - info( " Don't copy all routes to namespace"); - info( " --no-copy-addrs DEPRECATED:"); - info( " Don't copy all addresses to namespace"); - info( " --ns-mac-addr ADDR Set MAC address on tap interface"); + fprintf(f, + " -t, --tcp-ports SPEC TCP port forwarding to namespace\n" + " can be specified multiple times\n" + " SPEC can be:\n" + " 'none': don't forward any ports\n" + " 'auto': forward all ports currently bound in namespace\n" + " a comma-separated list, optionally ranged with '-'\n" + " and optional target ports after ':', with optional\n" + " address specification suffixed by '/' and optional\n" + " interface prefixed by '%%'. Examples:\n" + " -t 22 Forward local port 22 to port 22 in netns\n" + " -t 22:23 Forward local port 22 to port 23\n" + " -t 22,25 Forward ports 22, 25 to ports 22, 25\n" + " -t 22-80 Forward ports 22 to 80\n" + " -t 22-80:32-90 Forward ports 22 to 80 to\n" + " corresponding port numbers plus 10\n" + " -t 192.0.2.1/5 Bind port 5 of 192.0.2.1 to namespace\n" + " -t 5-25,~10-20 Forward ports 5 to 9, and 21 to 25\n" + " -t ~25 Forward all bound ports except for 25\n" + " default: auto\n" + " IPv6 bound ports are also forwarded for IPv4\n" + " -u, --udp-ports SPEC UDP port forwarding to namespace\n" + " SPEC is as described for TCP above\n" + " default: auto\n" + " IPv6 bound ports are also forwarded for IPv4\n" + " unless specified, with '-t auto', UDP ports with numbers\n" + " corresponding to forwarded TCP port numbers are\n" + " forwarded too\n" + " -T, --tcp-ns SPEC TCP port forwarding to init namespace\n" + " SPEC is as described above\n" + " default: auto\n" + " -U, --udp-ns SPEC UDP port forwarding to init namespace\n" + " SPEC is as described above\n" + " default: auto\n" + " --userns NSPATH Target user namespace to join\n" + " --netns PATH|NAME Target network namespace to join\n" + " --netns-only Don't join existing user namespace\n" + " implied if PATH or NAME are given without --userns\n" + " --no-netns-quit Don't quit if filesystem-bound target\n" + " network namespace is deleted\n" + " --config-net Configure tap interface in namespace\n" + " --no-copy-routes DEPRECATED:\n" + " Don't copy all routes to namespace\n" + " --no-copy-addrs DEPRECATED:\n" + " Don't copy all addresses to namespace\n" + " --ns-mac-addr ADDR Set MAC address on tap interface\n"); exit(status); } /** - * usage() - Print usage and exit with failure - * @name: Executable name - */ -static void usage(const char *name) -{ - print_usage(name, EXIT_FAILURE); -} - -/** * conf_print() - Print fundamental configuration parameters * @c: Execution context */ @@ -1127,6 +1125,39 @@ } /** + * parse_mac - Parse a MAC address from a string + * @mac: Binary MAC address, initialised on success + * @str: String to parse + * + * Parses @str as an Ethernet MAC address stored in @mac on success. Exits on + * failure. + */ +static void parse_mac(unsigned char mac[ETH_ALEN], const char *str) +{ + size_t i; + + if (strlen(str) != (ETH_ALEN * 3 - 1)) + goto fail; + + for (i = 0; i < ETH_ALEN; i++) { + const char *octet = str + 3 * i; + unsigned long b; + char *end; + + errno = 0; + b = strtoul(octet, &end, 16); + if (b > UCHAR_MAX || errno || end != octet + 2 || + *end != ((i == ETH_ALEN - 1) ? '\0' : ':')) + goto fail; + mac[i] = b; + } + return; + +fail: + die("Invalid MAC address: %s", str); +} + +/** * conf() - Process command-line arguments and set configuration * @c: Execution context * @argc: Argument count @@ -1202,9 +1233,9 @@ unsigned int ifi4 = 0, ifi6 = 0; const char *logfile = NULL; const char *optstring; - int name, ret, b, i; size_t logsize = 0; char *runas = NULL; + int name, ret; uid_t uid; gid_t gid; @@ -1245,14 +1276,7 @@ if (c->mode != MODE_PASTA) die("--ns-mac-addr is for pasta mode only"); - for (i = 0; i < ETH_ALEN; i++) { - errno = 0; - b = strtol(optarg + (intptr_t)i * 3, NULL, 16); - if (b < 0 || b > UCHAR_MAX || errno) - die("Invalid MAC address: %s", optarg); - - c->mac_guest[i] = b; - } + parse_mac(c->mac_guest, optarg); break; case 5: if (c->mode != MODE_PASTA) @@ -1512,14 +1536,7 @@ break; case 'M': - for (i = 0; i < ETH_ALEN; i++) { - errno = 0; - b = strtol(optarg + (intptr_t)i * 3, NULL, 16); - if (b < 0 || b > UCHAR_MAX || errno) - die("Invalid MAC address: %s", optarg); - - c->mac[i] = b; - } + parse_mac(c->mac, optarg); break; case 'g': if (c->mode == MODE_PASTA) @@ -1646,12 +1663,11 @@ /* Handle these later, once addresses are configured */ break; case 'h': - log_to_stdout = 1; - print_usage(argv[0], EXIT_SUCCESS); + usage(argv[0], stdout, EXIT_SUCCESS); break; case '?': default: - usage(argv[0]); + usage(argv[0], stderr, EXIT_FAILURE); break; } } while (name != -1); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/contrib/selinux/pasta.te new/passt-20240607.8a83b53/contrib/selinux/pasta.te --- old/passt-20240523.765eb0b/contrib/selinux/pasta.te 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/contrib/selinux/pasta.te 2024-06-07 20:44:44.000000000 +0200 @@ -211,3 +211,4 @@ allow pasta_t netutils_t:process { noatsecure rlimitinh siginh }; allow pasta_t ping_t:process { noatsecure rlimitinh siginh }; allow pasta_t user_tty_device_t:chr_file { append read write }; +allow pasta_t user_devpts_t:chr_file { append read write }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/lineread.c new/passt-20240607.8a83b53/lineread.c --- old/passt-20240523.765eb0b/lineread.c 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/lineread.c 2024-06-07 20:44:44.000000000 +0200 @@ -39,13 +39,11 @@ * * Return: length of line in bytes, -1 if no line was found */ -static int peek_line(struct lineread *lr, bool eof) +static ssize_t peek_line(struct lineread *lr, bool eof) { char *nl; /* Sanity checks (which also document invariants) */ - ASSERT(lr->count >= 0); - ASSERT(lr->next_line >= 0); ASSERT(lr->next_line + lr->count >= lr->next_line); ASSERT(lr->next_line + lr->count <= LINEREAD_BUFFER_SIZE); @@ -74,13 +72,13 @@ * * Return: Length of line read on success, 0 on EOF, negative on error */ -int lineread_get(struct lineread *lr, char **line) +ssize_t lineread_get(struct lineread *lr, char **line) { bool eof = false; - int line_len; + ssize_t line_len; while ((line_len = peek_line(lr, eof)) < 0) { - int rc; + ssize_t rc; if ((lr->next_line + lr->count) == LINEREAD_BUFFER_SIZE) { /* No space at end */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/lineread.h new/passt-20240607.8a83b53/lineread.h --- old/passt-20240523.765eb0b/lineread.h 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/lineread.h 2024-06-07 20:44:44.000000000 +0200 @@ -18,14 +18,15 @@ * @buf: Buffer storing data read from file. */ struct lineread { - int fd; int next_line; - int count; + int fd; + ssize_t next_line; + ssize_t count; /* One extra byte for possible trailing \0 */ char buf[LINEREAD_BUFFER_SIZE+1]; }; void lineread_init(struct lineread *lr, int fd); -int lineread_get(struct lineread *lr, char **line); +ssize_t lineread_get(struct lineread *lr, char **line); #endif /* _LINEREAD_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/log.c new/passt-20240607.8a83b53/log.c --- old/passt-20240523.765eb0b/log.c 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/log.c 2024-06-07 20:44:44.000000000 +0200 @@ -46,18 +46,16 @@ static time_t log_start; /* Start timestamp */ int log_trace; /* --trace mode enabled */ -int log_to_stdout; /* Print to stdout instead of stderr */ void vlogmsg(int pri, const char *format, va_list ap) { bool debug_print = (log_mask & LOG_MASK(LOG_DEBUG)) && log_file == -1; bool early_print = LOG_PRI(log_mask) == LOG_EARLY; - FILE *out = log_to_stdout ? stdout : stderr; struct timespec tp; if (debug_print) { clock_gettime(CLOCK_REALTIME, &tp); - fprintf(out, "%lli.%04lli: ", + fprintf(stderr, "%lli.%04lli: ", (long long int)tp.tv_sec - log_start, (long long int)tp.tv_nsec / (100L * 1000)); } @@ -75,9 +73,9 @@ } if (debug_print || (early_print && !(log_opt & LOG_PERROR))) { - (void)vfprintf(out, format, ap); + (void)vfprintf(stderr, format, ap); if (format[strlen(format)] != '\n') - fprintf(out, "\n"); + fprintf(stderr, "\n"); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/log.h new/passt-20240607.8a83b53/log.h --- old/passt-20240523.765eb0b/log.h 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/log.h 2024-06-07 20:44:44.000000000 +0200 @@ -28,7 +28,6 @@ } while (0) extern int log_trace; -extern int log_to_stdout; void trace_init(int enable); #define trace(...) \ do { \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/passt.c new/passt-20240607.8a83b53/passt.c --- old/passt-20240523.765eb0b/passt.c 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/passt.c 2024-06-07 20:44:44.000000000 +0200 @@ -84,7 +84,7 @@ */ static void post_handler(struct ctx *c, const struct timespec *now) { -#define CALL_PROTO_HANDLER(c, now, lc, uc) \ +#define CALL_PROTO_HANDLER(lc, uc) \ do { \ extern void \ lc ## _defer_handler (struct ctx *c) \ @@ -103,9 +103,9 @@ } while (0) /* NOLINTNEXTLINE(bugprone-branch-clone): intervals can be the same */ - CALL_PROTO_HANDLER(c, now, tcp, TCP); + CALL_PROTO_HANDLER(tcp, TCP); /* NOLINTNEXTLINE(bugprone-branch-clone): intervals can be the same */ - CALL_PROTO_HANDLER(c, now, udp, UDP); + CALL_PROTO_HANDLER(udp, UDP); flow_defer_handler(c, now); #undef CALL_PROTO_HANDLER diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/tap.c new/passt-20240607.8a83b53/tap.c --- old/passt-20240523.765eb0b/tap.c 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/tap.c 2024-06-07 20:44:44.000000000 +0200 @@ -674,18 +674,18 @@ continue; } -#define L4_MATCH(iph, uh, seq) \ - (seq->protocol == iph->protocol && \ - seq->source == uh->source && seq->dest == uh->dest && \ - seq->saddr.s_addr == iph->saddr && seq->daddr.s_addr == iph->daddr) +#define L4_MATCH(iph, uh, seq) \ + ((seq)->protocol == (iph)->protocol && \ + (seq)->source == (uh)->source && (seq)->dest == (uh)->dest && \ + (seq)->saddr.s_addr == (iph)->saddr && (seq)->daddr.s_addr == (iph)->daddr) #define L4_SET(iph, uh, seq) \ do { \ - seq->protocol = iph->protocol; \ - seq->source = uh->source; \ - seq->dest = uh->dest; \ - seq->saddr.s_addr = iph->saddr; \ - seq->daddr.s_addr = iph->daddr; \ + (seq)->protocol = (iph)->protocol; \ + (seq)->source = (uh)->source; \ + (seq)->dest = (uh)->dest; \ + (seq)->saddr.s_addr = (iph)->saddr; \ + (seq)->daddr.s_addr = (iph)->daddr; \ } while (0) if (seq && L4_MATCH(iph, uh, seq) && seq->p.count < UIO_MAXIOV) @@ -848,18 +848,19 @@ } #define L4_MATCH(ip6h, proto, uh, seq) \ - (seq->protocol == proto && \ - seq->source == uh->source && seq->dest == uh->dest && \ - IN6_ARE_ADDR_EQUAL(&seq->saddr, saddr) && \ - IN6_ARE_ADDR_EQUAL(&seq->daddr, daddr)) + ((seq)->protocol == (proto) && \ + (seq)->source == (uh)->source && \ + (seq)->dest == (uh)->dest && \ + IN6_ARE_ADDR_EQUAL(&(seq)->saddr, saddr) && \ + IN6_ARE_ADDR_EQUAL(&(seq)->daddr, daddr)) #define L4_SET(ip6h, proto, uh, seq) \ do { \ - seq->protocol = proto; \ - seq->source = uh->source; \ - seq->dest = uh->dest; \ - seq->saddr = *saddr; \ - seq->daddr = *daddr; \ + (seq)->protocol = (proto); \ + (seq)->source = (uh)->source; \ + (seq)->dest = (uh)->dest; \ + (seq)->saddr = *saddr; \ + (seq)->daddr = *daddr; \ } while (0) if (seq && L4_MATCH(ip6h, proto, uh, seq) && diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/tcp.c new/passt-20240607.8a83b53/tcp.c --- old/passt-20240523.765eb0b/tcp.c 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/tcp.c 2024-06-07 20:44:44.000000000 +0200 @@ -326,7 +326,7 @@ #define WINDOW_DEFAULT 14600 /* RFC 6928 */ #ifdef HAS_SND_WND -# define KERNEL_REPORTS_SND_WND(c) (c->tcp.kernel_snd_wnd) +# define KERNEL_REPORTS_SND_WND(c) ((c)->tcp.kernel_snd_wnd) #else # define KERNEL_REPORTS_SND_WND(c) (0 && (c)) #endif @@ -373,9 +373,9 @@ #define CONN_V4(conn) (!!inany_v4(&(conn)->faddr)) #define CONN_V6(conn) (!CONN_V4(conn)) #define CONN_IS_CLOSING(conn) \ - ((conn->events & ESTABLISHED) && \ - (conn->events & (SOCK_FIN_RCVD | TAP_FIN_RCVD))) -#define CONN_HAS(conn, set) ((conn->events & (set)) == (set)) + (((conn)->events & ESTABLISHED) && \ + ((conn)->events & (SOCK_FIN_RCVD | TAP_FIN_RCVD))) +#define CONN_HAS(conn, set) (((conn)->events & (set)) == (set)) static const char *tcp_event_str[] __attribute((__unused__)) = { "SOCK_ACCEPTED", "TAP_SYN_RCVD", "ESTABLISHED", "TAP_SYN_ACK_SENT", @@ -408,16 +408,6 @@ */ static union inany_addr low_rtt_dst[LOW_RTT_TABLE_SIZE]; -/** - * tcp_buf_seq_update - Sequences to update with length of frames once sent - * @seq: Pointer to sequence number sent to tap-side, to be updated - * @len: TCP payload length - */ -struct tcp_buf_seq_update { - uint32_t *seq; - uint16_t len; -}; - /* Static buffers */ /** * struct tcp_payload_t - TCP header and data to send segments with payload @@ -459,7 +449,8 @@ static_assert(MSS4 <= sizeof(tcp4_payload[0].data), "MSS4 is greater than 65516"); -static struct tcp_buf_seq_update tcp4_seq_update[TCP_FRAMES_MEM]; +/* References tracking the owner connection of frames in the tap outqueue */ +static struct tcp_tap_conn *tcp4_frame_conns[TCP_FRAMES_MEM]; static unsigned int tcp4_payload_used; static struct tap_hdr tcp4_flags_tap_hdr[TCP_FRAMES_MEM]; @@ -481,7 +472,8 @@ static_assert(MSS6 <= sizeof(tcp6_payload[0].data), "MSS6 is greater than 65516"); -static struct tcp_buf_seq_update tcp6_seq_update[TCP_FRAMES_MEM]; +/* References tracking the owner connection of frames in the tap outqueue */ +static struct tcp_tap_conn *tcp6_frame_conns[TCP_FRAMES_MEM]; static unsigned int tcp6_payload_used; static struct tap_hdr tcp6_flags_tap_hdr[TCP_FRAMES_MEM]; @@ -1258,24 +1250,50 @@ } /** + * tcp_revert_seq() - Revert affected conn->seq_to_tap after failed transmission + * @conns: Array of connection pointers corresponding to queued frames + * @frames: Two-dimensional array containing queued frames with sub-iovs + * @num_frames: Number of entries in the two arrays to be compared + */ +static void tcp_revert_seq(struct tcp_tap_conn **conns, struct iovec (*frames)[TCP_NUM_IOVS], + int num_frames) +{ + int i; + + for (i = 0; i < num_frames; i++) { + const struct tcphdr *th = frames[i][TCP_IOV_PAYLOAD].iov_base; + struct tcp_tap_conn *conn = conns[i]; + uint32_t seq = ntohl(th->seq); + + if (SEQ_LE(conn->seq_to_tap, seq)) + continue; + + conn->seq_to_tap = seq; + } +} + +/** * tcp_payload_flush() - Send out buffers for segments with data * @c: Execution context */ static void tcp_payload_flush(const struct ctx *c) { - unsigned i; size_t m; m = tap_send_frames(c, &tcp6_l2_iov[0][0], TCP_NUM_IOVS, tcp6_payload_used); - for (i = 0; i < m; i++) - *tcp6_seq_update[i].seq += tcp6_seq_update[i].len; + if (m != tcp6_payload_used) { + tcp_revert_seq(&tcp6_frame_conns[m], &tcp6_l2_iov[m], + tcp6_payload_used - m); + } tcp6_payload_used = 0; m = tap_send_frames(c, &tcp4_l2_iov[0][0], TCP_NUM_IOVS, tcp4_payload_used); - for (i = 0; i < m; i++) - *tcp4_seq_update[i].seq += tcp4_seq_update[i].len; + if (m != tcp4_payload_used) { + tcp_revert_seq(&tcp4_frame_conns[m], &tcp4_l2_iov[m], + tcp4_payload_used - m); + } tcp4_payload_used = 0; } @@ -2049,7 +2067,7 @@ if (!bind(s, sa, sl)) { tcp_rst(c, conn); /* Nobody is listening then */ - return; + goto cancel; } if (errno != EADDRNOTAVAIL && errno != EACCES) conn_flag(c, conn, LOCAL); @@ -2062,7 +2080,7 @@ if (connect(s, sa, sl)) { if (errno != EINPROGRESS) { tcp_rst(c, conn); - return; + goto cancel; } tcp_get_sndbuf(conn); @@ -2070,7 +2088,7 @@ tcp_get_sndbuf(conn); if (tcp_send_flag(c, conn, SYN | ACK)) - return; + goto cancel; conn_event(c, conn, TAP_SYN_ACK_SENT); } @@ -2129,10 +2147,11 @@ static void tcp_data_to_tap(const struct ctx *c, struct tcp_tap_conn *conn, ssize_t dlen, int no_csum, uint32_t seq) { - uint32_t *seq_update = &conn->seq_to_tap; struct iovec *iov; size_t l4len; + conn->seq_to_tap = seq + dlen; + if (CONN_V4(conn)) { struct iovec *iov_prev = tcp4_l2_iov[tcp4_payload_used - 1]; const uint16_t *check = NULL; @@ -2142,8 +2161,7 @@ check = &iph->check; } - tcp4_seq_update[tcp4_payload_used].seq = seq_update; - tcp4_seq_update[tcp4_payload_used].len = dlen; + tcp4_frame_conns[tcp4_payload_used] = conn; iov = tcp4_l2_iov[tcp4_payload_used++]; l4len = tcp_l2_buf_fill_headers(c, conn, iov, dlen, check, seq); @@ -2151,8 +2169,7 @@ if (tcp4_payload_used > TCP_FRAMES_MEM - 1) tcp_payload_flush(c); } else if (CONN_V6(conn)) { - tcp6_seq_update[tcp6_payload_used].seq = seq_update; - tcp6_seq_update[tcp6_payload_used].len = dlen; + tcp6_frame_conns[tcp6_payload_used] = conn; iov = tcp6_l2_iov[tcp6_payload_used++]; l4len = tcp_l2_buf_fill_headers(c, conn, iov, dlen, NULL, seq); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/tcp_splice.c new/passt-20240607.8a83b53/tcp_splice.c --- old/passt-20240523.765eb0b/tcp_splice.c 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/tcp_splice.c 2024-06-07 20:44:44.000000000 +0200 @@ -73,9 +73,9 @@ /* Pool of pre-opened pipes */ static int splice_pipe_pool [TCP_SPLICE_PIPE_POOL_SIZE][2]; -#define CONN_V6(x) (x->flags & SPLICE_V6) +#define CONN_V6(x) ((x)->flags & SPLICE_V6) #define CONN_V4(x) (!CONN_V6(x)) -#define CONN_HAS(conn, set) ((conn->events & (set)) == (set)) +#define CONN_HAS(conn, set) (((conn)->events & (set)) == (set)) #define CONN(idx) (&FLOW(idx)->tcp_splice) /* Display strings for connection events */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/udp.c new/passt-20240607.8a83b53/udp.c --- old/passt-20240523.765eb0b/udp.c 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/udp.c 2024-06-07 20:44:44.000000000 +0200 @@ -277,10 +277,9 @@ "Forward and reverse delta arrays must have same size"); for (i = 0; i < ARRAY_SIZE(fwd->f.delta); i++) { in_port_t delta = fwd->f.delta[i]; - in_port_t rport = i + delta; if (delta) - fwd->rdelta[rport] = NUM_PORTS - delta; + fwd->rdelta[i + delta] = NUM_PORTS - delta; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/util.c new/passt-20240607.8a83b53/util.c --- old/passt-20240523.765eb0b/util.c 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/util.c 2024-06-07 20:44:44.000000000 +0200 @@ -216,7 +216,7 @@ * * Return: difference in milliseconds */ -int timespec_diff_ms(const struct timespec *a, const struct timespec *b) +long timespec_diff_ms(const struct timespec *a, const struct timespec *b) { if (a->tv_nsec < b->tv_nsec) { return (b->tv_nsec - a->tv_nsec) / 1000000 + @@ -232,7 +232,7 @@ * @map: Pointer to bitmap * @bit: Bit number to set */ -void bitmap_set(uint8_t *map, int bit) +void bitmap_set(uint8_t *map, unsigned bit) { unsigned long *word = (unsigned long *)map + BITMAP_WORD(bit); @@ -244,7 +244,7 @@ * @map: Pointer to bitmap * @bit: Bit number to clear */ -void bitmap_clear(uint8_t *map, int bit) +void bitmap_clear(uint8_t *map, unsigned bit) { unsigned long *word = (unsigned long *)map + BITMAP_WORD(bit); @@ -256,9 +256,9 @@ * @map: Pointer to bitmap * @bit: Bit number to check * - * Return: one if given bit is set, zero if it's not + * Return: true if given bit is set, false if it's not */ -int bitmap_isset(const uint8_t *map, int bit) +bool bitmap_isset(const uint8_t *map, unsigned bit) { const unsigned long *word = (const unsigned long *)map + BITMAP_WORD(bit); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/passt-20240523.765eb0b/util.h new/passt-20240607.8a83b53/util.h --- old/passt-20240523.765eb0b/util.h 2024-05-23 16:44:21.000000000 +0200 +++ new/passt-20240607.8a83b53/util.h 2024-06-07 20:44:44.000000000 +0200 @@ -147,10 +147,10 @@ const void *bind_addr, const char *ifname, uint16_t port, uint32_t data); void sock_probe_mem(struct ctx *c); -int timespec_diff_ms(const struct timespec *a, const struct timespec *b); -void bitmap_set(uint8_t *map, int bit); -void bitmap_clear(uint8_t *map, int bit); -int bitmap_isset(const uint8_t *map, int bit); +long timespec_diff_ms(const struct timespec *a, const struct timespec *b); +void bitmap_set(uint8_t *map, unsigned bit); +void bitmap_clear(uint8_t *map, unsigned bit); +bool bitmap_isset(const uint8_t *map, unsigned bit); void bitmap_or(uint8_t *dst, size_t size, const uint8_t *a, const uint8_t *b); char *line_read(char *buf, size_t len, int fd); void ns_enter(const struct ctx *c);