本文共 963 字,大约阅读时间需要 3 分钟。
TCP的头部的构造是在函数tcp_transmit_skb()中进行的
函数片段如下:
/* Build TCP header and checksum it. */ th = tcp_hdr(skb); th->source = inet->inet_sport; th->dest = inet->inet_dport; th->seq = htonl(tcb->seq); th->ack_seq = htonl(tp->rcv_nxt); *(((__be16 *)th) + 6) = htons(((tcp_header_size >> 2) << 12) | tcb->flags);
我想分析的的是 最后一条代码,
*(((__be16 *)th) + 6) = htons(((tcp_header_size >> 2) << 12) | tcb->flags);
咋一看还没有看清楚,这个要结合TCP的头部结构来分析,下面是TCP结构图
代码解释如下:
1. (__be16 *)th 强制转换th为__be16类型 ; sizeof(__be16) 是2字节, 16bit ;
2. tcp_header_size >> 2 计算出了tcp首部长度, 因为 首部长度是指 4字节的个数,所以要要用真正的字节数来除以4; 3. ((tcp_header_size >> 2) << 12) 左移12位, 这样首部长度就位于13-16bit处, 空出来的12bit就留给保留位4位,flag 8位(新内核从6增加到8位) (比如:0x5000 , 5表示首部大小为20字节,接下来0,是保留位,剩下的就是flag.这时候保留位和flag都是0) tcb->flags是在control buffer(即sock->cb)中取的标记位的值 ;flag = CWR | ECE | URG | ACK | PSH | RST | SYN | FIN 如果有标记在sock处理过程中被置1了(比如SYN置1和ACK置1,此时flag=0x0011), 此时相或的话, 0x5000|0x0011 == 0x5011就可以把tcp头部的相应位置置1了; 我们也就我们也就填充好了flag位.