tun/tap を使用して TCP パケットを構造体に読み込もうとしているので、tun デバイスを使用するように IFF_TUN フラグが設定されています (イーサネット ヘッダーなし)。
私は次のような構造体を持っています (エンディアンの問題は気にしません):
TCP ヘッダー:
struct tcphdr {
uint16_t sport;
uint16_t dport;
uint32_t seq;
uint32_t ack_seq;
uint8_t rsvd : 4;
uint8_t dataoff : 4;
uint8_t fin : 1,
syn : 1,
rst : 1,
psh : 1,
ack : 1,
urg : 1,
ece : 1,
cwr : 1;
uint16_t win;
uint16_t csum;
uint16_t urp;
} __attribute__((packed));
Ipv4 ヘッダー:
struct ipv4hdr {
uint8_t ihl : 4;
uint8_t version : 4;
uint8_t tos;
uint16_t len;
uint16_t id;
uint16_t frag_offset;
uint8_t ttl;
uint8_t proto;
uint16_t csum;
uint32_t saddr;
uint32_t daddr;
} __attribute__((packed));
次のようにパケットを読み取ります。
size_t nbytes = read(fd, bytes, 1504); // fd is eg. fd = open("/dev/net/tun", O_RDWR)
uint16_t eth_flags = bytes[0] << 8 | bytes[1]; // big-endian
uint16_t eth_proto = bytes[2] << 8 | bytes[3]; // big-endian
if (eth_proto != 0x800)
// ignore no ipv4 packets
// https://en.wikipedia.org/wiki/EtherType
continue;
if (ip_hdr->proto != 0x06)
// ignore non-TCP packets
// https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers
continue;
そしてこれまでのところ、とても良いです。しかし、TCPシーケンス番号を読み取ろうとすると、間違った番号が表示されます:
ipv4hdr *ip_hdr = (ipv4hdr *)(bytes + 4); // 4 first bytes are packet information provided by kernel
tcphdr *tcp_hdr = (tcphdr *)(bytes + 4 + ip_hdr->ihl * 4); // reading TCP at the end of the IP header
std::cout << std::hex << ntohl(tcp_hdr->seq) << std::endl; // the output number is wrong!
tshark の出力は seq=0 を示します (以下のように):
Capturing on 'tun0'
1 0.000000000 192.168.0.1 → 192.168.0.2 TCP 60 44248 → 8000 [SYN] Seq=0 Win=29200 Len=0 MSS=1460 SACK_PERM=1 TSval=1233752815 TSecr=0 WS=128
しかし、私のコード出力は7be53b39 です