2009-06-10 143 views
8

我試圖設置DF(不分片標誌)使用UDP發送數據包。如何在套接字上設置不分段(DF)標誌?

查看Richard Steven的書第1卷Unix網絡編程;套接字網絡API,我無法找到如何設置此。

我懷疑我會用setsockopt()做到這一點,但無法找到它的頁表193

請建議如何做到這一點。

回答

18

您與setsockopt()呼叫做,通過使用IP_DONTFRAG選項::

int val = 1; 
setsockopt(sd, IPPROTO_IP, IP_DONTFRAG, &val, sizeof(val)); 

Here's進一步詳細解釋這個頁面。

對於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)); 

我沒有測試過這一點,只是看着在頭文件和有點網絡搜索,所以你需要測試它。

至於是否有另一種方式的DF標誌可以設置:

I find nowhere in my program where the "force DF flag" is set, yet tcpdump suggests it is. Is there any other way this could get set?

從這個優秀的頁面here

IP_MTU_DISCOVER: Sets or receives the Path MTU Discovery setting for a socket. When enabled, Linux will perform Path MTU Discovery as defined in RFC 1191 on this socket. The don't fragment flag is set on all outgoing datagrams. The system-wide default is controlled by the ip_no_pmtu_disc sysctl for SOCK_STREAM sockets, and disabled on all others. For non SOCK_STREAM sockets it is the user's responsibility to packetize the data in MTU sized chunks and to do the retransmits if necessary. The kernel will reject packets that are bigger than the known path MTU if this flag is set (with EMSGSIZE).

這看起來對我來說,你可以設置系統默認使用sysctl

sysctl ip_no_pmtu_disc 

返回"error: "ip_no_pmtu_disc" is an unknown key"在我的系統上,但它可能會設置在你的系統上。除此之外,我不知道任何其他可能會影響設置的內容(前面提到的setsockopt()除外)。

+0

哪個水平是在IPPROTO_IP下? – WilliamKF 2009-06-10 02:37:20

3

如果您在Userland工作,打算繞過內核網絡堆棧,從而構建自己的數據包和標題並將它們交給定製的內核模塊,則有一個比setsockopt()更好的選項。

實際上,您可以像設置linux/ip.h中定義的struct iphdr的任何其他字段一樣設置DF標誌。 3位IP標誌實際上是該結構的frag_off (片段偏移)成員的一部分。

當你考慮這個問題時,將這兩件事情分組是有意義的,因爲這些標誌與碎片相關。根據RFC-791,描述IP頭結構的部分指出片段偏移長度爲13位,並且有三個1位標誌。 frag_off成員的類型爲__be16,它可以保存13 + 3位。

長話短說,這裏有一個解決方案:

struct iphdr ip; 
ip.frag_off |= ntohs(IP_DF); 

使用設計的換那個,尤其是用IP_DF面膜我們在這裏正好設置DF位。

IP_DF定義在net/ip.h(當然是內核標題),而struct iphdr定義在linux/ip.h中。

0

我同意paxdiablo的回答。

  • setsockopt的(的sockfd,IPPROTO_IP,IP_MTU_DISCOVER,&纈氨酸,的sizeof(VAL))
#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在內核源:

if (ipv4_config.no_pmtu_disc) inet->pmtudisc = IP_PMTUDISC_DONT; else inet->pmtudisc = IP_PMTUDISC_WANT;

相關問題