Seeing TCP socket options on apps you don't have source code for


I (Mike MacCana) needed to identify whether an app we did not have source code for was using TCP_NODELAY on its sockets. Originally I thought netstat or lsof may do this per other OSs, but reading the lsof FAQ:

3.14.1  Why doesn't lsof report socket options, socket states, and TCP
        flags and values for my dialect?

                No socket options and values, socket states, or TCP
                flags and values are reported.  The support for "-Tf"
                could not be added to Linux, because socket options,
                socket states, and TCP flags and values are not
                available via the /proc file system.

Damn, that sucks. However the SystemTap Networking Tapset provides a tcp.setsockopt breakpoint which I can use. See (search for tcp.setsockopt ).


So here's the .stap file.

# Show sockets setting options

# Return enabled or disabled based on value of optval
function getstatus(optval)
    if ( optval == 1 )
        return "enabling"
        return "disabling"

probe begin
        print ("\nChecking for apps setting socket options\n")

# Set a socket option 
probe tcp.setsockopt
    status = getstatus(user_int($optval))
        printf ("  App '%s' (PID %d) is %s socket option %s... ", execname(), pid(), status, optstr)

# Check setting the socket option worked
probe tcp.setsockopt.return
    if ( ret == 0 )
        printf ("success")
        printf ("failed")
    printf ("\n")    

probe end
        print ("\nClosing down\n")

Let's make a quick app to test the tap works. The app below makes a socket with NO_DELAY and hangs around for 10 seconds before cleaning up:

# -*- python -*-
# -*- coding: utf-8 -*-
'''Simple example to create a socket with NODELAY. '''

host = 'localhost'
port = 60000

import socket
import time

def settcpoption(socket,option,enabled):
    '''Set a TCP option to be True or False on a socket'''

    # /usr/src/redhat/BUILD/linux-2.6.18/include/linux/socket.h
    socketlevels = {
    # /usr/src/redhat/BUILD/linux-2.6.18/include/linux/tcp.h    
    tcpoptions = {
    socket.setsockopt(socketlevels['ip'], tcpoptions[option], int(enabled))

def makeclient():
    '''Create a client socket'''
    #create an INET, STREAMing socket
    clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    return clientsocket

if __name__ == '__main__':
    clientsocket = makeclient()
    # Set TCP_NODELAY before sending short messages that should be sent immediately.
    # Set TCP_CORK before sending a series of data 
    # that should be considered as a single message
    # settcpoption(clientsocket,'cork',True)    

We'll run the demo app first, then run stap in another tab:


Checking for apps setting socket options
  App 'python2.4' (PID 14415) is enabling socket option TCP_NODELAY... success
  App 'python2.4' (PID 14420) is disabling socket option TCP_NODELAY... success

Sweet, it works with our demo app. We can now run the tap while our proprietary application runs, and see whether it's using NODELAY or not.


We can use SystemTap to get info out of the kernel even if the developers haven't exposed it via /proc or /sys.


None: WSTCPSocketOptions (last edited 2010-03-26 10:19:49 by ln-bas00)