mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-08-26 08:55:06 +03:00
Merge 17146ee5bb
into 8c29f4b6dc
This commit is contained in:
commit
139c63d5ff
10 changed files with 75 additions and 111 deletions
|
@ -21,42 +21,42 @@ jobs:
|
|||
- run:
|
||||
name: Build for Linux (including Debian packages)
|
||||
command: |
|
||||
PKGARCH=amd64 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-amd64;
|
||||
PKGARCH=i386 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-i386;
|
||||
PKGARCH=mipsel sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mipsel;
|
||||
PKGARCH=mips sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mips;
|
||||
PKGARCH=armhf sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-armhf;
|
||||
PKGARCH=amd64 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-amd64;
|
||||
PKGARCH=i386 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-i386;
|
||||
PKGARCH=mipsel sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mipsel && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-mipsel;
|
||||
PKGARCH=mips sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mips && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-mips;
|
||||
PKGARCH=armhf sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-armh && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-armhf;
|
||||
mv *.deb /tmp/upload/
|
||||
|
||||
- run:
|
||||
name: Build for macOS
|
||||
command: |
|
||||
GOOS=darwin GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-amd64;
|
||||
GOOS=darwin GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-i386;
|
||||
GOOS=darwin GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-darwin-amd64;
|
||||
GOOS=darwin GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-darwin-i386;
|
||||
|
||||
- run:
|
||||
name: Build for OpenBSD
|
||||
command: |
|
||||
GOOS=openbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-amd64;
|
||||
GOOS=openbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-i386;
|
||||
GOOS=openbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-openbsd-amd64;
|
||||
GOOS=openbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-openbsd-i386;
|
||||
|
||||
- run:
|
||||
name: Build for FreeBSD
|
||||
command: |
|
||||
GOOS=freebsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-amd64;
|
||||
GOOS=freebsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-i386;
|
||||
GOOS=freebsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-freebsd-amd64;
|
||||
GOOS=freebsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-freebsd-i386;
|
||||
|
||||
- run:
|
||||
name: Build for NetBSD
|
||||
command: |
|
||||
GOOS=netbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-amd64;
|
||||
GOOS=netbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-i386;
|
||||
GOOS=netbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-netbsd-amd64;
|
||||
GOOS=netbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-netbsd-i386;
|
||||
|
||||
- run:
|
||||
name: Build for Windows
|
||||
command: |
|
||||
GOOS=windows GOARCH=amd64 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-amd64.exe;
|
||||
GOOS=windows GOARCH=386 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-i386.exe;
|
||||
GOOS=windows GOARCH=amd64 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-amd64.exe && mv yggdrasilctl.exe /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-windows-amd64.exe;
|
||||
GOOS=windows GOARCH=386 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-i386.exe && mv yggdrasilctl.exe /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-windows-i386.exe;
|
||||
|
||||
- run:
|
||||
name: Build for EdgeRouter
|
||||
|
|
|
@ -15,6 +15,11 @@ PKGNAME=$(sh contrib/semver/name.sh)
|
|||
PKGVERSION=$(sh contrib/semver/version.sh | cut -c 2-)
|
||||
PKGARCH=${PKGARCH-amd64}
|
||||
PKGFILE=$PKGNAME-$PKGVERSION-$PKGARCH.deb
|
||||
PKGREPLACES=yggdrasil
|
||||
|
||||
if [ $PKGBRANCH = "master" ]; then
|
||||
PKGREPLACES=yggdrasil-develop
|
||||
fi
|
||||
|
||||
if [ $PKGARCH = "amd64" ]; then GOARCH=amd64 GOOS=linux ./build
|
||||
elif [ $PKGARCH = "i386" ]; then GOARCH=386 GOOS=linux ./build
|
||||
|
@ -34,7 +39,7 @@ mkdir -p /tmp/$PKGNAME/usr/bin/
|
|||
mkdir -p /tmp/$PKGNAME/etc/systemd/system/
|
||||
|
||||
cat > /tmp/$PKGNAME/debian/changelog << EOF
|
||||
Please see https://github.com/Arceliar/yggdrasil-go/
|
||||
Please see https://github.com/yggdrasil-network/yggdrasil-go/
|
||||
EOF
|
||||
echo 9 > /tmp/$PKGNAME/debian/compat
|
||||
cat > /tmp/$PKGNAME/debian/control << EOF
|
||||
|
@ -43,15 +48,17 @@ Version: $PKGVERSION
|
|||
Section: contrib/net
|
||||
Priority: extra
|
||||
Architecture: $PKGARCH
|
||||
Replaces: $PKGREPLACES
|
||||
Conflicts: $PKGREPLACES
|
||||
Maintainer: Neil Alexander <neilalexander@users.noreply.github.com>
|
||||
Description: Debian yggdrasil package
|
||||
Binary yggdrasil package for Debian and Ubuntu
|
||||
EOF
|
||||
cat > /tmp/$PKGNAME/debian/copyright << EOF
|
||||
Please see https://github.com/Arceliar/yggdrasil-go/
|
||||
Please see https://github.com/yggdrasil-network/yggdrasil-go/
|
||||
EOF
|
||||
cat > /tmp/$PKGNAME/debian/docs << EOF
|
||||
Please see https://github.com/Arceliar/yggdrasil-go/
|
||||
Please see https://github.com/yggdrasil-network/yggdrasil-go/
|
||||
EOF
|
||||
cat > /tmp/$PKGNAME/debian/install << EOF
|
||||
usr/bin/yggdrasil usr/bin
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<array>
|
||||
<string>sh</string>
|
||||
<string>-c</string>
|
||||
<string>/usr/bin/yggdrasil -useconf < /etc/yggdrasil.conf</string>
|
||||
<string>/usr/local/bin/yggdrasil -useconf < /etc/yggdrasil.conf</string>
|
||||
</array>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
|
|
|
@ -7,9 +7,10 @@ type address [16]byte
|
|||
type subnet [8]byte
|
||||
|
||||
// address_prefix is the prefix used for all addresses and subnets in the network.
|
||||
// The current implementation requires this to be a multiple of 8 bits.
|
||||
// The current implementation requires this to be a muliple of 8 bits + 7 bits.
|
||||
// The 8th bit of the last byte is used to signal nodes (0) or /64 prefixes (1).
|
||||
// Nodes that configure this differently will be unable to communicate with eachother, though routing and the DHT machinery *should* still work.
|
||||
var address_prefix = [...]byte{0xfd}
|
||||
var address_prefix = [...]byte{0x02}
|
||||
|
||||
// isValid returns true if an address falls within the range used by nodes in the network.
|
||||
func (a *address) isValid() bool {
|
||||
|
@ -18,24 +19,24 @@ func (a *address) isValid() bool {
|
|||
return false
|
||||
}
|
||||
}
|
||||
return (*a)[len(address_prefix)]&0x80 == 0
|
||||
return true
|
||||
}
|
||||
|
||||
// isValid returns true if a prefix falls within the range usable by the network.
|
||||
func (s *subnet) isValid() bool {
|
||||
for idx := range address_prefix {
|
||||
l := len(address_prefix)
|
||||
for idx := range address_prefix[:l-1] {
|
||||
if (*s)[idx] != address_prefix[idx] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return (*s)[len(address_prefix)]&0x80 != 0
|
||||
return (*s)[l-1] == address_prefix[l-1]|0x01
|
||||
}
|
||||
|
||||
// address_addrForNodeID takes a *NodeID as an argument and returns an *address.
|
||||
// This address begins with the address prefix.
|
||||
// The next bit is 0 for an address, and 1 for a subnet.
|
||||
// The following 7 bits are set to the number of leading 1 bits in the NodeID.
|
||||
// The NodeID, excluding the leading 1 bits and the first leading 1 bit, is truncated to the appropriate length and makes up the remainder of the address.
|
||||
// This subnet begins with the address prefix, with the last bit set to 0 to indicate an address.
|
||||
// The following 8 bits are set to the number of leading 1 bits in the NodeID.
|
||||
// The NodeID, excluding the leading 1 bits and the first leading 0 bit, is truncated to the appropriate length and makes up the remainder of the address.
|
||||
func address_addrForNodeID(nid *NodeID) *address {
|
||||
// 128 bit address
|
||||
// Begins with prefix
|
||||
|
@ -67,16 +68,15 @@ func address_addrForNodeID(nid *NodeID) *address {
|
|||
}
|
||||
}
|
||||
copy(addr[:], address_prefix[:])
|
||||
addr[len(address_prefix)] = ones & 0x7f
|
||||
addr[len(address_prefix)] = ones
|
||||
copy(addr[len(address_prefix)+1:], temp)
|
||||
return &addr
|
||||
}
|
||||
|
||||
// address_subnetForNodeID takes a *NodeID as an argument and returns a *subnet.
|
||||
// This subnet begins with the address prefix.
|
||||
// The next bit is 0 for an address, and 1 for a subnet.
|
||||
// The following 7 bits are set to the number of leading 1 bits in the NodeID.
|
||||
// The NodeID, excluding the leading 1 bits and the first leading 1 bit, is truncated to the appropriate length and makes up the remainder of the subnet.
|
||||
// This subnet begins with the address prefix, with the last bit set to 1 to indicate a prefix.
|
||||
// The following 8 bits are set to the number of leading 1 bits in the NodeID.
|
||||
// The NodeID, excluding the leading 1 bits and the first leading 0 bit, is truncated to the appropriate length and makes up the remainder of the subnet.
|
||||
func address_subnetForNodeID(nid *NodeID) *subnet {
|
||||
// Exactly as the address version, with two exceptions:
|
||||
// 1) The first bit after the fixed prefix is a 1 instead of a 0
|
||||
|
@ -84,7 +84,7 @@ func address_subnetForNodeID(nid *NodeID) *subnet {
|
|||
addr := *address_addrForNodeID(nid)
|
||||
var snet subnet
|
||||
copy(snet[:], addr[:])
|
||||
snet[len(address_prefix)] |= 0x80
|
||||
snet[len(address_prefix)-1] |= 0x01
|
||||
return &snet
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ func (a *address) getNodeIDandMask() (*NodeID, *NodeID) {
|
|||
// This means truncated leading 1s, first leading 0, and visible part of addr
|
||||
var nid NodeID
|
||||
var mask NodeID
|
||||
ones := int(a[len(address_prefix)] & 0x7f)
|
||||
ones := int(a[len(address_prefix)])
|
||||
for idx := 0; idx < ones; idx++ {
|
||||
nid[idx/8] |= 0x80 >> byte(idx%8)
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ func (s *subnet) getNodeIDandMask() (*NodeID, *NodeID) {
|
|||
// As with the address version, but visible parts of the subnet prefix instead
|
||||
var nid NodeID
|
||||
var mask NodeID
|
||||
ones := int(s[len(address_prefix)] & 0x7f)
|
||||
ones := int(s[len(address_prefix)])
|
||||
for idx := 0; idx < ones; idx++ {
|
||||
nid[idx/8] |= 0x80 >> byte(idx%8)
|
||||
}
|
||||
|
|
|
@ -406,7 +406,7 @@ func (a *admin) startTunWithMTU(ifname string, iftapmode bool, ifmtu int) error
|
|||
_ = a.core.tun.close()
|
||||
// Then reconfigure and start it
|
||||
addr := a.core.router.addr
|
||||
straddr := fmt.Sprintf("%s/%v", net.IP(addr[:]).String(), 8*len(address_prefix))
|
||||
straddr := fmt.Sprintf("%s/%v", net.IP(addr[:]).String(), 8*len(address_prefix)-1)
|
||||
if ifname != "none" {
|
||||
err := a.core.tun.setup(ifname, iftapmode, straddr, ifmtu)
|
||||
if err != nil {
|
||||
|
|
|
@ -117,7 +117,7 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
|
|||
}
|
||||
|
||||
ip := net.IP(c.router.addr[:]).String()
|
||||
if err := c.tun.start(nc.IfName, nc.IfTAPMode, fmt.Sprintf("%s/8", ip), nc.IfMTU); err != nil {
|
||||
if err := c.tun.start(nc.IfName, nc.IfTAPMode, fmt.Sprintf("%s/%d", ip, 8*len(address_prefix)-1), nc.IfMTU); err != nil {
|
||||
c.log.Println("Failed to start TUN/TAP")
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -252,7 +252,7 @@ func (i *icmpv6) handle_ndp(in []byte) ([]byte, error) {
|
|||
case source.isValid():
|
||||
case snet.isValid():
|
||||
default:
|
||||
return nil, errors.New("Not an NDP for fd00::/8")
|
||||
return nil, errors.New("Not an NDP for 0200::/7")
|
||||
}
|
||||
|
||||
// Create our NDP message body response
|
||||
|
|
|
@ -437,41 +437,14 @@ func (sinfo *sessionInfo) doSend(bs []byte) {
|
|||
// TODO? remove the MTU updating part? That should never happen with TCP peers, and the old UDP code that caused it was removed (and if replaced, should be replaced with something that can reliably send messages with an arbitrary size).
|
||||
func (sinfo *sessionInfo) doRecv(p *wire_trafficPacket) {
|
||||
defer util_putBytes(p.Payload)
|
||||
payloadSize := uint16(len(p.Payload))
|
||||
if !sinfo.nonceIsOK(&p.Nonce) {
|
||||
return
|
||||
}
|
||||
bs, isOK := boxOpen(&sinfo.sharedSesKey, p.Payload, &p.Nonce)
|
||||
if !isOK {
|
||||
// We're going to guess that the session MTU is too large
|
||||
// Set myMTU to the largest value we think we can receive
|
||||
fixSessionMTU := func() {
|
||||
// This clamps down to 1280 almost immediately over ipv4
|
||||
// Over link-local ipv6, it seems to approach link MTU
|
||||
// So maybe it's doing the right thing?...
|
||||
//sinfo.core.log.Println("DEBUG got bad packet:", payloadSize)
|
||||
newMTU := payloadSize - boxOverhead
|
||||
if newMTU < 1280 {
|
||||
newMTU = 1280
|
||||
}
|
||||
if newMTU < sinfo.myMTU {
|
||||
sinfo.myMTU = newMTU
|
||||
sinfo.core.sessions.sendPingPong(sinfo, false)
|
||||
sinfo.mtuTime = time.Now()
|
||||
sinfo.wasMTUFixed = true
|
||||
}
|
||||
}
|
||||
go func() { sinfo.core.router.admin <- fixSessionMTU }()
|
||||
util_putBytes(bs)
|
||||
return
|
||||
}
|
||||
fixSessionMTU := func() {
|
||||
if time.Since(sinfo.mtuTime) > time.Minute {
|
||||
sinfo.myMTU = uint16(sinfo.core.tun.mtu)
|
||||
sinfo.mtuTime = time.Now()
|
||||
}
|
||||
}
|
||||
go func() { sinfo.core.router.admin <- fixSessionMTU }()
|
||||
sinfo.updateNonce(&p.Nonce)
|
||||
sinfo.time = time.Now()
|
||||
sinfo.bytesRecvd += uint64(len(bs))
|
||||
|
|
|
@ -60,29 +60,12 @@ func (iface *tcpInterface) getAddr() *net.TCPAddr {
|
|||
|
||||
// Attempts to initiate a connection to the provided address.
|
||||
func (iface *tcpInterface) connect(addr string) {
|
||||
iface.call(addr)
|
||||
iface.call(addr, nil)
|
||||
}
|
||||
|
||||
// Attempst to initiate a connection to the provided address, viathe provided socks proxy address.
|
||||
func (iface *tcpInterface) connectSOCKS(socksaddr, peeraddr string) {
|
||||
// TODO make sure this doesn't keep attempting/killing connections when one is already active.
|
||||
// I think some of the interaction between this and callWithConn needs work, so the dial isn't even attempted if there's already an outgoing call to peeraddr.
|
||||
// Or maybe only if there's already an outgoing call to peeraddr via this socksaddr?
|
||||
go func() {
|
||||
dialer, err := proxy.SOCKS5("tcp", socksaddr, nil, proxy.Direct)
|
||||
if err == nil {
|
||||
conn, err := dialer.Dial("tcp", peeraddr)
|
||||
if err == nil {
|
||||
iface.callWithConn(&wrappedConn{
|
||||
c: conn,
|
||||
raddr: &wrappedAddr{
|
||||
network: "tcp",
|
||||
addr: peeraddr,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}()
|
||||
iface.call(peeraddr, &socksaddr)
|
||||
}
|
||||
|
||||
// Initializes the struct.
|
||||
|
@ -112,33 +95,12 @@ func (iface *tcpInterface) listener() {
|
|||
}
|
||||
}
|
||||
|
||||
// Called by connectSOCKS, it's like call but with the connection already established.
|
||||
func (iface *tcpInterface) callWithConn(conn net.Conn) {
|
||||
go func() {
|
||||
raddr := conn.RemoteAddr().String()
|
||||
iface.mutex.Lock()
|
||||
_, isIn := iface.calls[raddr]
|
||||
iface.mutex.Unlock()
|
||||
if !isIn {
|
||||
iface.mutex.Lock()
|
||||
iface.calls[raddr] = struct{}{}
|
||||
iface.mutex.Unlock()
|
||||
defer func() {
|
||||
iface.mutex.Lock()
|
||||
delete(iface.calls, raddr)
|
||||
iface.mutex.Unlock()
|
||||
}()
|
||||
iface.handler(conn, false)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Checks if a connection already exists.
|
||||
// If not, it adds it to the list of active outgoing calls (to block future attempts) and dials the address.
|
||||
// If the dial is successful, it launches the handler.
|
||||
// When finished, it removes the outgoing call, so reconnection attempts can be made later.
|
||||
// This all happens in a separate goroutine that it spawns.
|
||||
func (iface *tcpInterface) call(saddr string) {
|
||||
func (iface *tcpInterface) call(saddr string, socksaddr *string) {
|
||||
go func() {
|
||||
quit := false
|
||||
iface.mutex.Lock()
|
||||
|
@ -153,13 +115,35 @@ func (iface *tcpInterface) call(saddr string) {
|
|||
}()
|
||||
}
|
||||
iface.mutex.Unlock()
|
||||
if !quit {
|
||||
conn, err := net.Dial("tcp", saddr)
|
||||
if quit {
|
||||
return
|
||||
}
|
||||
var conn net.Conn
|
||||
var err error
|
||||
if socksaddr != nil {
|
||||
var dialer proxy.Dialer
|
||||
dialer, err = proxy.SOCKS5("tcp", *socksaddr, nil, proxy.Direct)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
iface.handler(conn, false)
|
||||
conn, err = dialer.Dial("tcp", saddr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
conn = &wrappedConn{
|
||||
c: conn,
|
||||
raddr: &wrappedAddr{
|
||||
network: "tcp",
|
||||
addr: saddr,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
conn, err = net.Dial("tcp", saddr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
iface.handler(conn, false)
|
||||
}()
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ func (tun *tunDevice) setupAddress(addr string) error {
|
|||
|
||||
ar.ifra_prefixmask.sin6_len = uint8(unsafe.Sizeof(ar.ifra_prefixmask))
|
||||
b := make([]byte, 16)
|
||||
binary.LittleEndian.PutUint16(b, uint16(0xFF00))
|
||||
binary.LittleEndian.PutUint16(b, uint16(0xFE00))
|
||||
ar.ifra_prefixmask.sin6_addr[0] = uint16(binary.BigEndian.Uint16(b))
|
||||
|
||||
ar.ifra_addr.sin6_len = uint8(unsafe.Sizeof(ar.ifra_addr))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue