如何在套接字上设置不分段(DF)标志?
我正在尝试设置 DF(不分段标志)以使用 UDP 发送数据包。
正在看 Richard Steven 的书 Volume 1 Unix Network Programming; Sockets Networking API,我无法找到如何设置它。
我怀疑我会使用setsockopt() 来完成此操作,但在第193 页的表中找不到它。
请建议如何完成此操作。
I am trying to set the DF (don't fragment flag) for sending packets using UDP.
Looking at the Richard Steven's book Volume 1 Unix Network Programming; The Sockets Networking API, I am unable to find how to set this.
I suspect that I would do it with setsockopt() but can't find it in the table on page 193.
Please suggest how this is done.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您在 Userland 中工作,打算绕过内核网络堆栈,从而构建自己的数据包和标头,并将它们交给自定义内核模块,那么有一个比
setsockopt()
更好的选择。实际上,您可以像
linux/ip.h
中定义的struct iphdr
的任何其他字段一样设置 DF 标志。 3 位 IP 标志实际上是frag_off
的一部分(Fragment Offset) 结构成员。
当您考虑它时,将这两件事分组是有意义的,因为标志与碎片相关。 根据RFC-791,描述IP头结构的部分指出Fragment Offset是13 位长,有 3 个 1 位标志。 <代码>
frag_off 成员的类型为
__be16
,可以容纳 13 + 3 位。长话短说,这是一个解决方案:
我们在这里使用专门设计的
IP_DF
掩码来准确设置 DF 位。IP_DF
在net/ip.h
中定义(当然是内核头文件),而struct iphdr
在linux/ip 中定义.h
。If you are working in Userland with the intention to bypass the Kernel network stack and thus building your own packets and headers and hand them to a custom Kernel module, there is a better option than
setsockopt()
.You can actually set the DF flag just like any other field of
struct iphdr
defined inlinux/ip.h
. The 3-bit IP flags are in fact part of thefrag_off
(Fragment Offset) member of the structure.
When you think about it, it makes sense to group those two things as the flags are fragmentation related. According to the RFC-791, the section describing the IP header structure states that Fragment Offset is 13-bit long and there are three 1-bit flags. The
member is of typefrag_off
__be16
, which can hold 13 + 3 bits.Long story short, here's a solution:
We are here exactly setting the DF bit using the designed-for-that-particular-purpose
IP_DF
mask.IP_DF
is defined innet/ip.h
(kernel headers, of course), whereasstruct iphdr
is defined inlinux/ip.h
.我同意paxdiablo的回答。
其中
val
是以下之一:ip_no_pmtu_disc
:I agree with the paxdiablo's answer.
where
val
is one of:ip_no_pmtu_disc
in kernel source:您可以使用
IP_DONTFRAG
选项通过setsockopt()
调用来完成此操作:这里页面对此进行了更详细的解释。
对于 Linux,您似乎必须使用带有值
IP_PMTUDISC_DO
的IP_MTU_DISCOVER
选项(或IP_PMTUDISC_DONT
将其关闭):我还没有对此进行了测试,只需查看头文件和一些网络搜索,因此您需要对其进行测试。
至于是否还有另一种方法可以设置 DF 标志:
从这个优秀的页面此处:
在我看来,您可以使用 sysctl 设置系统范围的默认值:
在我的系统上返回
"error: "ip_no_pmtu_disc" is an Unknown key"
但它可能已设置在你的身上。 除此之外,我不知道任何其他因素(除了前面提到的setsockopt()
之外)会影响设置。You do it with the
setsockopt()
call, by using theIP_DONTFRAG
option:Here's a page explaining this in further detail.
For Linux, it appears you have to use the
IP_MTU_DISCOVER
option with the valueIP_PMTUDISC_DO
(orIP_PMTUDISC_DONT
to turn it off):I haven't tested this, just looked in the header files and a bit of a web search so you'll need to test it.
As to whether there's another way the DF flag could be set:
From this excellent page here:
This looks to me like you can set the system-wide default using
sysctl
:returns
"error: "ip_no_pmtu_disc" is an unknown key"
on my system but it may be set on yours. Other than that, I'm not aware of anything else (other thansetsockopt()
as previously mentioned) that can affect the setting.