2 回答

TA貢獻(xiàn)1860條經(jīng)驗(yàn) 獲得超9個(gè)贊
好的,我現(xiàn)在可以讓它在 OS X 上運(yùn)行了。您需要確保您正在設(shè)置IP_HDRINCL套接字選項(xiàng)syscall.SetsockoptInt(s, syscall.IPPROTO_IP, syscall.IP_HDRINCL, 1),然后您需要小心構(gòu)建數(shù)據(jù)包。吸引我很長(zhǎng)時(shí)間的一個(gè)技巧是,出于某種原因,Sendto OS X/BSD 想要主機(jī)字節(jié)順序中的 IP 長(zhǎng)度,在我的情況下是 LittleEndian,而不是 BigEndian,這是典型的網(wǎng)絡(luò)順序。如果您查看此代碼(我只是自己構(gòu)建了 IP 標(biāo)頭,您可以以另一種方式構(gòu)建它),它會(huì)按預(yù)期運(yùn)行。
package main
import (
"encoding/binary"
"fmt"
"syscall"
)
func main() {
s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
if err != nil {
panic(err)
}
err = syscall.SetsockoptInt(s, syscall.IPPROTO_IP, syscall.IP_HDRINCL, 1)
if err != nil {
panic(err)
}
addr := syscall.SockaddrInet4{Addr: [4]byte{127, 0, 0, 1}}
data := makepacket()
for _, v := range data {
if v == 0 {
fmt.Printf("00 ")
continue
} else if v < 0xf {
fmt.Printf("0%x ", v)
continue
}
fmt.Printf("%x ", v)
}
fmt.Printf("\n")
err = syscall.Sendto(s, data, 0, &addr)
if err != nil {
panic(err)
}
}
func makepacket() []byte {
icmp := []byte{
8, // type: echo request
0, // code: not used by echo request
0, // checksum (16 bit), we fill in below
0,
0, // identifier (16 bit). zero allowed.
0,
0, // sequence number (16 bit). zero allowed.
0,
0xC0, // Optional data. ping puts time packet sent here
0xDE,
}
cs := csum(icmp)
icmp[2] = byte(cs)
icmp[3] = byte(cs >> 8)
buf := []byte{0x45, 0x00, 0x00, 0x00, 0x95, 0x13, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x7f, 0x00, 0x0
0, 0x01, 0x7f, 0x00, 0x00, 0x01}
binary.LittleEndian.PutUint16(buf[2:4], uint16(len(icmp) + len(buf)))
return append(buf, icmp...)
}
func csum(b []byte) uint16 {
var s uint32
for i := 0; i < len(b); i += 2 {
s += uint32(b[i+1])<<8 | uint32(b[i])
這段代碼給了我這個(gè)輸出 # tcpdump -X -i lo0
20:05:24.016465 IP localhost > localhost: ICMP echo request, id 0, seq 0, length 10
0x0000: 4500 001e 9513 0000 4001 0000 7f00 0001 E.......@.......
0x0010: 7f00 0001 0800 3721 0000 0000 c0de ......7!......
20:05:24.016495 IP localhost > localhost: ICMP echo reply, id 0, seq 0, length 10
0x0000: 4500 001e 3e4f 0000 4001 0000 7f00 0001 E...>O..@.......
0x0010: 7f00 0001 0000 3f21 0000 0000 c0de ......?!......

TA貢獻(xiàn)1836條經(jīng)驗(yàn) 獲得超5個(gè)贊
這是我從 Mikio 那里得到的關(guān)于 Go 項(xiàng)目的答案。我在這里為可能正在尋找此問題解決方案的其他人添加它。
package main
import (
"fmt"
"golang.org/x/net/ipv4"
"log"
"net"
)
func main() {
ip := net.ParseIP("127.0.0.1")
proto := 1
c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", proto), "0.0.0.0")
if err != nil {
log.Fatal(err)
}
defer c.Close()
p, err := ipv4.NewRawConn(c)
if err != nil {
log.Fatal(err)
}
b := []byte("HELLO-R-U-THERE")
h := &ipv4.Header{
Version: ipv4.Version,
Len: ipv4.HeaderLen,
TotalLen: ipv4.HeaderLen + len(b),
ID: 12345,
Protocol: proto,
Dst: ip.To4(),
}
if err := p.WriteTo(h, b, nil); err != nil {
log.Println(err)
}
}
- 2 回答
- 0 關(guān)注
- 289 瀏覽
添加回答
舉報(bào)