passt: Add clang-tidy Makefile target and test, take care of warnings

Most are just about style and form, but a few were actually
serious mistakes (NDP-related).

Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
Stefano Brivio 2021-10-20 00:05:11 +02:00
parent 7f1e7019cb
commit 12cfa6444c
14 changed files with 172 additions and 73 deletions

View file

@ -87,3 +87,78 @@ pkgs:
fakeroot alien --to-rpm --target=$(shell uname -m) \ fakeroot alien --to-rpm --target=$(shell uname -m) \
--description="User-mode networking for VMs and namespaces" \ --description="User-mode networking for VMs and namespaces" \
-k --version=g$(shell git rev-parse --short HEAD) passt.tar.gz -k --version=g$(shell git rev-parse --short HEAD) passt.tar.gz
# Checkers currently disabled for clang-tidy:
# - 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
# Debatable whether that improves readability, right now it would look
# like a mess
#
# - readability-magic-numbers
# - cppcoreguidelines-avoid-magic-numbers
# TODO: in most cases they are justified, but probably not everywhere
#
# - clang-analyzer-valist.Uninitialized
# TODO: enable once https://bugs.llvm.org/show_bug.cgi?id=41311 is fixed
#
# - clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling
# Probably not doable to impement this without plain memcpy(), memset()
#
# - cppcoreguidelines-init-variables
# Dubious value, would kill readability
#
# - hicpp-signed-bitwise
# Those are needed for syscalls, epoll_wait flags, etc.
#
# - bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp
# This flags _GNU_SOURCE, currently needed
#
# - llvm-include-order
# TODO: not really important, but nice to fix eventually
#
# - readability-isolate-declaration
# Dubious value, would kill readability
#
# - android-cloexec-open
# - android-cloexec-pipe
# - android-cloexec-pipe2
# - android-cloexec-epoll-create1
# TODO: check, fix except for the few cases where we need to share fds
#
# - bugprone-narrowing-conversions
# - cppcoreguidelines-narrowing-conversions
# TODO: nice to fix eventually
#
# - cppcoreguidelines-avoid-non-const-global-variables
# TODO: check, fix, and more in general constify wherever possible
#
# - bugprone-suspicious-string-compare
# Return value of memcmp(), not really suspicious
clang-tidy: $(wildcard *.c)
clang-tidy -checks=*,-modernize-*,\
-clang-analyzer-valist.Uninitialized,\
-cppcoreguidelines-init-variables,\
-bugprone-macro-parentheses,\
-google-readability-braces-around-statements,\
-hicpp-braces-around-statements,\
-readability-braces-around-statements,\
-readability-magic-numbers,\
-llvmlibc-restrict-system-libc-headers,\
-hicpp-signed-bitwise,\
-bugprone-reserved-identifier,-cert-dcl37-c,-cert-dcl51-cpp,\
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,\
-llvm-include-order,\
-cppcoreguidelines-avoid-magic-numbers,\
-readability-isolate-declaration,\
-android-cloexec-open,-android-cloexec-pipe,-android-cloexec-pipe2,\
-android-cloexec-epoll-create1,\
-bugprone-narrowing-conversions,\
-cppcoreguidelines-narrowing-conversions,\
-cppcoreguidelines-avoid-non-const-global-variables,\
-bugprone-suspicious-string-compare \
--warnings-as-errors=* $(wildcard *.c) -- $(CFLAGS)

9
conf.c
View file

@ -912,10 +912,6 @@ void conf(struct ctx *c, int argc, char **argv)
c->foreground = 1; c->foreground = 1;
break; break;
case '?':
case 'h':
usage(argv[0]);
break;
case 's': case 's':
if (*c->sock_path) { if (*c->sock_path) {
err("Multiple --socket options given"); err("Multiple --socket options given");
@ -1142,6 +1138,11 @@ void conf(struct ctx *c, int argc, char **argv)
usage(argv[0]); usage(argv[0]);
break; break;
case '?':
case 'h':
default:
usage(argv[0]);
break;
} }
} while (name != -1); } while (name != -1);

3
dhcp.c
View file

@ -225,9 +225,8 @@ static void opt_set_dns_search(struct ctx *c, size_t max_len)
buf[n++] = '\xc0'; buf[n++] = '\xc0';
buf[n++] = dup; buf[n++] = dup;
break; break;
} else {
buf[n++] = '.';
} }
buf[n++] = '.';
} else { } else {
buf[n++] = *p; buf[n++] = *p;
} }

4
icmp.c
View file

@ -254,11 +254,11 @@ void icmp_timer(struct ctx *c, struct timespec *ts)
v6: v6:
word = (long *)icmp_act[v6 ? V6 : V4]; word = (long *)icmp_act[v6 ? V6 : V4];
for (i = 0; i < sizeof(icmp_act[0]) / sizeof(long); i++, word++) { for (i = 0; i < ARRAY_SIZE(icmp_act); i += sizeof(long), word++) {
tmp = *word; tmp = *word;
while ((n = ffsl(tmp))) { while ((n = ffsl(tmp))) {
tmp &= ~(1UL << (n - 1)); tmp &= ~(1UL << (n - 1));
icmp_timer_one(c, v6, i * sizeof(long) * 8 + n - 1, ts); icmp_timer_one(c, v6, i * 8 + n - 1, ts);
} }
} }

4
ndp.c
View file

@ -53,7 +53,7 @@ int ndp(struct ctx *c, struct ethhdr *eh, size_t len)
char buf[BUFSIZ] = { 0 }; char buf[BUFSIZ] = { 0 };
uint8_t proto, *p; uint8_t proto, *p;
if (len < sizeof(*ehr) + sizeof(*ip6h) + sizeof(ih)) if (len < sizeof(*ehr) + sizeof(*ip6h) + sizeof(*ih))
return 0; return 0;
ih = (struct icmp6hdr *)ipv6_l4hdr(ip6h, &proto); ih = (struct icmp6hdr *)ipv6_l4hdr(ip6h, &proto);
@ -72,7 +72,7 @@ int ndp(struct ctx *c, struct ethhdr *eh, size_t len)
ihr = (struct icmp6hdr *)(ip6hr + 1); ihr = (struct icmp6hdr *)(ip6hr + 1);
if (ih->icmp6_type == NS) { if (ih->icmp6_type == NS) {
if (len < sizeof(*ehr) + sizeof(*ip6h) + sizeof(ih) + if (len < sizeof(*ehr) + sizeof(*ip6h) + sizeof(*ih) +
sizeof(struct in6_addr)) sizeof(struct in6_addr))
return -1; return -1;

View file

@ -97,13 +97,15 @@ int nl_sock_init(struct ctx *c)
*/ */
static int nl_req(int ns, char *buf, void *req, ssize_t len) static int nl_req(int ns, char *buf, void *req, ssize_t len)
{ {
int n, s = ns ? nl_sock_ns : nl_sock, done = 0; int s = ns ? nl_sock_ns : nl_sock, done = 0;
char flush[BUFSIZ]; char flush[BUFSIZ];
ssize_t n;
while (!done && (n = recv(s, flush, sizeof(flush), MSG_DONTWAIT)) > 0) { while (!done && (n = recv(s, flush, sizeof(flush), MSG_DONTWAIT)) > 0) {
struct nlmsghdr *nh = (struct nlmsghdr *)flush; struct nlmsghdr *nh = (struct nlmsghdr *)flush;
size_t nm = n;
for ( ; NLMSG_OK(nh, n); nh = NLMSG_NEXT(nh, n)) { for ( ; NLMSG_OK(nh, nm); nh = NLMSG_NEXT(nh, nm)) {
if (nh->nlmsg_type == NLMSG_DONE || if (nh->nlmsg_type == NLMSG_DONE ||
nh->nlmsg_type == NLMSG_ERROR) { nh->nlmsg_type == NLMSG_ERROR) {
done = 1; done = 1;
@ -129,7 +131,7 @@ unsigned int nl_get_ext_if(int *v4, int *v6)
{ {
struct { struct nlmsghdr nlh; struct rtmsg rtm; } req = { struct { struct nlmsghdr nlh; struct rtmsg rtm; } req = {
.nlh.nlmsg_type = RTM_GETROUTE, .nlh.nlmsg_type = RTM_GETROUTE,
.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP | NLM_F_EXCL, .nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)), .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)),
.nlh.nlmsg_seq = nl_seq++, .nlh.nlmsg_seq = nl_seq++,
@ -145,8 +147,9 @@ unsigned int nl_get_ext_if(int *v4, int *v6)
struct rtmsg *rtm; struct rtmsg *rtm;
char buf[BUFSIZ]; char buf[BUFSIZ];
long *word, tmp; long *word, tmp;
int n, na, *v;
uint8_t *vmap; uint8_t *vmap;
size_t n, na;
int *v;
if (*v4 == IP_VERSION_PROBE) { if (*v4 == IP_VERSION_PROBE) {
v = v4; v = v4;
@ -170,8 +173,8 @@ v6:
if (rtm->rtm_dst_len || rtm->rtm_family != req.rtm.rtm_family) if (rtm->rtm_dst_len || rtm->rtm_family != req.rtm.rtm_family)
continue; continue;
for (rta = (struct rtattr *)RTM_RTA(rtm), na = RTM_PAYLOAD(nh); for (rta = RTM_RTA(rtm), na = RTM_PAYLOAD(nh); RTA_OK(rta, na);
RTA_OK(rta, na); rta = RTA_NEXT(rta, na)) { rta = RTA_NEXT(rta, na)) {
unsigned int ifi; unsigned int ifi;
if (rta->rta_type != RTA_OIF) if (rta->rta_type != RTA_OIF)
@ -283,7 +286,7 @@ void nl_route(int ns, unsigned int ifi, sa_family_t af, void *gw)
struct rtattr *rta; struct rtattr *rta;
struct rtmsg *rtm; struct rtmsg *rtm;
char buf[BUFSIZ]; char buf[BUFSIZ];
int n, na; size_t n, na;
if (set) { if (set) {
if (af == AF_INET6) { if (af == AF_INET6) {
@ -326,8 +329,8 @@ void nl_route(int ns, unsigned int ifi, sa_family_t af, void *gw)
if (rtm->rtm_dst_len) if (rtm->rtm_dst_len)
continue; continue;
for (rta = (struct rtattr *)RTM_RTA(rtm), na = RTM_PAYLOAD(nh); for (rta = RTM_RTA(rtm), na = RTM_PAYLOAD(nh); RTA_OK(rta, na);
RTA_OK(rta, na); rta = RTA_NEXT(rta, na)) { rta = RTA_NEXT(rta, na)) {
if (rta->rta_type != RTA_GATEWAY) if (rta->rta_type != RTA_GATEWAY)
continue; continue;
@ -388,7 +391,7 @@ void nl_addr(int ns, unsigned int ifi, sa_family_t af,
struct nlmsghdr *nh; struct nlmsghdr *nh;
struct rtattr *rta; struct rtattr *rta;
char buf[BUFSIZ]; char buf[BUFSIZ];
int n, na; size_t n, na;
if (set) { if (set) {
if (af == AF_INET6) { if (af == AF_INET6) {
@ -429,8 +432,8 @@ void nl_addr(int ns, unsigned int ifi, sa_family_t af,
if (ifa->ifa_index != ifi) if (ifa->ifa_index != ifi)
goto next; goto next;
for (rta = (struct rtattr *)IFA_RTA(ifa), na = RTM_PAYLOAD(nh); for (rta = IFA_RTA(ifa), na = RTM_PAYLOAD(nh); RTA_OK(rta, na);
RTA_OK(rta, na); rta = RTA_NEXT(rta, na)) { rta = RTA_NEXT(rta, na)) {
if (rta->rta_type != IFA_ADDRESS) if (rta->rta_type != IFA_ADDRESS)
continue; continue;
@ -487,7 +490,7 @@ void nl_link(int ns, unsigned int ifi, void *mac, int up, int mtu)
struct nlmsghdr *nh; struct nlmsghdr *nh;
struct rtattr *rta; struct rtattr *rta;
char buf[BUFSIZ]; char buf[BUFSIZ];
int n, na; size_t n, na;
if (!MAC_IS_ZERO(mac)) { if (!MAC_IS_ZERO(mac)) {
req.nlh.nlmsg_len = sizeof(req); req.nlh.nlmsg_len = sizeof(req);
@ -522,8 +525,8 @@ void nl_link(int ns, unsigned int ifi, void *mac, int up, int mtu)
ifm = (struct ifinfomsg *)NLMSG_DATA(nh); ifm = (struct ifinfomsg *)NLMSG_DATA(nh);
for (rta = (struct rtattr *)IFLA_RTA(ifm), na = RTM_PAYLOAD(nh); for (rta = IFLA_RTA(ifm), na = RTM_PAYLOAD(nh); RTA_OK(rta, na);
RTA_OK(rta, na); rta = RTA_NEXT(rta, na)) { rta = RTA_NEXT(rta, na)) {
if (rta->rta_type != IFLA_ADDRESS) if (rta->rta_type != IFLA_ADDRESS)
continue; continue;

View file

@ -204,7 +204,7 @@ void pasta_start_ns(struct ctx *c)
close(fd); close(fd);
fd = open("/proc/self/setgroups", O_WRONLY); fd = open("/proc/self/setgroups", O_WRONLY);
if (write(fd, "deny", sizeof("deny"))) if (write(fd, "deny", sizeof("deny")) < 0)
warn("Cannot write to setgroups in namespace"); warn("Cannot write to setgroups in namespace");
close(fd); close(fd);

62
tcp.c
View file

@ -511,7 +511,7 @@ struct tcp_tap_conn {
struct timespec ts_ack_to_tap; struct timespec ts_ack_to_tap;
struct timespec tap_data_noack; struct timespec tap_data_noack;
int mss_guest; unsigned int mss_guest;
uint32_t events; uint32_t events;
}; };
@ -898,7 +898,7 @@ static void tcp_update_check_tcp6(struct tcp6_l2_buf_t *buf)
* @ip_da: Pointer to IPv4 destination address, NULL if unchanged * @ip_da: Pointer to IPv4 destination address, NULL if unchanged
*/ */
void tcp_update_l2_buf(unsigned char *eth_d, unsigned char *eth_s, void tcp_update_l2_buf(unsigned char *eth_d, unsigned char *eth_s,
uint32_t *ip_da) const uint32_t *ip_da)
{ {
int i; int i;
@ -1452,7 +1452,7 @@ void tcp_defer_handler(struct ctx *c)
*/ */
static size_t tcp_l2_buf_fill_headers(struct ctx *c, struct tcp_tap_conn *conn, static size_t tcp_l2_buf_fill_headers(struct ctx *c, struct tcp_tap_conn *conn,
void *p, size_t plen, void *p, size_t plen,
uint16_t *check, uint32_t seq) const uint16_t *check, uint32_t seq)
{ {
size_t ip_len, eth_len; size_t ip_len, eth_len;
@ -1582,7 +1582,7 @@ static int tcp_update_seqack_wnd(struct ctx *c, struct tcp_tap_conn *conn,
conn->wnd_to_tap = info->tcpi_snd_wnd; conn->wnd_to_tap = info->tcpi_snd_wnd;
} else { } else {
tcp_get_sndbuf(conn); tcp_get_sndbuf(conn);
conn->wnd_to_tap = MIN(info->tcpi_snd_wnd, conn->snd_buf); conn->wnd_to_tap = MIN((int)info->tcpi_snd_wnd, conn->snd_buf);
} }
conn->wnd_to_tap = MIN(conn->wnd_to_tap, MAX_WINDOW); conn->wnd_to_tap = MIN(conn->wnd_to_tap, MAX_WINDOW);
@ -1622,7 +1622,7 @@ static int tcp_send_to_tap(struct ctx *c, struct tcp_tap_conn *conn, int flags,
return 0; return 0;
if (getsockopt(s, SOL_TCP, TCP_INFO, &info, &sl)) { if (getsockopt(s, SOL_TCP, TCP_INFO, &info, &sl)) {
tcp_rst(c, conn); tcp_tap_destroy(c, conn);
return -ECONNRESET; return -ECONNRESET;
} }
@ -1658,7 +1658,7 @@ static int tcp_send_to_tap(struct ctx *c, struct tcp_tap_conn *conn, int flags,
if (c->mtu == -1) { if (c->mtu == -1) {
mss = info.tcpi_snd_mss; mss = info.tcpi_snd_mss;
} else { } else {
mss = c->mtu - sizeof(sizeof *th); mss = c->mtu - sizeof(struct tcphdr);
if (CONN_V4(conn)) if (CONN_V4(conn))
mss -= sizeof(struct iphdr); mss -= sizeof(struct iphdr);
else else
@ -1880,9 +1880,9 @@ static void tcp_conn_from_tap(struct ctx *c, int af, void *addr,
.sin6_addr = *(struct in6_addr *)addr, .sin6_addr = *(struct in6_addr *)addr,
}; };
union epoll_ref ref = { .proto = IPPROTO_TCP }; union epoll_ref ref = { .proto = IPPROTO_TCP };
int i, s, *sock_pool_p, mss;
const struct sockaddr *sa; const struct sockaddr *sa;
struct tcp_tap_conn *conn; struct tcp_tap_conn *conn;
int i, s, *sock_pool_p;
struct epoll_event ev; struct epoll_event ev;
socklen_t sl; socklen_t sl;
@ -1921,7 +1921,10 @@ static void tcp_conn_from_tap(struct ctx *c, int af, void *addr,
.sin6_addr = c->addr6_ll, .sin6_addr = c->addr6_ll,
.sin6_scope_id = c->ifi, .sin6_scope_id = c->ifi,
}; };
bind(s, (struct sockaddr *)&addr6_ll, sizeof(addr6_ll)); if (bind(s, (struct sockaddr *)&addr6_ll, sizeof(addr6_ll))) {
close(s);
return;
}
} }
conn = &tt[c->tcp.tap_conn_count++]; conn = &tt[c->tcp.tap_conn_count++];
@ -1930,9 +1933,10 @@ static void tcp_conn_from_tap(struct ctx *c, int af, void *addr,
conn->wnd_to_tap = WINDOW_DEFAULT; conn->wnd_to_tap = WINDOW_DEFAULT;
conn->mss_guest = tcp_opt_get(th, len, OPT_MSS, NULL, NULL); if ((mss = tcp_opt_get(th, len, OPT_MSS, NULL, NULL)) < 0)
if (conn->mss_guest < 0)
conn->mss_guest = MSS_DEFAULT; conn->mss_guest = MSS_DEFAULT;
else
conn->mss_guest = mss;
/* Don't upset qemu */ /* Don't upset qemu */
if (c->mode == MODE_PASST) { if (c->mode == MODE_PASST) {
@ -2186,9 +2190,8 @@ static int tcp_data_from_sock(struct ctx *c, struct tcp_tap_conn *conn,
iov_sock[0].iov_base = tcp_buf_discard; iov_sock[0].iov_base = tcp_buf_discard;
iov_sock[0].iov_len = already_sent; iov_sock[0].iov_len = already_sent;
if (v4 && tcp4_l2_buf_used + fill_bufs > ARRAY_SIZE(tcp4_l2_buf)) if (( v4 && tcp4_l2_buf_used + fill_bufs > ARRAY_SIZE(tcp4_l2_buf)) ||
tcp_l2_buf_flush(c); (!v4 && tcp6_l2_buf_used + fill_bufs > ARRAY_SIZE(tcp6_l2_buf)))
else if (!v4 && tcp6_l2_buf_used + fill_bufs > ARRAY_SIZE(tcp6_l2_buf))
tcp_l2_buf_flush(c); tcp_l2_buf_flush(c);
for (i = 0, iov = iov_sock + 1; i < fill_bufs; i++, iov++) { for (i = 0, iov = iov_sock + 1; i < fill_bufs; i++, iov++) {
@ -2543,6 +2546,7 @@ int tcp_tap_handler(struct ctx *c, int af, void *addr,
struct tcphdr *th = (struct tcphdr *)(pkt_buf + msg[0].pkt_buf_offset); struct tcphdr *th = (struct tcphdr *)(pkt_buf + msg[0].pkt_buf_offset);
uint16_t len = msg[0].l4_len; uint16_t len = msg[0].l4_len;
struct tcp_tap_conn *conn; struct tcp_tap_conn *conn;
int mss;
conn = tcp_hash_lookup(c, af, addr, htons(th->source), htons(th->dest)); conn = tcp_hash_lookup(c, af, addr, htons(th->source), htons(th->dest));
if (!conn) { if (!conn) {
@ -2567,9 +2571,10 @@ int tcp_tap_handler(struct ctx *c, int af, void *addr,
tcp_clamp_window(conn, th, len, 0, 1); tcp_clamp_window(conn, th, len, 0, 1);
conn->mss_guest = tcp_opt_get(th, len, OPT_MSS, NULL, NULL); if ((mss = tcp_opt_get(th, len, OPT_MSS, NULL, NULL)) < 0)
if (conn->mss_guest < 0)
conn->mss_guest = MSS_DEFAULT; conn->mss_guest = MSS_DEFAULT;
else
conn->mss_guest = mss;
/* Don't upset qemu */ /* Don't upset qemu */
if (c->mode == MODE_PASST) { if (c->mode == MODE_PASST) {
@ -2936,7 +2941,7 @@ static void tcp_conn_from_sock(struct ctx *c, union epoll_ref ref,
in_addr_t s_addr; in_addr_t s_addr;
memcpy(&sa4, &sa, sizeof(sa4)); memcpy(&sa4, &sa, sizeof(sa4));
s_addr = sa4.sin_addr.s_addr; s_addr = ntohl(sa4.sin_addr.s_addr);
memset(&conn->a.a4.zero, 0, sizeof(conn->a.a4.zero)); memset(&conn->a.a4.zero, 0, sizeof(conn->a.a4.zero));
memset(&conn->a.a4.one, 0xff, sizeof(conn->a.a4.one)); memset(&conn->a.a4.one, 0xff, sizeof(conn->a.a4.one));
@ -3156,9 +3161,12 @@ eintr:
ev.data.u64 = ref.u64, ev.data.u64 = ref.u64,
epoll_ctl(c->epollfd, EPOLL_CTL_MOD, move_to, &ev); epoll_ctl(c->epollfd, EPOLL_CTL_MOD, move_to, &ev);
break; break;
} else if (never_read && written == (long)(c->tcp.pipe_size)) { }
if (never_read && written == (long)(c->tcp.pipe_size))
goto retry; goto retry;
} else if (!never_read && written < to_write) {
if (!never_read && written < to_write) {
to_write -= written; to_write -= written;
goto retry; goto retry;
} }
@ -3221,7 +3229,6 @@ close:
epoll_ctl(c->epollfd, EPOLL_CTL_DEL, conn->from, NULL); epoll_ctl(c->epollfd, EPOLL_CTL_DEL, conn->from, NULL);
epoll_ctl(c->epollfd, EPOLL_CTL_DEL, conn->to, NULL); epoll_ctl(c->epollfd, EPOLL_CTL_DEL, conn->to, NULL);
conn->state = CLOSED; conn->state = CLOSED;
return;
} }
/** /**
@ -3448,7 +3455,7 @@ static void tcp_sock_init_one(struct ctx *c, int ns, in_port_t port)
static int tcp_sock_init_ns(void *arg) static int tcp_sock_init_ns(void *arg)
{ {
struct ctx *c = (struct ctx *)arg; struct ctx *c = (struct ctx *)arg;
in_port_t port; int port;
ns_enter(c); ns_enter(c);
@ -3550,8 +3557,7 @@ static int tcp_sock_refill(void *arg)
int tcp_sock_init(struct ctx *c, struct timespec *now) int tcp_sock_init(struct ctx *c, struct timespec *now)
{ {
struct tcp_sock_refill_arg refill_arg = { c, 0 }; struct tcp_sock_refill_arg refill_arg = { c, 0 };
in_port_t port; int i, port;
int i;
if (getrandom(&c->tcp.hash_secret, sizeof(c->tcp.hash_secret), if (getrandom(&c->tcp.hash_secret, sizeof(c->tcp.hash_secret),
GRND_RANDOM) < 0) { GRND_RANDOM) < 0) {
@ -3646,9 +3652,7 @@ static void tcp_timer_one(struct ctx *c, struct tcp_tap_conn *conn,
break; break;
} }
if (!conn->wnd_to_tap) if (!conn->wnd_to_tap || ack_to_tap > ACK_INTERVAL)
tcp_send_to_tap(c, conn, 0, ts);
else if (ack_to_tap > ACK_INTERVAL)
tcp_send_to_tap(c, conn, 0, ts); tcp_send_to_tap(c, conn, 0, ts);
if (tap_data_noack > ACK_TIMEOUT) { if (tap_data_noack > ACK_TIMEOUT) {
@ -3673,9 +3677,7 @@ static void tcp_timer_one(struct ctx *c, struct tcp_tap_conn *conn,
tcp_rst(c, conn); tcp_rst(c, conn);
break; break;
case LAST_ACK: case LAST_ACK:
if (sock_act > LAST_ACK_TIMEOUT) if (sock_act > LAST_ACK_TIMEOUT || tap_act > LAST_ACK_TIMEOUT)
tcp_rst(c, conn);
else if (tap_act > LAST_ACK_TIMEOUT)
tcp_rst(c, conn); tcp_rst(c, conn);
break; break;
case TAP_SYN_SENT: case TAP_SYN_SENT:
@ -3739,7 +3741,7 @@ struct tcp_port_rebind_arg {
static int tcp_port_rebind(void *arg) static int tcp_port_rebind(void *arg)
{ {
struct tcp_port_rebind_arg *a = (struct tcp_port_rebind_arg *)arg; struct tcp_port_rebind_arg *a = (struct tcp_port_rebind_arg *)arg;
in_port_t port; int port;
if (a->bind_in_ns) { if (a->bind_in_ns) {
ns_enter(a->c); ns_enter(a->c);
@ -3808,7 +3810,7 @@ static int tcp_port_rebind(void *arg)
/** /**
* tcp_timer() - Scan activity bitmap for sockets waiting for timed events * tcp_timer() - Scan activity bitmap for sockets waiting for timed events
* @c: Execution context * @c: Execution context
* @ts: Timestamp from caller * @now: Timestamp from caller
*/ */
void tcp_timer(struct ctx *c, struct timespec *now) void tcp_timer(struct ctx *c, struct timespec *now)
{ {

4
tcp.h
View file

@ -18,10 +18,10 @@ void tcp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
int tcp_tap_handler(struct ctx *c, int af, void *addr, int tcp_tap_handler(struct ctx *c, int af, void *addr,
struct tap_l4_msg *msg, int count, struct timespec *now); struct tap_l4_msg *msg, int count, struct timespec *now);
int tcp_sock_init(struct ctx *c, struct timespec *now); int tcp_sock_init(struct ctx *c, struct timespec *now);
void tcp_timer(struct ctx *c, struct timespec *ts); void tcp_timer(struct ctx *c, struct timespec *now);
void tcp_defer_handler(struct ctx *c); void tcp_defer_handler(struct ctx *c);
void tcp_update_l2_buf(unsigned char *eth_d, unsigned char *eth_s, void tcp_update_l2_buf(unsigned char *eth_d, unsigned char *eth_s,
uint32_t *ip_da); const uint32_t *ip_da);
void tcp_remap_to_tap(in_port_t port, in_port_t delta); void tcp_remap_to_tap(in_port_t port, in_port_t delta);
void tcp_remap_to_init(in_port_t port, in_port_t delta); void tcp_remap_to_init(in_port_t port, in_port_t delta);

View file

@ -0,0 +1,18 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/build/clang_tidy - Run source through clang-tidy(1) linter
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
htools clang-tidy
test Run clang-tidy
hout RET make clang-tidy; echo $?
check [ __RET__ -eq 0 ]

18
udp.c
View file

@ -319,7 +319,7 @@ static void udp_update_check4(struct udp4_l2_buf_t *buf)
* @ip_da: Pointer to IPv4 destination address, NULL if unchanged * @ip_da: Pointer to IPv4 destination address, NULL if unchanged
*/ */
void udp_update_l2_buf(unsigned char *eth_d, unsigned char *eth_s, void udp_update_l2_buf(unsigned char *eth_d, unsigned char *eth_s,
uint32_t *ip_da) const uint32_t *ip_da)
{ {
int i; int i;
@ -1017,7 +1017,7 @@ int udp_sock_init_ns(void *arg)
{ {
union udp_epoll_ref uref = { .bound = 1, .splice = UDP_TO_INIT }; union udp_epoll_ref uref = { .bound = 1, .splice = UDP_TO_INIT };
struct ctx *c = (struct ctx *)arg; struct ctx *c = (struct ctx *)arg;
in_port_t dst; int dst;
ns_enter(c); ns_enter(c);
@ -1105,8 +1105,7 @@ static void udp_splice_iov_init(void)
int udp_sock_init(struct ctx *c, struct timespec *now) int udp_sock_init(struct ctx *c, struct timespec *now)
{ {
union udp_epoll_ref uref = { .bound = 1 }; union udp_epoll_ref uref = { .bound = 1 };
in_port_t dst; int dst, s;
int s;
(void)now; (void)now;
@ -1224,21 +1223,22 @@ void udp_timer(struct ctx *c, struct timespec *ts)
unsigned int i; unsigned int i;
long *word, tmp; long *word, tmp;
if (!c->v4)
v6 = 1;
v6: v6:
for (t = 0; t < UDP_ACT_TYPE_MAX; t++) { for (t = 0; t < UDP_ACT_TYPE_MAX; t++) {
word = (long *)udp_act[v6 ? V6 : V4][t]; word = (long *)udp_act[v6 ? V6 : V4][t];
for (i = 0; i < sizeof(udp_act[0][0]) / sizeof(long); for (i = 0; i < ARRAY_SIZE(udp_act[0][0]);
i++, word++) { i += sizeof(long), word++) {
tmp = *word; tmp = *word;
while ((n = ffsl(tmp))) { while ((n = ffsl(tmp))) {
tmp &= ~(1UL << (n - 1)); tmp &= ~(1UL << (n - 1));
udp_timer_one(c, v6, t, udp_timer_one(c, v6, t, i * 8 + n - 1, ts);
i * sizeof(long) * 8 + n - 1, ts);
} }
} }
} }
if (!v6) { if (!v6 && c->v6) {
v6 = 1; v6 = 1;
goto v6; goto v6;
} }

2
udp.h
View file

@ -15,7 +15,7 @@ int udp_tap_handler(struct ctx *c, int af, void *addr,
int udp_sock_init(struct ctx *c, struct timespec *now); int udp_sock_init(struct ctx *c, struct timespec *now);
void udp_timer(struct ctx *c, struct timespec *ts); void udp_timer(struct ctx *c, struct timespec *ts);
void udp_update_l2_buf(unsigned char *eth_d, unsigned char *eth_s, void udp_update_l2_buf(unsigned char *eth_d, unsigned char *eth_s,
uint32_t *ip_da); const uint32_t *ip_da);
void udp_remap_to_tap(in_port_t port, in_port_t delta); void udp_remap_to_tap(in_port_t port, in_port_t delta);
void udp_remap_to_init(in_port_t port, in_port_t delta); void udp_remap_to_init(in_port_t port, in_port_t delta);

5
util.c
View file

@ -143,7 +143,7 @@ void passt_vsyslog(int pri, const char *format, va_list ap)
n += snprintf(buf + n, BUFSIZ - n, "\n"); n += snprintf(buf + n, BUFSIZ - n, "\n");
if (log_opt | LOG_PERROR) if (log_opt | LOG_PERROR)
fprintf(stderr, buf + sizeof("<0>")); fprintf(stderr, "%s", buf + sizeof("<0>"));
send(log_sock, buf, n, 0); send(log_sock, buf, n, 0);
} }
@ -362,7 +362,7 @@ void bitmap_clear(uint8_t *map, int bit)
* *
* Return: non-zero if given bit is set, zero if it's not * Return: non-zero if given bit is set, zero if it's not
*/ */
int bitmap_isset(uint8_t *map, int bit) int bitmap_isset(const uint8_t *map, int bit)
{ {
return map[bit / 8] & (1 << bit % 8); return map[bit / 8] & (1 << bit % 8);
} }
@ -437,6 +437,7 @@ void procfs_scan_listen(char *name, uint8_t *map, uint8_t *exclude)
*line = 0; *line = 0;
line_read(line, sizeof(line), fd); line_read(line, sizeof(line), fd);
while (line_read(line, sizeof(line), fd)) { while (line_read(line, sizeof(line), fd)) {
/* NOLINTNEXTLINE(cert-err34-c): != 2 if conversion fails */
if (sscanf(line, "%*u: %*x:%lx %*x:%*x %x", &port, &state) != 2) if (sscanf(line, "%*u: %*x:%lx %*x:%*x %x", &port, &state) != 2)
continue; continue;

6
util.h
View file

@ -36,7 +36,7 @@ void debug(const char *format, ...);
#define SWAP(a, b) \ #define SWAP(a, b) \
do { \ do { \
typeof(a) __x = (a); (a) = (b); (b) = __x; \ __typeof__(a) __x = (a); (a) = (b); (b) = __x; \
} while (0) \ } while (0) \
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
@ -152,7 +152,7 @@ enum bind_type {
struct ctx; struct ctx;
void __openlog(const char *ident, int option, int facility); void __openlog(const char *ident, int option, int facility);
void passt_vsyslog(int pri, const char *fmt, va_list ap); void passt_vsyslog(int pri, const char *format, va_list ap);
void __setlogmask(int mask); void __setlogmask(int mask);
char *ipv6_l4hdr(struct ipv6hdr *ip6h, uint8_t *proto); char *ipv6_l4hdr(struct ipv6hdr *ip6h, uint8_t *proto);
int sock_l4(struct ctx *c, int af, uint8_t proto, uint16_t port, int sock_l4(struct ctx *c, int af, uint8_t proto, uint16_t port,
@ -161,7 +161,7 @@ void sock_probe_mem(struct ctx *c);
int timespec_diff_ms(struct timespec *a, struct timespec *b); int timespec_diff_ms(struct timespec *a, struct timespec *b);
void bitmap_set(uint8_t *map, int bit); void bitmap_set(uint8_t *map, int bit);
void bitmap_clear(uint8_t *map, int bit); void bitmap_clear(uint8_t *map, int bit);
int bitmap_isset(uint8_t *map, int bit); int bitmap_isset(const uint8_t *map, int bit);
char *line_read(char *buf, size_t len, int fd); char *line_read(char *buf, size_t len, int fd);
void procfs_scan_listen(char *name, uint8_t *map, uint8_t *exclude); void procfs_scan_listen(char *name, uint8_t *map, uint8_t *exclude);
int ns_enter(struct ctx *c); int ns_enter(struct ctx *c);