diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 51e0c241..1eeeb2a0 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -220,15 +220,15 @@ }, { "ImportPath": "github.com/vishvananda/netlink", - "Rev": "fe3b5664d23a11b52ba59bece4ff29c52772a56b" + "Rev": "6e453822d85ef5721799774b654d4d02fed62afb" }, { "ImportPath": "github.com/vishvananda/netlink/nl", - "Rev": "fe3b5664d23a11b52ba59bece4ff29c52772a56b" + "Rev": "6e453822d85ef5721799774b654d4d02fed62afb" }, { "ImportPath": "github.com/vishvananda/netns", - "Rev": "8ba1072b58e0c2a240eb5f6120165c7776c3e7b8" + "Rev": "54f0e4339ce73702a0607f49922aaa1e749b418d" }, { "ImportPath": "golang.org/x/sys/unix", diff --git a/vendor/github.com/vishvananda/netlink/.travis.yml b/vendor/github.com/vishvananda/netlink/.travis.yml index 73a0374c..f5c0b3eb 100644 --- a/vendor/github.com/vishvananda/netlink/.travis.yml +++ b/vendor/github.com/vishvananda/netlink/.travis.yml @@ -4,5 +4,10 @@ before_script: - sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers # modprobe ip_gre or else the first gre device can't be deleted - sudo modprobe ip_gre + # modprobe nf_conntrack for the conntrack testing + - sudo modprobe nf_conntrack + - sudo modprobe nf_conntrack_netlink + - sudo modprobe nf_conntrack_ipv4 + - sudo modprobe nf_conntrack_ipv6 install: - go get github.com/vishvananda/netns diff --git a/vendor/github.com/vishvananda/netlink/addr.go b/vendor/github.com/vishvananda/netlink/addr.go index fe3e3d36..f08c9569 100644 --- a/vendor/github.com/vishvananda/netlink/addr.go +++ b/vendor/github.com/vishvananda/netlink/addr.go @@ -10,11 +10,13 @@ import ( // include a mask, so it stores the address as a net.IPNet. type Addr struct { *net.IPNet - Label string - Flags int - Scope int - Peer *net.IPNet - Broadcast net.IP + Label string + Flags int + Scope int + Peer *net.IPNet + Broadcast net.IP + PreferedLft int + ValidLft int } // String returns $ip/$netmask $label diff --git a/vendor/github.com/vishvananda/netlink/addr_linux.go b/vendor/github.com/vishvananda/netlink/addr_linux.go index 5348e403..f33242a7 100644 --- a/vendor/github.com/vishvananda/netlink/addr_linux.go +++ b/vendor/github.com/vishvananda/netlink/addr_linux.go @@ -27,6 +27,19 @@ func (h *Handle) AddrAdd(link Link, addr *Addr) error { return h.addrHandle(link, addr, req) } +// AddrReplace will replace (or, if not present, add) an IP address on a link device. +// Equivalent to: `ip addr replace $addr dev $link` +func AddrReplace(link Link, addr *Addr) error { + return pkgHandle.AddrReplace(link, addr) +} + +// AddrReplace will replace (or, if not present, add) an IP address on a link device. +// Equivalent to: `ip addr replace $addr dev $link` +func (h *Handle) AddrReplace(link Link, addr *Addr) error { + req := h.newNetlinkRequest(syscall.RTM_NEWADDR, syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE|syscall.NLM_F_ACK) + return h.addrHandle(link, addr, req) +} + // AddrDel will delete an IP address from a link device. // Equivalent to: `ip addr del $addr dev $link` func AddrDel(link Link, addr *Addr) error { @@ -182,10 +195,16 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) { Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), } addr.IPNet = local + case syscall.IFA_BROADCAST: + addr.Broadcast = attr.Value case syscall.IFA_LABEL: addr.Label = string(attr.Value[:len(attr.Value)-1]) case IFA_FLAGS: addr.Flags = int(native.Uint32(attr.Value[0:4])) + case nl.IFA_CACHEINFO: + ci := nl.DeserializeIfaCacheInfo(attr.Value) + addr.PreferedLft = int(ci.IfaPrefered) + addr.ValidLft = int(ci.IfaValid) } } @@ -203,6 +222,10 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) { type AddrUpdate struct { LinkAddress net.IPNet LinkIndex int + Flags int + Scope int + PreferedLft int + ValidLft int NewAddr bool // true=added false=deleted } @@ -250,7 +273,13 @@ func addrSubscribe(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-cha continue } - ch <- AddrUpdate{LinkAddress: *addr.IPNet, LinkIndex: ifindex, NewAddr: msgType == syscall.RTM_NEWADDR} + ch <- AddrUpdate{LinkAddress: *addr.IPNet, + LinkIndex: ifindex, + NewAddr: msgType == syscall.RTM_NEWADDR, + Flags: addr.Flags, + Scope: addr.Scope, + PreferedLft: addr.PreferedLft, + ValidLft: addr.ValidLft} } } }() diff --git a/vendor/github.com/vishvananda/netlink/bridge_linux.go b/vendor/github.com/vishvananda/netlink/bridge_linux.go new file mode 100644 index 00000000..a65d6a13 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/bridge_linux.go @@ -0,0 +1,115 @@ +package netlink + +import ( + "fmt" + "syscall" + + "github.com/vishvananda/netlink/nl" +) + +// BridgeVlanList gets a map of device id to bridge vlan infos. +// Equivalent to: `bridge vlan show` +func BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) { + return pkgHandle.BridgeVlanList() +} + +// BridgeVlanList gets a map of device id to bridge vlan infos. +// Equivalent to: `bridge vlan show` +func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) { + req := h.newNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_DUMP) + msg := nl.NewIfInfomsg(syscall.AF_BRIDGE) + req.AddData(msg) + req.AddData(nl.NewRtAttr(nl.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN)))) + + msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWLINK) + if err != nil { + return nil, err + } + ret := make(map[int32][]*nl.BridgeVlanInfo) + for _, m := range msgs { + msg := nl.DeserializeIfInfomsg(m) + + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return nil, err + } + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.IFLA_AF_SPEC: + //nested attr + nestAttrs, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, fmt.Errorf("failed to parse nested attr %v", err) + } + for _, nestAttr := range nestAttrs { + switch nestAttr.Attr.Type { + case nl.IFLA_BRIDGE_VLAN_INFO: + vlanInfo := nl.DeserializeBridgeVlanInfo(nestAttr.Value) + ret[msg.Index] = append(ret[msg.Index], vlanInfo) + } + } + } + } + } + return ret, nil +} + +// BridgeVlanAdd adds a new vlan filter entry +// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` +func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error { + return pkgHandle.BridgeVlanAdd(link, vid, pvid, untagged, self, master) +} + +// BridgeVlanAdd adds a new vlan filter entry +// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` +func (h *Handle) BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error { + return h.bridgeVlanModify(syscall.RTM_SETLINK, link, vid, pvid, untagged, self, master) +} + +// BridgeVlanDel adds a new vlan filter entry +// Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` +func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error { + return pkgHandle.BridgeVlanDel(link, vid, pvid, untagged, self, master) +} + +// BridgeVlanDel adds a new vlan filter entry +// Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` +func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error { + return h.bridgeVlanModify(syscall.RTM_DELLINK, link, vid, pvid, untagged, self, master) +} + +func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged, self, master bool) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(cmd, syscall.NLM_F_ACK) + + msg := nl.NewIfInfomsg(syscall.AF_BRIDGE) + msg.Index = int32(base.Index) + req.AddData(msg) + + br := nl.NewRtAttr(nl.IFLA_AF_SPEC, nil) + var flags uint16 + if self { + flags |= nl.BRIDGE_FLAGS_SELF + } + if master { + flags |= nl.BRIDGE_FLAGS_MASTER + } + if flags > 0 { + nl.NewRtAttrChild(br, nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags)) + } + vlanInfo := &nl.BridgeVlanInfo{Vid: vid} + if pvid { + vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_PVID + } + if untagged { + vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED + } + nl.NewRtAttrChild(br, nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize()) + req.AddData(br) + _, err := req.Execute(syscall.NETLINK_ROUTE, 0) + if err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/vishvananda/netlink/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/conntrack_linux.go new file mode 100644 index 00000000..bcdd6920 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/conntrack_linux.go @@ -0,0 +1,352 @@ +package netlink + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "net" + "syscall" + + "github.com/vishvananda/netlink/nl" +) + +// ConntrackTableType Conntrack table for the netlink operation +type ConntrackTableType uint8 + +const ( + // ConntrackTable Conntrack table + // https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink.h -> #define NFNL_SUBSYS_CTNETLINK 1 + ConntrackTable = 1 + // ConntrackExpectTable Conntrack expect table + // https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink.h -> #define NFNL_SUBSYS_CTNETLINK_EXP 2 + ConntrackExpectTable = 2 +) + +const ( + // backward compatibility with golang 1.6 which does not have io.SeekCurrent + seekCurrent = 1 +) + +// InetFamily Family type +type InetFamily uint8 + +// -L [table] [options] List conntrack or expectation table +// -G [table] parameters Get conntrack or expectation + +// -I [table] parameters Create a conntrack or expectation +// -U [table] parameters Update a conntrack +// -E [table] [options] Show events + +// -C [table] Show counter +// -S Show statistics + +// ConntrackTableList returns the flow list of a table of a specific family +// conntrack -L [table] [options] List conntrack or expectation table +func ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { + return pkgHandle.ConntrackTableList(table, family) +} + +// ConntrackTableFlush flushes all the flows of a specified table +// conntrack -F [table] Flush table +// The flush operation applies to all the family types +func ConntrackTableFlush(table ConntrackTableType) error { + return pkgHandle.ConntrackTableFlush(table) +} + +// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter +// conntrack -D [table] parameters Delete conntrack or expectation +func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) { + return pkgHandle.ConntrackDeleteFilter(table, family, filter) +} + +// ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed +// conntrack -L [table] [options] List conntrack or expectation table +func (h *Handle) ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { + res, err := h.dumpConntrackTable(table, family) + if err != nil { + return nil, err + } + + // Deserialize all the flows + var result []*ConntrackFlow + for _, dataRaw := range res { + result = append(result, parseRawData(dataRaw)) + } + + return result, nil +} + +// ConntrackTableFlush flushes all the flows of a specified table using the netlink handle passed +// conntrack -F [table] Flush table +// The flush operation applies to all the family types +func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error { + req := h.newConntrackRequest(table, syscall.AF_INET, nl.IPCTNL_MSG_CT_DELETE, syscall.NLM_F_ACK) + _, err := req.Execute(syscall.NETLINK_NETFILTER, 0) + return err +} + +// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter using the netlink handle passed +// conntrack -D [table] parameters Delete conntrack or expectation +func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) { + res, err := h.dumpConntrackTable(table, family) + if err != nil { + return 0, err + } + + var matched uint + for _, dataRaw := range res { + flow := parseRawData(dataRaw) + if match := filter.MatchConntrackFlow(flow); match { + req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, syscall.NLM_F_ACK) + // skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already + req2.AddRawData(dataRaw[4:]) + req2.Execute(syscall.NETLINK_NETFILTER, 0) + matched++ + } + } + + return matched, nil +} + +func (h *Handle) newConntrackRequest(table ConntrackTableType, family InetFamily, operation, flags int) *nl.NetlinkRequest { + // Create the Netlink request object + req := h.newNetlinkRequest((int(table)<<8)|operation, flags) + // Add the netfilter header + msg := &nl.Nfgenmsg{ + NfgenFamily: uint8(family), + Version: nl.NFNETLINK_V0, + ResId: 0, + } + req.AddData(msg) + return req +} + +func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily) ([][]byte, error) { + req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_GET, syscall.NLM_F_DUMP) + return req.Execute(syscall.NETLINK_NETFILTER, 0) +} + +// The full conntrack flow structure is very complicated and can be found in the file: +// http://git.netfilter.org/libnetfilter_conntrack/tree/include/internal/object.h +// For the time being, the structure below allows to parse and extract the base information of a flow +type ipTuple struct { + SrcIP net.IP + DstIP net.IP + Protocol uint8 + SrcPort uint16 + DstPort uint16 +} + +type ConntrackFlow struct { + FamilyType uint8 + Forward ipTuple + Reverse ipTuple +} + +func (s *ConntrackFlow) String() string { + // conntrack cmd output: + // udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 + return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d\tsrc=%s dst=%s sport=%d dport=%d", + nl.L4ProtoMap[s.Forward.Protocol], s.Forward.Protocol, + s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort, + s.Reverse.SrcIP.String(), s.Reverse.DstIP.String(), s.Reverse.SrcPort, s.Reverse.DstPort) +} + +// This method parse the ip tuple structure +// The message structure is the following: +// +// +// +// +// +func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) { + for i := 0; i < 2; i++ { + _, t, _, v := parseNfAttrTLV(reader) + switch t { + case nl.CTA_IP_V4_SRC, nl.CTA_IP_V6_SRC: + tpl.SrcIP = v + case nl.CTA_IP_V4_DST, nl.CTA_IP_V6_DST: + tpl.DstIP = v + } + } + // Skip the next 4 bytes nl.NLA_F_NESTED|nl.CTA_TUPLE_PROTO + reader.Seek(4, seekCurrent) + _, t, _, v := parseNfAttrTLV(reader) + if t == nl.CTA_PROTO_NUM { + tpl.Protocol = uint8(v[0]) + } + // Skip some padding 3 bytes + reader.Seek(3, seekCurrent) + for i := 0; i < 2; i++ { + _, t, _ := parseNfAttrTL(reader) + switch t { + case nl.CTA_PROTO_SRC_PORT: + parseBERaw16(reader, &tpl.SrcPort) + case nl.CTA_PROTO_DST_PORT: + parseBERaw16(reader, &tpl.DstPort) + } + // Skip some padding 2 byte + reader.Seek(2, seekCurrent) + } +} + +func parseNfAttrTLV(r *bytes.Reader) (isNested bool, attrType, len uint16, value []byte) { + isNested, attrType, len = parseNfAttrTL(r) + + value = make([]byte, len) + binary.Read(r, binary.BigEndian, &value) + return isNested, attrType, len, value +} + +func parseNfAttrTL(r *bytes.Reader) (isNested bool, attrType, len uint16) { + binary.Read(r, nl.NativeEndian(), &len) + len -= nl.SizeofNfattr + + binary.Read(r, nl.NativeEndian(), &attrType) + isNested = (attrType & nl.NLA_F_NESTED) == nl.NLA_F_NESTED + attrType = attrType & (nl.NLA_F_NESTED - 1) + + return isNested, attrType, len +} + +func parseBERaw16(r *bytes.Reader, v *uint16) { + binary.Read(r, binary.BigEndian, v) +} + +func parseRawData(data []byte) *ConntrackFlow { + s := &ConntrackFlow{} + // First there is the Nfgenmsg header + // consume only the family field + reader := bytes.NewReader(data) + binary.Read(reader, nl.NativeEndian(), &s.FamilyType) + + // skip rest of the Netfilter header + reader.Seek(3, seekCurrent) + // The message structure is the following: + // 4 bytes + // 4 bytes + // flow information of the forward flow + // 4 bytes + // 4 bytes + // flow information of the reverse flow + for reader.Len() > 0 { + nested, t, l := parseNfAttrTL(reader) + if nested && t == nl.CTA_TUPLE_ORIG { + if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP { + parseIpTuple(reader, &s.Forward) + } + } else if nested && t == nl.CTA_TUPLE_REPLY { + if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP { + parseIpTuple(reader, &s.Reverse) + + // Got all the useful information stop parsing + break + } else { + // Header not recognized skip it + reader.Seek(int64(l), seekCurrent) + } + } + } + + return s +} + +// Conntrack parameters and options: +// -n, --src-nat ip source NAT ip +// -g, --dst-nat ip destination NAT ip +// -j, --any-nat ip source or destination NAT ip +// -m, --mark mark Set mark +// -c, --secmark secmark Set selinux secmark +// -e, --event-mask eventmask Event mask, eg. NEW,DESTROY +// -z, --zero Zero counters while listing +// -o, --output type[,...] Output format, eg. xml +// -l, --label label[,...] conntrack labels + +// Common parameters and options: +// -s, --src, --orig-src ip Source address from original direction +// -d, --dst, --orig-dst ip Destination address from original direction +// -r, --reply-src ip Source addres from reply direction +// -q, --reply-dst ip Destination address from reply direction +// -p, --protonum proto Layer 4 Protocol, eg. 'tcp' +// -f, --family proto Layer 3 Protocol, eg. 'ipv6' +// -t, --timeout timeout Set timeout +// -u, --status status Set status, eg. ASSURED +// -w, --zone value Set conntrack zone +// --orig-zone value Set zone for original direction +// --reply-zone value Set zone for reply direction +// -b, --buffer-size Netlink socket buffer size +// --mask-src ip Source mask address +// --mask-dst ip Destination mask address + +// Filter types +type ConntrackFilterType uint8 + +const ( + ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction + ConntrackOrigDstIP // -orig-dst ip Destination address from original direction + ConntrackNatSrcIP // -src-nat ip Source NAT ip + ConntrackNatDstIP // -dst-nat ip Destination NAT ip + ConntrackNatAnyIP // -any-nat ip Source or destination NAT ip +) + +type CustomConntrackFilter interface { + // MatchConntrackFlow applies the filter to the flow and returns true if the flow matches + // the filter or false otherwise + MatchConntrackFlow(flow *ConntrackFlow) bool +} + +type ConntrackFilter struct { + ipFilter map[ConntrackFilterType]net.IP +} + +// AddIP adds an IP to the conntrack filter +func (f *ConntrackFilter) AddIP(tp ConntrackFilterType, ip net.IP) error { + if f.ipFilter == nil { + f.ipFilter = make(map[ConntrackFilterType]net.IP) + } + if _, ok := f.ipFilter[tp]; ok { + return errors.New("Filter attribute already present") + } + f.ipFilter[tp] = ip + return nil +} + +// MatchConntrackFlow applies the filter to the flow and returns true if the flow matches the filter +// false otherwise +func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool { + if len(f.ipFilter) == 0 { + // empty filter always not match + return false + } + + match := true + // -orig-src ip Source address from original direction + if elem, found := f.ipFilter[ConntrackOrigSrcIP]; found { + match = match && elem.Equal(flow.Forward.SrcIP) + } + + // -orig-dst ip Destination address from original direction + if elem, found := f.ipFilter[ConntrackOrigDstIP]; match && found { + match = match && elem.Equal(flow.Forward.DstIP) + } + + // -src-nat ip Source NAT ip + if elem, found := f.ipFilter[ConntrackNatSrcIP]; match && found { + match = match && elem.Equal(flow.Reverse.SrcIP) + } + + // -dst-nat ip Destination NAT ip + if elem, found := f.ipFilter[ConntrackNatDstIP]; match && found { + match = match && elem.Equal(flow.Reverse.DstIP) + } + + // -any-nat ip Source or destination NAT ip + if elem, found := f.ipFilter[ConntrackNatAnyIP]; match && found { + match = match && (elem.Equal(flow.Reverse.SrcIP) || elem.Equal(flow.Reverse.DstIP)) + } + + return match +} + +var _ CustomConntrackFilter = (*ConntrackFilter)(nil) diff --git a/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go b/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go new file mode 100644 index 00000000..af7af799 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go @@ -0,0 +1,53 @@ +// +build !linux + +package netlink + +// ConntrackTableType Conntrack table for the netlink operation +type ConntrackTableType uint8 + +// InetFamily Family type +type InetFamily uint8 + +// ConntrackFlow placeholder +type ConntrackFlow struct{} + +// ConntrackFilter placeholder +type ConntrackFilter struct{} + +// ConntrackTableList returns the flow list of a table of a specific family +// conntrack -L [table] [options] List conntrack or expectation table +func ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { + return nil, ErrNotImplemented +} + +// ConntrackTableFlush flushes all the flows of a specified table +// conntrack -F [table] Flush table +// The flush operation applies to all the family types +func ConntrackTableFlush(table ConntrackTableType) error { + return ErrNotImplemented +} + +// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter +// conntrack -D [table] parameters Delete conntrack or expectation +func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter *ConntrackFilter) (uint, error) { + return 0, ErrNotImplemented +} + +// ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed +// conntrack -L [table] [options] List conntrack or expectation table +func (h *Handle) ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { + return nil, ErrNotImplemented +} + +// ConntrackTableFlush flushes all the flows of a specified table using the netlink handle passed +// conntrack -F [table] Flush table +// The flush operation applies to all the family types +func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error { + return ErrNotImplemented +} + +// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter using the netlink handle passed +// conntrack -D [table] parameters Delete conntrack or expectation +func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter *ConntrackFilter) (uint, error) { + return 0, ErrNotImplemented +} diff --git a/vendor/github.com/vishvananda/netlink/filter.go b/vendor/github.com/vishvananda/netlink/filter.go index bc8a1e96..938b28b0 100644 --- a/vendor/github.com/vishvananda/netlink/filter.go +++ b/vendor/github.com/vishvananda/netlink/filter.go @@ -1,6 +1,10 @@ package netlink -import "fmt" +import ( + "fmt" + + "github.com/vishvananda/netlink/nl" +) type Filter interface { Attrs() *FilterAttrs @@ -180,11 +184,46 @@ func NewMirredAction(redirIndex int) *MirredAction { } } +// Constants used in TcU32Sel.Flags. +const ( + TC_U32_TERMINAL = nl.TC_U32_TERMINAL + TC_U32_OFFSET = nl.TC_U32_OFFSET + TC_U32_VAROFFSET = nl.TC_U32_VAROFFSET + TC_U32_EAT = nl.TC_U32_EAT +) + +// Sel of the U32 filters that contains multiple TcU32Key. This is the copy +// and the frontend representation of nl.TcU32Sel. It is serialized into canonical +// nl.TcU32Sel with the appropriate endianness. +type TcU32Sel struct { + Flags uint8 + Offshift uint8 + Nkeys uint8 + Pad uint8 + Offmask uint16 + Off uint16 + Offoff int16 + Hoff int16 + Hmask uint32 + Keys []TcU32Key +} + +// TcU32Key contained of Sel in the U32 filters. This is the copy and the frontend +// representation of nl.TcU32Key. It is serialized into chanonical nl.TcU32Sel +// with the appropriate endianness. +type TcU32Key struct { + Mask uint32 + Val uint32 + Off int32 + OffMask int32 +} + // U32 filters on many packet related properties type U32 struct { FilterAttrs ClassId uint32 RedirIndex int + Sel *TcU32Sel Actions []Action } diff --git a/vendor/github.com/vishvananda/netlink/filter_linux.go b/vendor/github.com/vishvananda/netlink/filter_linux.go index d9aedca7..dc0f90af 100644 --- a/vendor/github.com/vishvananda/netlink/filter_linux.go +++ b/vendor/github.com/vishvananda/netlink/filter_linux.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "syscall" + "unsafe" "github.com/vishvananda/netlink/nl" ) @@ -128,12 +129,34 @@ func (h *Handle) FilterAdd(filter Filter) error { options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) if u32, ok := filter.(*U32); ok { - // match all - sel := nl.TcU32Sel{ - Nkeys: 1, - Flags: nl.TC_U32_TERMINAL, + // Convert TcU32Sel into nl.TcU32Sel as it is without copy. + sel := (*nl.TcU32Sel)(unsafe.Pointer(u32.Sel)) + if sel == nil { + // match all + sel = &nl.TcU32Sel{ + Nkeys: 1, + Flags: nl.TC_U32_TERMINAL, + } + sel.Keys = append(sel.Keys, nl.TcU32Key{}) } - sel.Keys = append(sel.Keys, nl.TcU32Key{}) + + if native != networkOrder { + // Copy TcU32Sel. + cSel := *sel + keys := make([]nl.TcU32Key, cap(sel.Keys)) + copy(keys, sel.Keys) + cSel.Keys = keys + sel = &cSel + + // Handle the endianness of attributes + sel.Offmask = native.Uint16(htons(sel.Offmask)) + sel.Hmask = native.Uint32(htonl(sel.Hmask)) + for i, key := range sel.Keys { + sel.Keys[i].Mask = native.Uint32(htonl(key.Mask)) + sel.Keys[i].Val = native.Uint32(htonl(key.Val)) + } + } + sel.Nkeys = uint8(len(sel.Keys)) nl.NewRtAttrChild(options, nl.TCA_U32_SEL, sel.Serialize()) if u32.ClassId != 0 { nl.NewRtAttrChild(options, nl.TCA_U32_CLASSID, nl.Uint32Attr(u32.ClassId)) @@ -425,9 +448,15 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) case nl.TCA_U32_SEL: detailed = true sel := nl.DeserializeTcU32Sel(datum.Value) - // only parse if we have a very basic redirect - if sel.Flags&nl.TC_U32_TERMINAL == 0 || sel.Nkeys != 1 { - return detailed, nil + u32.Sel = (*TcU32Sel)(unsafe.Pointer(sel)) + if native != networkOrder { + // Handle the endianness of attributes + u32.Sel.Offmask = native.Uint16(htons(sel.Offmask)) + u32.Sel.Hmask = native.Uint32(htonl(sel.Hmask)) + for i, key := range u32.Sel.Keys { + u32.Sel.Keys[i].Mask = native.Uint32(htonl(key.Mask)) + u32.Sel.Keys[i].Val = native.Uint32(htonl(key.Val)) + } } case nl.TCA_U32_ACT: tables, err := nl.ParseRouteAttr(datum.Value) @@ -443,6 +472,8 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) u32.RedirIndex = int(action.Ifindex) } } + case nl.TCA_U32_CLASSID: + u32.ClassId = native.Uint32(datum.Value) } } return detailed, nil diff --git a/vendor/github.com/vishvananda/netlink/genetlink_linux.go b/vendor/github.com/vishvananda/netlink/genetlink_linux.go new file mode 100644 index 00000000..a388a870 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/genetlink_linux.go @@ -0,0 +1,167 @@ +package netlink + +import ( + "fmt" + "syscall" + + "github.com/vishvananda/netlink/nl" +) + +type GenlOp struct { + ID uint32 + Flags uint32 +} + +type GenlMulticastGroup struct { + ID uint32 + Name string +} + +type GenlFamily struct { + ID uint16 + HdrSize uint32 + Name string + Version uint32 + MaxAttr uint32 + Ops []GenlOp + Groups []GenlMulticastGroup +} + +func parseOps(b []byte) ([]GenlOp, error) { + attrs, err := nl.ParseRouteAttr(b) + if err != nil { + return nil, err + } + ops := make([]GenlOp, 0, len(attrs)) + for _, a := range attrs { + nattrs, err := nl.ParseRouteAttr(a.Value) + if err != nil { + return nil, err + } + var op GenlOp + for _, na := range nattrs { + switch na.Attr.Type { + case nl.GENL_CTRL_ATTR_OP_ID: + op.ID = native.Uint32(na.Value) + case nl.GENL_CTRL_ATTR_OP_FLAGS: + op.Flags = native.Uint32(na.Value) + } + } + ops = append(ops, op) + } + return ops, nil +} + +func parseMulticastGroups(b []byte) ([]GenlMulticastGroup, error) { + attrs, err := nl.ParseRouteAttr(b) + if err != nil { + return nil, err + } + groups := make([]GenlMulticastGroup, 0, len(attrs)) + for _, a := range attrs { + nattrs, err := nl.ParseRouteAttr(a.Value) + if err != nil { + return nil, err + } + var g GenlMulticastGroup + for _, na := range nattrs { + switch na.Attr.Type { + case nl.GENL_CTRL_ATTR_MCAST_GRP_NAME: + g.Name = nl.BytesToString(na.Value) + case nl.GENL_CTRL_ATTR_MCAST_GRP_ID: + g.ID = native.Uint32(na.Value) + } + } + groups = append(groups, g) + } + return groups, nil +} + +func (f *GenlFamily) parseAttributes(attrs []syscall.NetlinkRouteAttr) error { + for _, a := range attrs { + switch a.Attr.Type { + case nl.GENL_CTRL_ATTR_FAMILY_NAME: + f.Name = nl.BytesToString(a.Value) + case nl.GENL_CTRL_ATTR_FAMILY_ID: + f.ID = native.Uint16(a.Value) + case nl.GENL_CTRL_ATTR_VERSION: + f.Version = native.Uint32(a.Value) + case nl.GENL_CTRL_ATTR_HDRSIZE: + f.HdrSize = native.Uint32(a.Value) + case nl.GENL_CTRL_ATTR_MAXATTR: + f.MaxAttr = native.Uint32(a.Value) + case nl.GENL_CTRL_ATTR_OPS: + ops, err := parseOps(a.Value) + if err != nil { + return err + } + f.Ops = ops + case nl.GENL_CTRL_ATTR_MCAST_GROUPS: + groups, err := parseMulticastGroups(a.Value) + if err != nil { + return err + } + f.Groups = groups + } + } + + return nil +} + +func parseFamilies(msgs [][]byte) ([]*GenlFamily, error) { + families := make([]*GenlFamily, 0, len(msgs)) + for _, m := range msgs { + attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) + if err != nil { + return nil, err + } + family := &GenlFamily{} + if err := family.parseAttributes(attrs); err != nil { + return nil, err + } + + families = append(families, family) + } + return families, nil +} + +func (h *Handle) GenlFamilyList() ([]*GenlFamily, error) { + msg := &nl.Genlmsg{ + Command: nl.GENL_CTRL_CMD_GETFAMILY, + Version: nl.GENL_CTRL_VERSION, + } + req := h.newNetlinkRequest(nl.GENL_ID_CTRL, syscall.NLM_F_DUMP) + req.AddData(msg) + msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + return parseFamilies(msgs) +} + +func GenlFamilyList() ([]*GenlFamily, error) { + return pkgHandle.GenlFamilyList() +} + +func (h *Handle) GenlFamilyGet(name string) (*GenlFamily, error) { + msg := &nl.Genlmsg{ + Command: nl.GENL_CTRL_CMD_GETFAMILY, + Version: nl.GENL_CTRL_VERSION, + } + req := h.newNetlinkRequest(nl.GENL_ID_CTRL, 0) + req.AddData(msg) + req.AddData(nl.NewRtAttr(nl.GENL_CTRL_ATTR_FAMILY_NAME, nl.ZeroTerminated(name))) + msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + families, err := parseFamilies(msgs) + if len(families) != 1 { + return nil, fmt.Errorf("invalid response for GENL_CTRL_CMD_GETFAMILY") + } + return families[0], nil +} + +func GenlFamilyGet(name string) (*GenlFamily, error) { + return pkgHandle.GenlFamilyGet(name) +} diff --git a/vendor/github.com/vishvananda/netlink/genetlink_unspecified.go b/vendor/github.com/vishvananda/netlink/genetlink_unspecified.go new file mode 100644 index 00000000..0192b991 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/genetlink_unspecified.go @@ -0,0 +1,25 @@ +// +build !linux + +package netlink + +type GenlOp struct{} + +type GenlMulticastGroup struct{} + +type GenlFamily struct{} + +func (h *Handle) GenlFamilyList() ([]*GenlFamily, error) { + return nil, ErrNotImplemented +} + +func GenlFamilyList() ([]*GenlFamily, error) { + return nil, ErrNotImplemented +} + +func (h *Handle) GenlFamilyGet(name string) (*GenlFamily, error) { + return nil, ErrNotImplemented +} + +func GenlFamilyGet(name string) (*GenlFamily, error) { + return nil, ErrNotImplemented +} diff --git a/vendor/github.com/vishvananda/netlink/gtp_linux.go b/vendor/github.com/vishvananda/netlink/gtp_linux.go new file mode 100644 index 00000000..7331303e --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/gtp_linux.go @@ -0,0 +1,238 @@ +package netlink + +import ( + "fmt" + "net" + "strings" + "syscall" + + "github.com/vishvananda/netlink/nl" +) + +type PDP struct { + Version uint32 + TID uint64 + PeerAddress net.IP + MSAddress net.IP + Flow uint16 + NetNSFD uint32 + ITEI uint32 + OTEI uint32 +} + +func (pdp *PDP) String() string { + elems := []string{} + elems = append(elems, fmt.Sprintf("Version: %d", pdp.Version)) + if pdp.Version == 0 { + elems = append(elems, fmt.Sprintf("TID: %d", pdp.TID)) + } else if pdp.Version == 1 { + elems = append(elems, fmt.Sprintf("TEI: %d/%d", pdp.ITEI, pdp.OTEI)) + } + elems = append(elems, fmt.Sprintf("MS-Address: %s", pdp.MSAddress)) + elems = append(elems, fmt.Sprintf("Peer-Address: %s", pdp.PeerAddress)) + return fmt.Sprintf("{%s}", strings.Join(elems, " ")) +} + +func (p *PDP) parseAttributes(attrs []syscall.NetlinkRouteAttr) error { + for _, a := range attrs { + switch a.Attr.Type { + case nl.GENL_GTP_ATTR_VERSION: + p.Version = native.Uint32(a.Value) + case nl.GENL_GTP_ATTR_TID: + p.TID = native.Uint64(a.Value) + case nl.GENL_GTP_ATTR_PEER_ADDRESS: + p.PeerAddress = net.IP(a.Value) + case nl.GENL_GTP_ATTR_MS_ADDRESS: + p.MSAddress = net.IP(a.Value) + case nl.GENL_GTP_ATTR_FLOW: + p.Flow = native.Uint16(a.Value) + case nl.GENL_GTP_ATTR_NET_NS_FD: + p.NetNSFD = native.Uint32(a.Value) + case nl.GENL_GTP_ATTR_I_TEI: + p.ITEI = native.Uint32(a.Value) + case nl.GENL_GTP_ATTR_O_TEI: + p.OTEI = native.Uint32(a.Value) + } + } + return nil +} + +func parsePDP(msgs [][]byte) ([]*PDP, error) { + pdps := make([]*PDP, 0, len(msgs)) + for _, m := range msgs { + attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) + if err != nil { + return nil, err + } + pdp := &PDP{} + if err := pdp.parseAttributes(attrs); err != nil { + return nil, err + } + pdps = append(pdps, pdp) + } + return pdps, nil +} + +func (h *Handle) GTPPDPList() ([]*PDP, error) { + f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME) + if err != nil { + return nil, err + } + msg := &nl.Genlmsg{ + Command: nl.GENL_GTP_CMD_GETPDP, + Version: nl.GENL_GTP_VERSION, + } + req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_DUMP) + req.AddData(msg) + msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + return parsePDP(msgs) +} + +func GTPPDPList() ([]*PDP, error) { + return pkgHandle.GTPPDPList() +} + +func gtpPDPGet(req *nl.NetlinkRequest) (*PDP, error) { + msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + pdps, err := parsePDP(msgs) + if err != nil { + return nil, err + } + if len(pdps) != 1 { + return nil, fmt.Errorf("invalid reqponse for GENL_GTP_CMD_GETPDP") + } + return pdps[0], nil +} + +func (h *Handle) GTPPDPByTID(link Link, tid int) (*PDP, error) { + f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME) + if err != nil { + return nil, err + } + msg := &nl.Genlmsg{ + Command: nl.GENL_GTP_CMD_GETPDP, + Version: nl.GENL_GTP_VERSION, + } + req := h.newNetlinkRequest(int(f.ID), 0) + req.AddData(msg) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(0))) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index)))) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_TID, nl.Uint64Attr(uint64(tid)))) + return gtpPDPGet(req) +} + +func GTPPDPByTID(link Link, tid int) (*PDP, error) { + return pkgHandle.GTPPDPByTID(link, tid) +} + +func (h *Handle) GTPPDPByITEI(link Link, itei int) (*PDP, error) { + f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME) + if err != nil { + return nil, err + } + msg := &nl.Genlmsg{ + Command: nl.GENL_GTP_CMD_GETPDP, + Version: nl.GENL_GTP_VERSION, + } + req := h.newNetlinkRequest(int(f.ID), 0) + req.AddData(msg) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(1))) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index)))) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_I_TEI, nl.Uint32Attr(uint32(itei)))) + return gtpPDPGet(req) +} + +func GTPPDPByITEI(link Link, itei int) (*PDP, error) { + return pkgHandle.GTPPDPByITEI(link, itei) +} + +func (h *Handle) GTPPDPByMSAddress(link Link, addr net.IP) (*PDP, error) { + f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME) + if err != nil { + return nil, err + } + msg := &nl.Genlmsg{ + Command: nl.GENL_GTP_CMD_GETPDP, + Version: nl.GENL_GTP_VERSION, + } + req := h.newNetlinkRequest(int(f.ID), 0) + req.AddData(msg) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(0))) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index)))) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_MS_ADDRESS, []byte(addr.To4()))) + return gtpPDPGet(req) +} + +func GTPPDPByMSAddress(link Link, addr net.IP) (*PDP, error) { + return pkgHandle.GTPPDPByMSAddress(link, addr) +} + +func (h *Handle) GTPPDPAdd(link Link, pdp *PDP) error { + f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME) + if err != nil { + return err + } + msg := &nl.Genlmsg{ + Command: nl.GENL_GTP_CMD_NEWPDP, + Version: nl.GENL_GTP_VERSION, + } + req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_EXCL|syscall.NLM_F_ACK) + req.AddData(msg) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version))) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index)))) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_PEER_ADDRESS, []byte(pdp.PeerAddress.To4()))) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_MS_ADDRESS, []byte(pdp.MSAddress.To4()))) + + switch pdp.Version { + case 0: + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_TID, nl.Uint64Attr(pdp.TID))) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_FLOW, nl.Uint16Attr(pdp.Flow))) + case 1: + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_I_TEI, nl.Uint32Attr(pdp.ITEI))) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_O_TEI, nl.Uint32Attr(pdp.OTEI))) + default: + return fmt.Errorf("unsupported GTP version: %d", pdp.Version) + } + _, err = req.Execute(syscall.NETLINK_GENERIC, 0) + return err +} + +func GTPPDPAdd(link Link, pdp *PDP) error { + return pkgHandle.GTPPDPAdd(link, pdp) +} + +func (h *Handle) GTPPDPDel(link Link, pdp *PDP) error { + f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME) + if err != nil { + return err + } + msg := &nl.Genlmsg{ + Command: nl.GENL_GTP_CMD_DELPDP, + Version: nl.GENL_GTP_VERSION, + } + req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_EXCL|syscall.NLM_F_ACK) + req.AddData(msg) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version))) + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index)))) + + switch pdp.Version { + case 0: + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_TID, nl.Uint64Attr(pdp.TID))) + case 1: + req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_I_TEI, nl.Uint32Attr(pdp.ITEI))) + default: + return fmt.Errorf("unsupported GTP version: %d", pdp.Version) + } + _, err = req.Execute(syscall.NETLINK_GENERIC, 0) + return err +} + +func GTPPDPDel(link Link, pdp *PDP) error { + return pkgHandle.GTPPDPDel(link, pdp) +} diff --git a/vendor/github.com/vishvananda/netlink/link.go b/vendor/github.com/vishvananda/netlink/link.go index 924211cd..9ec4ce26 100644 --- a/vendor/github.com/vishvananda/netlink/link.go +++ b/vendor/github.com/vishvananda/netlink/link.go @@ -170,6 +170,7 @@ type LinkStatistics64 struct { type LinkXdp struct { Fd int Attached bool + Flags uint32 } // Device links cannot be created via netlink. These links @@ -215,6 +216,8 @@ func (ifb *Ifb) Type() string { // Bridge links are simple linux bridges type Bridge struct { LinkAttrs + MulticastSnooping *bool + HelloTime *uint32 } func (bridge *Bridge) Attrs() *LinkAttrs { @@ -336,6 +339,7 @@ type Vxlan struct { UDPCSum bool NoAge bool GBP bool + FlowBased bool Age int Limit int Port int @@ -590,7 +594,11 @@ type Bond struct { LacpRate BondLacpRate AdSelect BondAdSelect // looking at iproute tool AdInfo can only be retrived. It can't be set. - AdInfo *BondAdInfo + AdInfo *BondAdInfo + AdActorSysPrio int + AdUserPortKey int + AdActorSystem net.HardwareAddr + TlbDynamicLb int } func NewLinkBond(atr LinkAttrs) *Bond { @@ -618,6 +626,10 @@ func NewLinkBond(atr LinkAttrs) *Bond { PackersPerSlave: -1, LacpRate: -1, AdSelect: -1, + AdActorSysPrio: -1, + AdUserPortKey: -1, + AdActorSystem: nil, + TlbDynamicLb: -1, } } @@ -673,6 +685,7 @@ type Gretap struct { EncapType uint16 EncapFlags uint16 Link uint32 + FlowBased bool } func (gretap *Gretap) Attrs() *LinkAttrs { @@ -731,8 +744,32 @@ func (vrf *Vrf) Type() string { return "vrf" } +type GTP struct { + LinkAttrs + FD0 int + FD1 int + Role int + PDPHashsize int +} + +func (gtp *GTP) Attrs() *LinkAttrs { + return >p.LinkAttrs +} + +func (gtp *GTP) Type() string { + return "gtp" +} + // iproute2 supported devices; // vlan | veth | vcan | dummy | ifb | macvlan | macvtap | // bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan | // gre | gretap | ip6gre | ip6gretap | vti | nlmon | // bond_slave | ipvlan + +// LinkNotFoundError wraps the various not found errors when +// getting/reading links. This is intended for better error +// handling by dependent code so that "not found error" can +// be distinguished from other errors +type LinkNotFoundError struct { + error +} diff --git a/vendor/github.com/vishvananda/netlink/link_linux.go b/vendor/github.com/vishvananda/netlink/link_linux.go index 56409eb2..f1431442 100644 --- a/vendor/github.com/vishvananda/netlink/link_linux.go +++ b/vendor/github.com/vishvananda/netlink/link_linux.go @@ -58,6 +58,44 @@ func (h *Handle) ensureIndex(link *LinkAttrs) { } } +func (h *Handle) LinkSetARPOff(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK) + + msg := nl.NewIfInfomsg(syscall.AF_UNSPEC) + msg.Change |= syscall.IFF_NOARP + msg.Flags |= syscall.IFF_NOARP + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(syscall.NETLINK_ROUTE, 0) + return err +} + +func LinkSetARPOff(link Link) error { + return pkgHandle.LinkSetARPOff(link) +} + +func (h *Handle) LinkSetARPOn(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK) + + msg := nl.NewIfInfomsg(syscall.AF_UNSPEC) + msg.Change |= syscall.IFF_NOARP + msg.Flags &= ^uint32(syscall.IFF_NOARP) + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(syscall.NETLINK_ROUTE, 0) + return err +} + +func LinkSetARPOn(link Link) error { + return pkgHandle.LinkSetARPOn(link) +} + func (h *Handle) SetPromiscOn(link Link) error { base := link.Attrs() h.ensureIndex(base) @@ -65,7 +103,7 @@ func (h *Handle) SetPromiscOn(link Link) error { msg := nl.NewIfInfomsg(syscall.AF_UNSPEC) msg.Change = syscall.IFF_PROMISC - msg.Flags = syscall.IFF_UP + msg.Flags = syscall.IFF_PROMISC msg.Index = int32(base.Index) req.AddData(msg) @@ -73,6 +111,16 @@ func (h *Handle) SetPromiscOn(link Link) error { return err } +func BridgeSetMcastSnoop(link Link, on bool) error { + return pkgHandle.BridgeSetMcastSnoop(link, on) +} + +func (h *Handle) BridgeSetMcastSnoop(link Link, on bool) error { + bridge := link.(*Bridge) + bridge.MulticastSnooping = &on + return h.linkModify(bridge, syscall.NLM_F_ACK) +} + func SetPromiscOn(link Link) error { return pkgHandle.SetPromiscOn(link) } @@ -84,7 +132,7 @@ func (h *Handle) SetPromiscOff(link Link) error { msg := nl.NewIfInfomsg(syscall.AF_UNSPEC) msg.Change = syscall.IFF_PROMISC - msg.Flags = 0 & ^syscall.IFF_UP + msg.Flags = 0 & ^syscall.IFF_PROMISC msg.Index = int32(base.Index) req.AddData(msg) @@ -480,7 +528,13 @@ type vxlanPortRange struct { func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) { data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil) + + if vxlan.FlowBased { + vxlan.VxlanId = 0 + } + nl.NewRtAttrChild(data, nl.IFLA_VXLAN_ID, nl.Uint32Attr(uint32(vxlan.VxlanId))) + if vxlan.VtepDevIndex != 0 { nl.NewRtAttrChild(data, nl.IFLA_VXLAN_LINK, nl.Uint32Attr(uint32(vxlan.VtepDevIndex))) } @@ -521,6 +575,9 @@ func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) { if vxlan.GBP { nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GBP, []byte{}) } + if vxlan.FlowBased { + nl.NewRtAttrChild(data, nl.IFLA_VXLAN_FLOWBASED, boolAttr(vxlan.FlowBased)) + } if vxlan.NoAge { nl.NewRtAttrChild(data, nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0)) } else if vxlan.Age > 0 { @@ -621,6 +678,18 @@ func addBondAttrs(bond *Bond, linkInfo *nl.RtAttr) { if bond.AdSelect >= 0 { nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_SELECT, nl.Uint8Attr(uint8(bond.AdSelect))) } + if bond.AdActorSysPrio >= 0 { + nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_ACTOR_SYS_PRIO, nl.Uint16Attr(uint16(bond.AdActorSysPrio))) + } + if bond.AdUserPortKey >= 0 { + nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_USER_PORT_KEY, nl.Uint16Attr(uint16(bond.AdUserPortKey))) + } + if bond.AdActorSystem != nil { + nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_ACTOR_SYSTEM, []byte(bond.AdActorSystem)) + } + if bond.TlbDynamicLb >= 0 { + nl.NewRtAttrChild(data, nl.IFLA_BOND_TLB_DYNAMIC_LB, nl.Uint8Attr(uint8(bond.TlbDynamicLb))) + } } // LinkAdd adds a new link device. The type and features of the device @@ -634,7 +703,10 @@ func LinkAdd(link Link) error { // are taken fromt the parameters in the link object. // Equivalent to: `ip link add $link` func (h *Handle) LinkAdd(link Link) error { - // TODO: set mtu and hardware address + return h.linkModify(link, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK) +} + +func (h *Handle) linkModify(link Link, flags int) error { // TODO: support extra data for macvlan base := link.Attrs() @@ -681,7 +753,7 @@ func (h *Handle) LinkAdd(link Link) error { return nil } - req := h.newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK) + req := h.newNetlinkRequest(syscall.RTM_NEWLINK, flags) msg := nl.NewIfInfomsg(syscall.AF_UNSPEC) // TODO: make it shorter @@ -729,6 +801,11 @@ func (h *Handle) LinkAdd(link Link) error { req.AddData(qlen) } + if base.HardwareAddr != nil { + hwaddr := nl.NewRtAttr(syscall.IFLA_ADDRESS, []byte(base.HardwareAddr)) + req.AddData(hwaddr) + } + if base.Namespace != nil { var attr *nl.RtAttr switch base.Namespace.(type) { @@ -792,6 +869,10 @@ func (h *Handle) LinkAdd(link Link) error { addVtiAttrs(vti, linkInfo) } else if vrf, ok := link.(*Vrf); ok { addVrfAttrs(vrf, linkInfo) + } else if bridge, ok := link.(*Bridge); ok { + addBridgeAttrs(bridge, linkInfo) + } else if gtp, ok := link.(*GTP); ok { + addGTPAttrs(gtp, linkInfo) } req.AddData(linkInfo) @@ -847,7 +928,7 @@ func (h *Handle) linkByNameDump(name string) (Link, error) { return link, nil } } - return nil, fmt.Errorf("Link %s not found", name) + return nil, LinkNotFoundError{fmt.Errorf("Link %s not found", name)} } func (h *Handle) linkByAliasDump(alias string) (Link, error) { @@ -861,7 +942,7 @@ func (h *Handle) linkByAliasDump(alias string) (Link, error) { return link, nil } } - return nil, fmt.Errorf("Link alias %s not found", alias) + return nil, LinkNotFoundError{fmt.Errorf("Link alias %s not found", alias)} } // LinkByName finds a link by name and returns a pointer to the object. @@ -947,7 +1028,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) { if err != nil { if errno, ok := err.(syscall.Errno); ok { if errno == syscall.ENODEV { - return nil, fmt.Errorf("Link not found") + return nil, LinkNotFoundError{fmt.Errorf("Link not found")} } } return nil, err @@ -955,7 +1036,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) { switch { case len(msgs) == 0: - return nil, fmt.Errorf("Link not found") + return nil, LinkNotFoundError{fmt.Errorf("Link not found")} case len(msgs) == 1: return LinkDeserialize(nil, msgs[0]) @@ -1025,6 +1106,8 @@ func LinkDeserialize(hdr *syscall.NlMsghdr, m []byte) (Link, error) { link = &Vti{} case "vrf": link = &Vrf{} + case "gtp": + link = >P{} default: link = &GenericLink{LinkType: linkType} } @@ -1054,6 +1137,10 @@ func LinkDeserialize(hdr *syscall.NlMsghdr, m []byte) (Link, error) { parseVtiData(link, data) case "vrf": parseVrfData(link, data) + case "bridge": + parseBridgeData(link, data) + case "gtp": + parseGTPData(link, data) } } } @@ -1250,6 +1337,22 @@ func (h *Handle) LinkSetFlood(link Link, mode bool) error { return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_UNICAST_FLOOD) } +func LinkSetBrProxyArp(link Link, mode bool) error { + return pkgHandle.LinkSetBrProxyArp(link, mode) +} + +func (h *Handle) LinkSetBrProxyArp(link Link, mode bool) error { + return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP) +} + +func LinkSetBrProxyArpWiFi(link Link, mode bool) error { + return pkgHandle.LinkSetBrProxyArpWiFi(link, mode) +} + +func (h *Handle) LinkSetBrProxyArpWiFi(link Link, mode bool) error { + return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP_WIFI) +} + func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error { base := link.Attrs() h.ensureIndex(base) @@ -1313,6 +1416,8 @@ func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) { vxlan.UDPCSum = int8(datum.Value[0]) != 0 case nl.IFLA_VXLAN_GBP: vxlan.GBP = true + case nl.IFLA_VXLAN_FLOWBASED: + vxlan.FlowBased = int8(datum.Value[0]) != 0 case nl.IFLA_VXLAN_AGEING: vxlan.Age = int(native.Uint32(datum.Value[0:4])) vxlan.NoAge = vxlan.Age == 0 @@ -1332,7 +1437,7 @@ func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) { } func parseBondData(link Link, data []syscall.NetlinkRouteAttr) { - bond := NewLinkBond(NewLinkAttrs()) + bond := link.(*Bond) for i := range data { switch data[i].Attr.Type { case nl.IFLA_BOND_MODE: @@ -1381,6 +1486,14 @@ func parseBondData(link Link, data []syscall.NetlinkRouteAttr) { bond.AdSelect = BondAdSelect(data[i].Value[0]) case nl.IFLA_BOND_AD_INFO: // TODO: implement + case nl.IFLA_BOND_AD_ACTOR_SYS_PRIO: + bond.AdActorSysPrio = int(native.Uint16(data[i].Value[0:2])) + case nl.IFLA_BOND_AD_USER_PORT_KEY: + bond.AdUserPortKey = int(native.Uint16(data[i].Value[0:2])) + case nl.IFLA_BOND_AD_ACTOR_SYSTEM: + bond.AdActorSystem = net.HardwareAddr(data[i].Value[0:6]) + case nl.IFLA_BOND_TLB_DYNAMIC_LB: + bond.TlbDynamicLb = int(data[i].Value[0]) } } } @@ -1445,6 +1558,12 @@ func linkFlags(rawFlags uint32) net.Flags { func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) { data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil) + if gretap.FlowBased { + // In flow based mode, no other attributes need to be configured + nl.NewRtAttrChild(data, nl.IFLA_GRE_COLLECT_METADATA, boolAttr(gretap.FlowBased)) + return + } + ip := gretap.Local.To4() if ip != nil { nl.NewRtAttrChild(data, nl.IFLA_GRE_LOCAL, []byte(ip)) @@ -1511,6 +1630,8 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) { gre.EncapType = native.Uint16(datum.Value[0:2]) case nl.IFLA_GRE_ENCAP_FLAGS: gre.EncapFlags = native.Uint16(datum.Value[0:2]) + case nl.IFLA_GRE_COLLECT_METADATA: + gre.FlowBased = int8(datum.Value[0]) != 0 } } } @@ -1528,6 +1649,8 @@ func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) { b := make([]byte, 4) native.PutUint32(b, uint32(xdp.Fd)) nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FD, b) + native.PutUint32(b, xdp.Flags) + nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FLAGS, b) req.AddData(attrs) } @@ -1543,6 +1666,8 @@ func parseLinkXdp(data []byte) (*LinkXdp, error) { xdp.Fd = int(native.Uint32(attr.Value[0:4])) case nl.IFLA_XDP_ATTACHED: xdp.Attached = attr.Value[0] != 0 + case nl.IFLA_XDP_FLAGS: + xdp.Flags = native.Uint32(attr.Value[0:4]) } } return xdp, nil @@ -1640,3 +1765,53 @@ func parseVrfData(link Link, data []syscall.NetlinkRouteAttr) { } } } + +func addBridgeAttrs(bridge *Bridge, linkInfo *nl.RtAttr) { + data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil) + if bridge.MulticastSnooping != nil { + nl.NewRtAttrChild(data, nl.IFLA_BR_MCAST_SNOOPING, boolToByte(*bridge.MulticastSnooping)) + } + if bridge.HelloTime != nil { + nl.NewRtAttrChild(data, nl.IFLA_BR_HELLO_TIME, nl.Uint32Attr(*bridge.HelloTime)) + } +} + +func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) { + br := bridge.(*Bridge) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_BR_HELLO_TIME: + helloTime := native.Uint32(datum.Value[0:4]) + br.HelloTime = &helloTime + case nl.IFLA_BR_MCAST_SNOOPING: + mcastSnooping := datum.Value[0] == 1 + br.MulticastSnooping = &mcastSnooping + } + } +} + +func addGTPAttrs(gtp *GTP, linkInfo *nl.RtAttr) { + data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil) + nl.NewRtAttrChild(data, nl.IFLA_GTP_FD0, nl.Uint32Attr(uint32(gtp.FD0))) + nl.NewRtAttrChild(data, nl.IFLA_GTP_FD1, nl.Uint32Attr(uint32(gtp.FD1))) + nl.NewRtAttrChild(data, nl.IFLA_GTP_PDP_HASHSIZE, nl.Uint32Attr(131072)) + if gtp.Role != nl.GTP_ROLE_GGSN { + nl.NewRtAttrChild(data, nl.IFLA_GTP_ROLE, nl.Uint32Attr(uint32(gtp.Role))) + } +} + +func parseGTPData(link Link, data []syscall.NetlinkRouteAttr) { + gtp := link.(*GTP) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_GTP_FD0: + gtp.FD0 = int(native.Uint32(datum.Value)) + case nl.IFLA_GTP_FD1: + gtp.FD1 = int(native.Uint32(datum.Value)) + case nl.IFLA_GTP_PDP_HASHSIZE: + gtp.PDPHashsize = int(native.Uint32(datum.Value)) + case nl.IFLA_GTP_ROLE: + gtp.Role = int(native.Uint32(datum.Value)) + } + } +} diff --git a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go index fa421e4e..2d57c16d 100644 --- a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go +++ b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go @@ -16,7 +16,7 @@ func LinkSetMTU(link Link, mtu int) error { return ErrNotImplemented } -func LinkSetMaster(link Link, master *Link) error { +func LinkSetMaster(link Link, master *Bridge) error { return ErrNotImplemented } @@ -64,6 +64,14 @@ func LinkSetXdpFd(link Link, fd int) error { return ErrNotImplemented } +func LinkSetARPOff(link Link) error { + return ErrNotImplemented +} + +func LinkSetARPOn(link Link) error { + return ErrNotImplemented +} + func LinkByName(name string) (Link, error) { return nil, ErrNotImplemented } diff --git a/vendor/github.com/vishvananda/netlink/nl/addr_linux.go b/vendor/github.com/vishvananda/netlink/nl/addr_linux.go index 17088fa0..fe362e9f 100644 --- a/vendor/github.com/vishvananda/netlink/nl/addr_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/addr_linux.go @@ -45,3 +45,32 @@ func (msg *IfAddrmsg) Serialize() []byte { func (msg *IfAddrmsg) Len() int { return syscall.SizeofIfAddrmsg } + +// struct ifa_cacheinfo { +// __u32 ifa_prefered; +// __u32 ifa_valid; +// __u32 cstamp; /* created timestamp, hundredths of seconds */ +// __u32 tstamp; /* updated timestamp, hundredths of seconds */ +// }; + +const IFA_CACHEINFO = 6 +const SizeofIfaCacheInfo = 0x10 + +type IfaCacheInfo struct { + IfaPrefered uint32 + IfaValid uint32 + Cstamp uint32 + Tstamp uint32 +} + +func (msg *IfaCacheInfo) Len() int { + return SizeofIfaCacheInfo +} + +func DeserializeIfaCacheInfo(b []byte) *IfaCacheInfo { + return (*IfaCacheInfo)(unsafe.Pointer(&b[0:SizeofIfaCacheInfo][0])) +} + +func (msg *IfaCacheInfo) Serialize() []byte { + return (*(*[SizeofIfaCacheInfo]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/nl/bridge_linux.go b/vendor/github.com/vishvananda/netlink/nl/bridge_linux.go new file mode 100644 index 00000000..6c0d3333 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/bridge_linux.go @@ -0,0 +1,74 @@ +package nl + +import ( + "fmt" + "unsafe" +) + +const ( + SizeofBridgeVlanInfo = 0x04 +) + +/* Bridge Flags */ +const ( + BRIDGE_FLAGS_MASTER = iota /* Bridge command to/from master */ + BRIDGE_FLAGS_SELF /* Bridge command to/from lowerdev */ +) + +/* Bridge management nested attributes + * [IFLA_AF_SPEC] = { + * [IFLA_BRIDGE_FLAGS] + * [IFLA_BRIDGE_MODE] + * [IFLA_BRIDGE_VLAN_INFO] + * } + */ +const ( + IFLA_BRIDGE_FLAGS = iota + IFLA_BRIDGE_MODE + IFLA_BRIDGE_VLAN_INFO +) + +const ( + BRIDGE_VLAN_INFO_MASTER = 1 << iota + BRIDGE_VLAN_INFO_PVID + BRIDGE_VLAN_INFO_UNTAGGED + BRIDGE_VLAN_INFO_RANGE_BEGIN + BRIDGE_VLAN_INFO_RANGE_END +) + +// struct bridge_vlan_info { +// __u16 flags; +// __u16 vid; +// }; + +type BridgeVlanInfo struct { + Flags uint16 + Vid uint16 +} + +func (b *BridgeVlanInfo) Serialize() []byte { + return (*(*[SizeofBridgeVlanInfo]byte)(unsafe.Pointer(b)))[:] +} + +func DeserializeBridgeVlanInfo(b []byte) *BridgeVlanInfo { + return (*BridgeVlanInfo)(unsafe.Pointer(&b[0:SizeofBridgeVlanInfo][0])) +} + +func (b *BridgeVlanInfo) PortVID() bool { + return b.Flags&BRIDGE_VLAN_INFO_PVID > 0 +} + +func (b *BridgeVlanInfo) EngressUntag() bool { + return b.Flags&BRIDGE_VLAN_INFO_UNTAGGED > 0 +} + +func (b *BridgeVlanInfo) String() string { + return fmt.Sprintf("%+v", *b) +} + +/* New extended info filters for IFLA_EXT_MASK */ +const ( + RTEXT_FILTER_VF = 1 << iota + RTEXT_FILTER_BRVLAN + RTEXT_FILTER_BRVLAN_COMPRESSED +) diff --git a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go new file mode 100644 index 00000000..6692b53e --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go @@ -0,0 +1,189 @@ +package nl + +import "unsafe" + +// Track the message sizes for the correct serialization/deserialization +const ( + SizeofNfgenmsg = 4 + SizeofNfattr = 4 + SizeofNfConntrack = 376 + SizeofNfctTupleHead = 52 +) + +var L4ProtoMap = map[uint8]string{ + 6: "tcp", + 17: "udp", +} + +// All the following constants are coming from: +// https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink_conntrack.h + +// enum cntl_msg_types { +// IPCTNL_MSG_CT_NEW, +// IPCTNL_MSG_CT_GET, +// IPCTNL_MSG_CT_DELETE, +// IPCTNL_MSG_CT_GET_CTRZERO, +// IPCTNL_MSG_CT_GET_STATS_CPU, +// IPCTNL_MSG_CT_GET_STATS, +// IPCTNL_MSG_CT_GET_DYING, +// IPCTNL_MSG_CT_GET_UNCONFIRMED, +// +// IPCTNL_MSG_MAX +// }; +const ( + IPCTNL_MSG_CT_GET = 1 + IPCTNL_MSG_CT_DELETE = 2 +) + +// #define NFNETLINK_V0 0 +const ( + NFNETLINK_V0 = 0 +) + +// #define NLA_F_NESTED (1 << 15) +const ( + NLA_F_NESTED = (1 << 15) +) + +// enum ctattr_type { +// CTA_UNSPEC, +// CTA_TUPLE_ORIG, +// CTA_TUPLE_REPLY, +// CTA_STATUS, +// CTA_PROTOINFO, +// CTA_HELP, +// CTA_NAT_SRC, +// #define CTA_NAT CTA_NAT_SRC /* backwards compatibility */ +// CTA_TIMEOUT, +// CTA_MARK, +// CTA_COUNTERS_ORIG, +// CTA_COUNTERS_REPLY, +// CTA_USE, +// CTA_ID, +// CTA_NAT_DST, +// CTA_TUPLE_MASTER, +// CTA_SEQ_ADJ_ORIG, +// CTA_NAT_SEQ_ADJ_ORIG = CTA_SEQ_ADJ_ORIG, +// CTA_SEQ_ADJ_REPLY, +// CTA_NAT_SEQ_ADJ_REPLY = CTA_SEQ_ADJ_REPLY, +// CTA_SECMARK, /* obsolete */ +// CTA_ZONE, +// CTA_SECCTX, +// CTA_TIMESTAMP, +// CTA_MARK_MASK, +// CTA_LABELS, +// CTA_LABELS_MASK, +// __CTA_MAX +// }; +const ( + CTA_TUPLE_ORIG = 1 + CTA_TUPLE_REPLY = 2 + CTA_STATUS = 3 + CTA_TIMEOUT = 8 + CTA_MARK = 9 + CTA_PROTOINFO = 4 +) + +// enum ctattr_tuple { +// CTA_TUPLE_UNSPEC, +// CTA_TUPLE_IP, +// CTA_TUPLE_PROTO, +// CTA_TUPLE_ZONE, +// __CTA_TUPLE_MAX +// }; +// #define CTA_TUPLE_MAX (__CTA_TUPLE_MAX - 1) +const ( + CTA_TUPLE_IP = 1 + CTA_TUPLE_PROTO = 2 +) + +// enum ctattr_ip { +// CTA_IP_UNSPEC, +// CTA_IP_V4_SRC, +// CTA_IP_V4_DST, +// CTA_IP_V6_SRC, +// CTA_IP_V6_DST, +// __CTA_IP_MAX +// }; +// #define CTA_IP_MAX (__CTA_IP_MAX - 1) +const ( + CTA_IP_V4_SRC = 1 + CTA_IP_V4_DST = 2 + CTA_IP_V6_SRC = 3 + CTA_IP_V6_DST = 4 +) + +// enum ctattr_l4proto { +// CTA_PROTO_UNSPEC, +// CTA_PROTO_NUM, +// CTA_PROTO_SRC_PORT, +// CTA_PROTO_DST_PORT, +// CTA_PROTO_ICMP_ID, +// CTA_PROTO_ICMP_TYPE, +// CTA_PROTO_ICMP_CODE, +// CTA_PROTO_ICMPV6_ID, +// CTA_PROTO_ICMPV6_TYPE, +// CTA_PROTO_ICMPV6_CODE, +// __CTA_PROTO_MAX +// }; +// #define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1) +const ( + CTA_PROTO_NUM = 1 + CTA_PROTO_SRC_PORT = 2 + CTA_PROTO_DST_PORT = 3 +) + +// enum ctattr_protoinfo { +// CTA_PROTOINFO_UNSPEC, +// CTA_PROTOINFO_TCP, +// CTA_PROTOINFO_DCCP, +// CTA_PROTOINFO_SCTP, +// __CTA_PROTOINFO_MAX +// }; +// #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1) +const ( + CTA_PROTOINFO_TCP = 1 +) + +// enum ctattr_protoinfo_tcp { +// CTA_PROTOINFO_TCP_UNSPEC, +// CTA_PROTOINFO_TCP_STATE, +// CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, +// CTA_PROTOINFO_TCP_WSCALE_REPLY, +// CTA_PROTOINFO_TCP_FLAGS_ORIGINAL, +// CTA_PROTOINFO_TCP_FLAGS_REPLY, +// __CTA_PROTOINFO_TCP_MAX +// }; +// #define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1) +const ( + CTA_PROTOINFO_TCP_STATE = 1 + CTA_PROTOINFO_TCP_WSCALE_ORIGINAL = 2 + CTA_PROTOINFO_TCP_WSCALE_REPLY = 3 + CTA_PROTOINFO_TCP_FLAGS_ORIGINAL = 4 + CTA_PROTOINFO_TCP_FLAGS_REPLY = 5 +) + +// /* General form of address family dependent message. +// */ +// struct nfgenmsg { +// __u8 nfgen_family; /* AF_xxx */ +// __u8 version; /* nfnetlink version */ +// __be16 res_id; /* resource id */ +// }; +type Nfgenmsg struct { + NfgenFamily uint8 + Version uint8 + ResId uint16 // big endian +} + +func (msg *Nfgenmsg) Len() int { + return SizeofNfgenmsg +} + +func DeserializeNfgenmsg(b []byte) *Nfgenmsg { + return (*Nfgenmsg)(unsafe.Pointer(&b[0:SizeofNfgenmsg][0])) +} + +func (msg *Nfgenmsg) Serialize() []byte { + return (*(*[SizeofNfgenmsg]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go b/vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go new file mode 100644 index 00000000..81b46f2c --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go @@ -0,0 +1,89 @@ +package nl + +import ( + "unsafe" +) + +const SizeofGenlmsg = 4 + +const ( + GENL_ID_CTRL = 0x10 + GENL_CTRL_VERSION = 2 + GENL_CTRL_NAME = "nlctrl" +) + +const ( + GENL_CTRL_CMD_GETFAMILY = 3 +) + +const ( + GENL_CTRL_ATTR_UNSPEC = iota + GENL_CTRL_ATTR_FAMILY_ID + GENL_CTRL_ATTR_FAMILY_NAME + GENL_CTRL_ATTR_VERSION + GENL_CTRL_ATTR_HDRSIZE + GENL_CTRL_ATTR_MAXATTR + GENL_CTRL_ATTR_OPS + GENL_CTRL_ATTR_MCAST_GROUPS +) + +const ( + GENL_CTRL_ATTR_OP_UNSPEC = iota + GENL_CTRL_ATTR_OP_ID + GENL_CTRL_ATTR_OP_FLAGS +) + +const ( + GENL_ADMIN_PERM = 1 << iota + GENL_CMD_CAP_DO + GENL_CMD_CAP_DUMP + GENL_CMD_CAP_HASPOL +) + +const ( + GENL_CTRL_ATTR_MCAST_GRP_UNSPEC = iota + GENL_CTRL_ATTR_MCAST_GRP_NAME + GENL_CTRL_ATTR_MCAST_GRP_ID +) + +const ( + GENL_GTP_VERSION = 0 + GENL_GTP_NAME = "gtp" +) + +const ( + GENL_GTP_CMD_NEWPDP = iota + GENL_GTP_CMD_DELPDP + GENL_GTP_CMD_GETPDP +) + +const ( + GENL_GTP_ATTR_UNSPEC = iota + GENL_GTP_ATTR_LINK + GENL_GTP_ATTR_VERSION + GENL_GTP_ATTR_TID + GENL_GTP_ATTR_PEER_ADDRESS + GENL_GTP_ATTR_MS_ADDRESS + GENL_GTP_ATTR_FLOW + GENL_GTP_ATTR_NET_NS_FD + GENL_GTP_ATTR_I_TEI + GENL_GTP_ATTR_O_TEI + GENL_GTP_ATTR_PAD +) + +type Genlmsg struct { + Command uint8 + Version uint8 +} + +func (msg *Genlmsg) Len() int { + return SizeofGenlmsg +} + +func DeserializeGenlmsg(b []byte) *Genlmsg { + return (*Genlmsg)(unsafe.Pointer(&b[0:SizeofGenlmsg][0])) +} + +func (msg *Genlmsg) Serialize() []byte { + return (*(*[SizeofGenlmsg]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/nl/link_linux.go b/vendor/github.com/vishvananda/netlink/nl/link_linux.go index 6d9af569..f7b95759 100644 --- a/vendor/github.com/vishvananda/netlink/nl/link_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/link_linux.go @@ -102,7 +102,10 @@ const ( IFLA_BRPORT_FAST_LEAVE IFLA_BRPORT_LEARNING IFLA_BRPORT_UNICAST_FLOOD - IFLA_BRPORT_MAX = IFLA_BRPORT_UNICAST_FLOOD + IFLA_BRPORT_PROXYARP + IFLA_BRPORT_LEARNING_SYNC + IFLA_BRPORT_PROXYARP_WIFI + IFLA_BRPORT_MAX = IFLA_BRPORT_PROXYARP_WIFI ) const ( @@ -151,6 +154,10 @@ const ( IFLA_BOND_AD_LACP_RATE IFLA_BOND_AD_SELECT IFLA_BOND_AD_INFO + IFLA_BOND_AD_ACTOR_SYS_PRIO + IFLA_BOND_AD_USER_PORT_KEY + IFLA_BOND_AD_ACTOR_SYSTEM + IFLA_BOND_TLB_DYNAMIC_LB ) const ( @@ -416,7 +423,8 @@ const ( IFLA_XDP_UNSPEC = iota IFLA_XDP_FD /* fd of xdp program to attach, or -1 to remove */ IFLA_XDP_ATTACHED /* read-only bool indicating if prog is attached */ - IFLA_XDP_MAX = IFLA_XDP_ATTACHED + IFLA_XDP_FLAGS /* xdp prog related flags */ + IFLA_XDP_MAX = IFLA_XDP_FLAGS ) const ( @@ -452,3 +460,65 @@ const ( IFLA_VRF_UNSPEC = iota IFLA_VRF_TABLE ) + +const ( + IFLA_BR_UNSPEC = iota + IFLA_BR_FORWARD_DELAY + IFLA_BR_HELLO_TIME + IFLA_BR_MAX_AGE + IFLA_BR_AGEING_TIME + IFLA_BR_STP_STATE + IFLA_BR_PRIORITY + IFLA_BR_VLAN_FILTERING + IFLA_BR_VLAN_PROTOCOL + IFLA_BR_GROUP_FWD_MASK + IFLA_BR_ROOT_ID + IFLA_BR_BRIDGE_ID + IFLA_BR_ROOT_PORT + IFLA_BR_ROOT_PATH_COST + IFLA_BR_TOPOLOGY_CHANGE + IFLA_BR_TOPOLOGY_CHANGE_DETECTED + IFLA_BR_HELLO_TIMER + IFLA_BR_TCN_TIMER + IFLA_BR_TOPOLOGY_CHANGE_TIMER + IFLA_BR_GC_TIMER + IFLA_BR_GROUP_ADDR + IFLA_BR_FDB_FLUSH + IFLA_BR_MCAST_ROUTER + IFLA_BR_MCAST_SNOOPING + IFLA_BR_MCAST_QUERY_USE_IFADDR + IFLA_BR_MCAST_QUERIER + IFLA_BR_MCAST_HASH_ELASTICITY + IFLA_BR_MCAST_HASH_MAX + IFLA_BR_MCAST_LAST_MEMBER_CNT + IFLA_BR_MCAST_STARTUP_QUERY_CNT + IFLA_BR_MCAST_LAST_MEMBER_INTVL + IFLA_BR_MCAST_MEMBERSHIP_INTVL + IFLA_BR_MCAST_QUERIER_INTVL + IFLA_BR_MCAST_QUERY_INTVL + IFLA_BR_MCAST_QUERY_RESPONSE_INTVL + IFLA_BR_MCAST_STARTUP_QUERY_INTVL + IFLA_BR_NF_CALL_IPTABLES + IFLA_BR_NF_CALL_IP6TABLES + IFLA_BR_NF_CALL_ARPTABLES + IFLA_BR_VLAN_DEFAULT_PVID + IFLA_BR_PAD + IFLA_BR_VLAN_STATS_ENABLED + IFLA_BR_MCAST_STATS_ENABLED + IFLA_BR_MCAST_IGMP_VERSION + IFLA_BR_MCAST_MLD_VERSION + IFLA_BR_MAX = IFLA_BR_MCAST_MLD_VERSION +) + +const ( + IFLA_GTP_UNSPEC = iota + IFLA_GTP_FD0 + IFLA_GTP_FD1 + IFLA_GTP_PDP_HASHSIZE + IFLA_GTP_ROLE +) + +const ( + GTP_ROLE_GGSN = iota + GTP_ROLE_SGSN +) diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go index fb9031e3..1329acd8 100644 --- a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go @@ -24,7 +24,7 @@ const ( ) // SupportedNlFamilies contains the list of netlink families this netlink package supports -var SupportedNlFamilies = []int{syscall.NETLINK_ROUTE, syscall.NETLINK_XFRM} +var SupportedNlFamilies = []int{syscall.NETLINK_ROUTE, syscall.NETLINK_XFRM, syscall.NETLINK_NETFILTER} var nextSeqNr uint32 @@ -321,6 +321,7 @@ func (a *RtAttr) Serialize() []byte { type NetlinkRequest struct { syscall.NlMsghdr Data []NetlinkRequestData + RawData []byte Sockets map[int]*SocketHandle } @@ -332,6 +333,8 @@ func (req *NetlinkRequest) Serialize() []byte { dataBytes[i] = data.Serialize() length = length + len(dataBytes[i]) } + length += len(req.RawData) + req.Len = uint32(length) b := make([]byte, length) hdr := (*(*[syscall.SizeofNlMsghdr]byte)(unsafe.Pointer(req)))[:] @@ -343,6 +346,10 @@ func (req *NetlinkRequest) Serialize() []byte { next = next + 1 } } + // Add the raw data if any + if len(req.RawData) > 0 { + copy(b[next:length], req.RawData) + } return b } @@ -352,6 +359,13 @@ func (req *NetlinkRequest) AddData(data NetlinkRequestData) { } } +// AddRawData adds raw bytes to the end of the NetlinkRequest object during serialization +func (req *NetlinkRequest) AddRawData(data []byte) { + if data != nil { + req.RawData = append(req.RawData, data...) + } +} + // Execute the request against a the given sockType. // Returns a list of netlink messages in serialized format, optionally filtered // by resType. @@ -445,18 +459,18 @@ func NewNetlinkRequest(proto, flags int) *NetlinkRequest { } type NetlinkSocket struct { - fd int + fd int32 lsa syscall.SockaddrNetlink sync.Mutex } func getNetlinkSocket(protocol int) (*NetlinkSocket, error) { - fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, protocol) + fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW|syscall.SOCK_CLOEXEC, protocol) if err != nil { return nil, err } s := &NetlinkSocket{ - fd: fd, + fd: int32(fd), } s.lsa.Family = syscall.AF_NETLINK if err := syscall.Bind(fd, &s.lsa); err != nil { @@ -542,7 +556,7 @@ func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) { return nil, err } s := &NetlinkSocket{ - fd: fd, + fd: int32(fd), } s.lsa.Family = syscall.AF_NETLINK @@ -571,30 +585,32 @@ func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*Ne } func (s *NetlinkSocket) Close() { - syscall.Close(s.fd) - s.fd = -1 + fd := int(atomic.SwapInt32(&s.fd, -1)) + syscall.Close(fd) } func (s *NetlinkSocket) GetFd() int { - return s.fd + return int(atomic.LoadInt32(&s.fd)) } func (s *NetlinkSocket) Send(request *NetlinkRequest) error { - if s.fd < 0 { + fd := int(atomic.LoadInt32(&s.fd)) + if fd < 0 { return fmt.Errorf("Send called on a closed socket") } - if err := syscall.Sendto(s.fd, request.Serialize(), 0, &s.lsa); err != nil { + if err := syscall.Sendto(fd, request.Serialize(), 0, &s.lsa); err != nil { return err } return nil } func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) { - if s.fd < 0 { + fd := int(atomic.LoadInt32(&s.fd)) + if fd < 0 { return nil, fmt.Errorf("Receive called on a closed socket") } rb := make([]byte, syscall.Getpagesize()) - nr, _, err := syscall.Recvfrom(s.fd, rb, 0) + nr, _, err := syscall.Recvfrom(fd, rb, 0) if err != nil { return nil, err } @@ -606,7 +622,8 @@ func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) { } func (s *NetlinkSocket) GetPid() (uint32, error) { - lsa, err := syscall.Getsockname(s.fd) + fd := int(atomic.LoadInt32(&s.fd)) + lsa, err := syscall.Getsockname(fd) if err != nil { return 0, err } diff --git a/vendor/github.com/vishvananda/netlink/protinfo.go b/vendor/github.com/vishvananda/netlink/protinfo.go index ead3f2f1..0087c443 100644 --- a/vendor/github.com/vishvananda/netlink/protinfo.go +++ b/vendor/github.com/vishvananda/netlink/protinfo.go @@ -6,12 +6,14 @@ import ( // Protinfo represents bridge flags from netlink. type Protinfo struct { - Hairpin bool - Guard bool - FastLeave bool - RootBlock bool - Learning bool - Flood bool + Hairpin bool + Guard bool + FastLeave bool + RootBlock bool + Learning bool + Flood bool + ProxyArp bool + ProxyArpWiFi bool } // String returns a list of enabled flags @@ -35,6 +37,12 @@ func (prot *Protinfo) String() string { if prot.Flood { boolStrings = append(boolStrings, "Flood") } + if prot.ProxyArp { + boolStrings = append(boolStrings, "ProxyArp") + } + if prot.ProxyArpWiFi { + boolStrings = append(boolStrings, "ProxyArpWiFi") + } return strings.Join(boolStrings, " ") } diff --git a/vendor/github.com/vishvananda/netlink/protinfo_linux.go b/vendor/github.com/vishvananda/netlink/protinfo_linux.go index ea726953..10dd0d53 100644 --- a/vendor/github.com/vishvananda/netlink/protinfo_linux.go +++ b/vendor/github.com/vishvananda/netlink/protinfo_linux.go @@ -64,6 +64,10 @@ func parseProtinfo(infos []syscall.NetlinkRouteAttr) *Protinfo { pi.Learning = byteToBool(info.Value[0]) case nl.IFLA_BRPORT_UNICAST_FLOOD: pi.Flood = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_PROXYARP: + pi.ProxyArp = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_PROXYARP_WIFI: + pi.ProxyArpWiFi = byteToBool(info.Value[0]) } } return &pi diff --git a/vendor/github.com/vishvananda/netlink/route_linux.go b/vendor/github.com/vishvananda/netlink/route_linux.go index 9e0f1f93..cd739e71 100644 --- a/vendor/github.com/vishvananda/netlink/route_linux.go +++ b/vendor/github.com/vishvananda/netlink/route_linux.go @@ -401,7 +401,7 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) } if filter != nil { switch { - case filterMask&RT_FILTER_TABLE != 0 && route.Table != filter.Table: + case filterMask&RT_FILTER_TABLE != 0 && filter.Table != syscall.RT_TABLE_UNSPEC && route.Table != filter.Table: continue case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol: continue diff --git a/vendor/github.com/vishvananda/netns/README.md b/vendor/github.com/vishvananda/netns/README.md index 6b45cfb8..66a5f725 100644 --- a/vendor/github.com/vishvananda/netns/README.md +++ b/vendor/github.com/vishvananda/netns/README.md @@ -37,6 +37,7 @@ func main() { // Create a new network namespace newns, _ := netns.New() + netns.Set(newns) defer newns.Close() // Do something with the network namespace diff --git a/vendor/github.com/vishvananda/netns/netns.go b/vendor/github.com/vishvananda/netns/netns.go index 1ba6b261..dd2f2157 100644 --- a/vendor/github.com/vishvananda/netns/netns.go +++ b/vendor/github.com/vishvananda/netns/netns.go @@ -19,7 +19,7 @@ type NsHandle int // Equal determines if two network handles refer to the same network // namespace. This is done by comparing the device and inode that the -// file descripors point to. +// file descriptors point to. func (ns NsHandle) Equal(other NsHandle) bool { if ns == other { return true diff --git a/vendor/github.com/vishvananda/netns/netns_linux.go b/vendor/github.com/vishvananda/netns/netns_linux.go index 0f038d16..7162b86a 100644 --- a/vendor/github.com/vishvananda/netns/netns_linux.go +++ b/vendor/github.com/vishvananda/netns/netns_linux.go @@ -19,6 +19,8 @@ var SYS_SETNS = map[string]uintptr{ "amd64": 308, "arm64": 268, "arm": 375, + "mips": 4344, + "mipsle": 4344, "ppc64": 350, "ppc64le": 350, "s390x": 339, diff --git a/vendor/github.com/vishvananda/netns/netns_unspecified.go b/vendor/github.com/vishvananda/netns/netns_unspecified.go index b2edc565..d06af62b 100644 --- a/vendor/github.com/vishvananda/netns/netns_unspecified.go +++ b/vendor/github.com/vishvananda/netns/netns_unspecified.go @@ -22,6 +22,10 @@ func Get() (NsHandle, error) { return -1, ErrNotImplemented } +func GetFromPath(path string) (NsHandle, error) { + return -1, ErrNotImplemented +} + func GetFromName(name string) (NsHandle, error) { return -1, ErrNotImplemented } @@ -30,6 +34,10 @@ func GetFromPid(pid int) (NsHandle, error) { return -1, ErrNotImplemented } +func GetFromThread(pid, tid int) (NsHandle, error) { + return -1, ErrNotImplemented +} + func GetFromDocker(id string) (NsHandle, error) { return -1, ErrNotImplemented }