pkelsey / libuinet

a library version of FreeBSD's TCP/IP stack plus extras
750 stars 198 forks source link

TCP frame sending is occuring with passive listen sockets #26

Closed erikarn closed 9 years ago

erikarn commented 9 years ago

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

pkelsey commented 9 years ago

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 822c563c034c8615eeece8ae0a1430fb4e86aac5.