init
This commit is contained in:
		
							
								
								
									
										13
									
								
								vendor/github.com/vishvananda/netlink/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/vishvananda/netlink/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| language: go | ||||
| before_script: | ||||
|   # make sure we keep path in tact when we sudo | ||||
|   - 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 | ||||
							
								
								
									
										5
									
								
								vendor/github.com/vishvananda/netlink/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/vishvananda/netlink/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| # Changelog | ||||
|  | ||||
| ## 1.0.0 (2018-03-15) | ||||
|  | ||||
| Initial release tagging | ||||
							
								
								
									
										192
									
								
								vendor/github.com/vishvananda/netlink/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								vendor/github.com/vishvananda/netlink/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,192 @@ | ||||
|  | ||||
|                                  Apache License | ||||
|                            Version 2.0, January 2004 | ||||
|                         http://www.apache.org/licenses/ | ||||
|  | ||||
|    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
|  | ||||
|    1. Definitions. | ||||
|  | ||||
|       "License" shall mean the terms and conditions for use, reproduction, | ||||
|       and distribution as defined by Sections 1 through 9 of this document. | ||||
|  | ||||
|       "Licensor" shall mean the copyright owner or entity authorized by | ||||
|       the copyright owner that is granting the License. | ||||
|  | ||||
|       "Legal Entity" shall mean the union of the acting entity and all | ||||
|       other entities that control, are controlled by, or are under common | ||||
|       control with that entity. For the purposes of this definition, | ||||
|       "control" means (i) the power, direct or indirect, to cause the | ||||
|       direction or management of such entity, whether by contract or | ||||
|       otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
|       outstanding shares, or (iii) beneficial ownership of such entity. | ||||
|  | ||||
|       "You" (or "Your") shall mean an individual or Legal Entity | ||||
|       exercising permissions granted by this License. | ||||
|  | ||||
|       "Source" form shall mean the preferred form for making modifications, | ||||
|       including but not limited to software source code, documentation | ||||
|       source, and configuration files. | ||||
|  | ||||
|       "Object" form shall mean any form resulting from mechanical | ||||
|       transformation or translation of a Source form, including but | ||||
|       not limited to compiled object code, generated documentation, | ||||
|       and conversions to other media types. | ||||
|  | ||||
|       "Work" shall mean the work of authorship, whether in Source or | ||||
|       Object form, made available under the License, as indicated by a | ||||
|       copyright notice that is included in or attached to the work | ||||
|       (an example is provided in the Appendix below). | ||||
|  | ||||
|       "Derivative Works" shall mean any work, whether in Source or Object | ||||
|       form, that is based on (or derived from) the Work and for which the | ||||
|       editorial revisions, annotations, elaborations, or other modifications | ||||
|       represent, as a whole, an original work of authorship. For the purposes | ||||
|       of this License, Derivative Works shall not include works that remain | ||||
|       separable from, or merely link (or bind by name) to the interfaces of, | ||||
|       the Work and Derivative Works thereof. | ||||
|  | ||||
|       "Contribution" shall mean any work of authorship, including | ||||
|       the original version of the Work and any modifications or additions | ||||
|       to that Work or Derivative Works thereof, that is intentionally | ||||
|       submitted to Licensor for inclusion in the Work by the copyright owner | ||||
|       or by an individual or Legal Entity authorized to submit on behalf of | ||||
|       the copyright owner. For the purposes of this definition, "submitted" | ||||
|       means any form of electronic, verbal, or written communication sent | ||||
|       to the Licensor or its representatives, including but not limited to | ||||
|       communication on electronic mailing lists, source code control systems, | ||||
|       and issue tracking systems that are managed by, or on behalf of, the | ||||
|       Licensor for the purpose of discussing and improving the Work, but | ||||
|       excluding communication that is conspicuously marked or otherwise | ||||
|       designated in writing by the copyright owner as "Not a Contribution." | ||||
|  | ||||
|       "Contributor" shall mean Licensor and any individual or Legal Entity | ||||
|       on behalf of whom a Contribution has been received by Licensor and | ||||
|       subsequently incorporated within the Work. | ||||
|  | ||||
|    2. Grant of Copyright License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       copyright license to reproduce, prepare Derivative Works of, | ||||
|       publicly display, publicly perform, sublicense, and distribute the | ||||
|       Work and such Derivative Works in Source or Object form. | ||||
|  | ||||
|    3. Grant of Patent License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       (except as stated in this section) patent license to make, have made, | ||||
|       use, offer to sell, sell, import, and otherwise transfer the Work, | ||||
|       where such license applies only to those patent claims licensable | ||||
|       by such Contributor that are necessarily infringed by their | ||||
|       Contribution(s) alone or by combination of their Contribution(s) | ||||
|       with the Work to which such Contribution(s) was submitted. If You | ||||
|       institute patent litigation against any entity (including a | ||||
|       cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||
|       or a Contribution incorporated within the Work constitutes direct | ||||
|       or contributory patent infringement, then any patent licenses | ||||
|       granted to You under this License for that Work shall terminate | ||||
|       as of the date such litigation is filed. | ||||
|  | ||||
|    4. Redistribution. You may reproduce and distribute copies of the | ||||
|       Work or Derivative Works thereof in any medium, with or without | ||||
|       modifications, and in Source or Object form, provided that You | ||||
|       meet the following conditions: | ||||
|  | ||||
|       (a) You must give any other recipients of the Work or | ||||
|           Derivative Works a copy of this License; and | ||||
|  | ||||
|       (b) You must cause any modified files to carry prominent notices | ||||
|           stating that You changed the files; and | ||||
|  | ||||
|       (c) You must retain, in the Source form of any Derivative Works | ||||
|           that You distribute, all copyright, patent, trademark, and | ||||
|           attribution notices from the Source form of the Work, | ||||
|           excluding those notices that do not pertain to any part of | ||||
|           the Derivative Works; and | ||||
|  | ||||
|       (d) If the Work includes a "NOTICE" text file as part of its | ||||
|           distribution, then any Derivative Works that You distribute must | ||||
|           include a readable copy of the attribution notices contained | ||||
|           within such NOTICE file, excluding those notices that do not | ||||
|           pertain to any part of the Derivative Works, in at least one | ||||
|           of the following places: within a NOTICE text file distributed | ||||
|           as part of the Derivative Works; within the Source form or | ||||
|           documentation, if provided along with the Derivative Works; or, | ||||
|           within a display generated by the Derivative Works, if and | ||||
|           wherever such third-party notices normally appear. The contents | ||||
|           of the NOTICE file are for informational purposes only and | ||||
|           do not modify the License. You may add Your own attribution | ||||
|           notices within Derivative Works that You distribute, alongside | ||||
|           or as an addendum to the NOTICE text from the Work, provided | ||||
|           that such additional attribution notices cannot be construed | ||||
|           as modifying the License. | ||||
|  | ||||
|       You may add Your own copyright statement to Your modifications and | ||||
|       may provide additional or different license terms and conditions | ||||
|       for use, reproduction, or distribution of Your modifications, or | ||||
|       for any such Derivative Works as a whole, provided Your use, | ||||
|       reproduction, and distribution of the Work otherwise complies with | ||||
|       the conditions stated in this License. | ||||
|  | ||||
|    5. Submission of Contributions. Unless You explicitly state otherwise, | ||||
|       any Contribution intentionally submitted for inclusion in the Work | ||||
|       by You to the Licensor shall be under the terms and conditions of | ||||
|       this License, without any additional terms or conditions. | ||||
|       Notwithstanding the above, nothing herein shall supersede or modify | ||||
|       the terms of any separate license agreement you may have executed | ||||
|       with Licensor regarding such Contributions. | ||||
|  | ||||
|    6. Trademarks. This License does not grant permission to use the trade | ||||
|       names, trademarks, service marks, or product names of the Licensor, | ||||
|       except as required for reasonable and customary use in describing the | ||||
|       origin of the Work and reproducing the content of the NOTICE file. | ||||
|  | ||||
|    7. Disclaimer of Warranty. Unless required by applicable law or | ||||
|       agreed to in writing, Licensor provides the Work (and each | ||||
|       Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
|       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||
|       implied, including, without limitation, any warranties or conditions | ||||
|       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||
|       PARTICULAR PURPOSE. You are solely responsible for determining the | ||||
|       appropriateness of using or redistributing the Work and assume any | ||||
|       risks associated with Your exercise of permissions under this License. | ||||
|  | ||||
|    8. Limitation of Liability. In no event and under no legal theory, | ||||
|       whether in tort (including negligence), contract, or otherwise, | ||||
|       unless required by applicable law (such as deliberate and grossly | ||||
|       negligent acts) or agreed to in writing, shall any Contributor be | ||||
|       liable to You for damages, including any direct, indirect, special, | ||||
|       incidental, or consequential damages of any character arising as a | ||||
|       result of this License or out of the use or inability to use the | ||||
|       Work (including but not limited to damages for loss of goodwill, | ||||
|       work stoppage, computer failure or malfunction, or any and all | ||||
|       other commercial damages or losses), even if such Contributor | ||||
|       has been advised of the possibility of such damages. | ||||
|  | ||||
|    9. Accepting Warranty or Additional Liability. While redistributing | ||||
|       the Work or Derivative Works thereof, You may choose to offer, | ||||
|       and charge a fee for, acceptance of support, warranty, indemnity, | ||||
|       or other liability obligations and/or rights consistent with this | ||||
|       License. However, in accepting such obligations, You may act only | ||||
|       on Your own behalf and on Your sole responsibility, not on behalf | ||||
|       of any other Contributor, and only if You agree to indemnify, | ||||
|       defend, and hold each Contributor harmless for any liability | ||||
|       incurred by, or claims asserted against, such Contributor by reason | ||||
|       of your accepting any such warranty or additional liability. | ||||
|  | ||||
|    END OF TERMS AND CONDITIONS | ||||
|  | ||||
|    Copyright 2014 Vishvananda Ishaya. | ||||
|    Copyright 2014 Docker, Inc. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
							
								
								
									
										30
									
								
								vendor/github.com/vishvananda/netlink/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/vishvananda/netlink/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| DIRS := \ | ||||
| 	. \ | ||||
| 	nl | ||||
|  | ||||
| DEPS = \ | ||||
| 	github.com/vishvananda/netns \ | ||||
| 	golang.org/x/sys/unix | ||||
|  | ||||
| uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) | ||||
| testdirs = $(call uniq,$(foreach d,$(1),$(dir $(wildcard $(d)/*_test.go)))) | ||||
| goroot = $(addprefix ../../../,$(1)) | ||||
| unroot = $(subst ../../../,,$(1)) | ||||
| fmt = $(addprefix fmt-,$(1)) | ||||
|  | ||||
| all: test | ||||
|  | ||||
| $(call goroot,$(DEPS)): | ||||
| 	go get $(call unroot,$@) | ||||
|  | ||||
| .PHONY: $(call testdirs,$(DIRS)) | ||||
| $(call testdirs,$(DIRS)): | ||||
| 	go test -test.exec sudo -test.parallel 4 -timeout 60s -test.v github.com/vishvananda/netlink/$@ | ||||
|  | ||||
| $(call fmt,$(call testdirs,$(DIRS))): | ||||
| 	! gofmt -l $(subst fmt-,,$@)/*.go | grep -q . | ||||
|  | ||||
| .PHONY: fmt | ||||
| fmt: $(call fmt,$(call testdirs,$(DIRS))) | ||||
|  | ||||
| test: fmt $(call goroot,$(DEPS)) $(call testdirs,$(DIRS)) | ||||
							
								
								
									
										92
									
								
								vendor/github.com/vishvananda/netlink/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								vendor/github.com/vishvananda/netlink/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| # netlink - netlink library for go # | ||||
|  | ||||
| [](https://travis-ci.org/vishvananda/netlink) [](https://godoc.org/github.com/vishvananda/netlink) | ||||
|  | ||||
| The netlink package provides a simple netlink library for go. Netlink | ||||
| is the interface a user-space program in linux uses to communicate with | ||||
| the kernel. It can be used to add and remove interfaces, set ip addresses | ||||
| and routes, and configure ipsec. Netlink communication requires elevated | ||||
| privileges, so in most cases this code needs to be run as root. Since | ||||
| low-level netlink messages are inscrutable at best, the library attempts | ||||
| to provide an api that is loosely modeled on the CLI provided by iproute2. | ||||
| Actions like `ip link add` will be accomplished via a similarly named | ||||
| function like AddLink(). This library began its life as a fork of the | ||||
| netlink functionality in | ||||
| [docker/libcontainer](https://github.com/docker/libcontainer) but was | ||||
| heavily rewritten to improve testability, performance, and to add new | ||||
| functionality like ipsec xfrm handling. | ||||
|  | ||||
| ## Local Build and Test ## | ||||
|  | ||||
| You can use go get command: | ||||
|  | ||||
|     go get github.com/vishvananda/netlink | ||||
|  | ||||
| Testing dependencies: | ||||
|  | ||||
|     go get github.com/vishvananda/netns | ||||
|  | ||||
| Testing (requires root): | ||||
|  | ||||
|     sudo -E go test github.com/vishvananda/netlink | ||||
|  | ||||
| ## Examples ## | ||||
|  | ||||
| Add a new bridge and add eth1 into it: | ||||
|  | ||||
| ```go | ||||
| package main | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     "github.com/vishvananda/netlink" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
|     la := netlink.NewLinkAttrs() | ||||
|     la.Name = "foo" | ||||
|     mybridge := &netlink.Bridge{LinkAttrs: la} | ||||
|     err := netlink.LinkAdd(mybridge) | ||||
|     if err != nil  { | ||||
|         fmt.Printf("could not add %s: %v\n", la.Name, err) | ||||
|     } | ||||
|     eth1, _ := netlink.LinkByName("eth1") | ||||
|     netlink.LinkSetMaster(eth1, mybridge) | ||||
| } | ||||
|  | ||||
| ``` | ||||
| Note `NewLinkAttrs` constructor, it sets default values in structure. For now | ||||
| it sets only `TxQLen` to `-1`, so kernel will set default by itself. If you're | ||||
| using simple initialization(`LinkAttrs{Name: "foo"}`) `TxQLen` will be set to | ||||
| `0` unless you specify it like `LinkAttrs{Name: "foo", TxQLen: 1000}`. | ||||
|  | ||||
| Add a new ip address to loopback: | ||||
|  | ||||
| ```go | ||||
| package main | ||||
|  | ||||
| import ( | ||||
|     "github.com/vishvananda/netlink" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
|     lo, _ := netlink.LinkByName("lo") | ||||
|     addr, _ := netlink.ParseAddr("169.254.169.254/32") | ||||
|     netlink.AddrAdd(lo, addr) | ||||
| } | ||||
|  | ||||
| ``` | ||||
|  | ||||
| ## Future Work ## | ||||
|  | ||||
| Many pieces of netlink are not yet fully supported in the high-level | ||||
| interface. Aspects of virtually all of the high-level objects don't exist. | ||||
| Many of the underlying primitives are there, so its a matter of putting | ||||
| the right fields into the high-level objects and making sure that they | ||||
| are serialized and deserialized correctly in the Add and List methods. | ||||
|  | ||||
| There are also a few pieces of low level netlink functionality that still | ||||
| need to be implemented. Routing rules are not in place and some of the | ||||
| more advanced link types. Hopefully there is decent structure and testing | ||||
| in place to make these fairly straightforward to add. | ||||
|  | ||||
							
								
								
									
										56
									
								
								vendor/github.com/vishvananda/netlink/addr.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								vendor/github.com/vishvananda/netlink/addr.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // Addr represents an IP address from netlink. Netlink ip addresses | ||||
| // 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 | ||||
| 	PreferedLft int | ||||
| 	ValidLft    int | ||||
| } | ||||
|  | ||||
| // String returns $ip/$netmask $label | ||||
| func (a Addr) String() string { | ||||
| 	return strings.TrimSpace(fmt.Sprintf("%s %s", a.IPNet, a.Label)) | ||||
| } | ||||
|  | ||||
| // ParseAddr parses the string representation of an address in the | ||||
| // form $ip/$netmask $label. The label portion is optional | ||||
| func ParseAddr(s string) (*Addr, error) { | ||||
| 	label := "" | ||||
| 	parts := strings.Split(s, " ") | ||||
| 	if len(parts) > 1 { | ||||
| 		s = parts[0] | ||||
| 		label = parts[1] | ||||
| 	} | ||||
| 	m, err := ParseIPNet(s) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &Addr{IPNet: m, Label: label}, nil | ||||
| } | ||||
|  | ||||
| // Equal returns true if both Addrs have the same net.IPNet value. | ||||
| func (a Addr) Equal(x Addr) bool { | ||||
| 	sizea, _ := a.Mask.Size() | ||||
| 	sizeb, _ := x.Mask.Size() | ||||
| 	// ignore label for comparison | ||||
| 	return a.IP.Equal(x.IP) && sizea == sizeb | ||||
| } | ||||
|  | ||||
| func (a Addr) PeerEqual(x Addr) bool { | ||||
| 	sizea, _ := a.Peer.Mask.Size() | ||||
| 	sizeb, _ := x.Peer.Mask.Size() | ||||
| 	// ignore label for comparison | ||||
| 	return a.Peer.IP.Equal(x.Peer.IP) && sizea == sizeb | ||||
| } | ||||
							
								
								
									
										354
									
								
								vendor/github.com/vishvananda/netlink/addr_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										354
									
								
								vendor/github.com/vishvananda/netlink/addr_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,354 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"github.com/vishvananda/netns" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // IFA_FLAGS is a u32 attribute. | ||||
| const IFA_FLAGS = 0x8 | ||||
|  | ||||
| // AddrAdd will add an IP address to a link device. | ||||
| // Equivalent to: `ip addr add $addr dev $link` | ||||
| func AddrAdd(link Link, addr *Addr) error { | ||||
| 	return pkgHandle.AddrAdd(link, addr) | ||||
| } | ||||
|  | ||||
| // AddrAdd will add an IP address to a link device. | ||||
| // Equivalent to: `ip addr add $addr dev $link` | ||||
| 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) | ||||
| 	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(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.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 { | ||||
| 	return pkgHandle.AddrDel(link, addr) | ||||
| } | ||||
|  | ||||
| // AddrDel will delete an IP address from a link device. | ||||
| // Equivalent to: `ip addr del $addr dev $link` | ||||
| func (h *Handle) AddrDel(link Link, addr *Addr) error { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK) | ||||
| 	return h.addrHandle(link, addr, req) | ||||
| } | ||||
|  | ||||
| func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error { | ||||
| 	base := link.Attrs() | ||||
| 	if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) { | ||||
| 		return fmt.Errorf("label must begin with interface name") | ||||
| 	} | ||||
| 	h.ensureIndex(base) | ||||
|  | ||||
| 	family := nl.GetIPFamily(addr.IP) | ||||
|  | ||||
| 	msg := nl.NewIfAddrmsg(family) | ||||
| 	msg.Index = uint32(base.Index) | ||||
| 	msg.Scope = uint8(addr.Scope) | ||||
| 	prefixlen, masklen := addr.Mask.Size() | ||||
| 	msg.Prefixlen = uint8(prefixlen) | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	var localAddrData []byte | ||||
| 	if family == FAMILY_V4 { | ||||
| 		localAddrData = addr.IP.To4() | ||||
| 	} else { | ||||
| 		localAddrData = addr.IP.To16() | ||||
| 	} | ||||
|  | ||||
| 	localData := nl.NewRtAttr(unix.IFA_LOCAL, localAddrData) | ||||
| 	req.AddData(localData) | ||||
| 	var peerAddrData []byte | ||||
| 	if addr.Peer != nil { | ||||
| 		if family == FAMILY_V4 { | ||||
| 			peerAddrData = addr.Peer.IP.To4() | ||||
| 		} else { | ||||
| 			peerAddrData = addr.Peer.IP.To16() | ||||
| 		} | ||||
| 	} else { | ||||
| 		peerAddrData = localAddrData | ||||
| 	} | ||||
|  | ||||
| 	addressData := nl.NewRtAttr(unix.IFA_ADDRESS, peerAddrData) | ||||
| 	req.AddData(addressData) | ||||
|  | ||||
| 	if addr.Flags != 0 { | ||||
| 		if addr.Flags <= 0xff { | ||||
| 			msg.IfAddrmsg.Flags = uint8(addr.Flags) | ||||
| 		} else { | ||||
| 			b := make([]byte, 4) | ||||
| 			native.PutUint32(b, uint32(addr.Flags)) | ||||
| 			flagsData := nl.NewRtAttr(IFA_FLAGS, b) | ||||
| 			req.AddData(flagsData) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if family == FAMILY_V4 { | ||||
| 		if addr.Broadcast == nil { | ||||
| 			calcBroadcast := make(net.IP, masklen/8) | ||||
| 			for i := range localAddrData { | ||||
| 				calcBroadcast[i] = localAddrData[i] | ^addr.Mask[i] | ||||
| 			} | ||||
| 			addr.Broadcast = calcBroadcast | ||||
| 		} | ||||
| 		req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast)) | ||||
|  | ||||
| 		if addr.Label != "" { | ||||
| 			labelData := nl.NewRtAttr(unix.IFA_LABEL, nl.ZeroTerminated(addr.Label)) | ||||
| 			req.AddData(labelData) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// 0 is the default value for these attributes. However, 0 means "expired", while the least-surprising default | ||||
| 	// value should be "forever". To compensate for that, only add the attributes if at least one of the values is | ||||
| 	// non-zero, which means the caller has explicitly set them | ||||
| 	if addr.ValidLft > 0 || addr.PreferedLft > 0 { | ||||
| 		cachedata := nl.IfaCacheInfo{ | ||||
| 			IfaValid:    uint32(addr.ValidLft), | ||||
| 			IfaPrefered: uint32(addr.PreferedLft), | ||||
| 		} | ||||
| 		req.AddData(nl.NewRtAttr(unix.IFA_CACHEINFO, cachedata.Serialize())) | ||||
| 	} | ||||
|  | ||||
| 	_, err := req.Execute(unix.NETLINK_ROUTE, 0) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // AddrList gets a list of IP addresses in the system. | ||||
| // Equivalent to: `ip addr show`. | ||||
| // The list can be filtered by link and ip family. | ||||
| func AddrList(link Link, family int) ([]Addr, error) { | ||||
| 	return pkgHandle.AddrList(link, family) | ||||
| } | ||||
|  | ||||
| // AddrList gets a list of IP addresses in the system. | ||||
| // Equivalent to: `ip addr show`. | ||||
| // The list can be filtered by link and ip family. | ||||
| func (h *Handle) AddrList(link Link, family int) ([]Addr, error) { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_GETADDR, unix.NLM_F_DUMP) | ||||
| 	msg := nl.NewIfInfomsg(family) | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWADDR) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	indexFilter := 0 | ||||
| 	if link != nil { | ||||
| 		base := link.Attrs() | ||||
| 		h.ensureIndex(base) | ||||
| 		indexFilter = base.Index | ||||
| 	} | ||||
|  | ||||
| 	var res []Addr | ||||
| 	for _, m := range msgs { | ||||
| 		addr, msgFamily, ifindex, err := parseAddr(m) | ||||
| 		if err != nil { | ||||
| 			return res, err | ||||
| 		} | ||||
|  | ||||
| 		if link != nil && ifindex != indexFilter { | ||||
| 			// Ignore messages from other interfaces | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if family != FAMILY_ALL && msgFamily != family { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		res = append(res, addr) | ||||
| 	} | ||||
|  | ||||
| 	return res, nil | ||||
| } | ||||
|  | ||||
| func parseAddr(m []byte) (addr Addr, family, index int, err error) { | ||||
| 	msg := nl.DeserializeIfAddrmsg(m) | ||||
|  | ||||
| 	family = -1 | ||||
| 	index = -1 | ||||
|  | ||||
| 	attrs, err1 := nl.ParseRouteAttr(m[msg.Len():]) | ||||
| 	if err1 != nil { | ||||
| 		err = err1 | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	family = int(msg.Family) | ||||
| 	index = int(msg.Index) | ||||
|  | ||||
| 	var local, dst *net.IPNet | ||||
| 	for _, attr := range attrs { | ||||
| 		switch attr.Attr.Type { | ||||
| 		case unix.IFA_ADDRESS: | ||||
| 			dst = &net.IPNet{ | ||||
| 				IP:   attr.Value, | ||||
| 				Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), | ||||
| 			} | ||||
| 			addr.Peer = dst | ||||
| 		case unix.IFA_LOCAL: | ||||
| 			local = &net.IPNet{ | ||||
| 				IP:   attr.Value, | ||||
| 				Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), | ||||
| 			} | ||||
| 			addr.IPNet = local | ||||
| 		case unix.IFA_BROADCAST: | ||||
| 			addr.Broadcast = attr.Value | ||||
| 		case unix.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) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// IFA_LOCAL should be there but if not, fall back to IFA_ADDRESS | ||||
| 	if local != nil { | ||||
| 		addr.IPNet = local | ||||
| 	} else { | ||||
| 		addr.IPNet = dst | ||||
| 	} | ||||
| 	addr.Scope = int(msg.Scope) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| type AddrUpdate struct { | ||||
| 	LinkAddress net.IPNet | ||||
| 	LinkIndex   int | ||||
| 	Flags       int | ||||
| 	Scope       int | ||||
| 	PreferedLft int | ||||
| 	ValidLft    int | ||||
| 	NewAddr     bool // true=added false=deleted | ||||
| } | ||||
|  | ||||
| // AddrSubscribe takes a chan down which notifications will be sent | ||||
| // when addresses change.  Close the 'done' chan to stop subscription. | ||||
| func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error { | ||||
| 	return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false) | ||||
| } | ||||
|  | ||||
| // AddrSubscribeAt works like AddrSubscribe plus it allows the caller | ||||
| // to choose the network namespace in which to subscribe (ns). | ||||
| func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error { | ||||
| 	return addrSubscribeAt(ns, netns.None(), ch, done, nil, false) | ||||
| } | ||||
|  | ||||
| // AddrSubscribeOptions contains a set of options to use with | ||||
| // AddrSubscribeWithOptions. | ||||
| type AddrSubscribeOptions struct { | ||||
| 	Namespace     *netns.NsHandle | ||||
| 	ErrorCallback func(error) | ||||
| 	ListExisting  bool | ||||
| } | ||||
|  | ||||
| // AddrSubscribeWithOptions work like AddrSubscribe but enable to | ||||
| // provide additional options to modify the behavior. Currently, the | ||||
| // namespace can be provided as well as an error callback. | ||||
| func AddrSubscribeWithOptions(ch chan<- AddrUpdate, done <-chan struct{}, options AddrSubscribeOptions) error { | ||||
| 	if options.Namespace == nil { | ||||
| 		none := netns.None() | ||||
| 		options.Namespace = &none | ||||
| 	} | ||||
| 	return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting) | ||||
| } | ||||
|  | ||||
| func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error { | ||||
| 	s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if done != nil { | ||||
| 		go func() { | ||||
| 			<-done | ||||
| 			s.Close() | ||||
| 		}() | ||||
| 	} | ||||
| 	if listExisting { | ||||
| 		req := pkgHandle.newNetlinkRequest(unix.RTM_GETADDR, | ||||
| 			unix.NLM_F_DUMP) | ||||
| 		infmsg := nl.NewIfInfomsg(unix.AF_UNSPEC) | ||||
| 		req.AddData(infmsg) | ||||
| 		if err := s.Send(req); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	go func() { | ||||
| 		defer close(ch) | ||||
| 		for { | ||||
| 			msgs, err := s.Receive() | ||||
| 			if err != nil { | ||||
| 				if cberr != nil { | ||||
| 					cberr(err) | ||||
| 				} | ||||
| 				return | ||||
| 			} | ||||
| 			for _, m := range msgs { | ||||
| 				if m.Header.Type == unix.NLMSG_DONE { | ||||
| 					continue | ||||
| 				} | ||||
| 				if m.Header.Type == unix.NLMSG_ERROR { | ||||
| 					native := nl.NativeEndian() | ||||
| 					error := int32(native.Uint32(m.Data[0:4])) | ||||
| 					if error == 0 { | ||||
| 						continue | ||||
| 					} | ||||
| 					if cberr != nil { | ||||
| 						cberr(syscall.Errno(-error)) | ||||
| 					} | ||||
| 					return | ||||
| 				} | ||||
| 				msgType := m.Header.Type | ||||
| 				if msgType != unix.RTM_NEWADDR && msgType != unix.RTM_DELADDR { | ||||
| 					if cberr != nil { | ||||
| 						cberr(fmt.Errorf("bad message type: %d", msgType)) | ||||
| 					} | ||||
| 					return | ||||
| 				} | ||||
|  | ||||
| 				addr, _, ifindex, err := parseAddr(m.Data) | ||||
| 				if err != nil { | ||||
| 					if cberr != nil { | ||||
| 						cberr(fmt.Errorf("could not parse address: %v", err)) | ||||
| 					} | ||||
| 					return | ||||
| 				} | ||||
|  | ||||
| 				ch <- AddrUpdate{LinkAddress: *addr.IPNet, | ||||
| 					LinkIndex:   ifindex, | ||||
| 					NewAddr:     msgType == unix.RTM_NEWADDR, | ||||
| 					Flags:       addr.Flags, | ||||
| 					Scope:       addr.Scope, | ||||
| 					PreferedLft: addr.PreferedLft, | ||||
| 					ValidLft:    addr.ValidLft} | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										53
									
								
								vendor/github.com/vishvananda/netlink/bpf_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								vendor/github.com/vishvananda/netlink/bpf_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| type BpfProgType uint32 | ||||
|  | ||||
| const ( | ||||
| 	BPF_PROG_TYPE_UNSPEC BpfProgType = iota | ||||
| 	BPF_PROG_TYPE_SOCKET_FILTER | ||||
| 	BPF_PROG_TYPE_KPROBE | ||||
| 	BPF_PROG_TYPE_SCHED_CLS | ||||
| 	BPF_PROG_TYPE_SCHED_ACT | ||||
| 	BPF_PROG_TYPE_TRACEPOINT | ||||
| 	BPF_PROG_TYPE_XDP | ||||
| ) | ||||
|  | ||||
| type BPFAttr struct { | ||||
| 	ProgType    uint32 | ||||
| 	InsnCnt     uint32 | ||||
| 	Insns       uintptr | ||||
| 	License     uintptr | ||||
| 	LogLevel    uint32 | ||||
| 	LogSize     uint32 | ||||
| 	LogBuf      uintptr | ||||
| 	KernVersion uint32 | ||||
| } | ||||
|  | ||||
| // loadSimpleBpf loads a trivial bpf program for testing purposes. | ||||
| func loadSimpleBpf(progType BpfProgType, ret uint32) (int, error) { | ||||
| 	insns := []uint64{ | ||||
| 		0x00000000000000b7 | (uint64(ret) << 32), | ||||
| 		0x0000000000000095, | ||||
| 	} | ||||
| 	license := []byte{'A', 'S', 'L', '2', '\x00'} | ||||
| 	attr := BPFAttr{ | ||||
| 		ProgType: uint32(progType), | ||||
| 		InsnCnt:  uint32(len(insns)), | ||||
| 		Insns:    uintptr(unsafe.Pointer(&insns[0])), | ||||
| 		License:  uintptr(unsafe.Pointer(&license[0])), | ||||
| 	} | ||||
| 	fd, _, errno := unix.Syscall(unix.SYS_BPF, | ||||
| 		5, /* bpf cmd */ | ||||
| 		uintptr(unsafe.Pointer(&attr)), | ||||
| 		unsafe.Sizeof(attr)) | ||||
| 	if errno != 0 { | ||||
| 		return 0, errno | ||||
| 	} | ||||
| 	return int(fd), nil | ||||
| } | ||||
							
								
								
									
										115
									
								
								vendor/github.com/vishvananda/netlink/bridge_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								vendor/github.com/vishvananda/netlink/bridge_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // 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(unix.RTM_GETLINK, unix.NLM_F_DUMP) | ||||
| 	msg := nl.NewIfInfomsg(unix.AF_BRIDGE) | ||||
| 	req.AddData(msg) | ||||
| 	req.AddData(nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN)))) | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.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 unix.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(unix.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(unix.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, unix.NLM_F_ACK) | ||||
|  | ||||
| 	msg := nl.NewIfInfomsg(unix.AF_BRIDGE) | ||||
| 	msg.Index = int32(base.Index) | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	br := nl.NewRtAttr(unix.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(unix.NETLINK_ROUTE, 0) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										78
									
								
								vendor/github.com/vishvananda/netlink/class.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								vendor/github.com/vishvananda/netlink/class.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| ) | ||||
|  | ||||
| type Class interface { | ||||
| 	Attrs() *ClassAttrs | ||||
| 	Type() string | ||||
| } | ||||
|  | ||||
| // ClassAttrs represents a netlink class. A filter is associated with a link, | ||||
| // has a handle and a parent. The root filter of a device should have a | ||||
| // parent == HANDLE_ROOT. | ||||
| type ClassAttrs struct { | ||||
| 	LinkIndex int | ||||
| 	Handle    uint32 | ||||
| 	Parent    uint32 | ||||
| 	Leaf      uint32 | ||||
| } | ||||
|  | ||||
| func (q ClassAttrs) String() string { | ||||
| 	return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Leaf: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Leaf) | ||||
| } | ||||
|  | ||||
| type HtbClassAttrs struct { | ||||
| 	// TODO handle all attributes | ||||
| 	Rate    uint64 | ||||
| 	Ceil    uint64 | ||||
| 	Buffer  uint32 | ||||
| 	Cbuffer uint32 | ||||
| 	Quantum uint32 | ||||
| 	Level   uint32 | ||||
| 	Prio    uint32 | ||||
| } | ||||
|  | ||||
| func (q HtbClassAttrs) String() string { | ||||
| 	return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer) | ||||
| } | ||||
|  | ||||
| // HtbClass represents an Htb class | ||||
| type HtbClass struct { | ||||
| 	ClassAttrs | ||||
| 	Rate    uint64 | ||||
| 	Ceil    uint64 | ||||
| 	Buffer  uint32 | ||||
| 	Cbuffer uint32 | ||||
| 	Quantum uint32 | ||||
| 	Level   uint32 | ||||
| 	Prio    uint32 | ||||
| } | ||||
|  | ||||
| func (q HtbClass) String() string { | ||||
| 	return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer) | ||||
| } | ||||
|  | ||||
| func (q *HtbClass) Attrs() *ClassAttrs { | ||||
| 	return &q.ClassAttrs | ||||
| } | ||||
|  | ||||
| func (q *HtbClass) Type() string { | ||||
| 	return "htb" | ||||
| } | ||||
|  | ||||
| // GenericClass classes represent types that are not currently understood | ||||
| // by this netlink library. | ||||
| type GenericClass struct { | ||||
| 	ClassAttrs | ||||
| 	ClassType string | ||||
| } | ||||
|  | ||||
| func (class *GenericClass) Attrs() *ClassAttrs { | ||||
| 	return &class.ClassAttrs | ||||
| } | ||||
|  | ||||
| func (class *GenericClass) Type() string { | ||||
| 	return class.ClassType | ||||
| } | ||||
							
								
								
									
										255
									
								
								vendor/github.com/vishvananda/netlink/class_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								vendor/github.com/vishvananda/netlink/class_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,255 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // NOTE: function is in here because it uses other linux functions | ||||
| func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass { | ||||
| 	mtu := 1600 | ||||
| 	rate := cattrs.Rate / 8 | ||||
| 	ceil := cattrs.Ceil / 8 | ||||
| 	buffer := cattrs.Buffer | ||||
| 	cbuffer := cattrs.Cbuffer | ||||
|  | ||||
| 	if ceil == 0 { | ||||
| 		ceil = rate | ||||
| 	} | ||||
|  | ||||
| 	if buffer == 0 { | ||||
| 		buffer = uint32(float64(rate)/Hz() + float64(mtu)) | ||||
| 	} | ||||
| 	buffer = uint32(Xmittime(rate, buffer)) | ||||
|  | ||||
| 	if cbuffer == 0 { | ||||
| 		cbuffer = uint32(float64(ceil)/Hz() + float64(mtu)) | ||||
| 	} | ||||
| 	cbuffer = uint32(Xmittime(ceil, cbuffer)) | ||||
|  | ||||
| 	return &HtbClass{ | ||||
| 		ClassAttrs: attrs, | ||||
| 		Rate:       rate, | ||||
| 		Ceil:       ceil, | ||||
| 		Buffer:     buffer, | ||||
| 		Cbuffer:    cbuffer, | ||||
| 		Quantum:    10, | ||||
| 		Level:      0, | ||||
| 		Prio:       0, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ClassDel will delete a class from the system. | ||||
| // Equivalent to: `tc class del $class` | ||||
| func ClassDel(class Class) error { | ||||
| 	return pkgHandle.ClassDel(class) | ||||
| } | ||||
|  | ||||
| // ClassDel will delete a class from the system. | ||||
| // Equivalent to: `tc class del $class` | ||||
| func (h *Handle) ClassDel(class Class) error { | ||||
| 	return h.classModify(unix.RTM_DELTCLASS, 0, class) | ||||
| } | ||||
|  | ||||
| // ClassChange will change a class in place | ||||
| // Equivalent to: `tc class change $class` | ||||
| // The parent and handle MUST NOT be changed. | ||||
| func ClassChange(class Class) error { | ||||
| 	return pkgHandle.ClassChange(class) | ||||
| } | ||||
|  | ||||
| // ClassChange will change a class in place | ||||
| // Equivalent to: `tc class change $class` | ||||
| // The parent and handle MUST NOT be changed. | ||||
| func (h *Handle) ClassChange(class Class) error { | ||||
| 	return h.classModify(unix.RTM_NEWTCLASS, 0, class) | ||||
| } | ||||
|  | ||||
| // ClassReplace will replace a class to the system. | ||||
| // quivalent to: `tc class replace $class` | ||||
| // The handle MAY be changed. | ||||
| // If a class already exist with this parent/handle pair, the class is changed. | ||||
| // If a class does not already exist with this parent/handle, a new class is created. | ||||
| func ClassReplace(class Class) error { | ||||
| 	return pkgHandle.ClassReplace(class) | ||||
| } | ||||
|  | ||||
| // ClassReplace will replace a class to the system. | ||||
| // quivalent to: `tc class replace $class` | ||||
| // The handle MAY be changed. | ||||
| // If a class already exist with this parent/handle pair, the class is changed. | ||||
| // If a class does not already exist with this parent/handle, a new class is created. | ||||
| func (h *Handle) ClassReplace(class Class) error { | ||||
| 	return h.classModify(unix.RTM_NEWTCLASS, unix.NLM_F_CREATE, class) | ||||
| } | ||||
|  | ||||
| // ClassAdd will add a class to the system. | ||||
| // Equivalent to: `tc class add $class` | ||||
| func ClassAdd(class Class) error { | ||||
| 	return pkgHandle.ClassAdd(class) | ||||
| } | ||||
|  | ||||
| // ClassAdd will add a class to the system. | ||||
| // Equivalent to: `tc class add $class` | ||||
| func (h *Handle) ClassAdd(class Class) error { | ||||
| 	return h.classModify( | ||||
| 		unix.RTM_NEWTCLASS, | ||||
| 		unix.NLM_F_CREATE|unix.NLM_F_EXCL, | ||||
| 		class, | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func (h *Handle) classModify(cmd, flags int, class Class) error { | ||||
| 	req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK) | ||||
| 	base := class.Attrs() | ||||
| 	msg := &nl.TcMsg{ | ||||
| 		Family:  nl.FAMILY_ALL, | ||||
| 		Ifindex: int32(base.LinkIndex), | ||||
| 		Handle:  base.Handle, | ||||
| 		Parent:  base.Parent, | ||||
| 	} | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	if cmd != unix.RTM_DELTCLASS { | ||||
| 		if err := classPayload(req, class); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	_, err := req.Execute(unix.NETLINK_ROUTE, 0) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func classPayload(req *nl.NetlinkRequest, class Class) error { | ||||
| 	req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(class.Type()))) | ||||
|  | ||||
| 	options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) | ||||
| 	if htb, ok := class.(*HtbClass); ok { | ||||
| 		opt := nl.TcHtbCopt{} | ||||
| 		opt.Buffer = htb.Buffer | ||||
| 		opt.Cbuffer = htb.Cbuffer | ||||
| 		opt.Quantum = htb.Quantum | ||||
| 		opt.Level = htb.Level | ||||
| 		opt.Prio = htb.Prio | ||||
| 		// TODO: Handle Debug properly. For now default to 0 | ||||
| 		/* Calculate {R,C}Tab and set Rate and Ceil */ | ||||
| 		cellLog := -1 | ||||
| 		ccellLog := -1 | ||||
| 		linklayer := nl.LINKLAYER_ETHERNET | ||||
| 		mtu := 1600 | ||||
| 		var rtab [256]uint32 | ||||
| 		var ctab [256]uint32 | ||||
| 		tcrate := nl.TcRateSpec{Rate: uint32(htb.Rate)} | ||||
| 		if CalcRtable(&tcrate, rtab[:], cellLog, uint32(mtu), linklayer) < 0 { | ||||
| 			return errors.New("HTB: failed to calculate rate table") | ||||
| 		} | ||||
| 		opt.Rate = tcrate | ||||
| 		tcceil := nl.TcRateSpec{Rate: uint32(htb.Ceil)} | ||||
| 		if CalcRtable(&tcceil, ctab[:], ccellLog, uint32(mtu), linklayer) < 0 { | ||||
| 			return errors.New("HTB: failed to calculate ceil rate table") | ||||
| 		} | ||||
| 		opt.Ceil = tcceil | ||||
| 		nl.NewRtAttrChild(options, nl.TCA_HTB_PARMS, opt.Serialize()) | ||||
| 		nl.NewRtAttrChild(options, nl.TCA_HTB_RTAB, SerializeRtab(rtab)) | ||||
| 		nl.NewRtAttrChild(options, nl.TCA_HTB_CTAB, SerializeRtab(ctab)) | ||||
| 	} | ||||
| 	req.AddData(options) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ClassList gets a list of classes in the system. | ||||
| // Equivalent to: `tc class show`. | ||||
| // Generally returns nothing if link and parent are not specified. | ||||
| func ClassList(link Link, parent uint32) ([]Class, error) { | ||||
| 	return pkgHandle.ClassList(link, parent) | ||||
| } | ||||
|  | ||||
| // ClassList gets a list of classes in the system. | ||||
| // Equivalent to: `tc class show`. | ||||
| // Generally returns nothing if link and parent are not specified. | ||||
| func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_GETTCLASS, unix.NLM_F_DUMP) | ||||
| 	msg := &nl.TcMsg{ | ||||
| 		Family: nl.FAMILY_ALL, | ||||
| 		Parent: parent, | ||||
| 	} | ||||
| 	if link != nil { | ||||
| 		base := link.Attrs() | ||||
| 		h.ensureIndex(base) | ||||
| 		msg.Ifindex = int32(base.Index) | ||||
| 	} | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTCLASS) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	var res []Class | ||||
| 	for _, m := range msgs { | ||||
| 		msg := nl.DeserializeTcMsg(m) | ||||
|  | ||||
| 		attrs, err := nl.ParseRouteAttr(m[msg.Len():]) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		base := ClassAttrs{ | ||||
| 			LinkIndex: int(msg.Ifindex), | ||||
| 			Handle:    msg.Handle, | ||||
| 			Parent:    msg.Parent, | ||||
| 		} | ||||
|  | ||||
| 		var class Class | ||||
| 		classType := "" | ||||
| 		for _, attr := range attrs { | ||||
| 			switch attr.Attr.Type { | ||||
| 			case nl.TCA_KIND: | ||||
| 				classType = string(attr.Value[:len(attr.Value)-1]) | ||||
| 				switch classType { | ||||
| 				case "htb": | ||||
| 					class = &HtbClass{} | ||||
| 				default: | ||||
| 					class = &GenericClass{ClassType: classType} | ||||
| 				} | ||||
| 			case nl.TCA_OPTIONS: | ||||
| 				switch classType { | ||||
| 				case "htb": | ||||
| 					data, err := nl.ParseRouteAttr(attr.Value) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 					_, err = parseHtbClassData(class, data) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		*class.Attrs() = base | ||||
| 		res = append(res, class) | ||||
| 	} | ||||
|  | ||||
| 	return res, nil | ||||
| } | ||||
|  | ||||
| func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, error) { | ||||
| 	htb := class.(*HtbClass) | ||||
| 	detailed := false | ||||
| 	for _, datum := range data { | ||||
| 		switch datum.Attr.Type { | ||||
| 		case nl.TCA_HTB_PARMS: | ||||
| 			opt := nl.DeserializeTcHtbCopt(datum.Value) | ||||
| 			htb.Rate = uint64(opt.Rate.Rate) | ||||
| 			htb.Ceil = uint64(opt.Ceil.Rate) | ||||
| 			htb.Buffer = opt.Buffer | ||||
| 			htb.Cbuffer = opt.Cbuffer | ||||
| 			htb.Quantum = opt.Quantum | ||||
| 			htb.Level = opt.Level | ||||
| 			htb.Prio = opt.Prio | ||||
| 		} | ||||
| 	} | ||||
| 	return detailed, nil | ||||
| } | ||||
							
								
								
									
										371
									
								
								vendor/github.com/vishvananda/netlink/conntrack_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										371
									
								
								vendor/github.com/vishvananda/netlink/conntrack_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,371 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // 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 ( | ||||
| 	// For Parsing Mark | ||||
| 	TCP_PROTO = 6 | ||||
| 	UDP_PROTO = 17 | ||||
| ) | ||||
| 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, unix.AF_INET, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK) | ||||
| 	_, err := req.Execute(unix.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, unix.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(unix.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, unix.NLM_F_DUMP) | ||||
| 	return req.Execute(unix.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 | ||||
| 	Mark       uint32 | ||||
| } | ||||
|  | ||||
| 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 mark=0 | ||||
| 	return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d\tsrc=%s dst=%s sport=%d dport=%d mark=%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, s.Mark) | ||||
| } | ||||
|  | ||||
| // This method parse the ip tuple structure | ||||
| // The message structure is the following: | ||||
| // <len, [CTA_IP_V4_SRC|CTA_IP_V6_SRC], 16 bytes for the IP> | ||||
| // <len, [CTA_IP_V4_DST|CTA_IP_V6_DST], 16 bytes for the IP> | ||||
| // <len, NLA_F_NESTED|nl.CTA_TUPLE_PROTO, 1 byte for the protocol, 3 bytes of padding> | ||||
| // <len, CTA_PROTO_SRC_PORT, 2 bytes for the source port, 2 bytes of padding> | ||||
| // <len, CTA_PROTO_DST_PORT, 2 bytes for the source port, 2 bytes of padding> | ||||
| func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 { | ||||
| 	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) | ||||
| 	} | ||||
| 	return tpl.Protocol | ||||
| } | ||||
|  | ||||
| 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{} | ||||
| 	var proto uint8 | ||||
| 	// 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: | ||||
| 	// <len, NLA_F_NESTED|CTA_TUPLE_ORIG> 4 bytes | ||||
| 	// <len, NLA_F_NESTED|CTA_TUPLE_IP> 4 bytes | ||||
| 	// flow information of the forward flow | ||||
| 	// <len, NLA_F_NESTED|CTA_TUPLE_REPLY> 4 bytes | ||||
| 	// <len, NLA_F_NESTED|CTA_TUPLE_IP> 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 { | ||||
| 				proto = 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) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	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 | ||||
| } | ||||
|  | ||||
| // 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) | ||||
							
								
								
									
										53
									
								
								vendor/github.com/vishvananda/netlink/conntrack_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								vendor/github.com/vishvananda/netlink/conntrack_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										288
									
								
								vendor/github.com/vishvananda/netlink/filter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								vendor/github.com/vishvananda/netlink/filter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,288 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| ) | ||||
|  | ||||
| type Filter interface { | ||||
| 	Attrs() *FilterAttrs | ||||
| 	Type() string | ||||
| } | ||||
|  | ||||
| // FilterAttrs represents a netlink filter. A filter is associated with a link, | ||||
| // has a handle and a parent. The root filter of a device should have a | ||||
| // parent == HANDLE_ROOT. | ||||
| type FilterAttrs struct { | ||||
| 	LinkIndex int | ||||
| 	Handle    uint32 | ||||
| 	Parent    uint32 | ||||
| 	Priority  uint16 // lower is higher priority | ||||
| 	Protocol  uint16 // unix.ETH_P_* | ||||
| } | ||||
|  | ||||
| func (q FilterAttrs) String() string { | ||||
| 	return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Priority: %d, Protocol: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Priority, q.Protocol) | ||||
| } | ||||
|  | ||||
| type TcAct int32 | ||||
|  | ||||
| const ( | ||||
| 	TC_ACT_UNSPEC     TcAct = -1 | ||||
| 	TC_ACT_OK         TcAct = 0 | ||||
| 	TC_ACT_RECLASSIFY TcAct = 1 | ||||
| 	TC_ACT_SHOT       TcAct = 2 | ||||
| 	TC_ACT_PIPE       TcAct = 3 | ||||
| 	TC_ACT_STOLEN     TcAct = 4 | ||||
| 	TC_ACT_QUEUED     TcAct = 5 | ||||
| 	TC_ACT_REPEAT     TcAct = 6 | ||||
| 	TC_ACT_REDIRECT   TcAct = 7 | ||||
| 	TC_ACT_JUMP       TcAct = 0x10000000 | ||||
| ) | ||||
|  | ||||
| func (a TcAct) String() string { | ||||
| 	switch a { | ||||
| 	case TC_ACT_UNSPEC: | ||||
| 		return "unspec" | ||||
| 	case TC_ACT_OK: | ||||
| 		return "ok" | ||||
| 	case TC_ACT_RECLASSIFY: | ||||
| 		return "reclassify" | ||||
| 	case TC_ACT_SHOT: | ||||
| 		return "shot" | ||||
| 	case TC_ACT_PIPE: | ||||
| 		return "pipe" | ||||
| 	case TC_ACT_STOLEN: | ||||
| 		return "stolen" | ||||
| 	case TC_ACT_QUEUED: | ||||
| 		return "queued" | ||||
| 	case TC_ACT_REPEAT: | ||||
| 		return "repeat" | ||||
| 	case TC_ACT_REDIRECT: | ||||
| 		return "redirect" | ||||
| 	case TC_ACT_JUMP: | ||||
| 		return "jump" | ||||
| 	} | ||||
| 	return fmt.Sprintf("0x%x", int32(a)) | ||||
| } | ||||
|  | ||||
| type TcPolAct int32 | ||||
|  | ||||
| const ( | ||||
| 	TC_POLICE_UNSPEC     TcPolAct = TcPolAct(TC_ACT_UNSPEC) | ||||
| 	TC_POLICE_OK         TcPolAct = TcPolAct(TC_ACT_OK) | ||||
| 	TC_POLICE_RECLASSIFY TcPolAct = TcPolAct(TC_ACT_RECLASSIFY) | ||||
| 	TC_POLICE_SHOT       TcPolAct = TcPolAct(TC_ACT_SHOT) | ||||
| 	TC_POLICE_PIPE       TcPolAct = TcPolAct(TC_ACT_PIPE) | ||||
| ) | ||||
|  | ||||
| func (a TcPolAct) String() string { | ||||
| 	switch a { | ||||
| 	case TC_POLICE_UNSPEC: | ||||
| 		return "unspec" | ||||
| 	case TC_POLICE_OK: | ||||
| 		return "ok" | ||||
| 	case TC_POLICE_RECLASSIFY: | ||||
| 		return "reclassify" | ||||
| 	case TC_POLICE_SHOT: | ||||
| 		return "shot" | ||||
| 	case TC_POLICE_PIPE: | ||||
| 		return "pipe" | ||||
| 	} | ||||
| 	return fmt.Sprintf("0x%x", int32(a)) | ||||
| } | ||||
|  | ||||
| type ActionAttrs struct { | ||||
| 	Index   int | ||||
| 	Capab   int | ||||
| 	Action  TcAct | ||||
| 	Refcnt  int | ||||
| 	Bindcnt int | ||||
| } | ||||
|  | ||||
| func (q ActionAttrs) String() string { | ||||
| 	return fmt.Sprintf("{Index: %d, Capab: %x, Action: %s, Refcnt: %d, Bindcnt: %d}", q.Index, q.Capab, q.Action.String(), q.Refcnt, q.Bindcnt) | ||||
| } | ||||
|  | ||||
| // Action represents an action in any supported filter. | ||||
| type Action interface { | ||||
| 	Attrs() *ActionAttrs | ||||
| 	Type() string | ||||
| } | ||||
|  | ||||
| type GenericAction struct { | ||||
| 	ActionAttrs | ||||
| } | ||||
|  | ||||
| func (action *GenericAction) Type() string { | ||||
| 	return "generic" | ||||
| } | ||||
|  | ||||
| func (action *GenericAction) Attrs() *ActionAttrs { | ||||
| 	return &action.ActionAttrs | ||||
| } | ||||
|  | ||||
| type BpfAction struct { | ||||
| 	ActionAttrs | ||||
| 	Fd   int | ||||
| 	Name string | ||||
| } | ||||
|  | ||||
| func (action *BpfAction) Type() string { | ||||
| 	return "bpf" | ||||
| } | ||||
|  | ||||
| func (action *BpfAction) Attrs() *ActionAttrs { | ||||
| 	return &action.ActionAttrs | ||||
| } | ||||
|  | ||||
| type MirredAct uint8 | ||||
|  | ||||
| func (a MirredAct) String() string { | ||||
| 	switch a { | ||||
| 	case TCA_EGRESS_REDIR: | ||||
| 		return "egress redir" | ||||
| 	case TCA_EGRESS_MIRROR: | ||||
| 		return "egress mirror" | ||||
| 	case TCA_INGRESS_REDIR: | ||||
| 		return "ingress redir" | ||||
| 	case TCA_INGRESS_MIRROR: | ||||
| 		return "ingress mirror" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	TCA_EGRESS_REDIR   MirredAct = 1 /* packet redirect to EGRESS*/ | ||||
| 	TCA_EGRESS_MIRROR  MirredAct = 2 /* mirror packet to EGRESS */ | ||||
| 	TCA_INGRESS_REDIR  MirredAct = 3 /* packet redirect to INGRESS*/ | ||||
| 	TCA_INGRESS_MIRROR MirredAct = 4 /* mirror packet to INGRESS */ | ||||
| ) | ||||
|  | ||||
| type MirredAction struct { | ||||
| 	ActionAttrs | ||||
| 	MirredAction MirredAct | ||||
| 	Ifindex      int | ||||
| } | ||||
|  | ||||
| func (action *MirredAction) Type() string { | ||||
| 	return "mirred" | ||||
| } | ||||
|  | ||||
| func (action *MirredAction) Attrs() *ActionAttrs { | ||||
| 	return &action.ActionAttrs | ||||
| } | ||||
|  | ||||
| func NewMirredAction(redirIndex int) *MirredAction { | ||||
| 	return &MirredAction{ | ||||
| 		ActionAttrs: ActionAttrs{ | ||||
| 			Action: TC_ACT_STOLEN, | ||||
| 		}, | ||||
| 		MirredAction: TCA_EGRESS_REDIR, | ||||
| 		Ifindex:      redirIndex, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // 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 | ||||
| } | ||||
|  | ||||
| func (filter *U32) Attrs() *FilterAttrs { | ||||
| 	return &filter.FilterAttrs | ||||
| } | ||||
|  | ||||
| func (filter *U32) Type() string { | ||||
| 	return "u32" | ||||
| } | ||||
|  | ||||
| // MatchAll filters match all packets | ||||
| type MatchAll struct { | ||||
| 	FilterAttrs | ||||
| 	ClassId uint32 | ||||
| 	Actions []Action | ||||
| } | ||||
|  | ||||
| func (filter *MatchAll) Attrs() *FilterAttrs { | ||||
| 	return &filter.FilterAttrs | ||||
| } | ||||
|  | ||||
| func (filter *MatchAll) Type() string { | ||||
| 	return "matchall" | ||||
| } | ||||
|  | ||||
| type FilterFwAttrs struct { | ||||
| 	ClassId   uint32 | ||||
| 	InDev     string | ||||
| 	Mask      uint32 | ||||
| 	Index     uint32 | ||||
| 	Buffer    uint32 | ||||
| 	Mtu       uint32 | ||||
| 	Mpu       uint16 | ||||
| 	Rate      uint32 | ||||
| 	AvRate    uint32 | ||||
| 	PeakRate  uint32 | ||||
| 	Action    TcPolAct | ||||
| 	Overhead  uint16 | ||||
| 	LinkLayer int | ||||
| } | ||||
|  | ||||
| type BpfFilter struct { | ||||
| 	FilterAttrs | ||||
| 	ClassId      uint32 | ||||
| 	Fd           int | ||||
| 	Name         string | ||||
| 	DirectAction bool | ||||
| } | ||||
|  | ||||
| func (filter *BpfFilter) Type() string { | ||||
| 	return "bpf" | ||||
| } | ||||
|  | ||||
| func (filter *BpfFilter) Attrs() *FilterAttrs { | ||||
| 	return &filter.FilterAttrs | ||||
| } | ||||
|  | ||||
| // GenericFilter filters represent types that are not currently understood | ||||
| // by this netlink library. | ||||
| type GenericFilter struct { | ||||
| 	FilterAttrs | ||||
| 	FilterType string | ||||
| } | ||||
|  | ||||
| func (filter *GenericFilter) Attrs() *FilterAttrs { | ||||
| 	return &filter.FilterAttrs | ||||
| } | ||||
|  | ||||
| func (filter *GenericFilter) Type() string { | ||||
| 	return filter.FilterType | ||||
| } | ||||
							
								
								
									
										639
									
								
								vendor/github.com/vishvananda/netlink/filter_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										639
									
								
								vendor/github.com/vishvananda/netlink/filter_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,639 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // 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 | ||||
| ) | ||||
|  | ||||
| // Fw filter filters on firewall marks | ||||
| // NOTE: this is in filter_linux because it refers to nl.TcPolice which | ||||
| //       is defined in nl/tc_linux.go | ||||
| type Fw struct { | ||||
| 	FilterAttrs | ||||
| 	ClassId uint32 | ||||
| 	// TODO remove nl type from interface | ||||
| 	Police nl.TcPolice | ||||
| 	InDev  string | ||||
| 	// TODO Action | ||||
| 	Mask   uint32 | ||||
| 	AvRate uint32 | ||||
| 	Rtab   [256]uint32 | ||||
| 	Ptab   [256]uint32 | ||||
| } | ||||
|  | ||||
| func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) { | ||||
| 	var rtab [256]uint32 | ||||
| 	var ptab [256]uint32 | ||||
| 	rcellLog := -1 | ||||
| 	pcellLog := -1 | ||||
| 	avrate := fattrs.AvRate / 8 | ||||
| 	police := nl.TcPolice{} | ||||
| 	police.Rate.Rate = fattrs.Rate / 8 | ||||
| 	police.PeakRate.Rate = fattrs.PeakRate / 8 | ||||
| 	buffer := fattrs.Buffer | ||||
| 	linklayer := nl.LINKLAYER_ETHERNET | ||||
|  | ||||
| 	if fattrs.LinkLayer != nl.LINKLAYER_UNSPEC { | ||||
| 		linklayer = fattrs.LinkLayer | ||||
| 	} | ||||
|  | ||||
| 	police.Action = int32(fattrs.Action) | ||||
| 	if police.Rate.Rate != 0 { | ||||
| 		police.Rate.Mpu = fattrs.Mpu | ||||
| 		police.Rate.Overhead = fattrs.Overhead | ||||
| 		if CalcRtable(&police.Rate, rtab[:], rcellLog, fattrs.Mtu, linklayer) < 0 { | ||||
| 			return nil, errors.New("TBF: failed to calculate rate table") | ||||
| 		} | ||||
| 		police.Burst = uint32(Xmittime(uint64(police.Rate.Rate), uint32(buffer))) | ||||
| 	} | ||||
| 	police.Mtu = fattrs.Mtu | ||||
| 	if police.PeakRate.Rate != 0 { | ||||
| 		police.PeakRate.Mpu = fattrs.Mpu | ||||
| 		police.PeakRate.Overhead = fattrs.Overhead | ||||
| 		if CalcRtable(&police.PeakRate, ptab[:], pcellLog, fattrs.Mtu, linklayer) < 0 { | ||||
| 			return nil, errors.New("POLICE: failed to calculate peak rate table") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return &Fw{ | ||||
| 		FilterAttrs: attrs, | ||||
| 		ClassId:     fattrs.ClassId, | ||||
| 		InDev:       fattrs.InDev, | ||||
| 		Mask:        fattrs.Mask, | ||||
| 		Police:      police, | ||||
| 		AvRate:      avrate, | ||||
| 		Rtab:        rtab, | ||||
| 		Ptab:        ptab, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func (filter *Fw) Attrs() *FilterAttrs { | ||||
| 	return &filter.FilterAttrs | ||||
| } | ||||
|  | ||||
| func (filter *Fw) Type() string { | ||||
| 	return "fw" | ||||
| } | ||||
|  | ||||
| // FilterDel will delete a filter from the system. | ||||
| // Equivalent to: `tc filter del $filter` | ||||
| func FilterDel(filter Filter) error { | ||||
| 	return pkgHandle.FilterDel(filter) | ||||
| } | ||||
|  | ||||
| // FilterDel will delete a filter from the system. | ||||
| // Equivalent to: `tc filter del $filter` | ||||
| func (h *Handle) FilterDel(filter Filter) error { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_DELTFILTER, unix.NLM_F_ACK) | ||||
| 	base := filter.Attrs() | ||||
| 	msg := &nl.TcMsg{ | ||||
| 		Family:  nl.FAMILY_ALL, | ||||
| 		Ifindex: int32(base.LinkIndex), | ||||
| 		Handle:  base.Handle, | ||||
| 		Parent:  base.Parent, | ||||
| 		Info:    MakeHandle(base.Priority, nl.Swap16(base.Protocol)), | ||||
| 	} | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	_, err := req.Execute(unix.NETLINK_ROUTE, 0) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // FilterAdd will add a filter to the system. | ||||
| // Equivalent to: `tc filter add $filter` | ||||
| func FilterAdd(filter Filter) error { | ||||
| 	return pkgHandle.FilterAdd(filter) | ||||
| } | ||||
|  | ||||
| // FilterAdd will add a filter to the system. | ||||
| // Equivalent to: `tc filter add $filter` | ||||
| func (h *Handle) FilterAdd(filter Filter) error { | ||||
| 	native = nl.NativeEndian() | ||||
| 	req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) | ||||
| 	base := filter.Attrs() | ||||
| 	msg := &nl.TcMsg{ | ||||
| 		Family:  nl.FAMILY_ALL, | ||||
| 		Ifindex: int32(base.LinkIndex), | ||||
| 		Handle:  base.Handle, | ||||
| 		Parent:  base.Parent, | ||||
| 		Info:    MakeHandle(base.Priority, nl.Swap16(base.Protocol)), | ||||
| 	} | ||||
| 	req.AddData(msg) | ||||
| 	req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type()))) | ||||
|  | ||||
| 	options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) | ||||
|  | ||||
| 	switch filter := filter.(type) { | ||||
| 	case *U32: | ||||
| 		// Convert TcU32Sel into nl.TcU32Sel as it is without copy. | ||||
| 		sel := (*nl.TcU32Sel)(unsafe.Pointer(filter.Sel)) | ||||
| 		if sel == nil { | ||||
| 			// match all | ||||
| 			sel = &nl.TcU32Sel{ | ||||
| 				Nkeys: 1, | ||||
| 				Flags: nl.TC_U32_TERMINAL, | ||||
| 			} | ||||
| 			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 filter.ClassId != 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_U32_CLASSID, nl.Uint32Attr(filter.ClassId)) | ||||
| 		} | ||||
| 		actionsAttr := nl.NewRtAttrChild(options, nl.TCA_U32_ACT, nil) | ||||
| 		// backwards compatibility | ||||
| 		if filter.RedirIndex != 0 { | ||||
| 			filter.Actions = append([]Action{NewMirredAction(filter.RedirIndex)}, filter.Actions...) | ||||
| 		} | ||||
| 		if err := EncodeActions(actionsAttr, filter.Actions); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	case *Fw: | ||||
| 		if filter.Mask != 0 { | ||||
| 			b := make([]byte, 4) | ||||
| 			native.PutUint32(b, filter.Mask) | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FW_MASK, b) | ||||
| 		} | ||||
| 		if filter.InDev != "" { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev)) | ||||
| 		} | ||||
| 		if (filter.Police != nl.TcPolice{}) { | ||||
|  | ||||
| 			police := nl.NewRtAttrChild(options, nl.TCA_FW_POLICE, nil) | ||||
| 			nl.NewRtAttrChild(police, nl.TCA_POLICE_TBF, filter.Police.Serialize()) | ||||
| 			if (filter.Police.Rate != nl.TcRateSpec{}) { | ||||
| 				payload := SerializeRtab(filter.Rtab) | ||||
| 				nl.NewRtAttrChild(police, nl.TCA_POLICE_RATE, payload) | ||||
| 			} | ||||
| 			if (filter.Police.PeakRate != nl.TcRateSpec{}) { | ||||
| 				payload := SerializeRtab(filter.Ptab) | ||||
| 				nl.NewRtAttrChild(police, nl.TCA_POLICE_PEAKRATE, payload) | ||||
| 			} | ||||
| 		} | ||||
| 		if filter.ClassId != 0 { | ||||
| 			b := make([]byte, 4) | ||||
| 			native.PutUint32(b, filter.ClassId) | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FW_CLASSID, b) | ||||
| 		} | ||||
| 	case *BpfFilter: | ||||
| 		var bpfFlags uint32 | ||||
| 		if filter.ClassId != 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_BPF_CLASSID, nl.Uint32Attr(filter.ClassId)) | ||||
| 		} | ||||
| 		if filter.Fd >= 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_BPF_FD, nl.Uint32Attr((uint32(filter.Fd)))) | ||||
| 		} | ||||
| 		if filter.Name != "" { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_BPF_NAME, nl.ZeroTerminated(filter.Name)) | ||||
| 		} | ||||
| 		if filter.DirectAction { | ||||
| 			bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT | ||||
| 		} | ||||
| 		nl.NewRtAttrChild(options, nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags)) | ||||
| 	case *MatchAll: | ||||
| 		actionsAttr := nl.NewRtAttrChild(options, nl.TCA_MATCHALL_ACT, nil) | ||||
| 		if err := EncodeActions(actionsAttr, filter.Actions); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if filter.ClassId != 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId)) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	req.AddData(options) | ||||
| 	_, err := req.Execute(unix.NETLINK_ROUTE, 0) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // FilterList gets a list of filters in the system. | ||||
| // Equivalent to: `tc filter show`. | ||||
| // Generally returns nothing if link and parent are not specified. | ||||
| func FilterList(link Link, parent uint32) ([]Filter, error) { | ||||
| 	return pkgHandle.FilterList(link, parent) | ||||
| } | ||||
|  | ||||
| // FilterList gets a list of filters in the system. | ||||
| // Equivalent to: `tc filter show`. | ||||
| // Generally returns nothing if link and parent are not specified. | ||||
| func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_GETTFILTER, unix.NLM_F_DUMP) | ||||
| 	msg := &nl.TcMsg{ | ||||
| 		Family: nl.FAMILY_ALL, | ||||
| 		Parent: parent, | ||||
| 	} | ||||
| 	if link != nil { | ||||
| 		base := link.Attrs() | ||||
| 		h.ensureIndex(base) | ||||
| 		msg.Ifindex = int32(base.Index) | ||||
| 	} | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTFILTER) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	var res []Filter | ||||
| 	for _, m := range msgs { | ||||
| 		msg := nl.DeserializeTcMsg(m) | ||||
|  | ||||
| 		attrs, err := nl.ParseRouteAttr(m[msg.Len():]) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		base := FilterAttrs{ | ||||
| 			LinkIndex: int(msg.Ifindex), | ||||
| 			Handle:    msg.Handle, | ||||
| 			Parent:    msg.Parent, | ||||
| 		} | ||||
| 		base.Priority, base.Protocol = MajorMinor(msg.Info) | ||||
| 		base.Protocol = nl.Swap16(base.Protocol) | ||||
|  | ||||
| 		var filter Filter | ||||
| 		filterType := "" | ||||
| 		detailed := false | ||||
| 		for _, attr := range attrs { | ||||
| 			switch attr.Attr.Type { | ||||
| 			case nl.TCA_KIND: | ||||
| 				filterType = string(attr.Value[:len(attr.Value)-1]) | ||||
| 				switch filterType { | ||||
| 				case "u32": | ||||
| 					filter = &U32{} | ||||
| 				case "fw": | ||||
| 					filter = &Fw{} | ||||
| 				case "bpf": | ||||
| 					filter = &BpfFilter{} | ||||
| 				case "matchall": | ||||
| 					filter = &MatchAll{} | ||||
| 				default: | ||||
| 					filter = &GenericFilter{FilterType: filterType} | ||||
| 				} | ||||
| 			case nl.TCA_OPTIONS: | ||||
| 				data, err := nl.ParseRouteAttr(attr.Value) | ||||
| 				if err != nil { | ||||
| 					return nil, err | ||||
| 				} | ||||
| 				switch filterType { | ||||
| 				case "u32": | ||||
| 					detailed, err = parseU32Data(filter, data) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 				case "fw": | ||||
| 					detailed, err = parseFwData(filter, data) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 				case "bpf": | ||||
| 					detailed, err = parseBpfData(filter, data) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 				case "matchall": | ||||
| 					detailed, err = parseMatchAllData(filter, data) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 				default: | ||||
| 					detailed = true | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		// only return the detailed version of the filter | ||||
| 		if detailed { | ||||
| 			*filter.Attrs() = base | ||||
| 			res = append(res, filter) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return res, nil | ||||
| } | ||||
|  | ||||
| func toTcGen(attrs *ActionAttrs, tcgen *nl.TcGen) { | ||||
| 	tcgen.Index = uint32(attrs.Index) | ||||
| 	tcgen.Capab = uint32(attrs.Capab) | ||||
| 	tcgen.Action = int32(attrs.Action) | ||||
| 	tcgen.Refcnt = int32(attrs.Refcnt) | ||||
| 	tcgen.Bindcnt = int32(attrs.Bindcnt) | ||||
| } | ||||
|  | ||||
| func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) { | ||||
| 	attrs.Index = int(tcgen.Index) | ||||
| 	attrs.Capab = int(tcgen.Capab) | ||||
| 	attrs.Action = TcAct(tcgen.Action) | ||||
| 	attrs.Refcnt = int(tcgen.Refcnt) | ||||
| 	attrs.Bindcnt = int(tcgen.Bindcnt) | ||||
| } | ||||
|  | ||||
| func EncodeActions(attr *nl.RtAttr, actions []Action) error { | ||||
| 	tabIndex := int(nl.TCA_ACT_TAB) | ||||
|  | ||||
| 	for _, action := range actions { | ||||
| 		switch action := action.(type) { | ||||
| 		default: | ||||
| 			return fmt.Errorf("unknown action type %s", action.Type()) | ||||
| 		case *MirredAction: | ||||
| 			table := nl.NewRtAttrChild(attr, tabIndex, nil) | ||||
| 			tabIndex++ | ||||
| 			nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred")) | ||||
| 			aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil) | ||||
| 			mirred := nl.TcMirred{ | ||||
| 				Eaction: int32(action.MirredAction), | ||||
| 				Ifindex: uint32(action.Ifindex), | ||||
| 			} | ||||
| 			toTcGen(action.Attrs(), &mirred.TcGen) | ||||
| 			nl.NewRtAttrChild(aopts, nl.TCA_MIRRED_PARMS, mirred.Serialize()) | ||||
| 		case *BpfAction: | ||||
| 			table := nl.NewRtAttrChild(attr, tabIndex, nil) | ||||
| 			tabIndex++ | ||||
| 			nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf")) | ||||
| 			aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil) | ||||
| 			gen := nl.TcGen{} | ||||
| 			toTcGen(action.Attrs(), &gen) | ||||
| 			nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_PARMS, gen.Serialize()) | ||||
| 			nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd))) | ||||
| 			nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name)) | ||||
| 		case *GenericAction: | ||||
| 			table := nl.NewRtAttrChild(attr, tabIndex, nil) | ||||
| 			tabIndex++ | ||||
| 			nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("gact")) | ||||
| 			aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil) | ||||
| 			gen := nl.TcGen{} | ||||
| 			toTcGen(action.Attrs(), &gen) | ||||
| 			nl.NewRtAttrChild(aopts, nl.TCA_GACT_PARMS, gen.Serialize()) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { | ||||
| 	var actions []Action | ||||
| 	for _, table := range tables { | ||||
| 		var action Action | ||||
| 		var actionType string | ||||
| 		aattrs, err := nl.ParseRouteAttr(table.Value) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	nextattr: | ||||
| 		for _, aattr := range aattrs { | ||||
| 			switch aattr.Attr.Type { | ||||
| 			case nl.TCA_KIND: | ||||
| 				actionType = string(aattr.Value[:len(aattr.Value)-1]) | ||||
| 				// only parse if the action is mirred or bpf | ||||
| 				switch actionType { | ||||
| 				case "mirred": | ||||
| 					action = &MirredAction{} | ||||
| 				case "bpf": | ||||
| 					action = &BpfAction{} | ||||
| 				case "gact": | ||||
| 					action = &GenericAction{} | ||||
| 				default: | ||||
| 					break nextattr | ||||
| 				} | ||||
| 			case nl.TCA_OPTIONS: | ||||
| 				adata, err := nl.ParseRouteAttr(aattr.Value) | ||||
| 				if err != nil { | ||||
| 					return nil, err | ||||
| 				} | ||||
| 				for _, adatum := range adata { | ||||
| 					switch actionType { | ||||
| 					case "mirred": | ||||
| 						switch adatum.Attr.Type { | ||||
| 						case nl.TCA_MIRRED_PARMS: | ||||
| 							mirred := *nl.DeserializeTcMirred(adatum.Value) | ||||
| 							toAttrs(&mirred.TcGen, action.Attrs()) | ||||
| 							action.(*MirredAction).ActionAttrs = ActionAttrs{} | ||||
| 							action.(*MirredAction).Ifindex = int(mirred.Ifindex) | ||||
| 							action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction) | ||||
| 						} | ||||
| 					case "bpf": | ||||
| 						switch adatum.Attr.Type { | ||||
| 						case nl.TCA_ACT_BPF_PARMS: | ||||
| 							gen := *nl.DeserializeTcGen(adatum.Value) | ||||
| 							toAttrs(&gen, action.Attrs()) | ||||
| 						case nl.TCA_ACT_BPF_FD: | ||||
| 							action.(*BpfAction).Fd = int(native.Uint32(adatum.Value[0:4])) | ||||
| 						case nl.TCA_ACT_BPF_NAME: | ||||
| 							action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1]) | ||||
| 						} | ||||
| 					case "gact": | ||||
| 						switch adatum.Attr.Type { | ||||
| 						case nl.TCA_GACT_PARMS: | ||||
| 							gen := *nl.DeserializeTcGen(adatum.Value) | ||||
| 							toAttrs(&gen, action.Attrs()) | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		actions = append(actions, action) | ||||
| 	} | ||||
| 	return actions, nil | ||||
| } | ||||
|  | ||||
| func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { | ||||
| 	native = nl.NativeEndian() | ||||
| 	u32 := filter.(*U32) | ||||
| 	detailed := false | ||||
| 	for _, datum := range data { | ||||
| 		switch datum.Attr.Type { | ||||
| 		case nl.TCA_U32_SEL: | ||||
| 			detailed = true | ||||
| 			sel := nl.DeserializeTcU32Sel(datum.Value) | ||||
| 			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) | ||||
| 			if err != nil { | ||||
| 				return detailed, err | ||||
| 			} | ||||
| 			u32.Actions, err = parseActions(tables) | ||||
| 			if err != nil { | ||||
| 				return detailed, err | ||||
| 			} | ||||
| 			for _, action := range u32.Actions { | ||||
| 				if action, ok := action.(*MirredAction); ok { | ||||
| 					u32.RedirIndex = int(action.Ifindex) | ||||
| 				} | ||||
| 			} | ||||
| 		case nl.TCA_U32_CLASSID: | ||||
| 			u32.ClassId = native.Uint32(datum.Value) | ||||
| 		} | ||||
| 	} | ||||
| 	return detailed, nil | ||||
| } | ||||
|  | ||||
| func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { | ||||
| 	native = nl.NativeEndian() | ||||
| 	fw := filter.(*Fw) | ||||
| 	detailed := true | ||||
| 	for _, datum := range data { | ||||
| 		switch datum.Attr.Type { | ||||
| 		case nl.TCA_FW_MASK: | ||||
| 			fw.Mask = native.Uint32(datum.Value[0:4]) | ||||
| 		case nl.TCA_FW_CLASSID: | ||||
| 			fw.ClassId = native.Uint32(datum.Value[0:4]) | ||||
| 		case nl.TCA_FW_INDEV: | ||||
| 			fw.InDev = string(datum.Value[:len(datum.Value)-1]) | ||||
| 		case nl.TCA_FW_POLICE: | ||||
| 			adata, _ := nl.ParseRouteAttr(datum.Value) | ||||
| 			for _, aattr := range adata { | ||||
| 				switch aattr.Attr.Type { | ||||
| 				case nl.TCA_POLICE_TBF: | ||||
| 					fw.Police = *nl.DeserializeTcPolice(aattr.Value) | ||||
| 				case nl.TCA_POLICE_RATE: | ||||
| 					fw.Rtab = DeserializeRtab(aattr.Value) | ||||
| 				case nl.TCA_POLICE_PEAKRATE: | ||||
| 					fw.Ptab = DeserializeRtab(aattr.Value) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return detailed, nil | ||||
| } | ||||
|  | ||||
| func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { | ||||
| 	native = nl.NativeEndian() | ||||
| 	bpf := filter.(*BpfFilter) | ||||
| 	detailed := true | ||||
| 	for _, datum := range data { | ||||
| 		switch datum.Attr.Type { | ||||
| 		case nl.TCA_BPF_FD: | ||||
| 			bpf.Fd = int(native.Uint32(datum.Value[0:4])) | ||||
| 		case nl.TCA_BPF_NAME: | ||||
| 			bpf.Name = string(datum.Value[:len(datum.Value)-1]) | ||||
| 		case nl.TCA_BPF_CLASSID: | ||||
| 			bpf.ClassId = native.Uint32(datum.Value[0:4]) | ||||
| 		case nl.TCA_BPF_FLAGS: | ||||
| 			flags := native.Uint32(datum.Value[0:4]) | ||||
| 			if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 { | ||||
| 				bpf.DirectAction = true | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return detailed, nil | ||||
| } | ||||
|  | ||||
| func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { | ||||
| 	native = nl.NativeEndian() | ||||
| 	matchall := filter.(*MatchAll) | ||||
| 	detailed := true | ||||
| 	for _, datum := range data { | ||||
| 		switch datum.Attr.Type { | ||||
| 		case nl.TCA_MATCHALL_CLASSID: | ||||
| 			matchall.ClassId = native.Uint32(datum.Value[0:4]) | ||||
| 		case nl.TCA_MATCHALL_ACT: | ||||
| 			tables, err := nl.ParseRouteAttr(datum.Value) | ||||
| 			if err != nil { | ||||
| 				return detailed, err | ||||
| 			} | ||||
| 			matchall.Actions, err = parseActions(tables) | ||||
| 			if err != nil { | ||||
| 				return detailed, err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return detailed, nil | ||||
| } | ||||
|  | ||||
| func AlignToAtm(size uint) uint { | ||||
| 	var linksize, cells int | ||||
| 	cells = int(size / nl.ATM_CELL_PAYLOAD) | ||||
| 	if (size % nl.ATM_CELL_PAYLOAD) > 0 { | ||||
| 		cells++ | ||||
| 	} | ||||
| 	linksize = cells * nl.ATM_CELL_SIZE | ||||
| 	return uint(linksize) | ||||
| } | ||||
|  | ||||
| func AdjustSize(sz uint, mpu uint, linklayer int) uint { | ||||
| 	if sz < mpu { | ||||
| 		sz = mpu | ||||
| 	} | ||||
| 	switch linklayer { | ||||
| 	case nl.LINKLAYER_ATM: | ||||
| 		return AlignToAtm(sz) | ||||
| 	default: | ||||
| 		return sz | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, linklayer int) int { | ||||
| 	bps := rate.Rate | ||||
| 	mpu := rate.Mpu | ||||
| 	var sz uint | ||||
| 	if mtu == 0 { | ||||
| 		mtu = 2047 | ||||
| 	} | ||||
| 	if cellLog < 0 { | ||||
| 		cellLog = 0 | ||||
| 		for (mtu >> uint(cellLog)) > 255 { | ||||
| 			cellLog++ | ||||
| 		} | ||||
| 	} | ||||
| 	for i := 0; i < 256; i++ { | ||||
| 		sz = AdjustSize(uint((i+1)<<uint32(cellLog)), uint(mpu), linklayer) | ||||
| 		rtab[i] = uint32(Xmittime(uint64(bps), uint32(sz))) | ||||
| 	} | ||||
| 	rate.CellAlign = -1 | ||||
| 	rate.CellLog = uint8(cellLog) | ||||
| 	rate.Linklayer = uint8(linklayer & nl.TC_LINKLAYER_MASK) | ||||
| 	return cellLog | ||||
| } | ||||
|  | ||||
| func DeserializeRtab(b []byte) [256]uint32 { | ||||
| 	var rtab [256]uint32 | ||||
| 	native := nl.NativeEndian() | ||||
| 	r := bytes.NewReader(b) | ||||
| 	_ = binary.Read(r, native, &rtab) | ||||
| 	return rtab | ||||
| } | ||||
|  | ||||
| func SerializeRtab(rtab [256]uint32) []byte { | ||||
| 	native := nl.NativeEndian() | ||||
| 	var w bytes.Buffer | ||||
| 	_ = binary.Write(&w, native, rtab) | ||||
| 	return w.Bytes() | ||||
| } | ||||
							
								
								
									
										21
									
								
								vendor/github.com/vishvananda/netlink/fou.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/vishvananda/netlink/fou.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// ErrAttrHeaderTruncated is returned when a netlink attribute's header is | ||||
| 	// truncated. | ||||
| 	ErrAttrHeaderTruncated = errors.New("attribute header truncated") | ||||
| 	// ErrAttrBodyTruncated is returned when a netlink attribute's body is | ||||
| 	// truncated. | ||||
| 	ErrAttrBodyTruncated = errors.New("attribute body truncated") | ||||
| ) | ||||
|  | ||||
| type Fou struct { | ||||
| 	Family    int | ||||
| 	Port      int | ||||
| 	Protocol  int | ||||
| 	EncapType int | ||||
| } | ||||
							
								
								
									
										215
									
								
								vendor/github.com/vishvananda/netlink/fou_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								vendor/github.com/vishvananda/netlink/fou_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,215 @@ | ||||
| // +build linux | ||||
|  | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	FOU_GENL_NAME = "fou" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	FOU_CMD_UNSPEC uint8 = iota | ||||
| 	FOU_CMD_ADD | ||||
| 	FOU_CMD_DEL | ||||
| 	FOU_CMD_GET | ||||
| 	FOU_CMD_MAX = FOU_CMD_GET | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	FOU_ATTR_UNSPEC = iota | ||||
| 	FOU_ATTR_PORT | ||||
| 	FOU_ATTR_AF | ||||
| 	FOU_ATTR_IPPROTO | ||||
| 	FOU_ATTR_TYPE | ||||
| 	FOU_ATTR_REMCSUM_NOPARTIAL | ||||
| 	FOU_ATTR_MAX = FOU_ATTR_REMCSUM_NOPARTIAL | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	FOU_ENCAP_UNSPEC = iota | ||||
| 	FOU_ENCAP_DIRECT | ||||
| 	FOU_ENCAP_GUE | ||||
| 	FOU_ENCAP_MAX = FOU_ENCAP_GUE | ||||
| ) | ||||
|  | ||||
| var fouFamilyId int | ||||
|  | ||||
| func FouFamilyId() (int, error) { | ||||
| 	if fouFamilyId != 0 { | ||||
| 		return fouFamilyId, nil | ||||
| 	} | ||||
|  | ||||
| 	fam, err := GenlFamilyGet(FOU_GENL_NAME) | ||||
| 	if err != nil { | ||||
| 		return -1, err | ||||
| 	} | ||||
|  | ||||
| 	fouFamilyId = int(fam.ID) | ||||
| 	return fouFamilyId, nil | ||||
| } | ||||
|  | ||||
| func FouAdd(f Fou) error { | ||||
| 	return pkgHandle.FouAdd(f) | ||||
| } | ||||
|  | ||||
| func (h *Handle) FouAdd(f Fou) error { | ||||
| 	fam_id, err := FouFamilyId() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// setting ip protocol conflicts with encapsulation type GUE | ||||
| 	if f.EncapType == FOU_ENCAP_GUE && f.Protocol != 0 { | ||||
| 		return errors.New("GUE encapsulation doesn't specify an IP protocol") | ||||
| 	} | ||||
|  | ||||
| 	req := h.newNetlinkRequest(fam_id, unix.NLM_F_ACK) | ||||
|  | ||||
| 	// int to byte for port | ||||
| 	bp := make([]byte, 2) | ||||
| 	binary.BigEndian.PutUint16(bp[0:2], uint16(f.Port)) | ||||
|  | ||||
| 	attrs := []*nl.RtAttr{ | ||||
| 		nl.NewRtAttr(FOU_ATTR_PORT, bp), | ||||
| 		nl.NewRtAttr(FOU_ATTR_TYPE, []byte{uint8(f.EncapType)}), | ||||
| 		nl.NewRtAttr(FOU_ATTR_AF, []byte{uint8(f.Family)}), | ||||
| 		nl.NewRtAttr(FOU_ATTR_IPPROTO, []byte{uint8(f.Protocol)}), | ||||
| 	} | ||||
| 	raw := []byte{FOU_CMD_ADD, 1, 0, 0} | ||||
| 	for _, a := range attrs { | ||||
| 		raw = append(raw, a.Serialize()...) | ||||
| 	} | ||||
|  | ||||
| 	req.AddRawData(raw) | ||||
|  | ||||
| 	_, err = req.Execute(unix.NETLINK_GENERIC, 0) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func FouDel(f Fou) error { | ||||
| 	return pkgHandle.FouDel(f) | ||||
| } | ||||
|  | ||||
| func (h *Handle) FouDel(f Fou) error { | ||||
| 	fam_id, err := FouFamilyId() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	req := h.newNetlinkRequest(fam_id, unix.NLM_F_ACK) | ||||
|  | ||||
| 	// int to byte for port | ||||
| 	bp := make([]byte, 2) | ||||
| 	binary.BigEndian.PutUint16(bp[0:2], uint16(f.Port)) | ||||
|  | ||||
| 	attrs := []*nl.RtAttr{ | ||||
| 		nl.NewRtAttr(FOU_ATTR_PORT, bp), | ||||
| 		nl.NewRtAttr(FOU_ATTR_AF, []byte{uint8(f.Family)}), | ||||
| 	} | ||||
| 	raw := []byte{FOU_CMD_DEL, 1, 0, 0} | ||||
| 	for _, a := range attrs { | ||||
| 		raw = append(raw, a.Serialize()...) | ||||
| 	} | ||||
|  | ||||
| 	req.AddRawData(raw) | ||||
|  | ||||
| 	_, err = req.Execute(unix.NETLINK_GENERIC, 0) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func FouList(fam int) ([]Fou, error) { | ||||
| 	return pkgHandle.FouList(fam) | ||||
| } | ||||
|  | ||||
| func (h *Handle) FouList(fam int) ([]Fou, error) { | ||||
| 	fam_id, err := FouFamilyId() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	req := h.newNetlinkRequest(fam_id, unix.NLM_F_DUMP) | ||||
|  | ||||
| 	attrs := []*nl.RtAttr{ | ||||
| 		nl.NewRtAttr(FOU_ATTR_AF, []byte{uint8(fam)}), | ||||
| 	} | ||||
| 	raw := []byte{FOU_CMD_GET, 1, 0, 0} | ||||
| 	for _, a := range attrs { | ||||
| 		raw = append(raw, a.Serialize()...) | ||||
| 	} | ||||
|  | ||||
| 	req.AddRawData(raw) | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	fous := make([]Fou, 0, len(msgs)) | ||||
| 	for _, m := range msgs { | ||||
| 		f, err := deserializeFouMsg(m) | ||||
| 		if err != nil { | ||||
| 			return fous, err | ||||
| 		} | ||||
|  | ||||
| 		fous = append(fous, f) | ||||
| 	} | ||||
|  | ||||
| 	return fous, nil | ||||
| } | ||||
|  | ||||
| func deserializeFouMsg(msg []byte) (Fou, error) { | ||||
| 	// we'll skip to byte 4 to first attribute | ||||
| 	msg = msg[3:] | ||||
| 	var shift int | ||||
| 	fou := Fou{} | ||||
|  | ||||
| 	for { | ||||
| 		// attribute header is at least 16 bits | ||||
| 		if len(msg) < 4 { | ||||
| 			return fou, ErrAttrHeaderTruncated | ||||
| 		} | ||||
|  | ||||
| 		lgt := int(binary.BigEndian.Uint16(msg[0:2])) | ||||
| 		if len(msg) < lgt+4 { | ||||
| 			return fou, ErrAttrBodyTruncated | ||||
| 		} | ||||
| 		attr := binary.BigEndian.Uint16(msg[2:4]) | ||||
|  | ||||
| 		shift = lgt + 3 | ||||
| 		switch attr { | ||||
| 		case FOU_ATTR_AF: | ||||
| 			fou.Family = int(msg[5]) | ||||
| 		case FOU_ATTR_PORT: | ||||
| 			fou.Port = int(binary.BigEndian.Uint16(msg[5:7])) | ||||
| 			// port is 2 bytes | ||||
| 			shift = lgt + 2 | ||||
| 		case FOU_ATTR_IPPROTO: | ||||
| 			fou.Protocol = int(msg[5]) | ||||
| 		case FOU_ATTR_TYPE: | ||||
| 			fou.EncapType = int(msg[5]) | ||||
| 		} | ||||
|  | ||||
| 		msg = msg[shift:] | ||||
|  | ||||
| 		if len(msg) < 4 { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return fou, nil | ||||
| } | ||||
							
								
								
									
										15
									
								
								vendor/github.com/vishvananda/netlink/fou_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/vishvananda/netlink/fou_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| // +build !linux | ||||
|  | ||||
| package netlink | ||||
|  | ||||
| func FouAdd(f Fou) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func FouDel(f Fou) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func FouList(fam int) ([]Fou, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
							
								
								
									
										168
									
								
								vendor/github.com/vishvananda/netlink/genetlink_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								vendor/github.com/vishvananda/netlink/genetlink_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| 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, unix.NLM_F_DUMP) | ||||
| 	req.AddData(msg) | ||||
| 	msgs, err := req.Execute(unix.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(unix.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) | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/github.com/vishvananda/netlink/genetlink_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/vishvananda/netlink/genetlink_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										239
									
								
								vendor/github.com/vishvananda/netlink/gtp_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								vendor/github.com/vishvananda/netlink/gtp_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,239 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| 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), unix.NLM_F_DUMP) | ||||
| 	req.AddData(msg) | ||||
| 	msgs, err := req.Execute(unix.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(unix.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), unix.NLM_F_EXCL|unix.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(unix.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), unix.NLM_F_EXCL|unix.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(unix.NETLINK_GENERIC, 0) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func GTPPDPDel(link Link, pdp *PDP) error { | ||||
| 	return pkgHandle.GTPPDPDel(link, pdp) | ||||
| } | ||||
							
								
								
									
										144
									
								
								vendor/github.com/vishvananda/netlink/handle_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								vendor/github.com/vishvananda/netlink/handle_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"github.com/vishvananda/netns" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // Empty handle used by the netlink package methods | ||||
| var pkgHandle = &Handle{} | ||||
|  | ||||
| // Handle is an handle for the netlink requests on a | ||||
| // specific network namespace. All the requests on the | ||||
| // same netlink family share the same netlink socket, | ||||
| // which gets released when the handle is deleted. | ||||
| type Handle struct { | ||||
| 	sockets      map[int]*nl.SocketHandle | ||||
| 	lookupByDump bool | ||||
| } | ||||
|  | ||||
| // SupportsNetlinkFamily reports whether the passed netlink family is supported by this Handle | ||||
| func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool { | ||||
| 	_, ok := h.sockets[nlFamily] | ||||
| 	return ok | ||||
| } | ||||
|  | ||||
| // NewHandle returns a netlink handle on the current network namespace. | ||||
| // Caller may specify the netlink families the handle should support. | ||||
| // If no families are specified, all the families the netlink package | ||||
| // supports will be automatically added. | ||||
| func NewHandle(nlFamilies ...int) (*Handle, error) { | ||||
| 	return newHandle(netns.None(), netns.None(), nlFamilies...) | ||||
| } | ||||
|  | ||||
| // SetSocketTimeout sets the send and receive timeout for each socket in the | ||||
| // netlink handle. Although the socket timeout has granularity of one | ||||
| // microsecond, the effective granularity is floored by the kernel timer tick, | ||||
| // which default value is four milliseconds. | ||||
| func (h *Handle) SetSocketTimeout(to time.Duration) error { | ||||
| 	if to < time.Microsecond { | ||||
| 		return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond) | ||||
| 	} | ||||
| 	tv := unix.NsecToTimeval(to.Nanoseconds()) | ||||
| 	for _, sh := range h.sockets { | ||||
| 		if err := sh.Socket.SetSendTimeout(&tv); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := sh.Socket.SetReceiveTimeout(&tv); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // SetSocketReceiveBufferSize sets the receive buffer size for each | ||||
| // socket in the netlink handle. The maximum value is capped by | ||||
| // /proc/sys/net/core/rmem_max. | ||||
| func (h *Handle) SetSocketReceiveBufferSize(size int, force bool) error { | ||||
| 	opt := unix.SO_RCVBUF | ||||
| 	if force { | ||||
| 		opt = unix.SO_RCVBUFFORCE | ||||
| 	} | ||||
| 	for _, sh := range h.sockets { | ||||
| 		fd := sh.Socket.GetFd() | ||||
| 		err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, opt, size) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // GetSocketReceiveBufferSize gets the receiver buffer size for each | ||||
| // socket in the netlink handle. The retrieved value should be the | ||||
| // double to the one set for SetSocketReceiveBufferSize. | ||||
| func (h *Handle) GetSocketReceiveBufferSize() ([]int, error) { | ||||
| 	results := make([]int, len(h.sockets)) | ||||
| 	i := 0 | ||||
| 	for _, sh := range h.sockets { | ||||
| 		fd := sh.Socket.GetFd() | ||||
| 		size, err := unix.GetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_RCVBUF) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		results[i] = size | ||||
| 		i++ | ||||
| 	} | ||||
| 	return results, nil | ||||
| } | ||||
|  | ||||
| // NewHandle returns a netlink handle on the network namespace | ||||
| // specified by ns. If ns=netns.None(), current network namespace | ||||
| // will be assumed | ||||
| func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) { | ||||
| 	return newHandle(ns, netns.None(), nlFamilies...) | ||||
| } | ||||
|  | ||||
| // NewHandleAtFrom works as NewHandle but allows client to specify the | ||||
| // new and the origin netns Handle. | ||||
| func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) { | ||||
| 	return newHandle(newNs, curNs) | ||||
| } | ||||
|  | ||||
| func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error) { | ||||
| 	h := &Handle{sockets: map[int]*nl.SocketHandle{}} | ||||
| 	fams := nl.SupportedNlFamilies | ||||
| 	if len(nlFamilies) != 0 { | ||||
| 		fams = nlFamilies | ||||
| 	} | ||||
| 	for _, f := range fams { | ||||
| 		s, err := nl.GetNetlinkSocketAt(newNs, curNs, f) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		h.sockets[f] = &nl.SocketHandle{Socket: s} | ||||
| 	} | ||||
| 	return h, nil | ||||
| } | ||||
|  | ||||
| // Delete releases the resources allocated to this handle | ||||
| func (h *Handle) Delete() { | ||||
| 	for _, sh := range h.sockets { | ||||
| 		sh.Close() | ||||
| 	} | ||||
| 	h.sockets = nil | ||||
| } | ||||
|  | ||||
| func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest { | ||||
| 	// Do this so that package API still use nl package variable nextSeqNr | ||||
| 	if h.sockets == nil { | ||||
| 		return nl.NewNetlinkRequest(proto, flags) | ||||
| 	} | ||||
| 	return &nl.NetlinkRequest{ | ||||
| 		NlMsghdr: unix.NlMsghdr{ | ||||
| 			Len:   uint32(unix.SizeofNlMsghdr), | ||||
| 			Type:  uint16(proto), | ||||
| 			Flags: unix.NLM_F_REQUEST | uint16(flags), | ||||
| 		}, | ||||
| 		Sockets: h.sockets, | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										258
									
								
								vendor/github.com/vishvananda/netlink/handle_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								vendor/github.com/vishvananda/netlink/handle_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,258 @@ | ||||
| // +build !linux | ||||
|  | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"net" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/vishvananda/netns" | ||||
| ) | ||||
|  | ||||
| type Handle struct{} | ||||
|  | ||||
| func NewHandle(nlFamilies ...int) (*Handle, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) Delete() {} | ||||
|  | ||||
| func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func (h *Handle) SetSocketTimeout(to time.Duration) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) SetPromiscOn(link Link) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) SetPromiscOff(link Link) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetUp(link Link) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetDown(link Link) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetMTU(link Link, mtu int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetName(link Link, name string) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetAlias(link Link, name string) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetMaster(link Link, master *Bridge) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetNoMaster(link Link) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetMasterByIndex(link Link, masterIndex int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetNsPid(link Link, nspid int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetNsFd(link Link, fd int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkAdd(link Link) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkDel(link Link) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkByName(name string) (Link, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkByAlias(alias string) (Link, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkByIndex(index int) (Link, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkList() ([]Link, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetHairpin(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetGuard(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetFastLeave(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetLearning(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetRootBlock(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetFlood(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkSetTxQLen(link Link, qlen int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) AddrAdd(link Link, addr *Addr) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) AddrDel(link Link, addr *Addr) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) AddrList(link Link, family int) ([]Addr, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) ClassDel(class Class) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) ClassChange(class Class) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) ClassReplace(class Class) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) ClassAdd(class Class) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) FilterDel(filter Filter) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) FilterAdd(filter Filter) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) NeighAdd(neigh *Neigh) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) NeighSet(neigh *Neigh) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) NeighAppend(neigh *Neigh) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) NeighDel(neigh *Neigh) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) RouteAdd(route *Route) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) RouteDel(route *Route) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) RouteGet(destination net.IP) ([]Route, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) RouteList(link Link, family int) ([]Route, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) RouteReplace(route *Route) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) RuleAdd(rule *Rule) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) RuleDel(rule *Rule) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (h *Handle) RuleList(family int) ([]Rule, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
							
								
								
									
										98
									
								
								vendor/github.com/vishvananda/netlink/ioctl_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								vendor/github.com/vishvananda/netlink/ioctl_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // ioctl for statistics. | ||||
| const ( | ||||
| 	// ETHTOOL_GSSET_INFO gets string set info | ||||
| 	ETHTOOL_GSSET_INFO = 0x00000037 | ||||
| 	// SIOCETHTOOL is Ethtool interface | ||||
| 	SIOCETHTOOL = 0x8946 | ||||
| 	// ETHTOOL_GSTRINGS gets specified string set | ||||
| 	ETHTOOL_GSTRINGS = 0x0000001b | ||||
| 	// ETHTOOL_GSTATS gets NIC-specific statistics | ||||
| 	ETHTOOL_GSTATS = 0x0000001d | ||||
| ) | ||||
|  | ||||
| // string set id. | ||||
| const ( | ||||
| 	// ETH_SS_TEST is self-test result names, for use with %ETHTOOL_TEST | ||||
| 	ETH_SS_TEST = iota | ||||
| 	// ETH_SS_STATS statistic names, for use with %ETHTOOL_GSTATS | ||||
| 	ETH_SS_STATS | ||||
| 	// ETH_SS_PRIV_FLAGS are driver private flag names | ||||
| 	ETH_SS_PRIV_FLAGS | ||||
| 	// _ETH_SS_NTUPLE_FILTERS is deprecated | ||||
| 	_ETH_SS_NTUPLE_FILTERS | ||||
| 	// ETH_SS_FEATURES are device feature names | ||||
| 	ETH_SS_FEATURES | ||||
| 	// ETH_SS_RSS_HASH_FUNCS is RSS hush function names | ||||
| 	ETH_SS_RSS_HASH_FUNCS | ||||
| ) | ||||
|  | ||||
| // IfreqSlave is a struct for ioctl bond manipulation syscalls. | ||||
| // It is used to assign slave to bond interface with Name. | ||||
| type IfreqSlave struct { | ||||
| 	Name  [unix.IFNAMSIZ]byte | ||||
| 	Slave [unix.IFNAMSIZ]byte | ||||
| } | ||||
|  | ||||
| // Ifreq is a struct for ioctl ethernet manipulation syscalls. | ||||
| type Ifreq struct { | ||||
| 	Name [unix.IFNAMSIZ]byte | ||||
| 	Data uintptr | ||||
| } | ||||
|  | ||||
| // ethtoolSset is a string set information | ||||
| type ethtoolSset struct { | ||||
| 	cmd      uint32 | ||||
| 	reserved uint32 | ||||
| 	mask     uint64 | ||||
| 	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 { | ||||
| 	cmd    uint32 | ||||
| 	nStats uint32 | ||||
| 	data   [1]uint64 | ||||
| } | ||||
|  | ||||
| // newIocltSlaveReq returns filled IfreqSlave with proper interface names | ||||
| // It is used by ioctl to assign slave to bond master | ||||
| func newIocltSlaveReq(slave, master string) *IfreqSlave { | ||||
| 	ifreq := &IfreqSlave{} | ||||
| 	copy(ifreq.Name[:unix.IFNAMSIZ-1], master) | ||||
| 	copy(ifreq.Slave[:unix.IFNAMSIZ-1], slave) | ||||
| 	return ifreq | ||||
| } | ||||
|  | ||||
| // newIocltStringSetReq creates request to get interface string set | ||||
| func newIocltStringSetReq(linkName string) (*Ifreq, *ethtoolSset) { | ||||
| 	e := ðtoolSset{ | ||||
| 		cmd:  ETHTOOL_GSSET_INFO, | ||||
| 		mask: 1 << ETH_SS_STATS, | ||||
| 	} | ||||
|  | ||||
| 	ifreq := &Ifreq{Data: uintptr(unsafe.Pointer(e))} | ||||
| 	copy(ifreq.Name[:unix.IFNAMSIZ-1], linkName) | ||||
| 	return ifreq, e | ||||
| } | ||||
|  | ||||
| // getSocketUDP returns file descriptor to new UDP socket | ||||
| // It is used for communication with ioctl interface. | ||||
| func getSocketUDP() (int, error) { | ||||
| 	return syscall.Socket(unix.AF_INET, unix.SOCK_DGRAM, 0) | ||||
| } | ||||
							
								
								
									
										846
									
								
								vendor/github.com/vishvananda/netlink/link.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										846
									
								
								vendor/github.com/vishvananda/netlink/link.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,846 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| // Link represents a link device from netlink. Shared link attributes | ||||
| // like name may be retrieved using the Attrs() method. Unique data | ||||
| // can be retrieved by casting the object to the proper type. | ||||
| type Link interface { | ||||
| 	Attrs() *LinkAttrs | ||||
| 	Type() string | ||||
| } | ||||
|  | ||||
| type ( | ||||
| 	NsPid int | ||||
| 	NsFd  int | ||||
| ) | ||||
|  | ||||
| // LinkAttrs represents data shared by most link types | ||||
| type LinkAttrs struct { | ||||
| 	Index        int | ||||
| 	MTU          int | ||||
| 	TxQLen       int // Transmit Queue Length | ||||
| 	Name         string | ||||
| 	HardwareAddr net.HardwareAddr | ||||
| 	Flags        net.Flags | ||||
| 	RawFlags     uint32 | ||||
| 	ParentIndex  int         // index of the parent link device | ||||
| 	MasterIndex  int         // must be the index of a bridge | ||||
| 	Namespace    interface{} // nil | NsPid | NsFd | ||||
| 	Alias        string | ||||
| 	Statistics   *LinkStatistics | ||||
| 	Promisc      int | ||||
| 	Xdp          *LinkXdp | ||||
| 	EncapType    string | ||||
| 	Protinfo     *Protinfo | ||||
| 	OperState    LinkOperState | ||||
| 	NetNsID      int | ||||
| 	NumTxQueues  int | ||||
| 	NumRxQueues  int | ||||
| } | ||||
|  | ||||
| // LinkOperState represents the values of the IFLA_OPERSTATE link | ||||
| // attribute, which contains the RFC2863 state of the interface. | ||||
| type LinkOperState uint8 | ||||
|  | ||||
| const ( | ||||
| 	OperUnknown        = iota // Status can't be determined. | ||||
| 	OperNotPresent            // Some component is missing. | ||||
| 	OperDown                  // Down. | ||||
| 	OperLowerLayerDown        // Down due to state of lower layer. | ||||
| 	OperTesting               // In some test mode. | ||||
| 	OperDormant               // Not up but pending an external event. | ||||
| 	OperUp                    // Up, ready to send packets. | ||||
| ) | ||||
|  | ||||
| func (s LinkOperState) String() string { | ||||
| 	switch s { | ||||
| 	case OperNotPresent: | ||||
| 		return "not-present" | ||||
| 	case OperDown: | ||||
| 		return "down" | ||||
| 	case OperLowerLayerDown: | ||||
| 		return "lower-layer-down" | ||||
| 	case OperTesting: | ||||
| 		return "testing" | ||||
| 	case OperDormant: | ||||
| 		return "dormant" | ||||
| 	case OperUp: | ||||
| 		return "up" | ||||
| 	default: | ||||
| 		return "unknown" | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // NewLinkAttrs returns LinkAttrs structure filled with default values | ||||
| func NewLinkAttrs() LinkAttrs { | ||||
| 	return LinkAttrs{ | ||||
| 		TxQLen: -1, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type LinkStatistics LinkStatistics64 | ||||
|  | ||||
| /* | ||||
| Ref: struct rtnl_link_stats {...} | ||||
| */ | ||||
| type LinkStatistics32 struct { | ||||
| 	RxPackets         uint32 | ||||
| 	TxPackets         uint32 | ||||
| 	RxBytes           uint32 | ||||
| 	TxBytes           uint32 | ||||
| 	RxErrors          uint32 | ||||
| 	TxErrors          uint32 | ||||
| 	RxDropped         uint32 | ||||
| 	TxDropped         uint32 | ||||
| 	Multicast         uint32 | ||||
| 	Collisions        uint32 | ||||
| 	RxLengthErrors    uint32 | ||||
| 	RxOverErrors      uint32 | ||||
| 	RxCrcErrors       uint32 | ||||
| 	RxFrameErrors     uint32 | ||||
| 	RxFifoErrors      uint32 | ||||
| 	RxMissedErrors    uint32 | ||||
| 	TxAbortedErrors   uint32 | ||||
| 	TxCarrierErrors   uint32 | ||||
| 	TxFifoErrors      uint32 | ||||
| 	TxHeartbeatErrors uint32 | ||||
| 	TxWindowErrors    uint32 | ||||
| 	RxCompressed      uint32 | ||||
| 	TxCompressed      uint32 | ||||
| } | ||||
|  | ||||
| func (s32 LinkStatistics32) to64() *LinkStatistics64 { | ||||
| 	return &LinkStatistics64{ | ||||
| 		RxPackets:         uint64(s32.RxPackets), | ||||
| 		TxPackets:         uint64(s32.TxPackets), | ||||
| 		RxBytes:           uint64(s32.RxBytes), | ||||
| 		TxBytes:           uint64(s32.TxBytes), | ||||
| 		RxErrors:          uint64(s32.RxErrors), | ||||
| 		TxErrors:          uint64(s32.TxErrors), | ||||
| 		RxDropped:         uint64(s32.RxDropped), | ||||
| 		TxDropped:         uint64(s32.TxDropped), | ||||
| 		Multicast:         uint64(s32.Multicast), | ||||
| 		Collisions:        uint64(s32.Collisions), | ||||
| 		RxLengthErrors:    uint64(s32.RxLengthErrors), | ||||
| 		RxOverErrors:      uint64(s32.RxOverErrors), | ||||
| 		RxCrcErrors:       uint64(s32.RxCrcErrors), | ||||
| 		RxFrameErrors:     uint64(s32.RxFrameErrors), | ||||
| 		RxFifoErrors:      uint64(s32.RxFifoErrors), | ||||
| 		RxMissedErrors:    uint64(s32.RxMissedErrors), | ||||
| 		TxAbortedErrors:   uint64(s32.TxAbortedErrors), | ||||
| 		TxCarrierErrors:   uint64(s32.TxCarrierErrors), | ||||
| 		TxFifoErrors:      uint64(s32.TxFifoErrors), | ||||
| 		TxHeartbeatErrors: uint64(s32.TxHeartbeatErrors), | ||||
| 		TxWindowErrors:    uint64(s32.TxWindowErrors), | ||||
| 		RxCompressed:      uint64(s32.RxCompressed), | ||||
| 		TxCompressed:      uint64(s32.TxCompressed), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| Ref: struct rtnl_link_stats64 {...} | ||||
| */ | ||||
| type LinkStatistics64 struct { | ||||
| 	RxPackets         uint64 | ||||
| 	TxPackets         uint64 | ||||
| 	RxBytes           uint64 | ||||
| 	TxBytes           uint64 | ||||
| 	RxErrors          uint64 | ||||
| 	TxErrors          uint64 | ||||
| 	RxDropped         uint64 | ||||
| 	TxDropped         uint64 | ||||
| 	Multicast         uint64 | ||||
| 	Collisions        uint64 | ||||
| 	RxLengthErrors    uint64 | ||||
| 	RxOverErrors      uint64 | ||||
| 	RxCrcErrors       uint64 | ||||
| 	RxFrameErrors     uint64 | ||||
| 	RxFifoErrors      uint64 | ||||
| 	RxMissedErrors    uint64 | ||||
| 	TxAbortedErrors   uint64 | ||||
| 	TxCarrierErrors   uint64 | ||||
| 	TxFifoErrors      uint64 | ||||
| 	TxHeartbeatErrors uint64 | ||||
| 	TxWindowErrors    uint64 | ||||
| 	RxCompressed      uint64 | ||||
| 	TxCompressed      uint64 | ||||
| } | ||||
|  | ||||
| type LinkXdp struct { | ||||
| 	Fd       int | ||||
| 	Attached bool | ||||
| 	Flags    uint32 | ||||
| 	ProgId   uint32 | ||||
| } | ||||
|  | ||||
| // Device links cannot be created via netlink. These links | ||||
| // are links created by udev like 'lo' and 'etho0' | ||||
| type Device struct { | ||||
| 	LinkAttrs | ||||
| } | ||||
|  | ||||
| func (device *Device) Attrs() *LinkAttrs { | ||||
| 	return &device.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (device *Device) Type() string { | ||||
| 	return "device" | ||||
| } | ||||
|  | ||||
| // Dummy links are dummy ethernet devices | ||||
| type Dummy struct { | ||||
| 	LinkAttrs | ||||
| } | ||||
|  | ||||
| func (dummy *Dummy) Attrs() *LinkAttrs { | ||||
| 	return &dummy.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (dummy *Dummy) Type() string { | ||||
| 	return "dummy" | ||||
| } | ||||
|  | ||||
| // Ifb links are advanced dummy devices for packet filtering | ||||
| type Ifb struct { | ||||
| 	LinkAttrs | ||||
| } | ||||
|  | ||||
| func (ifb *Ifb) Attrs() *LinkAttrs { | ||||
| 	return &ifb.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (ifb *Ifb) Type() string { | ||||
| 	return "ifb" | ||||
| } | ||||
|  | ||||
| // Bridge links are simple linux bridges | ||||
| type Bridge struct { | ||||
| 	LinkAttrs | ||||
| 	MulticastSnooping *bool | ||||
| 	HelloTime         *uint32 | ||||
| } | ||||
|  | ||||
| func (bridge *Bridge) Attrs() *LinkAttrs { | ||||
| 	return &bridge.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (bridge *Bridge) Type() string { | ||||
| 	return "bridge" | ||||
| } | ||||
|  | ||||
| // Vlan links have ParentIndex set in their Attrs() | ||||
| type Vlan struct { | ||||
| 	LinkAttrs | ||||
| 	VlanId int | ||||
| } | ||||
|  | ||||
| func (vlan *Vlan) Attrs() *LinkAttrs { | ||||
| 	return &vlan.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (vlan *Vlan) Type() string { | ||||
| 	return "vlan" | ||||
| } | ||||
|  | ||||
| type MacvlanMode uint16 | ||||
|  | ||||
| const ( | ||||
| 	MACVLAN_MODE_DEFAULT MacvlanMode = iota | ||||
| 	MACVLAN_MODE_PRIVATE | ||||
| 	MACVLAN_MODE_VEPA | ||||
| 	MACVLAN_MODE_BRIDGE | ||||
| 	MACVLAN_MODE_PASSTHRU | ||||
| 	MACVLAN_MODE_SOURCE | ||||
| ) | ||||
|  | ||||
| // Macvlan links have ParentIndex set in their Attrs() | ||||
| type Macvlan struct { | ||||
| 	LinkAttrs | ||||
| 	Mode MacvlanMode | ||||
|  | ||||
| 	// MACAddrs is only populated for Macvlan SOURCE links | ||||
| 	MACAddrs []net.HardwareAddr | ||||
| } | ||||
|  | ||||
| func (macvlan *Macvlan) Attrs() *LinkAttrs { | ||||
| 	return &macvlan.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (macvlan *Macvlan) Type() string { | ||||
| 	return "macvlan" | ||||
| } | ||||
|  | ||||
| // Macvtap - macvtap is a virtual interfaces based on macvlan | ||||
| type Macvtap struct { | ||||
| 	Macvlan | ||||
| } | ||||
|  | ||||
| func (macvtap Macvtap) Type() string { | ||||
| 	return "macvtap" | ||||
| } | ||||
|  | ||||
| type TuntapMode uint16 | ||||
| type TuntapFlag uint16 | ||||
|  | ||||
| // Tuntap links created via /dev/tun/tap, but can be destroyed via netlink | ||||
| type Tuntap struct { | ||||
| 	LinkAttrs | ||||
| 	Mode   TuntapMode | ||||
| 	Flags  TuntapFlag | ||||
| 	Queues int | ||||
| 	Fds    []*os.File | ||||
| } | ||||
|  | ||||
| func (tuntap *Tuntap) Attrs() *LinkAttrs { | ||||
| 	return &tuntap.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (tuntap *Tuntap) Type() string { | ||||
| 	return "tuntap" | ||||
| } | ||||
|  | ||||
| // Veth devices must specify PeerName on create | ||||
| type Veth struct { | ||||
| 	LinkAttrs | ||||
| 	PeerName string // veth on create only | ||||
| } | ||||
|  | ||||
| func (veth *Veth) Attrs() *LinkAttrs { | ||||
| 	return &veth.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (veth *Veth) Type() string { | ||||
| 	return "veth" | ||||
| } | ||||
|  | ||||
| // GenericLink links represent types that are not currently understood | ||||
| // by this netlink library. | ||||
| type GenericLink struct { | ||||
| 	LinkAttrs | ||||
| 	LinkType string | ||||
| } | ||||
|  | ||||
| func (generic *GenericLink) Attrs() *LinkAttrs { | ||||
| 	return &generic.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (generic *GenericLink) Type() string { | ||||
| 	return generic.LinkType | ||||
| } | ||||
|  | ||||
| type Vxlan struct { | ||||
| 	LinkAttrs | ||||
| 	VxlanId        int | ||||
| 	VtepDevIndex   int | ||||
| 	SrcAddr        net.IP | ||||
| 	Group          net.IP | ||||
| 	TTL            int | ||||
| 	TOS            int | ||||
| 	Learning       bool | ||||
| 	Proxy          bool | ||||
| 	RSC            bool | ||||
| 	L2miss         bool | ||||
| 	L3miss         bool | ||||
| 	UDPCSum        bool | ||||
| 	UDP6ZeroCSumTx bool | ||||
| 	UDP6ZeroCSumRx bool | ||||
| 	NoAge          bool | ||||
| 	GBP            bool | ||||
| 	FlowBased      bool | ||||
| 	Age            int | ||||
| 	Limit          int | ||||
| 	Port           int | ||||
| 	PortLow        int | ||||
| 	PortHigh       int | ||||
| } | ||||
|  | ||||
| func (vxlan *Vxlan) Attrs() *LinkAttrs { | ||||
| 	return &vxlan.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (vxlan *Vxlan) Type() string { | ||||
| 	return "vxlan" | ||||
| } | ||||
|  | ||||
| type IPVlanMode uint16 | ||||
|  | ||||
| const ( | ||||
| 	IPVLAN_MODE_L2 IPVlanMode = iota | ||||
| 	IPVLAN_MODE_L3 | ||||
| 	IPVLAN_MODE_L3S | ||||
| 	IPVLAN_MODE_MAX | ||||
| ) | ||||
|  | ||||
| type IPVlan struct { | ||||
| 	LinkAttrs | ||||
| 	Mode IPVlanMode | ||||
| } | ||||
|  | ||||
| func (ipvlan *IPVlan) Attrs() *LinkAttrs { | ||||
| 	return &ipvlan.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (ipvlan *IPVlan) Type() string { | ||||
| 	return "ipvlan" | ||||
| } | ||||
|  | ||||
| // BondMode type | ||||
| type BondMode int | ||||
|  | ||||
| func (b BondMode) String() string { | ||||
| 	s, ok := bondModeToString[b] | ||||
| 	if !ok { | ||||
| 		return fmt.Sprintf("BondMode(%d)", b) | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| // StringToBondMode returns bond mode, or uknonw is the s is invalid. | ||||
| func StringToBondMode(s string) BondMode { | ||||
| 	mode, ok := StringToBondModeMap[s] | ||||
| 	if !ok { | ||||
| 		return BOND_MODE_UNKNOWN | ||||
| 	} | ||||
| 	return mode | ||||
| } | ||||
|  | ||||
| // Possible BondMode | ||||
| const ( | ||||
| 	BOND_MODE_BALANCE_RR BondMode = iota | ||||
| 	BOND_MODE_ACTIVE_BACKUP | ||||
| 	BOND_MODE_BALANCE_XOR | ||||
| 	BOND_MODE_BROADCAST | ||||
| 	BOND_MODE_802_3AD | ||||
| 	BOND_MODE_BALANCE_TLB | ||||
| 	BOND_MODE_BALANCE_ALB | ||||
| 	BOND_MODE_UNKNOWN | ||||
| ) | ||||
|  | ||||
| var bondModeToString = map[BondMode]string{ | ||||
| 	BOND_MODE_BALANCE_RR:    "balance-rr", | ||||
| 	BOND_MODE_ACTIVE_BACKUP: "active-backup", | ||||
| 	BOND_MODE_BALANCE_XOR:   "balance-xor", | ||||
| 	BOND_MODE_BROADCAST:     "broadcast", | ||||
| 	BOND_MODE_802_3AD:       "802.3ad", | ||||
| 	BOND_MODE_BALANCE_TLB:   "balance-tlb", | ||||
| 	BOND_MODE_BALANCE_ALB:   "balance-alb", | ||||
| } | ||||
| var StringToBondModeMap = map[string]BondMode{ | ||||
| 	"balance-rr":    BOND_MODE_BALANCE_RR, | ||||
| 	"active-backup": BOND_MODE_ACTIVE_BACKUP, | ||||
| 	"balance-xor":   BOND_MODE_BALANCE_XOR, | ||||
| 	"broadcast":     BOND_MODE_BROADCAST, | ||||
| 	"802.3ad":       BOND_MODE_802_3AD, | ||||
| 	"balance-tlb":   BOND_MODE_BALANCE_TLB, | ||||
| 	"balance-alb":   BOND_MODE_BALANCE_ALB, | ||||
| } | ||||
|  | ||||
| // BondArpValidate type | ||||
| type BondArpValidate int | ||||
|  | ||||
| // Possible BondArpValidate value | ||||
| const ( | ||||
| 	BOND_ARP_VALIDATE_NONE BondArpValidate = iota | ||||
| 	BOND_ARP_VALIDATE_ACTIVE | ||||
| 	BOND_ARP_VALIDATE_BACKUP | ||||
| 	BOND_ARP_VALIDATE_ALL | ||||
| ) | ||||
|  | ||||
| // BondPrimaryReselect type | ||||
| type BondPrimaryReselect int | ||||
|  | ||||
| // Possible BondPrimaryReselect value | ||||
| const ( | ||||
| 	BOND_PRIMARY_RESELECT_ALWAYS BondPrimaryReselect = iota | ||||
| 	BOND_PRIMARY_RESELECT_BETTER | ||||
| 	BOND_PRIMARY_RESELECT_FAILURE | ||||
| ) | ||||
|  | ||||
| // BondArpAllTargets type | ||||
| type BondArpAllTargets int | ||||
|  | ||||
| // Possible BondArpAllTargets value | ||||
| const ( | ||||
| 	BOND_ARP_ALL_TARGETS_ANY BondArpAllTargets = iota | ||||
| 	BOND_ARP_ALL_TARGETS_ALL | ||||
| ) | ||||
|  | ||||
| // BondFailOverMac type | ||||
| type BondFailOverMac int | ||||
|  | ||||
| // Possible BondFailOverMac value | ||||
| const ( | ||||
| 	BOND_FAIL_OVER_MAC_NONE BondFailOverMac = iota | ||||
| 	BOND_FAIL_OVER_MAC_ACTIVE | ||||
| 	BOND_FAIL_OVER_MAC_FOLLOW | ||||
| ) | ||||
|  | ||||
| // BondXmitHashPolicy type | ||||
| type BondXmitHashPolicy int | ||||
|  | ||||
| func (b BondXmitHashPolicy) String() string { | ||||
| 	s, ok := bondXmitHashPolicyToString[b] | ||||
| 	if !ok { | ||||
| 		return fmt.Sprintf("XmitHashPolicy(%d)", b) | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| // StringToBondXmitHashPolicy returns bond lacp arte, or uknonw is the s is invalid. | ||||
| func StringToBondXmitHashPolicy(s string) BondXmitHashPolicy { | ||||
| 	lacp, ok := StringToBondXmitHashPolicyMap[s] | ||||
| 	if !ok { | ||||
| 		return BOND_XMIT_HASH_POLICY_UNKNOWN | ||||
| 	} | ||||
| 	return lacp | ||||
| } | ||||
|  | ||||
| // Possible BondXmitHashPolicy value | ||||
| const ( | ||||
| 	BOND_XMIT_HASH_POLICY_LAYER2 BondXmitHashPolicy = iota | ||||
| 	BOND_XMIT_HASH_POLICY_LAYER3_4 | ||||
| 	BOND_XMIT_HASH_POLICY_LAYER2_3 | ||||
| 	BOND_XMIT_HASH_POLICY_ENCAP2_3 | ||||
| 	BOND_XMIT_HASH_POLICY_ENCAP3_4 | ||||
| 	BOND_XMIT_HASH_POLICY_UNKNOWN | ||||
| ) | ||||
|  | ||||
| var bondXmitHashPolicyToString = map[BondXmitHashPolicy]string{ | ||||
| 	BOND_XMIT_HASH_POLICY_LAYER2:   "layer2", | ||||
| 	BOND_XMIT_HASH_POLICY_LAYER3_4: "layer3+4", | ||||
| 	BOND_XMIT_HASH_POLICY_LAYER2_3: "layer2+3", | ||||
| 	BOND_XMIT_HASH_POLICY_ENCAP2_3: "encap2+3", | ||||
| 	BOND_XMIT_HASH_POLICY_ENCAP3_4: "encap3+4", | ||||
| } | ||||
| var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{ | ||||
| 	"layer2":   BOND_XMIT_HASH_POLICY_LAYER2, | ||||
| 	"layer3+4": BOND_XMIT_HASH_POLICY_LAYER3_4, | ||||
| 	"layer2+3": BOND_XMIT_HASH_POLICY_LAYER2_3, | ||||
| 	"encap2+3": BOND_XMIT_HASH_POLICY_ENCAP2_3, | ||||
| 	"encap3+4": BOND_XMIT_HASH_POLICY_ENCAP3_4, | ||||
| } | ||||
|  | ||||
| // BondLacpRate type | ||||
| type BondLacpRate int | ||||
|  | ||||
| func (b BondLacpRate) String() string { | ||||
| 	s, ok := bondLacpRateToString[b] | ||||
| 	if !ok { | ||||
| 		return fmt.Sprintf("LacpRate(%d)", b) | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| // StringToBondLacpRate returns bond lacp arte, or uknonw is the s is invalid. | ||||
| func StringToBondLacpRate(s string) BondLacpRate { | ||||
| 	lacp, ok := StringToBondLacpRateMap[s] | ||||
| 	if !ok { | ||||
| 		return BOND_LACP_RATE_UNKNOWN | ||||
| 	} | ||||
| 	return lacp | ||||
| } | ||||
|  | ||||
| // Possible BondLacpRate value | ||||
| const ( | ||||
| 	BOND_LACP_RATE_SLOW BondLacpRate = iota | ||||
| 	BOND_LACP_RATE_FAST | ||||
| 	BOND_LACP_RATE_UNKNOWN | ||||
| ) | ||||
|  | ||||
| var bondLacpRateToString = map[BondLacpRate]string{ | ||||
| 	BOND_LACP_RATE_SLOW: "slow", | ||||
| 	BOND_LACP_RATE_FAST: "fast", | ||||
| } | ||||
| var StringToBondLacpRateMap = map[string]BondLacpRate{ | ||||
| 	"slow": BOND_LACP_RATE_SLOW, | ||||
| 	"fast": BOND_LACP_RATE_FAST, | ||||
| } | ||||
|  | ||||
| // BondAdSelect type | ||||
| type BondAdSelect int | ||||
|  | ||||
| // Possible BondAdSelect value | ||||
| const ( | ||||
| 	BOND_AD_SELECT_STABLE BondAdSelect = iota | ||||
| 	BOND_AD_SELECT_BANDWIDTH | ||||
| 	BOND_AD_SELECT_COUNT | ||||
| ) | ||||
|  | ||||
| // BondAdInfo represents ad info for bond | ||||
| type BondAdInfo struct { | ||||
| 	AggregatorId int | ||||
| 	NumPorts     int | ||||
| 	ActorKey     int | ||||
| 	PartnerKey   int | ||||
| 	PartnerMac   net.HardwareAddr | ||||
| } | ||||
|  | ||||
| // Bond representation | ||||
| type Bond struct { | ||||
| 	LinkAttrs | ||||
| 	Mode            BondMode | ||||
| 	ActiveSlave     int | ||||
| 	Miimon          int | ||||
| 	UpDelay         int | ||||
| 	DownDelay       int | ||||
| 	UseCarrier      int | ||||
| 	ArpInterval     int | ||||
| 	ArpIpTargets    []net.IP | ||||
| 	ArpValidate     BondArpValidate | ||||
| 	ArpAllTargets   BondArpAllTargets | ||||
| 	Primary         int | ||||
| 	PrimaryReselect BondPrimaryReselect | ||||
| 	FailOverMac     BondFailOverMac | ||||
| 	XmitHashPolicy  BondXmitHashPolicy | ||||
| 	ResendIgmp      int | ||||
| 	NumPeerNotif    int | ||||
| 	AllSlavesActive int | ||||
| 	MinLinks        int | ||||
| 	LpInterval      int | ||||
| 	PackersPerSlave int | ||||
| 	LacpRate        BondLacpRate | ||||
| 	AdSelect        BondAdSelect | ||||
| 	// looking at iproute tool AdInfo can only be retrived. It can't be set. | ||||
| 	AdInfo         *BondAdInfo | ||||
| 	AdActorSysPrio int | ||||
| 	AdUserPortKey  int | ||||
| 	AdActorSystem  net.HardwareAddr | ||||
| 	TlbDynamicLb   int | ||||
| } | ||||
|  | ||||
| func NewLinkBond(atr LinkAttrs) *Bond { | ||||
| 	return &Bond{ | ||||
| 		LinkAttrs:       atr, | ||||
| 		Mode:            -1, | ||||
| 		ActiveSlave:     -1, | ||||
| 		Miimon:          -1, | ||||
| 		UpDelay:         -1, | ||||
| 		DownDelay:       -1, | ||||
| 		UseCarrier:      -1, | ||||
| 		ArpInterval:     -1, | ||||
| 		ArpIpTargets:    nil, | ||||
| 		ArpValidate:     -1, | ||||
| 		ArpAllTargets:   -1, | ||||
| 		Primary:         -1, | ||||
| 		PrimaryReselect: -1, | ||||
| 		FailOverMac:     -1, | ||||
| 		XmitHashPolicy:  -1, | ||||
| 		ResendIgmp:      -1, | ||||
| 		NumPeerNotif:    -1, | ||||
| 		AllSlavesActive: -1, | ||||
| 		MinLinks:        -1, | ||||
| 		LpInterval:      -1, | ||||
| 		PackersPerSlave: -1, | ||||
| 		LacpRate:        -1, | ||||
| 		AdSelect:        -1, | ||||
| 		AdActorSysPrio:  -1, | ||||
| 		AdUserPortKey:   -1, | ||||
| 		AdActorSystem:   nil, | ||||
| 		TlbDynamicLb:    -1, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Flag mask for bond options. Bond.Flagmask must be set to on for option to work. | ||||
| const ( | ||||
| 	BOND_MODE_MASK uint64 = 1 << (1 + iota) | ||||
| 	BOND_ACTIVE_SLAVE_MASK | ||||
| 	BOND_MIIMON_MASK | ||||
| 	BOND_UPDELAY_MASK | ||||
| 	BOND_DOWNDELAY_MASK | ||||
| 	BOND_USE_CARRIER_MASK | ||||
| 	BOND_ARP_INTERVAL_MASK | ||||
| 	BOND_ARP_VALIDATE_MASK | ||||
| 	BOND_ARP_ALL_TARGETS_MASK | ||||
| 	BOND_PRIMARY_MASK | ||||
| 	BOND_PRIMARY_RESELECT_MASK | ||||
| 	BOND_FAIL_OVER_MAC_MASK | ||||
| 	BOND_XMIT_HASH_POLICY_MASK | ||||
| 	BOND_RESEND_IGMP_MASK | ||||
| 	BOND_NUM_PEER_NOTIF_MASK | ||||
| 	BOND_ALL_SLAVES_ACTIVE_MASK | ||||
| 	BOND_MIN_LINKS_MASK | ||||
| 	BOND_LP_INTERVAL_MASK | ||||
| 	BOND_PACKETS_PER_SLAVE_MASK | ||||
| 	BOND_LACP_RATE_MASK | ||||
| 	BOND_AD_SELECT_MASK | ||||
| ) | ||||
|  | ||||
| // Attrs implementation. | ||||
| func (bond *Bond) Attrs() *LinkAttrs { | ||||
| 	return &bond.LinkAttrs | ||||
| } | ||||
|  | ||||
| // Type implementation fro Vxlan. | ||||
| func (bond *Bond) Type() string { | ||||
| 	return "bond" | ||||
| } | ||||
|  | ||||
| // Gretap devices must specify LocalIP and RemoteIP on create | ||||
| type Gretap struct { | ||||
| 	LinkAttrs | ||||
| 	IKey       uint32 | ||||
| 	OKey       uint32 | ||||
| 	EncapSport uint16 | ||||
| 	EncapDport uint16 | ||||
| 	Local      net.IP | ||||
| 	Remote     net.IP | ||||
| 	IFlags     uint16 | ||||
| 	OFlags     uint16 | ||||
| 	PMtuDisc   uint8 | ||||
| 	Ttl        uint8 | ||||
| 	Tos        uint8 | ||||
| 	EncapType  uint16 | ||||
| 	EncapFlags uint16 | ||||
| 	Link       uint32 | ||||
| 	FlowBased  bool | ||||
| } | ||||
|  | ||||
| func (gretap *Gretap) Attrs() *LinkAttrs { | ||||
| 	return &gretap.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (gretap *Gretap) Type() string { | ||||
| 	if gretap.Local.To4() == nil { | ||||
| 		return "ip6gretap" | ||||
| 	} | ||||
| 	return "gretap" | ||||
| } | ||||
|  | ||||
| type Iptun struct { | ||||
| 	LinkAttrs | ||||
| 	Ttl        uint8 | ||||
| 	Tos        uint8 | ||||
| 	PMtuDisc   uint8 | ||||
| 	Link       uint32 | ||||
| 	Local      net.IP | ||||
| 	Remote     net.IP | ||||
| 	EncapSport uint16 | ||||
| 	EncapDport uint16 | ||||
| 	EncapType  uint16 | ||||
| 	EncapFlags uint16 | ||||
| 	FlowBased  bool | ||||
| } | ||||
|  | ||||
| func (iptun *Iptun) Attrs() *LinkAttrs { | ||||
| 	return &iptun.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (iptun *Iptun) Type() string { | ||||
| 	return "ipip" | ||||
| } | ||||
|  | ||||
| type Sittun struct { | ||||
| 	LinkAttrs | ||||
| 	Link       uint32 | ||||
| 	Local      net.IP | ||||
| 	Remote     net.IP | ||||
| 	Ttl        uint8 | ||||
| 	Tos        uint8 | ||||
| 	PMtuDisc   uint8 | ||||
| 	EncapType  uint16 | ||||
| 	EncapFlags uint16 | ||||
| 	EncapSport uint16 | ||||
| 	EncapDport uint16 | ||||
| } | ||||
|  | ||||
| func (sittun *Sittun) Attrs() *LinkAttrs { | ||||
| 	return &sittun.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (sittun *Sittun) Type() string { | ||||
| 	return "sit" | ||||
| } | ||||
|  | ||||
| type Vti struct { | ||||
| 	LinkAttrs | ||||
| 	IKey   uint32 | ||||
| 	OKey   uint32 | ||||
| 	Link   uint32 | ||||
| 	Local  net.IP | ||||
| 	Remote net.IP | ||||
| } | ||||
|  | ||||
| func (vti *Vti) Attrs() *LinkAttrs { | ||||
| 	return &vti.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (iptun *Vti) Type() string { | ||||
| 	return "vti" | ||||
| } | ||||
|  | ||||
| type Gretun struct { | ||||
| 	LinkAttrs | ||||
| 	Link       uint32 | ||||
| 	IFlags     uint16 | ||||
| 	OFlags     uint16 | ||||
| 	IKey       uint32 | ||||
| 	OKey       uint32 | ||||
| 	Local      net.IP | ||||
| 	Remote     net.IP | ||||
| 	Ttl        uint8 | ||||
| 	Tos        uint8 | ||||
| 	PMtuDisc   uint8 | ||||
| 	EncapType  uint16 | ||||
| 	EncapFlags uint16 | ||||
| 	EncapSport uint16 | ||||
| 	EncapDport uint16 | ||||
| } | ||||
|  | ||||
| func (gretun *Gretun) Attrs() *LinkAttrs { | ||||
| 	return &gretun.LinkAttrs | ||||
| } | ||||
|  | ||||
| func (gretun *Gretun) Type() string { | ||||
| 	if gretun.Local.To4() == nil { | ||||
| 		return "ip6gre" | ||||
| 	} | ||||
| 	return "gre" | ||||
| } | ||||
|  | ||||
| type Vrf struct { | ||||
| 	LinkAttrs | ||||
| 	Table uint32 | ||||
| } | ||||
|  | ||||
| func (vrf *Vrf) Attrs() *LinkAttrs { | ||||
| 	return &vrf.LinkAttrs | ||||
| } | ||||
|  | ||||
| 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 | ||||
| } | ||||
							
								
								
									
										2354
									
								
								vendor/github.com/vishvananda/netlink/link_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2354
									
								
								vendor/github.com/vishvananda/netlink/link_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										14
									
								
								vendor/github.com/vishvananda/netlink/link_tuntap_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/vishvananda/netlink/link_tuntap_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| package netlink | ||||
|  | ||||
| // ideally golang.org/x/sys/unix would define IfReq but it only has | ||||
| // IFNAMSIZ, hence this minimalistic implementation | ||||
| const ( | ||||
| 	SizeOfIfReq = 40 | ||||
| 	IFNAMSIZ    = 16 | ||||
| ) | ||||
|  | ||||
| type ifReq struct { | ||||
| 	Name  [IFNAMSIZ]byte | ||||
| 	Flags uint16 | ||||
| 	pad   [SizeOfIfReq - IFNAMSIZ - 2]byte | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/github.com/vishvananda/netlink/neigh.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/vishvananda/netlink/neigh.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| ) | ||||
|  | ||||
| // Neigh represents a link layer neighbor from netlink. | ||||
| type Neigh struct { | ||||
| 	LinkIndex    int | ||||
| 	Family       int | ||||
| 	State        int | ||||
| 	Type         int | ||||
| 	Flags        int | ||||
| 	IP           net.IP | ||||
| 	HardwareAddr net.HardwareAddr | ||||
| 	LLIPAddr     net.IP //Used in the case of NHRP | ||||
| 	Vlan         int | ||||
| 	VNI          int | ||||
| } | ||||
|  | ||||
| // String returns $ip/$hwaddr $label | ||||
| func (neigh *Neigh) String() string { | ||||
| 	return fmt.Sprintf("%s %s", neigh.IP, neigh.HardwareAddr) | ||||
| } | ||||
							
								
								
									
										289
									
								
								vendor/github.com/vishvananda/netlink/neigh_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								vendor/github.com/vishvananda/netlink/neigh_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,289 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"net" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	NDA_UNSPEC = iota | ||||
| 	NDA_DST | ||||
| 	NDA_LLADDR | ||||
| 	NDA_CACHEINFO | ||||
| 	NDA_PROBES | ||||
| 	NDA_VLAN | ||||
| 	NDA_PORT | ||||
| 	NDA_VNI | ||||
| 	NDA_IFINDEX | ||||
| 	NDA_MAX = NDA_IFINDEX | ||||
| ) | ||||
|  | ||||
| // Neighbor Cache Entry States. | ||||
| const ( | ||||
| 	NUD_NONE       = 0x00 | ||||
| 	NUD_INCOMPLETE = 0x01 | ||||
| 	NUD_REACHABLE  = 0x02 | ||||
| 	NUD_STALE      = 0x04 | ||||
| 	NUD_DELAY      = 0x08 | ||||
| 	NUD_PROBE      = 0x10 | ||||
| 	NUD_FAILED     = 0x20 | ||||
| 	NUD_NOARP      = 0x40 | ||||
| 	NUD_PERMANENT  = 0x80 | ||||
| ) | ||||
|  | ||||
| // Neighbor Flags | ||||
| const ( | ||||
| 	NTF_USE    = 0x01 | ||||
| 	NTF_SELF   = 0x02 | ||||
| 	NTF_MASTER = 0x04 | ||||
| 	NTF_PROXY  = 0x08 | ||||
| 	NTF_ROUTER = 0x80 | ||||
| ) | ||||
|  | ||||
| type Ndmsg struct { | ||||
| 	Family uint8 | ||||
| 	Index  uint32 | ||||
| 	State  uint16 | ||||
| 	Flags  uint8 | ||||
| 	Type   uint8 | ||||
| } | ||||
|  | ||||
| func deserializeNdmsg(b []byte) *Ndmsg { | ||||
| 	var dummy Ndmsg | ||||
| 	return (*Ndmsg)(unsafe.Pointer(&b[0:unsafe.Sizeof(dummy)][0])) | ||||
| } | ||||
|  | ||||
| func (msg *Ndmsg) Serialize() []byte { | ||||
| 	return (*(*[unsafe.Sizeof(*msg)]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| func (msg *Ndmsg) Len() int { | ||||
| 	return int(unsafe.Sizeof(*msg)) | ||||
| } | ||||
|  | ||||
| // NeighAdd will add an IP to MAC mapping to the ARP table | ||||
| // Equivalent to: `ip neigh add ....` | ||||
| func NeighAdd(neigh *Neigh) error { | ||||
| 	return pkgHandle.NeighAdd(neigh) | ||||
| } | ||||
|  | ||||
| // NeighAdd will add an IP to MAC mapping to the ARP table | ||||
| // Equivalent to: `ip neigh add ....` | ||||
| func (h *Handle) NeighAdd(neigh *Neigh) error { | ||||
| 	return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_EXCL) | ||||
| } | ||||
|  | ||||
| // NeighSet will add or replace an IP to MAC mapping to the ARP table | ||||
| // Equivalent to: `ip neigh replace....` | ||||
| func NeighSet(neigh *Neigh) error { | ||||
| 	return pkgHandle.NeighSet(neigh) | ||||
| } | ||||
|  | ||||
| // NeighSet will add or replace an IP to MAC mapping to the ARP table | ||||
| // Equivalent to: `ip neigh replace....` | ||||
| func (h *Handle) NeighSet(neigh *Neigh) error { | ||||
| 	return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_REPLACE) | ||||
| } | ||||
|  | ||||
| // NeighAppend will append an entry to FDB | ||||
| // Equivalent to: `bridge fdb append...` | ||||
| func NeighAppend(neigh *Neigh) error { | ||||
| 	return pkgHandle.NeighAppend(neigh) | ||||
| } | ||||
|  | ||||
| // NeighAppend will append an entry to FDB | ||||
| // Equivalent to: `bridge fdb append...` | ||||
| func (h *Handle) NeighAppend(neigh *Neigh) error { | ||||
| 	return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_APPEND) | ||||
| } | ||||
|  | ||||
| // NeighAppend will append an entry to FDB | ||||
| // Equivalent to: `bridge fdb append...` | ||||
| func neighAdd(neigh *Neigh, mode int) error { | ||||
| 	return pkgHandle.neighAdd(neigh, mode) | ||||
| } | ||||
|  | ||||
| // NeighAppend will append an entry to FDB | ||||
| // Equivalent to: `bridge fdb append...` | ||||
| func (h *Handle) neighAdd(neigh *Neigh, mode int) error { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_NEWNEIGH, mode|unix.NLM_F_ACK) | ||||
| 	return neighHandle(neigh, req) | ||||
| } | ||||
|  | ||||
| // NeighDel will delete an IP address from a link device. | ||||
| // Equivalent to: `ip addr del $addr dev $link` | ||||
| func NeighDel(neigh *Neigh) error { | ||||
| 	return pkgHandle.NeighDel(neigh) | ||||
| } | ||||
|  | ||||
| // NeighDel will delete an IP address from a link device. | ||||
| // Equivalent to: `ip addr del $addr dev $link` | ||||
| func (h *Handle) NeighDel(neigh *Neigh) error { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_DELNEIGH, unix.NLM_F_ACK) | ||||
| 	return neighHandle(neigh, req) | ||||
| } | ||||
|  | ||||
| func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error { | ||||
| 	var family int | ||||
|  | ||||
| 	if neigh.Family > 0 { | ||||
| 		family = neigh.Family | ||||
| 	} else { | ||||
| 		family = nl.GetIPFamily(neigh.IP) | ||||
| 	} | ||||
|  | ||||
| 	msg := Ndmsg{ | ||||
| 		Family: uint8(family), | ||||
| 		Index:  uint32(neigh.LinkIndex), | ||||
| 		State:  uint16(neigh.State), | ||||
| 		Type:   uint8(neigh.Type), | ||||
| 		Flags:  uint8(neigh.Flags), | ||||
| 	} | ||||
| 	req.AddData(&msg) | ||||
|  | ||||
| 	ipData := neigh.IP.To4() | ||||
| 	if ipData == nil { | ||||
| 		ipData = neigh.IP.To16() | ||||
| 	} | ||||
|  | ||||
| 	dstData := nl.NewRtAttr(NDA_DST, ipData) | ||||
| 	req.AddData(dstData) | ||||
|  | ||||
| 	if neigh.LLIPAddr != nil { | ||||
| 		llIPData := nl.NewRtAttr(NDA_LLADDR, neigh.LLIPAddr.To4()) | ||||
| 		req.AddData(llIPData) | ||||
| 	} else if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil { | ||||
| 		hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr)) | ||||
| 		req.AddData(hwData) | ||||
| 	} | ||||
|  | ||||
| 	if neigh.Vlan != 0 { | ||||
| 		vlanData := nl.NewRtAttr(NDA_VLAN, nl.Uint16Attr(uint16(neigh.Vlan))) | ||||
| 		req.AddData(vlanData) | ||||
| 	} | ||||
|  | ||||
| 	if neigh.VNI != 0 { | ||||
| 		vniData := nl.NewRtAttr(NDA_VNI, nl.Uint32Attr(uint32(neigh.VNI))) | ||||
| 		req.AddData(vniData) | ||||
| 	} | ||||
|  | ||||
| 	_, err := req.Execute(unix.NETLINK_ROUTE, 0) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // NeighList gets a list of IP-MAC mappings in the system (ARP table). | ||||
| // Equivalent to: `ip neighbor show`. | ||||
| // The list can be filtered by link and ip family. | ||||
| func NeighList(linkIndex, family int) ([]Neigh, error) { | ||||
| 	return pkgHandle.NeighList(linkIndex, family) | ||||
| } | ||||
|  | ||||
| // NeighProxyList gets a list of neighbor proxies in the system. | ||||
| // Equivalent to: `ip neighbor show proxy`. | ||||
| // The list can be filtered by link and ip family. | ||||
| func NeighProxyList(linkIndex, family int) ([]Neigh, error) { | ||||
| 	return pkgHandle.NeighProxyList(linkIndex, family) | ||||
| } | ||||
|  | ||||
| // NeighList gets a list of IP-MAC mappings in the system (ARP table). | ||||
| // Equivalent to: `ip neighbor show`. | ||||
| // The list can be filtered by link and ip family. | ||||
| func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) { | ||||
| 	return h.neighList(linkIndex, family, 0) | ||||
| } | ||||
|  | ||||
| // NeighProxyList gets a list of neighbor proxies in the system. | ||||
| // Equivalent to: `ip neighbor show proxy`. | ||||
| // The list can be filtered by link, ip family. | ||||
| func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) { | ||||
| 	return h.neighList(linkIndex, family, NTF_PROXY) | ||||
| } | ||||
|  | ||||
| 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), | ||||
| 		Index:  uint32(linkIndex), | ||||
| 		Flags:  uint8(flags), | ||||
| 	} | ||||
| 	req.AddData(&msg) | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNEIGH) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	var res []Neigh | ||||
| 	for _, m := range msgs { | ||||
| 		ndm := deserializeNdmsg(m) | ||||
| 		if linkIndex != 0 && int(ndm.Index) != linkIndex { | ||||
| 			// Ignore messages from other interfaces | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		neigh, err := NeighDeserialize(m) | ||||
| 		if err != nil { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		res = append(res, *neigh) | ||||
| 	} | ||||
|  | ||||
| 	return res, nil | ||||
| } | ||||
|  | ||||
| func NeighDeserialize(m []byte) (*Neigh, error) { | ||||
| 	msg := deserializeNdmsg(m) | ||||
|  | ||||
| 	neigh := Neigh{ | ||||
| 		LinkIndex: int(msg.Index), | ||||
| 		Family:    int(msg.Family), | ||||
| 		State:     int(msg.State), | ||||
| 		Type:      int(msg.Type), | ||||
| 		Flags:     int(msg.Flags), | ||||
| 	} | ||||
|  | ||||
| 	attrs, err := nl.ParseRouteAttr(m[msg.Len():]) | ||||
| 	if err != nil { | ||||
| 		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 { | ||||
| 		switch attr.Attr.Type { | ||||
| 		case NDA_DST: | ||||
| 			neigh.IP = net.IP(attr.Value) | ||||
| 		case NDA_LLADDR: | ||||
| 			// BUG: Is this a bug in the netlink library? | ||||
| 			// #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len)) | ||||
| 			// #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0)) | ||||
| 			attrLen := attr.Attr.Len - unix.SizeofRtAttr | ||||
| 			if attrLen == 4 && (encapType == "ipip" || | ||||
| 				encapType == "sit" || | ||||
| 				encapType == "gre") { | ||||
| 				neigh.LLIPAddr = net.IP(attr.Value) | ||||
| 			} else if attrLen == 16 && | ||||
| 				encapType == "tunnel6" { | ||||
| 				neigh.IP = net.IP(attr.Value) | ||||
| 			} else { | ||||
| 				neigh.HardwareAddr = net.HardwareAddr(attr.Value) | ||||
| 			} | ||||
| 		case NDA_VLAN: | ||||
| 			neigh.Vlan = int(native.Uint16(attr.Value[0:2])) | ||||
| 		case NDA_VNI: | ||||
| 			neigh.VNI = int(native.Uint32(attr.Value[0:4])) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return &neigh, nil | ||||
| } | ||||
							
								
								
									
										39
									
								
								vendor/github.com/vishvananda/netlink/netlink.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/vishvananda/netlink/netlink.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| // Package netlink provides a simple library for netlink. Netlink is | ||||
| // the interface a user-space program in linux uses to communicate with | ||||
| // the kernel. It can be used to add and remove interfaces, set up ip | ||||
| // addresses and routes, and confiugre ipsec. Netlink communication | ||||
| // requires elevated privileges, so in most cases this code needs to | ||||
| // be run as root. The low level primitives for netlink are contained | ||||
| // in the nl subpackage. This package attempts to provide a high-level | ||||
| // interface that is loosly modeled on the iproute2 cli. | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"net" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// ErrNotImplemented is returned when a requested feature is not implemented. | ||||
| 	ErrNotImplemented = errors.New("not implemented") | ||||
| ) | ||||
|  | ||||
| // ParseIPNet parses a string in ip/net format and returns a net.IPNet. | ||||
| // This is valuable because addresses in netlink are often IPNets and | ||||
| // ParseCIDR returns an IPNet with the IP part set to the base IP of the | ||||
| // range. | ||||
| func ParseIPNet(s string) (*net.IPNet, error) { | ||||
| 	ip, ipNet, err := net.ParseCIDR(s) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &net.IPNet{IP: ip, Mask: ipNet.Mask}, nil | ||||
| } | ||||
|  | ||||
| // NewIPNet generates an IPNet from an ip address using a netmask of 32 or 128. | ||||
| func NewIPNet(ip net.IP) *net.IPNet { | ||||
| 	if ip.To4() != nil { | ||||
| 		return &net.IPNet{IP: ip, Mask: net.CIDRMask(32, 32)} | ||||
| 	} | ||||
| 	return &net.IPNet{IP: ip, Mask: net.CIDRMask(128, 128)} | ||||
| } | ||||
							
								
								
									
										11
									
								
								vendor/github.com/vishvananda/netlink/netlink_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/vishvananda/netlink/netlink_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| package netlink | ||||
|  | ||||
| import "github.com/vishvananda/netlink/nl" | ||||
|  | ||||
| // Family type definitions | ||||
| const ( | ||||
| 	FAMILY_ALL  = nl.FAMILY_ALL | ||||
| 	FAMILY_V4   = nl.FAMILY_V4 | ||||
| 	FAMILY_V6   = nl.FAMILY_V6 | ||||
| 	FAMILY_MPLS = nl.FAMILY_MPLS | ||||
| ) | ||||
							
								
								
									
										225
									
								
								vendor/github.com/vishvananda/netlink/netlink_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										225
									
								
								vendor/github.com/vishvananda/netlink/netlink_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,225 @@ | ||||
| // +build !linux | ||||
|  | ||||
| package netlink | ||||
|  | ||||
| import "net" | ||||
|  | ||||
| func LinkSetUp(link Link) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetDown(link Link) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetMTU(link Link, mtu int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetMaster(link Link, master *Bridge) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetNsPid(link Link, nspid int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetNsFd(link Link, fd int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetName(link Link, name string) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetAlias(link Link, name string) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetVfVlan(link Link, vf, vlan int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetVfTxRate(link Link, vf, rate int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetNoMaster(link Link) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetMasterByIndex(link Link, masterIndex int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| 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 | ||||
| } | ||||
|  | ||||
| func LinkByAlias(alias string) (Link, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkByIndex(index int) (Link, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetHairpin(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetGuard(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetFastLeave(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetLearning(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetRootBlock(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetFlood(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkSetTxQLen(link Link, qlen int) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkAdd(link Link) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkDel(link Link) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func SetHairpin(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func SetGuard(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func SetFastLeave(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func SetLearning(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func SetRootBlock(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func SetFlood(link Link, mode bool) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func LinkList() ([]Link, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func AddrAdd(link Link, addr *Addr) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func AddrDel(link Link, addr *Addr) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func AddrList(link Link, family int) ([]Addr, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func RouteAdd(route *Route) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func RouteDel(route *Route) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func RouteList(link Link, family int) ([]Route, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func XfrmPolicyAdd(policy *XfrmPolicy) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func XfrmPolicyDel(policy *XfrmPolicy) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func XfrmPolicyList(family int) ([]XfrmPolicy, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func XfrmStateAdd(policy *XfrmState) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func XfrmStateDel(policy *XfrmState) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func XfrmStateList(family int) ([]XfrmState, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func NeighAdd(neigh *Neigh) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func NeighSet(neigh *Neigh) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func NeighAppend(neigh *Neigh) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func NeighDel(neigh *Neigh) error { | ||||
| 	return ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func NeighList(linkIndex, family int) ([]Neigh, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func NeighDeserialize(m []byte) (*Neigh, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func SocketGet(local, remote net.Addr) (*Socket, error) { | ||||
| 	return nil, ErrNotImplemented | ||||
| } | ||||
							
								
								
									
										77
									
								
								vendor/github.com/vishvananda/netlink/nl/addr_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								vendor/github.com/vishvananda/netlink/nl/addr_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| package nl | ||||
|  | ||||
| import ( | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| type IfAddrmsg struct { | ||||
| 	unix.IfAddrmsg | ||||
| } | ||||
|  | ||||
| func NewIfAddrmsg(family int) *IfAddrmsg { | ||||
| 	return &IfAddrmsg{ | ||||
| 		IfAddrmsg: unix.IfAddrmsg{ | ||||
| 			Family: uint8(family), | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // struct ifaddrmsg { | ||||
| //   __u8    ifa_family; | ||||
| //   __u8    ifa_prefixlen;  /* The prefix length    */ | ||||
| //   __u8    ifa_flags;  /* Flags      */ | ||||
| //   __u8    ifa_scope;  /* Address scope    */ | ||||
| //   __u32   ifa_index;  /* Link index     */ | ||||
| // }; | ||||
|  | ||||
| // type IfAddrmsg struct { | ||||
| // 	Family    uint8 | ||||
| // 	Prefixlen uint8 | ||||
| // 	Flags     uint8 | ||||
| // 	Scope     uint8 | ||||
| // 	Index     uint32 | ||||
| // } | ||||
| // SizeofIfAddrmsg     = 0x8 | ||||
|  | ||||
| func DeserializeIfAddrmsg(b []byte) *IfAddrmsg { | ||||
| 	return (*IfAddrmsg)(unsafe.Pointer(&b[0:unix.SizeofIfAddrmsg][0])) | ||||
| } | ||||
|  | ||||
| func (msg *IfAddrmsg) Serialize() []byte { | ||||
| 	return (*(*[unix.SizeofIfAddrmsg]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| func (msg *IfAddrmsg) Len() int { | ||||
| 	return unix.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)))[:] | ||||
| } | ||||
							
								
								
									
										74
									
								
								vendor/github.com/vishvananda/netlink/nl/bridge_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								vendor/github.com/vishvananda/netlink/nl/bridge_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| ) | ||||
							
								
								
									
										189
									
								
								vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										189
									
								
								vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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     = 7 | ||||
| 	CTA_MARK        = 8 | ||||
| 	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)))[:] | ||||
| } | ||||
							
								
								
									
										89
									
								
								vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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)))[:] | ||||
| } | ||||
							
								
								
									
										548
									
								
								vendor/github.com/vishvananda/netlink/nl/link_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										548
									
								
								vendor/github.com/vishvananda/netlink/nl/link_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,548 @@ | ||||
| package nl | ||||
|  | ||||
| import ( | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	DEFAULT_CHANGE = 0xFFFFFFFF | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_INFO_UNSPEC = iota | ||||
| 	IFLA_INFO_KIND | ||||
| 	IFLA_INFO_DATA | ||||
| 	IFLA_INFO_XSTATS | ||||
| 	IFLA_INFO_MAX = IFLA_INFO_XSTATS | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_VLAN_UNSPEC = iota | ||||
| 	IFLA_VLAN_ID | ||||
| 	IFLA_VLAN_FLAGS | ||||
| 	IFLA_VLAN_EGRESS_QOS | ||||
| 	IFLA_VLAN_INGRESS_QOS | ||||
| 	IFLA_VLAN_PROTOCOL | ||||
| 	IFLA_VLAN_MAX = IFLA_VLAN_PROTOCOL | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	VETH_INFO_UNSPEC = iota | ||||
| 	VETH_INFO_PEER | ||||
| 	VETH_INFO_MAX = VETH_INFO_PEER | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_VXLAN_UNSPEC = iota | ||||
| 	IFLA_VXLAN_ID | ||||
| 	IFLA_VXLAN_GROUP | ||||
| 	IFLA_VXLAN_LINK | ||||
| 	IFLA_VXLAN_LOCAL | ||||
| 	IFLA_VXLAN_TTL | ||||
| 	IFLA_VXLAN_TOS | ||||
| 	IFLA_VXLAN_LEARNING | ||||
| 	IFLA_VXLAN_AGEING | ||||
| 	IFLA_VXLAN_LIMIT | ||||
| 	IFLA_VXLAN_PORT_RANGE | ||||
| 	IFLA_VXLAN_PROXY | ||||
| 	IFLA_VXLAN_RSC | ||||
| 	IFLA_VXLAN_L2MISS | ||||
| 	IFLA_VXLAN_L3MISS | ||||
| 	IFLA_VXLAN_PORT | ||||
| 	IFLA_VXLAN_GROUP6 | ||||
| 	IFLA_VXLAN_LOCAL6 | ||||
| 	IFLA_VXLAN_UDP_CSUM | ||||
| 	IFLA_VXLAN_UDP_ZERO_CSUM6_TX | ||||
| 	IFLA_VXLAN_UDP_ZERO_CSUM6_RX | ||||
| 	IFLA_VXLAN_REMCSUM_TX | ||||
| 	IFLA_VXLAN_REMCSUM_RX | ||||
| 	IFLA_VXLAN_GBP | ||||
| 	IFLA_VXLAN_REMCSUM_NOPARTIAL | ||||
| 	IFLA_VXLAN_FLOWBASED | ||||
| 	IFLA_VXLAN_MAX = IFLA_VXLAN_FLOWBASED | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	BRIDGE_MODE_UNSPEC = iota | ||||
| 	BRIDGE_MODE_HAIRPIN | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_BRPORT_UNSPEC = iota | ||||
| 	IFLA_BRPORT_STATE | ||||
| 	IFLA_BRPORT_PRIORITY | ||||
| 	IFLA_BRPORT_COST | ||||
| 	IFLA_BRPORT_MODE | ||||
| 	IFLA_BRPORT_GUARD | ||||
| 	IFLA_BRPORT_PROTECT | ||||
| 	IFLA_BRPORT_FAST_LEAVE | ||||
| 	IFLA_BRPORT_LEARNING | ||||
| 	IFLA_BRPORT_UNICAST_FLOOD | ||||
| 	IFLA_BRPORT_PROXYARP | ||||
| 	IFLA_BRPORT_LEARNING_SYNC | ||||
| 	IFLA_BRPORT_PROXYARP_WIFI | ||||
| 	IFLA_BRPORT_MAX = IFLA_BRPORT_PROXYARP_WIFI | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_IPVLAN_UNSPEC = iota | ||||
| 	IFLA_IPVLAN_MODE | ||||
| 	IFLA_IPVLAN_MAX = IFLA_IPVLAN_MODE | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_MACVLAN_UNSPEC = iota | ||||
| 	IFLA_MACVLAN_MODE | ||||
| 	IFLA_MACVLAN_FLAGS | ||||
| 	IFLA_MACVLAN_MACADDR_MODE | ||||
| 	IFLA_MACVLAN_MACADDR | ||||
| 	IFLA_MACVLAN_MACADDR_DATA | ||||
| 	IFLA_MACVLAN_MACADDR_COUNT | ||||
| 	IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	MACVLAN_MODE_PRIVATE  = 1 | ||||
| 	MACVLAN_MODE_VEPA     = 2 | ||||
| 	MACVLAN_MODE_BRIDGE   = 4 | ||||
| 	MACVLAN_MODE_PASSTHRU = 8 | ||||
| 	MACVLAN_MODE_SOURCE   = 16 | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	MACVLAN_MACADDR_ADD = iota | ||||
| 	MACVLAN_MACADDR_DEL | ||||
| 	MACVLAN_MACADDR_FLUSH | ||||
| 	MACVLAN_MACADDR_SET | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_BOND_UNSPEC = iota | ||||
| 	IFLA_BOND_MODE | ||||
| 	IFLA_BOND_ACTIVE_SLAVE | ||||
| 	IFLA_BOND_MIIMON | ||||
| 	IFLA_BOND_UPDELAY | ||||
| 	IFLA_BOND_DOWNDELAY | ||||
| 	IFLA_BOND_USE_CARRIER | ||||
| 	IFLA_BOND_ARP_INTERVAL | ||||
| 	IFLA_BOND_ARP_IP_TARGET | ||||
| 	IFLA_BOND_ARP_VALIDATE | ||||
| 	IFLA_BOND_ARP_ALL_TARGETS | ||||
| 	IFLA_BOND_PRIMARY | ||||
| 	IFLA_BOND_PRIMARY_RESELECT | ||||
| 	IFLA_BOND_FAIL_OVER_MAC | ||||
| 	IFLA_BOND_XMIT_HASH_POLICY | ||||
| 	IFLA_BOND_RESEND_IGMP | ||||
| 	IFLA_BOND_NUM_PEER_NOTIF | ||||
| 	IFLA_BOND_ALL_SLAVES_ACTIVE | ||||
| 	IFLA_BOND_MIN_LINKS | ||||
| 	IFLA_BOND_LP_INTERVAL | ||||
| 	IFLA_BOND_PACKETS_PER_SLAVE | ||||
| 	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 ( | ||||
| 	IFLA_BOND_AD_INFO_UNSPEC = iota | ||||
| 	IFLA_BOND_AD_INFO_AGGREGATOR | ||||
| 	IFLA_BOND_AD_INFO_NUM_PORTS | ||||
| 	IFLA_BOND_AD_INFO_ACTOR_KEY | ||||
| 	IFLA_BOND_AD_INFO_PARTNER_KEY | ||||
| 	IFLA_BOND_AD_INFO_PARTNER_MAC | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_BOND_SLAVE_UNSPEC = iota | ||||
| 	IFLA_BOND_SLAVE_STATE | ||||
| 	IFLA_BOND_SLAVE_MII_STATUS | ||||
| 	IFLA_BOND_SLAVE_LINK_FAILURE_COUNT | ||||
| 	IFLA_BOND_SLAVE_PERM_HWADDR | ||||
| 	IFLA_BOND_SLAVE_QUEUE_ID | ||||
| 	IFLA_BOND_SLAVE_AD_AGGREGATOR_ID | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_GRE_UNSPEC = iota | ||||
| 	IFLA_GRE_LINK | ||||
| 	IFLA_GRE_IFLAGS | ||||
| 	IFLA_GRE_OFLAGS | ||||
| 	IFLA_GRE_IKEY | ||||
| 	IFLA_GRE_OKEY | ||||
| 	IFLA_GRE_LOCAL | ||||
| 	IFLA_GRE_REMOTE | ||||
| 	IFLA_GRE_TTL | ||||
| 	IFLA_GRE_TOS | ||||
| 	IFLA_GRE_PMTUDISC | ||||
| 	IFLA_GRE_ENCAP_LIMIT | ||||
| 	IFLA_GRE_FLOWINFO | ||||
| 	IFLA_GRE_FLAGS | ||||
| 	IFLA_GRE_ENCAP_TYPE | ||||
| 	IFLA_GRE_ENCAP_FLAGS | ||||
| 	IFLA_GRE_ENCAP_SPORT | ||||
| 	IFLA_GRE_ENCAP_DPORT | ||||
| 	IFLA_GRE_COLLECT_METADATA | ||||
| 	IFLA_GRE_MAX = IFLA_GRE_COLLECT_METADATA | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	GRE_CSUM    = 0x8000 | ||||
| 	GRE_ROUTING = 0x4000 | ||||
| 	GRE_KEY     = 0x2000 | ||||
| 	GRE_SEQ     = 0x1000 | ||||
| 	GRE_STRICT  = 0x0800 | ||||
| 	GRE_REC     = 0x0700 | ||||
| 	GRE_FLAGS   = 0x00F8 | ||||
| 	GRE_VERSION = 0x0007 | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_VF_INFO_UNSPEC = iota | ||||
| 	IFLA_VF_INFO | ||||
| 	IFLA_VF_INFO_MAX = IFLA_VF_INFO | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_VF_UNSPEC = iota | ||||
| 	IFLA_VF_MAC    /* Hardware queue specific attributes */ | ||||
| 	IFLA_VF_VLAN | ||||
| 	IFLA_VF_TX_RATE      /* Max TX Bandwidth Allocation */ | ||||
| 	IFLA_VF_SPOOFCHK     /* Spoof Checking on/off switch */ | ||||
| 	IFLA_VF_LINK_STATE   /* link state enable/disable/auto switch */ | ||||
| 	IFLA_VF_RATE         /* Min and Max TX Bandwidth Allocation */ | ||||
| 	IFLA_VF_RSS_QUERY_EN /* RSS Redirection Table and Hash Key query | ||||
| 	 * on/off switch | ||||
| 	 */ | ||||
| 	IFLA_VF_STATS /* network device statistics */ | ||||
| 	IFLA_VF_TRUST /* Trust state of VF */ | ||||
| 	IFLA_VF_MAX   = IFLA_VF_TRUST | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_VF_LINK_STATE_AUTO    = iota /* link state of the uplink */ | ||||
| 	IFLA_VF_LINK_STATE_ENABLE         /* link always up */ | ||||
| 	IFLA_VF_LINK_STATE_DISABLE        /* link always down */ | ||||
| 	IFLA_VF_LINK_STATE_MAX     = IFLA_VF_LINK_STATE_DISABLE | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_VF_STATS_RX_PACKETS = iota | ||||
| 	IFLA_VF_STATS_TX_PACKETS | ||||
| 	IFLA_VF_STATS_RX_BYTES | ||||
| 	IFLA_VF_STATS_TX_BYTES | ||||
| 	IFLA_VF_STATS_BROADCAST | ||||
| 	IFLA_VF_STATS_MULTICAST | ||||
| 	IFLA_VF_STATS_MAX = IFLA_VF_STATS_MULTICAST | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	SizeofVfMac        = 0x24 | ||||
| 	SizeofVfVlan       = 0x0c | ||||
| 	SizeofVfTxRate     = 0x08 | ||||
| 	SizeofVfRate       = 0x0c | ||||
| 	SizeofVfSpoofchk   = 0x08 | ||||
| 	SizeofVfLinkState  = 0x08 | ||||
| 	SizeofVfRssQueryEn = 0x08 | ||||
| 	SizeofVfTrust      = 0x08 | ||||
| ) | ||||
|  | ||||
| // struct ifla_vf_mac { | ||||
| //   __u32 vf; | ||||
| //   __u8 mac[32]; /* MAX_ADDR_LEN */ | ||||
| // }; | ||||
|  | ||||
| type VfMac struct { | ||||
| 	Vf  uint32 | ||||
| 	Mac [32]byte | ||||
| } | ||||
|  | ||||
| func (msg *VfMac) Len() int { | ||||
| 	return SizeofVfMac | ||||
| } | ||||
|  | ||||
| func DeserializeVfMac(b []byte) *VfMac { | ||||
| 	return (*VfMac)(unsafe.Pointer(&b[0:SizeofVfMac][0])) | ||||
| } | ||||
|  | ||||
| func (msg *VfMac) Serialize() []byte { | ||||
| 	return (*(*[SizeofVfMac]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct ifla_vf_vlan { | ||||
| //   __u32 vf; | ||||
| //   __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */ | ||||
| //   __u32 qos; | ||||
| // }; | ||||
|  | ||||
| type VfVlan struct { | ||||
| 	Vf   uint32 | ||||
| 	Vlan uint32 | ||||
| 	Qos  uint32 | ||||
| } | ||||
|  | ||||
| func (msg *VfVlan) Len() int { | ||||
| 	return SizeofVfVlan | ||||
| } | ||||
|  | ||||
| func DeserializeVfVlan(b []byte) *VfVlan { | ||||
| 	return (*VfVlan)(unsafe.Pointer(&b[0:SizeofVfVlan][0])) | ||||
| } | ||||
|  | ||||
| func (msg *VfVlan) Serialize() []byte { | ||||
| 	return (*(*[SizeofVfVlan]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct ifla_vf_tx_rate { | ||||
| //   __u32 vf; | ||||
| //   __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ | ||||
| // }; | ||||
|  | ||||
| type VfTxRate struct { | ||||
| 	Vf   uint32 | ||||
| 	Rate uint32 | ||||
| } | ||||
|  | ||||
| func (msg *VfTxRate) Len() int { | ||||
| 	return SizeofVfTxRate | ||||
| } | ||||
|  | ||||
| func DeserializeVfTxRate(b []byte) *VfTxRate { | ||||
| 	return (*VfTxRate)(unsafe.Pointer(&b[0:SizeofVfTxRate][0])) | ||||
| } | ||||
|  | ||||
| func (msg *VfTxRate) Serialize() []byte { | ||||
| 	return (*(*[SizeofVfTxRate]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct ifla_vf_rate { | ||||
| //   __u32 vf; | ||||
| //   __u32 min_tx_rate; /* Min Bandwidth in Mbps */ | ||||
| //   __u32 max_tx_rate; /* Max Bandwidth in Mbps */ | ||||
| // }; | ||||
|  | ||||
| type VfRate struct { | ||||
| 	Vf        uint32 | ||||
| 	MinTxRate uint32 | ||||
| 	MaxTxRate uint32 | ||||
| } | ||||
|  | ||||
| func (msg *VfRate) Len() int { | ||||
| 	return SizeofVfRate | ||||
| } | ||||
|  | ||||
| func DeserializeVfRate(b []byte) *VfRate { | ||||
| 	return (*VfRate)(unsafe.Pointer(&b[0:SizeofVfRate][0])) | ||||
| } | ||||
|  | ||||
| func (msg *VfRate) Serialize() []byte { | ||||
| 	return (*(*[SizeofVfRate]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct ifla_vf_spoofchk { | ||||
| //   __u32 vf; | ||||
| //   __u32 setting; | ||||
| // }; | ||||
|  | ||||
| type VfSpoofchk struct { | ||||
| 	Vf      uint32 | ||||
| 	Setting uint32 | ||||
| } | ||||
|  | ||||
| func (msg *VfSpoofchk) Len() int { | ||||
| 	return SizeofVfSpoofchk | ||||
| } | ||||
|  | ||||
| func DeserializeVfSpoofchk(b []byte) *VfSpoofchk { | ||||
| 	return (*VfSpoofchk)(unsafe.Pointer(&b[0:SizeofVfSpoofchk][0])) | ||||
| } | ||||
|  | ||||
| func (msg *VfSpoofchk) Serialize() []byte { | ||||
| 	return (*(*[SizeofVfSpoofchk]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct ifla_vf_link_state { | ||||
| //   __u32 vf; | ||||
| //   __u32 link_state; | ||||
| // }; | ||||
|  | ||||
| type VfLinkState struct { | ||||
| 	Vf        uint32 | ||||
| 	LinkState uint32 | ||||
| } | ||||
|  | ||||
| func (msg *VfLinkState) Len() int { | ||||
| 	return SizeofVfLinkState | ||||
| } | ||||
|  | ||||
| func DeserializeVfLinkState(b []byte) *VfLinkState { | ||||
| 	return (*VfLinkState)(unsafe.Pointer(&b[0:SizeofVfLinkState][0])) | ||||
| } | ||||
|  | ||||
| func (msg *VfLinkState) Serialize() []byte { | ||||
| 	return (*(*[SizeofVfLinkState]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct ifla_vf_rss_query_en { | ||||
| //   __u32 vf; | ||||
| //   __u32 setting; | ||||
| // }; | ||||
|  | ||||
| type VfRssQueryEn struct { | ||||
| 	Vf      uint32 | ||||
| 	Setting uint32 | ||||
| } | ||||
|  | ||||
| func (msg *VfRssQueryEn) Len() int { | ||||
| 	return SizeofVfRssQueryEn | ||||
| } | ||||
|  | ||||
| func DeserializeVfRssQueryEn(b []byte) *VfRssQueryEn { | ||||
| 	return (*VfRssQueryEn)(unsafe.Pointer(&b[0:SizeofVfRssQueryEn][0])) | ||||
| } | ||||
|  | ||||
| func (msg *VfRssQueryEn) Serialize() []byte { | ||||
| 	return (*(*[SizeofVfRssQueryEn]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct ifla_vf_trust { | ||||
| //   __u32 vf; | ||||
| //   __u32 setting; | ||||
| // }; | ||||
|  | ||||
| type VfTrust struct { | ||||
| 	Vf      uint32 | ||||
| 	Setting uint32 | ||||
| } | ||||
|  | ||||
| func (msg *VfTrust) Len() int { | ||||
| 	return SizeofVfTrust | ||||
| } | ||||
|  | ||||
| func DeserializeVfTrust(b []byte) *VfTrust { | ||||
| 	return (*VfTrust)(unsafe.Pointer(&b[0:SizeofVfTrust][0])) | ||||
| } | ||||
|  | ||||
| func (msg *VfTrust) Serialize() []byte { | ||||
| 	return (*(*[SizeofVfTrust]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	XDP_FLAGS_UPDATE_IF_NOEXIST = 1 << iota | ||||
| 	XDP_FLAGS_SKB_MODE | ||||
| 	XDP_FLAGS_DRV_MODE | ||||
| 	XDP_FLAGS_MASK = XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE | ||||
| ) | ||||
|  | ||||
| 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_FLAGS    /* xdp prog related flags */ | ||||
| 	IFLA_XDP_PROG_ID  /* xdp prog id */ | ||||
| 	IFLA_XDP_MAX      = IFLA_XDP_PROG_ID | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_IPTUN_UNSPEC = iota | ||||
| 	IFLA_IPTUN_LINK | ||||
| 	IFLA_IPTUN_LOCAL | ||||
| 	IFLA_IPTUN_REMOTE | ||||
| 	IFLA_IPTUN_TTL | ||||
| 	IFLA_IPTUN_TOS | ||||
| 	IFLA_IPTUN_ENCAP_LIMIT | ||||
| 	IFLA_IPTUN_FLOWINFO | ||||
| 	IFLA_IPTUN_FLAGS | ||||
| 	IFLA_IPTUN_PROTO | ||||
| 	IFLA_IPTUN_PMTUDISC | ||||
| 	IFLA_IPTUN_6RD_PREFIX | ||||
| 	IFLA_IPTUN_6RD_RELAY_PREFIX | ||||
| 	IFLA_IPTUN_6RD_PREFIXLEN | ||||
| 	IFLA_IPTUN_6RD_RELAY_PREFIXLEN | ||||
| 	IFLA_IPTUN_ENCAP_TYPE | ||||
| 	IFLA_IPTUN_ENCAP_FLAGS | ||||
| 	IFLA_IPTUN_ENCAP_SPORT | ||||
| 	IFLA_IPTUN_ENCAP_DPORT | ||||
| 	IFLA_IPTUN_COLLECT_METADATA | ||||
| 	IFLA_IPTUN_MAX = IFLA_IPTUN_COLLECT_METADATA | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	IFLA_VTI_UNSPEC = iota | ||||
| 	IFLA_VTI_LINK | ||||
| 	IFLA_VTI_IKEY | ||||
| 	IFLA_VTI_OKEY | ||||
| 	IFLA_VTI_LOCAL | ||||
| 	IFLA_VTI_REMOTE | ||||
| 	IFLA_VTI_MAX = IFLA_VTI_REMOTE | ||||
| ) | ||||
|  | ||||
| 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 | ||||
| ) | ||||
							
								
								
									
										36
									
								
								vendor/github.com/vishvananda/netlink/nl/mpls_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/vishvananda/netlink/nl/mpls_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| package nl | ||||
|  | ||||
| import "encoding/binary" | ||||
|  | ||||
| const ( | ||||
| 	MPLS_LS_LABEL_SHIFT = 12 | ||||
| 	MPLS_LS_S_SHIFT     = 8 | ||||
| ) | ||||
|  | ||||
| func EncodeMPLSStack(labels ...int) []byte { | ||||
| 	b := make([]byte, 4*len(labels)) | ||||
| 	for idx, label := range labels { | ||||
| 		l := label << MPLS_LS_LABEL_SHIFT | ||||
| 		if idx == len(labels)-1 { | ||||
| 			l |= 1 << MPLS_LS_S_SHIFT | ||||
| 		} | ||||
| 		binary.BigEndian.PutUint32(b[idx*4:], uint32(l)) | ||||
| 	} | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| func DecodeMPLSStack(buf []byte) []int { | ||||
| 	if len(buf)%4 != 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	stack := make([]int, 0, len(buf)/4) | ||||
| 	for len(buf) > 0 { | ||||
| 		l := binary.BigEndian.Uint32(buf[:4]) | ||||
| 		buf = buf[4:] | ||||
| 		stack = append(stack, int(l)>>MPLS_LS_LABEL_SHIFT) | ||||
| 		if (l>>MPLS_LS_S_SHIFT)&1 > 0 { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	return stack | ||||
| } | ||||
							
								
								
									
										738
									
								
								vendor/github.com/vishvananda/netlink/nl/nl_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										738
									
								
								vendor/github.com/vishvananda/netlink/nl/nl_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,738 @@ | ||||
| // Package nl has low level primitives for making Netlink calls. | ||||
| package nl | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/binary" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"runtime" | ||||
| 	"sync" | ||||
| 	"sync/atomic" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/vishvananda/netns" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	// Family type definitions | ||||
| 	FAMILY_ALL  = unix.AF_UNSPEC | ||||
| 	FAMILY_V4   = unix.AF_INET | ||||
| 	FAMILY_V6   = unix.AF_INET6 | ||||
| 	FAMILY_MPLS = AF_MPLS | ||||
| ) | ||||
|  | ||||
| // SupportedNlFamilies contains the list of netlink families this netlink package supports | ||||
| var SupportedNlFamilies = []int{unix.NETLINK_ROUTE, unix.NETLINK_XFRM, unix.NETLINK_NETFILTER} | ||||
|  | ||||
| var nextSeqNr uint32 | ||||
|  | ||||
| // GetIPFamily returns the family type of a net.IP. | ||||
| func GetIPFamily(ip net.IP) int { | ||||
| 	if len(ip) <= net.IPv4len { | ||||
| 		return FAMILY_V4 | ||||
| 	} | ||||
| 	if ip.To4() != nil { | ||||
| 		return FAMILY_V4 | ||||
| 	} | ||||
| 	return FAMILY_V6 | ||||
| } | ||||
|  | ||||
| var nativeEndian binary.ByteOrder | ||||
|  | ||||
| // Get native endianness for the system | ||||
| func NativeEndian() binary.ByteOrder { | ||||
| 	if nativeEndian == nil { | ||||
| 		var x uint32 = 0x01020304 | ||||
| 		if *(*byte)(unsafe.Pointer(&x)) == 0x01 { | ||||
| 			nativeEndian = binary.BigEndian | ||||
| 		} else { | ||||
| 			nativeEndian = binary.LittleEndian | ||||
| 		} | ||||
| 	} | ||||
| 	return nativeEndian | ||||
| } | ||||
|  | ||||
| // Byte swap a 16 bit value if we aren't big endian | ||||
| func Swap16(i uint16) uint16 { | ||||
| 	if NativeEndian() == binary.BigEndian { | ||||
| 		return i | ||||
| 	} | ||||
| 	return (i&0xff00)>>8 | (i&0xff)<<8 | ||||
| } | ||||
|  | ||||
| // Byte swap a 32 bit value if aren't big endian | ||||
| func Swap32(i uint32) uint32 { | ||||
| 	if NativeEndian() == binary.BigEndian { | ||||
| 		return i | ||||
| 	} | ||||
| 	return (i&0xff000000)>>24 | (i&0xff0000)>>8 | (i&0xff00)<<8 | (i&0xff)<<24 | ||||
| } | ||||
|  | ||||
| type NetlinkRequestData interface { | ||||
| 	Len() int | ||||
| 	Serialize() []byte | ||||
| } | ||||
|  | ||||
| // IfInfomsg is related to links, but it is used for list requests as well | ||||
| type IfInfomsg struct { | ||||
| 	unix.IfInfomsg | ||||
| } | ||||
|  | ||||
| // Create an IfInfomsg with family specified | ||||
| func NewIfInfomsg(family int) *IfInfomsg { | ||||
| 	return &IfInfomsg{ | ||||
| 		IfInfomsg: unix.IfInfomsg{ | ||||
| 			Family: uint8(family), | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func DeserializeIfInfomsg(b []byte) *IfInfomsg { | ||||
| 	return (*IfInfomsg)(unsafe.Pointer(&b[0:unix.SizeofIfInfomsg][0])) | ||||
| } | ||||
|  | ||||
| func (msg *IfInfomsg) Serialize() []byte { | ||||
| 	return (*(*[unix.SizeofIfInfomsg]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| func (msg *IfInfomsg) Len() int { | ||||
| 	return unix.SizeofIfInfomsg | ||||
| } | ||||
|  | ||||
| func (msg *IfInfomsg) EncapType() string { | ||||
| 	switch msg.Type { | ||||
| 	case 0: | ||||
| 		return "generic" | ||||
| 	case unix.ARPHRD_ETHER: | ||||
| 		return "ether" | ||||
| 	case unix.ARPHRD_EETHER: | ||||
| 		return "eether" | ||||
| 	case unix.ARPHRD_AX25: | ||||
| 		return "ax25" | ||||
| 	case unix.ARPHRD_PRONET: | ||||
| 		return "pronet" | ||||
| 	case unix.ARPHRD_CHAOS: | ||||
| 		return "chaos" | ||||
| 	case unix.ARPHRD_IEEE802: | ||||
| 		return "ieee802" | ||||
| 	case unix.ARPHRD_ARCNET: | ||||
| 		return "arcnet" | ||||
| 	case unix.ARPHRD_APPLETLK: | ||||
| 		return "atalk" | ||||
| 	case unix.ARPHRD_DLCI: | ||||
| 		return "dlci" | ||||
| 	case unix.ARPHRD_ATM: | ||||
| 		return "atm" | ||||
| 	case unix.ARPHRD_METRICOM: | ||||
| 		return "metricom" | ||||
| 	case unix.ARPHRD_IEEE1394: | ||||
| 		return "ieee1394" | ||||
| 	case unix.ARPHRD_INFINIBAND: | ||||
| 		return "infiniband" | ||||
| 	case unix.ARPHRD_SLIP: | ||||
| 		return "slip" | ||||
| 	case unix.ARPHRD_CSLIP: | ||||
| 		return "cslip" | ||||
| 	case unix.ARPHRD_SLIP6: | ||||
| 		return "slip6" | ||||
| 	case unix.ARPHRD_CSLIP6: | ||||
| 		return "cslip6" | ||||
| 	case unix.ARPHRD_RSRVD: | ||||
| 		return "rsrvd" | ||||
| 	case unix.ARPHRD_ADAPT: | ||||
| 		return "adapt" | ||||
| 	case unix.ARPHRD_ROSE: | ||||
| 		return "rose" | ||||
| 	case unix.ARPHRD_X25: | ||||
| 		return "x25" | ||||
| 	case unix.ARPHRD_HWX25: | ||||
| 		return "hwx25" | ||||
| 	case unix.ARPHRD_PPP: | ||||
| 		return "ppp" | ||||
| 	case unix.ARPHRD_HDLC: | ||||
| 		return "hdlc" | ||||
| 	case unix.ARPHRD_LAPB: | ||||
| 		return "lapb" | ||||
| 	case unix.ARPHRD_DDCMP: | ||||
| 		return "ddcmp" | ||||
| 	case unix.ARPHRD_RAWHDLC: | ||||
| 		return "rawhdlc" | ||||
| 	case unix.ARPHRD_TUNNEL: | ||||
| 		return "ipip" | ||||
| 	case unix.ARPHRD_TUNNEL6: | ||||
| 		return "tunnel6" | ||||
| 	case unix.ARPHRD_FRAD: | ||||
| 		return "frad" | ||||
| 	case unix.ARPHRD_SKIP: | ||||
| 		return "skip" | ||||
| 	case unix.ARPHRD_LOOPBACK: | ||||
| 		return "loopback" | ||||
| 	case unix.ARPHRD_LOCALTLK: | ||||
| 		return "ltalk" | ||||
| 	case unix.ARPHRD_FDDI: | ||||
| 		return "fddi" | ||||
| 	case unix.ARPHRD_BIF: | ||||
| 		return "bif" | ||||
| 	case unix.ARPHRD_SIT: | ||||
| 		return "sit" | ||||
| 	case unix.ARPHRD_IPDDP: | ||||
| 		return "ip/ddp" | ||||
| 	case unix.ARPHRD_IPGRE: | ||||
| 		return "gre" | ||||
| 	case unix.ARPHRD_PIMREG: | ||||
| 		return "pimreg" | ||||
| 	case unix.ARPHRD_HIPPI: | ||||
| 		return "hippi" | ||||
| 	case unix.ARPHRD_ASH: | ||||
| 		return "ash" | ||||
| 	case unix.ARPHRD_ECONET: | ||||
| 		return "econet" | ||||
| 	case unix.ARPHRD_IRDA: | ||||
| 		return "irda" | ||||
| 	case unix.ARPHRD_FCPP: | ||||
| 		return "fcpp" | ||||
| 	case unix.ARPHRD_FCAL: | ||||
| 		return "fcal" | ||||
| 	case unix.ARPHRD_FCPL: | ||||
| 		return "fcpl" | ||||
| 	case unix.ARPHRD_FCFABRIC: | ||||
| 		return "fcfb0" | ||||
| 	case unix.ARPHRD_FCFABRIC + 1: | ||||
| 		return "fcfb1" | ||||
| 	case unix.ARPHRD_FCFABRIC + 2: | ||||
| 		return "fcfb2" | ||||
| 	case unix.ARPHRD_FCFABRIC + 3: | ||||
| 		return "fcfb3" | ||||
| 	case unix.ARPHRD_FCFABRIC + 4: | ||||
| 		return "fcfb4" | ||||
| 	case unix.ARPHRD_FCFABRIC + 5: | ||||
| 		return "fcfb5" | ||||
| 	case unix.ARPHRD_FCFABRIC + 6: | ||||
| 		return "fcfb6" | ||||
| 	case unix.ARPHRD_FCFABRIC + 7: | ||||
| 		return "fcfb7" | ||||
| 	case unix.ARPHRD_FCFABRIC + 8: | ||||
| 		return "fcfb8" | ||||
| 	case unix.ARPHRD_FCFABRIC + 9: | ||||
| 		return "fcfb9" | ||||
| 	case unix.ARPHRD_FCFABRIC + 10: | ||||
| 		return "fcfb10" | ||||
| 	case unix.ARPHRD_FCFABRIC + 11: | ||||
| 		return "fcfb11" | ||||
| 	case unix.ARPHRD_FCFABRIC + 12: | ||||
| 		return "fcfb12" | ||||
| 	case unix.ARPHRD_IEEE802_TR: | ||||
| 		return "tr" | ||||
| 	case unix.ARPHRD_IEEE80211: | ||||
| 		return "ieee802.11" | ||||
| 	case unix.ARPHRD_IEEE80211_PRISM: | ||||
| 		return "ieee802.11/prism" | ||||
| 	case unix.ARPHRD_IEEE80211_RADIOTAP: | ||||
| 		return "ieee802.11/radiotap" | ||||
| 	case unix.ARPHRD_IEEE802154: | ||||
| 		return "ieee802.15.4" | ||||
|  | ||||
| 	case 65534: | ||||
| 		return "none" | ||||
| 	case 65535: | ||||
| 		return "void" | ||||
| 	} | ||||
| 	return fmt.Sprintf("unknown%d", msg.Type) | ||||
| } | ||||
|  | ||||
| func rtaAlignOf(attrlen int) int { | ||||
| 	return (attrlen + unix.RTA_ALIGNTO - 1) & ^(unix.RTA_ALIGNTO - 1) | ||||
| } | ||||
|  | ||||
| func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg { | ||||
| 	msg := NewIfInfomsg(family) | ||||
| 	parent.children = append(parent.children, msg) | ||||
| 	return msg | ||||
| } | ||||
|  | ||||
| // Extend RtAttr to handle data and children | ||||
| type RtAttr struct { | ||||
| 	unix.RtAttr | ||||
| 	Data     []byte | ||||
| 	children []NetlinkRequestData | ||||
| } | ||||
|  | ||||
| // Create a new Extended RtAttr object | ||||
| func NewRtAttr(attrType int, data []byte) *RtAttr { | ||||
| 	return &RtAttr{ | ||||
| 		RtAttr: unix.RtAttr{ | ||||
| 			Type: uint16(attrType), | ||||
| 		}, | ||||
| 		children: []NetlinkRequestData{}, | ||||
| 		Data:     data, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Create a new RtAttr obj anc add it as a child of an existing object | ||||
| func NewRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr { | ||||
| 	attr := NewRtAttr(attrType, data) | ||||
| 	parent.children = append(parent.children, attr) | ||||
| 	return attr | ||||
| } | ||||
|  | ||||
| // AddChild adds an existing RtAttr as a child. | ||||
| func (a *RtAttr) AddChild(attr *RtAttr) { | ||||
| 	a.children = append(a.children, attr) | ||||
| } | ||||
|  | ||||
| func (a *RtAttr) Len() int { | ||||
| 	if len(a.children) == 0 { | ||||
| 		return (unix.SizeofRtAttr + len(a.Data)) | ||||
| 	} | ||||
|  | ||||
| 	l := 0 | ||||
| 	for _, child := range a.children { | ||||
| 		l += rtaAlignOf(child.Len()) | ||||
| 	} | ||||
| 	l += unix.SizeofRtAttr | ||||
| 	return rtaAlignOf(l + len(a.Data)) | ||||
| } | ||||
|  | ||||
| // Serialize the RtAttr into a byte array | ||||
| // This can't just unsafe.cast because it must iterate through children. | ||||
| func (a *RtAttr) Serialize() []byte { | ||||
| 	native := NativeEndian() | ||||
|  | ||||
| 	length := a.Len() | ||||
| 	buf := make([]byte, rtaAlignOf(length)) | ||||
|  | ||||
| 	next := 4 | ||||
| 	if a.Data != nil { | ||||
| 		copy(buf[next:], a.Data) | ||||
| 		next += rtaAlignOf(len(a.Data)) | ||||
| 	} | ||||
| 	if len(a.children) > 0 { | ||||
| 		for _, child := range a.children { | ||||
| 			childBuf := child.Serialize() | ||||
| 			copy(buf[next:], childBuf) | ||||
| 			next += rtaAlignOf(len(childBuf)) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if l := uint16(length); l != 0 { | ||||
| 		native.PutUint16(buf[0:2], l) | ||||
| 	} | ||||
| 	native.PutUint16(buf[2:4], a.Type) | ||||
| 	return buf | ||||
| } | ||||
|  | ||||
| type NetlinkRequest struct { | ||||
| 	unix.NlMsghdr | ||||
| 	Data    []NetlinkRequestData | ||||
| 	RawData []byte | ||||
| 	Sockets map[int]*SocketHandle | ||||
| } | ||||
|  | ||||
| // Serialize the Netlink Request into a byte array | ||||
| func (req *NetlinkRequest) Serialize() []byte { | ||||
| 	length := unix.SizeofNlMsghdr | ||||
| 	dataBytes := make([][]byte, len(req.Data)) | ||||
| 	for i, data := range req.Data { | ||||
| 		dataBytes[i] = data.Serialize() | ||||
| 		length = length + len(dataBytes[i]) | ||||
| 	} | ||||
| 	length += len(req.RawData) | ||||
|  | ||||
| 	req.Len = uint32(length) | ||||
| 	b := make([]byte, length) | ||||
| 	hdr := (*(*[unix.SizeofNlMsghdr]byte)(unsafe.Pointer(req)))[:] | ||||
| 	next := unix.SizeofNlMsghdr | ||||
| 	copy(b[0:next], hdr) | ||||
| 	for _, data := range dataBytes { | ||||
| 		for _, dataByte := range data { | ||||
| 			b[next] = dataByte | ||||
| 			next = next + 1 | ||||
| 		} | ||||
| 	} | ||||
| 	// Add the raw data if any | ||||
| 	if len(req.RawData) > 0 { | ||||
| 		copy(b[next:length], req.RawData) | ||||
| 	} | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| func (req *NetlinkRequest) AddData(data NetlinkRequestData) { | ||||
| 	if data != nil { | ||||
| 		req.Data = append(req.Data, data) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // 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. | ||||
| func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, error) { | ||||
| 	var ( | ||||
| 		s   *NetlinkSocket | ||||
| 		err error | ||||
| 	) | ||||
|  | ||||
| 	if req.Sockets != nil { | ||||
| 		if sh, ok := req.Sockets[sockType]; ok { | ||||
| 			s = sh.Socket | ||||
| 			req.Seq = atomic.AddUint32(&sh.Seq, 1) | ||||
| 		} | ||||
| 	} | ||||
| 	sharedSocket := s != nil | ||||
|  | ||||
| 	if s == nil { | ||||
| 		s, err = getNetlinkSocket(sockType) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		defer s.Close() | ||||
| 	} else { | ||||
| 		s.Lock() | ||||
| 		defer s.Unlock() | ||||
| 	} | ||||
|  | ||||
| 	if err := s.Send(req); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	pid, err := s.GetPid() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	var res [][]byte | ||||
|  | ||||
| done: | ||||
| 	for { | ||||
| 		msgs, err := s.Receive() | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		for _, m := range msgs { | ||||
| 			if m.Header.Seq != req.Seq { | ||||
| 				if sharedSocket { | ||||
| 					continue | ||||
| 				} | ||||
| 				return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq) | ||||
| 			} | ||||
| 			if m.Header.Pid != pid { | ||||
| 				return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid) | ||||
| 			} | ||||
| 			if m.Header.Type == unix.NLMSG_DONE { | ||||
| 				break done | ||||
| 			} | ||||
| 			if m.Header.Type == unix.NLMSG_ERROR { | ||||
| 				native := NativeEndian() | ||||
| 				error := int32(native.Uint32(m.Data[0:4])) | ||||
| 				if error == 0 { | ||||
| 					break done | ||||
| 				} | ||||
| 				return nil, syscall.Errno(-error) | ||||
| 			} | ||||
| 			if resType != 0 && m.Header.Type != resType { | ||||
| 				continue | ||||
| 			} | ||||
| 			res = append(res, m.Data) | ||||
| 			if m.Header.Flags&unix.NLM_F_MULTI == 0 { | ||||
| 				break done | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return res, nil | ||||
| } | ||||
|  | ||||
| // Create a new netlink request from proto and flags | ||||
| // Note the Len value will be inaccurate once data is added until | ||||
| // the message is serialized | ||||
| func NewNetlinkRequest(proto, flags int) *NetlinkRequest { | ||||
| 	return &NetlinkRequest{ | ||||
| 		NlMsghdr: unix.NlMsghdr{ | ||||
| 			Len:   uint32(unix.SizeofNlMsghdr), | ||||
| 			Type:  uint16(proto), | ||||
| 			Flags: unix.NLM_F_REQUEST | uint16(flags), | ||||
| 			Seq:   atomic.AddUint32(&nextSeqNr, 1), | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type NetlinkSocket struct { | ||||
| 	fd  int32 | ||||
| 	lsa unix.SockaddrNetlink | ||||
| 	sync.Mutex | ||||
| } | ||||
|  | ||||
| func getNetlinkSocket(protocol int) (*NetlinkSocket, error) { | ||||
| 	fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW|unix.SOCK_CLOEXEC, protocol) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	s := &NetlinkSocket{ | ||||
| 		fd: int32(fd), | ||||
| 	} | ||||
| 	s.lsa.Family = unix.AF_NETLINK | ||||
| 	if err := unix.Bind(fd, &s.lsa); err != nil { | ||||
| 		unix.Close(fd) | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return s, nil | ||||
| } | ||||
|  | ||||
| // GetNetlinkSocketAt opens a netlink socket in the network namespace newNs | ||||
| // and positions the thread back into the network namespace specified by curNs, | ||||
| // when done. If curNs is close, the function derives the current namespace and | ||||
| // moves back into it when done. If newNs is close, the socket will be opened | ||||
| // in the current network namespace. | ||||
| func GetNetlinkSocketAt(newNs, curNs netns.NsHandle, protocol int) (*NetlinkSocket, error) { | ||||
| 	c, err := executeInNetns(newNs, curNs) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer c() | ||||
| 	return getNetlinkSocket(protocol) | ||||
| } | ||||
|  | ||||
| // executeInNetns sets execution of the code following this call to the | ||||
| // network namespace newNs, then moves the thread back to curNs if open, | ||||
| // otherwise to the current netns at the time the function was invoked | ||||
| // In case of success, the caller is expected to execute the returned function | ||||
| // at the end of the code that needs to be executed in the network namespace. | ||||
| // Example: | ||||
| // func jobAt(...) error { | ||||
| //      d, err := executeInNetns(...) | ||||
| //      if err != nil { return err} | ||||
| //      defer d() | ||||
| //      < code which needs to be executed in specific netns> | ||||
| //  } | ||||
| // TODO: his function probably belongs to netns pkg. | ||||
| func executeInNetns(newNs, curNs netns.NsHandle) (func(), error) { | ||||
| 	var ( | ||||
| 		err       error | ||||
| 		moveBack  func(netns.NsHandle) error | ||||
| 		closeNs   func() error | ||||
| 		unlockThd func() | ||||
| 	) | ||||
| 	restore := func() { | ||||
| 		// order matters | ||||
| 		if moveBack != nil { | ||||
| 			moveBack(curNs) | ||||
| 		} | ||||
| 		if closeNs != nil { | ||||
| 			closeNs() | ||||
| 		} | ||||
| 		if unlockThd != nil { | ||||
| 			unlockThd() | ||||
| 		} | ||||
| 	} | ||||
| 	if newNs.IsOpen() { | ||||
| 		runtime.LockOSThread() | ||||
| 		unlockThd = runtime.UnlockOSThread | ||||
| 		if !curNs.IsOpen() { | ||||
| 			if curNs, err = netns.Get(); err != nil { | ||||
| 				restore() | ||||
| 				return nil, fmt.Errorf("could not get current namespace while creating netlink socket: %v", err) | ||||
| 			} | ||||
| 			closeNs = curNs.Close | ||||
| 		} | ||||
| 		if err := netns.Set(newNs); err != nil { | ||||
| 			restore() | ||||
| 			return nil, fmt.Errorf("failed to set into network namespace %d while creating netlink socket: %v", newNs, err) | ||||
| 		} | ||||
| 		moveBack = netns.Set | ||||
| 	} | ||||
| 	return restore, nil | ||||
| } | ||||
|  | ||||
| // Create a netlink socket with a given protocol (e.g. NETLINK_ROUTE) | ||||
| // and subscribe it to multicast groups passed in variable argument list. | ||||
| // Returns the netlink socket on which Receive() method can be called | ||||
| // to retrieve the messages from the kernel. | ||||
| func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) { | ||||
| 	fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW, protocol) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	s := &NetlinkSocket{ | ||||
| 		fd: int32(fd), | ||||
| 	} | ||||
| 	s.lsa.Family = unix.AF_NETLINK | ||||
|  | ||||
| 	for _, g := range groups { | ||||
| 		s.lsa.Groups |= (1 << (g - 1)) | ||||
| 	} | ||||
|  | ||||
| 	if err := unix.Bind(fd, &s.lsa); err != nil { | ||||
| 		unix.Close(fd) | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return s, nil | ||||
| } | ||||
|  | ||||
| // SubscribeAt works like Subscribe plus let's the caller choose the network | ||||
| // namespace in which the socket would be opened (newNs). Then control goes back | ||||
| // to curNs if open, otherwise to the netns at the time this function was called. | ||||
| func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*NetlinkSocket, error) { | ||||
| 	c, err := executeInNetns(newNs, curNs) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer c() | ||||
| 	return Subscribe(protocol, groups...) | ||||
| } | ||||
|  | ||||
| func (s *NetlinkSocket) Close() { | ||||
| 	fd := int(atomic.SwapInt32(&s.fd, -1)) | ||||
| 	unix.Close(fd) | ||||
| } | ||||
|  | ||||
| func (s *NetlinkSocket) GetFd() int { | ||||
| 	return int(atomic.LoadInt32(&s.fd)) | ||||
| } | ||||
|  | ||||
| func (s *NetlinkSocket) Send(request *NetlinkRequest) error { | ||||
| 	fd := int(atomic.LoadInt32(&s.fd)) | ||||
| 	if fd < 0 { | ||||
| 		return fmt.Errorf("Send called on a closed socket") | ||||
| 	} | ||||
| 	if err := unix.Sendto(fd, request.Serialize(), 0, &s.lsa); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) { | ||||
| 	fd := int(atomic.LoadInt32(&s.fd)) | ||||
| 	if fd < 0 { | ||||
| 		return nil, fmt.Errorf("Receive called on a closed socket") | ||||
| 	} | ||||
| 	rb := make([]byte, unix.Getpagesize()) | ||||
| 	nr, _, err := unix.Recvfrom(fd, rb, 0) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if nr < unix.NLMSG_HDRLEN { | ||||
| 		return nil, fmt.Errorf("Got short response from netlink") | ||||
| 	} | ||||
| 	rb = rb[:nr] | ||||
| 	return syscall.ParseNetlinkMessage(rb) | ||||
| } | ||||
|  | ||||
| // SetSendTimeout allows to set a send timeout on the socket | ||||
| func (s *NetlinkSocket) SetSendTimeout(timeout *unix.Timeval) error { | ||||
| 	// Set a send timeout of SOCKET_SEND_TIMEOUT, this will allow the Send to periodically unblock and avoid that a routine | ||||
| 	// remains stuck on a send on a closed fd | ||||
| 	return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_SNDTIMEO, timeout) | ||||
| } | ||||
|  | ||||
| // SetReceiveTimeout allows to set a receive timeout on the socket | ||||
| func (s *NetlinkSocket) SetReceiveTimeout(timeout *unix.Timeval) error { | ||||
| 	// Set a read timeout of SOCKET_READ_TIMEOUT, this will allow the Read to periodically unblock and avoid that a routine | ||||
| 	// remains stuck on a recvmsg on a closed fd | ||||
| 	return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_RCVTIMEO, timeout) | ||||
| } | ||||
|  | ||||
| func (s *NetlinkSocket) GetPid() (uint32, error) { | ||||
| 	fd := int(atomic.LoadInt32(&s.fd)) | ||||
| 	lsa, err := unix.Getsockname(fd) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	switch v := lsa.(type) { | ||||
| 	case *unix.SockaddrNetlink: | ||||
| 		return v.Pid, nil | ||||
| 	} | ||||
| 	return 0, fmt.Errorf("Wrong socket type") | ||||
| } | ||||
|  | ||||
| func ZeroTerminated(s string) []byte { | ||||
| 	bytes := make([]byte, len(s)+1) | ||||
| 	for i := 0; i < len(s); i++ { | ||||
| 		bytes[i] = s[i] | ||||
| 	} | ||||
| 	bytes[len(s)] = 0 | ||||
| 	return bytes | ||||
| } | ||||
|  | ||||
| func NonZeroTerminated(s string) []byte { | ||||
| 	bytes := make([]byte, len(s)) | ||||
| 	for i := 0; i < len(s); i++ { | ||||
| 		bytes[i] = s[i] | ||||
| 	} | ||||
| 	return bytes | ||||
| } | ||||
|  | ||||
| func BytesToString(b []byte) string { | ||||
| 	n := bytes.Index(b, []byte{0}) | ||||
| 	return string(b[:n]) | ||||
| } | ||||
|  | ||||
| func Uint8Attr(v uint8) []byte { | ||||
| 	return []byte{byte(v)} | ||||
| } | ||||
|  | ||||
| func Uint16Attr(v uint16) []byte { | ||||
| 	native := NativeEndian() | ||||
| 	bytes := make([]byte, 2) | ||||
| 	native.PutUint16(bytes, v) | ||||
| 	return bytes | ||||
| } | ||||
|  | ||||
| func Uint32Attr(v uint32) []byte { | ||||
| 	native := NativeEndian() | ||||
| 	bytes := make([]byte, 4) | ||||
| 	native.PutUint32(bytes, v) | ||||
| 	return bytes | ||||
| } | ||||
|  | ||||
| func Uint64Attr(v uint64) []byte { | ||||
| 	native := NativeEndian() | ||||
| 	bytes := make([]byte, 8) | ||||
| 	native.PutUint64(bytes, v) | ||||
| 	return bytes | ||||
| } | ||||
|  | ||||
| func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) { | ||||
| 	var attrs []syscall.NetlinkRouteAttr | ||||
| 	for len(b) >= unix.SizeofRtAttr { | ||||
| 		a, vbuf, alen, err := netlinkRouteAttrAndValue(b) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		ra := syscall.NetlinkRouteAttr{Attr: syscall.RtAttr(*a), Value: vbuf[:int(a.Len)-unix.SizeofRtAttr]} | ||||
| 		attrs = append(attrs, ra) | ||||
| 		b = b[alen:] | ||||
| 	} | ||||
| 	return attrs, nil | ||||
| } | ||||
|  | ||||
| func netlinkRouteAttrAndValue(b []byte) (*unix.RtAttr, []byte, int, error) { | ||||
| 	a := (*unix.RtAttr)(unsafe.Pointer(&b[0])) | ||||
| 	if int(a.Len) < unix.SizeofRtAttr || int(a.Len) > len(b) { | ||||
| 		return nil, nil, 0, unix.EINVAL | ||||
| 	} | ||||
| 	return a, b[unix.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil | ||||
| } | ||||
|  | ||||
| // SocketHandle contains the netlink socket and the associated | ||||
| // sequence counter for a specific netlink family | ||||
| type SocketHandle struct { | ||||
| 	Seq    uint32 | ||||
| 	Socket *NetlinkSocket | ||||
| } | ||||
|  | ||||
| // Close closes the netlink socket | ||||
| func (sh *SocketHandle) Close() { | ||||
| 	if sh.Socket != nil { | ||||
| 		sh.Socket.Close() | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										11
									
								
								vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !linux | ||||
|  | ||||
| package nl | ||||
|  | ||||
| import "encoding/binary" | ||||
|  | ||||
| var SupportedNlFamilies = []int{} | ||||
|  | ||||
| func NativeEndian() binary.ByteOrder { | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										81
									
								
								vendor/github.com/vishvananda/netlink/nl/route_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								vendor/github.com/vishvananda/netlink/nl/route_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| package nl | ||||
|  | ||||
| import ( | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| type RtMsg struct { | ||||
| 	unix.RtMsg | ||||
| } | ||||
|  | ||||
| func NewRtMsg() *RtMsg { | ||||
| 	return &RtMsg{ | ||||
| 		RtMsg: unix.RtMsg{ | ||||
| 			Table:    unix.RT_TABLE_MAIN, | ||||
| 			Scope:    unix.RT_SCOPE_UNIVERSE, | ||||
| 			Protocol: unix.RTPROT_BOOT, | ||||
| 			Type:     unix.RTN_UNICAST, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func NewRtDelMsg() *RtMsg { | ||||
| 	return &RtMsg{ | ||||
| 		RtMsg: unix.RtMsg{ | ||||
| 			Table: unix.RT_TABLE_MAIN, | ||||
| 			Scope: unix.RT_SCOPE_NOWHERE, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (msg *RtMsg) Len() int { | ||||
| 	return unix.SizeofRtMsg | ||||
| } | ||||
|  | ||||
| func DeserializeRtMsg(b []byte) *RtMsg { | ||||
| 	return (*RtMsg)(unsafe.Pointer(&b[0:unix.SizeofRtMsg][0])) | ||||
| } | ||||
|  | ||||
| func (msg *RtMsg) Serialize() []byte { | ||||
| 	return (*(*[unix.SizeofRtMsg]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| type RtNexthop struct { | ||||
| 	unix.RtNexthop | ||||
| 	Children []NetlinkRequestData | ||||
| } | ||||
|  | ||||
| func DeserializeRtNexthop(b []byte) *RtNexthop { | ||||
| 	return (*RtNexthop)(unsafe.Pointer(&b[0:unix.SizeofRtNexthop][0])) | ||||
| } | ||||
|  | ||||
| func (msg *RtNexthop) Len() int { | ||||
| 	if len(msg.Children) == 0 { | ||||
| 		return unix.SizeofRtNexthop | ||||
| 	} | ||||
|  | ||||
| 	l := 0 | ||||
| 	for _, child := range msg.Children { | ||||
| 		l += rtaAlignOf(child.Len()) | ||||
| 	} | ||||
| 	l += unix.SizeofRtNexthop | ||||
| 	return rtaAlignOf(l) | ||||
| } | ||||
|  | ||||
| func (msg *RtNexthop) Serialize() []byte { | ||||
| 	length := msg.Len() | ||||
| 	msg.RtNexthop.Len = uint16(length) | ||||
| 	buf := make([]byte, length) | ||||
| 	copy(buf, (*(*[unix.SizeofRtNexthop]byte)(unsafe.Pointer(msg)))[:]) | ||||
| 	next := rtaAlignOf(unix.SizeofRtNexthop) | ||||
| 	if len(msg.Children) > 0 { | ||||
| 		for _, child := range msg.Children { | ||||
| 			childBuf := child.Serialize() | ||||
| 			copy(buf[next:], childBuf) | ||||
| 			next += rtaAlignOf(len(childBuf)) | ||||
| 		} | ||||
| 	} | ||||
| 	return buf | ||||
| } | ||||
							
								
								
									
										111
									
								
								vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| package nl | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| ) | ||||
|  | ||||
| type IPv6SrHdr struct { | ||||
| 	nextHdr      uint8 | ||||
| 	hdrLen       uint8 | ||||
| 	routingType  uint8 | ||||
| 	segmentsLeft uint8 | ||||
| 	firstSegment uint8 | ||||
| 	flags        uint8 | ||||
| 	reserved     uint16 | ||||
|  | ||||
| 	Segments []net.IP | ||||
| } | ||||
|  | ||||
| func (s1 *IPv6SrHdr) Equal(s2 IPv6SrHdr) bool { | ||||
| 	if len(s1.Segments) != len(s2.Segments) { | ||||
| 		return false | ||||
| 	} | ||||
| 	for i := range s1.Segments { | ||||
| 		if s1.Segments[i].Equal(s2.Segments[i]) != true { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	return s1.nextHdr == s2.nextHdr && | ||||
| 		s1.hdrLen == s2.hdrLen && | ||||
| 		s1.routingType == s2.routingType && | ||||
| 		s1.segmentsLeft == s2.segmentsLeft && | ||||
| 		s1.firstSegment == s2.firstSegment && | ||||
| 		s1.flags == s2.flags | ||||
| 	// reserved doesn't need to be identical. | ||||
| } | ||||
|  | ||||
| // seg6 encap mode | ||||
| const ( | ||||
| 	SEG6_IPTUN_MODE_INLINE = iota | ||||
| 	SEG6_IPTUN_MODE_ENCAP | ||||
| ) | ||||
|  | ||||
| // number of nested RTATTR | ||||
| // from include/uapi/linux/seg6_iptunnel.h | ||||
| const ( | ||||
| 	SEG6_IPTUNNEL_UNSPEC = iota | ||||
| 	SEG6_IPTUNNEL_SRH | ||||
| 	__SEG6_IPTUNNEL_MAX | ||||
| ) | ||||
| const ( | ||||
| 	SEG6_IPTUNNEL_MAX = __SEG6_IPTUNNEL_MAX - 1 | ||||
| ) | ||||
|  | ||||
| func EncodeSEG6Encap(mode int, segments []net.IP) ([]byte, error) { | ||||
| 	nsegs := len(segments) // nsegs: number of segments | ||||
| 	if nsegs == 0 { | ||||
| 		return nil, errors.New("EncodeSEG6Encap: No Segment in srh") | ||||
| 	} | ||||
| 	b := make([]byte, 12, 12+len(segments)*16) | ||||
| 	native := NativeEndian() | ||||
| 	native.PutUint32(b, uint32(mode)) | ||||
| 	b[4] = 0                      // srh.nextHdr (0 when calling netlink) | ||||
| 	b[5] = uint8(16 * nsegs >> 3) // srh.hdrLen (in 8-octets unit) | ||||
| 	b[6] = IPV6_SRCRT_TYPE_4      // srh.routingType (assigned by IANA) | ||||
| 	b[7] = uint8(nsegs - 1)       // srh.segmentsLeft | ||||
| 	b[8] = uint8(nsegs - 1)       // srh.firstSegment | ||||
| 	b[9] = 0                      // srh.flags (SR6_FLAG1_HMAC for srh_hmac) | ||||
| 	// srh.reserved: Defined as "Tag" in draft-ietf-6man-segment-routing-header-07 | ||||
| 	native.PutUint16(b[10:], 0) // srh.reserved | ||||
| 	for _, netIP := range segments { | ||||
| 		b = append(b, netIP...) // srh.Segments | ||||
| 	} | ||||
| 	return b, nil | ||||
| } | ||||
|  | ||||
| func DecodeSEG6Encap(buf []byte) (int, []net.IP, error) { | ||||
| 	native := NativeEndian() | ||||
| 	mode := int(native.Uint32(buf)) | ||||
| 	srh := IPv6SrHdr{ | ||||
| 		nextHdr:      buf[4], | ||||
| 		hdrLen:       buf[5], | ||||
| 		routingType:  buf[6], | ||||
| 		segmentsLeft: buf[7], | ||||
| 		firstSegment: buf[8], | ||||
| 		flags:        buf[9], | ||||
| 		reserved:     native.Uint16(buf[10:12]), | ||||
| 	} | ||||
| 	buf = buf[12:] | ||||
| 	if len(buf)%16 != 0 { | ||||
| 		err := fmt.Errorf("DecodeSEG6Encap: error parsing Segment List (buf len: %d)\n", len(buf)) | ||||
| 		return mode, nil, err | ||||
| 	} | ||||
| 	for len(buf) > 0 { | ||||
| 		srh.Segments = append(srh.Segments, net.IP(buf[:16])) | ||||
| 		buf = buf[16:] | ||||
| 	} | ||||
| 	return mode, srh.Segments, nil | ||||
| } | ||||
|  | ||||
| // Helper functions | ||||
| func SEG6EncapModeString(mode int) string { | ||||
| 	switch mode { | ||||
| 	case SEG6_IPTUN_MODE_INLINE: | ||||
| 		return "inline" | ||||
| 	case SEG6_IPTUN_MODE_ENCAP: | ||||
| 		return "encap" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
							
								
								
									
										78
									
								
								vendor/github.com/vishvananda/netlink/nl/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								vendor/github.com/vishvananda/netlink/nl/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| package nl | ||||
|  | ||||
| // syscall package lack of rule atributes type. | ||||
| // Thus there are defined below | ||||
| const ( | ||||
| 	FRA_UNSPEC  = iota | ||||
| 	FRA_DST     /* destination address */ | ||||
| 	FRA_SRC     /* source address */ | ||||
| 	FRA_IIFNAME /* interface name */ | ||||
| 	FRA_GOTO    /* target to jump to (FR_ACT_GOTO) */ | ||||
| 	FRA_UNUSED2 | ||||
| 	FRA_PRIORITY /* priority/preference */ | ||||
| 	FRA_UNUSED3 | ||||
| 	FRA_UNUSED4 | ||||
| 	FRA_UNUSED5 | ||||
| 	FRA_FWMARK /* mark */ | ||||
| 	FRA_FLOW   /* flow/class id */ | ||||
| 	FRA_TUN_ID | ||||
| 	FRA_SUPPRESS_IFGROUP | ||||
| 	FRA_SUPPRESS_PREFIXLEN | ||||
| 	FRA_TABLE  /* Extended table id */ | ||||
| 	FRA_FWMASK /* mask for netfilter mark */ | ||||
| 	FRA_OIFNAME | ||||
| ) | ||||
|  | ||||
| // ip rule netlink request types | ||||
| const ( | ||||
| 	FR_ACT_UNSPEC = iota | ||||
| 	FR_ACT_TO_TBL /* Pass to fixed table */ | ||||
| 	FR_ACT_GOTO   /* Jump to another rule */ | ||||
| 	FR_ACT_NOP    /* No operation */ | ||||
| 	FR_ACT_RES3 | ||||
| 	FR_ACT_RES4 | ||||
| 	FR_ACT_BLACKHOLE   /* Drop without notification */ | ||||
| 	FR_ACT_UNREACHABLE /* Drop with ENETUNREACH */ | ||||
| 	FR_ACT_PROHIBIT    /* Drop with EACCES */ | ||||
| ) | ||||
|  | ||||
| // socket diags related | ||||
| const ( | ||||
| 	SOCK_DIAG_BY_FAMILY = 20         /* linux.sock_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 | ||||
| const ( | ||||
| 	MPLS_IPTUNNEL_UNSPEC = iota | ||||
| 	MPLS_IPTUNNEL_DST | ||||
| ) | ||||
|  | ||||
| // light weight tunnel encap types | ||||
| const ( | ||||
| 	LWTUNNEL_ENCAP_NONE = iota | ||||
| 	LWTUNNEL_ENCAP_MPLS | ||||
| 	LWTUNNEL_ENCAP_IP | ||||
| 	LWTUNNEL_ENCAP_ILA | ||||
| 	LWTUNNEL_ENCAP_IP6 | ||||
| 	LWTUNNEL_ENCAP_SEG6 | ||||
| 	LWTUNNEL_ENCAP_BPF | ||||
| ) | ||||
|  | ||||
| // routing header types | ||||
| const ( | ||||
| 	IPV6_SRCRT_STRICT = 0x01 // Deprecated; will be removed | ||||
| 	IPV6_SRCRT_TYPE_0 = 0    // Deprecated; will be removed | ||||
| 	IPV6_SRCRT_TYPE_2 = 2    // IPv6 type 2 Routing Header | ||||
| 	IPV6_SRCRT_TYPE_4 = 4    // Segment Routing with IPv6 | ||||
| ) | ||||
							
								
								
									
										710
									
								
								vendor/github.com/vishvananda/netlink/nl/tc_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										710
									
								
								vendor/github.com/vishvananda/netlink/nl/tc_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,710 @@ | ||||
| package nl | ||||
|  | ||||
| import ( | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| // LinkLayer | ||||
| const ( | ||||
| 	LINKLAYER_UNSPEC = iota | ||||
| 	LINKLAYER_ETHERNET | ||||
| 	LINKLAYER_ATM | ||||
| ) | ||||
|  | ||||
| // ATM | ||||
| const ( | ||||
| 	ATM_CELL_PAYLOAD = 48 | ||||
| 	ATM_CELL_SIZE    = 53 | ||||
| ) | ||||
|  | ||||
| const TC_LINKLAYER_MASK = 0x0F | ||||
|  | ||||
| // Police | ||||
| const ( | ||||
| 	TCA_POLICE_UNSPEC = iota | ||||
| 	TCA_POLICE_TBF | ||||
| 	TCA_POLICE_RATE | ||||
| 	TCA_POLICE_PEAKRATE | ||||
| 	TCA_POLICE_AVRATE | ||||
| 	TCA_POLICE_RESULT | ||||
| 	TCA_POLICE_MAX = TCA_POLICE_RESULT | ||||
| ) | ||||
|  | ||||
| // Message types | ||||
| const ( | ||||
| 	TCA_UNSPEC = iota | ||||
| 	TCA_KIND | ||||
| 	TCA_OPTIONS | ||||
| 	TCA_STATS | ||||
| 	TCA_XSTATS | ||||
| 	TCA_RATE | ||||
| 	TCA_FCNT | ||||
| 	TCA_STATS2 | ||||
| 	TCA_STAB | ||||
| 	TCA_MAX = TCA_STAB | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	TCA_ACT_TAB = 1 | ||||
| 	TCAA_MAX    = 1 | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	TCA_ACT_UNSPEC = iota | ||||
| 	TCA_ACT_KIND | ||||
| 	TCA_ACT_OPTIONS | ||||
| 	TCA_ACT_INDEX | ||||
| 	TCA_ACT_STATS | ||||
| 	TCA_ACT_MAX | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	TCA_PRIO_UNSPEC = iota | ||||
| 	TCA_PRIO_MQ | ||||
| 	TCA_PRIO_MAX = TCA_PRIO_MQ | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	SizeofTcMsg          = 0x14 | ||||
| 	SizeofTcActionMsg    = 0x04 | ||||
| 	SizeofTcPrioMap      = 0x14 | ||||
| 	SizeofTcRateSpec     = 0x0c | ||||
| 	SizeofTcNetemQopt    = 0x18 | ||||
| 	SizeofTcNetemCorr    = 0x0c | ||||
| 	SizeofTcNetemReorder = 0x08 | ||||
| 	SizeofTcNetemCorrupt = 0x08 | ||||
| 	SizeofTcTbfQopt      = 2*SizeofTcRateSpec + 0x0c | ||||
| 	SizeofTcHtbCopt      = 2*SizeofTcRateSpec + 0x14 | ||||
| 	SizeofTcHtbGlob      = 0x14 | ||||
| 	SizeofTcU32Key       = 0x10 | ||||
| 	SizeofTcU32Sel       = 0x10 // without keys | ||||
| 	SizeofTcGen          = 0x14 | ||||
| 	SizeofTcMirred       = SizeofTcGen + 0x08 | ||||
| 	SizeofTcPolice       = 2*SizeofTcRateSpec + 0x20 | ||||
| ) | ||||
|  | ||||
| // struct tcmsg { | ||||
| //   unsigned char tcm_family; | ||||
| //   unsigned char tcm__pad1; | ||||
| //   unsigned short  tcm__pad2; | ||||
| //   int   tcm_ifindex; | ||||
| //   __u32   tcm_handle; | ||||
| //   __u32   tcm_parent; | ||||
| //   __u32   tcm_info; | ||||
| // }; | ||||
|  | ||||
| type TcMsg struct { | ||||
| 	Family  uint8 | ||||
| 	Pad     [3]byte | ||||
| 	Ifindex int32 | ||||
| 	Handle  uint32 | ||||
| 	Parent  uint32 | ||||
| 	Info    uint32 | ||||
| } | ||||
|  | ||||
| func (msg *TcMsg) Len() int { | ||||
| 	return SizeofTcMsg | ||||
| } | ||||
|  | ||||
| func DeserializeTcMsg(b []byte) *TcMsg { | ||||
| 	return (*TcMsg)(unsafe.Pointer(&b[0:SizeofTcMsg][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcMsg) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcMsg]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| // struct tcamsg { | ||||
| //   unsigned char tca_family; | ||||
| //   unsigned char tca__pad1; | ||||
| //   unsigned short  tca__pad2; | ||||
| // }; | ||||
|  | ||||
| type TcActionMsg struct { | ||||
| 	Family uint8 | ||||
| 	Pad    [3]byte | ||||
| } | ||||
|  | ||||
| func (msg *TcActionMsg) Len() int { | ||||
| 	return SizeofTcActionMsg | ||||
| } | ||||
|  | ||||
| func DeserializeTcActionMsg(b []byte) *TcActionMsg { | ||||
| 	return (*TcActionMsg)(unsafe.Pointer(&b[0:SizeofTcActionMsg][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcActionMsg) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcActionMsg]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	TC_PRIO_MAX = 15 | ||||
| ) | ||||
|  | ||||
| // struct tc_prio_qopt { | ||||
| // 	int bands;      /* Number of bands */ | ||||
| // 	__u8  priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */ | ||||
| // }; | ||||
|  | ||||
| type TcPrioMap struct { | ||||
| 	Bands   int32 | ||||
| 	Priomap [TC_PRIO_MAX + 1]uint8 | ||||
| } | ||||
|  | ||||
| func (msg *TcPrioMap) Len() int { | ||||
| 	return SizeofTcPrioMap | ||||
| } | ||||
|  | ||||
| func DeserializeTcPrioMap(b []byte) *TcPrioMap { | ||||
| 	return (*TcPrioMap)(unsafe.Pointer(&b[0:SizeofTcPrioMap][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcPrioMap) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcPrioMap]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	TCA_TBF_UNSPEC = iota | ||||
| 	TCA_TBF_PARMS | ||||
| 	TCA_TBF_RTAB | ||||
| 	TCA_TBF_PTAB | ||||
| 	TCA_TBF_RATE64 | ||||
| 	TCA_TBF_PRATE64 | ||||
| 	TCA_TBF_BURST | ||||
| 	TCA_TBF_PBURST | ||||
| 	TCA_TBF_MAX = TCA_TBF_PBURST | ||||
| ) | ||||
|  | ||||
| // struct tc_ratespec { | ||||
| //   unsigned char cell_log; | ||||
| //   __u8    linklayer; /* lower 4 bits */ | ||||
| //   unsigned short  overhead; | ||||
| //   short   cell_align; | ||||
| //   unsigned short  mpu; | ||||
| //   __u32   rate; | ||||
| // }; | ||||
|  | ||||
| type TcRateSpec struct { | ||||
| 	CellLog   uint8 | ||||
| 	Linklayer uint8 | ||||
| 	Overhead  uint16 | ||||
| 	CellAlign int16 | ||||
| 	Mpu       uint16 | ||||
| 	Rate      uint32 | ||||
| } | ||||
|  | ||||
| func (msg *TcRateSpec) Len() int { | ||||
| 	return SizeofTcRateSpec | ||||
| } | ||||
|  | ||||
| func DeserializeTcRateSpec(b []byte) *TcRateSpec { | ||||
| 	return (*TcRateSpec)(unsafe.Pointer(&b[0:SizeofTcRateSpec][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcRateSpec) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcRateSpec]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| /** | ||||
| * NETEM | ||||
|  */ | ||||
|  | ||||
| const ( | ||||
| 	TCA_NETEM_UNSPEC = iota | ||||
| 	TCA_NETEM_CORR | ||||
| 	TCA_NETEM_DELAY_DIST | ||||
| 	TCA_NETEM_REORDER | ||||
| 	TCA_NETEM_CORRUPT | ||||
| 	TCA_NETEM_LOSS | ||||
| 	TCA_NETEM_RATE | ||||
| 	TCA_NETEM_ECN | ||||
| 	TCA_NETEM_RATE64 | ||||
| 	TCA_NETEM_MAX = TCA_NETEM_RATE64 | ||||
| ) | ||||
|  | ||||
| // struct tc_netem_qopt { | ||||
| //	__u32	latency;	/* added delay (us) */ | ||||
| //	__u32   limit;		/* fifo limit (packets) */ | ||||
| //	__u32	loss;		/* random packet loss (0=none ~0=100%) */ | ||||
| //	__u32	gap;		/* re-ordering gap (0 for none) */ | ||||
| //	__u32   duplicate;	/* random packet dup  (0=none ~0=100%) */ | ||||
| // 	__u32	jitter;		/* random jitter in latency (us) */ | ||||
| // }; | ||||
|  | ||||
| type TcNetemQopt struct { | ||||
| 	Latency   uint32 | ||||
| 	Limit     uint32 | ||||
| 	Loss      uint32 | ||||
| 	Gap       uint32 | ||||
| 	Duplicate uint32 | ||||
| 	Jitter    uint32 | ||||
| } | ||||
|  | ||||
| func (msg *TcNetemQopt) Len() int { | ||||
| 	return SizeofTcNetemQopt | ||||
| } | ||||
|  | ||||
| func DeserializeTcNetemQopt(b []byte) *TcNetemQopt { | ||||
| 	return (*TcNetemQopt)(unsafe.Pointer(&b[0:SizeofTcNetemQopt][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcNetemQopt) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcNetemQopt]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| // struct tc_netem_corr { | ||||
| //  __u32   delay_corr; /* delay correlation */ | ||||
| //  __u32   loss_corr;  /* packet loss correlation */ | ||||
| //  __u32   dup_corr;   /* duplicate correlation  */ | ||||
| // }; | ||||
|  | ||||
| type TcNetemCorr struct { | ||||
| 	DelayCorr uint32 | ||||
| 	LossCorr  uint32 | ||||
| 	DupCorr   uint32 | ||||
| } | ||||
|  | ||||
| func (msg *TcNetemCorr) Len() int { | ||||
| 	return SizeofTcNetemCorr | ||||
| } | ||||
|  | ||||
| func DeserializeTcNetemCorr(b []byte) *TcNetemCorr { | ||||
| 	return (*TcNetemCorr)(unsafe.Pointer(&b[0:SizeofTcNetemCorr][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcNetemCorr) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcNetemCorr]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| // struct tc_netem_reorder { | ||||
| //  __u32   probability; | ||||
| //  __u32   correlation; | ||||
| // }; | ||||
|  | ||||
| type TcNetemReorder struct { | ||||
| 	Probability uint32 | ||||
| 	Correlation uint32 | ||||
| } | ||||
|  | ||||
| func (msg *TcNetemReorder) Len() int { | ||||
| 	return SizeofTcNetemReorder | ||||
| } | ||||
|  | ||||
| func DeserializeTcNetemReorder(b []byte) *TcNetemReorder { | ||||
| 	return (*TcNetemReorder)(unsafe.Pointer(&b[0:SizeofTcNetemReorder][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcNetemReorder) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcNetemReorder]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| // struct tc_netem_corrupt { | ||||
| //  __u32   probability; | ||||
| //  __u32   correlation; | ||||
| // }; | ||||
|  | ||||
| type TcNetemCorrupt struct { | ||||
| 	Probability uint32 | ||||
| 	Correlation uint32 | ||||
| } | ||||
|  | ||||
| func (msg *TcNetemCorrupt) Len() int { | ||||
| 	return SizeofTcNetemCorrupt | ||||
| } | ||||
|  | ||||
| func DeserializeTcNetemCorrupt(b []byte) *TcNetemCorrupt { | ||||
| 	return (*TcNetemCorrupt)(unsafe.Pointer(&b[0:SizeofTcNetemCorrupt][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcNetemCorrupt) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcNetemCorrupt]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| // struct tc_tbf_qopt { | ||||
| //   struct tc_ratespec rate; | ||||
| //   struct tc_ratespec peakrate; | ||||
| //   __u32   limit; | ||||
| //   __u32   buffer; | ||||
| //   __u32   mtu; | ||||
| // }; | ||||
|  | ||||
| type TcTbfQopt struct { | ||||
| 	Rate     TcRateSpec | ||||
| 	Peakrate TcRateSpec | ||||
| 	Limit    uint32 | ||||
| 	Buffer   uint32 | ||||
| 	Mtu      uint32 | ||||
| } | ||||
|  | ||||
| func (msg *TcTbfQopt) Len() int { | ||||
| 	return SizeofTcTbfQopt | ||||
| } | ||||
|  | ||||
| func DeserializeTcTbfQopt(b []byte) *TcTbfQopt { | ||||
| 	return (*TcTbfQopt)(unsafe.Pointer(&b[0:SizeofTcTbfQopt][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcTbfQopt) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcTbfQopt]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	TCA_HTB_UNSPEC = iota | ||||
| 	TCA_HTB_PARMS | ||||
| 	TCA_HTB_INIT | ||||
| 	TCA_HTB_CTAB | ||||
| 	TCA_HTB_RTAB | ||||
| 	TCA_HTB_DIRECT_QLEN | ||||
| 	TCA_HTB_RATE64 | ||||
| 	TCA_HTB_CEIL64 | ||||
| 	TCA_HTB_MAX = TCA_HTB_CEIL64 | ||||
| ) | ||||
|  | ||||
| //struct tc_htb_opt { | ||||
| //	struct tc_ratespec	rate; | ||||
| //	struct tc_ratespec	ceil; | ||||
| //	__u32	buffer; | ||||
| //	__u32	cbuffer; | ||||
| //	__u32	quantum; | ||||
| //	__u32	level;		/* out only */ | ||||
| //	__u32	prio; | ||||
| //}; | ||||
|  | ||||
| type TcHtbCopt struct { | ||||
| 	Rate    TcRateSpec | ||||
| 	Ceil    TcRateSpec | ||||
| 	Buffer  uint32 | ||||
| 	Cbuffer uint32 | ||||
| 	Quantum uint32 | ||||
| 	Level   uint32 | ||||
| 	Prio    uint32 | ||||
| } | ||||
|  | ||||
| func (msg *TcHtbCopt) Len() int { | ||||
| 	return SizeofTcHtbCopt | ||||
| } | ||||
|  | ||||
| func DeserializeTcHtbCopt(b []byte) *TcHtbCopt { | ||||
| 	return (*TcHtbCopt)(unsafe.Pointer(&b[0:SizeofTcHtbCopt][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcHtbCopt) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcHtbCopt]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| type TcHtbGlob struct { | ||||
| 	Version      uint32 | ||||
| 	Rate2Quantum uint32 | ||||
| 	Defcls       uint32 | ||||
| 	Debug        uint32 | ||||
| 	DirectPkts   uint32 | ||||
| } | ||||
|  | ||||
| func (msg *TcHtbGlob) Len() int { | ||||
| 	return SizeofTcHtbGlob | ||||
| } | ||||
|  | ||||
| func DeserializeTcHtbGlob(b []byte) *TcHtbGlob { | ||||
| 	return (*TcHtbGlob)(unsafe.Pointer(&b[0:SizeofTcHtbGlob][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcHtbGlob) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcHtbGlob]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	TCA_U32_UNSPEC = iota | ||||
| 	TCA_U32_CLASSID | ||||
| 	TCA_U32_HASH | ||||
| 	TCA_U32_LINK | ||||
| 	TCA_U32_DIVISOR | ||||
| 	TCA_U32_SEL | ||||
| 	TCA_U32_POLICE | ||||
| 	TCA_U32_ACT | ||||
| 	TCA_U32_INDEV | ||||
| 	TCA_U32_PCNT | ||||
| 	TCA_U32_MARK | ||||
| 	TCA_U32_MAX = TCA_U32_MARK | ||||
| ) | ||||
|  | ||||
| // struct tc_u32_key { | ||||
| //   __be32    mask; | ||||
| //   __be32    val; | ||||
| //   int   off; | ||||
| //   int   offmask; | ||||
| // }; | ||||
|  | ||||
| type TcU32Key struct { | ||||
| 	Mask    uint32 // big endian | ||||
| 	Val     uint32 // big endian | ||||
| 	Off     int32 | ||||
| 	OffMask int32 | ||||
| } | ||||
|  | ||||
| func (msg *TcU32Key) Len() int { | ||||
| 	return SizeofTcU32Key | ||||
| } | ||||
|  | ||||
| func DeserializeTcU32Key(b []byte) *TcU32Key { | ||||
| 	return (*TcU32Key)(unsafe.Pointer(&b[0:SizeofTcU32Key][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcU32Key) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcU32Key]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| // struct tc_u32_sel { | ||||
| //   unsigned char   flags; | ||||
| //   unsigned char   offshift; | ||||
| //   unsigned char   nkeys; | ||||
| // | ||||
| //   __be16      offmask; | ||||
| //   __u16     off; | ||||
| //   short     offoff; | ||||
| // | ||||
| //   short     hoff; | ||||
| //   __be32      hmask; | ||||
| //   struct tc_u32_key keys[0]; | ||||
| // }; | ||||
|  | ||||
| const ( | ||||
| 	TC_U32_TERMINAL  = 1 << iota | ||||
| 	TC_U32_OFFSET    = 1 << iota | ||||
| 	TC_U32_VAROFFSET = 1 << iota | ||||
| 	TC_U32_EAT       = 1 << iota | ||||
| ) | ||||
|  | ||||
| type TcU32Sel struct { | ||||
| 	Flags    uint8 | ||||
| 	Offshift uint8 | ||||
| 	Nkeys    uint8 | ||||
| 	Pad      uint8 | ||||
| 	Offmask  uint16 // big endian | ||||
| 	Off      uint16 | ||||
| 	Offoff   int16 | ||||
| 	Hoff     int16 | ||||
| 	Hmask    uint32 // big endian | ||||
| 	Keys     []TcU32Key | ||||
| } | ||||
|  | ||||
| func (msg *TcU32Sel) Len() int { | ||||
| 	return SizeofTcU32Sel + int(msg.Nkeys)*SizeofTcU32Key | ||||
| } | ||||
|  | ||||
| func DeserializeTcU32Sel(b []byte) *TcU32Sel { | ||||
| 	x := &TcU32Sel{} | ||||
| 	copy((*(*[SizeofTcU32Sel]byte)(unsafe.Pointer(x)))[:], b) | ||||
| 	next := SizeofTcU32Sel | ||||
| 	var i uint8 | ||||
| 	for i = 0; i < x.Nkeys; i++ { | ||||
| 		x.Keys = append(x.Keys, *DeserializeTcU32Key(b[next:])) | ||||
| 		next += SizeofTcU32Key | ||||
| 	} | ||||
| 	return x | ||||
| } | ||||
|  | ||||
| func (x *TcU32Sel) Serialize() []byte { | ||||
| 	// This can't just unsafe.cast because it must iterate through keys. | ||||
| 	buf := make([]byte, x.Len()) | ||||
| 	copy(buf, (*(*[SizeofTcU32Sel]byte)(unsafe.Pointer(x)))[:]) | ||||
| 	next := SizeofTcU32Sel | ||||
| 	for _, key := range x.Keys { | ||||
| 		keyBuf := key.Serialize() | ||||
| 		copy(buf[next:], keyBuf) | ||||
| 		next += SizeofTcU32Key | ||||
| 	} | ||||
| 	return buf | ||||
| } | ||||
|  | ||||
| type TcGen struct { | ||||
| 	Index   uint32 | ||||
| 	Capab   uint32 | ||||
| 	Action  int32 | ||||
| 	Refcnt  int32 | ||||
| 	Bindcnt int32 | ||||
| } | ||||
|  | ||||
| func (msg *TcGen) Len() int { | ||||
| 	return SizeofTcGen | ||||
| } | ||||
|  | ||||
| func DeserializeTcGen(b []byte) *TcGen { | ||||
| 	return (*TcGen)(unsafe.Pointer(&b[0:SizeofTcGen][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcGen) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcGen]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| // #define tc_gen \ | ||||
| //   __u32                 index; \ | ||||
| //   __u32                 capab; \ | ||||
| //   int                   action; \ | ||||
| //   int                   refcnt; \ | ||||
| //   int                   bindcnt | ||||
|  | ||||
| const ( | ||||
| 	TCA_ACT_GACT = 5 | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	TCA_GACT_UNSPEC = iota | ||||
| 	TCA_GACT_TM | ||||
| 	TCA_GACT_PARMS | ||||
| 	TCA_GACT_PROB | ||||
| 	TCA_GACT_MAX = TCA_GACT_PROB | ||||
| ) | ||||
|  | ||||
| type TcGact TcGen | ||||
|  | ||||
| const ( | ||||
| 	TCA_ACT_BPF = 13 | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	TCA_ACT_BPF_UNSPEC = iota | ||||
| 	TCA_ACT_BPF_TM | ||||
| 	TCA_ACT_BPF_PARMS | ||||
| 	TCA_ACT_BPF_OPS_LEN | ||||
| 	TCA_ACT_BPF_OPS | ||||
| 	TCA_ACT_BPF_FD | ||||
| 	TCA_ACT_BPF_NAME | ||||
| 	TCA_ACT_BPF_MAX = TCA_ACT_BPF_NAME | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	TCA_BPF_FLAG_ACT_DIRECT uint32 = 1 << iota | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	TCA_BPF_UNSPEC = iota | ||||
| 	TCA_BPF_ACT | ||||
| 	TCA_BPF_POLICE | ||||
| 	TCA_BPF_CLASSID | ||||
| 	TCA_BPF_OPS_LEN | ||||
| 	TCA_BPF_OPS | ||||
| 	TCA_BPF_FD | ||||
| 	TCA_BPF_NAME | ||||
| 	TCA_BPF_FLAGS | ||||
| 	TCA_BPF_MAX = TCA_BPF_FLAGS | ||||
| ) | ||||
|  | ||||
| type TcBpf TcGen | ||||
|  | ||||
| const ( | ||||
| 	TCA_ACT_MIRRED = 8 | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	TCA_MIRRED_UNSPEC = iota | ||||
| 	TCA_MIRRED_TM | ||||
| 	TCA_MIRRED_PARMS | ||||
| 	TCA_MIRRED_MAX = TCA_MIRRED_PARMS | ||||
| ) | ||||
|  | ||||
| // struct tc_mirred { | ||||
| // 	tc_gen; | ||||
| // 	int                     eaction;   /* one of IN/EGRESS_MIRROR/REDIR */ | ||||
| // 	__u32                   ifindex;  /* ifindex of egress port */ | ||||
| // }; | ||||
|  | ||||
| type TcMirred struct { | ||||
| 	TcGen | ||||
| 	Eaction int32 | ||||
| 	Ifindex uint32 | ||||
| } | ||||
|  | ||||
| func (msg *TcMirred) Len() int { | ||||
| 	return SizeofTcMirred | ||||
| } | ||||
|  | ||||
| func DeserializeTcMirred(b []byte) *TcMirred { | ||||
| 	return (*TcMirred)(unsafe.Pointer(&b[0:SizeofTcMirred][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcMirred) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| // struct tc_police { | ||||
| // 	__u32			index; | ||||
| // 	int			action; | ||||
| // 	__u32			limit; | ||||
| // 	__u32			burst; | ||||
| // 	__u32			mtu; | ||||
| // 	struct tc_ratespec	rate; | ||||
| // 	struct tc_ratespec	peakrate; | ||||
| // 	int				refcnt; | ||||
| // 	int				bindcnt; | ||||
| // 	__u32			capab; | ||||
| // }; | ||||
|  | ||||
| type TcPolice struct { | ||||
| 	Index    uint32 | ||||
| 	Action   int32 | ||||
| 	Limit    uint32 | ||||
| 	Burst    uint32 | ||||
| 	Mtu      uint32 | ||||
| 	Rate     TcRateSpec | ||||
| 	PeakRate TcRateSpec | ||||
| 	Refcnt   int32 | ||||
| 	Bindcnt  int32 | ||||
| 	Capab    uint32 | ||||
| } | ||||
|  | ||||
| func (msg *TcPolice) Len() int { | ||||
| 	return SizeofTcPolice | ||||
| } | ||||
|  | ||||
| func DeserializeTcPolice(b []byte) *TcPolice { | ||||
| 	return (*TcPolice)(unsafe.Pointer(&b[0:SizeofTcPolice][0])) | ||||
| } | ||||
|  | ||||
| func (x *TcPolice) Serialize() []byte { | ||||
| 	return (*(*[SizeofTcPolice]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	TCA_FW_UNSPEC = iota | ||||
| 	TCA_FW_CLASSID | ||||
| 	TCA_FW_POLICE | ||||
| 	TCA_FW_INDEV | ||||
| 	TCA_FW_ACT | ||||
| 	TCA_FW_MASK | ||||
| 	TCA_FW_MAX = TCA_FW_MASK | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	TCA_MATCHALL_UNSPEC = iota | ||||
| 	TCA_MATCHALL_CLASSID | ||||
| 	TCA_MATCHALL_ACT | ||||
| 	TCA_MATCHALL_FLAGS | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	TCA_FQ_UNSPEC             = iota | ||||
| 	TCA_FQ_PLIMIT             // limit of total number of packets in queue | ||||
| 	TCA_FQ_FLOW_PLIMIT        // limit of packets per flow | ||||
| 	TCA_FQ_QUANTUM            // RR quantum | ||||
| 	TCA_FQ_INITIAL_QUANTUM    // RR quantum for new flow | ||||
| 	TCA_FQ_RATE_ENABLE        // enable/disable rate limiting | ||||
| 	TCA_FQ_FLOW_DEFAULT_RATE  // obsolete do not use | ||||
| 	TCA_FQ_FLOW_MAX_RATE      // per flow max rate | ||||
| 	TCA_FQ_BUCKETS_LOG        // log2(number of buckets) | ||||
| 	TCA_FQ_FLOW_REFILL_DELAY  // flow credit refill delay in usec | ||||
| 	TCA_FQ_ORPHAN_MASK        // mask applied to orphaned skb hashes | ||||
| 	TCA_FQ_LOW_RATE_THRESHOLD // per packet delay under this rate | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	TCA_FQ_CODEL_UNSPEC = iota | ||||
| 	TCA_FQ_CODEL_TARGET | ||||
| 	TCA_FQ_CODEL_LIMIT | ||||
| 	TCA_FQ_CODEL_INTERVAL | ||||
| 	TCA_FQ_CODEL_ECN | ||||
| 	TCA_FQ_CODEL_FLOWS | ||||
| 	TCA_FQ_CODEL_QUANTUM | ||||
| 	TCA_FQ_CODEL_CE_THRESHOLD | ||||
| 	TCA_FQ_CODEL_DROP_BATCH_SIZE | ||||
| 	TCA_FQ_CODEL_MEMORY_LIMIT | ||||
| ) | ||||
							
								
								
									
										296
									
								
								vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										296
									
								
								vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,296 @@ | ||||
| package nl | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"net" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| // Infinity for packet and byte counts | ||||
| const ( | ||||
| 	XFRM_INF = ^uint64(0) | ||||
| ) | ||||
|  | ||||
| type XfrmMsgType uint8 | ||||
|  | ||||
| type XfrmMsg interface { | ||||
| 	Type() XfrmMsgType | ||||
| } | ||||
|  | ||||
| // Message Types | ||||
| const ( | ||||
| 	XFRM_MSG_BASE        XfrmMsgType = 0x10 | ||||
| 	XFRM_MSG_NEWSA                   = 0x10 | ||||
| 	XFRM_MSG_DELSA                   = 0x11 | ||||
| 	XFRM_MSG_GETSA                   = 0x12 | ||||
| 	XFRM_MSG_NEWPOLICY               = 0x13 | ||||
| 	XFRM_MSG_DELPOLICY               = 0x14 | ||||
| 	XFRM_MSG_GETPOLICY               = 0x15 | ||||
| 	XFRM_MSG_ALLOCSPI                = 0x16 | ||||
| 	XFRM_MSG_ACQUIRE                 = 0x17 | ||||
| 	XFRM_MSG_EXPIRE                  = 0x18 | ||||
| 	XFRM_MSG_UPDPOLICY               = 0x19 | ||||
| 	XFRM_MSG_UPDSA                   = 0x1a | ||||
| 	XFRM_MSG_POLEXPIRE               = 0x1b | ||||
| 	XFRM_MSG_FLUSHSA                 = 0x1c | ||||
| 	XFRM_MSG_FLUSHPOLICY             = 0x1d | ||||
| 	XFRM_MSG_NEWAE                   = 0x1e | ||||
| 	XFRM_MSG_GETAE                   = 0x1f | ||||
| 	XFRM_MSG_REPORT                  = 0x20 | ||||
| 	XFRM_MSG_MIGRATE                 = 0x21 | ||||
| 	XFRM_MSG_NEWSADINFO              = 0x22 | ||||
| 	XFRM_MSG_GETSADINFO              = 0x23 | ||||
| 	XFRM_MSG_NEWSPDINFO              = 0x24 | ||||
| 	XFRM_MSG_GETSPDINFO              = 0x25 | ||||
| 	XFRM_MSG_MAPPING                 = 0x26 | ||||
| 	XFRM_MSG_MAX                     = 0x26 | ||||
| 	XFRM_NR_MSGTYPES                 = 0x17 | ||||
| ) | ||||
|  | ||||
| // Attribute types | ||||
| const ( | ||||
| 	/* Netlink message attributes.  */ | ||||
| 	XFRMA_UNSPEC         = 0x00 | ||||
| 	XFRMA_ALG_AUTH       = 0x01 /* struct xfrm_algo */ | ||||
| 	XFRMA_ALG_CRYPT      = 0x02 /* struct xfrm_algo */ | ||||
| 	XFRMA_ALG_COMP       = 0x03 /* struct xfrm_algo */ | ||||
| 	XFRMA_ENCAP          = 0x04 /* struct xfrm_algo + struct xfrm_encap_tmpl */ | ||||
| 	XFRMA_TMPL           = 0x05 /* 1 or more struct xfrm_user_tmpl */ | ||||
| 	XFRMA_SA             = 0x06 /* struct xfrm_usersa_info  */ | ||||
| 	XFRMA_POLICY         = 0x07 /* struct xfrm_userpolicy_info */ | ||||
| 	XFRMA_SEC_CTX        = 0x08 /* struct xfrm_sec_ctx */ | ||||
| 	XFRMA_LTIME_VAL      = 0x09 | ||||
| 	XFRMA_REPLAY_VAL     = 0x0a | ||||
| 	XFRMA_REPLAY_THRESH  = 0x0b | ||||
| 	XFRMA_ETIMER_THRESH  = 0x0c | ||||
| 	XFRMA_SRCADDR        = 0x0d /* xfrm_address_t */ | ||||
| 	XFRMA_COADDR         = 0x0e /* xfrm_address_t */ | ||||
| 	XFRMA_LASTUSED       = 0x0f /* unsigned long  */ | ||||
| 	XFRMA_POLICY_TYPE    = 0x10 /* struct xfrm_userpolicy_type */ | ||||
| 	XFRMA_MIGRATE        = 0x11 | ||||
| 	XFRMA_ALG_AEAD       = 0x12 /* struct xfrm_algo_aead */ | ||||
| 	XFRMA_KMADDRESS      = 0x13 /* struct xfrm_user_kmaddress */ | ||||
| 	XFRMA_ALG_AUTH_TRUNC = 0x14 /* struct xfrm_algo_auth */ | ||||
| 	XFRMA_MARK           = 0x15 /* struct xfrm_mark */ | ||||
| 	XFRMA_TFCPAD         = 0x16 /* __u32 */ | ||||
| 	XFRMA_REPLAY_ESN_VAL = 0x17 /* struct xfrm_replay_esn */ | ||||
| 	XFRMA_SA_EXTRA_FLAGS = 0x18 /* __u32 */ | ||||
| 	XFRMA_MAX            = 0x18 | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	SizeofXfrmAddress     = 0x10 | ||||
| 	SizeofXfrmSelector    = 0x38 | ||||
| 	SizeofXfrmLifetimeCfg = 0x40 | ||||
| 	SizeofXfrmLifetimeCur = 0x20 | ||||
| 	SizeofXfrmId          = 0x18 | ||||
| 	SizeofXfrmMark        = 0x08 | ||||
| ) | ||||
|  | ||||
| // Netlink groups | ||||
| const ( | ||||
| 	XFRMNLGRP_NONE    = 0x0 | ||||
| 	XFRMNLGRP_ACQUIRE = 0x1 | ||||
| 	XFRMNLGRP_EXPIRE  = 0x2 | ||||
| 	XFRMNLGRP_SA      = 0x3 | ||||
| 	XFRMNLGRP_POLICY  = 0x4 | ||||
| 	XFRMNLGRP_AEVENTS = 0x5 | ||||
| 	XFRMNLGRP_REPORT  = 0x6 | ||||
| 	XFRMNLGRP_MIGRATE = 0x7 | ||||
| 	XFRMNLGRP_MAPPING = 0x8 | ||||
| 	__XFRMNLGRP_MAX   = 0x9 | ||||
| ) | ||||
|  | ||||
| // typedef union { | ||||
| //   __be32    a4; | ||||
| //   __be32    a6[4]; | ||||
| // } xfrm_address_t; | ||||
|  | ||||
| type XfrmAddress [SizeofXfrmAddress]byte | ||||
|  | ||||
| func (x *XfrmAddress) ToIP() net.IP { | ||||
| 	var empty = [12]byte{} | ||||
| 	ip := make(net.IP, net.IPv6len) | ||||
| 	if bytes.Equal(x[4:16], empty[:]) { | ||||
| 		ip[10] = 0xff | ||||
| 		ip[11] = 0xff | ||||
| 		copy(ip[12:16], x[0:4]) | ||||
| 	} else { | ||||
| 		copy(ip[:], x[:]) | ||||
| 	} | ||||
| 	return ip | ||||
| } | ||||
|  | ||||
| func (x *XfrmAddress) ToIPNet(prefixlen uint8) *net.IPNet { | ||||
| 	ip := x.ToIP() | ||||
| 	if GetIPFamily(ip) == FAMILY_V4 { | ||||
| 		return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 32)} | ||||
| 	} | ||||
| 	return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 128)} | ||||
| } | ||||
|  | ||||
| func (x *XfrmAddress) FromIP(ip net.IP) { | ||||
| 	var empty = [16]byte{} | ||||
| 	if len(ip) < net.IPv4len { | ||||
| 		copy(x[4:16], empty[:]) | ||||
| 	} else if GetIPFamily(ip) == FAMILY_V4 { | ||||
| 		copy(x[0:4], ip.To4()[0:4]) | ||||
| 		copy(x[4:16], empty[:12]) | ||||
| 	} else { | ||||
| 		copy(x[0:16], ip.To16()[0:16]) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmAddress(b []byte) *XfrmAddress { | ||||
| 	return (*XfrmAddress)(unsafe.Pointer(&b[0:SizeofXfrmAddress][0])) | ||||
| } | ||||
|  | ||||
| func (x *XfrmAddress) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmAddress]byte)(unsafe.Pointer(x)))[:] | ||||
| } | ||||
|  | ||||
| // struct xfrm_selector { | ||||
| //   xfrm_address_t  daddr; | ||||
| //   xfrm_address_t  saddr; | ||||
| //   __be16  dport; | ||||
| //   __be16  dport_mask; | ||||
| //   __be16  sport; | ||||
| //   __be16  sport_mask; | ||||
| //   __u16 family; | ||||
| //   __u8  prefixlen_d; | ||||
| //   __u8  prefixlen_s; | ||||
| //   __u8  proto; | ||||
| //   int ifindex; | ||||
| //   __kernel_uid32_t  user; | ||||
| // }; | ||||
|  | ||||
| type XfrmSelector struct { | ||||
| 	Daddr      XfrmAddress | ||||
| 	Saddr      XfrmAddress | ||||
| 	Dport      uint16 // big endian | ||||
| 	DportMask  uint16 // big endian | ||||
| 	Sport      uint16 // big endian | ||||
| 	SportMask  uint16 // big endian | ||||
| 	Family     uint16 | ||||
| 	PrefixlenD uint8 | ||||
| 	PrefixlenS uint8 | ||||
| 	Proto      uint8 | ||||
| 	Pad        [3]byte | ||||
| 	Ifindex    int32 | ||||
| 	User       uint32 | ||||
| } | ||||
|  | ||||
| func (msg *XfrmSelector) Len() int { | ||||
| 	return SizeofXfrmSelector | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmSelector(b []byte) *XfrmSelector { | ||||
| 	return (*XfrmSelector)(unsafe.Pointer(&b[0:SizeofXfrmSelector][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmSelector) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmSelector]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct xfrm_lifetime_cfg { | ||||
| //   __u64 soft_byte_limit; | ||||
| //   __u64 hard_byte_limit; | ||||
| //   __u64 soft_packet_limit; | ||||
| //   __u64 hard_packet_limit; | ||||
| //   __u64 soft_add_expires_seconds; | ||||
| //   __u64 hard_add_expires_seconds; | ||||
| //   __u64 soft_use_expires_seconds; | ||||
| //   __u64 hard_use_expires_seconds; | ||||
| // }; | ||||
| // | ||||
|  | ||||
| type XfrmLifetimeCfg struct { | ||||
| 	SoftByteLimit         uint64 | ||||
| 	HardByteLimit         uint64 | ||||
| 	SoftPacketLimit       uint64 | ||||
| 	HardPacketLimit       uint64 | ||||
| 	SoftAddExpiresSeconds uint64 | ||||
| 	HardAddExpiresSeconds uint64 | ||||
| 	SoftUseExpiresSeconds uint64 | ||||
| 	HardUseExpiresSeconds uint64 | ||||
| } | ||||
|  | ||||
| func (msg *XfrmLifetimeCfg) Len() int { | ||||
| 	return SizeofXfrmLifetimeCfg | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmLifetimeCfg(b []byte) *XfrmLifetimeCfg { | ||||
| 	return (*XfrmLifetimeCfg)(unsafe.Pointer(&b[0:SizeofXfrmLifetimeCfg][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmLifetimeCfg) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmLifetimeCfg]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct xfrm_lifetime_cur { | ||||
| //   __u64 bytes; | ||||
| //   __u64 packets; | ||||
| //   __u64 add_time; | ||||
| //   __u64 use_time; | ||||
| // }; | ||||
|  | ||||
| type XfrmLifetimeCur struct { | ||||
| 	Bytes   uint64 | ||||
| 	Packets uint64 | ||||
| 	AddTime uint64 | ||||
| 	UseTime uint64 | ||||
| } | ||||
|  | ||||
| func (msg *XfrmLifetimeCur) Len() int { | ||||
| 	return SizeofXfrmLifetimeCur | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmLifetimeCur(b []byte) *XfrmLifetimeCur { | ||||
| 	return (*XfrmLifetimeCur)(unsafe.Pointer(&b[0:SizeofXfrmLifetimeCur][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmLifetimeCur) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmLifetimeCur]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct xfrm_id { | ||||
| //   xfrm_address_t  daddr; | ||||
| //   __be32    spi; | ||||
| //   __u8    proto; | ||||
| // }; | ||||
|  | ||||
| type XfrmId struct { | ||||
| 	Daddr XfrmAddress | ||||
| 	Spi   uint32 // big endian | ||||
| 	Proto uint8 | ||||
| 	Pad   [3]byte | ||||
| } | ||||
|  | ||||
| func (msg *XfrmId) Len() int { | ||||
| 	return SizeofXfrmId | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmId(b []byte) *XfrmId { | ||||
| 	return (*XfrmId)(unsafe.Pointer(&b[0:SizeofXfrmId][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmId) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmId]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| type XfrmMark struct { | ||||
| 	Value uint32 | ||||
| 	Mask  uint32 | ||||
| } | ||||
|  | ||||
| func (msg *XfrmMark) Len() int { | ||||
| 	return SizeofXfrmMark | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmMark(b []byte) *XfrmMark { | ||||
| 	return (*XfrmMark)(unsafe.Pointer(&b[0:SizeofXfrmMark][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmMark) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmMark]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
							
								
								
									
										32
									
								
								vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package nl | ||||
|  | ||||
| import ( | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	SizeofXfrmUserExpire = 0xe8 | ||||
| ) | ||||
|  | ||||
| // struct xfrm_user_expire { | ||||
| // 	struct xfrm_usersa_info		state; | ||||
| // 	__u8				hard; | ||||
| // }; | ||||
|  | ||||
| type XfrmUserExpire struct { | ||||
| 	XfrmUsersaInfo XfrmUsersaInfo | ||||
| 	Hard           uint8 | ||||
| 	Pad            [7]byte | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUserExpire) Len() int { | ||||
| 	return SizeofXfrmUserExpire | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmUserExpire(b []byte) *XfrmUserExpire { | ||||
| 	return (*XfrmUserExpire)(unsafe.Pointer(&b[0:SizeofXfrmUserExpire][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUserExpire) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmUserExpire]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
							
								
								
									
										119
									
								
								vendor/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								vendor/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | ||||
| package nl | ||||
|  | ||||
| import ( | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	SizeofXfrmUserpolicyId   = 0x40 | ||||
| 	SizeofXfrmUserpolicyInfo = 0xa8 | ||||
| 	SizeofXfrmUserTmpl       = 0x40 | ||||
| ) | ||||
|  | ||||
| // struct xfrm_userpolicy_id { | ||||
| //   struct xfrm_selector    sel; | ||||
| //   __u32       index; | ||||
| //   __u8        dir; | ||||
| // }; | ||||
| // | ||||
|  | ||||
| type XfrmUserpolicyId struct { | ||||
| 	Sel   XfrmSelector | ||||
| 	Index uint32 | ||||
| 	Dir   uint8 | ||||
| 	Pad   [3]byte | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUserpolicyId) Len() int { | ||||
| 	return SizeofXfrmUserpolicyId | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmUserpolicyId(b []byte) *XfrmUserpolicyId { | ||||
| 	return (*XfrmUserpolicyId)(unsafe.Pointer(&b[0:SizeofXfrmUserpolicyId][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUserpolicyId) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmUserpolicyId]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct xfrm_userpolicy_info { | ||||
| //   struct xfrm_selector    sel; | ||||
| //   struct xfrm_lifetime_cfg  lft; | ||||
| //   struct xfrm_lifetime_cur  curlft; | ||||
| //   __u32       priority; | ||||
| //   __u32       index; | ||||
| //   __u8        dir; | ||||
| //   __u8        action; | ||||
| // #define XFRM_POLICY_ALLOW 0 | ||||
| // #define XFRM_POLICY_BLOCK 1 | ||||
| //   __u8        flags; | ||||
| // #define XFRM_POLICY_LOCALOK 1 /* Allow user to override global policy */ | ||||
| //   /* Automatically expand selector to include matching ICMP payloads. */ | ||||
| // #define XFRM_POLICY_ICMP  2 | ||||
| //   __u8        share; | ||||
| // }; | ||||
|  | ||||
| type XfrmUserpolicyInfo struct { | ||||
| 	Sel      XfrmSelector | ||||
| 	Lft      XfrmLifetimeCfg | ||||
| 	Curlft   XfrmLifetimeCur | ||||
| 	Priority uint32 | ||||
| 	Index    uint32 | ||||
| 	Dir      uint8 | ||||
| 	Action   uint8 | ||||
| 	Flags    uint8 | ||||
| 	Share    uint8 | ||||
| 	Pad      [4]byte | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUserpolicyInfo) Len() int { | ||||
| 	return SizeofXfrmUserpolicyInfo | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmUserpolicyInfo(b []byte) *XfrmUserpolicyInfo { | ||||
| 	return (*XfrmUserpolicyInfo)(unsafe.Pointer(&b[0:SizeofXfrmUserpolicyInfo][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUserpolicyInfo) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmUserpolicyInfo]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct xfrm_user_tmpl { | ||||
| //   struct xfrm_id    id; | ||||
| //   __u16     family; | ||||
| //   xfrm_address_t    saddr; | ||||
| //   __u32     reqid; | ||||
| //   __u8      mode; | ||||
| //   __u8      share; | ||||
| //   __u8      optional; | ||||
| //   __u32     aalgos; | ||||
| //   __u32     ealgos; | ||||
| //   __u32     calgos; | ||||
| // } | ||||
|  | ||||
| type XfrmUserTmpl struct { | ||||
| 	XfrmId   XfrmId | ||||
| 	Family   uint16 | ||||
| 	Pad1     [2]byte | ||||
| 	Saddr    XfrmAddress | ||||
| 	Reqid    uint32 | ||||
| 	Mode     uint8 | ||||
| 	Share    uint8 | ||||
| 	Optional uint8 | ||||
| 	Pad2     byte | ||||
| 	Aalgos   uint32 | ||||
| 	Ealgos   uint32 | ||||
| 	Calgos   uint32 | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUserTmpl) Len() int { | ||||
| 	return SizeofXfrmUserTmpl | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmUserTmpl(b []byte) *XfrmUserTmpl { | ||||
| 	return (*XfrmUserTmpl)(unsafe.Pointer(&b[0:SizeofXfrmUserTmpl][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUserTmpl) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmUserTmpl]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
							
								
								
									
										334
									
								
								vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										334
									
								
								vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,334 @@ | ||||
| package nl | ||||
|  | ||||
| import ( | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	SizeofXfrmUsersaId       = 0x18 | ||||
| 	SizeofXfrmStats          = 0x0c | ||||
| 	SizeofXfrmUsersaInfo     = 0xe0 | ||||
| 	SizeofXfrmUserSpiInfo    = 0xe8 | ||||
| 	SizeofXfrmAlgo           = 0x44 | ||||
| 	SizeofXfrmAlgoAuth       = 0x48 | ||||
| 	SizeofXfrmAlgoAEAD       = 0x48 | ||||
| 	SizeofXfrmEncapTmpl      = 0x18 | ||||
| 	SizeofXfrmUsersaFlush    = 0x8 | ||||
| 	SizeofXfrmReplayStateEsn = 0x18 | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	XFRM_STATE_NOECN      = 1 | ||||
| 	XFRM_STATE_DECAP_DSCP = 2 | ||||
| 	XFRM_STATE_NOPMTUDISC = 4 | ||||
| 	XFRM_STATE_WILDRECV   = 8 | ||||
| 	XFRM_STATE_ICMP       = 16 | ||||
| 	XFRM_STATE_AF_UNSPEC  = 32 | ||||
| 	XFRM_STATE_ALIGN4     = 64 | ||||
| 	XFRM_STATE_ESN        = 128 | ||||
| ) | ||||
|  | ||||
| // struct xfrm_usersa_id { | ||||
| //   xfrm_address_t      daddr; | ||||
| //   __be32        spi; | ||||
| //   __u16       family; | ||||
| //   __u8        proto; | ||||
| // }; | ||||
|  | ||||
| type XfrmUsersaId struct { | ||||
| 	Daddr  XfrmAddress | ||||
| 	Spi    uint32 // big endian | ||||
| 	Family uint16 | ||||
| 	Proto  uint8 | ||||
| 	Pad    byte | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUsersaId) Len() int { | ||||
| 	return SizeofXfrmUsersaId | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmUsersaId(b []byte) *XfrmUsersaId { | ||||
| 	return (*XfrmUsersaId)(unsafe.Pointer(&b[0:SizeofXfrmUsersaId][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUsersaId) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmUsersaId]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct xfrm_stats { | ||||
| //   __u32 replay_window; | ||||
| //   __u32 replay; | ||||
| //   __u32 integrity_failed; | ||||
| // }; | ||||
|  | ||||
| type XfrmStats struct { | ||||
| 	ReplayWindow    uint32 | ||||
| 	Replay          uint32 | ||||
| 	IntegrityFailed uint32 | ||||
| } | ||||
|  | ||||
| func (msg *XfrmStats) Len() int { | ||||
| 	return SizeofXfrmStats | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmStats(b []byte) *XfrmStats { | ||||
| 	return (*XfrmStats)(unsafe.Pointer(&b[0:SizeofXfrmStats][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmStats) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmStats]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct xfrm_usersa_info { | ||||
| //   struct xfrm_selector    sel; | ||||
| //   struct xfrm_id      id; | ||||
| //   xfrm_address_t      saddr; | ||||
| //   struct xfrm_lifetime_cfg  lft; | ||||
| //   struct xfrm_lifetime_cur  curlft; | ||||
| //   struct xfrm_stats   stats; | ||||
| //   __u32       seq; | ||||
| //   __u32       reqid; | ||||
| //   __u16       family; | ||||
| //   __u8        mode;   /* XFRM_MODE_xxx */ | ||||
| //   __u8        replay_window; | ||||
| //   __u8        flags; | ||||
| // #define XFRM_STATE_NOECN  1 | ||||
| // #define XFRM_STATE_DECAP_DSCP 2 | ||||
| // #define XFRM_STATE_NOPMTUDISC 4 | ||||
| // #define XFRM_STATE_WILDRECV 8 | ||||
| // #define XFRM_STATE_ICMP   16 | ||||
| // #define XFRM_STATE_AF_UNSPEC  32 | ||||
| // #define XFRM_STATE_ALIGN4 64 | ||||
| // #define XFRM_STATE_ESN    128 | ||||
| // }; | ||||
| // | ||||
| // #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1 | ||||
| // | ||||
|  | ||||
| type XfrmUsersaInfo struct { | ||||
| 	Sel          XfrmSelector | ||||
| 	Id           XfrmId | ||||
| 	Saddr        XfrmAddress | ||||
| 	Lft          XfrmLifetimeCfg | ||||
| 	Curlft       XfrmLifetimeCur | ||||
| 	Stats        XfrmStats | ||||
| 	Seq          uint32 | ||||
| 	Reqid        uint32 | ||||
| 	Family       uint16 | ||||
| 	Mode         uint8 | ||||
| 	ReplayWindow uint8 | ||||
| 	Flags        uint8 | ||||
| 	Pad          [7]byte | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUsersaInfo) Len() int { | ||||
| 	return SizeofXfrmUsersaInfo | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmUsersaInfo(b []byte) *XfrmUsersaInfo { | ||||
| 	return (*XfrmUsersaInfo)(unsafe.Pointer(&b[0:SizeofXfrmUsersaInfo][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUsersaInfo) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmUsersaInfo]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct xfrm_userspi_info { | ||||
| // 	struct xfrm_usersa_info		info; | ||||
| // 	__u32				min; | ||||
| // 	__u32				max; | ||||
| // }; | ||||
|  | ||||
| type XfrmUserSpiInfo struct { | ||||
| 	XfrmUsersaInfo XfrmUsersaInfo | ||||
| 	Min            uint32 | ||||
| 	Max            uint32 | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUserSpiInfo) Len() int { | ||||
| 	return SizeofXfrmUserSpiInfo | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmUserSpiInfo(b []byte) *XfrmUserSpiInfo { | ||||
| 	return (*XfrmUserSpiInfo)(unsafe.Pointer(&b[0:SizeofXfrmUserSpiInfo][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUserSpiInfo) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmUserSpiInfo]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct xfrm_algo { | ||||
| //   char    alg_name[64]; | ||||
| //   unsigned int  alg_key_len;    /* in bits */ | ||||
| //   char    alg_key[0]; | ||||
| // }; | ||||
|  | ||||
| type XfrmAlgo struct { | ||||
| 	AlgName   [64]byte | ||||
| 	AlgKeyLen uint32 | ||||
| 	AlgKey    []byte | ||||
| } | ||||
|  | ||||
| func (msg *XfrmAlgo) Len() int { | ||||
| 	return SizeofXfrmAlgo + int(msg.AlgKeyLen/8) | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmAlgo(b []byte) *XfrmAlgo { | ||||
| 	ret := XfrmAlgo{} | ||||
| 	copy(ret.AlgName[:], b[0:64]) | ||||
| 	ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64])) | ||||
| 	ret.AlgKey = b[68:ret.Len()] | ||||
| 	return &ret | ||||
| } | ||||
|  | ||||
| func (msg *XfrmAlgo) Serialize() []byte { | ||||
| 	b := make([]byte, msg.Len()) | ||||
| 	copy(b[0:64], msg.AlgName[:]) | ||||
| 	copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:]) | ||||
| 	copy(b[68:msg.Len()], msg.AlgKey[:]) | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| // struct xfrm_algo_auth { | ||||
| //   char    alg_name[64]; | ||||
| //   unsigned int  alg_key_len;    /* in bits */ | ||||
| //   unsigned int  alg_trunc_len;  /* in bits */ | ||||
| //   char    alg_key[0]; | ||||
| // }; | ||||
|  | ||||
| type XfrmAlgoAuth struct { | ||||
| 	AlgName     [64]byte | ||||
| 	AlgKeyLen   uint32 | ||||
| 	AlgTruncLen uint32 | ||||
| 	AlgKey      []byte | ||||
| } | ||||
|  | ||||
| func (msg *XfrmAlgoAuth) Len() int { | ||||
| 	return SizeofXfrmAlgoAuth + int(msg.AlgKeyLen/8) | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmAlgoAuth(b []byte) *XfrmAlgoAuth { | ||||
| 	ret := XfrmAlgoAuth{} | ||||
| 	copy(ret.AlgName[:], b[0:64]) | ||||
| 	ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64])) | ||||
| 	ret.AlgTruncLen = *(*uint32)(unsafe.Pointer(&b[68])) | ||||
| 	ret.AlgKey = b[72:ret.Len()] | ||||
| 	return &ret | ||||
| } | ||||
|  | ||||
| func (msg *XfrmAlgoAuth) Serialize() []byte { | ||||
| 	b := make([]byte, msg.Len()) | ||||
| 	copy(b[0:64], msg.AlgName[:]) | ||||
| 	copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:]) | ||||
| 	copy(b[68:72], (*(*[4]byte)(unsafe.Pointer(&msg.AlgTruncLen)))[:]) | ||||
| 	copy(b[72:msg.Len()], msg.AlgKey[:]) | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| // struct xfrm_algo_aead { | ||||
| //   char    alg_name[64]; | ||||
| //   unsigned int  alg_key_len;  /* in bits */ | ||||
| //   unsigned int  alg_icv_len;  /* in bits */ | ||||
| //   char    alg_key[0]; | ||||
| // } | ||||
|  | ||||
| type XfrmAlgoAEAD struct { | ||||
| 	AlgName   [64]byte | ||||
| 	AlgKeyLen uint32 | ||||
| 	AlgICVLen uint32 | ||||
| 	AlgKey    []byte | ||||
| } | ||||
|  | ||||
| func (msg *XfrmAlgoAEAD) Len() int { | ||||
| 	return SizeofXfrmAlgoAEAD + int(msg.AlgKeyLen/8) | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmAlgoAEAD(b []byte) *XfrmAlgoAEAD { | ||||
| 	ret := XfrmAlgoAEAD{} | ||||
| 	copy(ret.AlgName[:], b[0:64]) | ||||
| 	ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64])) | ||||
| 	ret.AlgICVLen = *(*uint32)(unsafe.Pointer(&b[68])) | ||||
| 	ret.AlgKey = b[72:ret.Len()] | ||||
| 	return &ret | ||||
| } | ||||
|  | ||||
| func (msg *XfrmAlgoAEAD) Serialize() []byte { | ||||
| 	b := make([]byte, msg.Len()) | ||||
| 	copy(b[0:64], msg.AlgName[:]) | ||||
| 	copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:]) | ||||
| 	copy(b[68:72], (*(*[4]byte)(unsafe.Pointer(&msg.AlgICVLen)))[:]) | ||||
| 	copy(b[72:msg.Len()], msg.AlgKey[:]) | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| // struct xfrm_encap_tmpl { | ||||
| //   __u16   encap_type; | ||||
| //   __be16    encap_sport; | ||||
| //   __be16    encap_dport; | ||||
| //   xfrm_address_t  encap_oa; | ||||
| // }; | ||||
|  | ||||
| type XfrmEncapTmpl struct { | ||||
| 	EncapType  uint16 | ||||
| 	EncapSport uint16 // big endian | ||||
| 	EncapDport uint16 // big endian | ||||
| 	Pad        [2]byte | ||||
| 	EncapOa    XfrmAddress | ||||
| } | ||||
|  | ||||
| func (msg *XfrmEncapTmpl) Len() int { | ||||
| 	return SizeofXfrmEncapTmpl | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmEncapTmpl(b []byte) *XfrmEncapTmpl { | ||||
| 	return (*XfrmEncapTmpl)(unsafe.Pointer(&b[0:SizeofXfrmEncapTmpl][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmEncapTmpl) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmEncapTmpl]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct xfrm_usersa_flush { | ||||
| //    __u8 proto; | ||||
| // }; | ||||
|  | ||||
| type XfrmUsersaFlush struct { | ||||
| 	Proto uint8 | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUsersaFlush) Len() int { | ||||
| 	return SizeofXfrmUsersaFlush | ||||
| } | ||||
|  | ||||
| func DeserializeXfrmUsersaFlush(b []byte) *XfrmUsersaFlush { | ||||
| 	return (*XfrmUsersaFlush)(unsafe.Pointer(&b[0:SizeofXfrmUsersaFlush][0])) | ||||
| } | ||||
|  | ||||
| func (msg *XfrmUsersaFlush) Serialize() []byte { | ||||
| 	return (*(*[SizeofXfrmUsersaFlush]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
|  | ||||
| // struct xfrm_replay_state_esn { | ||||
| //     unsigned int    bmp_len; | ||||
| //     __u32           oseq; | ||||
| //     __u32           seq; | ||||
| //     __u32           oseq_hi; | ||||
| //     __u32           seq_hi; | ||||
| //     __u32           replay_window; | ||||
| //     __u32           bmp[0]; | ||||
| // }; | ||||
|  | ||||
| type XfrmReplayStateEsn struct { | ||||
| 	BmpLen       uint32 | ||||
| 	OSeq         uint32 | ||||
| 	Seq          uint32 | ||||
| 	OSeqHi       uint32 | ||||
| 	SeqHi        uint32 | ||||
| 	ReplayWindow uint32 | ||||
| 	Bmp          []uint32 | ||||
| } | ||||
|  | ||||
| func (msg *XfrmReplayStateEsn) Serialize() []byte { | ||||
| 	// We deliberately do not pass Bmp, as it gets set by the kernel. | ||||
| 	return (*(*[SizeofXfrmReplayStateEsn]byte)(unsafe.Pointer(msg)))[:] | ||||
| } | ||||
							
								
								
									
										32
									
								
								vendor/github.com/vishvananda/netlink/order.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/vishvananda/netlink/order.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"encoding/binary" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	native       = nl.NativeEndian() | ||||
| 	networkOrder = binary.BigEndian | ||||
| ) | ||||
|  | ||||
| func htonl(val uint32) []byte { | ||||
| 	bytes := make([]byte, 4) | ||||
| 	binary.BigEndian.PutUint32(bytes, val) | ||||
| 	return bytes | ||||
| } | ||||
|  | ||||
| func htons(val uint16) []byte { | ||||
| 	bytes := make([]byte, 2) | ||||
| 	binary.BigEndian.PutUint16(bytes, val) | ||||
| 	return bytes | ||||
| } | ||||
|  | ||||
| func ntohl(buf []byte) uint32 { | ||||
| 	return binary.BigEndian.Uint32(buf) | ||||
| } | ||||
|  | ||||
| func ntohs(buf []byte) uint16 { | ||||
| 	return binary.BigEndian.Uint16(buf) | ||||
| } | ||||
							
								
								
									
										58
									
								
								vendor/github.com/vishvananda/netlink/protinfo.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								vendor/github.com/vishvananda/netlink/protinfo.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // Protinfo represents bridge flags from netlink. | ||||
| type Protinfo struct { | ||||
| 	Hairpin      bool | ||||
| 	Guard        bool | ||||
| 	FastLeave    bool | ||||
| 	RootBlock    bool | ||||
| 	Learning     bool | ||||
| 	Flood        bool | ||||
| 	ProxyArp     bool | ||||
| 	ProxyArpWiFi bool | ||||
| } | ||||
|  | ||||
| // String returns a list of enabled flags | ||||
| func (prot *Protinfo) String() string { | ||||
| 	var boolStrings []string | ||||
| 	if prot.Hairpin { | ||||
| 		boolStrings = append(boolStrings, "Hairpin") | ||||
| 	} | ||||
| 	if prot.Guard { | ||||
| 		boolStrings = append(boolStrings, "Guard") | ||||
| 	} | ||||
| 	if prot.FastLeave { | ||||
| 		boolStrings = append(boolStrings, "FastLeave") | ||||
| 	} | ||||
| 	if prot.RootBlock { | ||||
| 		boolStrings = append(boolStrings, "RootBlock") | ||||
| 	} | ||||
| 	if prot.Learning { | ||||
| 		boolStrings = append(boolStrings, "Learning") | ||||
| 	} | ||||
| 	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, " ") | ||||
| } | ||||
|  | ||||
| func boolToByte(x bool) []byte { | ||||
| 	if x { | ||||
| 		return []byte{1} | ||||
| 	} | ||||
| 	return []byte{0} | ||||
| } | ||||
|  | ||||
| func byteToBool(x byte) bool { | ||||
| 	return uint8(x) != 0 | ||||
| } | ||||
							
								
								
									
										75
									
								
								vendor/github.com/vishvananda/netlink/protinfo_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								vendor/github.com/vishvananda/netlink/protinfo_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| func LinkGetProtinfo(link Link) (Protinfo, error) { | ||||
| 	return pkgHandle.LinkGetProtinfo(link) | ||||
| } | ||||
|  | ||||
| func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) { | ||||
| 	base := link.Attrs() | ||||
| 	h.ensureIndex(base) | ||||
| 	var pi Protinfo | ||||
| 	req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP) | ||||
| 	msg := nl.NewIfInfomsg(unix.AF_BRIDGE) | ||||
| 	req.AddData(msg) | ||||
| 	msgs, err := req.Execute(unix.NETLINK_ROUTE, 0) | ||||
| 	if err != nil { | ||||
| 		return pi, err | ||||
| 	} | ||||
|  | ||||
| 	for _, m := range msgs { | ||||
| 		ans := nl.DeserializeIfInfomsg(m) | ||||
| 		if int(ans.Index) != base.Index { | ||||
| 			continue | ||||
| 		} | ||||
| 		attrs, err := nl.ParseRouteAttr(m[ans.Len():]) | ||||
| 		if err != nil { | ||||
| 			return pi, err | ||||
| 		} | ||||
| 		for _, attr := range attrs { | ||||
| 			if attr.Attr.Type != unix.IFLA_PROTINFO|unix.NLA_F_NESTED { | ||||
| 				continue | ||||
| 			} | ||||
| 			infos, err := nl.ParseRouteAttr(attr.Value) | ||||
| 			if err != nil { | ||||
| 				return pi, err | ||||
| 			} | ||||
| 			pi = *parseProtinfo(infos) | ||||
|  | ||||
| 			return pi, nil | ||||
| 		} | ||||
| 	} | ||||
| 	return pi, fmt.Errorf("Device with index %d not found", base.Index) | ||||
| } | ||||
|  | ||||
| func parseProtinfo(infos []syscall.NetlinkRouteAttr) *Protinfo { | ||||
| 	var pi Protinfo | ||||
| 	for _, info := range infos { | ||||
| 		switch info.Attr.Type { | ||||
| 		case nl.IFLA_BRPORT_MODE: | ||||
| 			pi.Hairpin = byteToBool(info.Value[0]) | ||||
| 		case nl.IFLA_BRPORT_GUARD: | ||||
| 			pi.Guard = byteToBool(info.Value[0]) | ||||
| 		case nl.IFLA_BRPORT_FAST_LEAVE: | ||||
| 			pi.FastLeave = byteToBool(info.Value[0]) | ||||
| 		case nl.IFLA_BRPORT_PROTECT: | ||||
| 			pi.RootBlock = byteToBool(info.Value[0]) | ||||
| 		case nl.IFLA_BRPORT_LEARNING: | ||||
| 			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 | ||||
| } | ||||
							
								
								
									
										292
									
								
								vendor/github.com/vishvananda/netlink/qdisc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										292
									
								
								vendor/github.com/vishvananda/netlink/qdisc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,292 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"math" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	HANDLE_NONE      = 0 | ||||
| 	HANDLE_INGRESS   = 0xFFFFFFF1 | ||||
| 	HANDLE_CLSACT    = HANDLE_INGRESS | ||||
| 	HANDLE_ROOT      = 0xFFFFFFFF | ||||
| 	PRIORITY_MAP_LEN = 16 | ||||
| ) | ||||
| const ( | ||||
| 	HANDLE_MIN_INGRESS = 0xFFFFFFF2 | ||||
| 	HANDLE_MIN_EGRESS  = 0xFFFFFFF3 | ||||
| ) | ||||
|  | ||||
| type Qdisc interface { | ||||
| 	Attrs() *QdiscAttrs | ||||
| 	Type() string | ||||
| } | ||||
|  | ||||
| // QdiscAttrs represents a netlink qdisc. A qdisc is associated with a link, | ||||
| // has a handle, a parent and a refcnt. The root qdisc of a device should | ||||
| // have parent == HANDLE_ROOT. | ||||
| type QdiscAttrs struct { | ||||
| 	LinkIndex int | ||||
| 	Handle    uint32 | ||||
| 	Parent    uint32 | ||||
| 	Refcnt    uint32 // read only | ||||
| } | ||||
|  | ||||
| func (q QdiscAttrs) String() string { | ||||
| 	return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Refcnt: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Refcnt) | ||||
| } | ||||
|  | ||||
| func MakeHandle(major, minor uint16) uint32 { | ||||
| 	return (uint32(major) << 16) | uint32(minor) | ||||
| } | ||||
|  | ||||
| func MajorMinor(handle uint32) (uint16, uint16) { | ||||
| 	return uint16((handle & 0xFFFF0000) >> 16), uint16(handle & 0x0000FFFFF) | ||||
| } | ||||
|  | ||||
| func HandleStr(handle uint32) string { | ||||
| 	switch handle { | ||||
| 	case HANDLE_NONE: | ||||
| 		return "none" | ||||
| 	case HANDLE_INGRESS: | ||||
| 		return "ingress" | ||||
| 	case HANDLE_ROOT: | ||||
| 		return "root" | ||||
| 	default: | ||||
| 		major, minor := MajorMinor(handle) | ||||
| 		return fmt.Sprintf("%x:%x", major, minor) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func Percentage2u32(percentage float32) uint32 { | ||||
| 	// FIXME this is most likely not the best way to convert from % to uint32 | ||||
| 	if percentage == 100 { | ||||
| 		return math.MaxUint32 | ||||
| 	} | ||||
| 	return uint32(math.MaxUint32 * (percentage / 100)) | ||||
| } | ||||
|  | ||||
| // PfifoFast is the default qdisc created by the kernel if one has not | ||||
| // been defined for the interface | ||||
| type PfifoFast struct { | ||||
| 	QdiscAttrs | ||||
| 	Bands       uint8 | ||||
| 	PriorityMap [PRIORITY_MAP_LEN]uint8 | ||||
| } | ||||
|  | ||||
| func (qdisc *PfifoFast) Attrs() *QdiscAttrs { | ||||
| 	return &qdisc.QdiscAttrs | ||||
| } | ||||
|  | ||||
| func (qdisc *PfifoFast) Type() string { | ||||
| 	return "pfifo_fast" | ||||
| } | ||||
|  | ||||
| // Prio is a basic qdisc that works just like PfifoFast | ||||
| type Prio struct { | ||||
| 	QdiscAttrs | ||||
| 	Bands       uint8 | ||||
| 	PriorityMap [PRIORITY_MAP_LEN]uint8 | ||||
| } | ||||
|  | ||||
| func NewPrio(attrs QdiscAttrs) *Prio { | ||||
| 	return &Prio{ | ||||
| 		QdiscAttrs:  attrs, | ||||
| 		Bands:       3, | ||||
| 		PriorityMap: [PRIORITY_MAP_LEN]uint8{1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (qdisc *Prio) Attrs() *QdiscAttrs { | ||||
| 	return &qdisc.QdiscAttrs | ||||
| } | ||||
|  | ||||
| func (qdisc *Prio) Type() string { | ||||
| 	return "prio" | ||||
| } | ||||
|  | ||||
| // Htb is a classful qdisc that rate limits based on tokens | ||||
| type Htb struct { | ||||
| 	QdiscAttrs | ||||
| 	Version      uint32 | ||||
| 	Rate2Quantum uint32 | ||||
| 	Defcls       uint32 | ||||
| 	Debug        uint32 | ||||
| 	DirectPkts   uint32 | ||||
| } | ||||
|  | ||||
| func NewHtb(attrs QdiscAttrs) *Htb { | ||||
| 	return &Htb{ | ||||
| 		QdiscAttrs:   attrs, | ||||
| 		Version:      3, | ||||
| 		Defcls:       0, | ||||
| 		Rate2Quantum: 10, | ||||
| 		Debug:        0, | ||||
| 		DirectPkts:   0, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (qdisc *Htb) Attrs() *QdiscAttrs { | ||||
| 	return &qdisc.QdiscAttrs | ||||
| } | ||||
|  | ||||
| func (qdisc *Htb) Type() string { | ||||
| 	return "htb" | ||||
| } | ||||
|  | ||||
| // Netem is a classless qdisc that rate limits based on tokens | ||||
|  | ||||
| type NetemQdiscAttrs struct { | ||||
| 	Latency       uint32  // in us | ||||
| 	DelayCorr     float32 // in % | ||||
| 	Limit         uint32 | ||||
| 	Loss          float32 // in % | ||||
| 	LossCorr      float32 // in % | ||||
| 	Gap           uint32 | ||||
| 	Duplicate     float32 // in % | ||||
| 	DuplicateCorr float32 // in % | ||||
| 	Jitter        uint32  // in us | ||||
| 	ReorderProb   float32 // in % | ||||
| 	ReorderCorr   float32 // in % | ||||
| 	CorruptProb   float32 // in % | ||||
| 	CorruptCorr   float32 // in % | ||||
| } | ||||
|  | ||||
| func (q NetemQdiscAttrs) String() string { | ||||
| 	return fmt.Sprintf( | ||||
| 		"{Latency: %d, Limit: %d, Loss: %f, Gap: %d, Duplicate: %f, Jitter: %d}", | ||||
| 		q.Latency, q.Limit, q.Loss, q.Gap, q.Duplicate, q.Jitter, | ||||
| 	) | ||||
| } | ||||
|  | ||||
| type Netem struct { | ||||
| 	QdiscAttrs | ||||
| 	Latency       uint32 | ||||
| 	DelayCorr     uint32 | ||||
| 	Limit         uint32 | ||||
| 	Loss          uint32 | ||||
| 	LossCorr      uint32 | ||||
| 	Gap           uint32 | ||||
| 	Duplicate     uint32 | ||||
| 	DuplicateCorr uint32 | ||||
| 	Jitter        uint32 | ||||
| 	ReorderProb   uint32 | ||||
| 	ReorderCorr   uint32 | ||||
| 	CorruptProb   uint32 | ||||
| 	CorruptCorr   uint32 | ||||
| } | ||||
|  | ||||
| func (qdisc *Netem) Attrs() *QdiscAttrs { | ||||
| 	return &qdisc.QdiscAttrs | ||||
| } | ||||
|  | ||||
| func (qdisc *Netem) Type() string { | ||||
| 	return "netem" | ||||
| } | ||||
|  | ||||
| // Tbf is a classless qdisc that rate limits based on tokens | ||||
| type Tbf struct { | ||||
| 	QdiscAttrs | ||||
| 	Rate     uint64 | ||||
| 	Limit    uint32 | ||||
| 	Buffer   uint32 | ||||
| 	Peakrate uint64 | ||||
| 	Minburst uint32 | ||||
| 	// TODO: handle other settings | ||||
| } | ||||
|  | ||||
| func (qdisc *Tbf) Attrs() *QdiscAttrs { | ||||
| 	return &qdisc.QdiscAttrs | ||||
| } | ||||
|  | ||||
| func (qdisc *Tbf) Type() string { | ||||
| 	return "tbf" | ||||
| } | ||||
|  | ||||
| // Ingress is a qdisc for adding ingress filters | ||||
| type Ingress struct { | ||||
| 	QdiscAttrs | ||||
| } | ||||
|  | ||||
| func (qdisc *Ingress) Attrs() *QdiscAttrs { | ||||
| 	return &qdisc.QdiscAttrs | ||||
| } | ||||
|  | ||||
| func (qdisc *Ingress) Type() string { | ||||
| 	return "ingress" | ||||
| } | ||||
|  | ||||
| // GenericQdisc qdiscs represent types that are not currently understood | ||||
| // by this netlink library. | ||||
| type GenericQdisc struct { | ||||
| 	QdiscAttrs | ||||
| 	QdiscType string | ||||
| } | ||||
|  | ||||
| func (qdisc *GenericQdisc) Attrs() *QdiscAttrs { | ||||
| 	return &qdisc.QdiscAttrs | ||||
| } | ||||
|  | ||||
| func (qdisc *GenericQdisc) Type() string { | ||||
| 	return qdisc.QdiscType | ||||
| } | ||||
|  | ||||
| // Fq is a classless packet scheduler meant to be mostly used for locally generated traffic. | ||||
| type Fq struct { | ||||
| 	QdiscAttrs | ||||
| 	PacketLimit     uint32 | ||||
| 	FlowPacketLimit uint32 | ||||
| 	// In bytes | ||||
| 	Quantum        uint32 | ||||
| 	InitialQuantum uint32 | ||||
| 	// called RateEnable under the hood | ||||
| 	Pacing          uint32 | ||||
| 	FlowDefaultRate uint32 | ||||
| 	FlowMaxRate     uint32 | ||||
| 	// called BucketsLog under the hood | ||||
| 	Buckets          uint32 | ||||
| 	FlowRefillDelay  uint32 | ||||
| 	LowRateThreshold uint32 | ||||
| } | ||||
|  | ||||
| func NewFq(attrs QdiscAttrs) *Fq { | ||||
| 	return &Fq{ | ||||
| 		QdiscAttrs: attrs, | ||||
| 		Pacing:     1, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (qdisc *Fq) Attrs() *QdiscAttrs { | ||||
| 	return &qdisc.QdiscAttrs | ||||
| } | ||||
|  | ||||
| func (qdisc *Fq) Type() string { | ||||
| 	return "fq" | ||||
| } | ||||
|  | ||||
| // FQ_Codel (Fair Queuing Controlled Delay) is queuing discipline that combines Fair Queuing with the CoDel AQM scheme. | ||||
| type FqCodel struct { | ||||
| 	QdiscAttrs | ||||
| 	Target   uint32 | ||||
| 	Limit    uint32 | ||||
| 	Interval uint32 | ||||
| 	ECN      uint32 | ||||
| 	Flows    uint32 | ||||
| 	Quantum  uint32 | ||||
| 	// There are some more attributes here, but support for them seems not ubiquitous | ||||
| } | ||||
|  | ||||
| func NewFqCodel(attrs QdiscAttrs) *FqCodel { | ||||
| 	return &FqCodel{ | ||||
| 		QdiscAttrs: attrs, | ||||
| 		ECN:        1, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (qdisc *FqCodel) Attrs() *QdiscAttrs { | ||||
| 	return &qdisc.QdiscAttrs | ||||
| } | ||||
|  | ||||
| func (qdisc *FqCodel) Type() string { | ||||
| 	return "fq_codel" | ||||
| } | ||||
							
								
								
									
										647
									
								
								vendor/github.com/vishvananda/netlink/qdisc_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										647
									
								
								vendor/github.com/vishvananda/netlink/qdisc_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,647 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // NOTE function is here because it uses other linux functions | ||||
| func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem { | ||||
| 	var limit uint32 = 1000 | ||||
| 	var lossCorr, delayCorr, duplicateCorr uint32 | ||||
| 	var reorderProb, reorderCorr uint32 | ||||
| 	var corruptProb, corruptCorr uint32 | ||||
|  | ||||
| 	latency := nattrs.Latency | ||||
| 	loss := Percentage2u32(nattrs.Loss) | ||||
| 	gap := nattrs.Gap | ||||
| 	duplicate := Percentage2u32(nattrs.Duplicate) | ||||
| 	jitter := nattrs.Jitter | ||||
|  | ||||
| 	// Correlation | ||||
| 	if latency > 0 && jitter > 0 { | ||||
| 		delayCorr = Percentage2u32(nattrs.DelayCorr) | ||||
| 	} | ||||
| 	if loss > 0 { | ||||
| 		lossCorr = Percentage2u32(nattrs.LossCorr) | ||||
| 	} | ||||
| 	if duplicate > 0 { | ||||
| 		duplicateCorr = Percentage2u32(nattrs.DuplicateCorr) | ||||
| 	} | ||||
| 	// FIXME should validate values(like loss/duplicate are percentages...) | ||||
| 	latency = time2Tick(latency) | ||||
|  | ||||
| 	if nattrs.Limit != 0 { | ||||
| 		limit = nattrs.Limit | ||||
| 	} | ||||
| 	// Jitter is only value if latency is > 0 | ||||
| 	if latency > 0 { | ||||
| 		jitter = time2Tick(jitter) | ||||
| 	} | ||||
|  | ||||
| 	reorderProb = Percentage2u32(nattrs.ReorderProb) | ||||
| 	reorderCorr = Percentage2u32(nattrs.ReorderCorr) | ||||
|  | ||||
| 	if reorderProb > 0 { | ||||
| 		// ERROR if lantency == 0 | ||||
| 		if gap == 0 { | ||||
| 			gap = 1 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	corruptProb = Percentage2u32(nattrs.CorruptProb) | ||||
| 	corruptCorr = Percentage2u32(nattrs.CorruptCorr) | ||||
|  | ||||
| 	return &Netem{ | ||||
| 		QdiscAttrs:    attrs, | ||||
| 		Latency:       latency, | ||||
| 		DelayCorr:     delayCorr, | ||||
| 		Limit:         limit, | ||||
| 		Loss:          loss, | ||||
| 		LossCorr:      lossCorr, | ||||
| 		Gap:           gap, | ||||
| 		Duplicate:     duplicate, | ||||
| 		DuplicateCorr: duplicateCorr, | ||||
| 		Jitter:        jitter, | ||||
| 		ReorderProb:   reorderProb, | ||||
| 		ReorderCorr:   reorderCorr, | ||||
| 		CorruptProb:   corruptProb, | ||||
| 		CorruptCorr:   corruptCorr, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // QdiscDel will delete a qdisc from the system. | ||||
| // Equivalent to: `tc qdisc del $qdisc` | ||||
| func QdiscDel(qdisc Qdisc) error { | ||||
| 	return pkgHandle.QdiscDel(qdisc) | ||||
| } | ||||
|  | ||||
| // QdiscDel will delete a qdisc from the system. | ||||
| // Equivalent to: `tc qdisc del $qdisc` | ||||
| func (h *Handle) QdiscDel(qdisc Qdisc) error { | ||||
| 	return h.qdiscModify(unix.RTM_DELQDISC, 0, qdisc) | ||||
| } | ||||
|  | ||||
| // QdiscChange will change a qdisc in place | ||||
| // Equivalent to: `tc qdisc change $qdisc` | ||||
| // The parent and handle MUST NOT be changed. | ||||
| func QdiscChange(qdisc Qdisc) error { | ||||
| 	return pkgHandle.QdiscChange(qdisc) | ||||
| } | ||||
|  | ||||
| // QdiscChange will change a qdisc in place | ||||
| // Equivalent to: `tc qdisc change $qdisc` | ||||
| // The parent and handle MUST NOT be changed. | ||||
| func (h *Handle) QdiscChange(qdisc Qdisc) error { | ||||
| 	return h.qdiscModify(unix.RTM_NEWQDISC, 0, qdisc) | ||||
| } | ||||
|  | ||||
| // QdiscReplace will replace a qdisc to the system. | ||||
| // Equivalent to: `tc qdisc replace $qdisc` | ||||
| // The handle MUST change. | ||||
| func QdiscReplace(qdisc Qdisc) error { | ||||
| 	return pkgHandle.QdiscReplace(qdisc) | ||||
| } | ||||
|  | ||||
| // QdiscReplace will replace a qdisc to the system. | ||||
| // Equivalent to: `tc qdisc replace $qdisc` | ||||
| // The handle MUST change. | ||||
| func (h *Handle) QdiscReplace(qdisc Qdisc) error { | ||||
| 	return h.qdiscModify( | ||||
| 		unix.RTM_NEWQDISC, | ||||
| 		unix.NLM_F_CREATE|unix.NLM_F_REPLACE, | ||||
| 		qdisc) | ||||
| } | ||||
|  | ||||
| // QdiscAdd will add a qdisc to the system. | ||||
| // Equivalent to: `tc qdisc add $qdisc` | ||||
| func QdiscAdd(qdisc Qdisc) error { | ||||
| 	return pkgHandle.QdiscAdd(qdisc) | ||||
| } | ||||
|  | ||||
| // QdiscAdd will add a qdisc to the system. | ||||
| // Equivalent to: `tc qdisc add $qdisc` | ||||
| func (h *Handle) QdiscAdd(qdisc Qdisc) error { | ||||
| 	return h.qdiscModify( | ||||
| 		unix.RTM_NEWQDISC, | ||||
| 		unix.NLM_F_CREATE|unix.NLM_F_EXCL, | ||||
| 		qdisc) | ||||
| } | ||||
|  | ||||
| func (h *Handle) qdiscModify(cmd, flags int, qdisc Qdisc) error { | ||||
| 	req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK) | ||||
| 	base := qdisc.Attrs() | ||||
| 	msg := &nl.TcMsg{ | ||||
| 		Family:  nl.FAMILY_ALL, | ||||
| 		Ifindex: int32(base.LinkIndex), | ||||
| 		Handle:  base.Handle, | ||||
| 		Parent:  base.Parent, | ||||
| 	} | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	// When deleting don't bother building the rest of the netlink payload | ||||
| 	if cmd != unix.RTM_DELQDISC { | ||||
| 		if err := qdiscPayload(req, qdisc); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	_, err := req.Execute(unix.NETLINK_ROUTE, 0) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error { | ||||
|  | ||||
| 	req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(qdisc.Type()))) | ||||
|  | ||||
| 	options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) | ||||
|  | ||||
| 	switch qdisc := qdisc.(type) { | ||||
| 	case *Prio: | ||||
| 		tcmap := nl.TcPrioMap{ | ||||
| 			Bands:   int32(qdisc.Bands), | ||||
| 			Priomap: qdisc.PriorityMap, | ||||
| 		} | ||||
| 		options = nl.NewRtAttr(nl.TCA_OPTIONS, tcmap.Serialize()) | ||||
| 	case *Tbf: | ||||
| 		opt := nl.TcTbfQopt{} | ||||
| 		opt.Rate.Rate = uint32(qdisc.Rate) | ||||
| 		opt.Peakrate.Rate = uint32(qdisc.Peakrate) | ||||
| 		opt.Limit = qdisc.Limit | ||||
| 		opt.Buffer = qdisc.Buffer | ||||
| 		nl.NewRtAttrChild(options, nl.TCA_TBF_PARMS, opt.Serialize()) | ||||
| 		if qdisc.Rate >= uint64(1<<32) { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_TBF_RATE64, nl.Uint64Attr(qdisc.Rate)) | ||||
| 		} | ||||
| 		if qdisc.Peakrate >= uint64(1<<32) { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_TBF_PRATE64, nl.Uint64Attr(qdisc.Peakrate)) | ||||
| 		} | ||||
| 		if qdisc.Peakrate > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_TBF_PBURST, nl.Uint32Attr(qdisc.Minburst)) | ||||
| 		} | ||||
| 	case *Htb: | ||||
| 		opt := nl.TcHtbGlob{} | ||||
| 		opt.Version = qdisc.Version | ||||
| 		opt.Rate2Quantum = qdisc.Rate2Quantum | ||||
| 		opt.Defcls = qdisc.Defcls | ||||
| 		// TODO: Handle Debug properly. For now default to 0 | ||||
| 		opt.Debug = qdisc.Debug | ||||
| 		opt.DirectPkts = qdisc.DirectPkts | ||||
| 		nl.NewRtAttrChild(options, nl.TCA_HTB_INIT, opt.Serialize()) | ||||
| 		// nl.NewRtAttrChild(options, nl.TCA_HTB_DIRECT_QLEN, opt.Serialize()) | ||||
| 	case *Netem: | ||||
| 		opt := nl.TcNetemQopt{} | ||||
| 		opt.Latency = qdisc.Latency | ||||
| 		opt.Limit = qdisc.Limit | ||||
| 		opt.Loss = qdisc.Loss | ||||
| 		opt.Gap = qdisc.Gap | ||||
| 		opt.Duplicate = qdisc.Duplicate | ||||
| 		opt.Jitter = qdisc.Jitter | ||||
| 		options = nl.NewRtAttr(nl.TCA_OPTIONS, opt.Serialize()) | ||||
| 		// Correlation | ||||
| 		corr := nl.TcNetemCorr{} | ||||
| 		corr.DelayCorr = qdisc.DelayCorr | ||||
| 		corr.LossCorr = qdisc.LossCorr | ||||
| 		corr.DupCorr = qdisc.DuplicateCorr | ||||
|  | ||||
| 		if corr.DelayCorr > 0 || corr.LossCorr > 0 || corr.DupCorr > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_NETEM_CORR, corr.Serialize()) | ||||
| 		} | ||||
| 		// Corruption | ||||
| 		corruption := nl.TcNetemCorrupt{} | ||||
| 		corruption.Probability = qdisc.CorruptProb | ||||
| 		corruption.Correlation = qdisc.CorruptCorr | ||||
| 		if corruption.Probability > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_NETEM_CORRUPT, corruption.Serialize()) | ||||
| 		} | ||||
| 		// Reorder | ||||
| 		reorder := nl.TcNetemReorder{} | ||||
| 		reorder.Probability = qdisc.ReorderProb | ||||
| 		reorder.Correlation = qdisc.ReorderCorr | ||||
| 		if reorder.Probability > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_NETEM_REORDER, reorder.Serialize()) | ||||
| 		} | ||||
| 	case *Ingress: | ||||
| 		// ingress filters must use the proper handle | ||||
| 		if qdisc.Attrs().Parent != HANDLE_INGRESS { | ||||
| 			return fmt.Errorf("Ingress filters must set Parent to HANDLE_INGRESS") | ||||
| 		} | ||||
| 	case *FqCodel: | ||||
| 		nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_ECN, nl.Uint32Attr((uint32(qdisc.ECN)))) | ||||
| 		if qdisc.Limit > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_LIMIT, nl.Uint32Attr((uint32(qdisc.Limit)))) | ||||
| 		} | ||||
| 		if qdisc.Interval > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_INTERVAL, nl.Uint32Attr((uint32(qdisc.Interval)))) | ||||
| 		} | ||||
| 		if qdisc.Flows > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_FLOWS, nl.Uint32Attr((uint32(qdisc.Flows)))) | ||||
| 		} | ||||
| 		if qdisc.Quantum > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum)))) | ||||
| 		} | ||||
|  | ||||
| 	case *Fq: | ||||
| 		nl.NewRtAttrChild(options, nl.TCA_FQ_RATE_ENABLE, nl.Uint32Attr((uint32(qdisc.Pacing)))) | ||||
|  | ||||
| 		if qdisc.Buckets > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FQ_BUCKETS_LOG, nl.Uint32Attr((uint32(qdisc.Buckets)))) | ||||
| 		} | ||||
| 		if qdisc.LowRateThreshold > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FQ_LOW_RATE_THRESHOLD, nl.Uint32Attr((uint32(qdisc.LowRateThreshold)))) | ||||
| 		} | ||||
| 		if qdisc.Quantum > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FQ_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum)))) | ||||
| 		} | ||||
| 		if qdisc.InitialQuantum > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FQ_INITIAL_QUANTUM, nl.Uint32Attr((uint32(qdisc.InitialQuantum)))) | ||||
| 		} | ||||
| 		if qdisc.FlowRefillDelay > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FQ_FLOW_REFILL_DELAY, nl.Uint32Attr((uint32(qdisc.FlowRefillDelay)))) | ||||
| 		} | ||||
| 		if qdisc.FlowPacketLimit > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FQ_FLOW_PLIMIT, nl.Uint32Attr((uint32(qdisc.FlowPacketLimit)))) | ||||
| 		} | ||||
| 		if qdisc.FlowMaxRate > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FQ_FLOW_MAX_RATE, nl.Uint32Attr((uint32(qdisc.FlowMaxRate)))) | ||||
| 		} | ||||
| 		if qdisc.FlowDefaultRate > 0 { | ||||
| 			nl.NewRtAttrChild(options, nl.TCA_FQ_FLOW_DEFAULT_RATE, nl.Uint32Attr((uint32(qdisc.FlowDefaultRate)))) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	req.AddData(options) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // QdiscList gets a list of qdiscs in the system. | ||||
| // Equivalent to: `tc qdisc show`. | ||||
| // The list can be filtered by link. | ||||
| func QdiscList(link Link) ([]Qdisc, error) { | ||||
| 	return pkgHandle.QdiscList(link) | ||||
| } | ||||
|  | ||||
| // QdiscList gets a list of qdiscs in the system. | ||||
| // Equivalent to: `tc qdisc show`. | ||||
| // The list can be filtered by link. | ||||
| func (h *Handle) QdiscList(link Link) ([]Qdisc, error) { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_GETQDISC, unix.NLM_F_DUMP) | ||||
| 	index := int32(0) | ||||
| 	if link != nil { | ||||
| 		base := link.Attrs() | ||||
| 		h.ensureIndex(base) | ||||
| 		index = int32(base.Index) | ||||
| 	} | ||||
| 	msg := &nl.TcMsg{ | ||||
| 		Family:  nl.FAMILY_ALL, | ||||
| 		Ifindex: index, | ||||
| 	} | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWQDISC) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	var res []Qdisc | ||||
| 	for _, m := range msgs { | ||||
| 		msg := nl.DeserializeTcMsg(m) | ||||
|  | ||||
| 		attrs, err := nl.ParseRouteAttr(m[msg.Len():]) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		// skip qdiscs from other interfaces | ||||
| 		if link != nil && msg.Ifindex != index { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		base := QdiscAttrs{ | ||||
| 			LinkIndex: int(msg.Ifindex), | ||||
| 			Handle:    msg.Handle, | ||||
| 			Parent:    msg.Parent, | ||||
| 			Refcnt:    msg.Info, | ||||
| 		} | ||||
| 		var qdisc Qdisc | ||||
| 		qdiscType := "" | ||||
| 		for _, attr := range attrs { | ||||
| 			switch attr.Attr.Type { | ||||
| 			case nl.TCA_KIND: | ||||
| 				qdiscType = string(attr.Value[:len(attr.Value)-1]) | ||||
| 				switch qdiscType { | ||||
| 				case "pfifo_fast": | ||||
| 					qdisc = &PfifoFast{} | ||||
| 				case "prio": | ||||
| 					qdisc = &Prio{} | ||||
| 				case "tbf": | ||||
| 					qdisc = &Tbf{} | ||||
| 				case "ingress": | ||||
| 					qdisc = &Ingress{} | ||||
| 				case "htb": | ||||
| 					qdisc = &Htb{} | ||||
| 				case "fq": | ||||
| 					qdisc = &Fq{} | ||||
| 				case "fq_codel": | ||||
| 					qdisc = &FqCodel{} | ||||
| 				case "netem": | ||||
| 					qdisc = &Netem{} | ||||
| 				default: | ||||
| 					qdisc = &GenericQdisc{QdiscType: qdiscType} | ||||
| 				} | ||||
| 			case nl.TCA_OPTIONS: | ||||
| 				switch qdiscType { | ||||
| 				case "pfifo_fast": | ||||
| 					// pfifo returns TcPrioMap directly without wrapping it in rtattr | ||||
| 					if err := parsePfifoFastData(qdisc, attr.Value); err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 				case "prio": | ||||
| 					// prio returns TcPrioMap directly without wrapping it in rtattr | ||||
| 					if err := parsePrioData(qdisc, attr.Value); err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 				case "tbf": | ||||
| 					data, err := nl.ParseRouteAttr(attr.Value) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 					if err := parseTbfData(qdisc, data); err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 				case "htb": | ||||
| 					data, err := nl.ParseRouteAttr(attr.Value) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 					if err := parseHtbData(qdisc, data); err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 				case "fq": | ||||
| 					data, err := nl.ParseRouteAttr(attr.Value) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 					if err := parseFqData(qdisc, data); err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 				case "fq_codel": | ||||
| 					data, err := nl.ParseRouteAttr(attr.Value) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 					if err := parseFqCodelData(qdisc, data); err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 				case "netem": | ||||
| 					if err := parseNetemData(qdisc, attr.Value); err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
|  | ||||
| 					// no options for ingress | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		*qdisc.Attrs() = base | ||||
| 		res = append(res, qdisc) | ||||
| 	} | ||||
|  | ||||
| 	return res, nil | ||||
| } | ||||
|  | ||||
| func parsePfifoFastData(qdisc Qdisc, value []byte) error { | ||||
| 	pfifo := qdisc.(*PfifoFast) | ||||
| 	tcmap := nl.DeserializeTcPrioMap(value) | ||||
| 	pfifo.PriorityMap = tcmap.Priomap | ||||
| 	pfifo.Bands = uint8(tcmap.Bands) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func parsePrioData(qdisc Qdisc, value []byte) error { | ||||
| 	prio := qdisc.(*Prio) | ||||
| 	tcmap := nl.DeserializeTcPrioMap(value) | ||||
| 	prio.PriorityMap = tcmap.Priomap | ||||
| 	prio.Bands = uint8(tcmap.Bands) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { | ||||
| 	native = nl.NativeEndian() | ||||
| 	htb := qdisc.(*Htb) | ||||
| 	for _, datum := range data { | ||||
| 		switch datum.Attr.Type { | ||||
| 		case nl.TCA_HTB_INIT: | ||||
| 			opt := nl.DeserializeTcHtbGlob(datum.Value) | ||||
| 			htb.Version = opt.Version | ||||
| 			htb.Rate2Quantum = opt.Rate2Quantum | ||||
| 			htb.Defcls = opt.Defcls | ||||
| 			htb.Debug = opt.Debug | ||||
| 			htb.DirectPkts = opt.DirectPkts | ||||
| 		case nl.TCA_HTB_DIRECT_QLEN: | ||||
| 			// TODO | ||||
| 			//htb.DirectQlen = native.uint32(datum.Value) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { | ||||
| 	native = nl.NativeEndian() | ||||
| 	fqCodel := qdisc.(*FqCodel) | ||||
| 	for _, datum := range data { | ||||
|  | ||||
| 		switch datum.Attr.Type { | ||||
| 		case nl.TCA_FQ_CODEL_TARGET: | ||||
| 			fqCodel.Target = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_CODEL_LIMIT: | ||||
| 			fqCodel.Limit = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_CODEL_INTERVAL: | ||||
| 			fqCodel.Interval = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_CODEL_ECN: | ||||
| 			fqCodel.ECN = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_CODEL_FLOWS: | ||||
| 			fqCodel.Flows = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_CODEL_QUANTUM: | ||||
| 			fqCodel.Quantum = native.Uint32(datum.Value) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func parseFqData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { | ||||
| 	native = nl.NativeEndian() | ||||
| 	fq := qdisc.(*Fq) | ||||
| 	for _, datum := range data { | ||||
| 		switch datum.Attr.Type { | ||||
| 		case nl.TCA_FQ_BUCKETS_LOG: | ||||
| 			fq.Buckets = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_LOW_RATE_THRESHOLD: | ||||
| 			fq.LowRateThreshold = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_QUANTUM: | ||||
| 			fq.Quantum = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_RATE_ENABLE: | ||||
| 			fq.Pacing = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_INITIAL_QUANTUM: | ||||
| 			fq.InitialQuantum = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_ORPHAN_MASK: | ||||
| 			// TODO | ||||
| 		case nl.TCA_FQ_FLOW_REFILL_DELAY: | ||||
| 			fq.FlowRefillDelay = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_FLOW_PLIMIT: | ||||
| 			fq.FlowPacketLimit = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_PLIMIT: | ||||
| 			fq.PacketLimit = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_FLOW_MAX_RATE: | ||||
| 			fq.FlowMaxRate = native.Uint32(datum.Value) | ||||
| 		case nl.TCA_FQ_FLOW_DEFAULT_RATE: | ||||
| 			fq.FlowDefaultRate = native.Uint32(datum.Value) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func parseNetemData(qdisc Qdisc, value []byte) error { | ||||
| 	netem := qdisc.(*Netem) | ||||
| 	opt := nl.DeserializeTcNetemQopt(value) | ||||
| 	netem.Latency = opt.Latency | ||||
| 	netem.Limit = opt.Limit | ||||
| 	netem.Loss = opt.Loss | ||||
| 	netem.Gap = opt.Gap | ||||
| 	netem.Duplicate = opt.Duplicate | ||||
| 	netem.Jitter = opt.Jitter | ||||
| 	data, err := nl.ParseRouteAttr(value[nl.SizeofTcNetemQopt:]) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	for _, datum := range data { | ||||
| 		switch datum.Attr.Type { | ||||
| 		case nl.TCA_NETEM_CORR: | ||||
| 			opt := nl.DeserializeTcNetemCorr(datum.Value) | ||||
| 			netem.DelayCorr = opt.DelayCorr | ||||
| 			netem.LossCorr = opt.LossCorr | ||||
| 			netem.DuplicateCorr = opt.DupCorr | ||||
| 		case nl.TCA_NETEM_CORRUPT: | ||||
| 			opt := nl.DeserializeTcNetemCorrupt(datum.Value) | ||||
| 			netem.CorruptProb = opt.Probability | ||||
| 			netem.CorruptCorr = opt.Correlation | ||||
| 		case nl.TCA_NETEM_REORDER: | ||||
| 			opt := nl.DeserializeTcNetemReorder(datum.Value) | ||||
| 			netem.ReorderProb = opt.Probability | ||||
| 			netem.ReorderCorr = opt.Correlation | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func parseTbfData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { | ||||
| 	native = nl.NativeEndian() | ||||
| 	tbf := qdisc.(*Tbf) | ||||
| 	for _, datum := range data { | ||||
| 		switch datum.Attr.Type { | ||||
| 		case nl.TCA_TBF_PARMS: | ||||
| 			opt := nl.DeserializeTcTbfQopt(datum.Value) | ||||
| 			tbf.Rate = uint64(opt.Rate.Rate) | ||||
| 			tbf.Peakrate = uint64(opt.Peakrate.Rate) | ||||
| 			tbf.Limit = opt.Limit | ||||
| 			tbf.Buffer = opt.Buffer | ||||
| 		case nl.TCA_TBF_RATE64: | ||||
| 			tbf.Rate = native.Uint64(datum.Value[0:8]) | ||||
| 		case nl.TCA_TBF_PRATE64: | ||||
| 			tbf.Peakrate = native.Uint64(datum.Value[0:8]) | ||||
| 		case nl.TCA_TBF_PBURST: | ||||
| 			tbf.Minburst = native.Uint32(datum.Value[0:4]) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	TIME_UNITS_PER_SEC = 1000000 | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	tickInUsec  float64 | ||||
| 	clockFactor float64 | ||||
| 	hz          float64 | ||||
| ) | ||||
|  | ||||
| func initClock() { | ||||
| 	data, err := ioutil.ReadFile("/proc/net/psched") | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	parts := strings.Split(strings.TrimSpace(string(data)), " ") | ||||
| 	if len(parts) < 3 { | ||||
| 		return | ||||
| 	} | ||||
| 	var vals [3]uint64 | ||||
| 	for i := range vals { | ||||
| 		val, err := strconv.ParseUint(parts[i], 16, 32) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		vals[i] = val | ||||
| 	} | ||||
| 	// compatibility | ||||
| 	if vals[2] == 1000000000 { | ||||
| 		vals[0] = vals[1] | ||||
| 	} | ||||
| 	clockFactor = float64(vals[2]) / TIME_UNITS_PER_SEC | ||||
| 	tickInUsec = float64(vals[0]) / float64(vals[1]) * clockFactor | ||||
| 	hz = float64(vals[0]) | ||||
| } | ||||
|  | ||||
| func TickInUsec() float64 { | ||||
| 	if tickInUsec == 0.0 { | ||||
| 		initClock() | ||||
| 	} | ||||
| 	return tickInUsec | ||||
| } | ||||
|  | ||||
| func ClockFactor() float64 { | ||||
| 	if clockFactor == 0.0 { | ||||
| 		initClock() | ||||
| 	} | ||||
| 	return clockFactor | ||||
| } | ||||
|  | ||||
| func Hz() float64 { | ||||
| 	if hz == 0.0 { | ||||
| 		initClock() | ||||
| 	} | ||||
| 	return hz | ||||
| } | ||||
|  | ||||
| func time2Tick(time uint32) uint32 { | ||||
| 	return uint32(float64(time) * TickInUsec()) | ||||
| } | ||||
|  | ||||
| func tick2Time(tick uint32) uint32 { | ||||
| 	return uint32(float64(tick) / TickInUsec()) | ||||
| } | ||||
|  | ||||
| func time2Ktime(time uint32) uint32 { | ||||
| 	return uint32(float64(time) * ClockFactor()) | ||||
| } | ||||
|  | ||||
| func ktime2Time(ktime uint32) uint32 { | ||||
| 	return uint32(float64(ktime) / ClockFactor()) | ||||
| } | ||||
|  | ||||
| func burst(rate uint64, buffer uint32) uint32 { | ||||
| 	return uint32(float64(rate) * float64(tick2Time(buffer)) / TIME_UNITS_PER_SEC) | ||||
| } | ||||
|  | ||||
| func latency(rate uint64, limit, buffer uint32) float64 { | ||||
| 	return TIME_UNITS_PER_SEC*(float64(limit)/float64(rate)) - float64(tick2Time(buffer)) | ||||
| } | ||||
|  | ||||
| func Xmittime(rate uint64, size uint32) float64 { | ||||
| 	return TickInUsec() * TIME_UNITS_PER_SEC * (float64(size) / float64(rate)) | ||||
| } | ||||
							
								
								
									
										178
									
								
								vendor/github.com/vishvananda/netlink/route.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								vendor/github.com/vishvananda/netlink/route.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // Scope is an enum representing a route scope. | ||||
| type Scope uint8 | ||||
|  | ||||
| type NextHopFlag int | ||||
|  | ||||
| type Destination interface { | ||||
| 	Family() int | ||||
| 	Decode([]byte) error | ||||
| 	Encode() ([]byte, error) | ||||
| 	String() string | ||||
| 	Equal(Destination) bool | ||||
| } | ||||
|  | ||||
| type Encap interface { | ||||
| 	Type() int | ||||
| 	Decode([]byte) error | ||||
| 	Encode() ([]byte, error) | ||||
| 	String() string | ||||
| 	Equal(Encap) bool | ||||
| } | ||||
|  | ||||
| // Route represents a netlink route. | ||||
| type Route struct { | ||||
| 	LinkIndex  int | ||||
| 	ILinkIndex int | ||||
| 	Scope      Scope | ||||
| 	Dst        *net.IPNet | ||||
| 	Src        net.IP | ||||
| 	Gw         net.IP | ||||
| 	MultiPath  []*NexthopInfo | ||||
| 	Protocol   int | ||||
| 	Priority   int | ||||
| 	Table      int | ||||
| 	Type       int | ||||
| 	Tos        int | ||||
| 	Flags      int | ||||
| 	MPLSDst    *int | ||||
| 	NewDst     Destination | ||||
| 	Encap      Encap | ||||
| 	MTU        int | ||||
| 	AdvMSS     int | ||||
| } | ||||
|  | ||||
| func (r Route) String() string { | ||||
| 	elems := []string{} | ||||
| 	if len(r.MultiPath) == 0 { | ||||
| 		elems = append(elems, fmt.Sprintf("Ifindex: %d", r.LinkIndex)) | ||||
| 	} | ||||
| 	if r.MPLSDst != nil { | ||||
| 		elems = append(elems, fmt.Sprintf("Dst: %d", r.MPLSDst)) | ||||
| 	} else { | ||||
| 		elems = append(elems, fmt.Sprintf("Dst: %s", r.Dst)) | ||||
| 	} | ||||
| 	if r.NewDst != nil { | ||||
| 		elems = append(elems, fmt.Sprintf("NewDst: %s", r.NewDst)) | ||||
| 	} | ||||
| 	if r.Encap != nil { | ||||
| 		elems = append(elems, fmt.Sprintf("Encap: %s", r.Encap)) | ||||
| 	} | ||||
| 	elems = append(elems, fmt.Sprintf("Src: %s", r.Src)) | ||||
| 	if len(r.MultiPath) > 0 { | ||||
| 		elems = append(elems, fmt.Sprintf("Gw: %s", r.MultiPath)) | ||||
| 	} else { | ||||
| 		elems = append(elems, fmt.Sprintf("Gw: %s", r.Gw)) | ||||
| 	} | ||||
| 	elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags())) | ||||
| 	elems = append(elems, fmt.Sprintf("Table: %d", r.Table)) | ||||
| 	return fmt.Sprintf("{%s}", strings.Join(elems, " ")) | ||||
| } | ||||
|  | ||||
| func (r Route) Equal(x Route) bool { | ||||
| 	return r.LinkIndex == x.LinkIndex && | ||||
| 		r.ILinkIndex == x.ILinkIndex && | ||||
| 		r.Scope == x.Scope && | ||||
| 		ipNetEqual(r.Dst, x.Dst) && | ||||
| 		r.Src.Equal(x.Src) && | ||||
| 		r.Gw.Equal(x.Gw) && | ||||
| 		nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) && | ||||
| 		r.Protocol == x.Protocol && | ||||
| 		r.Priority == x.Priority && | ||||
| 		r.Table == x.Table && | ||||
| 		r.Type == x.Type && | ||||
| 		r.Tos == x.Tos && | ||||
| 		r.Flags == x.Flags && | ||||
| 		(r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) && | ||||
| 		(r.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) && | ||||
| 		(r.Encap == x.Encap || (r.Encap != nil && r.Encap.Equal(x.Encap))) | ||||
| } | ||||
|  | ||||
| func (r *Route) SetFlag(flag NextHopFlag) { | ||||
| 	r.Flags |= int(flag) | ||||
| } | ||||
|  | ||||
| func (r *Route) ClearFlag(flag NextHopFlag) { | ||||
| 	r.Flags &^= int(flag) | ||||
| } | ||||
|  | ||||
| type flagString struct { | ||||
| 	f NextHopFlag | ||||
| 	s string | ||||
| } | ||||
|  | ||||
| // RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE | ||||
| type RouteUpdate struct { | ||||
| 	Type uint16 | ||||
| 	Route | ||||
| } | ||||
|  | ||||
| type NexthopInfo struct { | ||||
| 	LinkIndex int | ||||
| 	Hops      int | ||||
| 	Gw        net.IP | ||||
| 	Flags     int | ||||
| 	NewDst    Destination | ||||
| 	Encap     Encap | ||||
| } | ||||
|  | ||||
| func (n *NexthopInfo) String() string { | ||||
| 	elems := []string{} | ||||
| 	elems = append(elems, fmt.Sprintf("Ifindex: %d", n.LinkIndex)) | ||||
| 	if n.NewDst != nil { | ||||
| 		elems = append(elems, fmt.Sprintf("NewDst: %s", n.NewDst)) | ||||
| 	} | ||||
| 	if n.Encap != nil { | ||||
| 		elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap)) | ||||
| 	} | ||||
| 	elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1)) | ||||
| 	elems = append(elems, fmt.Sprintf("Gw: %s", n.Gw)) | ||||
| 	elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags())) | ||||
| 	return fmt.Sprintf("{%s}", strings.Join(elems, " ")) | ||||
| } | ||||
|  | ||||
| func (n NexthopInfo) Equal(x NexthopInfo) bool { | ||||
| 	return n.LinkIndex == x.LinkIndex && | ||||
| 		n.Hops == x.Hops && | ||||
| 		n.Gw.Equal(x.Gw) && | ||||
| 		n.Flags == x.Flags && | ||||
| 		(n.NewDst == x.NewDst || (n.NewDst != nil && n.NewDst.Equal(x.NewDst))) && | ||||
| 		(n.Encap == x.Encap || (n.Encap != nil && n.Encap.Equal(x.Encap))) | ||||
| } | ||||
|  | ||||
| type nexthopInfoSlice []*NexthopInfo | ||||
|  | ||||
| func (n nexthopInfoSlice) Equal(x []*NexthopInfo) bool { | ||||
| 	if len(n) != len(x) { | ||||
| 		return false | ||||
| 	} | ||||
| 	for i := range n { | ||||
| 		if n[i] == nil || x[i] == nil { | ||||
| 			return false | ||||
| 		} | ||||
| 		if !n[i].Equal(*x[i]) { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // ipNetEqual returns true iff both IPNet are equal | ||||
| func ipNetEqual(ipn1 *net.IPNet, ipn2 *net.IPNet) bool { | ||||
| 	if ipn1 == ipn2 { | ||||
| 		return true | ||||
| 	} | ||||
| 	if ipn1 == nil || ipn2 == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	m1, _ := ipn1.Mask.Size() | ||||
| 	m2, _ := ipn2.Mask.Size() | ||||
| 	return m1 == m2 && ipn1.IP.Equal(ipn2.IP) | ||||
| } | ||||
							
								
								
									
										878
									
								
								vendor/github.com/vishvananda/netlink/route_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										878
									
								
								vendor/github.com/vishvananda/netlink/route_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,878 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"github.com/vishvananda/netns" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // RtAttr is shared so it is in netlink_linux.go | ||||
|  | ||||
| const ( | ||||
| 	SCOPE_UNIVERSE Scope = unix.RT_SCOPE_UNIVERSE | ||||
| 	SCOPE_SITE     Scope = unix.RT_SCOPE_SITE | ||||
| 	SCOPE_LINK     Scope = unix.RT_SCOPE_LINK | ||||
| 	SCOPE_HOST     Scope = unix.RT_SCOPE_HOST | ||||
| 	SCOPE_NOWHERE  Scope = unix.RT_SCOPE_NOWHERE | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	RT_FILTER_PROTOCOL uint64 = 1 << (1 + iota) | ||||
| 	RT_FILTER_SCOPE | ||||
| 	RT_FILTER_TYPE | ||||
| 	RT_FILTER_TOS | ||||
| 	RT_FILTER_IIF | ||||
| 	RT_FILTER_OIF | ||||
| 	RT_FILTER_DST | ||||
| 	RT_FILTER_SRC | ||||
| 	RT_FILTER_GW | ||||
| 	RT_FILTER_TABLE | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	FLAG_ONLINK    NextHopFlag = unix.RTNH_F_ONLINK | ||||
| 	FLAG_PERVASIVE NextHopFlag = unix.RTNH_F_PERVASIVE | ||||
| ) | ||||
|  | ||||
| var testFlags = []flagString{ | ||||
| 	{f: FLAG_ONLINK, s: "onlink"}, | ||||
| 	{f: FLAG_PERVASIVE, s: "pervasive"}, | ||||
| } | ||||
|  | ||||
| func listFlags(flag int) []string { | ||||
| 	var flags []string | ||||
| 	for _, tf := range testFlags { | ||||
| 		if flag&int(tf.f) != 0 { | ||||
| 			flags = append(flags, tf.s) | ||||
| 		} | ||||
| 	} | ||||
| 	return flags | ||||
| } | ||||
|  | ||||
| func (r *Route) ListFlags() []string { | ||||
| 	return listFlags(r.Flags) | ||||
| } | ||||
|  | ||||
| func (n *NexthopInfo) ListFlags() []string { | ||||
| 	return listFlags(n.Flags) | ||||
| } | ||||
|  | ||||
| type MPLSDestination struct { | ||||
| 	Labels []int | ||||
| } | ||||
|  | ||||
| func (d *MPLSDestination) Family() int { | ||||
| 	return nl.FAMILY_MPLS | ||||
| } | ||||
|  | ||||
| func (d *MPLSDestination) Decode(buf []byte) error { | ||||
| 	d.Labels = nl.DecodeMPLSStack(buf) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (d *MPLSDestination) Encode() ([]byte, error) { | ||||
| 	return nl.EncodeMPLSStack(d.Labels...), nil | ||||
| } | ||||
|  | ||||
| func (d *MPLSDestination) String() string { | ||||
| 	s := make([]string, 0, len(d.Labels)) | ||||
| 	for _, l := range d.Labels { | ||||
| 		s = append(s, fmt.Sprintf("%d", l)) | ||||
| 	} | ||||
| 	return strings.Join(s, "/") | ||||
| } | ||||
|  | ||||
| func (d *MPLSDestination) Equal(x Destination) bool { | ||||
| 	o, ok := x.(*MPLSDestination) | ||||
| 	if !ok { | ||||
| 		return false | ||||
| 	} | ||||
| 	if d == nil && o == nil { | ||||
| 		return true | ||||
| 	} | ||||
| 	if d == nil || o == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	if d.Labels == nil && o.Labels == nil { | ||||
| 		return true | ||||
| 	} | ||||
| 	if d.Labels == nil || o.Labels == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	if len(d.Labels) != len(o.Labels) { | ||||
| 		return false | ||||
| 	} | ||||
| 	for i := range d.Labels { | ||||
| 		if d.Labels[i] != o.Labels[i] { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| type MPLSEncap struct { | ||||
| 	Labels []int | ||||
| } | ||||
|  | ||||
| func (e *MPLSEncap) Type() int { | ||||
| 	return nl.LWTUNNEL_ENCAP_MPLS | ||||
| } | ||||
|  | ||||
| func (e *MPLSEncap) Decode(buf []byte) error { | ||||
| 	if len(buf) < 4 { | ||||
| 		return fmt.Errorf("lack of bytes") | ||||
| 	} | ||||
| 	native := nl.NativeEndian() | ||||
| 	l := native.Uint16(buf) | ||||
| 	if len(buf) < int(l) { | ||||
| 		return fmt.Errorf("lack of bytes") | ||||
| 	} | ||||
| 	buf = buf[:l] | ||||
| 	typ := native.Uint16(buf[2:]) | ||||
| 	if typ != nl.MPLS_IPTUNNEL_DST { | ||||
| 		return fmt.Errorf("unknown MPLS Encap Type: %d", typ) | ||||
| 	} | ||||
| 	e.Labels = nl.DecodeMPLSStack(buf[4:]) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (e *MPLSEncap) Encode() ([]byte, error) { | ||||
| 	s := nl.EncodeMPLSStack(e.Labels...) | ||||
| 	native := nl.NativeEndian() | ||||
| 	hdr := make([]byte, 4) | ||||
| 	native.PutUint16(hdr, uint16(len(s)+4)) | ||||
| 	native.PutUint16(hdr[2:], nl.MPLS_IPTUNNEL_DST) | ||||
| 	return append(hdr, s...), nil | ||||
| } | ||||
|  | ||||
| func (e *MPLSEncap) String() string { | ||||
| 	s := make([]string, 0, len(e.Labels)) | ||||
| 	for _, l := range e.Labels { | ||||
| 		s = append(s, fmt.Sprintf("%d", l)) | ||||
| 	} | ||||
| 	return strings.Join(s, "/") | ||||
| } | ||||
|  | ||||
| func (e *MPLSEncap) Equal(x Encap) bool { | ||||
| 	o, ok := x.(*MPLSEncap) | ||||
| 	if !ok { | ||||
| 		return false | ||||
| 	} | ||||
| 	if e == nil && o == nil { | ||||
| 		return true | ||||
| 	} | ||||
| 	if e == nil || o == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	if e.Labels == nil && o.Labels == nil { | ||||
| 		return true | ||||
| 	} | ||||
| 	if e.Labels == nil || o.Labels == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	if len(e.Labels) != len(o.Labels) { | ||||
| 		return false | ||||
| 	} | ||||
| 	for i := range e.Labels { | ||||
| 		if e.Labels[i] != o.Labels[i] { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // SEG6 definitions | ||||
| type SEG6Encap struct { | ||||
| 	Mode     int | ||||
| 	Segments []net.IP | ||||
| } | ||||
|  | ||||
| func (e *SEG6Encap) Type() int { | ||||
| 	return nl.LWTUNNEL_ENCAP_SEG6 | ||||
| } | ||||
| func (e *SEG6Encap) Decode(buf []byte) error { | ||||
| 	if len(buf) < 4 { | ||||
| 		return fmt.Errorf("lack of bytes") | ||||
| 	} | ||||
| 	native := nl.NativeEndian() | ||||
| 	// Get Length(l) & Type(typ) : 2 + 2 bytes | ||||
| 	l := native.Uint16(buf) | ||||
| 	if len(buf) < int(l) { | ||||
| 		return fmt.Errorf("lack of bytes") | ||||
| 	} | ||||
| 	buf = buf[:l] // make sure buf size upper limit is Length | ||||
| 	typ := native.Uint16(buf[2:]) | ||||
| 	if typ != nl.SEG6_IPTUNNEL_SRH { | ||||
| 		return fmt.Errorf("unknown SEG6 Type: %d", typ) | ||||
| 	} | ||||
|  | ||||
| 	var err error | ||||
| 	e.Mode, e.Segments, err = nl.DecodeSEG6Encap(buf[4:]) | ||||
|  | ||||
| 	return err | ||||
| } | ||||
| func (e *SEG6Encap) Encode() ([]byte, error) { | ||||
| 	s, err := nl.EncodeSEG6Encap(e.Mode, e.Segments) | ||||
| 	native := nl.NativeEndian() | ||||
| 	hdr := make([]byte, 4) | ||||
| 	native.PutUint16(hdr, uint16(len(s)+4)) | ||||
| 	native.PutUint16(hdr[2:], nl.SEG6_IPTUNNEL_SRH) | ||||
| 	return append(hdr, s...), err | ||||
| } | ||||
| func (e *SEG6Encap) String() string { | ||||
| 	segs := make([]string, 0, len(e.Segments)) | ||||
| 	// append segment backwards (from n to 0) since seg#0 is the last segment. | ||||
| 	for i := len(e.Segments); i > 0; i-- { | ||||
| 		segs = append(segs, fmt.Sprintf("%s", e.Segments[i-1])) | ||||
| 	} | ||||
| 	str := fmt.Sprintf("mode %s segs %d [ %s ]", nl.SEG6EncapModeString(e.Mode), | ||||
| 		len(e.Segments), strings.Join(segs, " ")) | ||||
| 	return str | ||||
| } | ||||
| func (e *SEG6Encap) Equal(x Encap) bool { | ||||
| 	o, ok := x.(*SEG6Encap) | ||||
| 	if !ok { | ||||
| 		return false | ||||
| 	} | ||||
| 	if e == o { | ||||
| 		return true | ||||
| 	} | ||||
| 	if e == nil || o == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	if e.Mode != o.Mode { | ||||
| 		return false | ||||
| 	} | ||||
| 	if len(e.Segments) != len(o.Segments) { | ||||
| 		return false | ||||
| 	} | ||||
| 	for i := range e.Segments { | ||||
| 		if !e.Segments[i].Equal(o.Segments[i]) { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // RouteAdd will add a route to the system. | ||||
| // Equivalent to: `ip route add $route` | ||||
| func RouteAdd(route *Route) error { | ||||
| 	return pkgHandle.RouteAdd(route) | ||||
| } | ||||
|  | ||||
| // RouteAdd will add a route to the system. | ||||
| // Equivalent to: `ip route add $route` | ||||
| func (h *Handle) RouteAdd(route *Route) error { | ||||
| 	flags := unix.NLM_F_CREATE | unix.NLM_F_EXCL | unix.NLM_F_ACK | ||||
| 	req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags) | ||||
| 	return h.routeHandle(route, req, nl.NewRtMsg()) | ||||
| } | ||||
|  | ||||
| // RouteReplace will add a route to the system. | ||||
| // Equivalent to: `ip route replace $route` | ||||
| func RouteReplace(route *Route) error { | ||||
| 	return pkgHandle.RouteReplace(route) | ||||
| } | ||||
|  | ||||
| // RouteReplace will add a route to the system. | ||||
| // Equivalent to: `ip route replace $route` | ||||
| func (h *Handle) RouteReplace(route *Route) error { | ||||
| 	flags := unix.NLM_F_CREATE | unix.NLM_F_REPLACE | unix.NLM_F_ACK | ||||
| 	req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags) | ||||
| 	return h.routeHandle(route, req, nl.NewRtMsg()) | ||||
| } | ||||
|  | ||||
| // RouteDel will delete a route from the system. | ||||
| // Equivalent to: `ip route del $route` | ||||
| func RouteDel(route *Route) error { | ||||
| 	return pkgHandle.RouteDel(route) | ||||
| } | ||||
|  | ||||
| // RouteDel will delete a route from the system. | ||||
| // Equivalent to: `ip route del $route` | ||||
| func (h *Handle) RouteDel(route *Route) error { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_DELROUTE, unix.NLM_F_ACK) | ||||
| 	return h.routeHandle(route, req, nl.NewRtDelMsg()) | ||||
| } | ||||
|  | ||||
| func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error { | ||||
| 	if (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil { | ||||
| 		return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil") | ||||
| 	} | ||||
|  | ||||
| 	family := -1 | ||||
| 	var rtAttrs []*nl.RtAttr | ||||
|  | ||||
| 	if route.Dst != nil && route.Dst.IP != nil { | ||||
| 		dstLen, _ := route.Dst.Mask.Size() | ||||
| 		msg.Dst_len = uint8(dstLen) | ||||
| 		dstFamily := nl.GetIPFamily(route.Dst.IP) | ||||
| 		family = dstFamily | ||||
| 		var dstData []byte | ||||
| 		if dstFamily == FAMILY_V4 { | ||||
| 			dstData = route.Dst.IP.To4() | ||||
| 		} else { | ||||
| 			dstData = route.Dst.IP.To16() | ||||
| 		} | ||||
| 		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, dstData)) | ||||
| 	} else if route.MPLSDst != nil { | ||||
| 		family = nl.FAMILY_MPLS | ||||
| 		msg.Dst_len = uint8(20) | ||||
| 		msg.Type = unix.RTN_UNICAST | ||||
| 		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, nl.EncodeMPLSStack(*route.MPLSDst))) | ||||
| 	} | ||||
|  | ||||
| 	if route.NewDst != nil { | ||||
| 		if family != -1 && family != route.NewDst.Family() { | ||||
| 			return fmt.Errorf("new destination and destination are not the same address family") | ||||
| 		} | ||||
| 		buf, err := route.NewDst.Encode() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_NEWDST, buf)) | ||||
| 	} | ||||
|  | ||||
| 	if route.Encap != nil { | ||||
| 		buf := make([]byte, 2) | ||||
| 		native.PutUint16(buf, uint16(route.Encap.Type())) | ||||
| 		rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP_TYPE, buf)) | ||||
| 		buf, err := route.Encap.Encode() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP, buf)) | ||||
| 	} | ||||
|  | ||||
| 	if route.Src != nil { | ||||
| 		srcFamily := nl.GetIPFamily(route.Src) | ||||
| 		if family != -1 && family != srcFamily { | ||||
| 			return fmt.Errorf("source and destination ip are not the same IP family") | ||||
| 		} | ||||
| 		family = srcFamily | ||||
| 		var srcData []byte | ||||
| 		if srcFamily == FAMILY_V4 { | ||||
| 			srcData = route.Src.To4() | ||||
| 		} else { | ||||
| 			srcData = route.Src.To16() | ||||
| 		} | ||||
| 		// The commonly used src ip for routes is actually PREFSRC | ||||
| 		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PREFSRC, srcData)) | ||||
| 	} | ||||
|  | ||||
| 	if route.Gw != nil { | ||||
| 		gwFamily := nl.GetIPFamily(route.Gw) | ||||
| 		if family != -1 && family != gwFamily { | ||||
| 			return fmt.Errorf("gateway, source, and destination ip are not the same IP family") | ||||
| 		} | ||||
| 		family = gwFamily | ||||
| 		var gwData []byte | ||||
| 		if gwFamily == FAMILY_V4 { | ||||
| 			gwData = route.Gw.To4() | ||||
| 		} else { | ||||
| 			gwData = route.Gw.To16() | ||||
| 		} | ||||
| 		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_GATEWAY, gwData)) | ||||
| 	} | ||||
|  | ||||
| 	if len(route.MultiPath) > 0 { | ||||
| 		buf := []byte{} | ||||
| 		for _, nh := range route.MultiPath { | ||||
| 			rtnh := &nl.RtNexthop{ | ||||
| 				RtNexthop: unix.RtNexthop{ | ||||
| 					Hops:    uint8(nh.Hops), | ||||
| 					Ifindex: int32(nh.LinkIndex), | ||||
| 					Flags:   uint8(nh.Flags), | ||||
| 				}, | ||||
| 			} | ||||
| 			children := []nl.NetlinkRequestData{} | ||||
| 			if nh.Gw != nil { | ||||
| 				gwFamily := nl.GetIPFamily(nh.Gw) | ||||
| 				if family != -1 && family != gwFamily { | ||||
| 					return fmt.Errorf("gateway, source, and destination ip are not the same IP family") | ||||
| 				} | ||||
| 				if gwFamily == FAMILY_V4 { | ||||
| 					children = append(children, nl.NewRtAttr(unix.RTA_GATEWAY, []byte(nh.Gw.To4()))) | ||||
| 				} else { | ||||
| 					children = append(children, nl.NewRtAttr(unix.RTA_GATEWAY, []byte(nh.Gw.To16()))) | ||||
| 				} | ||||
| 			} | ||||
| 			if nh.NewDst != nil { | ||||
| 				if family != -1 && family != nh.NewDst.Family() { | ||||
| 					return fmt.Errorf("new destination and destination are not the same address family") | ||||
| 				} | ||||
| 				buf, err := nh.NewDst.Encode() | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				children = append(children, nl.NewRtAttr(nl.RTA_NEWDST, buf)) | ||||
| 			} | ||||
| 			if nh.Encap != nil { | ||||
| 				buf := make([]byte, 2) | ||||
| 				native.PutUint16(buf, uint16(nh.Encap.Type())) | ||||
| 				rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP_TYPE, buf)) | ||||
| 				buf, err := nh.Encap.Encode() | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				children = append(children, nl.NewRtAttr(nl.RTA_ENCAP, buf)) | ||||
| 			} | ||||
| 			rtnh.Children = children | ||||
| 			buf = append(buf, rtnh.Serialize()...) | ||||
| 		} | ||||
| 		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_MULTIPATH, buf)) | ||||
| 	} | ||||
|  | ||||
| 	if route.Table > 0 { | ||||
| 		if route.Table >= 256 { | ||||
| 			msg.Table = unix.RT_TABLE_UNSPEC | ||||
| 			b := make([]byte, 4) | ||||
| 			native.PutUint32(b, uint32(route.Table)) | ||||
| 			rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_TABLE, b)) | ||||
| 		} else { | ||||
| 			msg.Table = uint8(route.Table) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if route.Priority > 0 { | ||||
| 		b := make([]byte, 4) | ||||
| 		native.PutUint32(b, uint32(route.Priority)) | ||||
| 		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PRIORITY, b)) | ||||
| 	} | ||||
| 	if route.Tos > 0 { | ||||
| 		msg.Tos = uint8(route.Tos) | ||||
| 	} | ||||
| 	if route.Protocol > 0 { | ||||
| 		msg.Protocol = uint8(route.Protocol) | ||||
| 	} | ||||
| 	if route.Type > 0 { | ||||
| 		msg.Type = uint8(route.Type) | ||||
| 	} | ||||
|  | ||||
| 	var metrics []*nl.RtAttr | ||||
| 	// TODO: support other rta_metric values | ||||
| 	if route.MTU > 0 { | ||||
| 		b := nl.Uint32Attr(uint32(route.MTU)) | ||||
| 		metrics = append(metrics, nl.NewRtAttr(unix.RTAX_MTU, b)) | ||||
| 	} | ||||
| 	if route.AdvMSS > 0 { | ||||
| 		b := nl.Uint32Attr(uint32(route.AdvMSS)) | ||||
| 		metrics = append(metrics, nl.NewRtAttr(unix.RTAX_ADVMSS, b)) | ||||
| 	} | ||||
|  | ||||
| 	if metrics != nil { | ||||
| 		attr := nl.NewRtAttr(unix.RTA_METRICS, nil) | ||||
| 		for _, metric := range metrics { | ||||
| 			attr.AddChild(metric) | ||||
| 		} | ||||
| 		rtAttrs = append(rtAttrs, attr) | ||||
| 	} | ||||
|  | ||||
| 	msg.Flags = uint32(route.Flags) | ||||
| 	msg.Scope = uint8(route.Scope) | ||||
| 	msg.Family = uint8(family) | ||||
| 	req.AddData(msg) | ||||
| 	for _, attr := range rtAttrs { | ||||
| 		req.AddData(attr) | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		b      = make([]byte, 4) | ||||
| 		native = nl.NativeEndian() | ||||
| 	) | ||||
| 	native.PutUint32(b, uint32(route.LinkIndex)) | ||||
|  | ||||
| 	req.AddData(nl.NewRtAttr(unix.RTA_OIF, b)) | ||||
|  | ||||
| 	_, err := req.Execute(unix.NETLINK_ROUTE, 0) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // RouteList gets a list of routes in the system. | ||||
| // Equivalent to: `ip route show`. | ||||
| // The list can be filtered by link and ip family. | ||||
| func RouteList(link Link, family int) ([]Route, error) { | ||||
| 	return pkgHandle.RouteList(link, family) | ||||
| } | ||||
|  | ||||
| // RouteList gets a list of routes in the system. | ||||
| // Equivalent to: `ip route show`. | ||||
| // The list can be filtered by link and ip family. | ||||
| func (h *Handle) RouteList(link Link, family int) ([]Route, error) { | ||||
| 	var routeFilter *Route | ||||
| 	if link != nil { | ||||
| 		routeFilter = &Route{ | ||||
| 			LinkIndex: link.Attrs().Index, | ||||
| 		} | ||||
| 	} | ||||
| 	return h.RouteListFiltered(family, routeFilter, RT_FILTER_OIF) | ||||
| } | ||||
|  | ||||
| // RouteListFiltered gets a list of routes in the system filtered with specified rules. | ||||
| // All rules must be defined in RouteFilter struct | ||||
| func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) { | ||||
| 	return pkgHandle.RouteListFiltered(family, filter, filterMask) | ||||
| } | ||||
|  | ||||
| // RouteListFiltered gets a list of routes in the system filtered with specified rules. | ||||
| // All rules must be defined in RouteFilter struct | ||||
| func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP) | ||||
| 	infmsg := nl.NewIfInfomsg(family) | ||||
| 	req.AddData(infmsg) | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	var res []Route | ||||
| 	for _, m := range msgs { | ||||
| 		msg := nl.DeserializeRtMsg(m) | ||||
| 		if msg.Flags&unix.RTM_F_CLONED != 0 { | ||||
| 			// Ignore cloned routes | ||||
| 			continue | ||||
| 		} | ||||
| 		if msg.Table != unix.RT_TABLE_MAIN { | ||||
| 			if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 { | ||||
| 				// Ignore non-main tables | ||||
| 				continue | ||||
| 			} | ||||
| 		} | ||||
| 		route, err := deserializeRoute(m) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if filter != nil { | ||||
| 			switch { | ||||
| 			case filterMask&RT_FILTER_TABLE != 0 && filter.Table != unix.RT_TABLE_UNSPEC && route.Table != filter.Table: | ||||
| 				continue | ||||
| 			case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol: | ||||
| 				continue | ||||
| 			case filterMask&RT_FILTER_SCOPE != 0 && route.Scope != filter.Scope: | ||||
| 				continue | ||||
| 			case filterMask&RT_FILTER_TYPE != 0 && route.Type != filter.Type: | ||||
| 				continue | ||||
| 			case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos: | ||||
| 				continue | ||||
| 			case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex: | ||||
| 				continue | ||||
| 			case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex: | ||||
| 				continue | ||||
| 			case filterMask&RT_FILTER_GW != 0 && !route.Gw.Equal(filter.Gw): | ||||
| 				continue | ||||
| 			case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src): | ||||
| 				continue | ||||
| 			case filterMask&RT_FILTER_DST != 0: | ||||
| 				if filter.MPLSDst == nil || route.MPLSDst == nil || (*filter.MPLSDst) != (*route.MPLSDst) { | ||||
| 					if !ipNetEqual(route.Dst, filter.Dst) { | ||||
| 						continue | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		res = append(res, route) | ||||
| 	} | ||||
| 	return res, nil | ||||
| } | ||||
|  | ||||
| // deserializeRoute decodes a binary netlink message into a Route struct | ||||
| func deserializeRoute(m []byte) (Route, error) { | ||||
| 	msg := nl.DeserializeRtMsg(m) | ||||
| 	attrs, err := nl.ParseRouteAttr(m[msg.Len():]) | ||||
| 	if err != nil { | ||||
| 		return Route{}, err | ||||
| 	} | ||||
| 	route := Route{ | ||||
| 		Scope:    Scope(msg.Scope), | ||||
| 		Protocol: int(msg.Protocol), | ||||
| 		Table:    int(msg.Table), | ||||
| 		Type:     int(msg.Type), | ||||
| 		Tos:      int(msg.Tos), | ||||
| 		Flags:    int(msg.Flags), | ||||
| 	} | ||||
|  | ||||
| 	native := nl.NativeEndian() | ||||
| 	var encap, encapType syscall.NetlinkRouteAttr | ||||
| 	for _, attr := range attrs { | ||||
| 		switch attr.Attr.Type { | ||||
| 		case unix.RTA_GATEWAY: | ||||
| 			route.Gw = net.IP(attr.Value) | ||||
| 		case unix.RTA_PREFSRC: | ||||
| 			route.Src = net.IP(attr.Value) | ||||
| 		case unix.RTA_DST: | ||||
| 			if msg.Family == nl.FAMILY_MPLS { | ||||
| 				stack := nl.DecodeMPLSStack(attr.Value) | ||||
| 				if len(stack) == 0 || len(stack) > 1 { | ||||
| 					return route, fmt.Errorf("invalid MPLS RTA_DST") | ||||
| 				} | ||||
| 				route.MPLSDst = &stack[0] | ||||
| 			} else { | ||||
| 				route.Dst = &net.IPNet{ | ||||
| 					IP:   attr.Value, | ||||
| 					Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)), | ||||
| 				} | ||||
| 			} | ||||
| 		case unix.RTA_OIF: | ||||
| 			route.LinkIndex = int(native.Uint32(attr.Value[0:4])) | ||||
| 		case unix.RTA_IIF: | ||||
| 			route.ILinkIndex = int(native.Uint32(attr.Value[0:4])) | ||||
| 		case unix.RTA_PRIORITY: | ||||
| 			route.Priority = int(native.Uint32(attr.Value[0:4])) | ||||
| 		case unix.RTA_TABLE: | ||||
| 			route.Table = int(native.Uint32(attr.Value[0:4])) | ||||
| 		case unix.RTA_MULTIPATH: | ||||
| 			parseRtNexthop := func(value []byte) (*NexthopInfo, []byte, error) { | ||||
| 				if len(value) < unix.SizeofRtNexthop { | ||||
| 					return nil, nil, fmt.Errorf("lack of bytes") | ||||
| 				} | ||||
| 				nh := nl.DeserializeRtNexthop(value) | ||||
| 				if len(value) < int(nh.RtNexthop.Len) { | ||||
| 					return nil, nil, fmt.Errorf("lack of bytes") | ||||
| 				} | ||||
| 				info := &NexthopInfo{ | ||||
| 					LinkIndex: int(nh.RtNexthop.Ifindex), | ||||
| 					Hops:      int(nh.RtNexthop.Hops), | ||||
| 					Flags:     int(nh.RtNexthop.Flags), | ||||
| 				} | ||||
| 				attrs, err := nl.ParseRouteAttr(value[unix.SizeofRtNexthop:int(nh.RtNexthop.Len)]) | ||||
| 				if err != nil { | ||||
| 					return nil, nil, err | ||||
| 				} | ||||
| 				var encap, encapType syscall.NetlinkRouteAttr | ||||
| 				for _, attr := range attrs { | ||||
| 					switch attr.Attr.Type { | ||||
| 					case unix.RTA_GATEWAY: | ||||
| 						info.Gw = net.IP(attr.Value) | ||||
| 					case nl.RTA_NEWDST: | ||||
| 						var d Destination | ||||
| 						switch msg.Family { | ||||
| 						case nl.FAMILY_MPLS: | ||||
| 							d = &MPLSDestination{} | ||||
| 						} | ||||
| 						if err := d.Decode(attr.Value); err != nil { | ||||
| 							return nil, nil, err | ||||
| 						} | ||||
| 						info.NewDst = d | ||||
| 					case nl.RTA_ENCAP_TYPE: | ||||
| 						encapType = attr | ||||
| 					case nl.RTA_ENCAP: | ||||
| 						encap = attr | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				if len(encap.Value) != 0 && len(encapType.Value) != 0 { | ||||
| 					typ := int(native.Uint16(encapType.Value[0:2])) | ||||
| 					var e Encap | ||||
| 					switch typ { | ||||
| 					case nl.LWTUNNEL_ENCAP_MPLS: | ||||
| 						e = &MPLSEncap{} | ||||
| 						if err := e.Decode(encap.Value); err != nil { | ||||
| 							return nil, nil, err | ||||
| 						} | ||||
| 					} | ||||
| 					info.Encap = e | ||||
| 				} | ||||
|  | ||||
| 				return info, value[int(nh.RtNexthop.Len):], nil | ||||
| 			} | ||||
| 			rest := attr.Value | ||||
| 			for len(rest) > 0 { | ||||
| 				info, buf, err := parseRtNexthop(rest) | ||||
| 				if err != nil { | ||||
| 					return route, err | ||||
| 				} | ||||
| 				route.MultiPath = append(route.MultiPath, info) | ||||
| 				rest = buf | ||||
| 			} | ||||
| 		case nl.RTA_NEWDST: | ||||
| 			var d Destination | ||||
| 			switch msg.Family { | ||||
| 			case nl.FAMILY_MPLS: | ||||
| 				d = &MPLSDestination{} | ||||
| 			} | ||||
| 			if err := d.Decode(attr.Value); err != nil { | ||||
| 				return route, err | ||||
| 			} | ||||
| 			route.NewDst = d | ||||
| 		case nl.RTA_ENCAP_TYPE: | ||||
| 			encapType = attr | ||||
| 		case nl.RTA_ENCAP: | ||||
| 			encap = attr | ||||
| 		case unix.RTA_METRICS: | ||||
| 			metrics, err := nl.ParseRouteAttr(attr.Value) | ||||
| 			if err != nil { | ||||
| 				return route, err | ||||
| 			} | ||||
| 			for _, metric := range metrics { | ||||
| 				switch metric.Attr.Type { | ||||
| 				case unix.RTAX_MTU: | ||||
| 					route.MTU = int(native.Uint32(metric.Value[0:4])) | ||||
| 				case unix.RTAX_ADVMSS: | ||||
| 					route.AdvMSS = int(native.Uint32(metric.Value[0:4])) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(encap.Value) != 0 && len(encapType.Value) != 0 { | ||||
| 		typ := int(native.Uint16(encapType.Value[0:2])) | ||||
| 		var e Encap | ||||
| 		switch typ { | ||||
| 		case nl.LWTUNNEL_ENCAP_MPLS: | ||||
| 			e = &MPLSEncap{} | ||||
| 			if err := e.Decode(encap.Value); err != nil { | ||||
| 				return route, err | ||||
| 			} | ||||
| 		case nl.LWTUNNEL_ENCAP_SEG6: | ||||
| 			e = &SEG6Encap{} | ||||
| 			if err := e.Decode(encap.Value); err != nil { | ||||
| 				return route, err | ||||
| 			} | ||||
| 		} | ||||
| 		route.Encap = e | ||||
| 	} | ||||
|  | ||||
| 	return route, nil | ||||
| } | ||||
|  | ||||
| // RouteGet gets a route to a specific destination from the host system. | ||||
| // Equivalent to: 'ip route get'. | ||||
| func RouteGet(destination net.IP) ([]Route, error) { | ||||
| 	return pkgHandle.RouteGet(destination) | ||||
| } | ||||
|  | ||||
| // RouteGet gets a route to a specific destination from the host system. | ||||
| // Equivalent to: 'ip route get'. | ||||
| func (h *Handle) RouteGet(destination net.IP) ([]Route, error) { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_REQUEST) | ||||
| 	family := nl.GetIPFamily(destination) | ||||
| 	var destinationData []byte | ||||
| 	var bitlen uint8 | ||||
| 	if family == FAMILY_V4 { | ||||
| 		destinationData = destination.To4() | ||||
| 		bitlen = 32 | ||||
| 	} else { | ||||
| 		destinationData = destination.To16() | ||||
| 		bitlen = 128 | ||||
| 	} | ||||
| 	msg := &nl.RtMsg{} | ||||
| 	msg.Family = uint8(family) | ||||
| 	msg.Dst_len = bitlen | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	rtaDst := nl.NewRtAttr(unix.RTA_DST, destinationData) | ||||
| 	req.AddData(rtaDst) | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	var res []Route | ||||
| 	for _, m := range msgs { | ||||
| 		route, err := deserializeRoute(m) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		res = append(res, route) | ||||
| 	} | ||||
| 	return res, nil | ||||
|  | ||||
| } | ||||
|  | ||||
| // RouteSubscribe takes a chan down which notifications will be sent | ||||
| // when routes are added or deleted. Close the 'done' chan to stop subscription. | ||||
| func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error { | ||||
| 	return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil, false) | ||||
| } | ||||
|  | ||||
| // RouteSubscribeAt works like RouteSubscribe plus it allows the caller | ||||
| // to choose the network namespace in which to subscribe (ns). | ||||
| func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error { | ||||
| 	return routeSubscribeAt(ns, netns.None(), ch, done, nil, false) | ||||
| } | ||||
|  | ||||
| // RouteSubscribeOptions contains a set of options to use with | ||||
| // RouteSubscribeWithOptions. | ||||
| type RouteSubscribeOptions struct { | ||||
| 	Namespace     *netns.NsHandle | ||||
| 	ErrorCallback func(error) | ||||
| 	ListExisting  bool | ||||
| } | ||||
|  | ||||
| // RouteSubscribeWithOptions work like RouteSubscribe but enable to | ||||
| // provide additional options to modify the behavior. Currently, the | ||||
| // namespace can be provided as well as an error callback. | ||||
| func RouteSubscribeWithOptions(ch chan<- RouteUpdate, done <-chan struct{}, options RouteSubscribeOptions) error { | ||||
| 	if options.Namespace == nil { | ||||
| 		none := netns.None() | ||||
| 		options.Namespace = &none | ||||
| 	} | ||||
| 	return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting) | ||||
| } | ||||
|  | ||||
| func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error { | ||||
| 	s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_ROUTE, unix.RTNLGRP_IPV6_ROUTE) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if done != nil { | ||||
| 		go func() { | ||||
| 			<-done | ||||
| 			s.Close() | ||||
| 		}() | ||||
| 	} | ||||
| 	if listExisting { | ||||
| 		req := pkgHandle.newNetlinkRequest(unix.RTM_GETROUTE, | ||||
| 			unix.NLM_F_DUMP) | ||||
| 		infmsg := nl.NewIfInfomsg(unix.AF_UNSPEC) | ||||
| 		req.AddData(infmsg) | ||||
| 		if err := s.Send(req); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	go func() { | ||||
| 		defer close(ch) | ||||
| 		for { | ||||
| 			msgs, err := s.Receive() | ||||
| 			if err != nil { | ||||
| 				if cberr != nil { | ||||
| 					cberr(err) | ||||
| 				} | ||||
| 				return | ||||
| 			} | ||||
| 			for _, m := range msgs { | ||||
| 				if m.Header.Type == unix.NLMSG_DONE { | ||||
| 					continue | ||||
| 				} | ||||
| 				if m.Header.Type == unix.NLMSG_ERROR { | ||||
| 					native := nl.NativeEndian() | ||||
| 					error := int32(native.Uint32(m.Data[0:4])) | ||||
| 					if error == 0 { | ||||
| 						continue | ||||
| 					} | ||||
| 					if cberr != nil { | ||||
| 						cberr(syscall.Errno(-error)) | ||||
| 					} | ||||
| 					return | ||||
| 				} | ||||
| 				route, err := deserializeRoute(m.Data) | ||||
| 				if err != nil { | ||||
| 					if cberr != nil { | ||||
| 						cberr(err) | ||||
| 					} | ||||
| 					return | ||||
| 				} | ||||
| 				ch <- RouteUpdate{Type: m.Header.Type, Route: route} | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										11
									
								
								vendor/github.com/vishvananda/netlink/route_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/vishvananda/netlink/route_unspecified.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !linux | ||||
|  | ||||
| package netlink | ||||
|  | ||||
| func (r *Route) ListFlags() []string { | ||||
| 	return []string{} | ||||
| } | ||||
|  | ||||
| func (n *NexthopInfo) ListFlags() []string { | ||||
| 	return []string{} | ||||
| } | ||||
							
								
								
									
										42
									
								
								vendor/github.com/vishvananda/netlink/rule.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								vendor/github.com/vishvananda/netlink/rule.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| ) | ||||
|  | ||||
| // Rule represents a netlink rule. | ||||
| type Rule struct { | ||||
| 	Priority          int | ||||
| 	Family            int | ||||
| 	Table             int | ||||
| 	Mark              int | ||||
| 	Mask              int | ||||
| 	TunID             uint | ||||
| 	Goto              int | ||||
| 	Src               *net.IPNet | ||||
| 	Dst               *net.IPNet | ||||
| 	Flow              int | ||||
| 	IifName           string | ||||
| 	OifName           string | ||||
| 	SuppressIfgroup   int | ||||
| 	SuppressPrefixlen int | ||||
| 	Invert            bool | ||||
| } | ||||
|  | ||||
| func (r Rule) String() string { | ||||
| 	return fmt.Sprintf("ip rule %d: from %s table %d", r.Priority, r.Src, r.Table) | ||||
| } | ||||
|  | ||||
| // NewRule return empty rules. | ||||
| func NewRule() *Rule { | ||||
| 	return &Rule{ | ||||
| 		SuppressIfgroup:   -1, | ||||
| 		SuppressPrefixlen: -1, | ||||
| 		Priority:          -1, | ||||
| 		Mark:              -1, | ||||
| 		Mask:              -1, | ||||
| 		Goto:              -1, | ||||
| 		Flow:              -1, | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										234
									
								
								vendor/github.com/vishvananda/netlink/rule_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								vendor/github.com/vishvananda/netlink/rule_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,234 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| const FibRuleInvert = 0x2 | ||||
|  | ||||
| // RuleAdd adds a rule to the system. | ||||
| // Equivalent to: ip rule add | ||||
| func RuleAdd(rule *Rule) error { | ||||
| 	return pkgHandle.RuleAdd(rule) | ||||
| } | ||||
|  | ||||
| // RuleAdd adds a rule to the system. | ||||
| // Equivalent to: ip rule add | ||||
| func (h *Handle) RuleAdd(rule *Rule) error { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_NEWRULE, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) | ||||
| 	return ruleHandle(rule, req) | ||||
| } | ||||
|  | ||||
| // RuleDel deletes a rule from the system. | ||||
| // Equivalent to: ip rule del | ||||
| func RuleDel(rule *Rule) error { | ||||
| 	return pkgHandle.RuleDel(rule) | ||||
| } | ||||
|  | ||||
| // RuleDel deletes a rule from the system. | ||||
| // Equivalent to: ip rule del | ||||
| func (h *Handle) RuleDel(rule *Rule) error { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_DELRULE, unix.NLM_F_ACK) | ||||
| 	return ruleHandle(rule, req) | ||||
| } | ||||
|  | ||||
| func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error { | ||||
| 	msg := nl.NewRtMsg() | ||||
| 	msg.Family = unix.AF_INET | ||||
| 	msg.Protocol = unix.RTPROT_BOOT | ||||
| 	msg.Scope = unix.RT_SCOPE_UNIVERSE | ||||
| 	msg.Table = unix.RT_TABLE_UNSPEC | ||||
| 	msg.Type = unix.RTN_UNSPEC | ||||
| 	if req.NlMsghdr.Flags&unix.NLM_F_CREATE > 0 { | ||||
| 		msg.Type = unix.RTN_UNICAST | ||||
| 	} | ||||
| 	if rule.Invert { | ||||
| 		msg.Flags |= FibRuleInvert | ||||
| 	} | ||||
| 	if rule.Family != 0 { | ||||
| 		msg.Family = uint8(rule.Family) | ||||
| 	} | ||||
| 	if rule.Table >= 0 && rule.Table < 256 { | ||||
| 		msg.Table = uint8(rule.Table) | ||||
| 	} | ||||
|  | ||||
| 	var dstFamily uint8 | ||||
| 	var rtAttrs []*nl.RtAttr | ||||
| 	if rule.Dst != nil && rule.Dst.IP != nil { | ||||
| 		dstLen, _ := rule.Dst.Mask.Size() | ||||
| 		msg.Dst_len = uint8(dstLen) | ||||
| 		msg.Family = uint8(nl.GetIPFamily(rule.Dst.IP)) | ||||
| 		dstFamily = msg.Family | ||||
| 		var dstData []byte | ||||
| 		if msg.Family == unix.AF_INET { | ||||
| 			dstData = rule.Dst.IP.To4() | ||||
| 		} else { | ||||
| 			dstData = rule.Dst.IP.To16() | ||||
| 		} | ||||
| 		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, dstData)) | ||||
| 	} | ||||
|  | ||||
| 	if rule.Src != nil && rule.Src.IP != nil { | ||||
| 		msg.Family = uint8(nl.GetIPFamily(rule.Src.IP)) | ||||
| 		if dstFamily != 0 && dstFamily != msg.Family { | ||||
| 			return fmt.Errorf("source and destination ip are not the same IP family") | ||||
| 		} | ||||
| 		srcLen, _ := rule.Src.Mask.Size() | ||||
| 		msg.Src_len = uint8(srcLen) | ||||
| 		var srcData []byte | ||||
| 		if msg.Family == unix.AF_INET { | ||||
| 			srcData = rule.Src.IP.To4() | ||||
| 		} else { | ||||
| 			srcData = rule.Src.IP.To16() | ||||
| 		} | ||||
| 		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_SRC, srcData)) | ||||
| 	} | ||||
|  | ||||
| 	req.AddData(msg) | ||||
| 	for i := range rtAttrs { | ||||
| 		req.AddData(rtAttrs[i]) | ||||
| 	} | ||||
|  | ||||
| 	native := nl.NativeEndian() | ||||
|  | ||||
| 	if rule.Priority >= 0 { | ||||
| 		b := make([]byte, 4) | ||||
| 		native.PutUint32(b, uint32(rule.Priority)) | ||||
| 		req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b)) | ||||
| 	} | ||||
| 	if rule.Mark >= 0 { | ||||
| 		b := make([]byte, 4) | ||||
| 		native.PutUint32(b, uint32(rule.Mark)) | ||||
| 		req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b)) | ||||
| 	} | ||||
| 	if rule.Mask >= 0 { | ||||
| 		b := make([]byte, 4) | ||||
| 		native.PutUint32(b, uint32(rule.Mask)) | ||||
| 		req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b)) | ||||
| 	} | ||||
| 	if rule.Flow >= 0 { | ||||
| 		b := make([]byte, 4) | ||||
| 		native.PutUint32(b, uint32(rule.Flow)) | ||||
| 		req.AddData(nl.NewRtAttr(nl.FRA_FLOW, b)) | ||||
| 	} | ||||
| 	if rule.TunID > 0 { | ||||
| 		b := make([]byte, 4) | ||||
| 		native.PutUint32(b, uint32(rule.TunID)) | ||||
| 		req.AddData(nl.NewRtAttr(nl.FRA_TUN_ID, b)) | ||||
| 	} | ||||
| 	if rule.Table >= 256 { | ||||
| 		b := make([]byte, 4) | ||||
| 		native.PutUint32(b, uint32(rule.Table)) | ||||
| 		req.AddData(nl.NewRtAttr(nl.FRA_TABLE, b)) | ||||
| 	} | ||||
| 	if msg.Table > 0 { | ||||
| 		if rule.SuppressPrefixlen >= 0 { | ||||
| 			b := make([]byte, 4) | ||||
| 			native.PutUint32(b, uint32(rule.SuppressPrefixlen)) | ||||
| 			req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_PREFIXLEN, b)) | ||||
| 		} | ||||
| 		if rule.SuppressIfgroup >= 0 { | ||||
| 			b := make([]byte, 4) | ||||
| 			native.PutUint32(b, uint32(rule.SuppressIfgroup)) | ||||
| 			req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_IFGROUP, b)) | ||||
| 		} | ||||
| 	} | ||||
| 	if rule.IifName != "" { | ||||
| 		req.AddData(nl.NewRtAttr(nl.FRA_IIFNAME, []byte(rule.IifName))) | ||||
| 	} | ||||
| 	if rule.OifName != "" { | ||||
| 		req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName))) | ||||
| 	} | ||||
| 	if rule.Goto >= 0 { | ||||
| 		msg.Type = nl.FR_ACT_NOP | ||||
| 		b := make([]byte, 4) | ||||
| 		native.PutUint32(b, uint32(rule.Goto)) | ||||
| 		req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b)) | ||||
| 	} | ||||
|  | ||||
| 	_, err := req.Execute(unix.NETLINK_ROUTE, 0) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // RuleList lists rules in the system. | ||||
| // Equivalent to: ip rule list | ||||
| func RuleList(family int) ([]Rule, error) { | ||||
| 	return pkgHandle.RuleList(family) | ||||
| } | ||||
|  | ||||
| // RuleList lists rules in the system. | ||||
| // Equivalent to: ip rule list | ||||
| func (h *Handle) RuleList(family int) ([]Rule, error) { | ||||
| 	req := h.newNetlinkRequest(unix.RTM_GETRULE, unix.NLM_F_DUMP|unix.NLM_F_REQUEST) | ||||
| 	msg := nl.NewIfInfomsg(family) | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWRULE) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	native := nl.NativeEndian() | ||||
| 	var res = make([]Rule, 0) | ||||
| 	for i := range msgs { | ||||
| 		msg := nl.DeserializeRtMsg(msgs[i]) | ||||
| 		attrs, err := nl.ParseRouteAttr(msgs[i][msg.Len():]) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		rule := NewRule() | ||||
|  | ||||
| 		rule.Invert = msg.Flags&FibRuleInvert > 0 | ||||
|  | ||||
| 		for j := range attrs { | ||||
| 			switch attrs[j].Attr.Type { | ||||
| 			case unix.RTA_TABLE: | ||||
| 				rule.Table = int(native.Uint32(attrs[j].Value[0:4])) | ||||
| 			case nl.FRA_SRC: | ||||
| 				rule.Src = &net.IPNet{ | ||||
| 					IP:   attrs[j].Value, | ||||
| 					Mask: net.CIDRMask(int(msg.Src_len), 8*len(attrs[j].Value)), | ||||
| 				} | ||||
| 			case nl.FRA_DST: | ||||
| 				rule.Dst = &net.IPNet{ | ||||
| 					IP:   attrs[j].Value, | ||||
| 					Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attrs[j].Value)), | ||||
| 				} | ||||
| 			case nl.FRA_FWMARK: | ||||
| 				rule.Mark = int(native.Uint32(attrs[j].Value[0:4])) | ||||
| 			case nl.FRA_FWMASK: | ||||
| 				rule.Mask = int(native.Uint32(attrs[j].Value[0:4])) | ||||
| 			case nl.FRA_TUN_ID: | ||||
| 				rule.TunID = uint(native.Uint64(attrs[j].Value[0:4])) | ||||
| 			case nl.FRA_IIFNAME: | ||||
| 				rule.IifName = string(attrs[j].Value[:len(attrs[j].Value)-1]) | ||||
| 			case nl.FRA_OIFNAME: | ||||
| 				rule.OifName = string(attrs[j].Value[:len(attrs[j].Value)-1]) | ||||
| 			case nl.FRA_SUPPRESS_PREFIXLEN: | ||||
| 				i := native.Uint32(attrs[j].Value[0:4]) | ||||
| 				if i != 0xffffffff { | ||||
| 					rule.SuppressPrefixlen = int(i) | ||||
| 				} | ||||
| 			case nl.FRA_SUPPRESS_IFGROUP: | ||||
| 				i := native.Uint32(attrs[j].Value[0:4]) | ||||
| 				if i != 0xffffffff { | ||||
| 					rule.SuppressIfgroup = int(i) | ||||
| 				} | ||||
| 			case nl.FRA_FLOW: | ||||
| 				rule.Flow = int(native.Uint32(attrs[j].Value[0:4])) | ||||
| 			case nl.FRA_GOTO: | ||||
| 				rule.Goto = int(native.Uint32(attrs[j].Value[0:4])) | ||||
| 			case nl.FRA_PRIORITY: | ||||
| 				rule.Priority = int(native.Uint32(attrs[j].Value[0:4])) | ||||
| 			} | ||||
| 		} | ||||
| 		res = append(res, *rule) | ||||
| 	} | ||||
|  | ||||
| 	return res, nil | ||||
| } | ||||
							
								
								
									
										27
									
								
								vendor/github.com/vishvananda/netlink/socket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/vishvananda/netlink/socket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| package netlink | ||||
|  | ||||
| import "net" | ||||
|  | ||||
| // SocketID identifies a single socket. | ||||
| type SocketID struct { | ||||
| 	SourcePort      uint16 | ||||
| 	DestinationPort uint16 | ||||
| 	Source          net.IP | ||||
| 	Destination     net.IP | ||||
| 	Interface       uint32 | ||||
| 	Cookie          [2]uint32 | ||||
| } | ||||
|  | ||||
| // Socket represents a netlink socket. | ||||
| type Socket struct { | ||||
| 	Family  uint8 | ||||
| 	State   uint8 | ||||
| 	Timer   uint8 | ||||
| 	Retrans uint8 | ||||
| 	ID      SocketID | ||||
| 	Expires uint32 | ||||
| 	RQueue  uint32 | ||||
| 	WQueue  uint32 | ||||
| 	UID     uint32 | ||||
| 	INode   uint32 | ||||
| } | ||||
							
								
								
									
										159
									
								
								vendor/github.com/vishvananda/netlink/socket_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								vendor/github.com/vishvananda/netlink/socket_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	sizeofSocketID      = 0x30 | ||||
| 	sizeofSocketRequest = sizeofSocketID + 0x8 | ||||
| 	sizeofSocket        = sizeofSocketID + 0x18 | ||||
| ) | ||||
|  | ||||
| type socketRequest struct { | ||||
| 	Family   uint8 | ||||
| 	Protocol uint8 | ||||
| 	Ext      uint8 | ||||
| 	pad      uint8 | ||||
| 	States   uint32 | ||||
| 	ID       SocketID | ||||
| } | ||||
|  | ||||
| type writeBuffer struct { | ||||
| 	Bytes []byte | ||||
| 	pos   int | ||||
| } | ||||
|  | ||||
| func (b *writeBuffer) Write(c byte) { | ||||
| 	b.Bytes[b.pos] = c | ||||
| 	b.pos++ | ||||
| } | ||||
|  | ||||
| func (b *writeBuffer) Next(n int) []byte { | ||||
| 	s := b.Bytes[b.pos : b.pos+n] | ||||
| 	b.pos += n | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| func (r *socketRequest) Serialize() []byte { | ||||
| 	b := writeBuffer{Bytes: make([]byte, sizeofSocketRequest)} | ||||
| 	b.Write(r.Family) | ||||
| 	b.Write(r.Protocol) | ||||
| 	b.Write(r.Ext) | ||||
| 	b.Write(r.pad) | ||||
| 	native.PutUint32(b.Next(4), r.States) | ||||
| 	networkOrder.PutUint16(b.Next(2), r.ID.SourcePort) | ||||
| 	networkOrder.PutUint16(b.Next(2), r.ID.DestinationPort) | ||||
| 	copy(b.Next(4), r.ID.Source.To4()) | ||||
| 	b.Next(12) | ||||
| 	copy(b.Next(4), r.ID.Destination.To4()) | ||||
| 	b.Next(12) | ||||
| 	native.PutUint32(b.Next(4), r.ID.Interface) | ||||
| 	native.PutUint32(b.Next(4), r.ID.Cookie[0]) | ||||
| 	native.PutUint32(b.Next(4), r.ID.Cookie[1]) | ||||
| 	return b.Bytes | ||||
| } | ||||
|  | ||||
| func (r *socketRequest) Len() int { return sizeofSocketRequest } | ||||
|  | ||||
| type readBuffer struct { | ||||
| 	Bytes []byte | ||||
| 	pos   int | ||||
| } | ||||
|  | ||||
| func (b *readBuffer) Read() byte { | ||||
| 	c := b.Bytes[b.pos] | ||||
| 	b.pos++ | ||||
| 	return c | ||||
| } | ||||
|  | ||||
| func (b *readBuffer) Next(n int) []byte { | ||||
| 	s := b.Bytes[b.pos : b.pos+n] | ||||
| 	b.pos += n | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| func (s *Socket) deserialize(b []byte) error { | ||||
| 	if len(b) < sizeofSocket { | ||||
| 		return fmt.Errorf("socket data short read (%d); want %d", len(b), sizeofSocket) | ||||
| 	} | ||||
| 	rb := readBuffer{Bytes: b} | ||||
| 	s.Family = rb.Read() | ||||
| 	s.State = rb.Read() | ||||
| 	s.Timer = rb.Read() | ||||
| 	s.Retrans = rb.Read() | ||||
| 	s.ID.SourcePort = networkOrder.Uint16(rb.Next(2)) | ||||
| 	s.ID.DestinationPort = networkOrder.Uint16(rb.Next(2)) | ||||
| 	s.ID.Source = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) | ||||
| 	rb.Next(12) | ||||
| 	s.ID.Destination = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) | ||||
| 	rb.Next(12) | ||||
| 	s.ID.Interface = native.Uint32(rb.Next(4)) | ||||
| 	s.ID.Cookie[0] = native.Uint32(rb.Next(4)) | ||||
| 	s.ID.Cookie[1] = native.Uint32(rb.Next(4)) | ||||
| 	s.Expires = native.Uint32(rb.Next(4)) | ||||
| 	s.RQueue = native.Uint32(rb.Next(4)) | ||||
| 	s.WQueue = native.Uint32(rb.Next(4)) | ||||
| 	s.UID = native.Uint32(rb.Next(4)) | ||||
| 	s.INode = native.Uint32(rb.Next(4)) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // SocketGet returns the Socket identified by its local and remote addresses. | ||||
| func SocketGet(local, remote net.Addr) (*Socket, error) { | ||||
| 	localTCP, ok := local.(*net.TCPAddr) | ||||
| 	if !ok { | ||||
| 		return nil, ErrNotImplemented | ||||
| 	} | ||||
| 	remoteTCP, ok := remote.(*net.TCPAddr) | ||||
| 	if !ok { | ||||
| 		return nil, ErrNotImplemented | ||||
| 	} | ||||
| 	localIP := localTCP.IP.To4() | ||||
| 	if localIP == nil { | ||||
| 		return nil, ErrNotImplemented | ||||
| 	} | ||||
| 	remoteIP := remoteTCP.IP.To4() | ||||
| 	if remoteIP == nil { | ||||
| 		return nil, ErrNotImplemented | ||||
| 	} | ||||
|  | ||||
| 	s, err := nl.Subscribe(unix.NETLINK_INET_DIAG) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer s.Close() | ||||
| 	req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, 0) | ||||
| 	req.AddData(&socketRequest{ | ||||
| 		Family:   unix.AF_INET, | ||||
| 		Protocol: unix.IPPROTO_TCP, | ||||
| 		ID: SocketID{ | ||||
| 			SourcePort:      uint16(localTCP.Port), | ||||
| 			DestinationPort: uint16(remoteTCP.Port), | ||||
| 			Source:          localIP, | ||||
| 			Destination:     remoteIP, | ||||
| 			Cookie:          [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE}, | ||||
| 		}, | ||||
| 	}) | ||||
| 	s.Send(req) | ||||
| 	msgs, err := s.Receive() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if len(msgs) == 0 { | ||||
| 		return nil, errors.New("no message nor error from netlink") | ||||
| 	} | ||||
| 	if len(msgs) > 2 { | ||||
| 		return nil, fmt.Errorf("multiple (%d) matching sockets", len(msgs)) | ||||
| 	} | ||||
| 	sock := &Socket{} | ||||
| 	if err := sock.deserialize(msgs[0].Data); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return sock, nil | ||||
| } | ||||
							
								
								
									
										75
									
								
								vendor/github.com/vishvananda/netlink/xfrm.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								vendor/github.com/vishvananda/netlink/xfrm.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| // Proto is an enum representing an ipsec protocol. | ||||
| type Proto uint8 | ||||
|  | ||||
| const ( | ||||
| 	XFRM_PROTO_ROUTE2    Proto = unix.IPPROTO_ROUTING | ||||
| 	XFRM_PROTO_ESP       Proto = unix.IPPROTO_ESP | ||||
| 	XFRM_PROTO_AH        Proto = unix.IPPROTO_AH | ||||
| 	XFRM_PROTO_HAO       Proto = unix.IPPROTO_DSTOPTS | ||||
| 	XFRM_PROTO_COMP      Proto = 0x6c // NOTE not defined on darwin | ||||
| 	XFRM_PROTO_IPSEC_ANY Proto = unix.IPPROTO_RAW | ||||
| ) | ||||
|  | ||||
| func (p Proto) String() string { | ||||
| 	switch p { | ||||
| 	case XFRM_PROTO_ROUTE2: | ||||
| 		return "route2" | ||||
| 	case XFRM_PROTO_ESP: | ||||
| 		return "esp" | ||||
| 	case XFRM_PROTO_AH: | ||||
| 		return "ah" | ||||
| 	case XFRM_PROTO_HAO: | ||||
| 		return "hao" | ||||
| 	case XFRM_PROTO_COMP: | ||||
| 		return "comp" | ||||
| 	case XFRM_PROTO_IPSEC_ANY: | ||||
| 		return "ipsec-any" | ||||
| 	} | ||||
| 	return fmt.Sprintf("%d", p) | ||||
| } | ||||
|  | ||||
| // Mode is an enum representing an ipsec transport. | ||||
| type Mode uint8 | ||||
|  | ||||
| const ( | ||||
| 	XFRM_MODE_TRANSPORT Mode = iota | ||||
| 	XFRM_MODE_TUNNEL | ||||
| 	XFRM_MODE_ROUTEOPTIMIZATION | ||||
| 	XFRM_MODE_IN_TRIGGER | ||||
| 	XFRM_MODE_BEET | ||||
| 	XFRM_MODE_MAX | ||||
| ) | ||||
|  | ||||
| func (m Mode) String() string { | ||||
| 	switch m { | ||||
| 	case XFRM_MODE_TRANSPORT: | ||||
| 		return "transport" | ||||
| 	case XFRM_MODE_TUNNEL: | ||||
| 		return "tunnel" | ||||
| 	case XFRM_MODE_ROUTEOPTIMIZATION: | ||||
| 		return "ro" | ||||
| 	case XFRM_MODE_IN_TRIGGER: | ||||
| 		return "in_trigger" | ||||
| 	case XFRM_MODE_BEET: | ||||
| 		return "beet" | ||||
| 	} | ||||
| 	return fmt.Sprintf("%d", m) | ||||
| } | ||||
|  | ||||
| // XfrmMark represents the mark associated to the state or policy | ||||
| type XfrmMark struct { | ||||
| 	Value uint32 | ||||
| 	Mask  uint32 | ||||
| } | ||||
|  | ||||
| func (m *XfrmMark) String() string { | ||||
| 	return fmt.Sprintf("(0x%x,0x%x)", m.Value, m.Mask) | ||||
| } | ||||
							
								
								
									
										97
									
								
								vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"github.com/vishvananda/netns" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| type XfrmMsg interface { | ||||
| 	Type() nl.XfrmMsgType | ||||
| } | ||||
|  | ||||
| type XfrmMsgExpire struct { | ||||
| 	XfrmState *XfrmState | ||||
| 	Hard      bool | ||||
| } | ||||
|  | ||||
| func (ue *XfrmMsgExpire) Type() nl.XfrmMsgType { | ||||
| 	return nl.XFRM_MSG_EXPIRE | ||||
| } | ||||
|  | ||||
| func parseXfrmMsgExpire(b []byte) *XfrmMsgExpire { | ||||
| 	var e XfrmMsgExpire | ||||
|  | ||||
| 	msg := nl.DeserializeXfrmUserExpire(b) | ||||
| 	e.XfrmState = xfrmStateFromXfrmUsersaInfo(&msg.XfrmUsersaInfo) | ||||
| 	e.Hard = msg.Hard == 1 | ||||
|  | ||||
| 	return &e | ||||
| } | ||||
|  | ||||
| func XfrmMonitor(ch chan<- XfrmMsg, done <-chan struct{}, errorChan chan<- error, | ||||
| 	types ...nl.XfrmMsgType) error { | ||||
|  | ||||
| 	groups, err := xfrmMcastGroups(types) | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_XFRM, groups...) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if done != nil { | ||||
| 		go func() { | ||||
| 			<-done | ||||
| 			s.Close() | ||||
| 		}() | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	go func() { | ||||
| 		defer close(ch) | ||||
| 		for { | ||||
| 			msgs, err := s.Receive() | ||||
| 			if err != nil { | ||||
| 				errorChan <- err | ||||
| 				return | ||||
| 			} | ||||
| 			for _, m := range msgs { | ||||
| 				switch m.Header.Type { | ||||
| 				case nl.XFRM_MSG_EXPIRE: | ||||
| 					ch <- parseXfrmMsgExpire(m.Data) | ||||
| 				default: | ||||
| 					errorChan <- fmt.Errorf("unsupported msg type: %x", m.Header.Type) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func xfrmMcastGroups(types []nl.XfrmMsgType) ([]uint, error) { | ||||
| 	groups := make([]uint, 0) | ||||
|  | ||||
| 	if len(types) == 0 { | ||||
| 		return nil, fmt.Errorf("no xfrm msg type specified") | ||||
| 	} | ||||
|  | ||||
| 	for _, t := range types { | ||||
| 		var group uint | ||||
|  | ||||
| 		switch t { | ||||
| 		case nl.XFRM_MSG_EXPIRE: | ||||
| 			group = nl.XFRMNLGRP_EXPIRE | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("unsupported group: %x", t) | ||||
| 		} | ||||
|  | ||||
| 		groups = append(groups, group) | ||||
| 	} | ||||
|  | ||||
| 	return groups, nil | ||||
| } | ||||
							
								
								
									
										74
									
								
								vendor/github.com/vishvananda/netlink/xfrm_policy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								vendor/github.com/vishvananda/netlink/xfrm_policy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| ) | ||||
|  | ||||
| // Dir is an enum representing an ipsec template direction. | ||||
| type Dir uint8 | ||||
|  | ||||
| const ( | ||||
| 	XFRM_DIR_IN Dir = iota | ||||
| 	XFRM_DIR_OUT | ||||
| 	XFRM_DIR_FWD | ||||
| 	XFRM_SOCKET_IN | ||||
| 	XFRM_SOCKET_OUT | ||||
| 	XFRM_SOCKET_FWD | ||||
| ) | ||||
|  | ||||
| func (d Dir) String() string { | ||||
| 	switch d { | ||||
| 	case XFRM_DIR_IN: | ||||
| 		return "dir in" | ||||
| 	case XFRM_DIR_OUT: | ||||
| 		return "dir out" | ||||
| 	case XFRM_DIR_FWD: | ||||
| 		return "dir fwd" | ||||
| 	case XFRM_SOCKET_IN: | ||||
| 		return "socket in" | ||||
| 	case XFRM_SOCKET_OUT: | ||||
| 		return "socket out" | ||||
| 	case XFRM_SOCKET_FWD: | ||||
| 		return "socket fwd" | ||||
| 	} | ||||
| 	return fmt.Sprintf("socket %d", d-XFRM_SOCKET_IN) | ||||
| } | ||||
|  | ||||
| // XfrmPolicyTmpl encapsulates a rule for the base addresses of an ipsec | ||||
| // policy. These rules are matched with XfrmState to determine encryption | ||||
| // and authentication algorithms. | ||||
| type XfrmPolicyTmpl struct { | ||||
| 	Dst   net.IP | ||||
| 	Src   net.IP | ||||
| 	Proto Proto | ||||
| 	Mode  Mode | ||||
| 	Spi   int | ||||
| 	Reqid int | ||||
| } | ||||
|  | ||||
| func (t XfrmPolicyTmpl) String() string { | ||||
| 	return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, Mode: %s, Spi: 0x%x, Reqid: 0x%x}", | ||||
| 		t.Dst, t.Src, t.Proto, t.Mode, t.Spi, t.Reqid) | ||||
| } | ||||
|  | ||||
| // XfrmPolicy represents an ipsec policy. It represents the overlay network | ||||
| // and has a list of XfrmPolicyTmpls representing the base addresses of | ||||
| // the policy. | ||||
| type XfrmPolicy struct { | ||||
| 	Dst      *net.IPNet | ||||
| 	Src      *net.IPNet | ||||
| 	Proto    Proto | ||||
| 	DstPort  int | ||||
| 	SrcPort  int | ||||
| 	Dir      Dir | ||||
| 	Priority int | ||||
| 	Index    int | ||||
| 	Mark     *XfrmMark | ||||
| 	Tmpls    []XfrmPolicyTmpl | ||||
| } | ||||
|  | ||||
| func (p XfrmPolicy) String() string { | ||||
| 	return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Mark: %s, Tmpls: %s}", | ||||
| 		p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Mark, p.Tmpls) | ||||
| } | ||||
							
								
								
									
										256
									
								
								vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,256 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) { | ||||
| 	sel.Family = uint16(nl.FAMILY_V4) | ||||
| 	if policy.Dst != nil { | ||||
| 		sel.Family = uint16(nl.GetIPFamily(policy.Dst.IP)) | ||||
| 		sel.Daddr.FromIP(policy.Dst.IP) | ||||
| 		prefixlenD, _ := policy.Dst.Mask.Size() | ||||
| 		sel.PrefixlenD = uint8(prefixlenD) | ||||
| 	} | ||||
| 	if policy.Src != nil { | ||||
| 		sel.Saddr.FromIP(policy.Src.IP) | ||||
| 		prefixlenS, _ := policy.Src.Mask.Size() | ||||
| 		sel.PrefixlenS = uint8(prefixlenS) | ||||
| 	} | ||||
| 	sel.Proto = uint8(policy.Proto) | ||||
| 	sel.Dport = nl.Swap16(uint16(policy.DstPort)) | ||||
| 	sel.Sport = nl.Swap16(uint16(policy.SrcPort)) | ||||
| 	if sel.Dport != 0 { | ||||
| 		sel.DportMask = ^uint16(0) | ||||
| 	} | ||||
| 	if sel.Sport != 0 { | ||||
| 		sel.SportMask = ^uint16(0) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // XfrmPolicyAdd will add an xfrm policy to the system. | ||||
| // Equivalent to: `ip xfrm policy add $policy` | ||||
| func XfrmPolicyAdd(policy *XfrmPolicy) error { | ||||
| 	return pkgHandle.XfrmPolicyAdd(policy) | ||||
| } | ||||
|  | ||||
| // XfrmPolicyAdd will add an xfrm policy to the system. | ||||
| // Equivalent to: `ip xfrm policy add $policy` | ||||
| func (h *Handle) XfrmPolicyAdd(policy *XfrmPolicy) error { | ||||
| 	return h.xfrmPolicyAddOrUpdate(policy, nl.XFRM_MSG_NEWPOLICY) | ||||
| } | ||||
|  | ||||
| // XfrmPolicyUpdate will update an xfrm policy to the system. | ||||
| // Equivalent to: `ip xfrm policy update $policy` | ||||
| func XfrmPolicyUpdate(policy *XfrmPolicy) error { | ||||
| 	return pkgHandle.XfrmPolicyUpdate(policy) | ||||
| } | ||||
|  | ||||
| // XfrmPolicyUpdate will update an xfrm policy to the system. | ||||
| // Equivalent to: `ip xfrm policy update $policy` | ||||
| func (h *Handle) XfrmPolicyUpdate(policy *XfrmPolicy) error { | ||||
| 	return h.xfrmPolicyAddOrUpdate(policy, nl.XFRM_MSG_UPDPOLICY) | ||||
| } | ||||
|  | ||||
| func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error { | ||||
| 	req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) | ||||
|  | ||||
| 	msg := &nl.XfrmUserpolicyInfo{} | ||||
| 	selFromPolicy(&msg.Sel, policy) | ||||
| 	msg.Priority = uint32(policy.Priority) | ||||
| 	msg.Index = uint32(policy.Index) | ||||
| 	msg.Dir = uint8(policy.Dir) | ||||
| 	msg.Lft.SoftByteLimit = nl.XFRM_INF | ||||
| 	msg.Lft.HardByteLimit = nl.XFRM_INF | ||||
| 	msg.Lft.SoftPacketLimit = nl.XFRM_INF | ||||
| 	msg.Lft.HardPacketLimit = nl.XFRM_INF | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	tmplData := make([]byte, nl.SizeofXfrmUserTmpl*len(policy.Tmpls)) | ||||
| 	for i, tmpl := range policy.Tmpls { | ||||
| 		start := i * nl.SizeofXfrmUserTmpl | ||||
| 		userTmpl := nl.DeserializeXfrmUserTmpl(tmplData[start : start+nl.SizeofXfrmUserTmpl]) | ||||
| 		userTmpl.XfrmId.Daddr.FromIP(tmpl.Dst) | ||||
| 		userTmpl.Saddr.FromIP(tmpl.Src) | ||||
| 		userTmpl.XfrmId.Proto = uint8(tmpl.Proto) | ||||
| 		userTmpl.XfrmId.Spi = nl.Swap32(uint32(tmpl.Spi)) | ||||
| 		userTmpl.Mode = uint8(tmpl.Mode) | ||||
| 		userTmpl.Reqid = uint32(tmpl.Reqid) | ||||
| 		userTmpl.Aalgos = ^uint32(0) | ||||
| 		userTmpl.Ealgos = ^uint32(0) | ||||
| 		userTmpl.Calgos = ^uint32(0) | ||||
| 	} | ||||
| 	if len(tmplData) > 0 { | ||||
| 		tmpls := nl.NewRtAttr(nl.XFRMA_TMPL, tmplData) | ||||
| 		req.AddData(tmpls) | ||||
| 	} | ||||
| 	if policy.Mark != nil { | ||||
| 		out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark)) | ||||
| 		req.AddData(out) | ||||
| 	} | ||||
|  | ||||
| 	_, err := req.Execute(unix.NETLINK_XFRM, 0) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // XfrmPolicyDel will delete an xfrm policy from the system. Note that | ||||
| // the Tmpls are ignored when matching the policy to delete. | ||||
| // Equivalent to: `ip xfrm policy del $policy` | ||||
| func XfrmPolicyDel(policy *XfrmPolicy) error { | ||||
| 	return pkgHandle.XfrmPolicyDel(policy) | ||||
| } | ||||
|  | ||||
| // XfrmPolicyDel will delete an xfrm policy from the system. Note that | ||||
| // the Tmpls are ignored when matching the policy to delete. | ||||
| // Equivalent to: `ip xfrm policy del $policy` | ||||
| func (h *Handle) XfrmPolicyDel(policy *XfrmPolicy) error { | ||||
| 	_, err := h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_DELPOLICY) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // XfrmPolicyList gets a list of xfrm policies in the system. | ||||
| // Equivalent to: `ip xfrm policy show`. | ||||
| // The list can be filtered by ip family. | ||||
| func XfrmPolicyList(family int) ([]XfrmPolicy, error) { | ||||
| 	return pkgHandle.XfrmPolicyList(family) | ||||
| } | ||||
|  | ||||
| // XfrmPolicyList gets a list of xfrm policies in the system. | ||||
| // Equivalent to: `ip xfrm policy show`. | ||||
| // The list can be filtered by ip family. | ||||
| func (h *Handle) XfrmPolicyList(family int) ([]XfrmPolicy, error) { | ||||
| 	req := h.newNetlinkRequest(nl.XFRM_MSG_GETPOLICY, unix.NLM_F_DUMP) | ||||
|  | ||||
| 	msg := nl.NewIfInfomsg(family) | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	var res []XfrmPolicy | ||||
| 	for _, m := range msgs { | ||||
| 		if policy, err := parseXfrmPolicy(m, family); err == nil { | ||||
| 			res = append(res, *policy) | ||||
| 		} else if err == familyError { | ||||
| 			continue | ||||
| 		} else { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	return res, nil | ||||
| } | ||||
|  | ||||
| // XfrmPolicyGet gets a the policy described by the index or selector, if found. | ||||
| // Equivalent to: `ip xfrm policy get { SELECTOR | index INDEX } dir DIR [ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]`. | ||||
| func XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) { | ||||
| 	return pkgHandle.XfrmPolicyGet(policy) | ||||
| } | ||||
|  | ||||
| // XfrmPolicyGet gets a the policy described by the index or selector, if found. | ||||
| // Equivalent to: `ip xfrm policy get { SELECTOR | index INDEX } dir DIR [ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]`. | ||||
| func (h *Handle) XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) { | ||||
| 	return h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_GETPOLICY) | ||||
| } | ||||
|  | ||||
| // XfrmPolicyFlush will flush the policies on the system. | ||||
| // Equivalent to: `ip xfrm policy flush` | ||||
| func XfrmPolicyFlush() error { | ||||
| 	return pkgHandle.XfrmPolicyFlush() | ||||
| } | ||||
|  | ||||
| // XfrmPolicyFlush will flush the policies on the system. | ||||
| // Equivalent to: `ip xfrm policy flush` | ||||
| func (h *Handle) XfrmPolicyFlush() error { | ||||
| 	req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHPOLICY, unix.NLM_F_ACK) | ||||
| 	_, err := req.Execute(unix.NETLINK_XFRM, 0) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPolicy, error) { | ||||
| 	req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK) | ||||
|  | ||||
| 	msg := &nl.XfrmUserpolicyId{} | ||||
| 	selFromPolicy(&msg.Sel, policy) | ||||
| 	msg.Index = uint32(policy.Index) | ||||
| 	msg.Dir = uint8(policy.Dir) | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	if policy.Mark != nil { | ||||
| 		out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark)) | ||||
| 		req.AddData(out) | ||||
| 	} | ||||
|  | ||||
| 	resType := nl.XFRM_MSG_NEWPOLICY | ||||
| 	if nlProto == nl.XFRM_MSG_DELPOLICY { | ||||
| 		resType = 0 | ||||
| 	} | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if nlProto == nl.XFRM_MSG_DELPOLICY { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	p, err := parseXfrmPolicy(msgs[0], FAMILY_ALL) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return p, nil | ||||
| } | ||||
|  | ||||
| func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) { | ||||
| 	msg := nl.DeserializeXfrmUserpolicyInfo(m) | ||||
|  | ||||
| 	// This is mainly for the policy dump | ||||
| 	if family != FAMILY_ALL && family != int(msg.Sel.Family) { | ||||
| 		return nil, familyError | ||||
| 	} | ||||
|  | ||||
| 	var policy XfrmPolicy | ||||
|  | ||||
| 	policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD) | ||||
| 	policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS) | ||||
| 	policy.Proto = Proto(msg.Sel.Proto) | ||||
| 	policy.DstPort = int(nl.Swap16(msg.Sel.Dport)) | ||||
| 	policy.SrcPort = int(nl.Swap16(msg.Sel.Sport)) | ||||
| 	policy.Priority = int(msg.Priority) | ||||
| 	policy.Index = int(msg.Index) | ||||
| 	policy.Dir = Dir(msg.Dir) | ||||
|  | ||||
| 	attrs, err := nl.ParseRouteAttr(m[msg.Len():]) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	for _, attr := range attrs { | ||||
| 		switch attr.Attr.Type { | ||||
| 		case nl.XFRMA_TMPL: | ||||
| 			max := len(attr.Value) | ||||
| 			for i := 0; i < max; i += nl.SizeofXfrmUserTmpl { | ||||
| 				var resTmpl XfrmPolicyTmpl | ||||
| 				tmpl := nl.DeserializeXfrmUserTmpl(attr.Value[i : i+nl.SizeofXfrmUserTmpl]) | ||||
| 				resTmpl.Dst = tmpl.XfrmId.Daddr.ToIP() | ||||
| 				resTmpl.Src = tmpl.Saddr.ToIP() | ||||
| 				resTmpl.Proto = Proto(tmpl.XfrmId.Proto) | ||||
| 				resTmpl.Mode = Mode(tmpl.Mode) | ||||
| 				resTmpl.Spi = int(nl.Swap32(tmpl.XfrmId.Spi)) | ||||
| 				resTmpl.Reqid = int(tmpl.Reqid) | ||||
| 				policy.Tmpls = append(policy.Tmpls, resTmpl) | ||||
| 			} | ||||
| 		case nl.XFRMA_MARK: | ||||
| 			mark := nl.DeserializeXfrmMark(attr.Value[:]) | ||||
| 			policy.Mark = new(XfrmMark) | ||||
| 			policy.Mark.Value = mark.Value | ||||
| 			policy.Mark.Mask = mark.Mask | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return &policy, nil | ||||
| } | ||||
							
								
								
									
										129
									
								
								vendor/github.com/vishvananda/netlink/xfrm_state.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								vendor/github.com/vishvananda/netlink/xfrm_state.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // XfrmStateAlgo represents the algorithm to use for the ipsec encryption. | ||||
| type XfrmStateAlgo struct { | ||||
| 	Name        string | ||||
| 	Key         []byte | ||||
| 	TruncateLen int // Auth only | ||||
| 	ICVLen      int // AEAD only | ||||
| } | ||||
|  | ||||
| func (a XfrmStateAlgo) String() string { | ||||
| 	base := fmt.Sprintf("{Name: %s, Key: 0x%x", a.Name, a.Key) | ||||
| 	if a.TruncateLen != 0 { | ||||
| 		base = fmt.Sprintf("%s, Truncate length: %d", base, a.TruncateLen) | ||||
| 	} | ||||
| 	if a.ICVLen != 0 { | ||||
| 		base = fmt.Sprintf("%s, ICV length: %d", base, a.ICVLen) | ||||
| 	} | ||||
| 	return fmt.Sprintf("%s}", base) | ||||
| } | ||||
|  | ||||
| // EncapType is an enum representing the optional packet encapsulation. | ||||
| type EncapType uint8 | ||||
|  | ||||
| const ( | ||||
| 	XFRM_ENCAP_ESPINUDP_NONIKE EncapType = iota + 1 | ||||
| 	XFRM_ENCAP_ESPINUDP | ||||
| ) | ||||
|  | ||||
| func (e EncapType) String() string { | ||||
| 	switch e { | ||||
| 	case XFRM_ENCAP_ESPINUDP_NONIKE: | ||||
| 		return "espinudp-non-ike" | ||||
| 	case XFRM_ENCAP_ESPINUDP: | ||||
| 		return "espinudp" | ||||
| 	} | ||||
| 	return "unknown" | ||||
| } | ||||
|  | ||||
| // XfrmStateEncap represents the encapsulation to use for the ipsec encryption. | ||||
| type XfrmStateEncap struct { | ||||
| 	Type            EncapType | ||||
| 	SrcPort         int | ||||
| 	DstPort         int | ||||
| 	OriginalAddress net.IP | ||||
| } | ||||
|  | ||||
| func (e XfrmStateEncap) String() string { | ||||
| 	return fmt.Sprintf("{Type: %s, Srcport: %d, DstPort: %d, OriginalAddress: %v}", | ||||
| 		e.Type, e.SrcPort, e.DstPort, e.OriginalAddress) | ||||
| } | ||||
|  | ||||
| // XfrmStateLimits represents the configured limits for the state. | ||||
| type XfrmStateLimits struct { | ||||
| 	ByteSoft    uint64 | ||||
| 	ByteHard    uint64 | ||||
| 	PacketSoft  uint64 | ||||
| 	PacketHard  uint64 | ||||
| 	TimeSoft    uint64 | ||||
| 	TimeHard    uint64 | ||||
| 	TimeUseSoft uint64 | ||||
| 	TimeUseHard uint64 | ||||
| } | ||||
|  | ||||
| // XfrmStateStats represents the current number of bytes/packets | ||||
| // processed by this State, the State's installation and first use | ||||
| // time and the replay window counters. | ||||
| type XfrmStateStats struct { | ||||
| 	ReplayWindow uint32 | ||||
| 	Replay       uint32 | ||||
| 	Failed       uint32 | ||||
| 	Bytes        uint64 | ||||
| 	Packets      uint64 | ||||
| 	AddTime      uint64 | ||||
| 	UseTime      uint64 | ||||
| } | ||||
|  | ||||
| // XfrmState represents the state of an ipsec policy. It optionally | ||||
| // contains an XfrmStateAlgo for encryption and one for authentication. | ||||
| type XfrmState struct { | ||||
| 	Dst          net.IP | ||||
| 	Src          net.IP | ||||
| 	Proto        Proto | ||||
| 	Mode         Mode | ||||
| 	Spi          int | ||||
| 	Reqid        int | ||||
| 	ReplayWindow int | ||||
| 	Limits       XfrmStateLimits | ||||
| 	Statistics   XfrmStateStats | ||||
| 	Mark         *XfrmMark | ||||
| 	Auth         *XfrmStateAlgo | ||||
| 	Crypt        *XfrmStateAlgo | ||||
| 	Aead         *XfrmStateAlgo | ||||
| 	Encap        *XfrmStateEncap | ||||
| 	ESN          bool | ||||
| } | ||||
|  | ||||
| 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", | ||||
| 		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) | ||||
| } | ||||
| func (sa XfrmState) Print(stats bool) string { | ||||
| 	if !stats { | ||||
| 		return sa.String() | ||||
| 	} | ||||
| 	at := time.Unix(int64(sa.Statistics.AddTime), 0).Format(time.UnixDate) | ||||
| 	ut := "-" | ||||
| 	if sa.Statistics.UseTime > 0 { | ||||
| 		ut = time.Unix(int64(sa.Statistics.UseTime), 0).Format(time.UnixDate) | ||||
| 	} | ||||
| 	return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d, Bytes: %d, Packets: %d, "+ | ||||
| 		"AddTime: %s, UseTime: %s, ReplayWindow: %d, Replay: %d, Failed: %d", | ||||
| 		sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard), | ||||
| 		sa.Limits.TimeSoft, sa.Limits.TimeHard, sa.Limits.TimeUseSoft, sa.Limits.TimeUseHard, sa.Statistics.Bytes, sa.Statistics.Packets, at, ut, | ||||
| 		sa.Statistics.ReplayWindow, sa.Statistics.Replay, sa.Statistics.Failed) | ||||
| } | ||||
|  | ||||
| func printLimit(lmt uint64) string { | ||||
| 	if lmt == ^uint64(0) { | ||||
| 		return "(INF)" | ||||
| 	} | ||||
| 	return fmt.Sprintf("%d", lmt) | ||||
| } | ||||
							
								
								
									
										457
									
								
								vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										457
									
								
								vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,457 @@ | ||||
| package netlink | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/vishvananda/netlink/nl" | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
|  | ||||
| func writeStateAlgo(a *XfrmStateAlgo) []byte { | ||||
| 	algo := nl.XfrmAlgo{ | ||||
| 		AlgKeyLen: uint32(len(a.Key) * 8), | ||||
| 		AlgKey:    a.Key, | ||||
| 	} | ||||
| 	end := len(a.Name) | ||||
| 	if end > 64 { | ||||
| 		end = 64 | ||||
| 	} | ||||
| 	copy(algo.AlgName[:end], a.Name) | ||||
| 	return algo.Serialize() | ||||
| } | ||||
|  | ||||
| func writeStateAlgoAuth(a *XfrmStateAlgo) []byte { | ||||
| 	algo := nl.XfrmAlgoAuth{ | ||||
| 		AlgKeyLen:   uint32(len(a.Key) * 8), | ||||
| 		AlgTruncLen: uint32(a.TruncateLen), | ||||
| 		AlgKey:      a.Key, | ||||
| 	} | ||||
| 	end := len(a.Name) | ||||
| 	if end > 64 { | ||||
| 		end = 64 | ||||
| 	} | ||||
| 	copy(algo.AlgName[:end], a.Name) | ||||
| 	return algo.Serialize() | ||||
| } | ||||
|  | ||||
| func writeStateAlgoAead(a *XfrmStateAlgo) []byte { | ||||
| 	algo := nl.XfrmAlgoAEAD{ | ||||
| 		AlgKeyLen: uint32(len(a.Key) * 8), | ||||
| 		AlgICVLen: uint32(a.ICVLen), | ||||
| 		AlgKey:    a.Key, | ||||
| 	} | ||||
| 	end := len(a.Name) | ||||
| 	if end > 64 { | ||||
| 		end = 64 | ||||
| 	} | ||||
| 	copy(algo.AlgName[:end], a.Name) | ||||
| 	return algo.Serialize() | ||||
| } | ||||
|  | ||||
| func writeMark(m *XfrmMark) []byte { | ||||
| 	mark := &nl.XfrmMark{ | ||||
| 		Value: m.Value, | ||||
| 		Mask:  m.Mask, | ||||
| 	} | ||||
| 	if mark.Mask == 0 { | ||||
| 		mark.Mask = ^uint32(0) | ||||
| 	} | ||||
| 	return mark.Serialize() | ||||
| } | ||||
|  | ||||
| func writeReplayEsn(replayWindow int) []byte { | ||||
| 	replayEsn := &nl.XfrmReplayStateEsn{ | ||||
| 		OSeq:         0, | ||||
| 		Seq:          0, | ||||
| 		OSeqHi:       0, | ||||
| 		SeqHi:        0, | ||||
| 		ReplayWindow: uint32(replayWindow), | ||||
| 	} | ||||
|  | ||||
| 	// Linux stores the bitmap to identify the already received sequence packets in blocks of uint32 elements. | ||||
| 	// Therefore bitmap length is the minimum number of uint32 elements needed. The following is a ceiling operation. | ||||
| 	bytesPerElem := int(unsafe.Sizeof(replayEsn.BmpLen)) // Any uint32 variable is good for this | ||||
| 	replayEsn.BmpLen = uint32((replayWindow + (bytesPerElem * 8) - 1) / (bytesPerElem * 8)) | ||||
|  | ||||
| 	return replayEsn.Serialize() | ||||
| } | ||||
|  | ||||
| // XfrmStateAdd will add an xfrm state to the system. | ||||
| // Equivalent to: `ip xfrm state add $state` | ||||
| func XfrmStateAdd(state *XfrmState) error { | ||||
| 	return pkgHandle.XfrmStateAdd(state) | ||||
| } | ||||
|  | ||||
| // XfrmStateAdd will add an xfrm state to the system. | ||||
| // Equivalent to: `ip xfrm state add $state` | ||||
| func (h *Handle) XfrmStateAdd(state *XfrmState) error { | ||||
| 	return h.xfrmStateAddOrUpdate(state, nl.XFRM_MSG_NEWSA) | ||||
| } | ||||
|  | ||||
| // XfrmStateAllocSpi will allocate an xfrm state in the system. | ||||
| // Equivalent to: `ip xfrm state allocspi` | ||||
| func XfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) { | ||||
| 	return pkgHandle.xfrmStateAllocSpi(state) | ||||
| } | ||||
|  | ||||
| // XfrmStateUpdate will update an xfrm state to the system. | ||||
| // Equivalent to: `ip xfrm state update $state` | ||||
| func XfrmStateUpdate(state *XfrmState) error { | ||||
| 	return pkgHandle.XfrmStateUpdate(state) | ||||
| } | ||||
|  | ||||
| // XfrmStateUpdate will update an xfrm state to the system. | ||||
| // Equivalent to: `ip xfrm state update $state` | ||||
| func (h *Handle) XfrmStateUpdate(state *XfrmState) error { | ||||
| 	return h.xfrmStateAddOrUpdate(state, nl.XFRM_MSG_UPDSA) | ||||
| } | ||||
|  | ||||
| func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error { | ||||
|  | ||||
| 	// A state with spi 0 can't be deleted so don't allow it to be set | ||||
| 	if state.Spi == 0 { | ||||
| 		return fmt.Errorf("Spi must be set when adding xfrm state.") | ||||
| 	} | ||||
| 	req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) | ||||
|  | ||||
| 	msg := xfrmUsersaInfoFromXfrmState(state) | ||||
|  | ||||
| 	if state.ESN { | ||||
| 		if state.ReplayWindow == 0 { | ||||
| 			return fmt.Errorf("ESN flag set without ReplayWindow") | ||||
| 		} | ||||
| 		msg.Flags |= nl.XFRM_STATE_ESN | ||||
| 		msg.ReplayWindow = 0 | ||||
| 	} | ||||
|  | ||||
| 	limitsToLft(state.Limits, &msg.Lft) | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	if state.Auth != nil { | ||||
| 		out := nl.NewRtAttr(nl.XFRMA_ALG_AUTH_TRUNC, writeStateAlgoAuth(state.Auth)) | ||||
| 		req.AddData(out) | ||||
| 	} | ||||
| 	if state.Crypt != nil { | ||||
| 		out := nl.NewRtAttr(nl.XFRMA_ALG_CRYPT, writeStateAlgo(state.Crypt)) | ||||
| 		req.AddData(out) | ||||
| 	} | ||||
| 	if state.Aead != nil { | ||||
| 		out := nl.NewRtAttr(nl.XFRMA_ALG_AEAD, writeStateAlgoAead(state.Aead)) | ||||
| 		req.AddData(out) | ||||
| 	} | ||||
| 	if state.Encap != nil { | ||||
| 		encapData := make([]byte, nl.SizeofXfrmEncapTmpl) | ||||
| 		encap := nl.DeserializeXfrmEncapTmpl(encapData) | ||||
| 		encap.EncapType = uint16(state.Encap.Type) | ||||
| 		encap.EncapSport = nl.Swap16(uint16(state.Encap.SrcPort)) | ||||
| 		encap.EncapDport = nl.Swap16(uint16(state.Encap.DstPort)) | ||||
| 		encap.EncapOa.FromIP(state.Encap.OriginalAddress) | ||||
| 		out := nl.NewRtAttr(nl.XFRMA_ENCAP, encapData) | ||||
| 		req.AddData(out) | ||||
| 	} | ||||
| 	if state.Mark != nil { | ||||
| 		out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) | ||||
| 		req.AddData(out) | ||||
| 	} | ||||
| 	if state.ESN { | ||||
| 		out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow)) | ||||
| 		req.AddData(out) | ||||
| 	} | ||||
|  | ||||
| 	_, err := req.Execute(unix.NETLINK_XFRM, 0) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) { | ||||
| 	req := h.newNetlinkRequest(nl.XFRM_MSG_ALLOCSPI, | ||||
| 		unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) | ||||
|  | ||||
| 	msg := &nl.XfrmUserSpiInfo{} | ||||
| 	msg.XfrmUsersaInfo = *(xfrmUsersaInfoFromXfrmState(state)) | ||||
| 	// 1-255 is reserved by IANA for future use | ||||
| 	msg.Min = 0x100 | ||||
| 	msg.Max = 0xffffffff | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	if state.Mark != nil { | ||||
| 		out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) | ||||
| 		req.AddData(out) | ||||
| 	} | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_XFRM, 0) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	s, err := parseXfrmState(msgs[0], FAMILY_ALL) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return s, err | ||||
| } | ||||
|  | ||||
| // XfrmStateDel will delete an xfrm state from the system. Note that | ||||
| // the Algos are ignored when matching the state to delete. | ||||
| // Equivalent to: `ip xfrm state del $state` | ||||
| func XfrmStateDel(state *XfrmState) error { | ||||
| 	return pkgHandle.XfrmStateDel(state) | ||||
| } | ||||
|  | ||||
| // XfrmStateDel will delete an xfrm state from the system. Note that | ||||
| // the Algos are ignored when matching the state to delete. | ||||
| // Equivalent to: `ip xfrm state del $state` | ||||
| func (h *Handle) XfrmStateDel(state *XfrmState) error { | ||||
| 	_, err := h.xfrmStateGetOrDelete(state, nl.XFRM_MSG_DELSA) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // XfrmStateList gets a list of xfrm states in the system. | ||||
| // Equivalent to: `ip [-4|-6] xfrm state show`. | ||||
| // The list can be filtered by ip family. | ||||
| func XfrmStateList(family int) ([]XfrmState, error) { | ||||
| 	return pkgHandle.XfrmStateList(family) | ||||
| } | ||||
|  | ||||
| // XfrmStateList gets a list of xfrm states in the system. | ||||
| // Equivalent to: `ip xfrm state show`. | ||||
| // The list can be filtered by ip family. | ||||
| func (h *Handle) XfrmStateList(family int) ([]XfrmState, error) { | ||||
| 	req := h.newNetlinkRequest(nl.XFRM_MSG_GETSA, unix.NLM_F_DUMP) | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWSA) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	var res []XfrmState | ||||
| 	for _, m := range msgs { | ||||
| 		if state, err := parseXfrmState(m, family); err == nil { | ||||
| 			res = append(res, *state) | ||||
| 		} else if err == familyError { | ||||
| 			continue | ||||
| 		} else { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	return res, nil | ||||
| } | ||||
|  | ||||
| // XfrmStateGet gets the xfrm state described by the ID, if found. | ||||
| // Equivalent to: `ip xfrm state get ID [ mark MARK [ mask MASK ] ]`. | ||||
| // Only the fields which constitue the SA ID must be filled in: | ||||
| // ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ] | ||||
| // mark is optional | ||||
| func XfrmStateGet(state *XfrmState) (*XfrmState, error) { | ||||
| 	return pkgHandle.XfrmStateGet(state) | ||||
| } | ||||
|  | ||||
| // XfrmStateGet gets the xfrm state described by the ID, if found. | ||||
| // Equivalent to: `ip xfrm state get ID [ mark MARK [ mask MASK ] ]`. | ||||
| // Only the fields which constitue the SA ID must be filled in: | ||||
| // ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ] | ||||
| // mark is optional | ||||
| func (h *Handle) XfrmStateGet(state *XfrmState) (*XfrmState, error) { | ||||
| 	return h.xfrmStateGetOrDelete(state, nl.XFRM_MSG_GETSA) | ||||
| } | ||||
|  | ||||
| func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState, error) { | ||||
| 	req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK) | ||||
|  | ||||
| 	msg := &nl.XfrmUsersaId{} | ||||
| 	msg.Family = uint16(nl.GetIPFamily(state.Dst)) | ||||
| 	msg.Daddr.FromIP(state.Dst) | ||||
| 	msg.Proto = uint8(state.Proto) | ||||
| 	msg.Spi = nl.Swap32(uint32(state.Spi)) | ||||
| 	req.AddData(msg) | ||||
|  | ||||
| 	if state.Mark != nil { | ||||
| 		out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) | ||||
| 		req.AddData(out) | ||||
| 	} | ||||
| 	if state.Src != nil { | ||||
| 		out := nl.NewRtAttr(nl.XFRMA_SRCADDR, state.Src.To16()) | ||||
| 		req.AddData(out) | ||||
| 	} | ||||
|  | ||||
| 	resType := nl.XFRM_MSG_NEWSA | ||||
| 	if nlProto == nl.XFRM_MSG_DELSA { | ||||
| 		resType = 0 | ||||
| 	} | ||||
|  | ||||
| 	msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if nlProto == nl.XFRM_MSG_DELSA { | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	s, err := parseXfrmState(msgs[0], FAMILY_ALL) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return s, nil | ||||
| } | ||||
|  | ||||
| var familyError = fmt.Errorf("family error") | ||||
|  | ||||
| func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState { | ||||
| 	var state XfrmState | ||||
|  | ||||
| 	state.Dst = msg.Id.Daddr.ToIP() | ||||
| 	state.Src = msg.Saddr.ToIP() | ||||
| 	state.Proto = Proto(msg.Id.Proto) | ||||
| 	state.Mode = Mode(msg.Mode) | ||||
| 	state.Spi = int(nl.Swap32(msg.Id.Spi)) | ||||
| 	state.Reqid = int(msg.Reqid) | ||||
| 	state.ReplayWindow = int(msg.ReplayWindow) | ||||
| 	lftToLimits(&msg.Lft, &state.Limits) | ||||
| 	curToStats(&msg.Curlft, &msg.Stats, &state.Statistics) | ||||
|  | ||||
| 	return &state | ||||
| } | ||||
|  | ||||
| func parseXfrmState(m []byte, family int) (*XfrmState, error) { | ||||
| 	msg := nl.DeserializeXfrmUsersaInfo(m) | ||||
|  | ||||
| 	// This is mainly for the state dump | ||||
| 	if family != FAMILY_ALL && family != int(msg.Family) { | ||||
| 		return nil, familyError | ||||
| 	} | ||||
|  | ||||
| 	state := xfrmStateFromXfrmUsersaInfo(msg) | ||||
|  | ||||
| 	attrs, err := nl.ParseRouteAttr(m[nl.SizeofXfrmUsersaInfo:]) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	for _, attr := range attrs { | ||||
| 		switch attr.Attr.Type { | ||||
| 		case nl.XFRMA_ALG_AUTH, nl.XFRMA_ALG_CRYPT: | ||||
| 			var resAlgo *XfrmStateAlgo | ||||
| 			if attr.Attr.Type == nl.XFRMA_ALG_AUTH { | ||||
| 				if state.Auth == nil { | ||||
| 					state.Auth = new(XfrmStateAlgo) | ||||
| 				} | ||||
| 				resAlgo = state.Auth | ||||
| 			} else { | ||||
| 				state.Crypt = new(XfrmStateAlgo) | ||||
| 				resAlgo = state.Crypt | ||||
| 			} | ||||
| 			algo := nl.DeserializeXfrmAlgo(attr.Value[:]) | ||||
| 			(*resAlgo).Name = nl.BytesToString(algo.AlgName[:]) | ||||
| 			(*resAlgo).Key = algo.AlgKey | ||||
| 		case nl.XFRMA_ALG_AUTH_TRUNC: | ||||
| 			if state.Auth == nil { | ||||
| 				state.Auth = new(XfrmStateAlgo) | ||||
| 			} | ||||
| 			algo := nl.DeserializeXfrmAlgoAuth(attr.Value[:]) | ||||
| 			state.Auth.Name = nl.BytesToString(algo.AlgName[:]) | ||||
| 			state.Auth.Key = algo.AlgKey | ||||
| 			state.Auth.TruncateLen = int(algo.AlgTruncLen) | ||||
| 		case nl.XFRMA_ALG_AEAD: | ||||
| 			state.Aead = new(XfrmStateAlgo) | ||||
| 			algo := nl.DeserializeXfrmAlgoAEAD(attr.Value[:]) | ||||
| 			state.Aead.Name = nl.BytesToString(algo.AlgName[:]) | ||||
| 			state.Aead.Key = algo.AlgKey | ||||
| 			state.Aead.ICVLen = int(algo.AlgICVLen) | ||||
| 		case nl.XFRMA_ENCAP: | ||||
| 			encap := nl.DeserializeXfrmEncapTmpl(attr.Value[:]) | ||||
| 			state.Encap = new(XfrmStateEncap) | ||||
| 			state.Encap.Type = EncapType(encap.EncapType) | ||||
| 			state.Encap.SrcPort = int(nl.Swap16(encap.EncapSport)) | ||||
| 			state.Encap.DstPort = int(nl.Swap16(encap.EncapDport)) | ||||
| 			state.Encap.OriginalAddress = encap.EncapOa.ToIP() | ||||
| 		case nl.XFRMA_MARK: | ||||
| 			mark := nl.DeserializeXfrmMark(attr.Value[:]) | ||||
| 			state.Mark = new(XfrmMark) | ||||
| 			state.Mark.Value = mark.Value | ||||
| 			state.Mark.Mask = mark.Mask | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return state, nil | ||||
| } | ||||
|  | ||||
| // XfrmStateFlush will flush the xfrm state on the system. | ||||
| // proto = 0 means any transformation protocols | ||||
| // Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]` | ||||
| func XfrmStateFlush(proto Proto) error { | ||||
| 	return pkgHandle.XfrmStateFlush(proto) | ||||
| } | ||||
|  | ||||
| // XfrmStateFlush will flush the xfrm state on the system. | ||||
| // proto = 0 means any transformation protocols | ||||
| // Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]` | ||||
| func (h *Handle) XfrmStateFlush(proto Proto) error { | ||||
| 	req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHSA, unix.NLM_F_ACK) | ||||
|  | ||||
| 	req.AddData(&nl.XfrmUsersaFlush{Proto: uint8(proto)}) | ||||
|  | ||||
| 	_, err := req.Execute(unix.NETLINK_XFRM, 0) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func limitsToLft(lmts XfrmStateLimits, lft *nl.XfrmLifetimeCfg) { | ||||
| 	if lmts.ByteSoft != 0 { | ||||
| 		lft.SoftByteLimit = lmts.ByteSoft | ||||
| 	} else { | ||||
| 		lft.SoftByteLimit = nl.XFRM_INF | ||||
| 	} | ||||
| 	if lmts.ByteHard != 0 { | ||||
| 		lft.HardByteLimit = lmts.ByteHard | ||||
| 	} else { | ||||
| 		lft.HardByteLimit = nl.XFRM_INF | ||||
| 	} | ||||
| 	if lmts.PacketSoft != 0 { | ||||
| 		lft.SoftPacketLimit = lmts.PacketSoft | ||||
| 	} else { | ||||
| 		lft.SoftPacketLimit = nl.XFRM_INF | ||||
| 	} | ||||
| 	if lmts.PacketHard != 0 { | ||||
| 		lft.HardPacketLimit = lmts.PacketHard | ||||
| 	} else { | ||||
| 		lft.HardPacketLimit = nl.XFRM_INF | ||||
| 	} | ||||
| 	lft.SoftAddExpiresSeconds = lmts.TimeSoft | ||||
| 	lft.HardAddExpiresSeconds = lmts.TimeHard | ||||
| 	lft.SoftUseExpiresSeconds = lmts.TimeUseSoft | ||||
| 	lft.HardUseExpiresSeconds = lmts.TimeUseHard | ||||
| } | ||||
|  | ||||
| func lftToLimits(lft *nl.XfrmLifetimeCfg, lmts *XfrmStateLimits) { | ||||
| 	*lmts = *(*XfrmStateLimits)(unsafe.Pointer(lft)) | ||||
| } | ||||
|  | ||||
| func curToStats(cur *nl.XfrmLifetimeCur, wstats *nl.XfrmStats, stats *XfrmStateStats) { | ||||
| 	stats.Bytes = cur.Bytes | ||||
| 	stats.Packets = cur.Packets | ||||
| 	stats.AddTime = cur.AddTime | ||||
| 	stats.UseTime = cur.UseTime | ||||
| 	stats.ReplayWindow = wstats.ReplayWindow | ||||
| 	stats.Replay = wstats.Replay | ||||
| 	stats.Failed = wstats.IntegrityFailed | ||||
| } | ||||
|  | ||||
| func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo { | ||||
| 	msg := &nl.XfrmUsersaInfo{} | ||||
| 	msg.Family = uint16(nl.GetIPFamily(state.Dst)) | ||||
| 	msg.Id.Daddr.FromIP(state.Dst) | ||||
| 	msg.Saddr.FromIP(state.Src) | ||||
| 	msg.Id.Proto = uint8(state.Proto) | ||||
| 	msg.Mode = uint8(state.Mode) | ||||
| 	msg.Id.Spi = nl.Swap32(uint32(state.Spi)) | ||||
| 	msg.Reqid = uint32(state.Reqid) | ||||
| 	msg.ReplayWindow = uint8(state.ReplayWindow) | ||||
|  | ||||
| 	return msg | ||||
| } | ||||
		Reference in New Issue
	
	Block a user