Search code examples
ctcplinux-kernelnetwork-programming

How to get next TCP segment in linux kernel module?


I know I can get the pointer of TCP packet data like this:

char *data = (char *)tcphdr + 4 * tcph->doff;

But once data was segmented I cannot get full data such way. So how to get next sk_buff of next segment?

My simple code:

#include ...

static struct nf_hook_ops nfho;

unsigned int hook_funcion(void *priv, struct sk_buff *skb, const struct
                          nf_hook_state *state)
{

    // check if it is TCP packet

    char *data = (char *)tcphdr + 4 * tcph->doff;

    // do something here

    return NF_ACCEPT;
}

static int __init hook_init(void)
{
    int ret;

    nfho.hook = hook_funcion;
    nfho.pf = NFPROTO_IPV4;
    nfho.hooknum = NF_INET_POST_ROUTING;
    nfho.priority = NF_IP_PRI_LAST;
    ret = nf_register_hook(&nfho);
    printk("xmurp-test start\n");
    printk("nf_register_hook returnd %d\n", ret);

    return 0;
}

static void __exit hook_exit(void)
{
    nf_unregister_hook(&nfho);
    printk("xmurp-test stop\n");
}

module_init(hook_init);
module_exit(hook_exit);

Solution

  • Your question is a bit complicated as there is no such thing in TCP as "full data", as TCP is a stream protocol and not a datagram protocol (in contrast of UDP). This means that there is no specific end to the data (unless the connection is closed / reset).

    If you're handling an application-layer protocol which segments the TCP stream into sized messages (for example: HTTP), you should act in the following steps:

    1. Parse the TCP payload and figure out how large this current message is.
    2. Only then you can handle the following packets / segments as they arrive in the network stack as the continuation of the same message.
    3. Finally, after all the data you expect have arrived, you can reassemble them and only then use their data on the application layer.

    Do remember that the network works in datagrams and TCP is a stream protocol. So it might be very much possible that at the time of your first segment's handling, the rest of the data has yet to arrive. Therefore you must manage a desegmentation (defragmentation) over this and future packets over this specific stream and only then parse upper layer protocols.