pkelsey/libuinet

TCP frame sending is occuring with passive listen sockets

Closed this issue · 1 comments

After the passive-to-active merge, there's a problem with the TCP code now sending TCP segments during session establishment.

It looks like the INP_PASSIVE flag isn't set early enough on in the connection lifecycle for tcp_output() to not output things.

(gdb) break if_netmap_start
Breakpoint 4 at 0x422fca: file uinet_if_netmap.c, line 524.
(gdb) cont
Continuing.
[New Thread 802c09c00 (LWP 101148 nm_rx: netmap0)]
[Switching to Thread 802c09c00 (LWP 101148 nm_rx: netmap0)]

Breakpoint 4, if_netmap_start (ifp=0x802ef0300) at uinet_if_netmap.c:524
524 struct if_netmap_softc *sc = ifp->if_softc;
(gdb) bt
#0 if_netmap_start (ifp=0x802ef0300) at uinet_if_netmap.c:524
#1 0x0000000000455602 in if_start (ifp=0x802ef0300, ifp=0x802ef0300) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/net/if.c:3401
#2 if_transmit (ifp=0x802ef0300, m=) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/net/if.c:3413
#3 0x0000000000456d57 in ether_output_frame (ifp=, m=0x800724300, m=0x800724300, m=0x800724300, m=0x800724300, m=0x800724300)

at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/net/if_ethersubr.c:513
#4 ether_output (ifp=0x802ef0300, m=0x800724300, dst=, ro=) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/net/if_ethersubr.c:484
#5 0x000000000047bcab in ip_output (m=0x800724300, opt=, flags=, imo=, inp=)

at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/ip_output.c:699
#6 0x000000000048538d in tcp_output (tp=0x800735418) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_output.c:1254
#7 0x0000000000482016 in tcp_do_segment (m=, th=, so=, tp=, drop_hdrlen=, tlen=0, iptos=,

ti_locked=<error reading variable: Cannot access memory at address 0x1>, no_unlock=1) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_input.c:3088
#8 0x000000000048adbd in syncache_passive_client_socket (lso=0x800728c20, m=, sc=, to=)

at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_syncache.c:1276
#9 syncache_socket (sc=, lso=, sc=, lso=, m=, to=)

at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_syncache.c:1311
#10 syncache_expand (inc=, to=, th=, lsop=0x7ffffe7f3d40, m=0x800724500)

at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_syncache.c:1737
#11 0x000000000047fdcb in tcp_input (m=, off0=<error reading variable: Cannot access memory at address 0x14>)

at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_input.c:1151
#12 0x00000000004787ae in ip_input (m=0x800724500) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/ip_input.c:774
#13 0x0000000000459c7c in netisr_dispatch_src (proto=, source=, m=0x800724500) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/net/netisr.c:1013
#14 0x000000000045819e in ether_input_internal (ifp=, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500,

m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500,
m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500,
m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500,
m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500,
m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500,
m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500, m=0x800724500,
m=0x800724500, m=0x800724500, m=0x800724500) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/net/if_ethersubr.c:986
#15 ether_nh_input (m=) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/net/if_ethersubr.c:998
#16 0x0000000000459c7c in netisr_dispatch_src (proto=, source=, m=0x800724500) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/net/netisr.c:1013
#17 0x0000000000423882 in if_netmap_receive (arg=0x806832180) at uinet_if_netmap.c:839
#18 0x00000000004968eb in pthread_start_routine (arg=0x8068314c0) at uinet_host_interface.c:537
#19 0x00000008022984f5 in ?? () from /lib/libthr.so.3
#20 0x0000000000000000 in ?? ()

(gdb)

and then;

It seems that:

the listen sockets have SO_PASSIVE set
when sonewconn_passive_client() is called, it clears SO_PASSIVE on the new socket, so it doesn't inherit it
but then when it attaches via tcp_attach(), it ends up at in_pcballoc() -> in_passive_inpcb_init(), which finds SO_PASSIVE isn't set, and thus doesn't mark the inpcb as passive and thus we see transmits.
Here's what's going down:

(gdb) bt
#0 in_passive_inpcb_init (inp=0x80072f640, warning: Unmapped DWARF Register #-2 encountered.

flags=<error reading variable: Unable to access DWARF register number 0xfffffffe>)
at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/in_passive.c:60
#1 0x0000000000471350 in in_pcballoc (so=0x800728308, pcbinfo=0x7042b8 ) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/in_pcb.c:352
#2 0x000000000048e64a in tcp_attach (so=0x800728308) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_usrreq.c:1648
#3 tcp_usr_attach (so=0x800728308, proto=, td=) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_usrreq.c:140
#4 0x000000000044affb in sonewconn_passive_client (head=0x800728c20, connstatus=4) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/kern/uipc_socket.c:590
#5 0x000000000048a34b in syncache_passive_client_socket (lso=0x800728c20, m=, sc=, to=)

at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_syncache.c:1043
#6 syncache_socket (sc=, lso=, sc=, lso=, m=, to=)

at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_syncache.c:1311
#7 syncache_expand (inc=, to=0x7ffffe7f3d18, th=, lsop=0x7ffffe7f3d40, m=0x80071f800)

at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_syncache.c:1737
#8 0x000000000047fdcb in tcp_input (m=, off0=<error reading variable: Cannot access memory at address 0x14>)

at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_input.c:1151
#9 0x00000000004787ae in ip_input (m=0x80071f800) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/ip_input.c:774
#10 0x0000000000459c7c in netisr_dispatch_src (proto=, source=, m=0x80071f800) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/net/netisr.c:1013
#11 0x000000000045819e in ether_input_internal (ifp=, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800,

m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800,
m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800,
m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800,
m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800,
m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800,
m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800, m=0x80071f800,
m=0x80071f800, m=0x80071f800, m=0x80071f800) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/net/if_ethersubr.c:986
#12 ether_nh_input (m=) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/net/if_ethersubr.c:998
#13 0x0000000000459c7c in netisr_dispatch_src (proto=, source=, m=0x80071f800) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/net/netisr.c:1013
#14 0x0000000000423882 in if_netmap_receive (arg=0x806832180) at uinet_if_netmap.c:839
#15 0x00000000004968eb in pthread_start_routine (arg=0x8068314c0) at uinet_host_interface.c:537
#16 0x00000008022984f5 in ?? () from /lib/libthr.so.3
#17 0x0000000000000000 in ?? ()

(gdb) frame 2
#2 0x000000000048e64a in tcp_attach (so=0x800728308) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_usrreq.c:1648

1648 error = in_pcballoc(so, &V_tcbinfo);
(gdb) frame 1
#1 0x0000000000471350 in in_pcballoc (so=0x800728308, pcbinfo=0x7042b8 ) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/in_pcb.c:352

352 error = in_passive_inpcb_init(inp, M_NOWAIT);
(gdb) frame 3
#3 tcp_usr_attach (so=0x800728308, proto=, td=) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_usrreq.c:140

140 error = tcp_attach(so);
(gdb) frame 4
#4 0x000000000044affb in sonewconn_passive_client (head=0x800728c20, connstatus=4) at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/kern/uipc_socket.c:590

590 (*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) {
(gdb) frame 5
#5 0x000000000048a34b in syncache_passive_client_socket (lso=0x800728c20, m=, sc=, to=)

at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/tcp_syncache.c:1043
1043 so = sonewconn_passive_client(lso, SS_ISCONNECTING);
(gdb) frame 0
#0 in_passive_inpcb_init (inp=0x80072f640, warning: Unmapped DWARF Register #-2 encountered.

flags=<error reading variable: Unable to access DWARF register number 0xfffffffe>)
at /home/adrian/git/github/erikarn/libuinet/lib/libuinet/../../sys/netinet/in_passive.c:60
60 if (inp->inp_socket->so_options & SO_PASSIVE)
(gdb) print inp->inp_socket->so_options
$1 = 66048

This is a regression introduced with the convert-to-active-on-timeout functionality I added to the syncache. In short, I disabled inheritance of SO_PASSIVE for the passive client socket in a passive pair and I shouldn't have. This is fixed in 822c563.