diff options
author | Kevin Krakauer <krakauer@google.com> | 2019-12-12 14:40:36 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2019-12-12 14:42:11 -0800 |
commit | be2754a4b99cc92f13f479f74a5da8b0e6cb5839 (patch) | |
tree | 17a1cbacb7b477950998555ab896782439436d7c /test/iptables/iptables_util.go | |
parent | 93d429d5b1e3801fb4c29568bcd40d6854c9fe94 (diff) |
Add iptables testing framework.
It would be preferrable to test iptables via syscall tests, but there are some
problems with that approach:
* We're limited to loopback-only, as syscall tests involve only a single
container. Other link interfaces (e.g. fdbased) should be tested.
* We'd have to shell out to call iptables anyways, as the iptables syscall
interface itself is too large and complex to work with alone.
* Running the Linux/native version of the syscall test will require root, which
is a pain to configure, is inherently unsafe, and could leave host iptables
misconfigured.
Using the go_test target allows there to be no new test runner.
PiperOrigin-RevId: 285274275
Diffstat (limited to 'test/iptables/iptables_util.go')
-rw-r--r-- | test/iptables/iptables_util.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/test/iptables/iptables_util.go b/test/iptables/iptables_util.go new file mode 100644 index 000000000..3a4d11f1a --- /dev/null +++ b/test/iptables/iptables_util.go @@ -0,0 +1,82 @@ +// Copyright 2019 The gVisor Authors. +// +// 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. + +package iptables + +import ( + "fmt" + "net" + "os/exec" + "time" +) + +const iptablesBinary = "iptables" + +// filterTable calls `iptables -t filter` with the given args. +func filterTable(args ...string) error { + args = append([]string{"-t", "filter"}, args...) + cmd := exec.Command(iptablesBinary, args...) + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("error running iptables with args %v\nerror: %v\noutput: %s", args, err, string(out)) + } + return nil +} + +// listenUDP listens on a UDP port and returns the value of net.Conn.Read() for +// the first read on that port. +func listenUDP(port int, timeout time.Duration) error { + localAddr := net.UDPAddr{ + Port: port, + } + conn, err := net.ListenUDP(network, &localAddr) + if err != nil { + return err + } + defer conn.Close() + conn.SetDeadline(time.Now().Add(timeout)) + _, err = conn.Read([]byte{0}) + return err +} + +// sendUDPLoop sends 1 byte UDP packets repeatedly to the IP and port specified +// over a duration. +func sendUDPLoop(ip net.IP, port int, duration time.Duration) error { + // Send packets for a few seconds. + remote := net.UDPAddr{ + IP: ip, + Port: port, + } + conn, err := net.DialUDP(network, nil, &remote) + if err != nil { + return err + } + defer conn.Close() + + to := time.After(duration) + for timedOut := false; !timedOut; { + // This may return an error (connection refused) if the remote + // hasn't started listening yet or they're dropping our + // packets. So we ignore Write errors and depend on the remote + // to report a failure if it doesn't get a packet it needs. + conn.Write([]byte{0}) + select { + case <-to: + timedOut = true + default: + time.Sleep(200 * time.Millisecond) + } + } + + return nil +} |