在Mac上的golang中使用AF_路由添加路由
我正在尝试使用golang中的AF_route套接字在我的Mac机器中添加路由。我用C语言写了一个pragram,并试图把它转换成golang。以下是我的golang计划:在Mac上的golang中使用AF_路由添加路由,go,routes,system-calls,raw-sockets,Go,Routes,System Calls,Raw Sockets,我正在尝试使用golang中的AF_route套接字在我的Mac机器中添加路由。我用C语言写了一个pragram,并试图把它转换成golang。以下是我的golang计划: package main import ( "bytes" "encoding/json" "fmt" "syscall" "unsafe" ) /* Copied and Converted from https://unix.superglobalmegacorp.com/Ne
package main
import (
"bytes"
"encoding/json"
"fmt"
"syscall"
"unsafe"
)
/* Copied and Converted from
https://unix.superglobalmegacorp.com/Net2/newsrc/net/route.h.html
*/
type rt_metrics struct {
rmx_locks uint64 /* Kernel must leave these values alone */
rmx_mtu uint64 /* MTU for this path */
rmx_hopcount uint64 /* max hops expected */
rmx_expire uint64 /* lifetime for route, e.g. redirect */
rmx_recvpipe uint64 /* inbound delay-bandwith product */
rmx_sendpipe uint64 /* outbound delay-bandwith product */
rmx_ssthresh uint64 /* outbound gateway buffer limit */
rmx_rtt uint64 /* estimated round trip time */
rmx_rttvar uint64 /* estimated rtt variance */
rmx_pksent uint32 /* packets sent using this route */
rmx_state uint32 /* route state */
rmx_filler [3]uint32 /* will be used for T/TCP later */
}
/* Copied and Converted from
https://unix.superglobalmegacorp.com/Net2/newsrc/net/route.h.html
*/
type rt_msghdr struct {
rtm_msglen uint16 /* to skip over non-understood messages */
rtm_version uint8 /* future binary compatability */
rtm_type uint8 /* message type */
rtm_index uint16 /* index for associated ifp */
rtm_pid uint32 /* identify sender */
rtm_addrs int /* bitmask identifying sockaddrs in msg */
rtm_seq int /* for sender to identify action */
rtm_errno int /* why failed */
rtm_flags int /* flags, incl. kern & message, e.g. DONE */
rtm_use int /* from rtentry */
rtm_inits uint64 /* which metrics we are initializing */
rtm_rmx rt_metrics /* metrics themselves */
}
type rt_msg struct {
hdr rt_msghdr
addr1 syscall.RawSockaddrInet4
addr2 syscall.RawSockaddrInet4
}
//Init initialize ROUTE Socket
func main() {
address1 := [4]byte{12, 13, 14, 15}
address2 := [4]byte{16, 17, 18, 19}
zero1 := [8]int8{0, 0, 0, 0, 0, 0, 0, 0}
addr1 := syscall.RawSockaddrInet4{
0,
syscall.AF_INET,
0,
address1,
zero1,
}
addr2 := syscall.RawSockaddrInet4{
0,
syscall.AF_INET,
0,
address2,
zero1,
}
var dummy rt_msghdr
a := unsafe.Sizeof(dummy)
b := unsafe.Sizeof(addr1) + unsafe.Sizeof(addr1)
c := a + b
// fmt.Print(" a ", a)
// fmt.Print(" b ", b)
// fmt.Print(" c ", c)
msgheader := rt_msghdr{
uint16(c),
syscall.RTM_VERSION,
syscall.RTM_ADD,
(syscall.RTA_DST | syscall.RTA_GATEWAY),
uint32(syscall.Getpid()),
syscall.RTA_DST | syscall.RTA_GATEWAY,
1,
0,
0,
0,
0,
rt_metrics{},
}
msg := rt_msg{msgheader, addr1, addr2}
fd, err := syscall.Socket(syscall.AF_ROUTE, syscall.SOCK_RAW, syscall.AF_UNSPEC)
if err != nil {
fmt.Printf("Could not create Raw Socket")
}
defer func() {
recover()
}()
msgtosend := new(bytes.Buffer)
json.NewEncoder(msgtosend).Encode(msg)
fmt.Print(" lenght of data ", len(msgtosend.Bytes()))
d, e := syscall.Write(fd, msgtosend.Bytes())
fmt.Print(" written ", d, " error is ", e, "\n\n")
}
在这个例子中,当我运行这个程序时,它说缓冲区不可用。有人能帮帮忙吗?这里有什么问题吗。
可能是我的结构不正确,或者缺少一些基本信息。您提到“可能是您的结构不正确吗?”,是的。。
导出字段的名称,并在这些字段上使用struct标记,也用于rt\u msghdr
,使编码器知道正确的名称
type rt_msg struct {
Hdr rt_msghdr `json:"hdr"`
Addr1 syscall.RawSockaddrInet4 `json:"addr1"`
Addr2 syscall.RawSockaddrInet4 `json:"addr2"`
}
type rt_msghdr struct {
Rtm_msglen uint16 `json:"rtm_msglen"` /* to skip over non-understood messages */
// ... and so on
Rtm_rmx rt_metrics `json:"rtm_rmx"` /* metrics themselves */
}
type rt_metrics struct {
Rmx_locks uint64 `json:"rmx_locks"` /* Kernel must leave these values alone */
// ... and so on
}
上面的代码修复了发送到
fd
的空字节问题。对于没有可用的缓冲区空间
,您可以检查此链接:。编译代码可能会在其他操作系统上遇到一些问题,因为它使用syscall
。某些标志可能不受支持。这并不是那么简单:如果接收端的JSON解码器在涉及文档中对象的字段名称时区分大小写,那么您的方法也不会起作用,因为“Hdr”与接收者可能期望的“Hdr”不一样。因此,完整的答案是“导出字段的名称,但在这些字段上使用struct标记使编码器知道正确的名称”。还应注意,rt_msghdr
的字段也必须以相同的方式处理。一个指向Go处理入门级HOWTO中某些JSON的指针将是一个胜利。请改进您的答案。@kostix非常感谢您的更正,我完全忘记了要包含这些标签。