我的印象是,在 Linux 下,只要設定了IP_FREEBIND套接字選項,就可以系結到非本地地址,但這不是我看到的行為:
$ sudo strace -e 'trace=%network' ...
...
socket(AF_INET, SOCK_RAW, IPPROTO_UDP) = 5
setsockopt(5, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(5, SOL_SOCKET, SO_NO_CHECK, [1], 4) = 0
setsockopt(5, SOL_IP, IP_HDRINCL, [1], 4) = 0
setsockopt(5, SOL_IP, IP_FREEBIND, [1], 4) = 0
bind(5, {sa_family=AF_INET, sin_port=htons(abcd), sin_addr=inet_addr("w.x.y.z")}, 16) = -1 EADDRNOTAVAIL (Cannot assign requested address)
...
我還設定了ip_nonlocal_bind設定,只是為了確定,我得到了相同的結果。
$ sysctl net.ipv4.ip_nonlocal_bind
net.ipv4.ip_nonlocal_bind = 1
uj5u.com熱心網友回復:
不幸的是,似乎不可能將原始 IP 套接字系結到非本地、非廣播和非多播地址,無論IP_FREEBIND. 由于我inet_addr("w.x.y.z")在您的strace輸出中看到,我假設這正是您想要做的并且w.x.y.z是非本地單播地址,因此您的bind系統呼叫失敗。
這似乎符合man 7 raw:
可以 使用
bind(2)呼叫將原始套接字系結到特定的本地地址。如果未系結,則接收所有具有指定 IP 協議的資料包。此外,原始套接字可以使用SO_BINDTODEVICE;系結到特定的網路設備;見socket(7)。
確實,查看內核源代碼,raw_bind()我們可以看到以下檢查:
ret = -EADDRNOTAVAIL;
if (addr->sin_addr.s_addr && chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
goto out;
另外,請注意.sin_port必須是0. 的.sin_port原始套接字欄位被用于選擇一個發送/接收IP協議(不是埠,因為我們在第3級和埠不存在)。如手冊所述,從 Linux 2.2 開始,您不能再選擇發送協議.sin_port,發送協議是創建套接字時設定的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/387197.html
