/* Print field offsets of xtcpcb, inpcb, tcpcb */
#include <stdio.h>
#include <stddef.h>
#include <sys/types.h>
#include <sys/socketvar.h>
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/tcp_var.h>

int main(void) {
    printf("sizeof(struct inpcb) = %zu\n", sizeof(struct inpcb));
    printf("sizeof(struct tcpcb) = %zu\n", sizeof(struct tcpcb));
    printf("sizeof(struct xtcpcb) = %zu\n", sizeof(struct xtcpcb));
    struct xtcpcb xt;
    printf("xt.xt_len offset = %zu\n", offsetof(struct xtcpcb, xt_len));
    printf("xt.xt_inp offset = %zu\n", offsetof(struct xtcpcb, xt_inp));
    printf("xt.xt_tp offset = %zu\n", offsetof(struct xtcpcb, xt_tp));
    printf("xt.xt_socket offset = %zu\n", offsetof(struct xtcpcb, xt_socket));
    printf("xt.xt_alignment_hack offset = %zu\n", offsetof(struct xtcpcb, xt_alignment_hack));
    printf("--- tcpcb field offsets (absolute in xtcpcb) ---\n");
    size_t tp_base = offsetof(struct xtcpcb, xt_tp);
    printf("tp.t_segq abs = %zu\n", tp_base + offsetof(struct tcpcb, t_segq));
    printf("tp.t_inpcb abs = %zu\n", tp_base + offsetof(struct tcpcb, t_inpcb));
    printf("tp.scb abs = %zu\n", tp_base + offsetof(struct tcpcb, scb));
    printf("tp.scb.sackblocks abs = %zu\n", tp_base + offsetof(struct tcpcb, scb) + offsetof(struct scoreboard, sackblocks));
    printf("tp.scb.lastfound abs = %zu\n", tp_base + offsetof(struct tcpcb, scb) + offsetof(struct scoreboard, lastfound));
    printf("tp.scb.freecache abs = %zu\n", tp_base + offsetof(struct tcpcb, scb) + offsetof(struct scoreboard, freecache));
    printf("tp.t_outputq abs = %zu\n", tp_base + offsetof(struct tcpcb, t_outputq));
    printf("--- inp field offsets (absolute in xtcpcb) ---\n");
    size_t inp_base = offsetof(struct xtcpcb, xt_inp);
    printf("inp.inp_hash abs = %zu\n", inp_base + offsetof(struct inpcb, inp_hash));
    printf("inp.inp_socket abs = %zu\n", inp_base + offsetof(struct inpcb, inp_socket));
    return 0;
}
