2007-07-21

What happened to tcp flag URGENT, MSG_OOB and SIGURG?

Nobody today uses tcp urgent mode, so it's good topic to make some research on.

Usually when socket receives tcp packet with URG flag it treats it as normal tcp data. recv() is going to read urgent data as it was normal tcp stream. The only difference is that the last byte of data is discarded. The last byte in urgent data was always a problem due to incoherent rfc.

Pseudocode for this case:

server: send("ab", MSG_OOB)
client: recv() -> "a"
Tcp urgent packets whould trigger SIGURG for process that's listening on socket. It doesn't work until we set process pid of socket owner (thanks MichaƂ for this tip).
if (fcntl(sd, F_SETOWN, getpid()) < 0) {
perror("fcntl()");
exit(-1);
}
The interesting thing is that after we enabled SIGURG it's possible to send a signal to remote process without sending any valid data. Such situation occures when process receives tcp URG packet with one byte payload. The only byte is discarded, no data is waiting on a socket, but SIGURG is sent to a process.
client: signal(SIGURG, handler);
client: fcntl(sd, F_SETOWN, getpid());
client: poll([sd], 1, 1000);
server: send("a", MSG_OOB);
client: signal SIGURG is received by a handler
client: poll ends, because of received signal
client: but there aren't any data waiting on a socket
That's all. Feel free to use draft source code of client and server I used for testing.


5 comments:

Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...

http://tools.ietf.org/html/draft-ietf-tcpm-urgent-data-05

Anonymous said...
This comment has been removed by the author.
majek said...

Tom, thanks for the link!

Unknown said...

You are only ever supposed to send one byte with SIGURG flag. On the receive end, the packet with URG bit set is put in the head of the received packets queue, behind any other URG-marked packets.
This is what lets your telnet session send the signal to HUP the connection and it's responded to quickly at the server even if there is a large volume of bytes carried by that connection that are not marked urgent. The byte is stripped from the stream and the urgetn signal can be delivered to the app (if it's set up to catch it).