在Mac上的golang中使用AF_ROUTE添加路线

问题描述 投票:1回答:1

我正在尝试使用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/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")
}

在我运行此程序时,它说缓冲区不可用。任何人都可以帮助这里的问题。可能是我的结构不正确,或者可能缺少基本的东西。

go routes system-calls raw-sockets
1个回答
1
投票

您提到“结构可能不正确吗?”,是的。设置导出字段的名称,并在这些字段上使用struct标记,也用于rt_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的问题。对于no buffer space available,您可以检查以下链接:https://docs.netgate.com/pfsense/en/latest/routing/no-buffer-space-available.html。编译代码可能会在其他操作系统上遇到问题,因为它使用syscall。某些标志可能不受支持。

© www.soinside.com 2019 - 2024. All rights reserved.