diff options
| -rw-r--r-- | flow.c | 12 | ||||
| -rw-r--r-- | fwd.c | 21 | ||||
| -rw-r--r-- | fwd.h | 1 | ||||
| -rw-r--r-- | tcp.c | 11 | ||||
| -rw-r--r-- | tcp_conn.h | 3 |
5 files changed, 35 insertions, 13 deletions
@@ -1023,6 +1023,9 @@ static int flow_migrate_source_rollback(struct ctx *c, unsigned bound, int ret) debug("...roll back migration"); + if (fwd_listen_sync(c, &c->tcp.fwd_in, PIF_HOST, IPPROTO_TCP) < 0) + die("Failed to re-establish listening sockets"); + foreach_established_tcp_flow(flow) { if (FLOW_IDX(flow) >= bound) break; @@ -1147,6 +1150,15 @@ int flow_migrate_source(struct ctx *c, const struct migrate_stage *stage, return flow_migrate_source_rollback(c, FLOW_MAX, rc); } + /* HACK: A local to local migrate will fail if the origin passt has the + * listening sockets still open when the destination passt tries to bind + * them. This does mean there's a window where we lost our listen()s, + * even if the migration is rolled back later. The only way to really + * fix that is to not allow local to local migration, which arguably we + * should (use namespaces for testing instead). */ + debug("Stop listen()s"); + fwd_listen_close(&c->tcp.fwd_in); + debug("Sending %u flows", ntohl(count)); if (!count) @@ -654,6 +654,27 @@ int fwd_listen_sync(const struct ctx *c, const struct fwd_ports *fwd, return 0; } +/** fwd_listen_close() - Close all listening sockets + * @fwd: Forwarding information + */ +void fwd_listen_close(const struct fwd_ports *fwd) +{ + unsigned i; + + for (i = 0; i < fwd->count; i++) { + const struct fwd_rule *rule = &fwd->rules[i]; + unsigned port; + + for (port = rule->first; port <= rule->last; port++) { + int *fdp = &rule->socks[port - rule->first]; + if (*fdp >= 0) { + close(*fdp); + *fdp = -1; + } + } + } +} + /* See enum in kernel's include/net/tcp_states.h */ #define UDP_LISTEN 0x07 #define TCP_LISTEN 0x0a @@ -118,6 +118,7 @@ void fwd_scan_ports_timer(struct ctx * c, const struct timespec *now); int fwd_listen_sync(const struct ctx *c, const struct fwd_ports *fwd, uint8_t pif, uint8_t proto); +void fwd_listen_close(const struct fwd_ports *fwd); bool nat_inbound(const struct ctx *c, const union inany_addr *addr, union inany_addr *translated); @@ -1704,7 +1704,6 @@ static void tcp_conn_from_tap(const struct ctx *c, sa_family_t af, conn->sock = s; conn->timer = -1; - conn->listening_sock = -1; flow_epollid_set(&conn->f, EPOLLFD_ID_DEFAULT); if (flow_epoll_set(&conn->f, EPOLL_CTL_ADD, 0, s, TGTSIDE) < 0) { flow_perror(flow, "Can't register with epoll"); @@ -2476,7 +2475,6 @@ static void tcp_tap_conn_from_sock(const struct ctx *c, union flow *flow, void tcp_listen_handler(const struct ctx *c, union epoll_ref ref, const struct timespec *now) { - struct tcp_tap_conn *conn; union sockaddr_inany sa; socklen_t sl = sizeof(sa); struct flowside *ini; @@ -2492,9 +2490,6 @@ void tcp_listen_handler(const struct ctx *c, union epoll_ref ref, if (s < 0) goto cancel; - conn = (struct tcp_tap_conn *)flow; - conn->listening_sock = ref.fd; - tcp_sock_set_nodelay(s); /* FIXME: If useful: when the listening port has a specific bound @@ -3393,7 +3388,7 @@ static int tcp_flow_repair_opt(const struct tcp_tap_conn *conn, } /** - * tcp_flow_migrate_source() - Send data (flow table) for flow, close listening + * tcp_flow_migrate_source() - Send data (flow table) for flow * @fd: Descriptor for state migration * @conn: Pointer to the TCP connection structure * @@ -3433,9 +3428,6 @@ int tcp_flow_migrate_source(int fd, struct tcp_tap_conn *conn) return rc; } - if (conn->listening_sock != -1 && !fcntl(conn->listening_sock, F_GETFD)) - close(conn->listening_sock); - return 0; } @@ -3645,7 +3637,6 @@ static int tcp_flow_repair_connect(const struct ctx *c, } conn->timer = -1; - conn->listening_sock = -1; return 0; } @@ -18,7 +18,6 @@ * @tap_mss: MSS advertised by tap/guest, rounded to 2 ^ TCP_MSS_BITS * @sock: Socket descriptor number * @events: Connection events, implying connection states - * @listening_sock: Listening socket this socket was accept()ed from, or -1 * @timer: timerfd descriptor for timeout events * @flags: Connection flags representing internal attributes * @sndbuf: Sending buffer in kernel, rounded to 2 ^ SNDBUF_BITS @@ -75,8 +74,6 @@ struct tcp_tap_conn { #define CONN_STATE_BITS /* Setting these clears other flags */ \ (SOCK_ACCEPTED | TAP_SYN_RCVD | ESTABLISHED) - int listening_sock; - int timer :FD_REF_BITS; uint8_t flags; |
