Update github.com/vishvananda/netlink to v1.1.0

Latest version allows to set a VRF device as master and not only
a bridge one.

Signed-off-by: Federico Paolinelli <fpaoline@redhat.com>
This commit is contained in:
Federico Paolinelli 2020-09-04 16:33:07 +02:00
parent 8d0d8a9547
commit 362f5d626a
271 changed files with 25100 additions and 90453 deletions

6
go.mod
View File

@ -23,11 +23,11 @@ require (
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8 github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8
github.com/sirupsen/logrus v1.0.6 // indirect github.com/sirupsen/logrus v1.0.6 // indirect
github.com/stretchr/testify v1.3.0 // indirect github.com/stretchr/testify v1.3.0 // indirect
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf github.com/vishvananda/netlink v1.1.0
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941 // indirect golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941 // indirect
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 // indirect golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 // indirect
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
) )

10
go.sum
View File

@ -45,14 +45,24 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf h1:3J37+NPjNyGW/dbfXtj3yWuF9OEepIdGOXRaJGbORV8= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf h1:3J37+NPjNyGW/dbfXtj3yWuF9OEepIdGOXRaJGbORV8=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941 h1:qBTHLajHecfu+xzRI9PqVDcqx7SdHj9d4B+EzSn3tAc= golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941 h1:qBTHLajHecfu+xzRI9PqVDcqx7SdHj9d4B+EzSn3tAc=
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 h1:Y/KGZSOdz/2r0WJ9Mkmz6NJBusp0kiNx1Cn82lzJQ6w= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 h1:Y/KGZSOdz/2r0WJ9Mkmz6NJBusp0kiNx1Cn82lzJQ6w=
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a h1:i47hUS795cOydZI4AwJQCKXOr4BvxzvikwDoDtHhP2Y=
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo= gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0=

View File

@ -200,7 +200,6 @@ func (t *dispatcher) pluginMain(cmdAdd, cmdCheck, cmdDel func(_ *CmdArgs) error,
} }
return err return err
} }
if cmd != "VERSION" { if cmd != "VERSION" {
if err = validateConfig(cmdArgs.StdinData); err != nil { if err = validateConfig(cmdArgs.StdinData); err != nil {
return err return err

1
vendor/github.com/vishvananda/netlink/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
.idea/

View File

@ -2,6 +2,7 @@ language: go
go: go:
- "1.10.x" - "1.10.x"
- "1.11.x" - "1.11.x"
- "1.12.x"
before_script: before_script:
# make sure we keep path in tact when we sudo # make sure we keep path in tact when we sudo
- sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers - sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers
@ -15,3 +16,4 @@ before_script:
- sudo modprobe sch_hfsc - sudo modprobe sch_hfsc
install: install:
- go get github.com/vishvananda/netns - go get github.com/vishvananda/netns
go_import_path: github.com/vishvananda/netlink

View File

@ -15,39 +15,62 @@ import (
const IFA_FLAGS = 0x8 const IFA_FLAGS = 0x8
// AddrAdd will add an IP address to a link device. // AddrAdd will add an IP address to a link device.
//
// Equivalent to: `ip addr add $addr dev $link` // Equivalent to: `ip addr add $addr dev $link`
//
// If `addr` is an IPv4 address and the broadcast address is not given, it
// will be automatically computed based on the IP mask if /30 or larger.
func AddrAdd(link Link, addr *Addr) error { func AddrAdd(link Link, addr *Addr) error {
return pkgHandle.AddrAdd(link, addr) return pkgHandle.AddrAdd(link, addr)
} }
// AddrAdd will add an IP address to a link device. // AddrAdd will add an IP address to a link device.
//
// Equivalent to: `ip addr add $addr dev $link` // Equivalent to: `ip addr add $addr dev $link`
//
// If `addr` is an IPv4 address and the broadcast address is not given, it
// will be automatically computed based on the IP mask if /30 or larger.
func (h *Handle) AddrAdd(link Link, addr *Addr) error { func (h *Handle) AddrAdd(link Link, addr *Addr) error {
req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
return h.addrHandle(link, addr, req) return h.addrHandle(link, addr, req)
} }
// AddrReplace will replace (or, if not present, add) an IP address on a link device. // AddrReplace will replace (or, if not present, add) an IP address on a link device.
//
// Equivalent to: `ip addr replace $addr dev $link` // Equivalent to: `ip addr replace $addr dev $link`
//
// If `addr` is an IPv4 address and the broadcast address is not given, it
// will be automatically computed based on the IP mask if /30 or larger.
func AddrReplace(link Link, addr *Addr) error { func AddrReplace(link Link, addr *Addr) error {
return pkgHandle.AddrReplace(link, addr) return pkgHandle.AddrReplace(link, addr)
} }
// AddrReplace will replace (or, if not present, add) an IP address on a link device. // AddrReplace will replace (or, if not present, add) an IP address on a link device.
//
// Equivalent to: `ip addr replace $addr dev $link` // Equivalent to: `ip addr replace $addr dev $link`
//
// If `addr` is an IPv4 address and the broadcast address is not given, it
// will be automatically computed based on the IP mask if /30 or larger.
func (h *Handle) AddrReplace(link Link, addr *Addr) error { func (h *Handle) AddrReplace(link Link, addr *Addr) error {
req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.NLM_F_ACK) req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.NLM_F_ACK)
return h.addrHandle(link, addr, req) return h.addrHandle(link, addr, req)
} }
// AddrDel will delete an IP address from a link device. // AddrDel will delete an IP address from a link device.
//
// Equivalent to: `ip addr del $addr dev $link` // Equivalent to: `ip addr del $addr dev $link`
//
// If `addr` is an IPv4 address and the broadcast address is not given, it
// will be automatically computed based on the IP mask if /30 or larger.
func AddrDel(link Link, addr *Addr) error { func AddrDel(link Link, addr *Addr) error {
return pkgHandle.AddrDel(link, addr) return pkgHandle.AddrDel(link, addr)
} }
// AddrDel will delete an IP address from a link device. // AddrDel will delete an IP address from a link device.
// Equivalent to: `ip addr del $addr dev $link` // Equivalent to: `ip addr del $addr dev $link`
//
// If `addr` is an IPv4 address and the broadcast address is not given, it
// will be automatically computed based on the IP mask if /30 or larger.
func (h *Handle) AddrDel(link Link, addr *Addr) error { func (h *Handle) AddrDel(link Link, addr *Addr) error {
req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK) req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK)
return h.addrHandle(link, addr, req) return h.addrHandle(link, addr, req)
@ -108,14 +131,20 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
} }
if family == FAMILY_V4 { if family == FAMILY_V4 {
if addr.Broadcast == nil { // Automatically set the broadcast address if it is unset and the
// subnet is large enough to sensibly have one (/30 or larger).
// See: RFC 3021
if addr.Broadcast == nil && prefixlen < 31 {
calcBroadcast := make(net.IP, masklen/8) calcBroadcast := make(net.IP, masklen/8)
for i := range localAddrData { for i := range localAddrData {
calcBroadcast[i] = localAddrData[i] | ^mask[i] calcBroadcast[i] = localAddrData[i] | ^mask[i]
} }
addr.Broadcast = calcBroadcast addr.Broadcast = calcBroadcast
} }
if addr.Broadcast != nil {
req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast)) req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast))
}
if addr.Label != "" { if addr.Label != "" {
labelData := nl.NewRtAttr(unix.IFA_LABEL, nl.ZeroTerminated(addr.Label)) labelData := nl.NewRtAttr(unix.IFA_LABEL, nl.ZeroTerminated(addr.Label))
@ -270,13 +299,13 @@ type AddrUpdate struct {
// AddrSubscribe takes a chan down which notifications will be sent // AddrSubscribe takes a chan down which notifications will be sent
// when addresses change. Close the 'done' chan to stop subscription. // when addresses change. Close the 'done' chan to stop subscription.
func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error { func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false) return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0)
} }
// AddrSubscribeAt works like AddrSubscribe plus it allows the caller // AddrSubscribeAt works like AddrSubscribe plus it allows the caller
// to choose the network namespace in which to subscribe (ns). // to choose the network namespace in which to subscribe (ns).
func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error { func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
return addrSubscribeAt(ns, netns.None(), ch, done, nil, false) return addrSubscribeAt(ns, netns.None(), ch, done, nil, false, 0)
} }
// AddrSubscribeOptions contains a set of options to use with // AddrSubscribeOptions contains a set of options to use with
@ -285,6 +314,7 @@ type AddrSubscribeOptions struct {
Namespace *netns.NsHandle Namespace *netns.NsHandle
ErrorCallback func(error) ErrorCallback func(error)
ListExisting bool ListExisting bool
ReceiveBufferSize int
} }
// AddrSubscribeWithOptions work like AddrSubscribe but enable to // AddrSubscribeWithOptions work like AddrSubscribe but enable to
@ -295,10 +325,10 @@ func AddrSubscribeWithOptions(ch chan<- AddrUpdate, done <-chan struct{}, option
none := netns.None() none := netns.None()
options.Namespace = &none options.Namespace = &none
} }
return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting) return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, options.ReceiveBufferSize)
} }
func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error { func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool, rcvbuf int) error {
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR) s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR)
if err != nil { if err != nil {
return err return err
@ -309,6 +339,12 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
s.Close() s.Close()
}() }()
} }
if rcvbuf != 0 {
err = pkgHandle.SetSocketReceiveBufferSize(rcvbuf, false)
if err != nil {
return err
}
}
if listExisting { if listExisting {
req := pkgHandle.newNetlinkRequest(unix.RTM_GETADDR, req := pkgHandle.newNetlinkRequest(unix.RTM_GETADDR,
unix.NLM_F_DUMP) unix.NLM_F_DUMP)
@ -321,13 +357,19 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
go func() { go func() {
defer close(ch) defer close(ch)
for { for {
msgs, err := s.Receive() msgs, from, err := s.Receive()
if err != nil { if err != nil {
if cberr != nil { if cberr != nil {
cberr(err) cberr(err)
} }
return return
} }
if from.Pid != nl.PidKernel {
if cberr != nil {
cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel))
}
continue
}
for _, m := range msgs { for _, m := range msgs {
if m.Header.Type == unix.NLMSG_DONE { if m.Header.Type == unix.NLMSG_DONE {
continue continue
@ -339,16 +381,17 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
continue continue
} }
if cberr != nil { if cberr != nil {
cberr(syscall.Errno(-error)) cberr(fmt.Errorf("error message: %v",
syscall.Errno(-error)))
} }
return continue
} }
msgType := m.Header.Type msgType := m.Header.Type
if msgType != unix.RTM_NEWADDR && msgType != unix.RTM_DELADDR { if msgType != unix.RTM_NEWADDR && msgType != unix.RTM_DELADDR {
if cberr != nil { if cberr != nil {
cberr(fmt.Errorf("bad message type: %d", msgType)) cberr(fmt.Errorf("bad message type: %d", msgType))
} }
return continue
} }
addr, _, ifindex, err := parseAddr(m.Data) addr, _, ifindex, err := parseAddr(m.Data)
@ -356,7 +399,7 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
if cberr != nil { if cberr != nil {
cberr(fmt.Errorf("could not parse address: %v", err)) cberr(fmt.Errorf("could not parse address: %v", err))
} }
return continue
} }
ch <- AddrUpdate{LinkAddress: *addr.IPNet, ch <- AddrUpdate{LinkAddress: *addr.IPNet,

View File

@ -108,8 +108,5 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize()) br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
req.AddData(br) req.AddData(br)
_, err := req.Execute(unix.NETLINK_ROUTE, 0) _, err := req.Execute(unix.NETLINK_ROUTE, 0)
if err != nil {
return err return err
} }
return nil
}

View File

@ -41,7 +41,7 @@ type GnetStatsQueue struct {
Overlimits uint32 // number of enqueues over the limit Overlimits uint32 // number of enqueues over the limit
} }
// ClassStatistics representaion based on generic networking statisticsfor netlink. // ClassStatistics representation based on generic networking statistics for netlink.
// See Documentation/networking/gen_stats.txt in Linux source code for more details. // See Documentation/networking/gen_stats.txt in Linux source code for more details.
type ClassStatistics struct { type ClassStatistics struct {
Basic *GnetStatsBasic Basic *GnetStatsBasic
@ -127,7 +127,7 @@ func (class *GenericClass) Attrs() *ClassAttrs {
return &class.ClassAttrs return &class.ClassAttrs
} }
// Type retrun the class type // Type return the class type
func (class *GenericClass) Type() string { func (class *GenericClass) Type() string {
return class.ClassType return class.ClassType
} }
@ -178,7 +178,7 @@ func (hfsc *HfscClass) SetUL(m1 uint32, d uint32, m2 uint32) {
hfsc.Usc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} hfsc.Usc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
} }
// SetLS implemtens the LS from the tc CLI // SetLS implements the LS from the tc CLI
func (hfsc *HfscClass) SetLS(m1 uint32, d uint32, m2 uint32) { func (hfsc *HfscClass) SetLS(m1 uint32, d uint32, m2 uint32) {
hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
} }

View File

@ -22,11 +22,7 @@ const (
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink.h -> #define NFNL_SUBSYS_CTNETLINK_EXP 2 // https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink.h -> #define NFNL_SUBSYS_CTNETLINK_EXP 2
ConntrackExpectTable = 2 ConntrackExpectTable = 2
) )
const (
// For Parsing Mark
TCP_PROTO = 6
UDP_PROTO = 17
)
const ( const (
// backward compatibility with golang 1.6 which does not have io.SeekCurrent // backward compatibility with golang 1.6 which does not have io.SeekCurrent
seekCurrent = 1 seekCurrent = 1
@ -223,6 +219,10 @@ func parseBERaw16(r *bytes.Reader, v *uint16) {
binary.Read(r, binary.BigEndian, v) binary.Read(r, binary.BigEndian, v)
} }
func parseBERaw32(r *bytes.Reader, v *uint32) {
binary.Read(r, binary.BigEndian, v)
}
func parseBERaw64(r *bytes.Reader, v *uint64) { func parseBERaw64(r *bytes.Reader, v *uint64) {
binary.Read(r, binary.BigEndian, v) binary.Read(r, binary.BigEndian, v)
} }
@ -241,9 +241,13 @@ func parseByteAndPacketCounters(r *bytes.Reader) (bytes, packets uint64) {
return return
} }
func parseConnectionMark(r *bytes.Reader) (mark uint32) {
parseBERaw32(r, &mark)
return
}
func parseRawData(data []byte) *ConntrackFlow { func parseRawData(data []byte) *ConntrackFlow {
s := &ConntrackFlow{} s := &ConntrackFlow{}
var proto uint8
// First there is the Nfgenmsg header // First there is the Nfgenmsg header
// consume only the family field // consume only the family field
reader := bytes.NewReader(data) reader := bytes.NewReader(data)
@ -263,7 +267,7 @@ func parseRawData(data []byte) *ConntrackFlow {
switch t { switch t {
case nl.CTA_TUPLE_ORIG: case nl.CTA_TUPLE_ORIG:
if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP { if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
proto = parseIpTuple(reader, &s.Forward) parseIpTuple(reader, &s.Forward)
} }
case nl.CTA_TUPLE_REPLY: case nl.CTA_TUPLE_REPLY:
if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP { if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
@ -277,20 +281,12 @@ func parseRawData(data []byte) *ConntrackFlow {
case nl.CTA_COUNTERS_REPLY: case nl.CTA_COUNTERS_REPLY:
s.Reverse.Bytes, s.Reverse.Packets = parseByteAndPacketCounters(reader) s.Reverse.Bytes, s.Reverse.Packets = parseByteAndPacketCounters(reader)
} }
} else {
switch t {
case nl.CTA_MARK:
s.Mark = parseConnectionMark(reader)
} }
} }
if proto == TCP_PROTO {
reader.Seek(64, seekCurrent)
_, t, _, v := parseNfAttrTLV(reader)
if t == nl.CTA_MARK {
s.Mark = uint32(v[3])
}
} else if proto == UDP_PROTO {
reader.Seek(16, seekCurrent)
_, t, _, v := parseNfAttrTLV(reader)
if t == nl.CTA_MARK {
s.Mark = uint32(v[3])
}
} }
return s return s
} }

272
vendor/github.com/vishvananda/netlink/devlink_linux.go generated vendored Normal file
View File

@ -0,0 +1,272 @@
package netlink
import (
"syscall"
"fmt"
"github.com/vishvananda/netlink/nl"
"golang.org/x/sys/unix"
)
// DevlinkDevEswitchAttr represents device's eswitch attributes
type DevlinkDevEswitchAttr struct {
Mode string
InlineMode string
EncapMode string
}
// DevlinkDevAttrs represents device attributes
type DevlinkDevAttrs struct {
Eswitch DevlinkDevEswitchAttr
}
// DevlinkDevice represents device and its attributes
type DevlinkDevice struct {
BusName string
DeviceName string
Attrs DevlinkDevAttrs
}
func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) {
devices := make([]*DevlinkDevice, 0, len(msgs))
for _, m := range msgs {
attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
if err != nil {
return nil, err
}
dev := &DevlinkDevice{}
if err = dev.parseAttributes(attrs); err != nil {
return nil, err
}
devices = append(devices, dev)
}
return devices, nil
}
func eswitchStringToMode(modeName string) (uint16, error) {
if modeName == "legacy" {
return nl.DEVLINK_ESWITCH_MODE_LEGACY, nil
} else if modeName == "switchdev" {
return nl.DEVLINK_ESWITCH_MODE_SWITCHDEV, nil
} else {
return 0xffff, fmt.Errorf("invalid switchdev mode")
}
}
func parseEswitchMode(mode uint16) string {
var eswitchMode = map[uint16]string{
nl.DEVLINK_ESWITCH_MODE_LEGACY: "legacy",
nl.DEVLINK_ESWITCH_MODE_SWITCHDEV: "switchdev",
}
if eswitchMode[mode] == "" {
return "unknown"
} else {
return eswitchMode[mode]
}
}
func parseEswitchInlineMode(inlinemode uint8) string {
var eswitchInlineMode = map[uint8]string{
nl.DEVLINK_ESWITCH_INLINE_MODE_NONE: "none",
nl.DEVLINK_ESWITCH_INLINE_MODE_LINK: "link",
nl.DEVLINK_ESWITCH_INLINE_MODE_NETWORK: "network",
nl.DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT: "transport",
}
if eswitchInlineMode[inlinemode] == "" {
return "unknown"
} else {
return eswitchInlineMode[inlinemode]
}
}
func parseEswitchEncapMode(encapmode uint8) string {
var eswitchEncapMode = map[uint8]string{
nl.DEVLINK_ESWITCH_ENCAP_MODE_NONE: "disable",
nl.DEVLINK_ESWITCH_ENCAP_MODE_BASIC: "enable",
}
if eswitchEncapMode[encapmode] == "" {
return "unknown"
} else {
return eswitchEncapMode[encapmode]
}
}
func (d *DevlinkDevice) parseAttributes(attrs []syscall.NetlinkRouteAttr) error {
for _, a := range attrs {
switch a.Attr.Type {
case nl.DEVLINK_ATTR_BUS_NAME:
d.BusName = string(a.Value)
case nl.DEVLINK_ATTR_DEV_NAME:
d.DeviceName = string(a.Value)
case nl.DEVLINK_ATTR_ESWITCH_MODE:
d.Attrs.Eswitch.Mode = parseEswitchMode(native.Uint16(a.Value))
case nl.DEVLINK_ATTR_ESWITCH_INLINE_MODE:
d.Attrs.Eswitch.InlineMode = parseEswitchInlineMode(uint8(a.Value[0]))
case nl.DEVLINK_ATTR_ESWITCH_ENCAP_MODE:
d.Attrs.Eswitch.EncapMode = parseEswitchEncapMode(uint8(a.Value[0]))
}
}
return nil
}
func (dev *DevlinkDevice) parseEswitchAttrs(msgs [][]byte) {
m := msgs[0]
attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
if err != nil {
return
}
dev.parseAttributes(attrs)
}
func (h *Handle) getEswitchAttrs(family *GenlFamily, dev *DevlinkDevice) {
msg := &nl.Genlmsg{
Command: nl.DEVLINK_CMD_ESWITCH_GET,
Version: nl.GENL_DEVLINK_VERSION,
}
req := h.newNetlinkRequest(int(family.ID), unix.NLM_F_REQUEST|unix.NLM_F_ACK)
req.AddData(msg)
b := make([]byte, len(dev.BusName))
copy(b, dev.BusName)
data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b)
req.AddData(data)
b = make([]byte, len(dev.DeviceName))
copy(b, dev.DeviceName)
data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b)
req.AddData(data)
msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
if err != nil {
return
}
dev.parseEswitchAttrs(msgs)
}
// DevLinkGetDeviceList provides a pointer to devlink devices and nil error,
// otherwise returns an error code.
func (h *Handle) DevLinkGetDeviceList() ([]*DevlinkDevice, error) {
f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME)
if err != nil {
return nil, err
}
msg := &nl.Genlmsg{
Command: nl.DEVLINK_CMD_GET,
Version: nl.GENL_DEVLINK_VERSION,
}
req := h.newNetlinkRequest(int(f.ID),
unix.NLM_F_REQUEST|unix.NLM_F_ACK|unix.NLM_F_DUMP)
req.AddData(msg)
msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
if err != nil {
return nil, err
}
devices, err := parseDevLinkDeviceList(msgs)
if err != nil {
return nil, err
}
for _, d := range devices {
h.getEswitchAttrs(f, d)
}
return devices, nil
}
// DevLinkGetDeviceList provides a pointer to devlink devices and nil error,
// otherwise returns an error code.
func DevLinkGetDeviceList() ([]*DevlinkDevice, error) {
return pkgHandle.DevLinkGetDeviceList()
}
func parseDevlinkDevice(msgs [][]byte) (*DevlinkDevice, error) {
m := msgs[0]
attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
if err != nil {
return nil, err
}
dev := &DevlinkDevice{}
if err = dev.parseAttributes(attrs); err != nil {
return nil, err
}
return dev, nil
}
func (h *Handle) createCmdReq(cmd uint8, bus string, device string) (*GenlFamily, *nl.NetlinkRequest, error) {
f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME)
if err != nil {
return nil, nil, err
}
msg := &nl.Genlmsg{
Command: cmd,
Version: nl.GENL_DEVLINK_VERSION,
}
req := h.newNetlinkRequest(int(f.ID),
unix.NLM_F_REQUEST|unix.NLM_F_ACK)
req.AddData(msg)
b := make([]byte, len(bus)+1)
copy(b, bus)
data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b)
req.AddData(data)
b = make([]byte, len(device)+1)
copy(b, device)
data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b)
req.AddData(data)
return f, req, nil
}
// DevlinkGetDeviceByName provides a pointer to devlink device and nil error,
// otherwise returns an error code.
func (h *Handle) DevLinkGetDeviceByName(Bus string, Device string) (*DevlinkDevice, error) {
f, req, err := h.createCmdReq(nl.DEVLINK_CMD_GET, Bus, Device)
if err != nil {
return nil, err
}
respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
if err != nil {
return nil, err
}
dev, err := parseDevlinkDevice(respmsg)
if err == nil {
h.getEswitchAttrs(f, dev)
}
return dev, err
}
// DevlinkGetDeviceByName provides a pointer to devlink device and nil error,
// otherwise returns an error code.
func DevLinkGetDeviceByName(Bus string, Device string) (*DevlinkDevice, error) {
return pkgHandle.DevLinkGetDeviceByName(Bus, Device)
}
// DevLinkSetEswitchMode sets eswitch mode if able to set successfully or
// returns an error code.
// Equivalent to: `devlink dev eswitch set $dev mode switchdev`
// Equivalent to: `devlink dev eswitch set $dev mode legacy`
func (h *Handle) DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error {
mode, err := eswitchStringToMode(NewMode)
if err != nil {
return err
}
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_ESWITCH_SET, Dev.BusName, Dev.DeviceName)
if err != nil {
return err
}
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_ESWITCH_MODE, nl.Uint16Attr(mode)))
_, err = req.Execute(unix.NETLINK_GENERIC, 0)
return err
}
// DevLinkSetEswitchMode sets eswitch mode if able to set successfully or
// returns an error code.
// Equivalent to: `devlink dev eswitch set $dev mode switchdev`
// Equivalent to: `devlink dev eswitch set $dev mode legacy`
func DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error {
return pkgHandle.DevLinkSetEswitchMode(Dev, NewMode)
}

View File

@ -2,6 +2,7 @@ package netlink
import ( import (
"fmt" "fmt"
"net"
) )
type Filter interface { type Filter interface {
@ -135,6 +136,27 @@ func (action *BpfAction) Attrs() *ActionAttrs {
return &action.ActionAttrs return &action.ActionAttrs
} }
type ConnmarkAction struct {
ActionAttrs
Zone uint16
}
func (action *ConnmarkAction) Type() string {
return "connmark"
}
func (action *ConnmarkAction) Attrs() *ActionAttrs {
return &action.ActionAttrs
}
func NewConnmarkAction() *ConnmarkAction {
return &ConnmarkAction{
ActionAttrs: ActionAttrs{
Action: TC_ACT_PIPE,
},
}
}
type MirredAct uint8 type MirredAct uint8
func (a MirredAct) String() string { func (a MirredAct) String() string {
@ -182,49 +204,59 @@ func NewMirredAction(redirIndex int) *MirredAction {
} }
} }
// Sel of the U32 filters that contains multiple TcU32Key. This is the copy type TunnelKeyAct int8
// and the frontend representation of nl.TcU32Sel. It is serialized into canonical
// nl.TcU32Sel with the appropriate endianness. const (
type TcU32Sel struct { TCA_TUNNEL_KEY_SET TunnelKeyAct = 1 // set tunnel key
Flags uint8 TCA_TUNNEL_KEY_UNSET TunnelKeyAct = 2 // unset tunnel key
Offshift uint8 )
Nkeys uint8
Pad uint8 type TunnelKeyAction struct {
Offmask uint16 ActionAttrs
Off uint16 Action TunnelKeyAct
Offoff int16 SrcAddr net.IP
Hoff int16 DstAddr net.IP
Hmask uint32 KeyID uint32
Keys []TcU32Key
} }
// TcU32Key contained of Sel in the U32 filters. This is the copy and the frontend func (action *TunnelKeyAction) Type() string {
// representation of nl.TcU32Key. It is serialized into chanonical nl.TcU32Sel return "tunnel_key"
// with the appropriate endianness.
type TcU32Key struct {
Mask uint32
Val uint32
Off int32
OffMask int32
} }
// U32 filters on many packet related properties func (action *TunnelKeyAction) Attrs() *ActionAttrs {
type U32 struct { return &action.ActionAttrs
FilterAttrs
ClassId uint32
Divisor uint32 // Divisor MUST be power of 2.
Hash uint32
RedirIndex int
Sel *TcU32Sel
Actions []Action
} }
func (filter *U32) Attrs() *FilterAttrs { func NewTunnelKeyAction() *TunnelKeyAction {
return &filter.FilterAttrs return &TunnelKeyAction{
ActionAttrs: ActionAttrs{
Action: TC_ACT_PIPE,
},
}
} }
func (filter *U32) Type() string { type SkbEditAction struct {
return "u32" ActionAttrs
QueueMapping *uint16
PType *uint16
Priority *uint32
Mark *uint32
}
func (action *SkbEditAction) Type() string {
return "skbedit"
}
func (action *SkbEditAction) Attrs() *ActionAttrs {
return &action.ActionAttrs
}
func NewSkbEditAction() *SkbEditAction {
return &SkbEditAction{
ActionAttrs: ActionAttrs{
Action: TC_ACT_PIPE,
},
}
} }
// MatchAll filters match all packets // MatchAll filters match all packets
@ -264,6 +296,8 @@ type BpfFilter struct {
Fd int Fd int
Name string Name string
DirectAction bool DirectAction bool
Id int
Tag string
} }
func (filter *BpfFilter) Type() string { func (filter *BpfFilter) Type() string {

View File

@ -3,10 +3,11 @@ package netlink
import ( import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/hex"
"errors" "errors"
"fmt" "fmt"
"net"
"syscall" "syscall"
"unsafe"
"github.com/vishvananda/netlink/nl" "github.com/vishvananda/netlink/nl"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
@ -20,6 +21,35 @@ const (
TC_U32_EAT = nl.TC_U32_EAT TC_U32_EAT = nl.TC_U32_EAT
) )
// Sel of the U32 filters that contains multiple TcU32Key. This is the type
// alias and the frontend representation of nl.TcU32Sel. It is serialized into
// canonical nl.TcU32Sel with the appropriate endianness.
type TcU32Sel = nl.TcU32Sel
// TcU32Key contained of Sel in the U32 filters. This is the type alias and the
// frontend representation of nl.TcU32Key. It is serialized into chanonical
// nl.TcU32Sel with the appropriate endianness.
type TcU32Key = nl.TcU32Key
// U32 filters on many packet related properties
type U32 struct {
FilterAttrs
ClassId uint32
Divisor uint32 // Divisor MUST be power of 2.
Hash uint32
RedirIndex int
Sel *TcU32Sel
Actions []Action
}
func (filter *U32) Attrs() *FilterAttrs {
return &filter.FilterAttrs
}
func (filter *U32) Type() string {
return "u32"
}
// Fw filter filters on firewall marks // Fw filter filters on firewall marks
// NOTE: this is in filter_linux because it refers to nl.TcPolice which // NOTE: this is in filter_linux because it refers to nl.TcPolice which
// is defined in nl/tc_linux.go // is defined in nl/tc_linux.go
@ -123,8 +153,24 @@ func FilterAdd(filter Filter) error {
// FilterAdd will add a filter to the system. // FilterAdd will add a filter to the system.
// Equivalent to: `tc filter add $filter` // Equivalent to: `tc filter add $filter`
func (h *Handle) FilterAdd(filter Filter) error { func (h *Handle) FilterAdd(filter Filter) error {
return h.filterModify(filter, unix.NLM_F_CREATE|unix.NLM_F_EXCL)
}
// FilterReplace will replace a filter.
// Equivalent to: `tc filter replace $filter`
func FilterReplace(filter Filter) error {
return pkgHandle.FilterReplace(filter)
}
// FilterReplace will replace a filter.
// Equivalent to: `tc filter replace $filter`
func (h *Handle) FilterReplace(filter Filter) error {
return h.filterModify(filter, unix.NLM_F_CREATE)
}
func (h *Handle) filterModify(filter Filter, flags int) error {
native = nl.NativeEndian() native = nl.NativeEndian()
req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK)
base := filter.Attrs() base := filter.Attrs()
msg := &nl.TcMsg{ msg := &nl.TcMsg{
Family: nl.FAMILY_ALL, Family: nl.FAMILY_ALL,
@ -140,8 +186,7 @@ func (h *Handle) FilterAdd(filter Filter) error {
switch filter := filter.(type) { switch filter := filter.(type) {
case *U32: case *U32:
// Convert TcU32Sel into nl.TcU32Sel as it is without copy. sel := filter.Sel
sel := (*nl.TcU32Sel)(unsafe.Pointer(filter.Sel))
if sel == nil { if sel == nil {
// match all // match all
sel = &nl.TcU32Sel{ sel = &nl.TcU32Sel{
@ -385,6 +430,63 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
} }
toTcGen(action.Attrs(), &mirred.TcGen) toTcGen(action.Attrs(), &mirred.TcGen)
aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize()) aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize())
case *TunnelKeyAction:
table := attr.AddRtAttr(tabIndex, nil)
tabIndex++
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("tunnel_key"))
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
tun := nl.TcTunnelKey{
Action: int32(action.Action),
}
toTcGen(action.Attrs(), &tun.TcGen)
aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_PARMS, tun.Serialize())
if action.Action == TCA_TUNNEL_KEY_SET {
aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_KEY_ID, htonl(action.KeyID))
if v4 := action.SrcAddr.To4(); v4 != nil {
aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC, v4[:])
} else if v6 := action.SrcAddr.To16(); v6 != nil {
aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC, v6[:])
} else {
return fmt.Errorf("invalid src addr %s for tunnel_key action", action.SrcAddr)
}
if v4 := action.DstAddr.To4(); v4 != nil {
aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_DST, v4[:])
} else if v6 := action.DstAddr.To16(); v6 != nil {
aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_DST, v6[:])
} else {
return fmt.Errorf("invalid dst addr %s for tunnel_key action", action.DstAddr)
}
}
case *SkbEditAction:
table := attr.AddRtAttr(tabIndex, nil)
tabIndex++
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("skbedit"))
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
skbedit := nl.TcSkbEdit{}
toTcGen(action.Attrs(), &skbedit.TcGen)
aopts.AddRtAttr(nl.TCA_SKBEDIT_PARMS, skbedit.Serialize())
if action.QueueMapping != nil {
aopts.AddRtAttr(nl.TCA_SKBEDIT_QUEUE_MAPPING, nl.Uint16Attr(*action.QueueMapping))
}
if action.Priority != nil {
aopts.AddRtAttr(nl.TCA_SKBEDIT_PRIORITY, nl.Uint32Attr(*action.Priority))
}
if action.PType != nil {
aopts.AddRtAttr(nl.TCA_SKBEDIT_PTYPE, nl.Uint16Attr(*action.PType))
}
if action.Mark != nil {
aopts.AddRtAttr(nl.TCA_SKBEDIT_MARK, nl.Uint32Attr(*action.Mark))
}
case *ConnmarkAction:
table := attr.AddRtAttr(tabIndex, nil)
tabIndex++
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("connmark"))
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
connmark := nl.TcConnmark{
Zone: action.Zone,
}
toTcGen(action.Attrs(), &connmark.TcGen)
aopts.AddRtAttr(nl.TCA_CONNMARK_PARMS, connmark.Serialize())
case *BpfAction: case *BpfAction:
table := attr.AddRtAttr(tabIndex, nil) table := attr.AddRtAttr(tabIndex, nil)
tabIndex++ tabIndex++
@ -428,8 +530,14 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
action = &MirredAction{} action = &MirredAction{}
case "bpf": case "bpf":
action = &BpfAction{} action = &BpfAction{}
case "connmark":
action = &ConnmarkAction{}
case "gact": case "gact":
action = &GenericAction{} action = &GenericAction{}
case "tunnel_key":
action = &TunnelKeyAction{}
case "skbedit":
action = &SkbEditAction{}
default: default:
break nextattr break nextattr
} }
@ -444,11 +552,46 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
switch adatum.Attr.Type { switch adatum.Attr.Type {
case nl.TCA_MIRRED_PARMS: case nl.TCA_MIRRED_PARMS:
mirred := *nl.DeserializeTcMirred(adatum.Value) mirred := *nl.DeserializeTcMirred(adatum.Value)
toAttrs(&mirred.TcGen, action.Attrs())
action.(*MirredAction).ActionAttrs = ActionAttrs{} action.(*MirredAction).ActionAttrs = ActionAttrs{}
toAttrs(&mirred.TcGen, action.Attrs())
action.(*MirredAction).Ifindex = int(mirred.Ifindex) action.(*MirredAction).Ifindex = int(mirred.Ifindex)
action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction) action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction)
} }
case "tunnel_key":
switch adatum.Attr.Type {
case nl.TCA_TUNNEL_KEY_PARMS:
tun := *nl.DeserializeTunnelKey(adatum.Value)
action.(*TunnelKeyAction).ActionAttrs = ActionAttrs{}
toAttrs(&tun.TcGen, action.Attrs())
action.(*TunnelKeyAction).Action = TunnelKeyAct(tun.Action)
case nl.TCA_TUNNEL_KEY_ENC_KEY_ID:
action.(*TunnelKeyAction).KeyID = networkOrder.Uint32(adatum.Value[0:4])
case nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC:
case nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC:
action.(*TunnelKeyAction).SrcAddr = net.IP(adatum.Value[:])
case nl.TCA_TUNNEL_KEY_ENC_IPV6_DST:
case nl.TCA_TUNNEL_KEY_ENC_IPV4_DST:
action.(*TunnelKeyAction).DstAddr = net.IP(adatum.Value[:])
}
case "skbedit":
switch adatum.Attr.Type {
case nl.TCA_SKBEDIT_PARMS:
skbedit := *nl.DeserializeSkbEdit(adatum.Value)
action.(*SkbEditAction).ActionAttrs = ActionAttrs{}
toAttrs(&skbedit.TcGen, action.Attrs())
case nl.TCA_SKBEDIT_MARK:
mark := native.Uint32(adatum.Value[0:4])
action.(*SkbEditAction).Mark = &mark
case nl.TCA_SKBEDIT_PRIORITY:
priority := native.Uint32(adatum.Value[0:4])
action.(*SkbEditAction).Priority = &priority
case nl.TCA_SKBEDIT_PTYPE:
ptype := native.Uint16(adatum.Value[0:2])
action.(*SkbEditAction).PType = &ptype
case nl.TCA_SKBEDIT_QUEUE_MAPPING:
mapping := native.Uint16(adatum.Value[0:2])
action.(*SkbEditAction).QueueMapping = &mapping
}
case "bpf": case "bpf":
switch adatum.Attr.Type { switch adatum.Attr.Type {
case nl.TCA_ACT_BPF_PARMS: case nl.TCA_ACT_BPF_PARMS:
@ -459,6 +602,14 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
case nl.TCA_ACT_BPF_NAME: case nl.TCA_ACT_BPF_NAME:
action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1]) action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1])
} }
case "connmark":
switch adatum.Attr.Type {
case nl.TCA_CONNMARK_PARMS:
connmark := *nl.DeserializeTcConnmark(adatum.Value)
action.(*ConnmarkAction).ActionAttrs = ActionAttrs{}
toAttrs(&connmark.TcGen, action.Attrs())
action.(*ConnmarkAction).Zone = connmark.Zone
}
case "gact": case "gact":
switch adatum.Attr.Type { switch adatum.Attr.Type {
case nl.TCA_GACT_PARMS: case nl.TCA_GACT_PARMS:
@ -483,7 +634,7 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
case nl.TCA_U32_SEL: case nl.TCA_U32_SEL:
detailed = true detailed = true
sel := nl.DeserializeTcU32Sel(datum.Value) sel := nl.DeserializeTcU32Sel(datum.Value)
u32.Sel = (*TcU32Sel)(unsafe.Pointer(sel)) u32.Sel = sel
if native != networkOrder { if native != networkOrder {
// Handle the endianness of attributes // Handle the endianness of attributes
u32.Sel.Offmask = native.Uint16(htons(sel.Offmask)) u32.Sel.Offmask = native.Uint16(htons(sel.Offmask))
@ -564,6 +715,10 @@ func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 { if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 {
bpf.DirectAction = true bpf.DirectAction = true
} }
case nl.TCA_BPF_ID:
bpf.Id = int(native.Uint32(datum.Value[0:4]))
case nl.TCA_BPF_TAG:
bpf.Tag = hex.EncodeToString(datum.Value[:len(datum.Value)-1])
} }
} }
return detailed, nil return detailed, nil

View File

@ -90,13 +90,9 @@ func (h *Handle) FouAdd(f Fou) error {
req.AddRawData(raw) req.AddRawData(raw)
_, err = req.Execute(unix.NETLINK_GENERIC, 0) _, err = req.Execute(unix.NETLINK_GENERIC, 0)
if err != nil {
return err return err
} }
return nil
}
func FouDel(f Fou) error { func FouDel(f Fou) error {
return pkgHandle.FouDel(f) return pkgHandle.FouDel(f)
} }

View File

@ -157,6 +157,9 @@ func (h *Handle) GenlFamilyGet(name string) (*GenlFamily, error) {
return nil, err return nil, err
} }
families, err := parseFamilies(msgs) families, err := parseFamilies(msgs)
if err != nil {
return nil, err
}
if len(families) != 1 { if len(families) != 1 {
return nil, fmt.Errorf("invalid response for GENL_CTRL_CMD_GETFAMILY") return nil, fmt.Errorf("invalid response for GENL_CTRL_CMD_GETFAMILY")
} }

8
vendor/github.com/vishvananda/netlink/go.mod generated vendored Normal file
View File

@ -0,0 +1,8 @@
module github.com/vishvananda/netlink
go 1.12
require (
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444
)

4
vendor/github.com/vishvananda/netlink/go.sum generated vendored Normal file
View File

@ -0,0 +1,4 @@
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444 h1:/d2cWp6PSamH4jDPFLyO150psQdqvtoNX8Zjg3AQ31g=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -91,7 +91,7 @@ func (h *Handle) GetSocketReceiveBufferSize() ([]int, error) {
return results, nil return results, nil
} }
// NewHandle returns a netlink handle on the network namespace // NewHandleAt returns a netlink handle on the network namespace
// specified by ns. If ns=netns.None(), current network namespace // specified by ns. If ns=netns.None(), current network namespace
// will be assumed // will be assumed
func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) { func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {

View File

@ -73,10 +73,18 @@ func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
return ErrNotImplemented return ErrNotImplemented
} }
func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error { func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
return ErrNotImplemented return ErrNotImplemented
} }
func (h *Handle) LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetMaster(link Link, master *Bridge) error { func (h *Handle) LinkSetMaster(link Link, master *Bridge) error {
return ErrNotImplemented return ErrNotImplemented
} }
@ -149,6 +157,10 @@ func (h *Handle) LinkSetTxQLen(link Link, qlen int) error {
return ErrNotImplemented return ErrNotImplemented
} }
func (h *Handle) LinkSetGroup(link Link, group int) error {
return ErrNotImplemented
}
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error { func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
return ErrNotImplemented return ErrNotImplemented
} }

View File

@ -56,18 +56,10 @@ type ethtoolSset struct {
data [1]uint32 data [1]uint32
} }
// ethtoolGstrings is string set for data tagging
type ethtoolGstrings struct {
cmd uint32
stringSet uint32
length uint32
data [32]byte
}
type ethtoolStats struct { type ethtoolStats struct {
cmd uint32 cmd uint32
nStats uint32 nStats uint32
data [1]uint64 // Followed by nStats * []uint64.
} }
// newIocltSlaveReq returns filled IfreqSlave with proper interface names // newIocltSlaveReq returns filled IfreqSlave with proper interface names

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"net" "net"
"os" "os"
"strconv"
) )
// Link represents a link device from netlink. Shared link attributes // Link represents a link device from netlink. Shared link attributes
@ -41,7 +42,16 @@ type LinkAttrs struct {
NetNsID int NetNsID int
NumTxQueues int NumTxQueues int
NumRxQueues int NumRxQueues int
GSOMaxSize uint32
GSOMaxSegs uint32
Vfs []VfInfo // virtual functions available on link Vfs []VfInfo // virtual functions available on link
Group uint32
Slave LinkSlave
}
// LinkSlave represents a slave device.
type LinkSlave interface {
SlaveType() string
} }
// VfInfo represents configuration of virtual function // VfInfo represents configuration of virtual function
@ -50,9 +60,11 @@ type VfInfo struct {
Mac net.HardwareAddr Mac net.HardwareAddr
Vlan int Vlan int
Qos int Qos int
TxRate int TxRate int // IFLA_VF_TX_RATE Max TxRate
Spoofchk bool Spoofchk bool
LinkState uint32 LinkState uint32
MaxTxRate uint32 // IFLA_VF_RATE Max TxRate
MinTxRate uint32 // IFLA_VF_RATE Min TxRate
} }
// LinkOperState represents the values of the IFLA_OPERSTATE link // LinkOperState represents the values of the IFLA_OPERSTATE link
@ -250,6 +262,7 @@ func (bridge *Bridge) Type() string {
type Vlan struct { type Vlan struct {
LinkAttrs LinkAttrs
VlanId int VlanId int
VlanProtocol VlanProtocol
} }
func (vlan *Vlan) Attrs() *LinkAttrs { func (vlan *Vlan) Attrs() *LinkAttrs {
@ -308,6 +321,8 @@ type Tuntap struct {
NonPersist bool NonPersist bool
Queues int Queues int
Fds []*os.File Fds []*os.File
Owner uint32
Group uint32
} }
func (tuntap *Tuntap) Attrs() *LinkAttrs { func (tuntap *Tuntap) Attrs() *LinkAttrs {
@ -322,6 +337,7 @@ func (tuntap *Tuntap) Type() string {
type Veth struct { type Veth struct {
LinkAttrs LinkAttrs
PeerName string // veth on create only PeerName string // veth on create only
PeerHardwareAddr net.HardwareAddr
} }
func (veth *Veth) Attrs() *LinkAttrs { func (veth *Veth) Attrs() *LinkAttrs {
@ -390,9 +406,18 @@ const (
IPVLAN_MODE_MAX IPVLAN_MODE_MAX
) )
type IPVlanFlag uint16
const (
IPVLAN_FLAG_BRIDGE IPVlanFlag = iota
IPVLAN_FLAG_PRIVATE
IPVLAN_FLAG_VEPA
)
type IPVlan struct { type IPVlan struct {
LinkAttrs LinkAttrs
Mode IPVlanMode Mode IPVlanMode
Flag IPVlanFlag
} }
func (ipvlan *IPVlan) Attrs() *LinkAttrs { func (ipvlan *IPVlan) Attrs() *LinkAttrs {
@ -403,6 +428,43 @@ func (ipvlan *IPVlan) Type() string {
return "ipvlan" return "ipvlan"
} }
// VlanProtocol type
type VlanProtocol int
func (p VlanProtocol) String() string {
s, ok := VlanProtocolToString[p]
if !ok {
return fmt.Sprintf("VlanProtocol(%d)", p)
}
return s
}
// StringToVlanProtocol returns vlan protocol, or unknown is the s is invalid.
func StringToVlanProtocol(s string) VlanProtocol {
mode, ok := StringToVlanProtocolMap[s]
if !ok {
return VLAN_PROTOCOL_UNKNOWN
}
return mode
}
// VlanProtocol possible values
const (
VLAN_PROTOCOL_UNKNOWN VlanProtocol = 0
VLAN_PROTOCOL_8021Q VlanProtocol = 0x8100
VLAN_PROTOCOL_8021AD VlanProtocol = 0x88A8
)
var VlanProtocolToString = map[VlanProtocol]string{
VLAN_PROTOCOL_8021Q: "802.1q",
VLAN_PROTOCOL_8021AD: "802.1ad",
}
var StringToVlanProtocolMap = map[string]VlanProtocol{
"802.1q": VLAN_PROTOCOL_8021Q,
"802.1ad": VLAN_PROTOCOL_8021AD,
}
// BondMode type // BondMode type
type BondMode int type BondMode int
@ -414,7 +476,7 @@ func (b BondMode) String() string {
return s return s
} }
// StringToBondMode returns bond mode, or uknonw is the s is invalid. // StringToBondMode returns bond mode, or unknown is the s is invalid.
func StringToBondMode(s string) BondMode { func StringToBondMode(s string) BondMode {
mode, ok := StringToBondModeMap[s] mode, ok := StringToBondModeMap[s]
if !ok { if !ok {
@ -505,7 +567,7 @@ func (b BondXmitHashPolicy) String() string {
return s return s
} }
// StringToBondXmitHashPolicy returns bond lacp arte, or uknonw is the s is invalid. // StringToBondXmitHashPolicy returns bond lacp arte, or unknown is the s is invalid.
func StringToBondXmitHashPolicy(s string) BondXmitHashPolicy { func StringToBondXmitHashPolicy(s string) BondXmitHashPolicy {
lacp, ok := StringToBondXmitHashPolicyMap[s] lacp, ok := StringToBondXmitHashPolicyMap[s]
if !ok { if !ok {
@ -550,7 +612,7 @@ func (b BondLacpRate) String() string {
return s return s
} }
// StringToBondLacpRate returns bond lacp arte, or uknonw is the s is invalid. // StringToBondLacpRate returns bond lacp arte, or unknown is the s is invalid.
func StringToBondLacpRate(s string) BondLacpRate { func StringToBondLacpRate(s string) BondLacpRate {
lacp, ok := StringToBondLacpRateMap[s] lacp, ok := StringToBondLacpRateMap[s]
if !ok { if !ok {
@ -694,6 +756,67 @@ func (bond *Bond) Type() string {
return "bond" return "bond"
} }
// BondSlaveState represents the values of the IFLA_BOND_SLAVE_STATE bond slave
// attribute, which contains the state of the bond slave.
type BondSlaveState uint8
const (
BondStateActive = iota // Link is active.
BondStateBackup // Link is backup.
)
func (s BondSlaveState) String() string {
switch s {
case BondStateActive:
return "ACTIVE"
case BondStateBackup:
return "BACKUP"
default:
return strconv.Itoa(int(s))
}
}
// BondSlaveState represents the values of the IFLA_BOND_SLAVE_MII_STATUS bond slave
// attribute, which contains the status of MII link monitoring
type BondSlaveMiiStatus uint8
const (
BondLinkUp = iota // link is up and running.
BondLinkFail // link has just gone down.
BondLinkDown // link has been down for too long time.
BondLinkBack // link is going back.
)
func (s BondSlaveMiiStatus) String() string {
switch s {
case BondLinkUp:
return "UP"
case BondLinkFail:
return "GOING_DOWN"
case BondLinkDown:
return "DOWN"
case BondLinkBack:
return "GOING_BACK"
default:
return strconv.Itoa(int(s))
}
}
type BondSlave struct {
State BondSlaveState
MiiStatus BondSlaveMiiStatus
LinkFailureCount uint32
PermHardwareAddr net.HardwareAddr
QueueId uint16
AggregatorId uint16
AdActorOperPortState uint8
AdPartnerOperPortState uint16
}
func (b *BondSlave) SlaveType() string {
return "bond"
}
// Gretap devices must specify LocalIP and RemoteIP on create // Gretap devices must specify LocalIP and RemoteIP on create
type Gretap struct { type Gretap struct {
LinkAttrs LinkAttrs
@ -748,6 +871,27 @@ func (iptun *Iptun) Type() string {
return "ipip" return "ipip"
} }
type Ip6tnl struct {
LinkAttrs
Link uint32
Local net.IP
Remote net.IP
Ttl uint8
Tos uint8
EncapLimit uint8
Flags uint32
Proto uint8
FlowInfo uint32
}
func (ip6tnl *Ip6tnl) Attrs() *LinkAttrs {
return &ip6tnl.LinkAttrs
}
func (ip6tnl *Ip6tnl) Type() string {
return "ip6tnl"
}
type Sittun struct { type Sittun struct {
LinkAttrs LinkAttrs
Link uint32 Link uint32
@ -848,11 +992,68 @@ func (gtp *GTP) Type() string {
return "gtp" return "gtp"
} }
// Virtual XFRM Interfaces
// Named "xfrmi" to prevent confusion with XFRM objects
type Xfrmi struct {
LinkAttrs
Ifid uint32
}
func (xfrm *Xfrmi) Attrs() *LinkAttrs {
return &xfrm.LinkAttrs
}
func (xfrm *Xfrmi) Type() string {
return "xfrm"
}
// IPoIB interface
type IPoIBMode uint16
func (m *IPoIBMode) String() string {
str, ok := iPoIBModeToString[*m]
if !ok {
return fmt.Sprintf("mode(%d)", *m)
}
return str
}
const (
IPOIB_MODE_DATAGRAM = iota
IPOIB_MODE_CONNECTED
)
var iPoIBModeToString = map[IPoIBMode]string{
IPOIB_MODE_DATAGRAM: "datagram",
IPOIB_MODE_CONNECTED: "connected",
}
var StringToIPoIBMode = map[string]IPoIBMode{
"datagram": IPOIB_MODE_DATAGRAM,
"connected": IPOIB_MODE_CONNECTED,
}
type IPoIB struct {
LinkAttrs
Pkey uint16
Mode IPoIBMode
Umcast uint16
}
func (ipoib *IPoIB) Attrs() *LinkAttrs {
return &ipoib.LinkAttrs
}
func (ipoib *IPoIB) Type() string {
return "ipoib"
}
// iproute2 supported devices; // iproute2 supported devices;
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap | // vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan | // bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
// gre | gretap | ip6gre | ip6gretap | vti | vti6 | nlmon | // gre | gretap | ip6gre | ip6gretap | vti | vti6 | nlmon |
// bond_slave | ipvlan // bond_slave | ipvlan | xfrm
// LinkNotFoundError wraps the various not found errors when // LinkNotFoundError wraps the various not found errors when
// getting/reading links. This is intended for better error // getting/reading links. This is intended for better error

View File

@ -4,8 +4,10 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io/ioutil"
"net" "net"
"os" "os"
"strconv"
"strings" "strings"
"syscall" "syscall"
"unsafe" "unsafe"
@ -17,7 +19,7 @@ import (
const ( const (
SizeofLinkStats32 = 0x5c SizeofLinkStats32 = 0x5c
SizeofLinkStats64 = 0xd8 SizeofLinkStats64 = 0xb8
) )
const ( const (
@ -32,6 +34,12 @@ const (
TUNTAP_MULTI_QUEUE_DEFAULTS TuntapFlag = TUNTAP_MULTI_QUEUE | TUNTAP_NO_PI TUNTAP_MULTI_QUEUE_DEFAULTS TuntapFlag = TUNTAP_MULTI_QUEUE | TUNTAP_NO_PI
) )
const (
VF_LINK_STATE_AUTO uint32 = 0
VF_LINK_STATE_ENABLE uint32 = 1
VF_LINK_STATE_DISABLE uint32 = 2
)
var lookupByDump = false var lookupByDump = false
var macvlanModes = [...]uint32{ var macvlanModes = [...]uint32{
@ -465,6 +473,37 @@ func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
return err return err
} }
// LinkSetVfVlanQos sets the vlan and qos priority of a vf for the link.
// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos`
func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
return pkgHandle.LinkSetVfVlanQos(link, vf, vlan, qos)
}
// LinkSetVfVlanQos sets the vlan and qos priority of a vf for the link.
// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos`
func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
base := link.Attrs()
h.ensureIndex(base)
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
msg.Index = int32(base.Index)
req.AddData(msg)
data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
vfmsg := nl.VfVlan{
Vf: uint32(vf),
Vlan: uint32(vlan),
Qos: uint32(qos),
}
nl.NewRtAttrChild(info, nl.IFLA_VF_VLAN, vfmsg.Serialize())
req.AddData(data)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
return err
}
// LinkSetVfTxRate sets the tx rate of a vf for the link. // LinkSetVfTxRate sets the tx rate of a vf for the link.
// Equivalent to: `ip link set $link vf $vf rate $rate` // Equivalent to: `ip link set $link vf $vf rate $rate`
func LinkSetVfTxRate(link Link, vf, rate int) error { func LinkSetVfTxRate(link Link, vf, rate int) error {
@ -495,13 +534,74 @@ func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
return err return err
} }
// LinkSetVfRate sets the min and max tx rate of a vf for the link.
// Equivalent to: `ip link set $link vf $vf min_tx_rate $min_rate max_tx_rate $max_rate`
func LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
return pkgHandle.LinkSetVfRate(link, vf, minRate, maxRate)
}
// LinkSetVfRate sets the min and max tx rate of a vf for the link.
// Equivalent to: `ip link set $link vf $vf min_tx_rate $min_rate max_tx_rate $max_rate`
func (h *Handle) LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
base := link.Attrs()
h.ensureIndex(base)
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
msg.Index = int32(base.Index)
req.AddData(msg)
data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
vfmsg := nl.VfRate{
Vf: uint32(vf),
MinTxRate: uint32(minRate),
MaxTxRate: uint32(maxRate),
}
info.AddRtAttr(nl.IFLA_VF_RATE, vfmsg.Serialize())
req.AddData(data)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
return err
}
// LinkSetVfState enables/disables virtual link state on a vf.
// Equivalent to: `ip link set $link vf $vf state $state`
func LinkSetVfState(link Link, vf int, state uint32) error {
return pkgHandle.LinkSetVfState(link, vf, state)
}
// LinkSetVfState enables/disables virtual link state on a vf.
// Equivalent to: `ip link set $link vf $vf state $state`
func (h *Handle) LinkSetVfState(link Link, vf int, state uint32) error {
base := link.Attrs()
h.ensureIndex(base)
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
msg.Index = int32(base.Index)
req.AddData(msg)
data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
vfmsg := nl.VfLinkState{
Vf: uint32(vf),
LinkState: state,
}
info.AddRtAttr(nl.IFLA_VF_LINK_STATE, vfmsg.Serialize())
req.AddData(data)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
return err
}
// LinkSetVfSpoofchk enables/disables spoof check on a vf for the link. // LinkSetVfSpoofchk enables/disables spoof check on a vf for the link.
// Equivalent to: `ip link set $link vf $vf spoofchk $check` // Equivalent to: `ip link set $link vf $vf spoofchk $check`
func LinkSetVfSpoofchk(link Link, vf int, check bool) error { func LinkSetVfSpoofchk(link Link, vf int, check bool) error {
return pkgHandle.LinkSetVfSpoofchk(link, vf, check) return pkgHandle.LinkSetVfSpoofchk(link, vf, check)
} }
// LinkSetVfSpookfchk enables/disables spoof check on a vf for the link. // LinkSetVfSpoofchk enables/disables spoof check on a vf for the link.
// Equivalent to: `ip link set $link vf $vf spoofchk $check` // Equivalent to: `ip link set $link vf $vf spoofchk $check`
func (h *Handle) LinkSetVfSpoofchk(link Link, vf int, check bool) error { func (h *Handle) LinkSetVfSpoofchk(link Link, vf int, check bool) error {
var setting uint32 var setting uint32
@ -581,7 +681,7 @@ func (h *Handle) LinkSetVfGUID(link Link, vf int, vfGuid net.HardwareAddr, guidT
var guid uint64 var guid uint64
buf := bytes.NewBuffer(vfGuid) buf := bytes.NewBuffer(vfGuid)
err = binary.Read(buf, binary.LittleEndian, &guid) err = binary.Read(buf, binary.BigEndian, &guid)
if err != nil { if err != nil {
return err return err
} }
@ -609,13 +709,13 @@ func (h *Handle) LinkSetVfGUID(link Link, vf int, vfGuid net.HardwareAddr, guidT
// LinkSetMaster sets the master of the link device. // LinkSetMaster sets the master of the link device.
// Equivalent to: `ip link set $link master $master` // Equivalent to: `ip link set $link master $master`
func LinkSetMaster(link Link, master *Bridge) error { func LinkSetMaster(link Link, master Link) error {
return pkgHandle.LinkSetMaster(link, master) return pkgHandle.LinkSetMaster(link, master)
} }
// LinkSetMaster sets the master of the link device. // LinkSetMaster sets the master of the link device.
// Equivalent to: `ip link set $link master $master` // Equivalent to: `ip link set $link master $master`
func (h *Handle) LinkSetMaster(link Link, master *Bridge) error { func (h *Handle) LinkSetMaster(link Link, master Link) error {
index := 0 index := 0
if master != nil { if master != nil {
masterBase := master.Attrs() masterBase := master.Attrs()
@ -1086,8 +1186,8 @@ func (h *Handle) linkModify(link Link, flags int) error {
native.PutUint32(b, uint32(base.ParentIndex)) native.PutUint32(b, uint32(base.ParentIndex))
data := nl.NewRtAttr(unix.IFLA_LINK, b) data := nl.NewRtAttr(unix.IFLA_LINK, b)
req.AddData(data) req.AddData(data)
} else if link.Type() == "ipvlan" { } else if link.Type() == "ipvlan" || link.Type() == "ipoib" {
return fmt.Errorf("Can't create ipvlan link without ParentIndex") return fmt.Errorf("Can't create %s link without ParentIndex", link.Type())
} }
nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(base.Name)) nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(base.Name))
@ -1118,14 +1218,29 @@ func (h *Handle) linkModify(link Link, flags int) error {
req.AddData(rxqueues) req.AddData(rxqueues)
} }
if base.GSOMaxSegs > 0 {
gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SEGS, nl.Uint32Attr(base.GSOMaxSegs))
req.AddData(gsoAttr)
}
if base.GSOMaxSize > 0 {
gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SIZE, nl.Uint32Attr(base.GSOMaxSize))
req.AddData(gsoAttr)
}
if base.Group > 0 {
groupAttr := nl.NewRtAttr(unix.IFLA_GROUP, nl.Uint32Attr(base.Group))
req.AddData(groupAttr)
}
if base.Namespace != nil { if base.Namespace != nil {
var attr *nl.RtAttr var attr *nl.RtAttr
switch base.Namespace.(type) { switch ns := base.Namespace.(type) {
case NsPid: case NsPid:
val := nl.Uint32Attr(uint32(base.Namespace.(NsPid))) val := nl.Uint32Attr(uint32(ns))
attr = nl.NewRtAttr(unix.IFLA_NET_NS_PID, val) attr = nl.NewRtAttr(unix.IFLA_NET_NS_PID, val)
case NsFd: case NsFd:
val := nl.Uint32Attr(uint32(base.Namespace.(NsFd))) val := nl.Uint32Attr(uint32(ns))
attr = nl.NewRtAttr(unix.IFLA_NET_NS_FD, val) attr = nl.NewRtAttr(unix.IFLA_NET_NS_FD, val)
} }
@ -1145,6 +1260,10 @@ func (h *Handle) linkModify(link Link, flags int) error {
native.PutUint16(b, uint16(link.VlanId)) native.PutUint16(b, uint16(link.VlanId))
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
data.AddRtAttr(nl.IFLA_VLAN_ID, b) data.AddRtAttr(nl.IFLA_VLAN_ID, b)
if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN {
data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol)))
}
case *Veth: case *Veth:
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil) peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil)
@ -1156,7 +1275,9 @@ func (h *Handle) linkModify(link Link, flags int) error {
if base.MTU > 0 { if base.MTU > 0 {
peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU))) peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU)))
} }
if link.PeerHardwareAddr != nil {
peer.AddRtAttr(unix.IFLA_ADDRESS, []byte(link.PeerHardwareAddr))
}
case *Vxlan: case *Vxlan:
addVxlanAttrs(link, linkInfo) addVxlanAttrs(link, linkInfo)
case *Bond: case *Bond:
@ -1164,6 +1285,7 @@ func (h *Handle) linkModify(link Link, flags int) error {
case *IPVlan: case *IPVlan:
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode))) data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
case *Macvlan: case *Macvlan:
if link.Mode != MACVLAN_MODE_DEFAULT { if link.Mode != MACVLAN_MODE_DEFAULT {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
@ -1178,6 +1300,8 @@ func (h *Handle) linkModify(link Link, flags int) error {
addGretapAttrs(link, linkInfo) addGretapAttrs(link, linkInfo)
case *Iptun: case *Iptun:
addIptunAttrs(link, linkInfo) addIptunAttrs(link, linkInfo)
case *Ip6tnl:
addIp6tnlAttrs(link, linkInfo)
case *Sittun: case *Sittun:
addSittunAttrs(link, linkInfo) addSittunAttrs(link, linkInfo)
case *Gretun: case *Gretun:
@ -1190,6 +1314,10 @@ func (h *Handle) linkModify(link Link, flags int) error {
addBridgeAttrs(link, linkInfo) addBridgeAttrs(link, linkInfo)
case *GTP: case *GTP:
addGTPAttrs(link, linkInfo) addGTPAttrs(link, linkInfo)
case *Xfrmi:
addXfrmiAttrs(link, linkInfo)
case *IPoIB:
addIPoIBAttrs(link, linkInfo)
} }
req.AddData(linkInfo) req.AddData(linkInfo)
@ -1387,9 +1515,11 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
} }
var ( var (
link Link link Link
stats32 []byte stats32 *LinkStatistics32
stats64 []byte stats64 *LinkStatistics64
linkType string linkType string
linkSlave LinkSlave
slaveType string
) )
for _, attr := range attrs { for _, attr := range attrs {
switch attr.Attr.Type { switch attr.Attr.Type {
@ -1429,6 +1559,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &Gretap{} link = &Gretap{}
case "ipip": case "ipip":
link = &Iptun{} link = &Iptun{}
case "ip6tnl":
link = &Ip6tnl{}
case "sit": case "sit":
link = &Sittun{} link = &Sittun{}
case "gre": case "gre":
@ -1441,6 +1573,12 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &Vrf{} link = &Vrf{}
case "gtp": case "gtp":
link = &GTP{} link = &GTP{}
case "xfrm":
link = &Xfrmi{}
case "tun":
link = &Tuntap{}
case "ipoib":
link = &IPoIB{}
default: default:
link = &GenericLink{LinkType: linkType} link = &GenericLink{LinkType: linkType}
} }
@ -1468,6 +1606,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
parseGretapData(link, data) parseGretapData(link, data)
case "ipip": case "ipip":
parseIptunData(link, data) parseIptunData(link, data)
case "ip6tnl":
parseIp6tnlData(link, data)
case "sit": case "sit":
parseSittunData(link, data) parseSittunData(link, data)
case "gre": case "gre":
@ -1482,6 +1622,27 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
parseBridgeData(link, data) parseBridgeData(link, data)
case "gtp": case "gtp":
parseGTPData(link, data) parseGTPData(link, data)
case "xfrm":
parseXfrmiData(link, data)
case "tun":
parseTuntapData(link, data)
case "ipoib":
parseIPoIBData(link, data)
}
case nl.IFLA_INFO_SLAVE_KIND:
slaveType = string(info.Value[:len(info.Value)-1])
switch slaveType {
case "bond":
linkSlave = &BondSlave{}
}
case nl.IFLA_INFO_SLAVE_DATA:
switch slaveType {
case "bond":
data, err := nl.ParseRouteAttr(info.Value)
if err != nil {
return nil, err
}
parseBondSlaveData(linkSlave, data)
} }
} }
} }
@ -1508,9 +1669,15 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
case unix.IFLA_IFALIAS: case unix.IFLA_IFALIAS:
base.Alias = string(attr.Value[:len(attr.Value)-1]) base.Alias = string(attr.Value[:len(attr.Value)-1])
case unix.IFLA_STATS: case unix.IFLA_STATS:
stats32 = attr.Value[:] stats32 = new(LinkStatistics32)
if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats32); err != nil {
return nil, err
}
case unix.IFLA_STATS64: case unix.IFLA_STATS64:
stats64 = attr.Value[:] stats64 = new(LinkStatistics64)
if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats64); err != nil {
return nil, err
}
case unix.IFLA_XDP: case unix.IFLA_XDP:
xdp, err := parseLinkXdp(attr.Value[:]) xdp, err := parseLinkXdp(attr.Value[:])
if err != nil { if err != nil {
@ -1531,6 +1698,10 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
base.OperState = LinkOperState(uint8(attr.Value[0])) base.OperState = LinkOperState(uint8(attr.Value[0]))
case unix.IFLA_LINK_NETNSID: case unix.IFLA_LINK_NETNSID:
base.NetNsID = int(native.Uint32(attr.Value[0:4])) base.NetNsID = int(native.Uint32(attr.Value[0:4]))
case unix.IFLA_GSO_MAX_SIZE:
base.GSOMaxSize = native.Uint32(attr.Value[0:4])
case unix.IFLA_GSO_MAX_SEGS:
base.GSOMaxSegs = native.Uint32(attr.Value[0:4])
case unix.IFLA_VFINFO_LIST: case unix.IFLA_VFINFO_LIST:
data, err := nl.ParseRouteAttr(attr.Value) data, err := nl.ParseRouteAttr(attr.Value)
if err != nil { if err != nil {
@ -1541,13 +1712,19 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
return nil, err return nil, err
} }
base.Vfs = vfs base.Vfs = vfs
case unix.IFLA_NUM_TX_QUEUES:
base.NumTxQueues = int(native.Uint32(attr.Value[0:4]))
case unix.IFLA_NUM_RX_QUEUES:
base.NumRxQueues = int(native.Uint32(attr.Value[0:4]))
case unix.IFLA_GROUP:
base.Group = native.Uint32(attr.Value[0:4])
} }
} }
if stats64 != nil { if stats64 != nil {
base.Statistics = parseLinkStats64(stats64) base.Statistics = (*LinkStatistics)(stats64)
} else if stats32 != nil { } else if stats32 != nil {
base.Statistics = parseLinkStats32(stats32) base.Statistics = (*LinkStatistics)(stats32.to64())
} }
// Links that don't have IFLA_INFO_KIND are hardware devices // Links that don't have IFLA_INFO_KIND are hardware devices
@ -1555,10 +1732,59 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &Device{} link = &Device{}
} }
*link.Attrs() = base *link.Attrs() = base
link.Attrs().Slave = linkSlave
// If the tuntap attributes are not updated by netlink due to
// an older driver, use sysfs
if link != nil && linkType == "tun" {
tuntap := link.(*Tuntap)
if tuntap.Mode == 0 {
ifname := tuntap.Attrs().Name
if flags, err := readSysPropAsInt64(ifname, "tun_flags"); err == nil {
if flags&unix.IFF_TUN != 0 {
tuntap.Mode = unix.IFF_TUN
} else if flags&unix.IFF_TAP != 0 {
tuntap.Mode = unix.IFF_TAP
}
tuntap.NonPersist = false
if flags&unix.IFF_PERSIST == 0 {
tuntap.NonPersist = true
}
}
// The sysfs interface for owner/group returns -1 for root user, instead of returning 0.
// So explicitly check for negative value, before assigning the owner uid/gid.
if owner, err := readSysPropAsInt64(ifname, "owner"); err == nil && owner > 0 {
tuntap.Owner = uint32(owner)
}
if group, err := readSysPropAsInt64(ifname, "group"); err == nil && group > 0 {
tuntap.Group = uint32(group)
}
}
}
return link, nil return link, nil
} }
func readSysPropAsInt64(ifname, prop string) (int64, error) {
fname := fmt.Sprintf("/sys/class/net/%s/%s", ifname, prop)
contents, err := ioutil.ReadFile(fname)
if err != nil {
return 0, err
}
num, err := strconv.ParseInt(strings.TrimSpace(string(contents)), 0, 64)
if err == nil {
return num, nil
}
return 0, err
}
// LinkList gets a list of link devices. // LinkList gets a list of link devices.
// Equivalent to: `ip link show` // Equivalent to: `ip link show`
func LinkList() ([]Link, error) { func LinkList() ([]Link, error) {
@ -1655,13 +1881,19 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c
go func() { go func() {
defer close(ch) defer close(ch)
for { for {
msgs, err := s.Receive() msgs, from, err := s.Receive()
if err != nil { if err != nil {
if cberr != nil { if cberr != nil {
cberr(err) cberr(err)
} }
return return
} }
if from.Pid != nl.PidKernel {
if cberr != nil {
cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel))
}
continue
}
for _, m := range msgs { for _, m := range msgs {
if m.Header.Type == unix.NLMSG_DONE { if m.Header.Type == unix.NLMSG_DONE {
continue continue
@ -1804,12 +2036,43 @@ func (h *Handle) LinkSetTxQLen(link Link, qlen int) error {
return err return err
} }
// LinkSetGroup sets the link group id which can be used to perform mass actions
// with iproute2 as well use it as a reference in nft filters.
// Equivalent to: `ip link set $link group $id`
func LinkSetGroup(link Link, group int) error {
return pkgHandle.LinkSetGroup(link, group)
}
// LinkSetGroup sets the link group id which can be used to perform mass actions
// with iproute2 as well use it as a reference in nft filters.
// Equivalent to: `ip link set $link group $id`
func (h *Handle) LinkSetGroup(link Link, group int) error {
base := link.Attrs()
h.ensureIndex(base)
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
msg.Index = int32(base.Index)
req.AddData(msg)
b := make([]byte, 4)
native.PutUint32(b, uint32(group))
data := nl.NewRtAttr(unix.IFLA_GROUP, b)
req.AddData(data)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
return err
}
func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) { func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) {
vlan := link.(*Vlan) vlan := link.(*Vlan)
for _, datum := range data { for _, datum := range data {
switch datum.Attr.Type { switch datum.Attr.Type {
case nl.IFLA_VLAN_ID: case nl.IFLA_VLAN_ID:
vlan.VlanId = int(native.Uint16(datum.Value[0:2])) vlan.VlanId = int(native.Uint16(datum.Value[0:2]))
case nl.IFLA_VLAN_PROTOCOL:
vlan.VlanProtocol = VlanProtocol(int(ntohs(datum.Value[0:2])))
} }
} }
} }
@ -1891,7 +2154,7 @@ func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
case nl.IFLA_BOND_ARP_INTERVAL: case nl.IFLA_BOND_ARP_INTERVAL:
bond.ArpInterval = int(native.Uint32(data[i].Value[0:4])) bond.ArpInterval = int(native.Uint32(data[i].Value[0:4]))
case nl.IFLA_BOND_ARP_IP_TARGET: case nl.IFLA_BOND_ARP_IP_TARGET:
// TODO: implement bond.ArpIpTargets = parseBondArpIpTargets(data[i].Value)
case nl.IFLA_BOND_ARP_VALIDATE: case nl.IFLA_BOND_ARP_VALIDATE:
bond.ArpValidate = BondArpValidate(native.Uint32(data[i].Value[0:4])) bond.ArpValidate = BondArpValidate(native.Uint32(data[i].Value[0:4]))
case nl.IFLA_BOND_ARP_ALL_TARGETS: case nl.IFLA_BOND_ARP_ALL_TARGETS:
@ -1934,12 +2197,75 @@ func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
} }
} }
func parseBondArpIpTargets(value []byte) []net.IP {
data, err := nl.ParseRouteAttr(value)
if err != nil {
return nil
}
targets := []net.IP{}
for i := range data {
target := net.IP(data[i].Value)
if ip := target.To4(); ip != nil {
targets = append(targets, ip)
continue
}
if ip := target.To16(); ip != nil {
targets = append(targets, ip)
}
}
return targets
}
func addBondSlaveAttrs(bondSlave *BondSlave, linkInfo *nl.RtAttr) {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil)
data.AddRtAttr(nl.IFLA_BOND_SLAVE_STATE, nl.Uint8Attr(uint8(bondSlave.State)))
data.AddRtAttr(nl.IFLA_BOND_SLAVE_MII_STATUS, nl.Uint8Attr(uint8(bondSlave.MiiStatus)))
data.AddRtAttr(nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, nl.Uint32Attr(bondSlave.LinkFailureCount))
data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(bondSlave.QueueId))
data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, nl.Uint16Attr(bondSlave.AggregatorId))
data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, nl.Uint8Attr(bondSlave.AdActorOperPortState))
data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, nl.Uint16Attr(bondSlave.AdPartnerOperPortState))
if mac := bondSlave.PermHardwareAddr; mac != nil {
data.AddRtAttr(nl.IFLA_BOND_SLAVE_PERM_HWADDR, []byte(mac))
}
}
func parseBondSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) {
bondSlave := slave.(*BondSlave)
for i := range data {
switch data[i].Attr.Type {
case nl.IFLA_BOND_SLAVE_STATE:
bondSlave.State = BondSlaveState(data[i].Value[0])
case nl.IFLA_BOND_SLAVE_MII_STATUS:
bondSlave.MiiStatus = BondSlaveMiiStatus(data[i].Value[0])
case nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT:
bondSlave.LinkFailureCount = native.Uint32(data[i].Value[0:4])
case nl.IFLA_BOND_SLAVE_PERM_HWADDR:
bondSlave.PermHardwareAddr = net.HardwareAddr(data[i].Value[0:6])
case nl.IFLA_BOND_SLAVE_QUEUE_ID:
bondSlave.QueueId = native.Uint16(data[i].Value[0:2])
case nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID:
bondSlave.AggregatorId = native.Uint16(data[i].Value[0:2])
case nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE:
bondSlave.AdActorOperPortState = uint8(data[i].Value[0])
case nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE:
bondSlave.AdPartnerOperPortState = native.Uint16(data[i].Value[0:2])
}
}
}
func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) { func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
ipv := link.(*IPVlan) ipv := link.(*IPVlan)
for _, datum := range data { for _, datum := range data {
if datum.Attr.Type == nl.IFLA_IPVLAN_MODE { switch datum.Attr.Type {
case nl.IFLA_IPVLAN_MODE:
ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4])) ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4]))
return case nl.IFLA_IPVLAN_FLAG:
ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4]))
} }
} }
} }
@ -2081,9 +2407,7 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
case nl.IFLA_GRE_ENCAP_FLAGS: case nl.IFLA_GRE_ENCAP_FLAGS:
gre.EncapFlags = native.Uint16(datum.Value[0:2]) gre.EncapFlags = native.Uint16(datum.Value[0:2])
case nl.IFLA_GRE_COLLECT_METADATA: case nl.IFLA_GRE_COLLECT_METADATA:
if len(datum.Value) > 0 { gre.FlowBased = true
gre.FlowBased = int8(datum.Value[0]) != 0
}
} }
} }
} }
@ -2165,14 +2489,6 @@ func parseGretunData(link Link, data []syscall.NetlinkRouteAttr) {
} }
} }
func parseLinkStats32(data []byte) *LinkStatistics {
return (*LinkStatistics)((*LinkStatistics32)(unsafe.Pointer(&data[0:SizeofLinkStats32][0])).to64())
}
func parseLinkStats64(data []byte) *LinkStatistics {
return (*LinkStatistics)((*LinkStatistics64)(unsafe.Pointer(&data[0:SizeofLinkStats64][0])))
}
func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) { func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) {
attrs := nl.NewRtAttr(unix.IFLA_XDP|unix.NLA_F_NESTED, nil) attrs := nl.NewRtAttr(unix.IFLA_XDP|unix.NLA_F_NESTED, nil)
b := make([]byte, 4) b := make([]byte, 4)
@ -2266,6 +2582,55 @@ func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
} }
} }
func addIp6tnlAttrs(ip6tnl *Ip6tnl, linkInfo *nl.RtAttr) {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
if ip6tnl.Link != 0 {
data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(ip6tnl.Link))
}
ip := ip6tnl.Local.To16()
if ip != nil {
data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip))
}
ip = ip6tnl.Remote.To16()
if ip != nil {
data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip))
}
data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(ip6tnl.Ttl))
data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(ip6tnl.Tos))
data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(ip6tnl.EncapLimit))
data.AddRtAttr(nl.IFLA_IPTUN_FLAGS, nl.Uint32Attr(ip6tnl.Flags))
data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(ip6tnl.Proto))
data.AddRtAttr(nl.IFLA_IPTUN_FLOWINFO, nl.Uint32Attr(ip6tnl.FlowInfo))
}
func parseIp6tnlData(link Link, data []syscall.NetlinkRouteAttr) {
ip6tnl := link.(*Ip6tnl)
for _, datum := range data {
switch datum.Attr.Type {
case nl.IFLA_IPTUN_LOCAL:
ip6tnl.Local = net.IP(datum.Value[:16])
case nl.IFLA_IPTUN_REMOTE:
ip6tnl.Remote = net.IP(datum.Value[:16])
case nl.IFLA_IPTUN_TTL:
ip6tnl.Ttl = uint8(datum.Value[0])
case nl.IFLA_IPTUN_TOS:
ip6tnl.Tos = uint8(datum.Value[0])
case nl.IFLA_IPTUN_ENCAP_LIMIT:
ip6tnl.EncapLimit = uint8(datum.Value[0])
case nl.IFLA_IPTUN_FLAGS:
ip6tnl.Flags = native.Uint32(datum.Value[:4])
case nl.IFLA_IPTUN_PROTO:
ip6tnl.Proto = uint8(datum.Value[0])
case nl.IFLA_IPTUN_FLOWINFO:
ip6tnl.FlowInfo = native.Uint32(datum.Value[:4])
}
}
}
func addSittunAttrs(sittun *Sittun, linkInfo *nl.RtAttr) { func addSittunAttrs(sittun *Sittun, linkInfo *nl.RtAttr) {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
@ -2483,11 +2848,34 @@ func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo {
case nl.IFLA_VF_LINK_STATE: case nl.IFLA_VF_LINK_STATE:
ls := nl.DeserializeVfLinkState(element.Value[:]) ls := nl.DeserializeVfLinkState(element.Value[:])
vf.LinkState = ls.LinkState vf.LinkState = ls.LinkState
case nl.IFLA_VF_RATE:
vfr := nl.DeserializeVfRate(element.Value[:])
vf.MaxTxRate = vfr.MaxTxRate
vf.MinTxRate = vfr.MinTxRate
} }
} }
return vf return vf
} }
func addXfrmiAttrs(xfrmi *Xfrmi, linkInfo *nl.RtAttr) {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
data.AddRtAttr(nl.IFLA_XFRM_LINK, nl.Uint32Attr(uint32(xfrmi.ParentIndex)))
data.AddRtAttr(nl.IFLA_XFRM_IF_ID, nl.Uint32Attr(xfrmi.Ifid))
}
func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) {
xfrmi := link.(*Xfrmi)
for _, datum := range data {
switch datum.Attr.Type {
case nl.IFLA_XFRM_LINK:
xfrmi.ParentIndex = int(native.Uint32(datum.Value))
case nl.IFLA_XFRM_IF_ID:
xfrmi.Ifid = native.Uint32(datum.Value)
}
}
}
// LinkSetBondSlave add slave to bond link via ioctl interface. // LinkSetBondSlave add slave to bond link via ioctl interface.
func LinkSetBondSlave(link Link, master *Bond) error { func LinkSetBondSlave(link Link, master *Bond) error {
fd, err := getSocketUDP() fd, err := getSocketUDP()
@ -2505,6 +2893,52 @@ func LinkSetBondSlave(link Link, master *Bond) error {
return nil return nil
} }
// LinkSetBondSlaveQueueId modify bond slave queue-id.
func (h *Handle) LinkSetBondSlaveQueueId(link Link, queueId uint16) error {
base := link.Attrs()
h.ensureIndex(base)
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
msg.Index = int32(base.Index)
req.AddData(msg)
linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil)
data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(queueId))
req.AddData(linkInfo)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
return err
}
// LinkSetBondSlaveQueueId modify bond slave queue-id.
func LinkSetBondSlaveQueueId(link Link, queueId uint16) error {
return pkgHandle.LinkSetBondSlaveQueueId(link, queueId)
}
func vethStatsSerialize(stats ethtoolStats) ([]byte, error) {
statsSize := int(unsafe.Sizeof(stats)) + int(stats.nStats)*int(unsafe.Sizeof(uint64(0)))
b := make([]byte, 0, statsSize)
buf := bytes.NewBuffer(b)
err := binary.Write(buf, nl.NativeEndian(), stats)
return buf.Bytes()[:statsSize], err
}
type vethEthtoolStats struct {
Cmd uint32
NStats uint32
Peer uint64
// Newer kernels have XDP stats in here, but we only care
// to extract the peer ifindex here.
}
func vethStatsDeserialize(b []byte) (vethEthtoolStats, error) {
var stats = vethEthtoolStats{}
err := binary.Read(bytes.NewReader(b), nl.NativeEndian(), &stats)
return stats, err
}
// VethPeerIndex get veth peer index. // VethPeerIndex get veth peer index.
func VethPeerIndex(link *Veth) (int, error) { func VethPeerIndex(link *Veth) (int, error) {
fd, err := getSocketUDP() fd, err := getSocketUDP()
@ -2519,25 +2953,66 @@ func VethPeerIndex(link *Veth) (int, error) {
return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno) return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno)
} }
gstrings := &ethtoolGstrings{ stats := ethtoolStats{
cmd: ETHTOOL_GSTRINGS, cmd: ETHTOOL_GSTATS,
stringSet: ETH_SS_STATS, nStats: sSet.data[0],
length: sSet.data[0],
} }
ifreq.Data = uintptr(unsafe.Pointer(gstrings))
buffer, err := vethStatsSerialize(stats)
if err != nil {
return -1, err
}
ifreq.Data = uintptr(unsafe.Pointer(&buffer[0]))
_, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq))) _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq)))
if errno != 0 { if errno != 0 {
return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno) return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno)
} }
stats := &ethtoolStats{ vstats, err := vethStatsDeserialize(buffer)
cmd: ETHTOOL_GSTATS, if err != nil {
nStats: gstrings.length, return -1, err
} }
ifreq.Data = uintptr(unsafe.Pointer(stats))
_, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq))) return int(vstats.Peer), nil
if errno != 0 {
return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno)
} }
return int(stats.data[0]), nil
func parseTuntapData(link Link, data []syscall.NetlinkRouteAttr) {
tuntap := link.(*Tuntap)
for _, datum := range data {
switch datum.Attr.Type {
case nl.IFLA_TUN_OWNER:
tuntap.Owner = native.Uint32(datum.Value)
case nl.IFLA_TUN_GROUP:
tuntap.Group = native.Uint32(datum.Value)
case nl.IFLA_TUN_TYPE:
tuntap.Mode = TuntapMode(uint8(datum.Value[0]))
case nl.IFLA_TUN_PERSIST:
tuntap.NonPersist = false
if uint8(datum.Value[0]) == 0 {
tuntap.NonPersist = true
}
}
}
}
func parseIPoIBData(link Link, data []syscall.NetlinkRouteAttr) {
ipoib := link.(*IPoIB)
for _, datum := range data {
switch datum.Attr.Type {
case nl.IFLA_IPOIB_PKEY:
ipoib.Pkey = uint16(native.Uint16(datum.Value))
case nl.IFLA_IPOIB_MODE:
ipoib.Mode = IPoIBMode(native.Uint16(datum.Value))
case nl.IFLA_IPOIB_UMCAST:
ipoib.Umcast = uint16(native.Uint16(datum.Value))
}
}
}
func addIPoIBAttrs(ipoib *IPoIB, linkInfo *nl.RtAttr) {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
data.AddRtAttr(nl.IFLA_IPOIB_PKEY, nl.Uint16Attr(uint16(ipoib.Pkey)))
data.AddRtAttr(nl.IFLA_IPOIB_MODE, nl.Uint16Attr(uint16(ipoib.Mode)))
data.AddRtAttr(nl.IFLA_IPOIB_UMCAST, nl.Uint16Attr(uint16(ipoib.Umcast)))
} }

View File

@ -17,6 +17,7 @@ type Neigh struct {
LLIPAddr net.IP //Used in the case of NHRP LLIPAddr net.IP //Used in the case of NHRP
Vlan int Vlan int
VNI int VNI int
MasterIndex int
} }
// String returns $ip/$hwaddr $label // String returns $ip/$hwaddr $label

View File

@ -1,6 +1,7 @@
package netlink package netlink
import ( import (
"fmt"
"net" "net"
"syscall" "syscall"
"unsafe" "unsafe"
@ -20,7 +21,10 @@ const (
NDA_PORT NDA_PORT
NDA_VNI NDA_VNI
NDA_IFINDEX NDA_IFINDEX
NDA_MAX = NDA_IFINDEX NDA_MASTER
NDA_LINK_NETNSID
NDA_SRC_VNI
NDA_MAX = NDA_SRC_VNI
) )
// Neighbor Cache Entry States. // Neighbor Cache Entry States.
@ -45,6 +49,7 @@ const (
NTF_ROUTER = 0x80 NTF_ROUTER = 0x80
) )
// Ndmsg is for adding, removing or receiving information about a neighbor table entry
type Ndmsg struct { type Ndmsg struct {
Family uint8 Family uint8
Index uint32 Index uint32
@ -172,45 +177,58 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
req.AddData(vniData) req.AddData(vniData)
} }
if neigh.MasterIndex != 0 {
masterData := nl.NewRtAttr(NDA_MASTER, nl.Uint32Attr(uint32(neigh.MasterIndex)))
req.AddData(masterData)
}
_, err := req.Execute(unix.NETLINK_ROUTE, 0) _, err := req.Execute(unix.NETLINK_ROUTE, 0)
return err return err
} }
// NeighList gets a list of IP-MAC mappings in the system (ARP table). // NeighList returns a list of IP-MAC mappings in the system (ARP table).
// Equivalent to: `ip neighbor show`. // Equivalent to: `ip neighbor show`.
// The list can be filtered by link and ip family. // The list can be filtered by link and ip family.
func NeighList(linkIndex, family int) ([]Neigh, error) { func NeighList(linkIndex, family int) ([]Neigh, error) {
return pkgHandle.NeighList(linkIndex, family) return pkgHandle.NeighList(linkIndex, family)
} }
// NeighProxyList gets a list of neighbor proxies in the system. // NeighProxyList returns a list of neighbor proxies in the system.
// Equivalent to: `ip neighbor show proxy`. // Equivalent to: `ip neighbor show proxy`.
// The list can be filtered by link and ip family. // The list can be filtered by link and ip family.
func NeighProxyList(linkIndex, family int) ([]Neigh, error) { func NeighProxyList(linkIndex, family int) ([]Neigh, error) {
return pkgHandle.NeighProxyList(linkIndex, family) return pkgHandle.NeighProxyList(linkIndex, family)
} }
// NeighList gets a list of IP-MAC mappings in the system (ARP table). // NeighList returns a list of IP-MAC mappings in the system (ARP table).
// Equivalent to: `ip neighbor show`. // Equivalent to: `ip neighbor show`.
// The list can be filtered by link and ip family. // The list can be filtered by link and ip family.
func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) { func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
return h.neighList(linkIndex, family, 0) return h.NeighListExecute(Ndmsg{
Family: uint8(family),
Index: uint32(linkIndex),
})
} }
// NeighProxyList gets a list of neighbor proxies in the system. // NeighProxyList returns a list of neighbor proxies in the system.
// Equivalent to: `ip neighbor show proxy`. // Equivalent to: `ip neighbor show proxy`.
// The list can be filtered by link, ip family. // The list can be filtered by link, ip family.
func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) { func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
return h.neighList(linkIndex, family, NTF_PROXY) return h.NeighListExecute(Ndmsg{
}
func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
req := h.newNetlinkRequest(unix.RTM_GETNEIGH, unix.NLM_F_DUMP)
msg := Ndmsg{
Family: uint8(family), Family: uint8(family),
Index: uint32(linkIndex), Index: uint32(linkIndex),
Flags: uint8(flags), Flags: NTF_PROXY,
})
} }
// NeighListExecute returns a list of neighbour entries filtered by link, ip family, flag and state.
func NeighListExecute(msg Ndmsg) ([]Neigh, error) {
return pkgHandle.NeighListExecute(msg)
}
// NeighListExecute returns a list of neighbour entries filtered by link, ip family, flag and state.
func (h *Handle) NeighListExecute(msg Ndmsg) ([]Neigh, error) {
req := h.newNetlinkRequest(unix.RTM_GETNEIGH, unix.NLM_F_DUMP)
req.AddData(&msg) req.AddData(&msg)
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNEIGH) msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNEIGH)
@ -221,7 +239,7 @@ func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
var res []Neigh var res []Neigh
for _, m := range msgs { for _, m := range msgs {
ndm := deserializeNdmsg(m) ndm := deserializeNdmsg(m)
if linkIndex != 0 && int(ndm.Index) != linkIndex { if msg.Index != 0 && ndm.Index != msg.Index {
// Ignore messages from other interfaces // Ignore messages from other interfaces
continue continue
} }
@ -253,14 +271,6 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
return nil, err return nil, err
} }
// This should be cached for perfomance
// once per table dump
link, err := LinkByIndex(neigh.LinkIndex)
if err != nil {
return nil, err
}
encapType := link.Attrs().EncapType
for _, attr := range attrs { for _, attr := range attrs {
switch attr.Attr.Type { switch attr.Attr.Type {
case NDA_DST: case NDA_DST:
@ -270,20 +280,25 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
// #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len)) // #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
// #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0)) // #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
attrLen := attr.Attr.Len - unix.SizeofRtAttr attrLen := attr.Attr.Len - unix.SizeofRtAttr
if attrLen == 4 && (encapType == "ipip" || if attrLen == 4 {
encapType == "sit" ||
encapType == "gre") {
neigh.LLIPAddr = net.IP(attr.Value) neigh.LLIPAddr = net.IP(attr.Value)
} else if attrLen == 16 && } else if attrLen == 16 {
encapType == "tunnel6" { // Can be IPv6 or FireWire HWAddr
link, err := LinkByIndex(neigh.LinkIndex)
if err == nil && link.Attrs().EncapType == "tunnel6" {
neigh.IP = net.IP(attr.Value) neigh.IP = net.IP(attr.Value)
} else { } else {
neigh.HardwareAddr = net.HardwareAddr(attr.Value) neigh.HardwareAddr = net.HardwareAddr(attr.Value)
} }
} else {
neigh.HardwareAddr = net.HardwareAddr(attr.Value)
}
case NDA_VLAN: case NDA_VLAN:
neigh.Vlan = int(native.Uint16(attr.Value[0:2])) neigh.Vlan = int(native.Uint16(attr.Value[0:2]))
case NDA_VNI: case NDA_VNI:
neigh.VNI = int(native.Uint32(attr.Value[0:4])) neigh.VNI = int(native.Uint32(attr.Value[0:4]))
case NDA_MASTER:
neigh.MasterIndex = int(native.Uint32(attr.Value[0:4]))
} }
} }
@ -323,6 +338,16 @@ func NeighSubscribeWithOptions(ch chan<- NeighUpdate, done <-chan struct{}, opti
func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error { func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_NEIGH) s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_NEIGH)
makeRequest := func(family int) error {
req := pkgHandle.newNetlinkRequest(unix.RTM_GETNEIGH,
unix.NLM_F_DUMP)
infmsg := nl.NewIfInfomsg(family)
req.AddData(infmsg)
if err := s.Send(req); err != nil {
return err
}
return nil
}
if err != nil { if err != nil {
return err return err
} }
@ -333,26 +358,41 @@ func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <
}() }()
} }
if listExisting { if listExisting {
req := pkgHandle.newNetlinkRequest(unix.RTM_GETNEIGH, if err := makeRequest(unix.AF_UNSPEC); err != nil {
unix.NLM_F_DUMP)
infmsg := nl.NewIfInfomsg(unix.AF_UNSPEC)
req.AddData(infmsg)
if err := s.Send(req); err != nil {
return err return err
} }
// We have to wait for NLMSG_DONE before making AF_BRIDGE request
} }
go func() { go func() {
defer close(ch) defer close(ch)
for { for {
msgs, err := s.Receive() msgs, from, err := s.Receive()
if err != nil { if err != nil {
if cberr != nil { if cberr != nil {
cberr(err) cberr(err)
} }
return return
} }
if from.Pid != nl.PidKernel {
if cberr != nil {
cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel))
}
continue
}
for _, m := range msgs { for _, m := range msgs {
if m.Header.Type == unix.NLMSG_DONE { if m.Header.Type == unix.NLMSG_DONE {
if listExisting {
// This will be called after handling AF_UNSPEC
// list request, we have to wait for NLMSG_DONE
// before making another request
if err := makeRequest(unix.AF_BRIDGE); err != nil {
if cberr != nil {
cberr(err)
}
return
}
listExisting = false
}
continue continue
} }
if m.Header.Type == unix.NLMSG_ERROR { if m.Header.Type == unix.NLMSG_ERROR {

View File

@ -48,10 +48,18 @@ func LinkSetVfVlan(link Link, vf, vlan int) error {
return ErrNotImplemented return ErrNotImplemented
} }
func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
return ErrNotImplemented
}
func LinkSetVfTxRate(link Link, vf, rate int) error { func LinkSetVfTxRate(link Link, vf, rate int) error {
return ErrNotImplemented return ErrNotImplemented
} }
func LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
return ErrNotImplemented
}
func LinkSetNoMaster(link Link) error { func LinkSetNoMaster(link Link) error {
return ErrNotImplemented return ErrNotImplemented
} }
@ -152,6 +160,10 @@ func AddrAdd(link Link, addr *Addr) error {
return ErrNotImplemented return ErrNotImplemented
} }
func AddrReplace(link Link, addr *Addr) error {
return ErrNotImplemented
}
func AddrDel(link Link, addr *Addr) error { func AddrDel(link Link, addr *Addr) error {
return ErrNotImplemented return ErrNotImplemented
} }

View File

@ -51,14 +51,14 @@ func SetNetNsIdByPid(pid, nsid int) error {
return pkgHandle.SetNetNsIdByPid(pid, nsid) return pkgHandle.SetNetNsIdByPid(pid, nsid)
} }
// GetNetNsIdByPid looks up the network namespace ID for a given fd. // GetNetNsIdByFd looks up the network namespace ID for a given fd.
// fd must be an open file descriptor to a namespace file. // fd must be an open file descriptor to a namespace file.
// Returns -1 if the namespace does not have an ID set. // Returns -1 if the namespace does not have an ID set.
func (h *Handle) GetNetNsIdByFd(fd int) (int, error) { func (h *Handle) GetNetNsIdByFd(fd int) (int, error) {
return h.getNetNsId(NETNSA_FD, uint32(fd)) return h.getNetNsId(NETNSA_FD, uint32(fd))
} }
// GetNetNsIdByPid looks up the network namespace ID for a given fd. // GetNetNsIdByFd looks up the network namespace ID for a given fd.
// fd must be an open file descriptor to a namespace file. // fd must be an open file descriptor to a namespace file.
// Returns -1 if the namespace does not have an ID set. // Returns -1 if the namespace does not have an ID set.
func GetNetNsIdByFd(fd int) (int, error) { func GetNetNsIdByFd(fd int) (int, error) {

View File

@ -79,11 +79,14 @@ const (
CTA_TUPLE_ORIG = 1 CTA_TUPLE_ORIG = 1
CTA_TUPLE_REPLY = 2 CTA_TUPLE_REPLY = 2
CTA_STATUS = 3 CTA_STATUS = 3
CTA_PROTOINFO = 4
CTA_TIMEOUT = 7 CTA_TIMEOUT = 7
CTA_MARK = 8 CTA_MARK = 8
CTA_COUNTERS_ORIG = 9 CTA_COUNTERS_ORIG = 9
CTA_COUNTERS_REPLY = 10 CTA_COUNTERS_REPLY = 10
CTA_PROTOINFO = 4 CTA_USE = 11
CTA_ID = 12
CTA_TIMESTAMP = 20
) )
// enum ctattr_tuple { // enum ctattr_tuple {
@ -180,6 +183,14 @@ const (
CTA_COUNTERS_BYTES = 2 CTA_COUNTERS_BYTES = 2
) )
// enum CTA TIMESTAMP TLVs
// CTA_TIMESTAMP_START /* 64bit value */
// CTA_TIMESTAMP_STOP /* 64bit value */
const (
CTA_TIMESTAMP_START = 1
CTA_TIMESTAMP_STOP = 2
)
// /* General form of address family dependent message. // /* General form of address family dependent message.
// */ // */
// struct nfgenmsg { // struct nfgenmsg {

View File

@ -0,0 +1,40 @@
package nl
// All the following constants are coming from:
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/devlink.h
const (
GENL_DEVLINK_VERSION = 1
GENL_DEVLINK_NAME = "devlink"
)
const (
DEVLINK_CMD_GET = 1
DEVLINK_CMD_ESWITCH_GET = 29
DEVLINK_CMD_ESWITCH_SET = 30
)
const (
DEVLINK_ATTR_BUS_NAME = 1
DEVLINK_ATTR_DEV_NAME = 2
DEVLINK_ATTR_ESWITCH_MODE = 25
DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
)
const (
DEVLINK_ESWITCH_MODE_LEGACY = 0
DEVLINK_ESWITCH_MODE_SWITCHDEV = 1
)
const (
DEVLINK_ESWITCH_INLINE_MODE_NONE = 0
DEVLINK_ESWITCH_INLINE_MODE_LINK = 1
DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 2
DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 3
)
const (
DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0
DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 1
)

View File

@ -13,7 +13,9 @@ const (
IFLA_INFO_KIND IFLA_INFO_KIND
IFLA_INFO_DATA IFLA_INFO_DATA
IFLA_INFO_XSTATS IFLA_INFO_XSTATS
IFLA_INFO_MAX = IFLA_INFO_XSTATS IFLA_INFO_SLAVE_KIND
IFLA_INFO_SLAVE_DATA
IFLA_INFO_MAX = IFLA_INFO_SLAVE_DATA
) )
const ( const (
@ -87,7 +89,8 @@ const (
const ( const (
IFLA_IPVLAN_UNSPEC = iota IFLA_IPVLAN_UNSPEC = iota
IFLA_IPVLAN_MODE IFLA_IPVLAN_MODE
IFLA_IPVLAN_MAX = IFLA_IPVLAN_MODE IFLA_IPVLAN_FLAG
IFLA_IPVLAN_MAX = IFLA_IPVLAN_FLAG
) )
const ( const (
@ -164,6 +167,8 @@ const (
IFLA_BOND_SLAVE_PERM_HWADDR IFLA_BOND_SLAVE_PERM_HWADDR
IFLA_BOND_SLAVE_QUEUE_ID IFLA_BOND_SLAVE_QUEUE_ID
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE
) )
const ( const (
@ -573,3 +578,33 @@ const (
GTP_ROLE_GGSN = iota GTP_ROLE_GGSN = iota
GTP_ROLE_SGSN GTP_ROLE_SGSN
) )
const (
IFLA_XFRM_UNSPEC = iota
IFLA_XFRM_LINK
IFLA_XFRM_IF_ID
IFLA_XFRM_MAX = iota - 1
)
const (
IFLA_TUN_UNSPEC = iota
IFLA_TUN_OWNER
IFLA_TUN_GROUP
IFLA_TUN_TYPE
IFLA_TUN_PI
IFLA_TUN_VNET_HDR
IFLA_TUN_PERSIST
IFLA_TUN_MULTI_QUEUE
IFLA_TUN_NUM_QUEUES
IFLA_TUN_NUM_DISABLED_QUEUES
IFLA_TUN_MAX = IFLA_TUN_NUM_DISABLED_QUEUES
)
const (
IFLA_IPOIB_UNSPEC = iota
IFLA_IPOIB_PKEY
IFLA_IPOIB_MODE
IFLA_IPOIB_UMCAST
IFLA_IPOIB_MAX = IFLA_IPOIB_UMCAST
)

View File

@ -21,11 +21,13 @@ const (
FAMILY_ALL = unix.AF_UNSPEC FAMILY_ALL = unix.AF_UNSPEC
FAMILY_V4 = unix.AF_INET FAMILY_V4 = unix.AF_INET
FAMILY_V6 = unix.AF_INET6 FAMILY_V6 = unix.AF_INET6
FAMILY_MPLS = AF_MPLS FAMILY_MPLS = unix.AF_MPLS
// Arbitrary set value (greater than default 4k) to allow receiving // Arbitrary set value (greater than default 4k) to allow receiving
// from kernel more verbose messages e.g. for statistics, // from kernel more verbose messages e.g. for statistics,
// tc rules or filters, or other more memory requiring data. // tc rules or filters, or other more memory requiring data.
RECEIVE_BUFFER_SIZE = 65536 RECEIVE_BUFFER_SIZE = 65536
// Kernel netlink pid
PidKernel uint32 = 0
) )
// SupportedNlFamilies contains the list of netlink families this netlink package supports // SupportedNlFamilies contains the list of netlink families this netlink package supports
@ -46,7 +48,7 @@ func GetIPFamily(ip net.IP) int {
var nativeEndian binary.ByteOrder var nativeEndian binary.ByteOrder
// Get native endianness for the system // NativeEndian gets native endianness for the system
func NativeEndian() binary.ByteOrder { func NativeEndian() binary.ByteOrder {
if nativeEndian == nil { if nativeEndian == nil {
var x uint32 = 0x01020304 var x uint32 = 0x01020304
@ -420,10 +422,13 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
done: done:
for { for {
msgs, err := s.Receive() msgs, from, err := s.Receive()
if err != nil { if err != nil {
return nil, err return nil, err
} }
if from.Pid != PidKernel {
return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel)
}
for _, m := range msgs { for _, m := range msgs {
if m.Header.Seq != req.Seq { if m.Header.Seq != req.Seq {
if sharedSocket { if sharedSocket {
@ -432,7 +437,7 @@ done:
return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq) return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq)
} }
if m.Header.Pid != pid { if m.Header.Pid != pid {
return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid) continue
} }
if m.Header.Type == unix.NLMSG_DONE { if m.Header.Type == unix.NLMSG_DONE {
break done break done
@ -617,21 +622,31 @@ func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
return nil return nil
} }
func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) { func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetlink, error) {
fd := int(atomic.LoadInt32(&s.fd)) fd := int(atomic.LoadInt32(&s.fd))
if fd < 0 { if fd < 0 {
return nil, fmt.Errorf("Receive called on a closed socket") return nil, nil, fmt.Errorf("Receive called on a closed socket")
} }
rb := make([]byte, RECEIVE_BUFFER_SIZE) var fromAddr *unix.SockaddrNetlink
nr, _, err := unix.Recvfrom(fd, rb, 0) var rb [RECEIVE_BUFFER_SIZE]byte
nr, from, err := unix.Recvfrom(fd, rb[:], 0)
if err != nil { if err != nil {
return nil, err return nil, nil, err
}
fromAddr, ok := from.(*unix.SockaddrNetlink)
if !ok {
return nil, nil, fmt.Errorf("Error converting to netlink sockaddr")
} }
if nr < unix.NLMSG_HDRLEN { if nr < unix.NLMSG_HDRLEN {
return nil, fmt.Errorf("Got short response from netlink") return nil, nil, fmt.Errorf("Got short response from netlink")
} }
rb = rb[:nr] rb2 := make([]byte, nr)
return syscall.ParseNetlinkMessage(rb) copy(rb2, rb[:nr])
nl, err := syscall.ParseNetlinkMessage(rb2)
if err != nil {
return nil, nil, err
}
return nl, fromAddr, nil
} }
// SetSendTimeout allows to set a send timeout on the socket // SetSendTimeout allows to set a send timeout on the socket

View File

@ -11,6 +11,8 @@ const (
const ( const (
RDMA_NLDEV_CMD_GET = 1 RDMA_NLDEV_CMD_GET = 1
RDMA_NLDEV_CMD_SET = 2 RDMA_NLDEV_CMD_SET = 2
RDMA_NLDEV_CMD_SYS_GET = 6
RDMA_NLDEV_CMD_SYS_SET = 7
) )
const ( const (
@ -28,4 +30,6 @@ const (
RDMA_NLDEV_ATTR_PORT_STATE = 12 RDMA_NLDEV_ATTR_PORT_STATE = 12
RDMA_NLDEV_ATTR_PORT_PHYS_STATE = 13 RDMA_NLDEV_ATTR_PORT_PHYS_STATE = 13
RDMA_NLDEV_ATTR_DEV_NODE_TYPE = 14 RDMA_NLDEV_ATTR_DEV_NODE_TYPE = 14
RDMA_NLDEV_SYS_ATTR_NETNS_MODE = 66
RDMA_NLDEV_NET_NS_FD = 68
) )

View File

@ -42,16 +42,6 @@ const (
TCPDIAG_NOCOOKIE = 0xFFFFFFFF /* TCPDIAG_NOCOOKIE in net/ipv4/tcp_diag.h*/ TCPDIAG_NOCOOKIE = 0xFFFFFFFF /* TCPDIAG_NOCOOKIE in net/ipv4/tcp_diag.h*/
) )
const (
AF_MPLS = 28
)
const (
RTA_NEWDST = 0x13
RTA_ENCAP_TYPE = 0x15
RTA_ENCAP = 0x16
)
// RTA_ENCAP subtype // RTA_ENCAP subtype
const ( const (
MPLS_IPTUNNEL_UNSPEC = iota MPLS_IPTUNNEL_UNSPEC = iota

View File

@ -89,7 +89,10 @@ const (
SizeofTcU32Key = 0x10 SizeofTcU32Key = 0x10
SizeofTcU32Sel = 0x10 // without keys SizeofTcU32Sel = 0x10 // without keys
SizeofTcGen = 0x14 SizeofTcGen = 0x14
SizeofTcConnmark = SizeofTcGen + 0x04
SizeofTcMirred = SizeofTcGen + 0x08 SizeofTcMirred = SizeofTcGen + 0x08
SizeofTcTunnelKey = SizeofTcGen + 0x04
SizeofTcSkbEdit = SizeofTcGen
SizeofTcPolice = 2*SizeofTcRateSpec + 0x20 SizeofTcPolice = 2*SizeofTcRateSpec + 0x20
) )
@ -647,11 +650,47 @@ const (
TCA_BPF_FD TCA_BPF_FD
TCA_BPF_NAME TCA_BPF_NAME
TCA_BPF_FLAGS TCA_BPF_FLAGS
TCA_BPF_MAX = TCA_BPF_FLAGS TCA_BPF_FLAGS_GEN
TCA_BPF_TAG
TCA_BPF_ID
TCA_BPF_MAX = TCA_BPF_ID
) )
type TcBpf TcGen type TcBpf TcGen
const (
TCA_ACT_CONNMARK = 14
)
const (
TCA_CONNMARK_UNSPEC = iota
TCA_CONNMARK_PARMS
TCA_CONNMARK_TM
TCA_CONNMARK_MAX = TCA_CONNMARK_TM
)
// struct tc_connmark {
// tc_gen;
// __u16 zone;
// };
type TcConnmark struct {
TcGen
Zone uint16
}
func (msg *TcConnmark) Len() int {
return SizeofTcConnmark
}
func DeserializeTcConnmark(b []byte) *TcConnmark {
return (*TcConnmark)(unsafe.Pointer(&b[0:SizeofTcConnmark][0]))
}
func (x *TcConnmark) Serialize() []byte {
return (*(*[SizeofTcConnmark]byte)(unsafe.Pointer(x)))[:]
}
const ( const (
TCA_ACT_MIRRED = 8 TCA_ACT_MIRRED = 8
) )
@ -687,6 +726,63 @@ func (x *TcMirred) Serialize() []byte {
return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:] return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:]
} }
const (
TCA_TUNNEL_KEY_UNSPEC = iota
TCA_TUNNEL_KEY_TM
TCA_TUNNEL_KEY_PARMS
TCA_TUNNEL_KEY_ENC_IPV4_SRC
TCA_TUNNEL_KEY_ENC_IPV4_DST
TCA_TUNNEL_KEY_ENC_IPV6_SRC
TCA_TUNNEL_KEY_ENC_IPV6_DST
TCA_TUNNEL_KEY_ENC_KEY_ID
TCA_TUNNEL_KEY_MAX = TCA_TUNNEL_KEY_ENC_KEY_ID
)
type TcTunnelKey struct {
TcGen
Action int32
}
func (x *TcTunnelKey) Len() int {
return SizeofTcTunnelKey
}
func DeserializeTunnelKey(b []byte) *TcTunnelKey {
return (*TcTunnelKey)(unsafe.Pointer(&b[0:SizeofTcTunnelKey][0]))
}
func (x *TcTunnelKey) Serialize() []byte {
return (*(*[SizeofTcTunnelKey]byte)(unsafe.Pointer(x)))[:]
}
const (
TCA_SKBEDIT_UNSPEC = iota
TCA_SKBEDIT_TM
TCA_SKBEDIT_PARMS
TCA_SKBEDIT_PRIORITY
TCA_SKBEDIT_QUEUE_MAPPING
TCA_SKBEDIT_MARK
TCA_SKBEDIT_PAD
TCA_SKBEDIT_PTYPE
TCA_SKBEDIT_MAX = TCA_SKBEDIT_MARK
)
type TcSkbEdit struct {
TcGen
}
func (x *TcSkbEdit) Len() int {
return SizeofTcSkbEdit
}
func DeserializeSkbEdit(b []byte) *TcSkbEdit {
return (*TcSkbEdit)(unsafe.Pointer(&b[0:SizeofTcSkbEdit][0]))
}
func (x *TcSkbEdit) Serialize() []byte {
return (*(*[SizeofTcSkbEdit]byte)(unsafe.Pointer(x)))[:]
}
// struct tc_police { // struct tc_police {
// __u32 index; // __u32 index;
// int action; // int action;

View File

@ -50,34 +50,44 @@ const (
// Attribute types // Attribute types
const ( const (
/* Netlink message attributes. */ /* Netlink message attributes. */
XFRMA_UNSPEC = 0x00 XFRMA_UNSPEC = iota
XFRMA_ALG_AUTH = 0x01 /* struct xfrm_algo */ XFRMA_ALG_AUTH /* struct xfrm_algo */
XFRMA_ALG_CRYPT = 0x02 /* struct xfrm_algo */ XFRMA_ALG_CRYPT /* struct xfrm_algo */
XFRMA_ALG_COMP = 0x03 /* struct xfrm_algo */ XFRMA_ALG_COMP /* struct xfrm_algo */
XFRMA_ENCAP = 0x04 /* struct xfrm_algo + struct xfrm_encap_tmpl */ XFRMA_ENCAP /* struct xfrm_algo + struct xfrm_encap_tmpl */
XFRMA_TMPL = 0x05 /* 1 or more struct xfrm_user_tmpl */ XFRMA_TMPL /* 1 or more struct xfrm_user_tmpl */
XFRMA_SA = 0x06 /* struct xfrm_usersa_info */ XFRMA_SA /* struct xfrm_usersa_info */
XFRMA_POLICY = 0x07 /* struct xfrm_userpolicy_info */ XFRMA_POLICY /* struct xfrm_userpolicy_info */
XFRMA_SEC_CTX = 0x08 /* struct xfrm_sec_ctx */ XFRMA_SEC_CTX /* struct xfrm_sec_ctx */
XFRMA_LTIME_VAL = 0x09 XFRMA_LTIME_VAL
XFRMA_REPLAY_VAL = 0x0a XFRMA_REPLAY_VAL
XFRMA_REPLAY_THRESH = 0x0b XFRMA_REPLAY_THRESH
XFRMA_ETIMER_THRESH = 0x0c XFRMA_ETIMER_THRESH
XFRMA_SRCADDR = 0x0d /* xfrm_address_t */ XFRMA_SRCADDR /* xfrm_address_t */
XFRMA_COADDR = 0x0e /* xfrm_address_t */ XFRMA_COADDR /* xfrm_address_t */
XFRMA_LASTUSED = 0x0f /* unsigned long */ XFRMA_LASTUSED /* unsigned long */
XFRMA_POLICY_TYPE = 0x10 /* struct xfrm_userpolicy_type */ XFRMA_POLICY_TYPE /* struct xfrm_userpolicy_type */
XFRMA_MIGRATE = 0x11 XFRMA_MIGRATE
XFRMA_ALG_AEAD = 0x12 /* struct xfrm_algo_aead */ XFRMA_ALG_AEAD /* struct xfrm_algo_aead */
XFRMA_KMADDRESS = 0x13 /* struct xfrm_user_kmaddress */ XFRMA_KMADDRESS /* struct xfrm_user_kmaddress */
XFRMA_ALG_AUTH_TRUNC = 0x14 /* struct xfrm_algo_auth */ XFRMA_ALG_AUTH_TRUNC /* struct xfrm_algo_auth */
XFRMA_MARK = 0x15 /* struct xfrm_mark */ XFRMA_MARK /* struct xfrm_mark */
XFRMA_TFCPAD = 0x16 /* __u32 */ XFRMA_TFCPAD /* __u32 */
XFRMA_REPLAY_ESN_VAL = 0x17 /* struct xfrm_replay_esn */ XFRMA_REPLAY_ESN_VAL /* struct xfrm_replay_esn */
XFRMA_SA_EXTRA_FLAGS = 0x18 /* __u32 */ XFRMA_SA_EXTRA_FLAGS /* __u32 */
XFRMA_MAX = 0x18 XFRMA_PROTO /* __u8 */
XFRMA_ADDRESS_FILTER /* struct xfrm_address_filter */
XFRMA_PAD
XFRMA_OFFLOAD_DEV /* struct xfrm_state_offload */
XFRMA_SET_MARK /* __u32 */
XFRMA_SET_MARK_MASK /* __u32 */
XFRMA_IF_ID /* __u32 */
XFRMA_MAX = iota - 1
) )
const XFRMA_OUTPUT_MARK = XFRMA_SET_MARK
const ( const (
SizeofXfrmAddress = 0x10 SizeofXfrmAddress = 0x10
SizeofXfrmSelector = 0x38 SizeofXfrmSelector = 0x38

View File

@ -285,7 +285,7 @@ type Fq struct {
func (fq *Fq) String() string { func (fq *Fq) String() string {
return fmt.Sprintf( return fmt.Sprintf(
"{PacketLimit: %v, FlowPacketLimit: %v, Quantum: %v, InitalQuantum: %v, Pacing: %v, FlowDefaultRate: %v, FlowMaxRate: %v, Buckets: %v, FlowRefillDelay: %v, LowRateTreshold: %v}", "{PacketLimit: %v, FlowPacketLimit: %v, Quantum: %v, InitialQuantum: %v, Pacing: %v, FlowDefaultRate: %v, FlowMaxRate: %v, Buckets: %v, FlowRefillDelay: %v, LowRateThreshold: %v}",
fq.PacketLimit, fq.FlowPacketLimit, fq.Quantum, fq.InitialQuantum, fq.Pacing, fq.FlowDefaultRate, fq.FlowMaxRate, fq.Buckets, fq.FlowRefillDelay, fq.LowRateThreshold, fq.PacketLimit, fq.FlowPacketLimit, fq.Quantum, fq.InitialQuantum, fq.Pacing, fq.FlowDefaultRate, fq.FlowMaxRate, fq.Buckets, fq.FlowRefillDelay, fq.LowRateThreshold,
) )
} }

View File

@ -143,3 +143,122 @@ func (h *Handle) RdmaLinkSetName(link *RdmaLink, name string) error {
return execRdmaSetLink(req) return execRdmaSetLink(req)
} }
func netnsModeToString(mode uint8) string {
switch mode {
case 0:
return "exclusive"
case 1:
return "shared"
default:
return "unknown"
}
}
func executeOneGetRdmaNetnsMode(data []byte) (string, error) {
reader := bytes.NewReader(data)
for reader.Len() >= 4 {
_, attrType, len, value := parseNfAttrTLV(reader)
switch attrType {
case nl.RDMA_NLDEV_SYS_ATTR_NETNS_MODE:
var mode uint8
r := bytes.NewReader(value)
binary.Read(r, nl.NativeEndian(), &mode)
return netnsModeToString(mode), nil
}
if (len % 4) != 0 {
// Skip pad bytes
reader.Seek(int64(4-(len%4)), seekCurrent)
}
}
return "", fmt.Errorf("Invalid netns mode")
}
// RdmaSystemGetNetnsMode gets the net namespace mode for RDMA subsystem
// Returns mode string and error status as nil on success or returns error
// otherwise.
// Equivalent to: `rdma system show netns'
func RdmaSystemGetNetnsMode() (string, error) {
return pkgHandle.RdmaSystemGetNetnsMode()
}
// RdmaSystemGetNetnsMode gets the net namespace mode for RDMA subsystem
// Returns mode string and error status as nil on success or returns error
// otherwise.
// Equivalent to: `rdma system show netns'
func (h *Handle) RdmaSystemGetNetnsMode() (string, error) {
proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SYS_GET)
req := h.newNetlinkRequest(proto, unix.NLM_F_ACK)
msgs, err := req.Execute(unix.NETLINK_RDMA, 0)
if err != nil {
return "", err
}
if len(msgs) == 0 {
return "", fmt.Errorf("No valid response from kernel")
}
return executeOneGetRdmaNetnsMode(msgs[0])
}
func netnsModeStringToUint8(mode string) (uint8, error) {
switch mode {
case "exclusive":
return 0, nil
case "shared":
return 1, nil
default:
return 0, fmt.Errorf("Invalid mode; %q", mode)
}
}
// RdmaSystemSetNetnsMode sets the net namespace mode for RDMA subsystem
// Returns nil on success or appropriate error code.
// Equivalent to: `rdma system set netns { shared | exclusive }'
func RdmaSystemSetNetnsMode(NewMode string) error {
return pkgHandle.RdmaSystemSetNetnsMode(NewMode)
}
// RdmaSystemSetNetnsMode sets the net namespace mode for RDMA subsystem
// Returns nil on success or appropriate error code.
// Equivalent to: `rdma system set netns { shared | exclusive }'
func (h *Handle) RdmaSystemSetNetnsMode(NewMode string) error {
value, err := netnsModeStringToUint8(NewMode)
if err != nil {
return err
}
proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SYS_SET)
req := h.newNetlinkRequest(proto, unix.NLM_F_ACK)
data := nl.NewRtAttr(nl.RDMA_NLDEV_SYS_ATTR_NETNS_MODE, []byte{value})
req.AddData(data)
_, err = req.Execute(unix.NETLINK_RDMA, 0)
return err
}
// RdmaLinkSetNsFd puts the RDMA device into a new network namespace. The
// fd must be an open file descriptor to a network namespace.
// Similar to: `rdma dev set $dev netns $ns`
func RdmaLinkSetNsFd(link *RdmaLink, fd uint32) error {
return pkgHandle.RdmaLinkSetNsFd(link, fd)
}
// RdmaLinkSetNsFd puts the RDMA device into a new network namespace. The
// fd must be an open file descriptor to a network namespace.
// Similar to: `rdma dev set $dev netns $ns`
func (h *Handle) RdmaLinkSetNsFd(link *RdmaLink, fd uint32) error {
proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SET)
req := h.newNetlinkRequest(proto, unix.NLM_F_ACK)
data := nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_INDEX,
nl.Uint32Attr(link.Attrs.Index))
req.AddData(data)
data = nl.NewRtAttr(nl.RDMA_NLDEV_NET_NS_FD, nl.Uint32Attr(fd))
req.AddData(data)
return execRdmaSetLink(req)
}

View File

@ -261,7 +261,7 @@ func (e *SEG6Encap) Equal(x Encap) bool {
return true return true
} }
// SEG6Local definitions // SEG6LocalEncap definitions
type SEG6LocalEncap struct { type SEG6LocalEncap struct {
Flags [nl.SEG6_LOCAL_MAX]bool Flags [nl.SEG6_LOCAL_MAX]bool
Action int Action int
@ -519,18 +519,18 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
if err != nil { if err != nil {
return err return err
} }
rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_NEWDST, buf)) rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_NEWDST, buf))
} }
if route.Encap != nil { if route.Encap != nil {
buf := make([]byte, 2) buf := make([]byte, 2)
native.PutUint16(buf, uint16(route.Encap.Type())) native.PutUint16(buf, uint16(route.Encap.Type()))
rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP_TYPE, buf)) rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf))
buf, err := route.Encap.Encode() buf, err := route.Encap.Encode()
if err != nil { if err != nil {
return err return err
} }
rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP, buf)) rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP, buf))
} }
if route.Src != nil { if route.Src != nil {
@ -594,17 +594,17 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
if err != nil { if err != nil {
return err return err
} }
children = append(children, nl.NewRtAttr(nl.RTA_NEWDST, buf)) children = append(children, nl.NewRtAttr(unix.RTA_NEWDST, buf))
} }
if nh.Encap != nil { if nh.Encap != nil {
buf := make([]byte, 2) buf := make([]byte, 2)
native.PutUint16(buf, uint16(nh.Encap.Type())) native.PutUint16(buf, uint16(nh.Encap.Type()))
rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP_TYPE, buf)) children = append(children, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf))
buf, err := nh.Encap.Encode() buf, err := nh.Encap.Encode()
if err != nil { if err != nil {
return err return err
} }
children = append(children, nl.NewRtAttr(nl.RTA_ENCAP, buf)) children = append(children, nl.NewRtAttr(unix.RTA_ENCAP, buf))
} }
rtnh.Children = children rtnh.Children = children
buf = append(buf, rtnh.Serialize()...) buf = append(buf, rtnh.Serialize()...)
@ -839,7 +839,7 @@ func deserializeRoute(m []byte) (Route, error) {
switch attr.Attr.Type { switch attr.Attr.Type {
case unix.RTA_GATEWAY: case unix.RTA_GATEWAY:
info.Gw = net.IP(attr.Value) info.Gw = net.IP(attr.Value)
case nl.RTA_NEWDST: case unix.RTA_NEWDST:
var d Destination var d Destination
switch msg.Family { switch msg.Family {
case nl.FAMILY_MPLS: case nl.FAMILY_MPLS:
@ -849,9 +849,9 @@ func deserializeRoute(m []byte) (Route, error) {
return nil, nil, err return nil, nil, err
} }
info.NewDst = d info.NewDst = d
case nl.RTA_ENCAP_TYPE: case unix.RTA_ENCAP_TYPE:
encapType = attr encapType = attr
case nl.RTA_ENCAP: case unix.RTA_ENCAP:
encap = attr encap = attr
} }
} }
@ -880,7 +880,7 @@ func deserializeRoute(m []byte) (Route, error) {
route.MultiPath = append(route.MultiPath, info) route.MultiPath = append(route.MultiPath, info)
rest = buf rest = buf
} }
case nl.RTA_NEWDST: case unix.RTA_NEWDST:
var d Destination var d Destination
switch msg.Family { switch msg.Family {
case nl.FAMILY_MPLS: case nl.FAMILY_MPLS:
@ -890,9 +890,9 @@ func deserializeRoute(m []byte) (Route, error) {
return route, err return route, err
} }
route.NewDst = d route.NewDst = d
case nl.RTA_ENCAP_TYPE: case unix.RTA_ENCAP_TYPE:
encapType = attr encapType = attr
case nl.RTA_ENCAP: case unix.RTA_ENCAP:
encap = attr encap = attr
case unix.RTA_METRICS: case unix.RTA_METRICS:
metrics, err := nl.ParseRouteAttr(attr.Value) metrics, err := nl.ParseRouteAttr(attr.Value)
@ -1037,13 +1037,19 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
go func() { go func() {
defer close(ch) defer close(ch)
for { for {
msgs, err := s.Receive() msgs, from, err := s.Receive()
if err != nil { if err != nil {
if cberr != nil { if cberr != nil {
cberr(err) cberr(err)
} }
return return
} }
if from.Pid != nl.PidKernel {
if cberr != nil {
cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel))
}
continue
}
for _, m := range msgs { for _, m := range msgs {
if m.Header.Type == unix.NLMSG_DONE { if m.Header.Type == unix.NLMSG_DONE {
continue continue

View File

@ -144,7 +144,7 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName))) req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName)))
} }
if rule.Goto >= 0 { if rule.Goto >= 0 {
msg.Type = nl.FR_ACT_NOP msg.Type = nl.FR_ACT_GOTO
b := make([]byte, 4) b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Goto)) native.PutUint32(b, uint32(rule.Goto))
req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b)) req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))

View File

@ -141,10 +141,13 @@ func SocketGet(local, remote net.Addr) (*Socket, error) {
}, },
}) })
s.Send(req) s.Send(req)
msgs, err := s.Receive() msgs, from, err := s.Receive()
if err != nil { if err != nil {
return nil, err return nil, err
} }
if from.Pid != nl.PidKernel {
return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
}
if len(msgs) == 0 { if len(msgs) == 0 {
return nil, errors.New("no message nor error from netlink") return nil, errors.New("no message nor error from netlink")
} }

View File

@ -54,11 +54,15 @@ func XfrmMonitor(ch chan<- XfrmMsg, done <-chan struct{}, errorChan chan<- error
go func() { go func() {
defer close(ch) defer close(ch)
for { for {
msgs, err := s.Receive() msgs, from, err := s.Receive()
if err != nil { if err != nil {
errorChan <- err errorChan <- err
return return
} }
if from.Pid != nl.PidKernel {
errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
return
}
for _, m := range msgs { for _, m := range msgs {
switch m.Header.Type { switch m.Header.Type {
case nl.XFRM_MSG_EXPIRE: case nl.XFRM_MSG_EXPIRE:

View File

@ -85,11 +85,12 @@ type XfrmPolicy struct {
Index int Index int
Action PolicyAction Action PolicyAction
Ifindex int Ifindex int
Ifid int
Mark *XfrmMark Mark *XfrmMark
Tmpls []XfrmPolicyTmpl Tmpls []XfrmPolicyTmpl
} }
func (p XfrmPolicy) String() string { func (p XfrmPolicy) String() string {
return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Action: %s, Ifindex: %d, Mark: %s, Tmpls: %s}", return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Action: %s, Ifindex: %d, Ifid: %d, Mark: %s, Tmpls: %s}",
p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Action, p.Ifindex, p.Mark, p.Tmpls) p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Action, p.Ifindex, p.Ifid, p.Mark, p.Tmpls)
} }

View File

@ -92,6 +92,9 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
req.AddData(out) req.AddData(out)
} }
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid)))
req.AddData(ifId)
_, err := req.Execute(unix.NETLINK_XFRM, 0) _, err := req.Execute(unix.NETLINK_XFRM, 0)
return err return err
} }
@ -185,6 +188,9 @@ func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPo
req.AddData(out) req.AddData(out)
} }
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid)))
req.AddData(ifId)
resType := nl.XFRM_MSG_NEWPOLICY resType := nl.XFRM_MSG_NEWPOLICY
if nlProto == nl.XFRM_MSG_DELPOLICY { if nlProto == nl.XFRM_MSG_DELPOLICY {
resType = 0 resType = 0
@ -248,6 +254,8 @@ func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
policy.Mark = new(XfrmMark) policy.Mark = new(XfrmMark)
policy.Mark.Value = mark.Value policy.Mark.Value = mark.Value
policy.Mark.Mask = mark.Mask policy.Mark.Mask = mark.Mask
case nl.XFRMA_IF_ID:
policy.Ifid = int(native.Uint32(attr.Value))
} }
} }

View File

@ -94,6 +94,8 @@ type XfrmState struct {
Limits XfrmStateLimits Limits XfrmStateLimits
Statistics XfrmStateStats Statistics XfrmStateStats
Mark *XfrmMark Mark *XfrmMark
OutputMark int
Ifid int
Auth *XfrmStateAlgo Auth *XfrmStateAlgo
Crypt *XfrmStateAlgo Crypt *XfrmStateAlgo
Aead *XfrmStateAlgo Aead *XfrmStateAlgo
@ -102,8 +104,8 @@ type XfrmState struct {
} }
func (sa XfrmState) String() string { func (sa XfrmState) String() string {
return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t", return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %d, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t",
sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN) sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.Ifid, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN)
} }
func (sa XfrmState) Print(stats bool) string { func (sa XfrmState) Print(stats bool) string {
if !stats { if !stats {

View File

@ -158,6 +158,13 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow)) out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow))
req.AddData(out) req.AddData(out)
} }
if state.OutputMark != 0 {
out := nl.NewRtAttr(nl.XFRMA_OUTPUT_MARK, nl.Uint32Attr(uint32(state.OutputMark)))
req.AddData(out)
}
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid)))
req.AddData(ifId)
_, err := req.Execute(unix.NETLINK_XFRM, 0) _, err := req.Execute(unix.NETLINK_XFRM, 0)
return err return err
@ -270,6 +277,9 @@ func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState
req.AddData(out) req.AddData(out)
} }
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid)))
req.AddData(ifId)
resType := nl.XFRM_MSG_NEWSA resType := nl.XFRM_MSG_NEWSA
if nlProto == nl.XFRM_MSG_DELSA { if nlProto == nl.XFRM_MSG_DELSA {
resType = 0 resType = 0
@ -367,6 +377,10 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
state.Mark = new(XfrmMark) state.Mark = new(XfrmMark)
state.Mark.Value = mark.Value state.Mark.Value = mark.Value
state.Mark.Mask = mark.Mask state.Mark.Mask = mark.Mask
case nl.XFRMA_OUTPUT_MARK:
state.OutputMark = int(native.Uint32(attr.Value))
case nl.XFRMA_IF_ID:
state.Ifid = int(native.Uint32(attr.Value))
} }
} }

View File

@ -37,7 +37,6 @@ func main() {
// Create a new network namespace // Create a new network namespace
newns, _ := netns.New() newns, _ := netns.New()
netns.Set(newns)
defer newns.Close() defer newns.Close()
// Do something with the network namespace // Do something with the network namespace

5
vendor/github.com/vishvananda/netns/go.mod generated vendored Normal file
View File

@ -0,0 +1,5 @@
module github.com/vishvananda/netns
go 1.12
require golang.org/x/sys v0.0.0-20200217220822-9197077df867

2
vendor/github.com/vishvananda/netns/go.sum generated vendored Normal file
View File

@ -0,0 +1,2 @@
golang.org/x/sys v0.0.0-20200217220822-9197077df867 h1:JoRuNIf+rpHl+VhScRQQvzbHed86tKkqwPMV34T8myw=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -10,7 +10,8 @@ package netns
import ( import (
"fmt" "fmt"
"syscall"
"golang.org/x/sys/unix"
) )
// NsHandle is a handle to a network namespace. It can be cast directly // NsHandle is a handle to a network namespace. It can be cast directly
@ -24,11 +25,11 @@ func (ns NsHandle) Equal(other NsHandle) bool {
if ns == other { if ns == other {
return true return true
} }
var s1, s2 syscall.Stat_t var s1, s2 unix.Stat_t
if err := syscall.Fstat(int(ns), &s1); err != nil { if err := unix.Fstat(int(ns), &s1); err != nil {
return false return false
} }
if err := syscall.Fstat(int(other), &s2); err != nil { if err := unix.Fstat(int(other), &s2); err != nil {
return false return false
} }
return (s1.Dev == s2.Dev) && (s1.Ino == s2.Ino) return (s1.Dev == s2.Dev) && (s1.Ino == s2.Ino)
@ -36,11 +37,11 @@ func (ns NsHandle) Equal(other NsHandle) bool {
// String shows the file descriptor number and its dev and inode. // String shows the file descriptor number and its dev and inode.
func (ns NsHandle) String() string { func (ns NsHandle) String() string {
var s syscall.Stat_t
if ns == -1 { if ns == -1 {
return "NS(None)" return "NS(None)"
} }
if err := syscall.Fstat(int(ns), &s); err != nil { var s unix.Stat_t
if err := unix.Fstat(int(ns), &s); err != nil {
return fmt.Sprintf("NS(%d: unknown)", ns) return fmt.Sprintf("NS(%d: unknown)", ns)
} }
return fmt.Sprintf("NS(%d: %d, %d)", ns, s.Dev, s.Ino) return fmt.Sprintf("NS(%d: %d, %d)", ns, s.Dev, s.Ino)
@ -49,11 +50,11 @@ func (ns NsHandle) String() string {
// UniqueId returns a string which uniquely identifies the namespace // UniqueId returns a string which uniquely identifies the namespace
// associated with the network handle. // associated with the network handle.
func (ns NsHandle) UniqueId() string { func (ns NsHandle) UniqueId() string {
var s syscall.Stat_t
if ns == -1 { if ns == -1 {
return "NS(none)" return "NS(none)"
} }
if err := syscall.Fstat(int(ns), &s); err != nil { var s unix.Stat_t
if err := unix.Fstat(int(ns), &s); err != nil {
return "NS(unknown)" return "NS(unknown)"
} }
return fmt.Sprintf("NS(%d:%d)", s.Dev, s.Ino) return fmt.Sprintf("NS(%d:%d)", s.Dev, s.Ino)
@ -67,7 +68,7 @@ func (ns NsHandle) IsOpen() bool {
// Close closes the NsHandle and resets its file descriptor to -1. // Close closes the NsHandle and resets its file descriptor to -1.
// It is not safe to use an NsHandle after Close() is called. // It is not safe to use an NsHandle after Close() is called.
func (ns *NsHandle) Close() error { func (ns *NsHandle) Close() error {
if err := syscall.Close(int(*ns)); err != nil { if err := unix.Close(int(*ns)); err != nil {
return err return err
} }
(*ns) = -1 (*ns) = -1

View File

@ -6,25 +6,14 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path"
"path/filepath" "path/filepath"
"runtime"
"strconv" "strconv"
"strings" "strings"
"syscall" "syscall"
)
// SYS_SETNS syscall allows changing the namespace of the current process. "golang.org/x/sys/unix"
var SYS_SETNS = map[string]uintptr{ )
"386": 346,
"amd64": 308,
"arm64": 268,
"arm": 375,
"mips": 4344,
"mipsle": 4344,
"ppc64": 350,
"ppc64le": 350,
"s390x": 339,
}[runtime.GOARCH]
// Deprecated: use syscall pkg instead (go >= 1.5 needed). // Deprecated: use syscall pkg instead (go >= 1.5 needed).
const ( const (
@ -34,16 +23,13 @@ const (
CLONE_NEWPID = 0x20000000 /* New pid namespace */ CLONE_NEWPID = 0x20000000 /* New pid namespace */
CLONE_NEWNET = 0x40000000 /* New network namespace */ CLONE_NEWNET = 0x40000000 /* New network namespace */
CLONE_IO = 0x80000000 /* Get io context */ CLONE_IO = 0x80000000 /* Get io context */
bindMountPath = "/run/netns" /* Bind mount path for named netns */
) )
// Setns sets namespace using syscall. Note that this should be a method // Setns sets namespace using syscall. Note that this should be a method
// in syscall but it has not been added. // in syscall but it has not been added.
func Setns(ns NsHandle, nstype int) (err error) { func Setns(ns NsHandle, nstype int) (err error) {
_, _, e1 := syscall.Syscall(SYS_SETNS, uintptr(ns), uintptr(nstype), 0) return unix.Setns(int(ns), nstype)
if e1 != 0 {
err = e1
}
return
} }
// Set sets the current network namespace to the namespace represented // Set sets the current network namespace to the namespace represented
@ -52,23 +38,67 @@ func Set(ns NsHandle) (err error) {
return Setns(ns, CLONE_NEWNET) return Setns(ns, CLONE_NEWNET)
} }
// New creates a new network namespace and returns a handle to it. // New creates a new network namespace, sets it as current and returns
// a handle to it.
func New() (ns NsHandle, err error) { func New() (ns NsHandle, err error) {
if err := syscall.Unshare(CLONE_NEWNET); err != nil { if err := unix.Unshare(CLONE_NEWNET); err != nil {
return -1, err return -1, err
} }
return Get() return Get()
} }
// NewNamed creates a new named network namespace and returns a handle to it
func NewNamed(name string) (NsHandle, error) {
if _, err := os.Stat(bindMountPath); os.IsNotExist(err) {
err = os.MkdirAll(bindMountPath, 0755)
if err != nil {
return None(), err
}
}
newNs, err := New()
if err != nil {
return None(), err
}
namedPath := path.Join(bindMountPath, name)
f, err := os.OpenFile(namedPath, os.O_CREATE|os.O_EXCL, 0444)
if err != nil {
return None(), err
}
f.Close()
nsPath := fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), syscall.Gettid())
err = syscall.Mount(nsPath, namedPath, "bind", syscall.MS_BIND, "")
if err != nil {
return None(), err
}
return newNs, nil
}
// DeleteNamed deletes a named network namespace
func DeleteNamed(name string) error {
namedPath := path.Join(bindMountPath, name)
err := syscall.Unmount(namedPath, syscall.MNT_DETACH)
if err != nil {
return err
}
return os.Remove(namedPath)
}
// Get gets a handle to the current threads network namespace. // Get gets a handle to the current threads network namespace.
func Get() (NsHandle, error) { func Get() (NsHandle, error) {
return GetFromThread(os.Getpid(), syscall.Gettid()) return GetFromThread(os.Getpid(), unix.Gettid())
} }
// GetFromPath gets a handle to a network namespace // GetFromPath gets a handle to a network namespace
// identified by the path // identified by the path
func GetFromPath(path string) (NsHandle, error) { func GetFromPath(path string) (NsHandle, error) {
fd, err := syscall.Open(path, syscall.O_RDONLY, 0) fd, err := unix.Open(path, unix.O_RDONLY|unix.O_CLOEXEC, 0)
if err != nil { if err != nil {
return -1, err return -1, err
} }

View File

@ -0,0 +1,30 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package unsafeheader contains header declarations for the Go runtime's
// slice and string implementations.
//
// This package allows x/sys to use types equivalent to
// reflect.SliceHeader and reflect.StringHeader without introducing
// a dependency on the (relatively heavy) "reflect" package.
package unsafeheader
import (
"unsafe"
)
// Slice is the runtime representation of a slice.
// It cannot be used safely or portably and its representation may change in a later release.
type Slice struct {
Data unsafe.Pointer
Len int
Cap int
}
// String is the runtime representation of a string.
// It cannot be used safely or portably and its representation may change in a later release.
type String struct {
Data unsafe.Pointer
Len int
}

View File

@ -89,7 +89,7 @@ constants.
Adding new syscall numbers is mostly done by running the build on a sufficiently Adding new syscall numbers is mostly done by running the build on a sufficiently
new installation of the target OS (or updating the source checkouts for the new installation of the target OS (or updating the source checkouts for the
new build system). However, depending on the OS, you make need to update the new build system). However, depending on the OS, you may need to update the
parsing in mksysnum. parsing in mksysnum.
### mksyscall.go ### mksyscall.go
@ -149,10 +149,21 @@ To add a constant, add the header that includes it to the appropriate variable.
Then, edit the regex (if necessary) to match the desired constant. Avoid making Then, edit the regex (if necessary) to match the desired constant. Avoid making
the regex too broad to avoid matching unintended constants. the regex too broad to avoid matching unintended constants.
### mkmerge.go
This program is used to extract duplicate const, func, and type declarations
from the generated architecture-specific files listed below, and merge these
into a common file for each OS.
The merge is performed in the following steps:
1. Construct the set of common code that is idential in all architecture-specific files.
2. Write this common code to the merged file.
3. Remove the common code from all architecture-specific files.
## Generated files ## Generated files
### `zerror_${GOOS}_${GOARCH}.go` ### `zerrors_${GOOS}_${GOARCH}.go`
A file containing all of the system's generated error numbers, error strings, A file containing all of the system's generated error numbers, error strings,
signal numbers, and constants. Generated by `mkerrors.sh` (see above). signal numbers, and constants. Generated by `mkerrors.sh` (see above).

View File

@ -7,6 +7,7 @@
package unix package unix
import ( import (
"math/bits"
"unsafe" "unsafe"
) )
@ -79,46 +80,7 @@ func (s *CPUSet) IsSet(cpu int) bool {
func (s *CPUSet) Count() int { func (s *CPUSet) Count() int {
c := 0 c := 0
for _, b := range s { for _, b := range s {
c += onesCount64(uint64(b)) c += bits.OnesCount64(uint64(b))
} }
return c return c
} }
// onesCount64 is a copy of Go 1.9's math/bits.OnesCount64.
// Once this package can require Go 1.9, we can delete this
// and update the caller to use bits.OnesCount64.
func onesCount64(x uint64) int {
const m0 = 0x5555555555555555 // 01010101 ...
const m1 = 0x3333333333333333 // 00110011 ...
const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ...
const m3 = 0x00ff00ff00ff00ff // etc.
const m4 = 0x0000ffff0000ffff
// Implementation: Parallel summing of adjacent bits.
// See "Hacker's Delight", Chap. 5: Counting Bits.
// The following pattern shows the general approach:
//
// x = x>>1&(m0&m) + x&(m0&m)
// x = x>>2&(m1&m) + x&(m1&m)
// x = x>>4&(m2&m) + x&(m2&m)
// x = x>>8&(m3&m) + x&(m3&m)
// x = x>>16&(m4&m) + x&(m4&m)
// x = x>>32&(m5&m) + x&(m5&m)
// return int(x)
//
// Masking (& operations) can be left away when there's no
// danger that a field's sum will carry over into the next
// field: Since the result cannot be > 64, 8 bits is enough
// and we can ignore the masks for the shifts by 8 and up.
// Per "Hacker's Delight", the first line can be simplified
// more, but it saves at best one instruction, so we leave
// it alone for clarity.
const m = 1<<64 - 1
x = x>>1&(m0&m) + x&(m0&m)
x = x>>2&(m1&m) + x&(m1&m)
x = (x>>4 + x) & (m2 & m)
x += x >> 8
x += x >> 16
x += x >> 32
return int(x) & (1<<7 - 1)
}

View File

@ -23,10 +23,6 @@ TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
MOV a1+8(FP), A0 MOV a1+8(FP), A0
MOV a2+16(FP), A1 MOV a2+16(FP), A1
MOV a3+24(FP), A2 MOV a3+24(FP), A2
MOV $0, A3
MOV $0, A4
MOV $0, A5
MOV $0, A6
MOV trap+0(FP), A7 // syscall entry MOV trap+0(FP), A7 // syscall entry
ECALL ECALL
MOV A0, r1+32(FP) // r1 MOV A0, r1+32(FP) // r1
@ -44,9 +40,6 @@ TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
MOV a1+8(FP), A0 MOV a1+8(FP), A0
MOV a2+16(FP), A1 MOV a2+16(FP), A1
MOV a3+24(FP), A2 MOV a3+24(FP), A2
MOV ZERO, A3
MOV ZERO, A4
MOV ZERO, A5
MOV trap+0(FP), A7 // syscall entry MOV trap+0(FP), A7 // syscall entry
ECALL ECALL
MOV A0, r1+32(FP) MOV A0, r1+32(FP)

29
vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s generated vendored Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo
#include "textflag.h"
//
// System call support for mips64, OpenBSD
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-56
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
JMP syscall·Syscall6(SB)
TEXT ·Syscall9(SB),NOSPLIT,$0-104
JMP syscall·Syscall9(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
JMP syscall·RawSyscall6(SB)

View File

@ -23,6 +23,7 @@ const (
HCI_CHANNEL_USER = 1 HCI_CHANNEL_USER = 1
HCI_CHANNEL_MONITOR = 2 HCI_CHANNEL_MONITOR = 2
HCI_CHANNEL_CONTROL = 3 HCI_CHANNEL_CONTROL = 3
HCI_CHANNEL_LOGGING = 4
) )
// Socketoption Level // Socketoption Level

View File

@ -2,16 +2,101 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package unix package unix
import "syscall" import "unsafe"
// readInt returns the size-bytes unsigned integer in native byte order at offset off.
func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
if len(b) < int(off+size) {
return 0, false
}
if isBigEndian {
return readIntBE(b[off:], size), true
}
return readIntLE(b[off:], size), true
}
func readIntBE(b []byte, size uintptr) uint64 {
switch size {
case 1:
return uint64(b[0])
case 2:
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[1]) | uint64(b[0])<<8
case 4:
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24
case 8:
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
default:
panic("syscall: readInt with unsupported size")
}
}
func readIntLE(b []byte, size uintptr) uint64 {
switch size {
case 1:
return uint64(b[0])
case 2:
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8
case 4:
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
case 8:
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
default:
panic("syscall: readInt with unsupported size")
}
}
// ParseDirent parses up to max directory entries in buf, // ParseDirent parses up to max directory entries in buf,
// appending the names to names. It returns the number of // appending the names to names. It returns the number of
// bytes consumed from buf, the number of entries added // bytes consumed from buf, the number of entries added
// to names, and the new names slice. // to names, and the new names slice.
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) { func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
return syscall.ParseDirent(buf, max, names) origlen := len(buf)
count = 0
for max != 0 && len(buf) > 0 {
reclen, ok := direntReclen(buf)
if !ok || reclen > uint64(len(buf)) {
return origlen, count, names
}
rec := buf[:reclen]
buf = buf[reclen:]
ino, ok := direntIno(rec)
if !ok {
break
}
if ino == 0 { // File absent in directory.
continue
}
const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
namlen, ok := direntNamlen(rec)
if !ok || namoff+namlen > uint64(len(rec)) {
break
}
name := rec[namoff : namoff+namlen]
for i, c := range name {
if c == 0 {
name = name[:i]
break
}
}
// Check for useless names before allocating a string.
if string(name) == "." || string(name) == ".." {
continue
}
max--
count++
names = append(names, string(name))
}
return origlen - len(buf), count, names
} }

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// //
// +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le // +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le riscv64
package unix package unix

View File

@ -8,6 +8,7 @@
package unix package unix
const ( const (
DLT_HHDLC = 0x79
IFF_SMART = 0x20 IFF_SMART = 0x20
IFT_1822 = 0x2 IFT_1822 = 0x2
IFT_A12MPPSWITCH = 0x82 IFT_A12MPPSWITCH = 0x82
@ -210,13 +211,18 @@ const (
IFT_XETHER = 0x1a IFT_XETHER = 0x1a
IPPROTO_MAXID = 0x34 IPPROTO_MAXID = 0x34
IPV6_FAITH = 0x1d IPV6_FAITH = 0x1d
IPV6_MIN_MEMBERSHIPS = 0x1f
IP_FAITH = 0x16 IP_FAITH = 0x16
IP_MAX_SOURCE_FILTER = 0x400
IP_MIN_MEMBERSHIPS = 0x1f
MAP_NORESERVE = 0x40 MAP_NORESERVE = 0x40
MAP_RENAME = 0x20 MAP_RENAME = 0x20
NET_RT_MAXID = 0x6 NET_RT_MAXID = 0x6
RTF_PRCLONING = 0x10000 RTF_PRCLONING = 0x10000
RTM_OLDADD = 0x9 RTM_OLDADD = 0x9
RTM_OLDDEL = 0xa RTM_OLDDEL = 0xa
RT_CACHING_CONTEXT = 0x1
RT_NORTREF = 0x2
SIOCADDRT = 0x8030720a SIOCADDRT = 0x8030720a
SIOCALIFADDR = 0x8118691b SIOCALIFADDR = 0x8118691b
SIOCDELRT = 0x8030720b SIOCDELRT = 0x8030720b

View File

@ -8,6 +8,7 @@
package unix package unix
const ( const (
DLT_HHDLC = 0x79
IFF_SMART = 0x20 IFF_SMART = 0x20
IFT_1822 = 0x2 IFT_1822 = 0x2
IFT_A12MPPSWITCH = 0x82 IFT_A12MPPSWITCH = 0x82
@ -210,13 +211,18 @@ const (
IFT_XETHER = 0x1a IFT_XETHER = 0x1a
IPPROTO_MAXID = 0x34 IPPROTO_MAXID = 0x34
IPV6_FAITH = 0x1d IPV6_FAITH = 0x1d
IPV6_MIN_MEMBERSHIPS = 0x1f
IP_FAITH = 0x16 IP_FAITH = 0x16
IP_MAX_SOURCE_FILTER = 0x400
IP_MIN_MEMBERSHIPS = 0x1f
MAP_NORESERVE = 0x40 MAP_NORESERVE = 0x40
MAP_RENAME = 0x20 MAP_RENAME = 0x20
NET_RT_MAXID = 0x6 NET_RT_MAXID = 0x6
RTF_PRCLONING = 0x10000 RTF_PRCLONING = 0x10000
RTM_OLDADD = 0x9 RTM_OLDADD = 0x9
RTM_OLDDEL = 0xa RTM_OLDDEL = 0xa
RT_CACHING_CONTEXT = 0x1
RT_NORTREF = 0x2
SIOCADDRT = 0x8040720a SIOCADDRT = 0x8040720a
SIOCALIFADDR = 0x8118691b SIOCALIFADDR = 0x8118691b
SIOCDELRT = 0x8040720b SIOCDELRT = 0x8040720b

17
vendor/golang.org/x/sys/unix/errors_freebsd_arm64.go generated vendored Normal file
View File

@ -0,0 +1,17 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
// them here for backwards compatibility.
package unix
const (
DLT_HHDLC = 0x79
IPV6_MIN_MEMBERSHIPS = 0x1f
IP_MAX_SOURCE_FILTER = 0x400
IP_MIN_MEMBERSHIPS = 0x1f
RT_CACHING_CONTEXT = 0x1
RT_NORTREF = 0x2
)

View File

@ -9,12 +9,11 @@ package unix
import "unsafe" import "unsafe"
// fcntl64Syscall is usually SYS_FCNTL, but is overridden on 32-bit Linux // fcntl64Syscall is usually SYS_FCNTL, but is overridden on 32-bit Linux
// systems by flock_linux_32bit.go to be SYS_FCNTL64. // systems by fcntl_linux_32bit.go to be SYS_FCNTL64.
var fcntl64Syscall uintptr = SYS_FCNTL var fcntl64Syscall uintptr = SYS_FCNTL
// FcntlInt performs a fcntl syscall on fd with the provided command and argument. func fcntl(fd int, cmd, arg int) (int, error) {
func FcntlInt(fd uintptr, cmd, arg int) (int, error) { valptr, _, errno := Syscall(fcntl64Syscall, uintptr(fd), uintptr(cmd), uintptr(arg))
valptr, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(arg))
var err error var err error
if errno != 0 { if errno != 0 {
err = errno err = errno
@ -22,6 +21,11 @@ func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
return int(valptr), err return int(valptr), err
} }
// FcntlInt performs a fcntl syscall on fd with the provided command and argument.
func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
return fcntl(int(fd), cmd, arg)
}
// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command. // FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
_, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk))) _, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk)))

29
vendor/golang.org/x/sys/unix/fdset.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package unix
// Set adds fd to the set fds.
func (fds *FdSet) Set(fd int) {
fds.Bits[fd/NFDBITS] |= (1 << (uintptr(fd) % NFDBITS))
}
// Clear removes fd from the set fds.
func (fds *FdSet) Clear(fd int) {
fds.Bits[fd/NFDBITS] &^= (1 << (uintptr(fd) % NFDBITS))
}
// IsSet returns whether fd is in the set fds.
func (fds *FdSet) IsSet(fd int) bool {
return fds.Bits[fd/NFDBITS]&(1<<(uintptr(fd)%NFDBITS)) != 0
}
// Zero clears the set fds.
func (fds *FdSet) Zero() {
for i := range fds.Bits {
fds.Bits[i] = 0
}
}

View File

@ -6,7 +6,28 @@
package unix package unix
import "runtime" import (
"runtime"
"unsafe"
)
// ioctl itself should not be exposed directly, but additional get/set
// functions for specific types are permissible.
// IoctlSetInt performs an ioctl operation which sets an integer value
// on fd, using the specified request number.
func IoctlSetInt(fd int, req uint, value int) error {
return ioctl(fd, req, uintptr(value))
}
// IoctlSetPointerInt performs an ioctl operation which sets an
// integer value on fd, using the specified request number. The ioctl
// argument is called with a pointer to the integer value, rather than
// passing the integer value directly.
func IoctlSetPointerInt(fd int, req uint, value int) error {
v := int32(value)
return ioctl(fd, req, uintptr(unsafe.Pointer(&v)))
}
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument. // IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
// //
@ -14,7 +35,7 @@ import "runtime"
func IoctlSetWinsize(fd int, req uint, value *Winsize) error { func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
// TODO: if we get the chance, remove the req parameter and // TODO: if we get the chance, remove the req parameter and
// hardcode TIOCSWINSZ. // hardcode TIOCSWINSZ.
err := ioctlSetWinsize(fd, req, value) err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
runtime.KeepAlive(value) runtime.KeepAlive(value)
return err return err
} }
@ -24,7 +45,30 @@ func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
// The req value will usually be TCSETA or TIOCSETA. // The req value will usually be TCSETA or TIOCSETA.
func IoctlSetTermios(fd int, req uint, value *Termios) error { func IoctlSetTermios(fd int, req uint, value *Termios) error {
// TODO: if we get the chance, remove the req parameter. // TODO: if we get the chance, remove the req parameter.
err := ioctlSetTermios(fd, req, value) err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
runtime.KeepAlive(value) runtime.KeepAlive(value)
return err return err
} }
// IoctlGetInt performs an ioctl operation which gets an integer value
// from fd, using the specified request number.
//
// A few ioctl requests use the return value as an output parameter;
// for those, IoctlRetInt should be used instead of this function.
func IoctlGetInt(fd int, req uint) (int, error) {
var value int
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return value, err
}
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
var value Winsize
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
var value Termios
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}

View File

@ -50,7 +50,7 @@ if [[ "$GOOS" = "linux" ]]; then
# Use the Docker-based build system # Use the Docker-based build system
# Files generated through docker (use $cmd so you can Ctl-C the build or run) # Files generated through docker (use $cmd so you can Ctl-C the build or run)
$cmd docker build --tag generate:$GOOS $GOOS $cmd docker build --tag generate:$GOOS $GOOS
$cmd docker run --interactive --tty --volume $(dirname "$(readlink -f "$0")"):/build generate:$GOOS $cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")" && /bin/pwd):/build generate:$GOOS
exit exit
fi fi
@ -73,26 +73,22 @@ aix_ppc64)
darwin_386) darwin_386)
mkerrors="$mkerrors -m32" mkerrors="$mkerrors -m32"
mksyscall="go run mksyscall.go -l32" mksyscall="go run mksyscall.go -l32"
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go" mkasm="go run mkasm_darwin.go"
;; ;;
darwin_amd64) darwin_amd64)
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go" mkasm="go run mkasm_darwin.go"
;; ;;
darwin_arm) darwin_arm)
mkerrors="$mkerrors" mkerrors="$mkerrors"
mksyscall="go run mksyscall.go -l32" mksyscall="go run mksyscall.go -l32"
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go" mkasm="go run mkasm_darwin.go"
;; ;;
darwin_arm64) darwin_arm64)
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go" mkasm="go run mkasm_darwin.go"
;; ;;
@ -124,7 +120,7 @@ freebsd_arm)
freebsd_arm64) freebsd_arm64)
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'" mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;; ;;
netbsd_386) netbsd_386)
mkerrors="$mkerrors -m32" mkerrors="$mkerrors -m32"
@ -184,12 +180,27 @@ openbsd_arm64)
# API consistent across platforms. # API consistent across platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;; ;;
openbsd_mips64)
mkerrors="$mkerrors -m64"
mksyscall="go run mksyscall.go -openbsd"
mksysctl="go run mksysctl_openbsd.go"
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
# Let the type of C char be signed for making the bare syscall
# API consistent across platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;;
solaris_amd64) solaris_amd64)
mksyscall="go run mksyscall_solaris.go" mksyscall="go run mksyscall_solaris.go"
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
mksysnum= mksysnum=
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;; ;;
illumos_amd64)
mksyscall="go run mksyscall_solaris.go"
mkerrors=
mksysnum=
mktypes=
;;
*) *)
echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2 echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
exit 1 exit 1
@ -211,10 +222,15 @@ esac
# aix/ppc64 script generates files instead of writing to stdin. # aix/ppc64 script generates files instead of writing to stdin.
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ; echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ;
elif [ "$GOOS" == "darwin" ]; then elif [ "$GOOS" == "darwin" ]; then
# pre-1.12, direct syscalls
echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go";
# 1.12 and later, syscalls via libSystem # 1.12 and later, syscalls via libSystem
echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
# 1.13 and later, syscalls via libSystem (including syscallPtr)
echo "$mksyscall -tags $GOOS,$GOARCH,go1.13 syscall_darwin.1_13.go |gofmt >zsyscall_$GOOSARCH.1_13.go";
elif [ "$GOOS" == "illumos" ]; then
# illumos code generation requires a --illumos switch
echo "$mksyscall -illumos -tags illumos,$GOARCH syscall_illumos.go |gofmt > zsyscall_illumos_$GOARCH.go";
# illumos implies solaris, so solaris code generation is also required
echo "$mksyscall -tags solaris,$GOARCH syscall_solaris.go syscall_solaris_$GOARCH.go |gofmt >zsyscall_solaris_$GOARCH.go";
else else
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
fi fi

View File

@ -44,6 +44,7 @@ includes_AIX='
#include <sys/stropts.h> #include <sys/stropts.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/poll.h> #include <sys/poll.h>
#include <sys/select.h>
#include <sys/termio.h> #include <sys/termio.h>
#include <termios.h> #include <termios.h>
#include <fcntl.h> #include <fcntl.h>
@ -60,6 +61,7 @@ includes_Darwin='
#include <sys/types.h> #include <sys/types.h>
#include <sys/event.h> #include <sys/event.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
@ -80,6 +82,7 @@ includes_Darwin='
includes_DragonFly=' includes_DragonFly='
#include <sys/types.h> #include <sys/types.h>
#include <sys/event.h> #include <sys/event.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -102,7 +105,10 @@ includes_FreeBSD='
#include <sys/capsicum.h> #include <sys/capsicum.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/disk.h>
#include <sys/event.h> #include <sys/event.h>
#include <sys/sched.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -179,51 +185,65 @@ struct ltchars {
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/select.h>
#include <sys/signalfd.h> #include <sys/signalfd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/timerfd.h>
#include <sys/uio.h>
#include <sys/xattr.h> #include <sys/xattr.h>
#include <linux/bpf.h> #include <linux/bpf.h>
#include <linux/can.h>
#include <linux/can/error.h>
#include <linux/can/raw.h>
#include <linux/capability.h>
#include <linux/cryptouser.h>
#include <linux/devlink.h>
#include <linux/dm-ioctl.h>
#include <linux/errqueue.h> #include <linux/errqueue.h>
#include <linux/falloc.h>
#include <linux/fanotify.h>
#include <linux/filter.h>
#include <linux/fs.h>
#include <linux/fscrypt.h>
#include <linux/fsverity.h>
#include <linux/genetlink.h>
#include <linux/hdreg.h>
#include <linux/icmpv6.h>
#include <linux/if.h> #include <linux/if.h>
#include <linux/if_addr.h>
#include <linux/if_alg.h> #include <linux/if_alg.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/if_ppp.h> #include <linux/if_ppp.h>
#include <linux/if_tun.h> #include <linux/if_tun.h>
#include <linux/if_packet.h> #include <linux/if_packet.h>
#include <linux/if_addr.h> #include <linux/if_xdp.h>
#include <linux/falloc.h>
#include <linux/fanotify.h>
#include <linux/filter.h>
#include <linux/fs.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/keyctl.h> #include <linux/keyctl.h>
#include <linux/loop.h>
#include <linux/magic.h> #include <linux/magic.h>
#include <linux/memfd.h> #include <linux/memfd.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/net_namespace.h> #include <linux/net_namespace.h>
#include <linux/nsfs.h>
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <linux/ptrace.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/rtc.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/ptrace.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/seccomp.h> #include <linux/seccomp.h>
#include <linux/sockios.h>
#include <linux/wait.h>
#include <linux/icmpv6.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/can.h> #include <linux/sockios.h>
#include <linux/vm_sockets.h>
#include <linux/taskstats.h> #include <linux/taskstats.h>
#include <linux/genetlink.h> #include <linux/tipc.h>
#include <linux/vm_sockets.h>
#include <linux/wait.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/hdreg.h>
#include <linux/rtc.h>
#include <linux/if_xdp.h>
#include <linux/cryptouser.h>
#include <mtd/ubi-user.h> #include <mtd/ubi-user.h>
#include <net/route.h> #include <net/route.h>
@ -262,6 +282,16 @@ struct ltchars {
#define FS_KEY_DESC_PREFIX "fscrypt:" #define FS_KEY_DESC_PREFIX "fscrypt:"
#define FS_KEY_DESC_PREFIX_SIZE 8 #define FS_KEY_DESC_PREFIX_SIZE 8
#define FS_MAX_KEY_SIZE 64 #define FS_MAX_KEY_SIZE 64
// The code generator produces -0x1 for (~0), but an unsigned value is necessary
// for the tipc_subscr timeout __u32 field.
#undef TIPC_WAIT_FOREVER
#define TIPC_WAIT_FOREVER 0xffffffff
// Copied from linux/l2tp.h
// Including linux/l2tp.h here causes conflicts between linux/in.h
// and netinet/in.h included via net/route.h above.
#define IPPROTO_L2TP 115
' '
includes_NetBSD=' includes_NetBSD='
@ -271,6 +301,8 @@ includes_NetBSD='
#include <sys/extattr.h> #include <sys/extattr.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/sched.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
@ -297,6 +329,8 @@ includes_OpenBSD='
#include <sys/event.h> #include <sys/event.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/select.h>
#include <sys/sched.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -333,6 +367,7 @@ includes_OpenBSD='
includes_SunOS=' includes_SunOS='
#include <limits.h> #include <limits.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -425,6 +460,7 @@ ccflags="$@"
$2 == "XCASE" || $2 == "XCASE" ||
$2 == "ALTWERASE" || $2 == "ALTWERASE" ||
$2 == "NOKERNINFO" || $2 == "NOKERNINFO" ||
$2 == "NFDBITS" ||
$2 ~ /^PAR/ || $2 ~ /^PAR/ ||
$2 ~ /^SIG[^_]/ || $2 ~ /^SIG[^_]/ ||
$2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ || $2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ ||
@ -434,6 +470,8 @@ ccflags="$@"
$2 ~ /^TC[IO](ON|OFF)$/ || $2 ~ /^TC[IO](ON|OFF)$/ ||
$2 ~ /^IN_/ || $2 ~ /^IN_/ ||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ || $2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
$2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|MCAST|EVFILT|NOTE|EV|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ || $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|MCAST|EVFILT|NOTE|EV|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
$2 ~ /^TP_STATUS_/ || $2 ~ /^TP_STATUS_/ ||
$2 ~ /^FALLOC_/ || $2 ~ /^FALLOC_/ ||
@ -447,13 +485,15 @@ ccflags="$@"
$2 ~ /^SYSCTL_VERS/ || $2 ~ /^SYSCTL_VERS/ ||
$2 !~ "MNT_BITS" && $2 !~ "MNT_BITS" &&
$2 ~ /^(MS|MNT|UMOUNT)_/ || $2 ~ /^(MS|MNT|UMOUNT)_/ ||
$2 ~ /^NS_GET_/ ||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT)_/ || $2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|TFD)_/ ||
$2 ~ /^KEXEC_/ || $2 ~ /^KEXEC_/ ||
$2 ~ /^LINUX_REBOOT_CMD_/ || $2 ~ /^LINUX_REBOOT_CMD_/ ||
$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
$2 ~ /^MODULE_INIT_/ || $2 ~ /^MODULE_INIT_/ ||
$2 !~ "NLA_TYPE_MASK" && $2 !~ "NLA_TYPE_MASK" &&
$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ || $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
$2 ~ /^SIOC/ || $2 ~ /^SIOC/ ||
$2 ~ /^TIOC/ || $2 ~ /^TIOC/ ||
@ -461,8 +501,9 @@ ccflags="$@"
$2 ~ /^TCSET/ || $2 ~ /^TCSET/ ||
$2 ~ /^TC(FLSH|SBRKP?|XONC)$/ || $2 ~ /^TC(FLSH|SBRKP?|XONC)$/ ||
$2 !~ "RTF_BITS" && $2 !~ "RTF_BITS" &&
$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ || $2 ~ /^(IFF|IFT|NET_RT|RTM(GRP)?|RTF|RTV|RTA|RTAX)_/ ||
$2 ~ /^BIOC/ || $2 ~ /^BIOC/ ||
$2 ~ /^DIOC/ ||
$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ || $2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ || $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ || $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
@ -472,8 +513,14 @@ ccflags="$@"
$2 ~ /^(CLOCK|TIMER)_/ || $2 ~ /^(CLOCK|TIMER)_/ ||
$2 ~ /^CAN_/ || $2 ~ /^CAN_/ ||
$2 ~ /^CAP_/ || $2 ~ /^CAP_/ ||
$2 ~ /^CP_/ ||
$2 ~ /^CPUSTATES$/ ||
$2 ~ /^ALG_/ || $2 ~ /^ALG_/ ||
$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE|IOC_(GET|SET)_ENCRYPTION)/ || $2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ ||
$2 ~ /^FS_IOC_.*(ENCRYPTION|VERITY|[GS]ETFLAGS)/ ||
$2 ~ /^FS_VERITY_/ ||
$2 ~ /^FSCRYPT_/ ||
$2 ~ /^DM_/ ||
$2 ~ /^GRND_/ || $2 ~ /^GRND_/ ||
$2 ~ /^RND/ || $2 ~ /^RND/ ||
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ || $2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
@ -500,8 +547,11 @@ ccflags="$@"
$2 ~ /^WDIOC_/ || $2 ~ /^WDIOC_/ ||
$2 ~ /^NFN/ || $2 ~ /^NFN/ ||
$2 ~ /^XDP_/ || $2 ~ /^XDP_/ ||
$2 ~ /^RWF_/ ||
$2 ~ /^(HDIO|WIN|SMART)_/ || $2 ~ /^(HDIO|WIN|SMART)_/ ||
$2 ~ /^CRYPTO_/ || $2 ~ /^CRYPTO_/ ||
$2 ~ /^TIPC_/ ||
$2 ~ /^DEVLINK_/ ||
$2 !~ "WMESGLEN" && $2 !~ "WMESGLEN" &&
$2 ~ /^W[A-Z0-9]+$/ || $2 ~ /^W[A-Z0-9]+$/ ||
$2 ~/^PPPIOC/ || $2 ~/^PPPIOC/ ||

12
vendor/golang.org/x/sys/unix/readdirent_getdents.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix dragonfly freebsd linux netbsd openbsd
package unix
// ReadDirent reads directory entries from fd and writes them into buf.
func ReadDirent(fd int, buf []byte) (n int, err error) {
return Getdents(fd, buf)
}

View File

@ -0,0 +1,19 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin
package unix
import "unsafe"
// ReadDirent reads directory entries from fd and writes them into buf.
func ReadDirent(fd int, buf []byte) (n int, err error) {
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
// 64 bits should be enough. (32 bits isn't even on 386). Since the
// actual system call is getdirentries64, 64 is a good guess.
// TODO(rsc): Can we use a single global basep for all calls?
var base = (*uintptr)(unsafe.Pointer(new(uint64)))
return Getdirentries(fd, buf, base)
}

16
vendor/golang.org/x/sys/unix/sockcmsg_dragonfly.go generated vendored Normal file
View File

@ -0,0 +1,16 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package unix
// Round the length of a raw sockaddr up to align it properly.
func cmsgAlignOf(salen int) int {
salign := SizeofPtr
if SizeofPtr == 8 && !supportsABI(_dragonflyABIChangeVersion) {
// 64-bit Dragonfly before the September 2019 ABI changes still requires
// 32-bit aligned access to network subsystem.
salign = 4
}
return (salen + salign - 1) & ^(salign - 1)
}

View File

@ -17,7 +17,7 @@ func UnixCredentials(ucred *Ucred) []byte {
h.Level = SOL_SOCKET h.Level = SOL_SOCKET
h.Type = SCM_CREDENTIALS h.Type = SCM_CREDENTIALS
h.SetLen(CmsgLen(SizeofUcred)) h.SetLen(CmsgLen(SizeofUcred))
*((*Ucred)(cmsgData(h))) = *ucred *(*Ucred)(h.data(0)) = *ucred
return b return b
} }

View File

@ -9,35 +9,9 @@
package unix package unix
import ( import (
"runtime"
"unsafe" "unsafe"
) )
// Round the length of a raw sockaddr up to align it properly.
func cmsgAlignOf(salen int) int {
salign := SizeofPtr
switch runtime.GOOS {
case "aix":
// There is no alignment on AIX.
salign = 1
case "darwin", "dragonfly", "solaris", "illumos":
// NOTE: It seems like 64-bit Darwin, DragonFly BSD,
// illumos, and Solaris kernels still require 32-bit
// aligned access to network subsystem.
if SizeofPtr == 8 {
salign = 4
}
case "netbsd", "openbsd":
// NetBSD and OpenBSD armv7 require 64-bit alignment.
if runtime.GOARCH == "arm" {
salign = 8
}
}
return (salen + salign - 1) & ^(salign - 1)
}
// CmsgLen returns the value to store in the Len field of the Cmsghdr // CmsgLen returns the value to store in the Len field of the Cmsghdr
// structure, taking into account any necessary alignment. // structure, taking into account any necessary alignment.
func CmsgLen(datalen int) int { func CmsgLen(datalen int) int {
@ -50,8 +24,8 @@ func CmsgSpace(datalen int) int {
return cmsgAlignOf(SizeofCmsghdr) + cmsgAlignOf(datalen) return cmsgAlignOf(SizeofCmsghdr) + cmsgAlignOf(datalen)
} }
func cmsgData(h *Cmsghdr) unsafe.Pointer { func (h *Cmsghdr) data(offset uintptr) unsafe.Pointer {
return unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(cmsgAlignOf(SizeofCmsghdr))) return unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(cmsgAlignOf(SizeofCmsghdr)) + offset)
} }
// SocketControlMessage represents a socket control message. // SocketControlMessage represents a socket control message.
@ -94,10 +68,8 @@ func UnixRights(fds ...int) []byte {
h.Level = SOL_SOCKET h.Level = SOL_SOCKET
h.Type = SCM_RIGHTS h.Type = SCM_RIGHTS
h.SetLen(CmsgLen(datalen)) h.SetLen(CmsgLen(datalen))
data := cmsgData(h) for i, fd := range fds {
for _, fd := range fds { *(*int32)(h.data(4 * uintptr(i))) = int32(fd)
*(*int32)(data) = int32(fd)
data = unsafe.Pointer(uintptr(data) + 4)
} }
return b return b
} }

38
vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go generated vendored Normal file
View File

@ -0,0 +1,38 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix darwin freebsd linux netbsd openbsd solaris
package unix
import (
"runtime"
)
// Round the length of a raw sockaddr up to align it properly.
func cmsgAlignOf(salen int) int {
salign := SizeofPtr
// dragonfly needs to check ABI version at runtime, see cmsgAlignOf in
// sockcmsg_dragonfly.go
switch runtime.GOOS {
case "aix":
// There is no alignment on AIX.
salign = 1
case "darwin", "illumos", "solaris":
// NOTE: It seems like 64-bit Darwin, Illumos and Solaris
// kernels still require 32-bit aligned access to network
// subsystem.
if SizeofPtr == 8 {
salign = 4
}
case "netbsd", "openbsd":
// NetBSD and OpenBSD armv7 require 64-bit alignment.
if runtime.GOARCH == "arm" {
salign = 8
}
}
return (salen + salign - 1) & ^(salign - 1)
}

View File

@ -280,8 +280,24 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
return -1, ENOSYS return -1, ENOSYS
} }
func direntIno(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
}
func direntReclen(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
}
func direntNamlen(buf []byte) (uint64, bool) {
reclen, ok := direntReclen(buf)
if !ok {
return 0, false
}
return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
}
//sys getdirent(fd int, buf []byte) (n int, err error) //sys getdirent(fd int, buf []byte) (n int, err error)
func ReadDirent(fd int, buf []byte) (n int, err error) { func Getdents(fd int, buf []byte) (n int, err error) {
return getdirent(fd, buf) return getdirent(fd, buf)
} }
@ -334,49 +350,12 @@ func (w WaitStatus) Signal() Signal {
func (w WaitStatus) Continued() bool { return w&0x01000000 != 0 } func (w WaitStatus) Continued() bool { return w&0x01000000 != 0 }
func (w WaitStatus) CoreDump() bool { return w&0x200 != 0 } func (w WaitStatus) CoreDump() bool { return w&0x80 == 0x80 }
func (w WaitStatus) TrapCause() int { return -1 } func (w WaitStatus) TrapCause() int { return -1 }
//sys ioctl(fd int, req uint, arg uintptr) (err error) //sys ioctl(fd int, req uint, arg uintptr) (err error)
// ioctl itself should not be exposed directly, but additional get/set
// functions for specific types are permissible.
// IoctlSetInt performs an ioctl operation which sets an integer value
// on fd, using the specified request number.
func IoctlSetInt(fd int, req uint, value int) error {
return ioctl(fd, req, uintptr(value))
}
func ioctlSetWinsize(fd int, req uint, value *Winsize) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
func ioctlSetTermios(fd int, req uint, value *Termios) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
// IoctlGetInt performs an ioctl operation which gets an integer value
// from fd, using the specified request number.
func IoctlGetInt(fd int, req uint) (int, error) {
var value int
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return value, err
}
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
var value Winsize
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
var value Termios
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
// fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX // fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX
// There is no way to create a custom fcntl and to keep //sys fcntl easily, // There is no way to create a custom fcntl and to keep //sys fcntl easily,
// Therefore, the programmer must call dup2 instead of fcntl in this case. // Therefore, the programmer must call dup2 instead of fcntl in this case.

View File

@ -29,6 +29,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = int32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }

View File

@ -29,6 +29,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = int32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }

View File

@ -63,15 +63,6 @@ func Setgroups(gids []int) (err error) {
return setgroups(len(a), &a[0]) return setgroups(len(a), &a[0])
} }
func ReadDirent(fd int, buf []byte) (n int, err error) {
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
// 64 bits should be enough. (32 bits isn't even on 386). Since the
// actual system call is getdirentries64, 64 is a good guess.
// TODO(rsc): Can we use a single global basep for all calls?
var base = (*uintptr)(unsafe.Pointer(new(uint64)))
return Getdirentries(fd, buf, base)
}
// Wait status is 7 bits at bottom, either 0 (exited), // Wait status is 7 bits at bottom, either 0 (exited),
// 0x7F (stopped), or a signal number that caused an exit. // 0x7F (stopped), or a signal number that caused an exit.
// The 0x80 bit is whether there was a core dump. // The 0x80 bit is whether there was a core dump.
@ -86,6 +77,7 @@ const (
shift = 8 shift = 8
exited = 0 exited = 0
killed = 9
stopped = 0x7F stopped = 0x7F
) )
@ -112,6 +104,8 @@ func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP } func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
func (w WaitStatus) Killed() bool { return w&mask == killed && syscall.Signal(w>>shift) != SIGKILL }
func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP } func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
func (w WaitStatus) StopSignal() syscall.Signal { func (w WaitStatus) StopSignal() syscall.Signal {
@ -243,7 +237,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
break break
} }
} }
bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
sa.Name = string(bytes) sa.Name = string(bytes)
return sa, nil return sa, nil
@ -419,8 +413,6 @@ func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, err e
return kevent(kq, change, len(changes), event, len(events), timeout) return kevent(kq, change, len(changes), event, len(events), timeout)
} }
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL
// sysctlmib translates name to mib number and appends any additional args. // sysctlmib translates name to mib number and appends any additional args.
func sysctlmib(name string, args ...int) ([]_C_int, error) { func sysctlmib(name string, args ...int) ([]_C_int, error) {
// Translate name to mib number. // Translate name to mib number.
@ -518,6 +510,40 @@ func SysctlRaw(name string, args ...int) ([]byte, error) {
return buf[:n], nil return buf[:n], nil
} }
func SysctlClockinfo(name string) (*Clockinfo, error) {
mib, err := sysctlmib(name)
if err != nil {
return nil, err
}
n := uintptr(SizeofClockinfo)
var ci Clockinfo
if err := sysctl(mib, (*byte)(unsafe.Pointer(&ci)), &n, nil, 0); err != nil {
return nil, err
}
if n != SizeofClockinfo {
return nil, EIO
}
return &ci, nil
}
func SysctlTimeval(name string) (*Timeval, error) {
mib, err := sysctlmib(name)
if err != nil {
return nil, err
}
var tv Timeval
n := uintptr(unsafe.Sizeof(tv))
if err := sysctl(mib, (*byte)(unsafe.Pointer(&tv)), &n, nil, 0); err != nil {
return nil, err
}
if n != unsafe.Sizeof(tv) {
return nil, EIO
}
return &tv, nil
}
//sys utimes(path string, timeval *[2]Timeval) (err error) //sys utimes(path string, timeval *[2]Timeval) (err error)
func Utimes(path string, tv []Timeval) error { func Utimes(path string, tv []Timeval) error {
@ -585,8 +611,6 @@ func Futimes(fd int, tv []Timeval) error {
return futimes(fd, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) return futimes(fd, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
} }
//sys fcntl(fd int, cmd int, arg int) (val int, err error)
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) //sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) { func Poll(fds []PollFd, timeout int) (n int, err error) {

31
vendor/golang.org/x/sys/unix/syscall_darwin.1_12.go generated vendored Normal file
View File

@ -0,0 +1,31 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin,go1.12,!go1.13
package unix
import (
"unsafe"
)
const _SYS_GETDIRENTRIES64 = 344
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
// To implement this using libSystem we'd need syscall_syscallPtr for
// fdopendir. However, syscallPtr was only added in Go 1.13, so we fall
// back to raw syscalls for this func on Go 1.12.
var p unsafe.Pointer
if len(buf) > 0 {
p = unsafe.Pointer(&buf[0])
} else {
p = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(_SYS_GETDIRENTRIES64, uintptr(fd), uintptr(p), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
n = int(r0)
if e1 != 0 {
return n, errnoErr(e1)
}
return n, nil
}

108
vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go generated vendored Normal file
View File

@ -0,0 +1,108 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin,go1.13
package unix
import (
"unsafe"
"golang.org/x/sys/internal/unsafeheader"
)
//sys closedir(dir uintptr) (err error)
//sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno)
func fdopendir(fd int) (dir uintptr, err error) {
r0, _, e1 := syscall_syscallPtr(funcPC(libc_fdopendir_trampoline), uintptr(fd), 0, 0)
dir = uintptr(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func libc_fdopendir_trampoline()
//go:linkname libc_fdopendir libc_fdopendir
//go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib"
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
// Simulate Getdirentries using fdopendir/readdir_r/closedir.
// We store the number of entries to skip in the seek
// offset of fd. See issue #31368.
// It's not the full required semantics, but should handle the case
// of calling Getdirentries or ReadDirent repeatedly.
// It won't handle assigning the results of lseek to *basep, or handle
// the directory being edited underfoot.
skip, err := Seek(fd, 0, 1 /* SEEK_CUR */)
if err != nil {
return 0, err
}
// We need to duplicate the incoming file descriptor
// because the caller expects to retain control of it, but
// fdopendir expects to take control of its argument.
// Just Dup'ing the file descriptor is not enough, as the
// result shares underlying state. Use Openat to make a really
// new file descriptor referring to the same directory.
fd2, err := Openat(fd, ".", O_RDONLY, 0)
if err != nil {
return 0, err
}
d, err := fdopendir(fd2)
if err != nil {
Close(fd2)
return 0, err
}
defer closedir(d)
var cnt int64
for {
var entry Dirent
var entryp *Dirent
e := readdir_r(d, &entry, &entryp)
if e != 0 {
return n, errnoErr(e)
}
if entryp == nil {
break
}
if skip > 0 {
skip--
cnt++
continue
}
reclen := int(entry.Reclen)
if reclen > len(buf) {
// Not enough room. Return for now.
// The counter will let us know where we should start up again.
// Note: this strategy for suspending in the middle and
// restarting is O(n^2) in the length of the directory. Oh well.
break
}
// Copy entry into return buffer.
var s []byte
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&s))
hdr.Data = unsafe.Pointer(&entry)
hdr.Cap = reclen
hdr.Len = reclen
copy(buf, s)
buf = buf[reclen:]
n += reclen
cnt++
}
// Set the seek offset of the input fd to record
// how many files we've already returned.
_, err = Seek(fd, cnt, 0 /* SEEK_SET */)
if err != nil {
return n, err
}
return n, nil
}

View File

@ -49,6 +49,11 @@ type SockaddrDatalink struct {
raw RawSockaddrDatalink raw RawSockaddrDatalink
} }
// Some external packages rely on SYS___SYSCTL being defined to implement their
// own sysctl wrappers. Provide it here, even though direct syscalls are no
// longer supported on darwin.
const SYS___SYSCTL = 202
// Translate "kern.hostname" to []_C_int{0,1,2,3}. // Translate "kern.hostname" to []_C_int{0,1,2,3}.
func nametomib(name string) (mib []_C_int, err error) { func nametomib(name string) (mib []_C_int, err error) {
const siz = unsafe.Sizeof(mib[0]) const siz = unsafe.Sizeof(mib[0])
@ -77,7 +82,18 @@ func nametomib(name string) (mib []_C_int, err error) {
return buf[0 : n/siz], nil return buf[0 : n/siz], nil
} }
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) func direntIno(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
}
func direntReclen(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
}
func direntNamlen(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
}
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) } func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) } func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
@ -144,23 +160,6 @@ func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (
//sys getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) //sys getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error)
func SysctlClockinfo(name string) (*Clockinfo, error) {
mib, err := sysctlmib(name)
if err != nil {
return nil, err
}
n := uintptr(SizeofClockinfo)
var ci Clockinfo
if err := sysctl(mib, (*byte)(unsafe.Pointer(&ci)), &n, nil, 0); err != nil {
return nil, err
}
if n != SizeofClockinfo {
return nil, EIO
}
return &ci, nil
}
//sysnb pipe() (r int, w int, err error) //sysnb pipe() (r int, w int, err error)
func Pipe(p []int) (err error) { func Pipe(p []int) (err error) {
@ -322,48 +321,15 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) error {
* Wrapped * Wrapped
*/ */
//sys fcntl(fd int, cmd int, arg int) (val int, err error)
//sys kill(pid int, signum int, posix int) (err error) //sys kill(pid int, signum int, posix int) (err error)
func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(signum), 1) } func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(signum), 1) }
//sys ioctl(fd int, req uint, arg uintptr) (err error) //sys ioctl(fd int, req uint, arg uintptr) (err error)
// ioctl itself should not be exposed directly, but additional get/set //sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS_SYSCTL
// functions for specific types are permissible.
// IoctlSetInt performs an ioctl operation which sets an integer value
// on fd, using the specified request number.
func IoctlSetInt(fd int, req uint, value int) error {
return ioctl(fd, req, uintptr(value))
}
func ioctlSetWinsize(fd int, req uint, value *Winsize) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
func ioctlSetTermios(fd int, req uint, value *Termios) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
// IoctlGetInt performs an ioctl operation which gets an integer value
// from fd, using the specified request number.
func IoctlGetInt(fd int, req uint) (int, error) {
var value int
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return value, err
}
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
var value Winsize
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
var value Termios
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func Uname(uname *Utsname) error { func Uname(uname *Utsname) error {
mib := []_C_int{CTL_KERN, KERN_OSTYPE} mib := []_C_int{CTL_KERN, KERN_OSTYPE}
@ -462,6 +428,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sysnb Getrlimit(which int, lim *Rlimit) (err error) //sysnb Getrlimit(which int, lim *Rlimit) (err error)
//sysnb Getrusage(who int, rusage *Rusage) (err error) //sysnb Getrusage(who int, rusage *Rusage) (err error)
//sysnb Getsid(pid int) (sid int, err error) //sysnb Getsid(pid int) (sid int, err error)
//sysnb Gettimeofday(tp *Timeval) (err error)
//sysnb Getuid() (uid int) //sysnb Getuid() (uid int)
//sysnb Issetugid() (tainted bool) //sysnb Issetugid() (tainted bool)
//sys Kqueue() (fd int, err error) //sys Kqueue() (fd int, err error)
@ -486,7 +453,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Revoke(path string) (err error) //sys Revoke(path string) (err error)
//sys Rmdir(path string) (err error) //sys Rmdir(path string) (err error)
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
//sys Setegid(egid int) (err error) //sys Setegid(egid int) (err error)
//sysnb Seteuid(euid int) (err error) //sysnb Seteuid(euid int) (err error)
//sysnb Setgid(gid int) (err error) //sysnb Setgid(gid int) (err error)

View File

@ -10,6 +10,8 @@ import (
"syscall" "syscall"
) )
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
func setTimespec(sec, nsec int64) Timespec { func setTimespec(sec, nsec int64) Timespec {
return Timespec{Sec: int32(sec), Nsec: int32(nsec)} return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
} }
@ -18,17 +20,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: int32(sec), Usec: int32(usec)} return Timeval{Sec: int32(sec), Usec: int32(usec)}
} }
//sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) {
// The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back
// in the two registers.
sec, usec, err := gettimeofday(tv)
tv.Sec = int32(sec)
tv.Usec = int32(usec)
return err
}
func SetKevent(k *Kevent_t, fd, mode, flags int) { func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd) k.Ident = uint32(fd)
k.Filter = int16(mode) k.Filter = int16(mode)
@ -43,20 +34,19 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = int32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of darwin/386 the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64 //sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64
//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64 //sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 //sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 //sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64

View File

@ -10,6 +10,8 @@ import (
"syscall" "syscall"
) )
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
func setTimespec(sec, nsec int64) Timespec { func setTimespec(sec, nsec int64) Timespec {
return Timespec{Sec: sec, Nsec: nsec} return Timespec{Sec: sec, Nsec: nsec}
} }
@ -18,17 +20,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: sec, Usec: int32(usec)} return Timeval{Sec: sec, Usec: int32(usec)}
} }
//sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) {
// The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back
// in the two registers.
sec, usec, err := gettimeofday(tv)
tv.Sec = sec
tv.Usec = usec
return err
}
func SetKevent(k *Kevent_t, fd, mode, flags int) { func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint64(fd) k.Ident = uint64(fd)
k.Filter = int16(mode) k.Filter = int16(mode)
@ -43,20 +34,19 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = int32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of darwin/amd64 the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64 //sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64
//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64 //sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 //sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 //sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64

View File

@ -8,6 +8,10 @@ import (
"syscall" "syscall"
) )
func ptrace(request int, pid int, addr uintptr, data uintptr) error {
return ENOTSUP
}
func setTimespec(sec, nsec int64) Timespec { func setTimespec(sec, nsec int64) Timespec {
return Timespec{Sec: int32(sec), Nsec: int32(nsec)} return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
} }
@ -16,17 +20,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: int32(sec), Usec: int32(usec)} return Timeval{Sec: int32(sec), Usec: int32(usec)}
} }
//sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) {
// The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back
// in the two registers.
sec, usec, err := gettimeofday(tv)
tv.Sec = int32(sec)
tv.Usec = int32(usec)
return err
}
func SetKevent(k *Kevent_t, fd, mode, flags int) { func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd) k.Ident = uint32(fd)
k.Filter = int16(mode) k.Filter = int16(mode)
@ -41,16 +34,16 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = int32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of darwin/arm the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) //sys Fstat(fd int, stat *Stat_t) (err error)
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
//sys Fstatfs(fd int, stat *Statfs_t) (err error) //sys Fstatfs(fd int, stat *Statfs_t) (err error)
@ -58,7 +51,3 @@ const SYS___SYSCTL = SYS_SYSCTL
//sys Lstat(path string, stat *Stat_t) (err error) //sys Lstat(path string, stat *Stat_t) (err error)
//sys Stat(path string, stat *Stat_t) (err error) //sys Stat(path string, stat *Stat_t) (err error)
//sys Statfs(path string, stat *Statfs_t) (err error) //sys Statfs(path string, stat *Statfs_t) (err error)
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
return 0, ENOSYS
}

View File

@ -10,6 +10,10 @@ import (
"syscall" "syscall"
) )
func ptrace(request int, pid int, addr uintptr, data uintptr) error {
return ENOTSUP
}
func setTimespec(sec, nsec int64) Timespec { func setTimespec(sec, nsec int64) Timespec {
return Timespec{Sec: sec, Nsec: nsec} return Timespec{Sec: sec, Nsec: nsec}
} }
@ -18,17 +22,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: sec, Usec: int32(usec)} return Timeval{Sec: sec, Usec: int32(usec)}
} }
//sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) {
// The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back
// in the two registers.
sec, usec, err := gettimeofday(tv)
tv.Sec = sec
tv.Usec = usec
return err
}
func SetKevent(k *Kevent_t, fd, mode, flags int) { func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint64(fd) k.Ident = uint64(fd)
k.Filter = int16(mode) k.Filter = int16(mode)
@ -43,16 +36,16 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = int32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of darwin/arm64 the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) //sys Fstat(fd int, stat *Stat_t) (err error)
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
//sys Fstatfs(fd int, stat *Statfs_t) (err error) //sys Fstatfs(fd int, stat *Statfs_t) (err error)
@ -60,7 +53,3 @@ const SYS___SYSCTL = SYS_SYSCTL
//sys Lstat(path string, stat *Stat_t) (err error) //sys Lstat(path string, stat *Stat_t) (err error)
//sys Stat(path string, stat *Stat_t) (err error) //sys Stat(path string, stat *Stat_t) (err error)
//sys Statfs(path string, stat *Statfs_t) (err error) //sys Statfs(path string, stat *Statfs_t) (err error)
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
return 0, ENOSYS
}

View File

@ -15,6 +15,7 @@ func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err
func syscall_syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) // 32-bit only func syscall_syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) // 32-bit only
func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
//go:linkname syscall_syscall syscall.syscall //go:linkname syscall_syscall syscall.syscall
//go:linkname syscall_syscall6 syscall.syscall6 //go:linkname syscall_syscall6 syscall.syscall6
@ -22,6 +23,7 @@ func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, er
//go:linkname syscall_syscall9 syscall.syscall9 //go:linkname syscall_syscall9 syscall.syscall9
//go:linkname syscall_rawSyscall syscall.rawSyscall //go:linkname syscall_rawSyscall syscall.rawSyscall
//go:linkname syscall_rawSyscall6 syscall.rawSyscall6 //go:linkname syscall_rawSyscall6 syscall.rawSyscall6
//go:linkname syscall_syscallPtr syscall.syscallPtr
// Find the entry point for f. See comments in runtime/proc.go for the // Find the entry point for f. See comments in runtime/proc.go for the
// function of the same name. // function of the same name.

View File

@ -12,7 +12,25 @@
package unix package unix
import "unsafe" import (
"sync"
"unsafe"
)
// See version list in https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/sys/param.h
var (
osreldateOnce sync.Once
osreldate uint32
)
// First __DragonFly_version after September 2019 ABI changes
// http://lists.dragonflybsd.org/pipermail/users/2019-September/358280.html
const _dragonflyABIChangeVersion = 500705
func supportsABI(ver uint32) bool {
osreldateOnce.Do(func() { osreldate, _ = SysctlUint32("kern.osreldate") })
return osreldate >= ver
}
// SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets. // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets.
type SockaddrDatalink struct { type SockaddrDatalink struct {
@ -57,6 +75,22 @@ func nametomib(name string) (mib []_C_int, err error) {
return buf[0 : n/siz], nil return buf[0 : n/siz], nil
} }
func direntIno(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
}
func direntReclen(buf []byte) (uint64, bool) {
namlen, ok := direntNamlen(buf)
if !ok {
return 0, false
}
return (16 + namlen + 1 + 7) &^ 7, true
}
func direntNamlen(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
}
//sysnb pipe() (r int, w int, err error) //sysnb pipe() (r int, w int, err error)
func Pipe(p []int) (err error) { func Pipe(p []int) (err error) {
@ -134,42 +168,7 @@ func setattrlistTimes(path string, times []Timespec, flags int) error {
//sys ioctl(fd int, req uint, arg uintptr) (err error) //sys ioctl(fd int, req uint, arg uintptr) (err error)
// ioctl itself should not be exposed directly, but additional get/set //sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL
// functions for specific types are permissible.
// IoctlSetInt performs an ioctl operation which sets an integer value
// on fd, using the specified request number.
func IoctlSetInt(fd int, req uint, value int) error {
return ioctl(fd, req, uintptr(value))
}
func ioctlSetWinsize(fd int, req uint, value *Winsize) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
func ioctlSetTermios(fd int, req uint, value *Termios) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
// IoctlGetInt performs an ioctl operation which gets an integer value
// from fd, using the specified request number.
func IoctlGetInt(fd int, req uint) (int, error) {
var value int
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return value, err
}
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
var value Winsize
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
var value Termios
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func sysctlUname(mib []_C_int, old *byte, oldlen *uintptr) error { func sysctlUname(mib []_C_int, old *byte, oldlen *uintptr) error {
err := sysctl(mib, old, oldlen, nil, 0) err := sysctl(mib, old, oldlen, nil, 0)
@ -269,6 +268,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Fstatfs(fd int, stat *Statfs_t) (err error) //sys Fstatfs(fd int, stat *Statfs_t) (err error)
//sys Fsync(fd int) (err error) //sys Fsync(fd int) (err error)
//sys Ftruncate(fd int, length int64) (err error) //sys Ftruncate(fd int, length int64) (err error)
//sys Getdents(fd int, buf []byte) (n int, err error)
//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) //sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error)
//sys Getdtablesize() (size int) //sys Getdtablesize() (size int)
//sysnb Getegid() (egid int) //sysnb Getegid() (egid int)
@ -308,7 +308,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Revoke(path string) (err error) //sys Revoke(path string) (err error)
//sys Rmdir(path string) (err error) //sys Rmdir(path string) (err error)
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
//sysnb Setegid(egid int) (err error) //sysnb Setegid(egid int) (err error)
//sysnb Seteuid(euid int) (err error) //sysnb Seteuid(euid int) (err error)
//sysnb Setgid(gid int) (err error) //sysnb Setgid(gid int) (err error)

View File

@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = int32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }

View File

@ -82,6 +82,18 @@ func nametomib(name string) (mib []_C_int, err error) {
return buf[0 : n/siz], nil return buf[0 : n/siz], nil
} }
func direntIno(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
}
func direntReclen(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
}
func direntNamlen(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
}
func Pipe(p []int) (err error) { func Pipe(p []int) (err error) {
return Pipe2(p, 0) return Pipe2(p, 0)
} }
@ -189,42 +201,7 @@ func setattrlistTimes(path string, times []Timespec, flags int) error {
//sys ioctl(fd int, req uint, arg uintptr) (err error) //sys ioctl(fd int, req uint, arg uintptr) (err error)
// ioctl itself should not be exposed directly, but additional get/set //sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL
// functions for specific types are permissible.
// IoctlSetInt performs an ioctl operation which sets an integer value
// on fd, using the specified request number.
func IoctlSetInt(fd int, req uint, value int) error {
return ioctl(fd, req, uintptr(value))
}
func ioctlSetWinsize(fd int, req uint, value *Winsize) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
func ioctlSetTermios(fd int, req uint, value *Termios) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
// IoctlGetInt performs an ioctl operation which gets an integer value
// from fd, using the specified request number.
func IoctlGetInt(fd int, req uint) (int, error) {
var value int
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return value, err
}
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
var value Winsize
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
var value Termios
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func Uname(uname *Utsname) error { func Uname(uname *Utsname) error {
mib := []_C_int{CTL_KERN, KERN_OSTYPE} mib := []_C_int{CTL_KERN, KERN_OSTYPE}
@ -362,7 +339,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
if supportsABI(_ino64First) { if supportsABI(_ino64First) {
if unsafe.Sizeof(*basep) == 8 { if basep == nil || unsafe.Sizeof(*basep) == 8 {
return getdirentries_freebsd12(fd, buf, (*uint64)(unsafe.Pointer(basep))) return getdirentries_freebsd12(fd, buf, (*uint64)(unsafe.Pointer(basep)))
} }
// The freebsd12 syscall needs a 64-bit base. On 32-bit machines // The freebsd12 syscall needs a 64-bit base. On 32-bit machines
@ -485,8 +462,12 @@ func convertFromDirents11(buf []byte, old []byte) int {
dstPos := 0 dstPos := 0
srcPos := 0 srcPos := 0
for dstPos+fixedSize < len(buf) && srcPos+oldFixedSize < len(old) { for dstPos+fixedSize < len(buf) && srcPos+oldFixedSize < len(old) {
dstDirent := (*Dirent)(unsafe.Pointer(&buf[dstPos])) var dstDirent Dirent
srcDirent := (*dirent_freebsd11)(unsafe.Pointer(&old[srcPos])) var srcDirent dirent_freebsd11
// If multiple direntries are written, sometimes when we reach the final one,
// we may have cap of old less than size of dirent_freebsd11.
copy((*[unsafe.Sizeof(srcDirent)]byte)(unsafe.Pointer(&srcDirent))[:], old[srcPos:])
reclen := roundup(fixedSize+int(srcDirent.Namlen)+1, 8) reclen := roundup(fixedSize+int(srcDirent.Namlen)+1, 8)
if dstPos+reclen > len(buf) { if dstPos+reclen > len(buf) {
@ -502,6 +483,7 @@ func convertFromDirents11(buf []byte, old []byte) int {
dstDirent.Pad1 = 0 dstDirent.Pad1 = 0
copy(dstDirent.Name[:], srcDirent.Name[:srcDirent.Namlen]) copy(dstDirent.Name[:], srcDirent.Name[:srcDirent.Namlen])
copy(buf[dstPos:], (*[unsafe.Sizeof(dstDirent)]byte)(unsafe.Pointer(&dstDirent))[:])
padding := buf[dstPos+fixedSize+int(dstDirent.Namlen) : dstPos+reclen] padding := buf[dstPos+fixedSize+int(dstDirent.Namlen) : dstPos+reclen]
for i := range padding { for i := range padding {
padding[i] = 0 padding[i] = 0
@ -521,6 +503,60 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
return sendfile(outfd, infd, offset, count) return sendfile(outfd, infd, offset, count)
} }
//sys ptrace(request int, pid int, addr uintptr, data int) (err error)
func PtraceAttach(pid int) (err error) {
return ptrace(PTRACE_ATTACH, pid, 0, 0)
}
func PtraceCont(pid int, signal int) (err error) {
return ptrace(PTRACE_CONT, pid, 1, signal)
}
func PtraceDetach(pid int) (err error) {
return ptrace(PTRACE_DETACH, pid, 1, 0)
}
func PtraceGetFpRegs(pid int, fpregsout *FpReg) (err error) {
return ptrace(PTRACE_GETFPREGS, pid, uintptr(unsafe.Pointer(fpregsout)), 0)
}
func PtraceGetRegs(pid int, regsout *Reg) (err error) {
return ptrace(PTRACE_GETREGS, pid, uintptr(unsafe.Pointer(regsout)), 0)
}
func PtraceLwpEvents(pid int, enable int) (err error) {
return ptrace(PTRACE_LWPEVENTS, pid, 0, enable)
}
func PtraceLwpInfo(pid int, info uintptr) (err error) {
return ptrace(PTRACE_LWPINFO, pid, info, int(unsafe.Sizeof(PtraceLwpInfoStruct{})))
}
func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) {
return PtraceIO(PIOD_READ_D, pid, addr, out, SizeofLong)
}
func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) {
return PtraceIO(PIOD_READ_I, pid, addr, out, SizeofLong)
}
func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) {
return PtraceIO(PIOD_WRITE_D, pid, addr, data, SizeofLong)
}
func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) {
return PtraceIO(PIOD_WRITE_I, pid, addr, data, SizeofLong)
}
func PtraceSetRegs(pid int, regs *Reg) (err error) {
return ptrace(PTRACE_SETREGS, pid, uintptr(unsafe.Pointer(regs)), 0)
}
func PtraceSingleStep(pid int) (err error) {
return ptrace(PTRACE_SINGLESTEP, pid, 1, 0)
}
/* /*
* Exposed directly * Exposed directly
*/ */
@ -612,7 +648,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Revoke(path string) (err error) //sys Revoke(path string) (err error)
//sys Rmdir(path string) (err error) //sys Rmdir(path string) (err error)
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
//sysnb Setegid(egid int) (err error) //sysnb Setegid(egid int) (err error)
//sysnb Seteuid(euid int) (err error) //sysnb Seteuid(euid int) (err error)
//sysnb Setgid(gid int) (err error) //sysnb Setgid(gid int) (err error)

View File

@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = int32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }
@ -50,3 +54,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
} }
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
return ptrace(PTRACE_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
}
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint32(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}

View File

@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = int32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }
@ -50,3 +54,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
} }
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
return ptrace(PTRACE_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
}
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint64(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}

View File

@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = int32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }
@ -50,3 +54,9 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
} }
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint32(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}

View File

@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = int32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }
@ -50,3 +54,9 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
} }
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint64(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}

57
vendor/golang.org/x/sys/unix/syscall_illumos.go generated vendored Normal file
View File

@ -0,0 +1,57 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// illumos system calls not present on Solaris.
// +build amd64,illumos
package unix
import "unsafe"
func bytes2iovec(bs [][]byte) []Iovec {
iovecs := make([]Iovec, len(bs))
for i, b := range bs {
iovecs[i].SetLen(len(b))
if len(b) > 0 {
// somehow Iovec.Base on illumos is (*int8), not (*byte)
iovecs[i].Base = (*int8)(unsafe.Pointer(&b[0]))
} else {
iovecs[i].Base = (*int8)(unsafe.Pointer(&_zero))
}
}
return iovecs
}
//sys readv(fd int, iovs []Iovec) (n int, err error)
func Readv(fd int, iovs [][]byte) (n int, err error) {
iovecs := bytes2iovec(iovs)
n, err = readv(fd, iovecs)
return n, err
}
//sys preadv(fd int, iovs []Iovec, off int64) (n int, err error)
func Preadv(fd int, iovs [][]byte, off int64) (n int, err error) {
iovecs := bytes2iovec(iovs)
n, err = preadv(fd, iovecs, off)
return n, err
}
//sys writev(fd int, iovs []Iovec) (n int, err error)
func Writev(fd int, iovs [][]byte) (n int, err error) {
iovecs := bytes2iovec(iovs)
n, err = writev(fd, iovecs)
return n, err
}
//sys pwritev(fd int, iovs []Iovec, off int64) (n int, err error)
func Pwritev(fd int, iovs [][]byte, off int64) (n int, err error) {
iovecs := bytes2iovec(iovs)
n, err = pwritev(fd, iovecs, off)
return n, err
}

View File

@ -13,7 +13,6 @@ package unix
import ( import (
"encoding/binary" "encoding/binary"
"net"
"runtime" "runtime"
"syscall" "syscall"
"unsafe" "unsafe"
@ -72,27 +71,15 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
// ioctl itself should not be exposed directly, but additional get/set // ioctl itself should not be exposed directly, but additional get/set
// functions for specific types are permissible. // functions for specific types are permissible.
// IoctlSetPointerInt performs an ioctl operation which sets an // IoctlRetInt performs an ioctl operation specified by req on a device
// integer value on fd, using the specified request number. The ioctl // associated with opened file descriptor fd, and returns a non-negative
// argument is called with a pointer to the integer value, rather than // integer that is returned by the ioctl syscall.
// passing the integer value directly. func IoctlRetInt(fd int, req uint) (int, error) {
func IoctlSetPointerInt(fd int, req uint, value int) error { ret, _, err := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), 0)
v := int32(value) if err != 0 {
return ioctl(fd, req, uintptr(unsafe.Pointer(&v))) return 0, err
} }
return int(ret), nil
// IoctlSetInt performs an ioctl operation which sets an integer value
// on fd, using the specified request number.
func IoctlSetInt(fd int, req uint, value int) error {
return ioctl(fd, req, uintptr(value))
}
func ioctlSetWinsize(fd int, req uint, value *Winsize) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
}
func ioctlSetTermios(fd int, req uint, value *Termios) error {
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
} }
func IoctlSetRTCTime(fd int, value *RTCTime) error { func IoctlSetRTCTime(fd int, value *RTCTime) error {
@ -101,12 +88,10 @@ func IoctlSetRTCTime(fd int, value *RTCTime) error {
return err return err
} }
// IoctlGetInt performs an ioctl operation which gets an integer value func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error {
// from fd, using the specified request number. err := ioctl(fd, RTC_WKALM_SET, uintptr(unsafe.Pointer(value)))
func IoctlGetInt(fd int, req uint) (int, error) { runtime.KeepAlive(value)
var value int return err
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return value, err
} }
func IoctlGetUint32(fd int, req uint) (uint32, error) { func IoctlGetUint32(fd int, req uint) (uint32, error) {
@ -115,24 +100,18 @@ func IoctlGetUint32(fd int, req uint) (uint32, error) {
return value, err return value, err
} }
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
var value Winsize
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
var value Termios
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
return &value, err
}
func IoctlGetRTCTime(fd int) (*RTCTime, error) { func IoctlGetRTCTime(fd int) (*RTCTime, error) {
var value RTCTime var value RTCTime
err := ioctl(fd, RTC_RD_TIME, uintptr(unsafe.Pointer(&value))) err := ioctl(fd, RTC_RD_TIME, uintptr(unsafe.Pointer(&value)))
return &value, err return &value, err
} }
func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) {
var value RTCWkAlrm
err := ioctl(fd, RTC_WKALM_RD, uintptr(unsafe.Pointer(&value)))
return &value, err
}
//sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) //sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
func Link(oldpath string, newpath string) (err error) { func Link(oldpath string, newpath string) (err error) {
@ -765,7 +744,7 @@ const px_proto_oe = 0
type SockaddrPPPoE struct { type SockaddrPPPoE struct {
SID uint16 SID uint16
Remote net.HardwareAddr Remote []byte
Dev string Dev string
raw RawSockaddrPPPoX raw RawSockaddrPPPoX
} }
@ -799,6 +778,133 @@ func (sa *SockaddrPPPoE) sockaddr() (unsafe.Pointer, _Socklen, error) {
return unsafe.Pointer(&sa.raw), SizeofSockaddrPPPoX, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrPPPoX, nil
} }
// SockaddrTIPC implements the Sockaddr interface for AF_TIPC type sockets.
// For more information on TIPC, see: http://tipc.sourceforge.net/.
type SockaddrTIPC struct {
// Scope is the publication scopes when binding service/service range.
// Should be set to TIPC_CLUSTER_SCOPE or TIPC_NODE_SCOPE.
Scope int
// Addr is the type of address used to manipulate a socket. Addr must be
// one of:
// - *TIPCSocketAddr: "id" variant in the C addr union
// - *TIPCServiceRange: "nameseq" variant in the C addr union
// - *TIPCServiceName: "name" variant in the C addr union
//
// If nil, EINVAL will be returned when the structure is used.
Addr TIPCAddr
raw RawSockaddrTIPC
}
// TIPCAddr is implemented by types that can be used as an address for
// SockaddrTIPC. It is only implemented by *TIPCSocketAddr, *TIPCServiceRange,
// and *TIPCServiceName.
type TIPCAddr interface {
tipcAddrtype() uint8
tipcAddr() [12]byte
}
func (sa *TIPCSocketAddr) tipcAddr() [12]byte {
var out [12]byte
copy(out[:], (*(*[unsafe.Sizeof(TIPCSocketAddr{})]byte)(unsafe.Pointer(sa)))[:])
return out
}
func (sa *TIPCSocketAddr) tipcAddrtype() uint8 { return TIPC_SOCKET_ADDR }
func (sa *TIPCServiceRange) tipcAddr() [12]byte {
var out [12]byte
copy(out[:], (*(*[unsafe.Sizeof(TIPCServiceRange{})]byte)(unsafe.Pointer(sa)))[:])
return out
}
func (sa *TIPCServiceRange) tipcAddrtype() uint8 { return TIPC_SERVICE_RANGE }
func (sa *TIPCServiceName) tipcAddr() [12]byte {
var out [12]byte
copy(out[:], (*(*[unsafe.Sizeof(TIPCServiceName{})]byte)(unsafe.Pointer(sa)))[:])
return out
}
func (sa *TIPCServiceName) tipcAddrtype() uint8 { return TIPC_SERVICE_ADDR }
func (sa *SockaddrTIPC) sockaddr() (unsafe.Pointer, _Socklen, error) {
if sa.Addr == nil {
return nil, 0, EINVAL
}
sa.raw.Family = AF_TIPC
sa.raw.Scope = int8(sa.Scope)
sa.raw.Addrtype = sa.Addr.tipcAddrtype()
sa.raw.Addr = sa.Addr.tipcAddr()
return unsafe.Pointer(&sa.raw), SizeofSockaddrTIPC, nil
}
// SockaddrL2TPIP implements the Sockaddr interface for IPPROTO_L2TP/AF_INET sockets.
type SockaddrL2TPIP struct {
Addr [4]byte
ConnId uint32
raw RawSockaddrL2TPIP
}
func (sa *SockaddrL2TPIP) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Family = AF_INET
sa.raw.Conn_id = sa.ConnId
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP, nil
}
// SockaddrL2TPIP6 implements the Sockaddr interface for IPPROTO_L2TP/AF_INET6 sockets.
type SockaddrL2TPIP6 struct {
Addr [16]byte
ZoneId uint32
ConnId uint32
raw RawSockaddrL2TPIP6
}
func (sa *SockaddrL2TPIP6) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Family = AF_INET6
sa.raw.Conn_id = sa.ConnId
sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP6, nil
}
// SockaddrIUCV implements the Sockaddr interface for AF_IUCV sockets.
type SockaddrIUCV struct {
UserID string
Name string
raw RawSockaddrIUCV
}
func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Family = AF_IUCV
// These are EBCDIC encoded by the kernel, but we still need to pad them
// with blanks. Initializing with blanks allows the caller to feed in either
// a padded or an unpadded string.
for i := 0; i < 8; i++ {
sa.raw.Nodeid[i] = ' '
sa.raw.User_id[i] = ' '
sa.raw.Name[i] = ' '
}
if len(sa.UserID) > 8 || len(sa.Name) > 8 {
return nil, 0, EINVAL
}
for i, b := range []byte(sa.UserID[:]) {
sa.raw.User_id[i] = int8(b)
}
for i, b := range []byte(sa.Name[:]) {
sa.raw.Name[i] = int8(b)
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrIUCV, nil
}
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
switch rsa.Addr.Family { switch rsa.Addr.Family {
case AF_NETLINK: case AF_NETLINK:
@ -844,11 +950,26 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
for n < len(pp.Path) && pp.Path[n] != 0 { for n < len(pp.Path) && pp.Path[n] != 0 {
n++ n++
} }
bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
sa.Name = string(bytes) sa.Name = string(bytes)
return sa, nil return sa, nil
case AF_INET: case AF_INET:
proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
if err != nil {
return nil, err
}
switch proto {
case IPPROTO_L2TP:
pp := (*RawSockaddrL2TPIP)(unsafe.Pointer(rsa))
sa := new(SockaddrL2TPIP)
sa.ConnId = pp.Conn_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
default:
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
sa := new(SockaddrInet4) sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port)) p := (*[2]byte)(unsafe.Pointer(&pp.Port))
@ -857,8 +978,25 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa.Addr[i] = pp.Addr[i] sa.Addr[i] = pp.Addr[i]
} }
return sa, nil return sa, nil
}
case AF_INET6: case AF_INET6:
proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
if err != nil {
return nil, err
}
switch proto {
case IPPROTO_L2TP:
pp := (*RawSockaddrL2TPIP6)(unsafe.Pointer(rsa))
sa := new(SockaddrL2TPIP6)
sa.ConnId = pp.Conn_id
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
default:
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
sa := new(SockaddrInet6) sa := new(SockaddrInet6)
p := (*[2]byte)(unsafe.Pointer(&pp.Port)) p := (*[2]byte)(unsafe.Pointer(&pp.Port))
@ -868,6 +1006,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa.Addr[i] = pp.Addr[i] sa.Addr[i] = pp.Addr[i]
} }
return sa, nil return sa, nil
}
case AF_VSOCK: case AF_VSOCK:
pp := (*RawSockaddrVM)(unsafe.Pointer(rsa)) pp := (*RawSockaddrVM)(unsafe.Pointer(rsa))
@ -916,7 +1055,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
} }
sa := &SockaddrPPPoE{ sa := &SockaddrPPPoE{
SID: binary.BigEndian.Uint16(pp[6:8]), SID: binary.BigEndian.Uint16(pp[6:8]),
Remote: net.HardwareAddr(pp[8:14]), Remote: pp[8:14],
} }
for i := 14; i < 14+IFNAMSIZ; i++ { for i := 14; i < 14+IFNAMSIZ; i++ {
if pp[i] == 0 { if pp[i] == 0 {
@ -925,6 +1064,59 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
} }
} }
return sa, nil return sa, nil
case AF_TIPC:
pp := (*RawSockaddrTIPC)(unsafe.Pointer(rsa))
sa := &SockaddrTIPC{
Scope: int(pp.Scope),
}
// Determine which union variant is present in pp.Addr by checking
// pp.Addrtype.
switch pp.Addrtype {
case TIPC_SERVICE_RANGE:
sa.Addr = (*TIPCServiceRange)(unsafe.Pointer(&pp.Addr))
case TIPC_SERVICE_ADDR:
sa.Addr = (*TIPCServiceName)(unsafe.Pointer(&pp.Addr))
case TIPC_SOCKET_ADDR:
sa.Addr = (*TIPCSocketAddr)(unsafe.Pointer(&pp.Addr))
default:
return nil, EINVAL
}
return sa, nil
case AF_IUCV:
pp := (*RawSockaddrIUCV)(unsafe.Pointer(rsa))
var user [8]byte
var name [8]byte
for i := 0; i < 8; i++ {
user[i] = byte(pp.User_id[i])
name[i] = byte(pp.Name[i])
}
sa := &SockaddrIUCV{
UserID: string(user[:]),
Name: string(name[:]),
}
return sa, nil
case AF_CAN:
pp := (*RawSockaddrCAN)(unsafe.Pointer(rsa))
sa := &SockaddrCAN{
Ifindex: int(pp.Ifindex),
}
rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
for i := 0; i < 4; i++ {
rx[i] = pp.Addr[i]
}
tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
for i := 0; i < 4; i++ {
tx[i] = pp.Addr[i+4]
}
return sa, nil
} }
return nil, EAFNOSUPPORT return nil, EAFNOSUPPORT
} }
@ -1161,6 +1353,34 @@ func KeyctlDHCompute(params *KeyctlDHParams, buffer []byte) (size int, err error
return keyctlDH(KEYCTL_DH_COMPUTE, params, buffer) return keyctlDH(KEYCTL_DH_COMPUTE, params, buffer)
} }
// KeyctlRestrictKeyring implements the KEYCTL_RESTRICT_KEYRING command. This
// command limits the set of keys that can be linked to the keyring, regardless
// of keyring permissions. The command requires the "setattr" permission.
//
// When called with an empty keyType the command locks the keyring, preventing
// any further keys from being linked to the keyring.
//
// The "asymmetric" keyType defines restrictions requiring key payloads to be
// DER encoded X.509 certificates signed by keys in another keyring. Restrictions
// for "asymmetric" include "builtin_trusted", "builtin_and_secondary_trusted",
// "key_or_keyring:<key>", and "key_or_keyring:<key>:chain".
//
// As of Linux 4.12, only the "asymmetric" keyType defines type-specific
// restrictions.
//
// See the full documentation at:
// http://man7.org/linux/man-pages/man3/keyctl_restrict_keyring.3.html
// http://man7.org/linux/man-pages/man2/keyctl.2.html
func KeyctlRestrictKeyring(ringid int, keyType string, restriction string) error {
if keyType == "" {
return keyctlRestrictKeyring(KEYCTL_RESTRICT_KEYRING, ringid)
}
return keyctlRestrictKeyringByType(KEYCTL_RESTRICT_KEYRING, ringid, keyType, restriction)
}
//sys keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) = SYS_KEYCTL
//sys keyctlRestrictKeyring(cmd int, arg2 int) (err error) = SYS_KEYCTL
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
var msg Msghdr var msg Msghdr
var rsa RawSockaddrAny var rsa RawSockaddrAny
@ -1404,8 +1624,12 @@ func PtraceSyscall(pid int, signal int) (err error) {
func PtraceSingleStep(pid int) (err error) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) } func PtraceSingleStep(pid int) (err error) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) }
func PtraceInterrupt(pid int) (err error) { return ptrace(PTRACE_INTERRUPT, pid, 0, 0) }
func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0) } func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0) }
func PtraceSeize(pid int) (err error) { return ptrace(PTRACE_SEIZE, pid, 0, 0) }
func PtraceDetach(pid int) (err error) { return ptrace(PTRACE_DETACH, pid, 0, 0) } func PtraceDetach(pid int) (err error) { return ptrace(PTRACE_DETACH, pid, 0, 0) }
//sys reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) //sys reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error)
@ -1414,8 +1638,20 @@ func Reboot(cmd int) (err error) {
return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "") return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
} }
func ReadDirent(fd int, buf []byte) (n int, err error) { func direntIno(buf []byte) (uint64, bool) {
return Getdents(fd, buf) return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
}
func direntReclen(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
}
func direntNamlen(buf []byte) (uint64, bool) {
reclen, ok := direntReclen(buf)
if !ok {
return 0, false
}
return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
} }
//sys mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) //sys mount(source string, target string, fstype string, flags uintptr, data *byte) (err error)
@ -1450,6 +1686,8 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Acct(path string) (err error) //sys Acct(path string) (err error)
//sys AddKey(keyType string, description string, payload []byte, ringid int) (id int, err error) //sys AddKey(keyType string, description string, payload []byte, ringid int) (id int, err error)
//sys Adjtimex(buf *Timex) (state int, err error) //sys Adjtimex(buf *Timex) (state int, err error)
//sysnb Capget(hdr *CapUserHeader, data *CapUserData) (err error)
//sysnb Capset(hdr *CapUserHeader, data *CapUserData) (err error)
//sys Chdir(path string) (err error) //sys Chdir(path string) (err error)
//sys Chroot(path string) (err error) //sys Chroot(path string) (err error)
//sys ClockGetres(clockid int32, res *Timespec) (err error) //sys ClockGetres(clockid int32, res *Timespec) (err error)
@ -1459,6 +1697,15 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) //sys CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
//sys DeleteModule(name string, flags int) (err error) //sys DeleteModule(name string, flags int) (err error)
//sys Dup(oldfd int) (fd int, err error) //sys Dup(oldfd int) (fd int, err error)
func Dup2(oldfd, newfd int) error {
// Android O and newer blocks dup2; riscv and arm64 don't implement dup2.
if runtime.GOOS == "android" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "arm64" {
return Dup3(oldfd, newfd, 0)
}
return dup2(oldfd, newfd)
}
//sys Dup3(oldfd int, newfd int, flags int) (err error) //sys Dup3(oldfd int, newfd int, flags int) (err error)
//sysnb EpollCreate1(flag int) (fd int, err error) //sysnb EpollCreate1(flag int) (fd int, err error)
//sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) //sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error)
@ -1468,7 +1715,6 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Fchdir(fd int) (err error) //sys Fchdir(fd int) (err error)
//sys Fchmod(fd int, mode uint32) (err error) //sys Fchmod(fd int, mode uint32) (err error)
//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
//sys fcntl(fd int, cmd int, arg int) (val int, err error)
//sys Fdatasync(fd int) (err error) //sys Fdatasync(fd int) (err error)
//sys Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) //sys Fgetxattr(fd int, attr string, dest []byte) (sz int, err error)
//sys FinitModule(fd int, params string, flags int) (err error) //sys FinitModule(fd int, params string, flags int) (err error)
@ -1524,6 +1770,17 @@ func Getpgrp() (pid int) {
//sysnb Settimeofday(tv *Timeval) (err error) //sysnb Settimeofday(tv *Timeval) (err error)
//sys Setns(fd int, nstype int) (err error) //sys Setns(fd int, nstype int) (err error)
// PrctlRetInt performs a prctl operation specified by option and further
// optional arguments arg2 through arg5 depending on option. It returns a
// non-negative integer that is returned by the prctl syscall.
func PrctlRetInt(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (int, error) {
ret, _, err := Syscall6(SYS_PRCTL, uintptr(option), uintptr(arg2), uintptr(arg3), uintptr(arg4), uintptr(arg5), 0)
if err != 0 {
return 0, err
}
return int(ret), nil
}
// issue 1435. // issue 1435.
// On linux Setuid and Setgid only affects the current thread, not the process. // On linux Setuid and Setgid only affects the current thread, not the process.
// This does not match what most callers expect so we must return an error // This does not match what most callers expect so we must return an error
@ -1537,6 +1794,30 @@ func Setgid(uid int) (err error) {
return EOPNOTSUPP return EOPNOTSUPP
} }
// SetfsgidRetGid sets fsgid for current thread and returns previous fsgid set.
// setfsgid(2) will return a non-nil error only if its caller lacks CAP_SETUID capability.
// If the call fails due to other reasons, current fsgid will be returned.
func SetfsgidRetGid(gid int) (int, error) {
return setfsgid(gid)
}
// SetfsuidRetUid sets fsuid for current thread and returns previous fsuid set.
// setfsgid(2) will return a non-nil error only if its caller lacks CAP_SETUID capability
// If the call fails due to other reasons, current fsuid will be returned.
func SetfsuidRetUid(uid int) (int, error) {
return setfsuid(uid)
}
func Setfsgid(gid int) error {
_, err := setfsgid(gid)
return err
}
func Setfsuid(uid int) error {
_, err := setfsuid(uid)
return err
}
func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) { func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) {
return signalfd(fd, sigmask, _C__NSIG/8, flags) return signalfd(fd, sigmask, _C__NSIG/8, flags)
} }
@ -1549,6 +1830,9 @@ func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) {
//sys Syncfs(fd int) (err error) //sys Syncfs(fd int) (err error)
//sysnb Sysinfo(info *Sysinfo_t) (err error) //sysnb Sysinfo(info *Sysinfo_t) (err error)
//sys Tee(rfd int, wfd int, len int, flags int) (n int64, err error) //sys Tee(rfd int, wfd int, len int, flags int) (n int64, err error)
//sysnb TimerfdCreate(clockid int, flags int) (fd int, err error)
//sysnb TimerfdGettime(fd int, currValue *ItimerSpec) (err error)
//sysnb TimerfdSettime(fd int, flags int, newValue *ItimerSpec, oldValue *ItimerSpec) (err error)
//sysnb Tgkill(tgid int, tid int, sig syscall.Signal) (err error) //sysnb Tgkill(tgid int, tid int, sig syscall.Signal) (err error)
//sysnb Times(tms *Tms) (ticks uintptr, err error) //sysnb Times(tms *Tms) (ticks uintptr, err error)
//sysnb Umask(mask int) (oldmask int) //sysnb Umask(mask int) (oldmask int)
@ -1559,6 +1843,123 @@ func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) {
//sys exitThread(code int) (err error) = SYS_EXIT //sys exitThread(code int) (err error) = SYS_EXIT
//sys readlen(fd int, p *byte, np int) (n int, err error) = SYS_READ //sys readlen(fd int, p *byte, np int) (n int, err error) = SYS_READ
//sys writelen(fd int, p *byte, np int) (n int, err error) = SYS_WRITE //sys writelen(fd int, p *byte, np int) (n int, err error) = SYS_WRITE
//sys readv(fd int, iovs []Iovec) (n int, err error) = SYS_READV
//sys writev(fd int, iovs []Iovec) (n int, err error) = SYS_WRITEV
//sys preadv(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) = SYS_PREADV
//sys pwritev(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) = SYS_PWRITEV
//sys preadv2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PREADV2
//sys pwritev2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PWRITEV2
func bytes2iovec(bs [][]byte) []Iovec {
iovecs := make([]Iovec, len(bs))
for i, b := range bs {
iovecs[i].SetLen(len(b))
if len(b) > 0 {
iovecs[i].Base = &b[0]
} else {
iovecs[i].Base = (*byte)(unsafe.Pointer(&_zero))
}
}
return iovecs
}
// offs2lohi splits offs into its lower and upper unsigned long. On 64-bit
// systems, hi will always be 0. On 32-bit systems, offs will be split in half.
// preadv/pwritev chose this calling convention so they don't need to add a
// padding-register for alignment on ARM.
func offs2lohi(offs int64) (lo, hi uintptr) {
return uintptr(offs), uintptr(uint64(offs) >> SizeofLong)
}
func Readv(fd int, iovs [][]byte) (n int, err error) {
iovecs := bytes2iovec(iovs)
n, err = readv(fd, iovecs)
readvRacedetect(iovecs, n, err)
return n, err
}
func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) {
iovecs := bytes2iovec(iovs)
lo, hi := offs2lohi(offset)
n, err = preadv(fd, iovecs, lo, hi)
readvRacedetect(iovecs, n, err)
return n, err
}
func Preadv2(fd int, iovs [][]byte, offset int64, flags int) (n int, err error) {
iovecs := bytes2iovec(iovs)
lo, hi := offs2lohi(offset)
n, err = preadv2(fd, iovecs, lo, hi, flags)
readvRacedetect(iovecs, n, err)
return n, err
}
func readvRacedetect(iovecs []Iovec, n int, err error) {
if !raceenabled {
return
}
for i := 0; n > 0 && i < len(iovecs); i++ {
m := int(iovecs[i].Len)
if m > n {
m = n
}
n -= m
if m > 0 {
raceWriteRange(unsafe.Pointer(iovecs[i].Base), m)
}
}
if err == nil {
raceAcquire(unsafe.Pointer(&ioSync))
}
}
func Writev(fd int, iovs [][]byte) (n int, err error) {
iovecs := bytes2iovec(iovs)
if raceenabled {
raceReleaseMerge(unsafe.Pointer(&ioSync))
}
n, err = writev(fd, iovecs)
writevRacedetect(iovecs, n)
return n, err
}
func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) {
iovecs := bytes2iovec(iovs)
if raceenabled {
raceReleaseMerge(unsafe.Pointer(&ioSync))
}
lo, hi := offs2lohi(offset)
n, err = pwritev(fd, iovecs, lo, hi)
writevRacedetect(iovecs, n)
return n, err
}
func Pwritev2(fd int, iovs [][]byte, offset int64, flags int) (n int, err error) {
iovecs := bytes2iovec(iovs)
if raceenabled {
raceReleaseMerge(unsafe.Pointer(&ioSync))
}
lo, hi := offs2lohi(offset)
n, err = pwritev2(fd, iovecs, lo, hi, flags)
writevRacedetect(iovecs, n)
return n, err
}
func writevRacedetect(iovecs []Iovec, n int) {
if !raceenabled {
return
}
for i := 0; n > 0 && i < len(iovecs); i++ {
m := int(iovecs[i].Len)
if m > n {
m = n
}
n -= m
if m > 0 {
raceReadRange(unsafe.Pointer(iovecs[i].Base), m)
}
}
}
// mmap varies by architecture; see syscall_linux_*.go. // mmap varies by architecture; see syscall_linux_*.go.
//sys munmap(addr uintptr, length uintptr) (err error) //sys munmap(addr uintptr, length uintptr) (err error)
@ -1601,11 +2002,30 @@ func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) {
return int(n), nil return int(n), nil
} }
func isGroupMember(gid int) bool {
groups, err := Getgroups()
if err != nil {
return false
}
for _, g := range groups {
if g == gid {
return true
}
}
return false
}
//sys faccessat(dirfd int, path string, mode uint32) (err error) //sys faccessat(dirfd int, path string, mode uint32) (err error)
//sys Faccessat2(dirfd int, path string, mode uint32, flags int) (err error)
func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
if flags & ^(AT_SYMLINK_NOFOLLOW|AT_EACCESS) != 0 { if flags == 0 {
return EINVAL return faccessat(dirfd, path, mode)
}
if err := Faccessat2(dirfd, path, mode, flags); err != ENOSYS && err != EPERM {
return err
} }
// The Linux kernel faccessat system call does not take any flags. // The Linux kernel faccessat system call does not take any flags.
@ -1614,8 +2034,8 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
// Because people naturally expect syscall.Faccessat to act // Because people naturally expect syscall.Faccessat to act
// like C faccessat, we do the same. // like C faccessat, we do the same.
if flags == 0 { if flags & ^(AT_SYMLINK_NOFOLLOW|AT_EACCESS) != 0 {
return faccessat(dirfd, path, mode) return EINVAL
} }
var st Stat_t var st Stat_t
@ -1658,7 +2078,7 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
gid = Getgid() gid = Getgid()
} }
if uint32(gid) == st.Gid { if uint32(gid) == st.Gid || isGroupMember(gid) {
fmode = (st.Mode >> 3) & 7 fmode = (st.Mode >> 3) & 7
} else { } else {
fmode = st.Mode & 7 fmode = st.Mode & 7
@ -1748,6 +2168,29 @@ func OpenByHandleAt(mountFD int, handle FileHandle, flags int) (fd int, err erro
return openByHandleAt(mountFD, handle.fileHandle, flags) return openByHandleAt(mountFD, handle.fileHandle, flags)
} }
// Klogset wraps the sys_syslog system call; it sets console_loglevel to
// the value specified by arg and passes a dummy pointer to bufp.
func Klogset(typ int, arg int) (err error) {
var p unsafe.Pointer
_, _, errno := Syscall(SYS_SYSLOG, uintptr(typ), uintptr(p), uintptr(arg))
if errno != 0 {
return errnoErr(errno)
}
return nil
}
// RemoteIovec is Iovec with the pointer replaced with an integer.
// It is used for ProcessVMReadv and ProcessVMWritev, where the pointer
// refers to a location in a different process' address space, which
// would confuse the Go garbage collector.
type RemoteIovec struct {
Base uintptr
Len int
}
//sys ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_READV
//sys ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_WRITEV
/* /*
* Unimplemented * Unimplemented
*/ */
@ -1755,8 +2198,6 @@ func OpenByHandleAt(mountFD int, handle FileHandle, flags int) (fd int, err erro
// Alarm // Alarm
// ArchPrctl // ArchPrctl
// Brk // Brk
// Capget
// Capset
// ClockNanosleep // ClockNanosleep
// ClockSettime // ClockSettime
// Clone // Clone
@ -1844,7 +2285,6 @@ func OpenByHandleAt(mountFD int, handle FileHandle, flags int) (fd int, err erro
// TimerGetoverrun // TimerGetoverrun
// TimerGettime // TimerGettime
// TimerSettime // TimerSettime
// Timerfd
// Tkill (obsolete) // Tkill (obsolete)
// Tuxcall // Tuxcall
// Umount2 // Umount2

View File

@ -49,7 +49,7 @@ func Pipe2(p []int, flags int) (err error) {
// 64-bit file system and 32-bit uid calls // 64-bit file system and 32-bit uid calls
// (386 default is 32-bit file system and 16-bit uid). // (386 default is 32-bit file system and 16-bit uid).
//sys Dup2(oldfd int, newfd int) (err error) //sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error) //sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64
@ -70,8 +70,8 @@ func Pipe2(p []int, flags int) (err error) {
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64 //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Setfsgid(gid int) (err error) = SYS_SETFSGID32 //sys setfsgid(gid int) (prev int, err error) = SYS_SETFSGID32
//sys Setfsuid(uid int) (err error) = SYS_SETFSUID32 //sys setfsuid(uid int) (prev int, err error) = SYS_SETFSUID32
//sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32 //sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32 //sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32
//sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32 //sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32
@ -372,6 +372,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = uint32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }

View File

@ -6,7 +6,7 @@
package unix package unix
//sys Dup2(oldfd int, newfd int) (err error) //sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error) //sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
@ -55,8 +55,8 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
} }
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error) //sys setfsgid(gid int) (prev int, err error)
//sys Setfsuid(uid int) (err error) //sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error) //sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error)
@ -163,6 +163,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint64(length) msghdr.Controllen = uint64(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = uint64(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length) cmsg.Len = uint64(length)
} }

View File

@ -7,7 +7,6 @@
package unix package unix
import ( import (
"syscall"
"unsafe" "unsafe"
) )
@ -49,10 +48,6 @@ func Pipe2(p []int, flags int) (err error) {
return return
} }
// Underlying system call writes to newoffset via pointer.
// Implemented in assembly to avoid allocation.
func seek(fd int, offset int64, whence int) (newoffset int64, err syscall.Errno)
func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
newoffset, errno := seek(fd, offset, whence) newoffset, errno := seek(fd, offset, whence)
if errno != 0 { if errno != 0 {
@ -80,7 +75,7 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
// 64-bit file system and 32-bit uid calls // 64-bit file system and 32-bit uid calls
// (16-bit uid calls are not always supported in newer kernels) // (16-bit uid calls are not always supported in newer kernels)
//sys Dup2(oldfd int, newfd int) (err error) //sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error) //sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32 //sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
@ -98,8 +93,8 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64 //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys Setfsgid(gid int) (err error) = SYS_SETFSGID32 //sys setfsgid(gid int) (prev int, err error) = SYS_SETFSGID32
//sys Setfsuid(uid int) (err error) = SYS_SETFSUID32 //sys setfsuid(uid int) (prev int, err error) = SYS_SETFSUID32
//sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32 //sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32 //sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32
//sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32 //sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32
@ -252,6 +247,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = uint32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }

View File

@ -25,7 +25,7 @@ func EpollCreate(size int) (fd int, err error) {
//sysnb Getegid() (egid int) //sysnb Getegid() (egid int)
//sysnb Geteuid() (euid int) //sysnb Geteuid() (euid int)
//sysnb Getgid() (gid int) //sysnb Getgid() (gid int)
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //sysnb getrlimit(resource int, rlim *Rlimit) (err error)
//sysnb Getuid() (uid int) //sysnb Getuid() (uid int)
//sys Listen(s int, n int) (err error) //sys Listen(s int, n int) (err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 //sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
@ -42,12 +42,12 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
} }
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error) //sys setfsgid(gid int) (prev int, err error)
//sys Setfsuid(uid int) (err error) //sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error) //sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error)
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error) //sysnb setrlimit(resource int, rlim *Rlimit) (err error)
//sysnb Setreuid(ruid int, euid int) (err error) //sysnb Setreuid(ruid int, euid int) (err error)
//sys Shutdown(fd int, how int) (err error) //sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
@ -168,6 +168,24 @@ func Pipe2(p []int, flags int) (err error) {
return return
} }
// Getrlimit prefers the prlimit64 system call. See issue 38604.
func Getrlimit(resource int, rlim *Rlimit) error {
err := prlimit(0, resource, nil, rlim)
if err != ENOSYS {
return err
}
return getrlimit(resource, rlim)
}
// Setrlimit prefers the prlimit64 system call. See issue 38604.
func Setrlimit(resource int, rlim *Rlimit) error {
err := prlimit(0, resource, rlim, nil)
if err != ENOSYS {
return err
}
return setrlimit(resource, rlim)
}
func (r *PtraceRegs) PC() uint64 { return r.Pc } func (r *PtraceRegs) PC() uint64 { return r.Pc }
func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc } func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc }
@ -180,6 +198,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint64(length) msghdr.Controllen = uint64(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = uint64(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length) cmsg.Len = uint64(length)
} }
@ -188,9 +210,9 @@ func InotifyInit() (fd int, err error) {
return InotifyInit1(0) return InotifyInit1(0)
} }
func Dup2(oldfd int, newfd int) (err error) { // dup2 exists because func Dup3 in syscall_linux.go references
return Dup3(oldfd, newfd, 0) // it in an unreachable path. dup2 isn't available on arm64.
} func dup2(oldfd int, newfd int) error
func Pause() error { func Pause() error {
_, err := ppoll(nil, 0, nil, nil) _, err := ppoll(nil, 0, nil, nil)

13
vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build arm,!gccgo,linux
package unix
import "syscall"
// Underlying system call writes to newoffset via pointer.
// Implemented in assembly to avoid allocation.
func seek(fd int, offset int64, whence int) (newoffset int64, err syscall.Errno)

View File

@ -7,7 +7,7 @@
package unix package unix
//sys Dup2(oldfd int, newfd int) (err error) //sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error) //sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
@ -36,8 +36,8 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
} }
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error) //sys setfsgid(gid int) (prev int, err error)
//sys Setfsuid(uid int) (err error) //sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error) //sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error)
@ -208,10 +208,18 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint64(length) msghdr.Controllen = uint64(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = uint64(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length) cmsg.Len = uint64(length)
} }
func InotifyInit() (fd int, err error) {
return InotifyInit1(0)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) //sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) { func Poll(fds []PollFd, timeout int) (n int, err error) {

View File

@ -14,7 +14,7 @@ import (
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
//sys Dup2(oldfd int, newfd int) (err error) //sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error) //sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
@ -31,8 +31,8 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64 //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Setfsgid(gid int) (err error) //sys setfsgid(gid int) (prev int, err error)
//sys Setfsuid(uid int) (err error) //sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error) //sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error)
@ -220,6 +220,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length) msghdr.Controllen = uint32(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = uint32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }

View File

@ -7,7 +7,7 @@
package unix package unix
//sys Dup2(oldfd int, newfd int) (err error) //sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error) //sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
@ -34,8 +34,8 @@ package unix
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error) //sys setfsgid(gid int) (prev int, err error)
//sys Setfsuid(uid int) (err error) //sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error) //sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error)
@ -91,6 +91,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint64(length) msghdr.Controllen = uint64(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = uint64(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length) cmsg.Len = uint64(length)
} }

View File

@ -41,8 +41,8 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
} }
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error) //sys setfsgid(gid int) (prev int, err error)
//sys Setfsuid(uid int) (err error) //sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error) //sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error)
@ -179,6 +179,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint64(length) msghdr.Controllen = uint64(length)
} }
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = uint64(length)
}
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length) cmsg.Len = uint64(length)
} }
@ -187,10 +191,6 @@ func InotifyInit() (fd int, err error) {
return InotifyInit1(0) return InotifyInit1(0)
} }
func Dup2(oldfd int, newfd int) (err error) {
return Dup3(oldfd, newfd, 0)
}
func Pause() error { func Pause() error {
_, err := ppoll(nil, 0, nil, nil) _, err := ppoll(nil, 0, nil, nil)
return err return err
@ -224,3 +224,7 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error
} }
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags) return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
} }
// dup2 exists because func Dup3 in syscall_linux.go references
// it in an unreachable path. dup2 isn't available on arm64.
func dup2(oldfd int, newfd int) error

Some files were not shown because too many files have changed in this diff Show More