Samba 3 socket status after [RST, ACK]
Petr Sumbera
Petr.Sumbera at Sun.COM
Thu Nov 30 14:51:21 GMT 2006
Hi All,
I would like ask you for your opinion on the following issue with Samba
3 (tested with 3.0.21b on Solaris and 3.0.20 on Linux).
When running samba against Windows (WinXP) client, there appears at some
point some strange TCP communication (ending with [RST,ACK]):
No. Time Src Dst Pro. Info
================================
67 .430902 WinXP Samba TCP 2321 > netbios-ssn [SYN] Seq=0 Len=0 MSS=1460
68 .431162 Samba WinXP TCP netbios-ssn > 2321 [SYN, ACK] Seq=0 Ack=1
Win=5840
Len=0 MSS=1460
69 .431623 WinXP Samba NBSS Session request, to TEST-DESKTOP<20> from
TEST-87E22893BE<00>
70 .431912 Samba WinXP TCP netbios-ssn > 2321 [ACK] Seq=1 Ack=73
Win=5840 Len=0
78 .447703 WinXP Samba TCP 2321 > netbios-ssn [RST, ACK] Seq=73 Ack=1
Win=0 Len=0
(above TCP stream was edited to better fit into email)
The best way how to run into this is following procedure on Windows client:
> net use t: \\s10-pc\public
--- Wait some time (something like 5 minutes but it's not clear)
> net use t: /delete
--- after issuing following command, error messages will appear
> net use t: \\s10-pc\public
As result of this you will see in log.smbd following:
Linux:
[2006/11/30 11:44:07, 0] lib/util_sock.c:get_peer_addr(1225)
getpeername failed. Error was Transport endpoint is not connected
[2006/11/30 11:44:07, 0] lib/util_sock.c:get_peer_addr(1225)
Solaris:
[2006/09/15 10:06:11, 0] lib/util_sock.c:(1229)
getpeername failed. Error was Invalid argument
[2006/09/15 10:06:11, 0] lib/util_sock.c:(261)
Failed to set socket option SO_KEEPALIVE (Error Invalid argument)
[2006/09/15 10:06:11, 0] lib/util_sock.c:(261)
Failed to set socket option TCP_NODELAY (Error Invalid argument)
[2006/09/15 10:06:11, 0] lib/util_sock.c:(1229)
getpeername failed. Error was Invalid argument
These messages comes from following piece of code in
samba-3.0.21b/source/smbd/server.c:
388 smbd_set_server_fd(accept(s,&addr,&in_addrlen));
---> inside smbd_set_server_fd() getpeername system call is issued and
it returns with Solaris error "getpeername failed. Error was Invalid
argument"
389
390 if (smbd_server_fd() == -1 && errno == EINTR)
391 continue;
392
393 if (smbd_server_fd() == -1) {
394 DEBUG(0,("open_sockets_smbd: accept: %s\n",
395 strerror(errno)));
396 continue;
397 }
398
399 /* Ensure child is set to blocking mode */
400 set_blocking(smbd_server_fd(),True);
401
402 if (smbd_server_fd() != -1 && interactive)
403 return True;
404
405 if (allowable_number_of_smbd_processes() && smbd_server_fd()
!= -1 && sys_fork()==0) {
406 /* Child code ... */
407
408 /* close the listening socket(s) */
409 for(i = 0; i < num_sockets; i++)
410 close(fd_listenset[i]);
411
412 /* close our standard file
413 descriptors */
414 close_low_fds(False);
415 am_parent = 0;
416
417 set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
---> error message "Failed to set socket option SO_KEEPALIVE (Error
Invalid argument)" is issued
418 set_socket_options(smbd_server_fd(),user_socket_options);
---> error message "Failed to set socket option TCP_NODELAY (Error
Invalid argument)" is issued
Notes:
======
- Not sure where the second getpeername() error comes from but it's not
important.
- It seems that setsockopt() error appears only on Solaris (I think I
saw somewhere on internet that it can be seen also on HP Unix)
Where I see the problem:
========================
Don't know why Windows is reseting TCP connection. But it seems that
there are usually in such a case two attempts to connect to samba server
(windows is trying to connect twice to ports 139 or to port 139 and 445)
at the same time.
Samba is not functionally affected in any way. There are only several
messages in log and samba is once forked more. But if there is many
Windows clients, there is many messages. And in that case it can be a
problem (messages and performance)...
How to avoid it?
================
I think we should add into samba after accept() is returned some check
for socket sanity. If we find that socket is in some wrong state we
shouldn't even do fork (just a close socket and continue in main loop).
But I see there some possible race condition. I believe [RST, ACK] can
arrive little bit later (after we returned from accept() and maybe even
after we are forked).
So, probably the best idea is to check return values from all socket
calls and behave according them (even for getpeername() and setsockopt()).
---
Any comments are welcomed... :-)
Petr
More information about the samba-technical
mailing list