pax*_*blo 19
你可以setsockopt()通过使用IP_DONTFRAG选项::
int val = 1;
setsockopt(sd, IPPROTO_IP, IP_DONTFRAG, &val, sizeof(val));
Run Code Online (Sandbox Code Playgroud)
这是一个更详细地解释这一点的页面.
对于Linux,您似乎必须使用IP_MTU_DISCOVER带有值的选项IP_PMTUDISC_DO(或IP_PMTUDISC_DONT将其关闭):
int val = IP_PMTUDISC_DO;
setsockopt(sd, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val));
Run Code Online (Sandbox Code Playgroud)
我没有测试过这个,只是查看了头文件和一些网页搜索,所以你需要测试它.
至于是否可以设置DF标志的另一种方式:
我发现在我的程序中没有设置"强制DF标志",但
tcpdump建议它是.有没有其他方法可以设置?
从这个优秀的页面在这里:
IP_MTU_DISCOVER:设置或接收套接字的"路径MTU发现"设置.启用后,Linux将在此套接字上执行RFC 1191中定义的路径MTU发现.在所有传出数据报上设置了不分段标志.系统范围的默认值由ip_no_pmtu_discsysctlforSOCK_STREAM套接字控制,在其他所有套接字上禁用.对于非SOCK_STREAM套接字,用户有责任将数据打包为MTU大小的块,并在必要时进行重新传输.如果设置了此标志(带EMSGSIZE),内核将拒绝大于已知路径MTU的数据包.
在我看来,您可以使用sysctl以下方法设置系统范围的默认值:
sysctl ip_no_pmtu_disc
Run Code Online (Sandbox Code Playgroud)
"error: "ip_no_pmtu_disc" is an unknown key"在我的系统上返回,但它可以设置在你的系统上.除此之外,我不知道setsockopt()可能影响设置的其他任何事情(除了前面提到的).
如果您在 Userland 中工作,打算绕过内核网络堆栈,从而构建自己的数据包和标头并将它们交给自定义内核模块,那么有一个比setsockopt().
struct iphdr实际上,您可以像中定义的任何其他字段一样设置 DF 标志linux/ip.h。3 位 IP 标志实际上是该frag_off
结构的(片段偏移)成员的一部分。
当您考虑它时,将这两件事分组是有意义的,因为标志与碎片相关。根据RFC-791,描述IP头结构的部分规定Fragment Offset是13位长,并且有3个1位标志。该
frag_off成员的类型为__be16,可以容纳 13 + 3 位。
长话短说,这是一个解决方案:
struct iphdr ip;
ip.frag_off |= ntohs(IP_DF);
Run Code Online (Sandbox Code Playgroud)
我们在这里使用专门设计的掩码来准确设置 DF 位IP_DF。
IP_DF是在net/ip.h(当然是内核头文件)中定义的,而struct iphdr是在linux/ip.h.
小智 5
我同意paxdiablo的回答。
其中val之一是:
Run Code Online (Sandbox Code Playgroud)#define IP_PMTUDISC_DONT 0 /* Never send DF frames. */ #define IP_PMTUDISC_WANT 1 /* Use per route hints. */ #define IP_PMTUDISC_DO 2 /* Always DF. */ #define IP_PMTUDISC_PROBE 3 /* Ignore dst pmtu. */
ip_no_pmtu_disc在内核源代码中:Run Code Online (Sandbox Code Playgroud)if (ipv4_config.no_pmtu_disc) inet->pmtudisc = IP_PMTUDISC_DONT; else inet->pmtudisc = IP_PMTUDISC_WANT;
| 归档时间: |
|
| 查看次数: |
36191 次 |
| 最近记录: |