【发布时间】:2017-03-12 17:16:51
【问题描述】:
我正在链接 linux/tcp.h 并且我正在尝试读取 TCP 选项,但我似乎无法找到这样做的方法。我已经在线阅读了一些内容,根据一些在线资源,我必须迭代所有“剩余数据包”,直到我点击我想要的选项? (现在我将尝试专注于“MSS”选项)。谁能给我一个代码示例?
struct iphdr *iph = ((struct iphdr *) full_packet);
fprintf(stdout, "IP{v=%u; ihl=%u; tos=%u; tot_len=%u; id=%u; ttl=%u; protocol=%u; "
,iph->version, iph->ihl*4, iph->tos, ntohs(iph->tot_len), ntohs(iph->id), iph->ttl, iph->protocol);
if (iph->protocol == 6){
struct tcphdr *tcp = ((struct tcphdr *) (full_packet + (iph->ihl << 2)));
fprintf(stdout, "TCP{sport=%u; dport=%u; seq=%u; ack_seq=%u; flags=u%ua%up%ur%us%uf%u; window=%u; urg=%u}\n",
ntohs(tcp->source), ntohs(tcp->dest), ntohl(tcp->seq), ntohl(tcp->ack_seq)
,tcp->urg, tcp->ack, tcp->psh, tcp->rst, tcp->syn, tcp->fin, ntohs(tcp->window), tcp->urg_ptr);\
}
到目前为止,我在读取/解析 IP/TCP 数据方面是什么
谢谢!
顶...任何帮助表示赞赏!
进度更新(感谢@WillisBlackburn):
struct iphdr *iph = ((struct iphdr *) full_packet);
fprintf(stdout, "IP{v=%u; ihl=%u; tos=%u; tot_len=%u; id=%u; ttl=%u; protocol=%u; "
,iph->version, iph->ihl*4, iph->tos, ntohs(iph->tot_len), ntohs(iph->id), iph->ttl, iph->protocol);
if (iph->protocol == 6){
struct tcphdr *tcp = ((struct tcphdr *) (full_packet + (iph->ihl << 2)));
uint8_t *p = (uint8_t *)tcp + 20;
uint8_t *end = (uint8_t *)tcp + tcp->doff * 4;
uint16_t mss = 0;
printf("\nThe offset is %d\n", tcp->doff);
printf("Let's check what's at location p: %u is supposed to be less than %d\n",(*(uint8_t *)tcp + 20), (uint8_t)end);
while (p < end) {
uint8_t kind = *p++;
if (kind == 0) {
printf("The kind is 0?\n");
break;
}
if (kind == 1) {
// No-op option with no length.
continue;
}
uint8_t size = *p++;
if (kind == 2) {
mss = ntohs(*(uint16_t *)p);
printf("The MSS value is: %d\n", mss);
}
p += (size - 2);
}
fprintf(stdout, "TCP{sport=%u; dport=%u; seq=%u; ack_seq=%u; flags=u%ua%up%ur%us%uf%u; window=%u; urg=%u}\n",
ntohs(tcp->source), ntohs(tcp->dest), ntohl(tcp->seq), ntohl(tcp->ack_seq)
,tcp->urg, tcp->ack, tcp->psh, tcp->rst, tcp->syn, tcp->fin, ntohs(tcp->window), tcp->urg_ptr);
}
更多进展:
发现了一些很酷的读取 TCP 选项的实现;但是,我不太确定在我的代码中实现它。人们有什么帮助吗?这是我发现的:
它似乎比 WillisBlackburn 的复杂一些,并且可能会解决那种太大的问题? (200+ 一些数据包,而不是我们期望的 MSS 的“2”(+ TCP 数据包中的其他选项)。
不胜感激!!!
如果你想谈论它,我将在频道#adamc 中的 chat.freenode.net (niven.freenode.net) 中讨论!
最新更新:
所以,我基于 MTCP,但这里是代码:(添加的用户测试):
const unsigned char *ptr;
const struct tcphdr *th = ((struct tcphdr *) (full_packet + (iph->ihl << 2)));
int length = (th->doff * 4) - sizeof(struct tcphdr);
ptr = (const unsigned char *)(th + 1);
while(length > 0){
printf("Got in the while loop\n");
int opcode = *ptr++;
int opsize;
switch(opcode) {
case 0:
printf("Got the initial val (EOL)\n");
return;
case 1:
printf("Got the NOP val as well!\n");
length--;
continue;
default:
printf("Entered default.\n");
opsize = *ptr++;
printf("Does stuff after setting the OPSize.\n");
if(opsize < 2) {
printf("OPSize = %d < 2;Length = %d\n", opsize, length);
return;
}
if(opsize > length) {
printf("OPSize = %d > Length = %d\n", opsize, length);
return;
}
switch(opcode) {
printf("Switching the OPCode\n");
case 2: //TCP MSS
if(opsize == 4 && th->syn) {
printf("MSS: %d\n", ptr);
}
case 3: //TCP Window
if(opsize==3 && th->syn) {
uint8_t wscale = *(uint8_t *)ptr;
if(wscale>14) {
printf("Illgal wscale value: %d\n", wscale);
}
printf("WSCALE: %d\n", *(uint8_t*)ptr);
}
break;
case 8: //Timestamp
if(opsize==10) {
printf("Timestamp is present!!!\n");
}
break;
case 4: //TCP SACK
if((opsize >= (2+8)) && !((opsize-2)%8)) {
printf("SACK val: %d\n", ((ptr-2)- (unsigned char *)th));
}
default:
printf("Entered default of switching OPCode\n");
return;
}
ptr += opsize-2;
length -= opsize;
}
}
所以现在我的问题是: 当我提出请求时,它会给我以下信息:
IP{v=4; ihl=20; tos=0; tot_len=64; id=48952; ttl=61; protocol=6; Got in the while loop
Entered default.
Does stuff after setting the OPSize.
OPSize = 127 > Length = 12
所以基本上,它进入了while循环,进入了默认值(在opsizes之间切换)等等;但是,OPSize 是 127(大于长度),所以我相信我在获取尺寸方面做错了。任何帮助将不胜感激!
【问题讨论】:
-
是用户空间程序吗?为什么需要选项?你从哪里得到的包?根据en.wikipedia.org/wiki/… 选项只是在 tcp 标头的固定字段之后,但它们没有固定的结构。请检查struct tcphdr 的“数据偏移”字段
doff字段,增加指向数据包的指针并解析它们(或要求解析给你full_packet的东西)。示例:lxr.free-electrons.com/source/net/netfilter/… - TCPOPT_MSS -
@osgx 是的,它是一个用户空间程序。我正在阅读防火墙中的选项,并通过他们的排队系统从 netfilter 获取数据包。我仍然对那个示例感到有些困惑。您还有其他更易于阅读的示例或与上述示例特别适用的示例吗?
-
我没有其他示例,并且我发现了这一示例中唯一令人困惑的点 - 指针增量为
op = skb_header_pointer(skb, par->thoff + sizeof(*th), optlen, _opt);- 将其替换为const u_int8_t *op = ((u_int8_t *) full_packet ) + tcphdr.doff*4 - sizeof(struct tcphdr)。宏定义在 include/net/tcp.h - lxr.free-electrons.com/source/include/net/tcp.h#L175 TCPOPT_MSS 2 TCPOLEN_MSS 4
标签: c linux networking tcp