3
votes

I have problem with a TCP socket receiving messages with wrong destination port.

The OS is Ubuntu Linux 10.10 and kernel version is 2.6.31-11-rt, but this happens with other kernels, too. The C/C++ program with this problem does this:

  1. A TCP server socket is listening to connections in INADDR_ANY at port 9000.

  2. Messages are received with recv(2) by a TCP message receiver thread. Connection is not closed after reading message, but the thread continues to read from the same connection forever.

  3. Error: also messages to other ports than 9000 are received by the TCP message receiver. For example, when a remote SFTP client connects to the PC where TCP message receiver is listening, it causes the TCP message receiver to receive also the SFTP messages. How is this EVER possible? How can the TCP ports "leak" this way? I think SFTP should use port 22, right? Then how it's possible those messages are visible in port 9000?

More info:

  • At the same time there's a raw socket listening on another network interface, and the interface is in promiscuous mode. Could this have an effect?

  • The TCP connection is not closed in between message receptions. The message listener just keeps reading data from the socket. Is this really a correct way to implement a TCP message receiver?

Has anyone seen this kind of problem? Thanks in advance.

EDIT:

Ok, here is some code. The code looks to be allright, so the main strange thing is, how a TCP socket can ever receive data sent to another port?

/// Create TCP socket and make it listen to defined port
TcpSocket::listen() {
    m_listenFd = socket(AF_INET, SOCK_STREAM, 0)
    ...
    bzero(&m_servaddr, sizeof(sockaddr_in));
    m_servaddr.sin_family = AF_INET;
    m_servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    m_servaddr.sin_port = htons(9000);
    bind(m_listenFd, (struct sockaddr *)&m_servaddr, sizeof(sockaddr_in);
    ...
    listen(m_listenFd, 1024);
    ...
    m_connectFd = accept(m_listenFd, NULL, NULL);
}

/// Receive message from TCP socket.
TcpSocket::receiveMessage() {
    Uint16 receivedBytes = 0;
    // get the common fixed-size message header (this is an own message structure)
    Uint16 numBytes = recv(m_connectFd, msgPtr + receivedBytes, sizeof(SCommonTcpMSGHeader), MSG_WAITALL);
    ...
    receivedBytes = numBytes;
    expectedMsgLength = commonMsgHeader->m_msgLength;   // commonMsgHeader is mapped to received header bytes
    ...
    // ok to get message body
    numBytes = recv(m_connectFd, msgPtr + receivedBytes, expectedMsgLength - receivedBytes, MSG_WAITALL);
}
2
Something else is likely going on (maybe you're reading from the raw socket, not the TCP socket). What kind of "messages" do you get e.g. when the sftp client connects ?nos
@nos The socket I'm reading from should be the correct one because it's in a TCP socket class. The raw socket is similarly in another class. Not possible to confuse. The messages are just whatever data comes in from the network. The printouts from TCP message handler class tell it has received stuff which it should not have received.HJK25
The sequence should be socket(), bind(), listen(), accept(). What's your code doing, could you post the relevant parts ?FrankH.
Also, when you say "receives from wrong port", do you mean that the remote port is different from 9000 ? That'd be normal / expected; all you can control before accepting a connection is the local port (via bind). The remote port number can only be queried after accept by calling getpeername(), but a connection cannot be refused based on a remote port number.FrankH.
@HJK25 Sure it should be, but give a bug/memory error/whatever, anything's possible. (besides, a socket is just an int, so if you for some reason get the wrong int/have a buffer overflow, you can easily read from something else. You should at least print out the socket file descriptor you're reading from. Then do some debugging by looking at /proc/the_pid/fd/ for the that socket descriptior, and compare its id with e.g. the output of netstat -apnnos

2 Answers

0
votes

The TCP connection is not closed in between message receptions. The message listener just keeps reading data from the socket. Is this really a correct way to implement a TCP message receiver?

Yes but it must close the socket and exit when it receives the EOS indication (recv() returns zero).

I think it's ten to one your raw socket and TCP socket FDs are getting mixed up somewhere.

0
votes

Umm... It appears that it was the raw socket after all which has received the messages. Can see from the log that it's the raw message handler printing out message reception things, not the TCP message handler. Duh...! :S Sorry. So it seems the binding of the raw socket into the other network interface doesn't work correctly. Need to fix that. Funny though that sometimes it works with SSH/SFTP, sometimes it does not.