blob: ea9bb76527187c95b9b62ace198f94f0859839cd [file] [log] [blame]
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin freebsd linux netbsd openbsd windows
package ipv4_test
import (
"code.google.com/p/go.net/ipv4"
"errors"
"net"
"os"
"runtime"
"testing"
)
type testUnicastConn interface {
TOS() (int, error)
SetTOS(int) error
TTL() (int, error)
SetTTL(int) error
}
type unicastSockoptTest struct {
tos int
ttl int
}
var unicastSockoptTests = []unicastSockoptTest{
{ipv4.DSCP_CS0 | ipv4.ECN_NOTECT, 127},
{ipv4.DSCP_AF11 | ipv4.ECN_NOTECT, 255},
}
func TestTCPUnicastSockopt(t *testing.T) {
for _, tt := range unicastSockoptTests {
listener := make(chan net.Listener)
go tcpListener(t, "127.0.0.1:0", listener)
ln := <-listener
if ln == nil {
return
}
defer ln.Close()
c, err := net.Dial("tcp4", ln.Addr().String())
if err != nil {
t.Errorf("net.Dial failed: %v", err)
return
}
defer c.Close()
cc := ipv4.NewConn(c)
if err := testUnicastSockopt(t, tt, cc); err != nil {
break
}
}
}
func tcpListener(t *testing.T, addr string, listener chan<- net.Listener) {
ln, err := net.Listen("tcp4", addr)
if err != nil {
t.Errorf("net.Listen failed: %v", err)
listener <- nil
return
}
listener <- ln
c, err := ln.Accept()
if err != nil {
return
}
c.Close()
}
func TestUDPUnicastSockopt(t *testing.T) {
for _, tt := range unicastSockoptTests {
c, err := net.ListenPacket("udp4", "127.0.0.1:0")
if err != nil {
t.Errorf("net.ListenPacket failed: %v", err)
return
}
defer c.Close()
p := ipv4.NewPacketConn(c)
if err := testUnicastSockopt(t, tt, p); err != nil {
break
}
}
}
func TestIPUnicastSockopt(t *testing.T) {
if os.Getuid() != 0 {
t.Skip("must be root")
}
for _, tt := range unicastSockoptTests {
c, err := net.ListenPacket("ip4:icmp", "127.0.0.1")
if err != nil {
t.Errorf("net.ListenPacket failed: %v", err)
return
}
defer c.Close()
r, err := ipv4.NewRawConn(c)
if err != nil {
t.Errorf("ipv4.NewRawConn failed: %v", err)
return
}
if err := testUnicastSockopt(t, tt, r); err != nil {
break
}
}
}
func testUnicastSockopt(t *testing.T, tt unicastSockoptTest, c testUnicastConn) error {
switch runtime.GOOS {
case "windows":
// IP_TOS option is supported on Windows 8 and beyond.
t.Logf("skipping IP_TOS test on %q", runtime.GOOS)
default:
if err := c.SetTOS(tt.tos); err != nil {
t.Errorf("ipv4.Conn.SetTOS failed: %v", err)
return err
}
if v, err := c.TOS(); err != nil {
t.Errorf("ipv4.Conn.TOS failed: %v", err)
return err
} else if v != tt.tos {
t.Errorf("Got unexpected TOS value %v; expected %v", v, tt.tos)
return errors.New("Got unexpected TOS value")
}
}
if err := c.SetTTL(tt.ttl); err != nil {
t.Errorf("ipv4.Conn.SetTTL failed: %v", err)
return err
}
if v, err := c.TTL(); err != nil {
t.Errorf("ipv4.Conn.TTL failed: %v", err)
return err
} else if v != tt.ttl {
t.Errorf("Got unexpected TTL value %v; expected %v", v, tt.ttl)
return errors.New("Got unexpected TTL value")
}
return nil
}