mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Convert int and bool socket options to use GetSockOptInt and GetSockOptBool
PiperOrigin-RevId: 305699233
This commit is contained in:
@@ -300,7 +300,7 @@ type SocketOperations struct {
|
||||
// New creates a new endpoint socket.
|
||||
func New(t *kernel.Task, family int, skType linux.SockType, protocol int, queue *waiter.Queue, endpoint tcpip.Endpoint) (*fs.File, *syserr.Error) {
|
||||
if skType == linux.SOCK_STREAM {
|
||||
if err := endpoint.SetSockOptInt(tcpip.DelayOption, 1); err != nil {
|
||||
if err := endpoint.SetSockOptBool(tcpip.DelayOption, true); err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
}
|
||||
@@ -965,6 +965,13 @@ func GetSockOpt(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, family in
|
||||
return nil, syserr.ErrProtocolNotAvailable
|
||||
}
|
||||
|
||||
func boolToInt32(v bool) int32 {
|
||||
if v {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// getSockOptSocket implements GetSockOpt when level is SOL_SOCKET.
|
||||
func getSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, family int, skType linux.SockType, name, outLen int) (interface{}, *syserr.Error) {
|
||||
// TODO(b/124056281): Stop rejecting short optLen values in getsockopt.
|
||||
@@ -998,12 +1005,11 @@ func getSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, fam
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var v tcpip.PasscredOption
|
||||
if err := ep.GetSockOpt(&v); err != nil {
|
||||
v, err := ep.GetSockOptBool(tcpip.PasscredOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
return int32(v), nil
|
||||
return boolToInt32(v), nil
|
||||
|
||||
case linux.SO_SNDBUF:
|
||||
if outLen < sizeOfInt32 {
|
||||
@@ -1042,24 +1048,22 @@ func getSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, fam
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var v tcpip.ReuseAddressOption
|
||||
if err := ep.GetSockOpt(&v); err != nil {
|
||||
v, err := ep.GetSockOptBool(tcpip.ReuseAddressOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
return int32(v), nil
|
||||
return boolToInt32(v), nil
|
||||
|
||||
case linux.SO_REUSEPORT:
|
||||
if outLen < sizeOfInt32 {
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var v tcpip.ReusePortOption
|
||||
if err := ep.GetSockOpt(&v); err != nil {
|
||||
v, err := ep.GetSockOptBool(tcpip.ReusePortOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
return int32(v), nil
|
||||
return boolToInt32(v), nil
|
||||
|
||||
case linux.SO_BINDTODEVICE:
|
||||
var v tcpip.BindToDeviceOption
|
||||
@@ -1089,24 +1093,22 @@ func getSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, fam
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var v tcpip.BroadcastOption
|
||||
if err := ep.GetSockOpt(&v); err != nil {
|
||||
v, err := ep.GetSockOptBool(tcpip.BroadcastOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
return int32(v), nil
|
||||
return boolToInt32(v), nil
|
||||
|
||||
case linux.SO_KEEPALIVE:
|
||||
if outLen < sizeOfInt32 {
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var v tcpip.KeepaliveEnabledOption
|
||||
if err := ep.GetSockOpt(&v); err != nil {
|
||||
v, err := ep.GetSockOptBool(tcpip.KeepaliveEnabledOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
return int32(v), nil
|
||||
return boolToInt32(v), nil
|
||||
|
||||
case linux.SO_LINGER:
|
||||
if outLen < linux.SizeOfLinger {
|
||||
@@ -1156,47 +1158,41 @@ func getSockOptTCP(t *kernel.Task, ep commonEndpoint, name, outLen int) (interfa
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
v, err := ep.GetSockOptInt(tcpip.DelayOption)
|
||||
v, err := ep.GetSockOptBool(tcpip.DelayOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
if v == 0 {
|
||||
return int32(1), nil
|
||||
}
|
||||
return int32(0), nil
|
||||
return boolToInt32(!v), nil
|
||||
|
||||
case linux.TCP_CORK:
|
||||
if outLen < sizeOfInt32 {
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var v tcpip.CorkOption
|
||||
if err := ep.GetSockOpt(&v); err != nil {
|
||||
v, err := ep.GetSockOptBool(tcpip.CorkOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
return int32(v), nil
|
||||
return boolToInt32(v), nil
|
||||
|
||||
case linux.TCP_QUICKACK:
|
||||
if outLen < sizeOfInt32 {
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var v tcpip.QuickAckOption
|
||||
if err := ep.GetSockOpt(&v); err != nil {
|
||||
v, err := ep.GetSockOptBool(tcpip.QuickAckOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
return int32(v), nil
|
||||
return boolToInt32(v), nil
|
||||
|
||||
case linux.TCP_MAXSEG:
|
||||
if outLen < sizeOfInt32 {
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var v tcpip.MaxSegOption
|
||||
if err := ep.GetSockOpt(&v); err != nil {
|
||||
v, err := ep.GetSockOptInt(tcpip.MaxSegOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
@@ -1328,11 +1324,7 @@ func getSockOptIPv6(t *kernel.Task, ep commonEndpoint, name, outLen int) (interf
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
var o int32
|
||||
if v {
|
||||
o = 1
|
||||
}
|
||||
return o, nil
|
||||
return boolToInt32(v), nil
|
||||
|
||||
case linux.IPV6_PATHMTU:
|
||||
t.Kernel().EmitUnimplementedEvent(t)
|
||||
@@ -1342,8 +1334,8 @@ func getSockOptIPv6(t *kernel.Task, ep commonEndpoint, name, outLen int) (interf
|
||||
if outLen == 0 {
|
||||
return make([]byte, 0), nil
|
||||
}
|
||||
var v tcpip.IPv6TrafficClassOption
|
||||
if err := ep.GetSockOpt(&v); err != nil {
|
||||
v, err := ep.GetSockOptInt(tcpip.IPv6TrafficClassOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
@@ -1365,12 +1357,7 @@ func getSockOptIPv6(t *kernel.Task, ep commonEndpoint, name, outLen int) (interf
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
var o int32
|
||||
if v {
|
||||
o = 1
|
||||
}
|
||||
return o, nil
|
||||
return boolToInt32(v), nil
|
||||
|
||||
default:
|
||||
emitUnimplementedEventIPv6(t, name)
|
||||
@@ -1386,8 +1373,8 @@ func getSockOptIP(t *kernel.Task, ep commonEndpoint, name, outLen int, family in
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var v tcpip.TTLOption
|
||||
if err := ep.GetSockOpt(&v); err != nil {
|
||||
v, err := ep.GetSockOptInt(tcpip.TTLOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
@@ -1403,8 +1390,8 @@ func getSockOptIP(t *kernel.Task, ep commonEndpoint, name, outLen int, family in
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var v tcpip.MulticastTTLOption
|
||||
if err := ep.GetSockOpt(&v); err != nil {
|
||||
v, err := ep.GetSockOptInt(tcpip.MulticastTTLOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
@@ -1429,23 +1416,19 @@ func getSockOptIP(t *kernel.Task, ep commonEndpoint, name, outLen int, family in
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var v tcpip.MulticastLoopOption
|
||||
if err := ep.GetSockOpt(&v); err != nil {
|
||||
v, err := ep.GetSockOptBool(tcpip.MulticastLoopOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
if v {
|
||||
return int32(1), nil
|
||||
}
|
||||
return int32(0), nil
|
||||
return boolToInt32(v), nil
|
||||
|
||||
case linux.IP_TOS:
|
||||
// Length handling for parity with Linux.
|
||||
if outLen == 0 {
|
||||
return []byte(nil), nil
|
||||
}
|
||||
var v tcpip.IPv4TOSOption
|
||||
if err := ep.GetSockOpt(&v); err != nil {
|
||||
v, err := ep.GetSockOptInt(tcpip.IPv4TOSOption)
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
if outLen < sizeOfInt32 {
|
||||
@@ -1462,11 +1445,7 @@ func getSockOptIP(t *kernel.Task, ep commonEndpoint, name, outLen int, family in
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
var o int32
|
||||
if v {
|
||||
o = 1
|
||||
}
|
||||
return o, nil
|
||||
return boolToInt32(v), nil
|
||||
|
||||
case linux.IP_PKTINFO:
|
||||
if outLen < sizeOfInt32 {
|
||||
@@ -1477,11 +1456,7 @@ func getSockOptIP(t *kernel.Task, ep commonEndpoint, name, outLen int, family in
|
||||
if err != nil {
|
||||
return nil, syserr.TranslateNetstackError(err)
|
||||
}
|
||||
var o int32
|
||||
if v {
|
||||
o = 1
|
||||
}
|
||||
return o, nil
|
||||
return boolToInt32(v), nil
|
||||
|
||||
default:
|
||||
emitUnimplementedEventIP(t, name)
|
||||
@@ -1592,7 +1567,7 @@ func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, nam
|
||||
}
|
||||
|
||||
v := usermem.ByteOrder.Uint32(optVal)
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.ReuseAddressOption(v)))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.ReuseAddressOption, v != 0))
|
||||
|
||||
case linux.SO_REUSEPORT:
|
||||
if len(optVal) < sizeOfInt32 {
|
||||
@@ -1600,7 +1575,7 @@ func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, nam
|
||||
}
|
||||
|
||||
v := usermem.ByteOrder.Uint32(optVal)
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.ReusePortOption(v)))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.ReusePortOption, v != 0))
|
||||
|
||||
case linux.SO_BINDTODEVICE:
|
||||
n := bytes.IndexByte(optVal, 0)
|
||||
@@ -1628,7 +1603,7 @@ func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, nam
|
||||
}
|
||||
|
||||
v := usermem.ByteOrder.Uint32(optVal)
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.BroadcastOption(v)))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.BroadcastOption, v != 0))
|
||||
|
||||
case linux.SO_PASSCRED:
|
||||
if len(optVal) < sizeOfInt32 {
|
||||
@@ -1636,7 +1611,7 @@ func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, nam
|
||||
}
|
||||
|
||||
v := usermem.ByteOrder.Uint32(optVal)
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.PasscredOption(v)))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.PasscredOption, v != 0))
|
||||
|
||||
case linux.SO_KEEPALIVE:
|
||||
if len(optVal) < sizeOfInt32 {
|
||||
@@ -1644,7 +1619,7 @@ func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, nam
|
||||
}
|
||||
|
||||
v := usermem.ByteOrder.Uint32(optVal)
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.KeepaliveEnabledOption(v)))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.KeepaliveEnabledOption, v != 0))
|
||||
|
||||
case linux.SO_SNDTIMEO:
|
||||
if len(optVal) < linux.SizeOfTimeval {
|
||||
@@ -1716,11 +1691,7 @@ func setSockOptTCP(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *
|
||||
}
|
||||
|
||||
v := usermem.ByteOrder.Uint32(optVal)
|
||||
var o int
|
||||
if v == 0 {
|
||||
o = 1
|
||||
}
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptInt(tcpip.DelayOption, o))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.DelayOption, v == 0))
|
||||
|
||||
case linux.TCP_CORK:
|
||||
if len(optVal) < sizeOfInt32 {
|
||||
@@ -1728,7 +1699,7 @@ func setSockOptTCP(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *
|
||||
}
|
||||
|
||||
v := usermem.ByteOrder.Uint32(optVal)
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.CorkOption(v)))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.CorkOption, v != 0))
|
||||
|
||||
case linux.TCP_QUICKACK:
|
||||
if len(optVal) < sizeOfInt32 {
|
||||
@@ -1736,7 +1707,7 @@ func setSockOptTCP(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *
|
||||
}
|
||||
|
||||
v := usermem.ByteOrder.Uint32(optVal)
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.QuickAckOption(v)))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.QuickAckOption, v != 0))
|
||||
|
||||
case linux.TCP_MAXSEG:
|
||||
if len(optVal) < sizeOfInt32 {
|
||||
@@ -1744,7 +1715,7 @@ func setSockOptTCP(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *
|
||||
}
|
||||
|
||||
v := usermem.ByteOrder.Uint32(optVal)
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.MaxSegOption(v)))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptInt(tcpip.MaxSegOption, int(v)))
|
||||
|
||||
case linux.TCP_KEEPIDLE:
|
||||
if len(optVal) < sizeOfInt32 {
|
||||
@@ -1855,7 +1826,7 @@ func setSockOptIPv6(t *kernel.Task, ep commonEndpoint, name int, optVal []byte)
|
||||
if v == -1 {
|
||||
v = 0
|
||||
}
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.IPv6TrafficClassOption(v)))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptInt(tcpip.IPv6TrafficClassOption, int(v)))
|
||||
|
||||
case linux.IPV6_RECVTCLASS:
|
||||
v, err := parseIntOrChar(optVal)
|
||||
@@ -1940,7 +1911,7 @@ func setSockOptIP(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *s
|
||||
if v < 0 || v > 255 {
|
||||
return syserr.ErrInvalidArgument
|
||||
}
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.MulticastTTLOption(v)))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptInt(tcpip.MulticastTTLOption, int(v)))
|
||||
|
||||
case linux.IP_ADD_MEMBERSHIP:
|
||||
req, err := copyInMulticastRequest(optVal, false /* allowAddr */)
|
||||
@@ -1987,9 +1958,7 @@ func setSockOptIP(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *s
|
||||
return err
|
||||
}
|
||||
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(
|
||||
tcpip.MulticastLoopOption(v != 0),
|
||||
))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.MulticastLoopOption, v != 0))
|
||||
|
||||
case linux.MCAST_JOIN_GROUP:
|
||||
// FIXME(b/124219304): Implement MCAST_JOIN_GROUP.
|
||||
@@ -2008,7 +1977,7 @@ func setSockOptIP(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *s
|
||||
} else if v < 1 || v > 255 {
|
||||
return syserr.ErrInvalidArgument
|
||||
}
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.TTLOption(v)))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptInt(tcpip.TTLOption, int(v)))
|
||||
|
||||
case linux.IP_TOS:
|
||||
if len(optVal) == 0 {
|
||||
@@ -2018,7 +1987,7 @@ func setSockOptIP(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *s
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.IPv4TOSOption(v)))
|
||||
return syserr.TranslateNetstackError(ep.SetSockOptInt(tcpip.IPv4TOSOption, int(v)))
|
||||
|
||||
case linux.IP_RECVTOS:
|
||||
v, err := parseIntOrChar(optVal)
|
||||
|
||||
@@ -30,6 +30,7 @@ go_library(
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/context",
|
||||
"//pkg/ilist",
|
||||
"//pkg/log",
|
||||
"//pkg/refs",
|
||||
"//pkg/sync",
|
||||
"//pkg/syserr",
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
"gvisor.dev/gvisor/pkg/syserr"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
@@ -838,24 +839,45 @@ func (e *baseEndpoint) SendMsg(ctx context.Context, data [][]byte, c ControlMess
|
||||
|
||||
// SetSockOpt sets a socket option. Currently not supported.
|
||||
func (e *baseEndpoint) SetSockOpt(opt interface{}) *tcpip.Error {
|
||||
switch v := opt.(type) {
|
||||
case tcpip.PasscredOption:
|
||||
e.setPasscred(v != 0)
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *baseEndpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error {
|
||||
switch opt {
|
||||
case tcpip.BroadcastOption:
|
||||
case tcpip.PasscredOption:
|
||||
e.setPasscred(v)
|
||||
case tcpip.ReuseAddressOption:
|
||||
default:
|
||||
log.Warningf("Unsupported socket option: %d", opt)
|
||||
return tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *baseEndpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
|
||||
switch opt {
|
||||
case tcpip.SendBufferSizeOption:
|
||||
case tcpip.ReceiveBufferSizeOption:
|
||||
default:
|
||||
log.Warningf("Unsupported socket option: %d", opt)
|
||||
return tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *baseEndpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) {
|
||||
return false, tcpip.ErrUnknownProtocolOption
|
||||
switch opt {
|
||||
case tcpip.KeepaliveEnabledOption:
|
||||
return false, nil
|
||||
|
||||
case tcpip.PasscredOption:
|
||||
return e.Passcred(), nil
|
||||
|
||||
default:
|
||||
log.Warningf("Unsupported socket option: %d", opt)
|
||||
return false, tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
}
|
||||
|
||||
func (e *baseEndpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
|
||||
@@ -914,29 +936,19 @@ func (e *baseEndpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
|
||||
return int(v), nil
|
||||
|
||||
default:
|
||||
log.Warningf("Unsupported socket option: %d", opt)
|
||||
return -1, tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
}
|
||||
|
||||
// GetSockOpt implements tcpip.Endpoint.GetSockOpt.
|
||||
func (e *baseEndpoint) GetSockOpt(opt interface{}) *tcpip.Error {
|
||||
switch o := opt.(type) {
|
||||
switch opt.(type) {
|
||||
case tcpip.ErrorOption:
|
||||
return nil
|
||||
|
||||
case *tcpip.PasscredOption:
|
||||
if e.Passcred() {
|
||||
*o = tcpip.PasscredOption(1)
|
||||
} else {
|
||||
*o = tcpip.PasscredOption(0)
|
||||
}
|
||||
return nil
|
||||
|
||||
case *tcpip.KeepaliveEnabledOption:
|
||||
*o = 0
|
||||
return nil
|
||||
|
||||
default:
|
||||
log.Warningf("Unsupported socket option: %T", opt)
|
||||
return tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ func TestTransportDemuxerRegister(t *testing.T) {
|
||||
// the distribution of packets received matches expectations.
|
||||
func TestBindToDeviceDistribution(t *testing.T) {
|
||||
type endpointSockopts struct {
|
||||
reuse int
|
||||
reuse bool
|
||||
bindToDevice tcpip.NICID
|
||||
}
|
||||
for _, test := range []struct {
|
||||
@@ -221,11 +221,11 @@ func TestBindToDeviceDistribution(t *testing.T) {
|
||||
"BindPortReuse",
|
||||
// 5 endpoints that all have reuse set.
|
||||
[]endpointSockopts{
|
||||
{reuse: 1, bindToDevice: 0},
|
||||
{reuse: 1, bindToDevice: 0},
|
||||
{reuse: 1, bindToDevice: 0},
|
||||
{reuse: 1, bindToDevice: 0},
|
||||
{reuse: 1, bindToDevice: 0},
|
||||
{reuse: true, bindToDevice: 0},
|
||||
{reuse: true, bindToDevice: 0},
|
||||
{reuse: true, bindToDevice: 0},
|
||||
{reuse: true, bindToDevice: 0},
|
||||
{reuse: true, bindToDevice: 0},
|
||||
},
|
||||
map[tcpip.NICID][]float64{
|
||||
// Injected packets on dev0 get distributed evenly.
|
||||
@@ -236,9 +236,9 @@ func TestBindToDeviceDistribution(t *testing.T) {
|
||||
"BindToDevice",
|
||||
// 3 endpoints with various bindings.
|
||||
[]endpointSockopts{
|
||||
{reuse: 0, bindToDevice: 1},
|
||||
{reuse: 0, bindToDevice: 2},
|
||||
{reuse: 0, bindToDevice: 3},
|
||||
{reuse: false, bindToDevice: 1},
|
||||
{reuse: false, bindToDevice: 2},
|
||||
{reuse: false, bindToDevice: 3},
|
||||
},
|
||||
map[tcpip.NICID][]float64{
|
||||
// Injected packets on dev0 go only to the endpoint bound to dev0.
|
||||
@@ -253,12 +253,12 @@ func TestBindToDeviceDistribution(t *testing.T) {
|
||||
"ReuseAndBindToDevice",
|
||||
// 6 endpoints with various bindings.
|
||||
[]endpointSockopts{
|
||||
{reuse: 1, bindToDevice: 1},
|
||||
{reuse: 1, bindToDevice: 1},
|
||||
{reuse: 1, bindToDevice: 2},
|
||||
{reuse: 1, bindToDevice: 2},
|
||||
{reuse: 1, bindToDevice: 2},
|
||||
{reuse: 1, bindToDevice: 0},
|
||||
{reuse: true, bindToDevice: 1},
|
||||
{reuse: true, bindToDevice: 1},
|
||||
{reuse: true, bindToDevice: 2},
|
||||
{reuse: true, bindToDevice: 2},
|
||||
{reuse: true, bindToDevice: 2},
|
||||
{reuse: true, bindToDevice: 0},
|
||||
},
|
||||
map[tcpip.NICID][]float64{
|
||||
// Injected packets on dev0 get distributed among endpoints bound to
|
||||
@@ -309,9 +309,8 @@ func TestBindToDeviceDistribution(t *testing.T) {
|
||||
}(ep)
|
||||
|
||||
defer ep.Close()
|
||||
reusePortOption := tcpip.ReusePortOption(endpoint.reuse)
|
||||
if err := ep.SetSockOpt(reusePortOption); err != nil {
|
||||
t.Fatalf("SetSockOpt(%#v) on endpoint %d failed: %s", reusePortOption, i, err)
|
||||
if err := ep.SetSockOptBool(tcpip.ReusePortOption, endpoint.reuse); err != nil {
|
||||
t.Fatalf("SetSockOptBool(ReusePortOption, %t) on endpoint %d failed: %s", endpoint.reuse, i, err)
|
||||
}
|
||||
bindToDeviceOption := tcpip.BindToDeviceOption(endpoint.bindToDevice)
|
||||
if err := ep.SetSockOpt(bindToDeviceOption); err != nil {
|
||||
|
||||
+69
-76
@@ -520,34 +520,90 @@ type WriteOptions struct {
|
||||
type SockOptBool int
|
||||
|
||||
const (
|
||||
// BroadcastOption is used by SetSockOpt/GetSockOpt to specify whether
|
||||
// datagram sockets are allowed to send packets to a broadcast address.
|
||||
BroadcastOption SockOptBool = iota
|
||||
|
||||
// CorkOption is used by SetSockOpt/GetSockOpt to specify if data should be
|
||||
// held until segments are full by the TCP transport protocol.
|
||||
CorkOption
|
||||
|
||||
// DelayOption is used by SetSockOpt/GetSockOpt to specify if data
|
||||
// should be sent out immediately by the transport protocol. For TCP,
|
||||
// it determines if the Nagle algorithm is on or off.
|
||||
DelayOption
|
||||
|
||||
// KeepaliveEnabledOption is used by SetSockOpt/GetSockOpt to specify whether
|
||||
// TCP keepalive is enabled for this socket.
|
||||
KeepaliveEnabledOption
|
||||
|
||||
// MulticastLoopOption is used by SetSockOpt/GetSockOpt to specify whether
|
||||
// multicast packets sent over a non-loopback interface will be looped back.
|
||||
MulticastLoopOption
|
||||
|
||||
// PasscredOption is used by SetSockOpt/GetSockOpt to specify whether
|
||||
// SCM_CREDENTIALS socket control messages are enabled.
|
||||
//
|
||||
// Only supported on Unix sockets.
|
||||
PasscredOption
|
||||
|
||||
// QuickAckOption is stubbed out in SetSockOpt/GetSockOpt.
|
||||
QuickAckOption
|
||||
|
||||
// ReceiveTClassOption is used by SetSockOpt/GetSockOpt to specify if the
|
||||
// IPV6_TCLASS ancillary message is passed with incoming packets.
|
||||
ReceiveTClassOption SockOptBool = iota
|
||||
ReceiveTClassOption
|
||||
|
||||
// ReceiveTOSOption is used by SetSockOpt/GetSockOpt to specify if the TOS
|
||||
// ancillary message is passed with incoming packets.
|
||||
ReceiveTOSOption
|
||||
|
||||
// V6OnlyOption is used by {G,S}etSockOptBool to specify whether an IPv6
|
||||
// socket is to be restricted to sending and receiving IPv6 packets only.
|
||||
V6OnlyOption
|
||||
|
||||
// ReceiveIPPacketInfoOption is used by {G,S}etSockOptBool to specify
|
||||
// if more inforamtion is provided with incoming packets such
|
||||
// as interface index and address.
|
||||
ReceiveIPPacketInfoOption
|
||||
|
||||
// TODO(b/146901447): convert existing bool socket options to be handled via
|
||||
// Get/SetSockOptBool
|
||||
// ReuseAddressOption is used by SetSockOpt/GetSockOpt to specify whether Bind()
|
||||
// should allow reuse of local address.
|
||||
ReuseAddressOption
|
||||
|
||||
// ReusePortOption is used by SetSockOpt/GetSockOpt to permit multiple sockets
|
||||
// to be bound to an identical socket address.
|
||||
ReusePortOption
|
||||
|
||||
// V6OnlyOption is used by {G,S}etSockOptBool to specify whether an IPv6
|
||||
// socket is to be restricted to sending and receiving IPv6 packets only.
|
||||
V6OnlyOption
|
||||
)
|
||||
|
||||
// SockOptInt represents socket options which values have the int type.
|
||||
type SockOptInt int
|
||||
|
||||
const (
|
||||
// KeepaliveCountOption is used by SetSockOpt/GetSockOpt to specify the number
|
||||
// of un-ACKed TCP keepalives that will be sent before the connection is
|
||||
// closed.
|
||||
KeepaliveCountOption SockOptInt = iota
|
||||
|
||||
// IPv4TOSOption is used by SetSockOpt/GetSockOpt to specify TOS
|
||||
// for all subsequent outgoing IPv4 packets from the endpoint.
|
||||
IPv4TOSOption
|
||||
|
||||
// IPv6TrafficClassOption is used by SetSockOpt/GetSockOpt to specify TOS
|
||||
// for all subsequent outgoing IPv6 packets from the endpoint.
|
||||
IPv6TrafficClassOption
|
||||
|
||||
// MaxSegOption is used by SetSockOpt/GetSockOpt to set/get the current
|
||||
// Maximum Segment Size(MSS) value as specified using the TCP_MAXSEG option.
|
||||
MaxSegOption
|
||||
|
||||
// MulticastTTLOption is used by SetSockOpt/GetSockOpt to control the default
|
||||
// TTL value for multicast messages. The default is 1.
|
||||
MulticastTTLOption
|
||||
|
||||
// ReceiveQueueSizeOption is used in GetSockOptInt to specify that the
|
||||
// number of unread bytes in the input buffer should be returned.
|
||||
ReceiveQueueSizeOption SockOptInt = iota
|
||||
ReceiveQueueSizeOption
|
||||
|
||||
// SendBufferSizeOption is used by SetSockOptInt/GetSockOptInt to
|
||||
// specify the send buffer size option.
|
||||
@@ -561,44 +617,21 @@ const (
|
||||
// number of unread bytes in the output buffer should be returned.
|
||||
SendQueueSizeOption
|
||||
|
||||
// DelayOption is used by SetSockOpt/GetSockOpt to specify if data
|
||||
// should be sent out immediately by the transport protocol. For TCP,
|
||||
// it determines if the Nagle algorithm is on or off.
|
||||
DelayOption
|
||||
|
||||
// TODO(b/137664753): convert all int socket options to be handled via
|
||||
// GetSockOptInt.
|
||||
// TTLOption is used by SetSockOpt/GetSockOpt to control the default TTL/hop
|
||||
// limit value for unicast messages. The default is protocol specific.
|
||||
//
|
||||
// A zero value indicates the default.
|
||||
TTLOption
|
||||
)
|
||||
|
||||
// ErrorOption is used in GetSockOpt to specify that the last error reported by
|
||||
// the endpoint should be cleared and returned.
|
||||
type ErrorOption struct{}
|
||||
|
||||
// CorkOption is used by SetSockOpt/GetSockOpt to specify if data should be
|
||||
// held until segments are full by the TCP transport protocol.
|
||||
type CorkOption int
|
||||
|
||||
// ReuseAddressOption is used by SetSockOpt/GetSockOpt to specify whether Bind()
|
||||
// should allow reuse of local address.
|
||||
type ReuseAddressOption int
|
||||
|
||||
// ReusePortOption is used by SetSockOpt/GetSockOpt to permit multiple sockets
|
||||
// to be bound to an identical socket address.
|
||||
type ReusePortOption int
|
||||
|
||||
// BindToDeviceOption is used by SetSockOpt/GetSockOpt to specify that sockets
|
||||
// should bind only on a specific NIC.
|
||||
type BindToDeviceOption NICID
|
||||
|
||||
// QuickAckOption is stubbed out in SetSockOpt/GetSockOpt.
|
||||
type QuickAckOption int
|
||||
|
||||
// PasscredOption is used by SetSockOpt/GetSockOpt to specify whether
|
||||
// SCM_CREDENTIALS socket control messages are enabled.
|
||||
//
|
||||
// Only supported on Unix sockets.
|
||||
type PasscredOption int
|
||||
|
||||
// TCPInfoOption is used by GetSockOpt to expose TCP statistics.
|
||||
//
|
||||
// TODO(b/64800844): Add and populate stat fields.
|
||||
@@ -607,10 +640,6 @@ type TCPInfoOption struct {
|
||||
RTTVar time.Duration
|
||||
}
|
||||
|
||||
// KeepaliveEnabledOption is used by SetSockOpt/GetSockOpt to specify whether
|
||||
// TCP keepalive is enabled for this socket.
|
||||
type KeepaliveEnabledOption int
|
||||
|
||||
// KeepaliveIdleOption is used by SetSockOpt/GetSockOpt to specify the time a
|
||||
// connection must remain idle before the first TCP keepalive packet is sent.
|
||||
// Once this time is reached, KeepaliveIntervalOption is used instead.
|
||||
@@ -620,11 +649,6 @@ type KeepaliveIdleOption time.Duration
|
||||
// interval between sending TCP keepalive packets.
|
||||
type KeepaliveIntervalOption time.Duration
|
||||
|
||||
// KeepaliveCountOption is used by SetSockOpt/GetSockOpt to specify the number
|
||||
// of un-ACKed TCP keepalives that will be sent before the connection is
|
||||
// closed.
|
||||
type KeepaliveCountOption int
|
||||
|
||||
// TCPUserTimeoutOption is used by SetSockOpt/GetSockOpt to specify a user
|
||||
// specified timeout for a given TCP connection.
|
||||
// See: RFC5482 for details.
|
||||
@@ -638,20 +662,9 @@ type CongestionControlOption string
|
||||
// control algorithms.
|
||||
type AvailableCongestionControlOption string
|
||||
|
||||
// ModerateReceiveBufferOption allows the caller to enable/disable TCP receive
|
||||
// buffer moderation.
|
||||
type ModerateReceiveBufferOption bool
|
||||
|
||||
// MaxSegOption is used by SetSockOpt/GetSockOpt to set/get the current
|
||||
// Maximum Segment Size(MSS) value as specified using the TCP_MAXSEG option.
|
||||
type MaxSegOption int
|
||||
|
||||
// TTLOption is used by SetSockOpt/GetSockOpt to control the default TTL/hop
|
||||
// limit value for unicast messages. The default is protocol specific.
|
||||
//
|
||||
// A zero value indicates the default.
|
||||
type TTLOption uint8
|
||||
|
||||
// TCPLingerTimeoutOption is used by SetSockOpt/GetSockOpt to set/get the
|
||||
// maximum duration for which a socket lingers in the TCP_FIN_WAIT_2 state
|
||||
// before being marked closed.
|
||||
@@ -668,10 +681,6 @@ type TCPTimeWaitTimeoutOption time.Duration
|
||||
// for a handshake till the specified timeout until a segment with data arrives.
|
||||
type TCPDeferAcceptOption time.Duration
|
||||
|
||||
// MulticastTTLOption is used by SetSockOpt/GetSockOpt to control the default
|
||||
// TTL value for multicast messages. The default is 1.
|
||||
type MulticastTTLOption uint8
|
||||
|
||||
// MulticastInterfaceOption is used by SetSockOpt/GetSockOpt to specify a
|
||||
// default interface for multicast.
|
||||
type MulticastInterfaceOption struct {
|
||||
@@ -679,10 +688,6 @@ type MulticastInterfaceOption struct {
|
||||
InterfaceAddr Address
|
||||
}
|
||||
|
||||
// MulticastLoopOption is used by SetSockOpt/GetSockOpt to specify whether
|
||||
// multicast packets sent over a non-loopback interface will be looped back.
|
||||
type MulticastLoopOption bool
|
||||
|
||||
// MembershipOption is used by SetSockOpt/GetSockOpt as an argument to
|
||||
// AddMembershipOption and RemoveMembershipOption.
|
||||
type MembershipOption struct {
|
||||
@@ -705,22 +710,10 @@ type RemoveMembershipOption MembershipOption
|
||||
// TCP out-of-band data is delivered along with the normal in-band data.
|
||||
type OutOfBandInlineOption int
|
||||
|
||||
// BroadcastOption is used by SetSockOpt/GetSockOpt to specify whether
|
||||
// datagram sockets are allowed to send packets to a broadcast address.
|
||||
type BroadcastOption int
|
||||
|
||||
// DefaultTTLOption is used by stack.(*Stack).NetworkProtocolOption to specify
|
||||
// a default TTL.
|
||||
type DefaultTTLOption uint8
|
||||
|
||||
// IPv4TOSOption is used by SetSockOpt/GetSockOpt to specify TOS
|
||||
// for all subsequent outgoing IPv4 packets from the endpoint.
|
||||
type IPv4TOSOption uint8
|
||||
|
||||
// IPv6TrafficClassOption is used by SetSockOpt/GetSockOpt to specify TOS
|
||||
// for all subsequent outgoing IPv6 packets from the endpoint.
|
||||
type IPv6TrafficClassOption uint8
|
||||
|
||||
// IPPacketInfo is the message struture for IP_PKTINFO.
|
||||
//
|
||||
// +stateify savable
|
||||
|
||||
@@ -348,29 +348,37 @@ func (e *endpoint) Peek([][]byte) (int64, tcpip.ControlMessages, *tcpip.Error) {
|
||||
|
||||
// SetSockOpt sets a socket option.
|
||||
func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
|
||||
switch o := opt.(type) {
|
||||
case tcpip.TTLOption:
|
||||
e.mu.Lock()
|
||||
e.ttl = uint8(o)
|
||||
e.mu.Unlock()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetSockOptBool sets a socket option. Currently not supported.
|
||||
func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error {
|
||||
return nil
|
||||
return tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
|
||||
// SetSockOptInt sets a socket option. Currently not supported.
|
||||
func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
|
||||
switch opt {
|
||||
case tcpip.TTLOption:
|
||||
e.mu.Lock()
|
||||
e.ttl = uint8(v)
|
||||
e.mu.Unlock()
|
||||
|
||||
default:
|
||||
return tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSockOptBool implements tcpip.Endpoint.GetSockOptBool.
|
||||
func (e *endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) {
|
||||
return false, tcpip.ErrUnknownProtocolOption
|
||||
switch opt {
|
||||
case tcpip.KeepaliveEnabledOption:
|
||||
return false, nil
|
||||
|
||||
default:
|
||||
return false, tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
}
|
||||
|
||||
// GetSockOptInt implements tcpip.Endpoint.GetSockOptInt.
|
||||
@@ -397,26 +405,23 @@ func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
|
||||
e.rcvMu.Unlock()
|
||||
return v, nil
|
||||
|
||||
case tcpip.TTLOption:
|
||||
e.rcvMu.Lock()
|
||||
v := int(e.ttl)
|
||||
e.rcvMu.Unlock()
|
||||
return v, nil
|
||||
|
||||
default:
|
||||
return -1, tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
return -1, tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
|
||||
// GetSockOpt implements tcpip.Endpoint.GetSockOpt.
|
||||
func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error {
|
||||
switch o := opt.(type) {
|
||||
switch opt.(type) {
|
||||
case tcpip.ErrorOption:
|
||||
return nil
|
||||
|
||||
case *tcpip.KeepaliveEnabledOption:
|
||||
*o = 0
|
||||
return nil
|
||||
|
||||
case *tcpip.TTLOption:
|
||||
e.rcvMu.Lock()
|
||||
*o = tcpip.TTLOption(e.ttl)
|
||||
e.rcvMu.Unlock()
|
||||
return nil
|
||||
|
||||
default:
|
||||
return tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
|
||||
@@ -533,14 +533,10 @@ func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
|
||||
|
||||
// GetSockOpt implements tcpip.Endpoint.GetSockOpt.
|
||||
func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error {
|
||||
switch o := opt.(type) {
|
||||
switch opt.(type) {
|
||||
case tcpip.ErrorOption:
|
||||
return nil
|
||||
|
||||
case *tcpip.KeepaliveEnabledOption:
|
||||
*o = 0
|
||||
return nil
|
||||
|
||||
default:
|
||||
return tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
@@ -548,7 +544,13 @@ func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error {
|
||||
|
||||
// GetSockOptBool implements tcpip.Endpoint.GetSockOptBool.
|
||||
func (e *endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) {
|
||||
return false, tcpip.ErrUnknownProtocolOption
|
||||
switch opt {
|
||||
case tcpip.KeepaliveEnabledOption:
|
||||
return false, nil
|
||||
|
||||
default:
|
||||
return false, tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
}
|
||||
|
||||
// GetSockOptInt implements tcpip.Endpoint.GetSockOptInt.
|
||||
@@ -576,9 +578,9 @@ func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
|
||||
e.rcvMu.Unlock()
|
||||
return v, nil
|
||||
|
||||
default:
|
||||
return -1, tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
|
||||
return -1, tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
|
||||
// HandlePacket implements stack.RawTransportEndpoint.HandlePacket.
|
||||
|
||||
+172
-215
File diff suppressed because it is too large
Load Diff
@@ -728,7 +728,7 @@ func TestUserSuppliedMSSOnConnectV4(t *testing.T) {
|
||||
const maxMSS = mtu - header.IPv4MinimumSize - header.TCPMinimumSize
|
||||
tests := []struct {
|
||||
name string
|
||||
setMSS uint16
|
||||
setMSS int
|
||||
expMSS uint16
|
||||
}{
|
||||
{
|
||||
@@ -756,15 +756,14 @@ func TestUserSuppliedMSSOnConnectV4(t *testing.T) {
|
||||
c.Create(-1)
|
||||
|
||||
// Set the MSS socket option.
|
||||
opt := tcpip.MaxSegOption(test.setMSS)
|
||||
if err := c.EP.SetSockOpt(opt); err != nil {
|
||||
t.Fatalf("SetSockOpt(%#v) failed: %s", opt, err)
|
||||
if err := c.EP.SetSockOptInt(tcpip.MaxSegOption, test.setMSS); err != nil {
|
||||
t.Fatalf("SetSockOptInt(MaxSegOption, %d) failed: %s", test.setMSS, err)
|
||||
}
|
||||
|
||||
// Get expected window size.
|
||||
rcvBufSize, err := c.EP.GetSockOptInt(tcpip.ReceiveBufferSizeOption)
|
||||
if err != nil {
|
||||
t.Fatalf("GetSockOpt(%v) failed: %s", tcpip.ReceiveBufferSizeOption, err)
|
||||
t.Fatalf("GetSockOptInt(ReceiveBufferSizeOption) failed: %s", err)
|
||||
}
|
||||
ws := tcp.FindWndScale(seqnum.Size(rcvBufSize))
|
||||
|
||||
@@ -818,15 +817,14 @@ func TestUserSuppliedMSSOnConnectV6(t *testing.T) {
|
||||
c.CreateV6Endpoint(true)
|
||||
|
||||
// Set the MSS socket option.
|
||||
opt := tcpip.MaxSegOption(test.setMSS)
|
||||
if err := c.EP.SetSockOpt(opt); err != nil {
|
||||
t.Fatalf("SetSockOpt(%#v) failed: %s", opt, err)
|
||||
if err := c.EP.SetSockOptInt(tcpip.MaxSegOption, int(test.setMSS)); err != nil {
|
||||
t.Fatalf("SetSockOptInt(MaxSegOption, %d) failed: %s", test.setMSS, err)
|
||||
}
|
||||
|
||||
// Get expected window size.
|
||||
rcvBufSize, err := c.EP.GetSockOptInt(tcpip.ReceiveBufferSizeOption)
|
||||
if err != nil {
|
||||
t.Fatalf("GetSockOpt(%v) failed: %s", tcpip.ReceiveBufferSizeOption, err)
|
||||
t.Fatalf("GetSockOptInt(ReceiveBufferSizeOption) failed: %s", err)
|
||||
}
|
||||
ws := tcp.FindWndScale(seqnum.Size(rcvBufSize))
|
||||
|
||||
@@ -1077,17 +1075,17 @@ func TestTOSV4(t *testing.T) {
|
||||
c.EP = ep
|
||||
|
||||
const tos = 0xC0
|
||||
if err := c.EP.SetSockOpt(tcpip.IPv4TOSOption(tos)); err != nil {
|
||||
t.Errorf("SetSockOpt(%#v) failed: %s", tcpip.IPv4TOSOption(tos), err)
|
||||
if err := c.EP.SetSockOptInt(tcpip.IPv4TOSOption, tos); err != nil {
|
||||
t.Errorf("SetSockOptInt(IPv4TOSOption, %d) failed: %s", tos, err)
|
||||
}
|
||||
|
||||
var v tcpip.IPv4TOSOption
|
||||
if err := c.EP.GetSockOpt(&v); err != nil {
|
||||
t.Errorf("GetSockopt failed: %s", err)
|
||||
v, err := c.EP.GetSockOptInt(tcpip.IPv4TOSOption)
|
||||
if err != nil {
|
||||
t.Errorf("GetSockoptInt(IPv4TOSOption) failed: %s", err)
|
||||
}
|
||||
|
||||
if want := tcpip.IPv4TOSOption(tos); v != want {
|
||||
t.Errorf("got GetSockOpt(...) = %#v, want = %#v", v, want)
|
||||
if v != tos {
|
||||
t.Errorf("got GetSockOptInt(IPv4TOSOption) = %d, want = %d", v, tos)
|
||||
}
|
||||
|
||||
testV4Connect(t, c, checker.TOS(tos, 0))
|
||||
@@ -1125,17 +1123,17 @@ func TestTrafficClassV6(t *testing.T) {
|
||||
c.CreateV6Endpoint(false)
|
||||
|
||||
const tos = 0xC0
|
||||
if err := c.EP.SetSockOpt(tcpip.IPv6TrafficClassOption(tos)); err != nil {
|
||||
t.Errorf("SetSockOpt(%#v) failed: %s", tcpip.IPv6TrafficClassOption(tos), err)
|
||||
if err := c.EP.SetSockOptInt(tcpip.IPv6TrafficClassOption, tos); err != nil {
|
||||
t.Errorf("SetSockOpInt(IPv6TrafficClassOption, %d) failed: %s", tos, err)
|
||||
}
|
||||
|
||||
var v tcpip.IPv6TrafficClassOption
|
||||
if err := c.EP.GetSockOpt(&v); err != nil {
|
||||
t.Fatalf("GetSockopt failed: %s", err)
|
||||
v, err := c.EP.GetSockOptInt(tcpip.IPv6TrafficClassOption)
|
||||
if err != nil {
|
||||
t.Fatalf("GetSockoptInt(IPv6TrafficClassOption) failed: %s", err)
|
||||
}
|
||||
|
||||
if want := tcpip.IPv6TrafficClassOption(tos); v != want {
|
||||
t.Errorf("got GetSockOpt(...) = %#v, want = %#v", v, want)
|
||||
if v != tos {
|
||||
t.Errorf("got GetSockOptInt(IPv6TrafficClassOption) = %d, want = %d", v, tos)
|
||||
}
|
||||
|
||||
// Test the connection request.
|
||||
@@ -1711,7 +1709,7 @@ func TestNoWindowShrinking(t *testing.T) {
|
||||
c.CreateConnected(789, 30000, 10)
|
||||
|
||||
if err := c.EP.SetSockOptInt(tcpip.ReceiveBufferSizeOption, 5); err != nil {
|
||||
t.Fatalf("SetSockOpt failed: %v", err)
|
||||
t.Fatalf("SetSockOptInt(ReceiveBufferSizeOption, 5) failed: %v", err)
|
||||
}
|
||||
|
||||
we, ch := waiter.NewChannelEntry(nil)
|
||||
@@ -1984,7 +1982,7 @@ func TestScaledWindowAccept(t *testing.T) {
|
||||
|
||||
// Set the window size greater than the maximum non-scaled window.
|
||||
if err := ep.SetSockOptInt(tcpip.ReceiveBufferSizeOption, 65535*3); err != nil {
|
||||
t.Fatalf("SetSockOpt failed failed: %v", err)
|
||||
t.Fatalf("SetSockOptInt(ReceiveBufferSizeOption, 65535*3) failed failed: %v", err)
|
||||
}
|
||||
|
||||
if err := ep.Bind(tcpip.FullAddress{Port: context.StackPort}); err != nil {
|
||||
@@ -2057,7 +2055,7 @@ func TestNonScaledWindowAccept(t *testing.T) {
|
||||
|
||||
// Set the window size greater than the maximum non-scaled window.
|
||||
if err := ep.SetSockOptInt(tcpip.ReceiveBufferSizeOption, 65535*3); err != nil {
|
||||
t.Fatalf("SetSockOpt failed failed: %v", err)
|
||||
t.Fatalf("SetSockOptInt(ReceiveBufferSizeOption, 65535*3) failed failed: %v", err)
|
||||
}
|
||||
|
||||
if err := ep.Bind(tcpip.FullAddress{Port: context.StackPort}); err != nil {
|
||||
@@ -2221,10 +2219,10 @@ func TestSegmentMerging(t *testing.T) {
|
||||
{
|
||||
"cork",
|
||||
func(ep tcpip.Endpoint) {
|
||||
ep.SetSockOpt(tcpip.CorkOption(1))
|
||||
ep.SetSockOptBool(tcpip.CorkOption, true)
|
||||
},
|
||||
func(ep tcpip.Endpoint) {
|
||||
ep.SetSockOpt(tcpip.CorkOption(0))
|
||||
ep.SetSockOptBool(tcpip.CorkOption, false)
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -2316,7 +2314,7 @@ func TestDelay(t *testing.T) {
|
||||
|
||||
c.CreateConnected(789, 30000, -1 /* epRcvBuf */)
|
||||
|
||||
c.EP.SetSockOptInt(tcpip.DelayOption, 1)
|
||||
c.EP.SetSockOptBool(tcpip.DelayOption, true)
|
||||
|
||||
var allData []byte
|
||||
for i, data := range [][]byte{{0}, {1, 2, 3, 4}, {5, 6, 7}, {8, 9}, {10}, {11}} {
|
||||
@@ -2364,7 +2362,7 @@ func TestUndelay(t *testing.T) {
|
||||
|
||||
c.CreateConnected(789, 30000, -1 /* epRcvBuf */)
|
||||
|
||||
c.EP.SetSockOptInt(tcpip.DelayOption, 1)
|
||||
c.EP.SetSockOptBool(tcpip.DelayOption, true)
|
||||
|
||||
allData := [][]byte{{0}, {1, 2, 3}}
|
||||
for i, data := range allData {
|
||||
@@ -2397,7 +2395,7 @@ func TestUndelay(t *testing.T) {
|
||||
// Check that we don't get the second packet yet.
|
||||
c.CheckNoPacketTimeout("delayed second packet transmitted", 100*time.Millisecond)
|
||||
|
||||
c.EP.SetSockOptInt(tcpip.DelayOption, 0)
|
||||
c.EP.SetSockOptBool(tcpip.DelayOption, false)
|
||||
|
||||
// Check that data is received.
|
||||
second := c.GetPacket()
|
||||
@@ -2434,8 +2432,8 @@ func TestMSSNotDelayed(t *testing.T) {
|
||||
fn func(tcpip.Endpoint)
|
||||
}{
|
||||
{"no-op", func(tcpip.Endpoint) {}},
|
||||
{"delay", func(ep tcpip.Endpoint) { ep.SetSockOptInt(tcpip.DelayOption, 1) }},
|
||||
{"cork", func(ep tcpip.Endpoint) { ep.SetSockOpt(tcpip.CorkOption(1)) }},
|
||||
{"delay", func(ep tcpip.Endpoint) { ep.SetSockOptBool(tcpip.DelayOption, true) }},
|
||||
{"cork", func(ep tcpip.Endpoint) { ep.SetSockOptBool(tcpip.CorkOption, true) }},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@@ -2576,12 +2574,12 @@ func TestSetTTL(t *testing.T) {
|
||||
t.Fatalf("NewEndpoint failed: %v", err)
|
||||
}
|
||||
|
||||
if err := c.EP.SetSockOpt(tcpip.TTLOption(wantTTL)); err != nil {
|
||||
t.Fatalf("SetSockOpt failed: %v", err)
|
||||
if err := c.EP.SetSockOptInt(tcpip.TTLOption, int(wantTTL)); err != nil {
|
||||
t.Fatalf("SetSockOptInt(TTLOption, %d) failed: %s", wantTTL, err)
|
||||
}
|
||||
|
||||
if err := c.EP.Connect(tcpip.FullAddress{Addr: context.TestAddr, Port: context.TestPort}); err != tcpip.ErrConnectStarted {
|
||||
t.Fatalf("Unexpected return value from Connect: %v", err)
|
||||
t.Fatalf("Unexpected return value from Connect: %s", err)
|
||||
}
|
||||
|
||||
// Receive SYN packet.
|
||||
@@ -2621,7 +2619,7 @@ func TestPassiveSendMSSLessThanMTU(t *testing.T) {
|
||||
// window scaling option.
|
||||
const rcvBufferSize = 0x20000
|
||||
if err := ep.SetSockOptInt(tcpip.ReceiveBufferSizeOption, rcvBufferSize); err != nil {
|
||||
t.Fatalf("SetSockOpt failed failed: %v", err)
|
||||
t.Fatalf("SetSockOptInt(ReceiveBufferSizeOption, %d) failed failed: %s", rcvBufferSize, err)
|
||||
}
|
||||
|
||||
if err := ep.Bind(tcpip.FullAddress{Port: context.StackPort}); err != nil {
|
||||
@@ -2765,7 +2763,7 @@ func TestSynOptionsOnActiveConnect(t *testing.T) {
|
||||
const rcvBufferSize = 0x20000
|
||||
const wndScale = 2
|
||||
if err := c.EP.SetSockOptInt(tcpip.ReceiveBufferSizeOption, rcvBufferSize); err != nil {
|
||||
t.Fatalf("SetSockOpt failed failed: %v", err)
|
||||
t.Fatalf("SetSockOptInt(ReceiveBufferSizeOption, %d) failed failed: %s", rcvBufferSize, err)
|
||||
}
|
||||
|
||||
// Start connection attempt.
|
||||
@@ -3882,26 +3880,26 @@ func TestMinMaxBufferSizes(t *testing.T) {
|
||||
|
||||
// Set values below the min.
|
||||
if err := ep.SetSockOptInt(tcpip.ReceiveBufferSizeOption, 199); err != nil {
|
||||
t.Fatalf("GetSockOpt failed: %v", err)
|
||||
t.Fatalf("SetSockOptInt(ReceiveBufferSizeOption, 199) failed: %s", err)
|
||||
}
|
||||
|
||||
checkRecvBufferSize(t, ep, 200)
|
||||
|
||||
if err := ep.SetSockOptInt(tcpip.SendBufferSizeOption, 299); err != nil {
|
||||
t.Fatalf("GetSockOpt failed: %v", err)
|
||||
t.Fatalf("SetSockOptInt(SendBufferSizeOption, 299) failed: %s", err)
|
||||
}
|
||||
|
||||
checkSendBufferSize(t, ep, 300)
|
||||
|
||||
// Set values above the max.
|
||||
if err := ep.SetSockOptInt(tcpip.ReceiveBufferSizeOption, 1+tcp.DefaultReceiveBufferSize*20); err != nil {
|
||||
t.Fatalf("GetSockOpt failed: %v", err)
|
||||
t.Fatalf("SetSockOptInt(ReceiveBufferSizeOption) failed: %s", err)
|
||||
}
|
||||
|
||||
checkRecvBufferSize(t, ep, tcp.DefaultReceiveBufferSize*20)
|
||||
|
||||
if err := ep.SetSockOptInt(tcpip.SendBufferSizeOption, 1+tcp.DefaultSendBufferSize*30); err != nil {
|
||||
t.Fatalf("GetSockOpt failed: %v", err)
|
||||
t.Fatalf("SetSockOptInt(SendBufferSizeOption) failed: %s", err)
|
||||
}
|
||||
|
||||
checkSendBufferSize(t, ep, tcp.DefaultSendBufferSize*30)
|
||||
@@ -4147,11 +4145,11 @@ func TestConnectAvoidsBoundPorts(t *testing.T) {
|
||||
case "ipv4":
|
||||
case "ipv6":
|
||||
if err := ep.SetSockOptBool(tcpip.V6OnlyOption, true); err != nil {
|
||||
t.Fatalf("SetSockOpt(V6OnlyOption(true)) failed: %v", err)
|
||||
t.Fatalf("SetSockOptBool(V6OnlyOption(true)) failed: %s", err)
|
||||
}
|
||||
case "dual":
|
||||
if err := ep.SetSockOptBool(tcpip.V6OnlyOption, false); err != nil {
|
||||
t.Fatalf("SetSockOpt(V6OnlyOption(false)) failed: %v", err)
|
||||
t.Fatalf("SetSockOptBool(V6OnlyOption(false)) failed: %s", err)
|
||||
}
|
||||
default:
|
||||
t.Fatalf("unknown network: '%s'", network)
|
||||
@@ -4477,8 +4475,8 @@ func TestKeepalive(t *testing.T) {
|
||||
const keepAliveInterval = 10 * time.Millisecond
|
||||
c.EP.SetSockOpt(tcpip.KeepaliveIdleOption(10 * time.Millisecond))
|
||||
c.EP.SetSockOpt(tcpip.KeepaliveIntervalOption(keepAliveInterval))
|
||||
c.EP.SetSockOpt(tcpip.KeepaliveCountOption(5))
|
||||
c.EP.SetSockOpt(tcpip.KeepaliveEnabledOption(1))
|
||||
c.EP.SetSockOptInt(tcpip.KeepaliveCountOption, 5)
|
||||
c.EP.SetSockOptBool(tcpip.KeepaliveEnabledOption, true)
|
||||
|
||||
// 5 unacked keepalives are sent. ACK each one, and check that the
|
||||
// connection stays alive after 5.
|
||||
@@ -5770,14 +5768,14 @@ func TestReceiveBufferAutoTuning(t *testing.T) {
|
||||
func TestDelayEnabled(t *testing.T) {
|
||||
c := context.New(t, defaultMTU)
|
||||
defer c.Cleanup()
|
||||
checkDelayOption(t, c, false, 0) // Delay is disabled by default.
|
||||
checkDelayOption(t, c, false, false) // Delay is disabled by default.
|
||||
|
||||
for _, v := range []struct {
|
||||
delayEnabled tcp.DelayEnabled
|
||||
wantDelayOption int
|
||||
wantDelayOption bool
|
||||
}{
|
||||
{delayEnabled: false, wantDelayOption: 0},
|
||||
{delayEnabled: true, wantDelayOption: 1},
|
||||
{delayEnabled: false, wantDelayOption: false},
|
||||
{delayEnabled: true, wantDelayOption: true},
|
||||
} {
|
||||
c := context.New(t, defaultMTU)
|
||||
defer c.Cleanup()
|
||||
@@ -5788,7 +5786,7 @@ func TestDelayEnabled(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func checkDelayOption(t *testing.T, c *context.Context, wantDelayEnabled tcp.DelayEnabled, wantDelayOption int) {
|
||||
func checkDelayOption(t *testing.T, c *context.Context, wantDelayEnabled tcp.DelayEnabled, wantDelayOption bool) {
|
||||
t.Helper()
|
||||
|
||||
var gotDelayEnabled tcp.DelayEnabled
|
||||
@@ -5803,12 +5801,12 @@ func checkDelayOption(t *testing.T, c *context.Context, wantDelayEnabled tcp.Del
|
||||
if err != nil {
|
||||
t.Fatalf("NewEndPoint(tcp, ipv4, new(waiter.Queue)) failed: %v", err)
|
||||
}
|
||||
gotDelayOption, err := ep.GetSockOptInt(tcpip.DelayOption)
|
||||
gotDelayOption, err := ep.GetSockOptBool(tcpip.DelayOption)
|
||||
if err != nil {
|
||||
t.Fatalf("ep.GetSockOptInt(tcpip.DelayOption) failed: %v", err)
|
||||
t.Fatalf("ep.GetSockOptBool(tcpip.DelayOption) failed: %s", err)
|
||||
}
|
||||
if gotDelayOption != wantDelayOption {
|
||||
t.Errorf("ep.GetSockOptInt(tcpip.DelayOption) got: %d, want: %d", gotDelayOption, wantDelayOption)
|
||||
t.Errorf("ep.GetSockOptBool(tcpip.DelayOption) got: %t, want: %t", gotDelayOption, wantDelayOption)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6620,8 +6618,8 @@ func TestKeepaliveWithUserTimeout(t *testing.T) {
|
||||
const keepAliveInterval = 10 * time.Millisecond
|
||||
c.EP.SetSockOpt(tcpip.KeepaliveIdleOption(10 * time.Millisecond))
|
||||
c.EP.SetSockOpt(tcpip.KeepaliveIntervalOption(keepAliveInterval))
|
||||
c.EP.SetSockOpt(tcpip.KeepaliveCountOption(10))
|
||||
c.EP.SetSockOpt(tcpip.KeepaliveEnabledOption(1))
|
||||
c.EP.SetSockOptInt(tcpip.KeepaliveCountOption, 10)
|
||||
c.EP.SetSockOptBool(tcpip.KeepaliveEnabledOption, true)
|
||||
|
||||
// Set userTimeout to be the duration for 3 keepalive probes.
|
||||
userTimeout := 30 * time.Millisecond
|
||||
|
||||
+113
-124
@@ -501,11 +501,20 @@ func (e *endpoint) Peek([][]byte) (int64, tcpip.ControlMessages, *tcpip.Error) {
|
||||
// SetSockOptBool implements tcpip.Endpoint.SetSockOptBool.
|
||||
func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error {
|
||||
switch opt {
|
||||
case tcpip.BroadcastOption:
|
||||
e.mu.Lock()
|
||||
e.broadcast = v
|
||||
e.mu.Unlock()
|
||||
|
||||
case tcpip.MulticastLoopOption:
|
||||
e.mu.Lock()
|
||||
e.multicastLoop = v
|
||||
e.mu.Unlock()
|
||||
|
||||
case tcpip.ReceiveTOSOption:
|
||||
e.mu.Lock()
|
||||
e.receiveTOS = v
|
||||
e.mu.Unlock()
|
||||
return nil
|
||||
|
||||
case tcpip.ReceiveTClassOption:
|
||||
// We only support this option on v6 endpoints.
|
||||
@@ -516,7 +525,18 @@ func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error {
|
||||
e.mu.Lock()
|
||||
e.receiveTClass = v
|
||||
e.mu.Unlock()
|
||||
return nil
|
||||
|
||||
case tcpip.ReceiveIPPacketInfoOption:
|
||||
e.mu.Lock()
|
||||
e.receiveIPPacketInfo = v
|
||||
e.mu.Unlock()
|
||||
|
||||
case tcpip.ReuseAddressOption:
|
||||
|
||||
case tcpip.ReusePortOption:
|
||||
e.mu.Lock()
|
||||
e.reusePort = v
|
||||
e.mu.Unlock()
|
||||
|
||||
case tcpip.V6OnlyOption:
|
||||
// We only recognize this option on v6 endpoints.
|
||||
@@ -533,13 +553,8 @@ func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error {
|
||||
}
|
||||
|
||||
e.v6only = v
|
||||
return nil
|
||||
|
||||
case tcpip.ReceiveIPPacketInfoOption:
|
||||
e.mu.Lock()
|
||||
e.receiveIPPacketInfo = v
|
||||
e.mu.Unlock()
|
||||
return nil
|
||||
default:
|
||||
return tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -547,22 +562,40 @@ func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error {
|
||||
|
||||
// SetSockOptInt implements tcpip.Endpoint.SetSockOptInt.
|
||||
func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
|
||||
switch opt {
|
||||
case tcpip.MulticastTTLOption:
|
||||
e.mu.Lock()
|
||||
e.multicastTTL = uint8(v)
|
||||
e.mu.Unlock()
|
||||
|
||||
case tcpip.TTLOption:
|
||||
e.mu.Lock()
|
||||
e.ttl = uint8(v)
|
||||
e.mu.Unlock()
|
||||
|
||||
case tcpip.IPv4TOSOption:
|
||||
e.mu.Lock()
|
||||
e.sendTOS = uint8(v)
|
||||
e.mu.Unlock()
|
||||
|
||||
case tcpip.IPv6TrafficClassOption:
|
||||
e.mu.Lock()
|
||||
e.sendTOS = uint8(v)
|
||||
e.mu.Unlock()
|
||||
|
||||
case tcpip.ReceiveBufferSizeOption:
|
||||
case tcpip.SendBufferSizeOption:
|
||||
|
||||
default:
|
||||
return tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetSockOpt implements tcpip.Endpoint.SetSockOpt.
|
||||
func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
|
||||
switch v := opt.(type) {
|
||||
case tcpip.TTLOption:
|
||||
e.mu.Lock()
|
||||
e.ttl = uint8(v)
|
||||
e.mu.Unlock()
|
||||
|
||||
case tcpip.MulticastTTLOption:
|
||||
e.mu.Lock()
|
||||
e.multicastTTL = uint8(v)
|
||||
e.mu.Unlock()
|
||||
|
||||
case tcpip.MulticastInterfaceOption:
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
@@ -686,16 +719,6 @@ func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
|
||||
e.multicastMemberships[memToRemoveIndex] = e.multicastMemberships[len(e.multicastMemberships)-1]
|
||||
e.multicastMemberships = e.multicastMemberships[:len(e.multicastMemberships)-1]
|
||||
|
||||
case tcpip.MulticastLoopOption:
|
||||
e.mu.Lock()
|
||||
e.multicastLoop = bool(v)
|
||||
e.mu.Unlock()
|
||||
|
||||
case tcpip.ReusePortOption:
|
||||
e.mu.Lock()
|
||||
e.reusePort = v != 0
|
||||
e.mu.Unlock()
|
||||
|
||||
case tcpip.BindToDeviceOption:
|
||||
id := tcpip.NICID(v)
|
||||
if id != 0 && !e.stack.HasNIC(id) {
|
||||
@@ -704,26 +727,6 @@ func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
|
||||
e.mu.Lock()
|
||||
e.bindToDevice = id
|
||||
e.mu.Unlock()
|
||||
return nil
|
||||
|
||||
case tcpip.BroadcastOption:
|
||||
e.mu.Lock()
|
||||
e.broadcast = v != 0
|
||||
e.mu.Unlock()
|
||||
|
||||
return nil
|
||||
|
||||
case tcpip.IPv4TOSOption:
|
||||
e.mu.Lock()
|
||||
e.sendTOS = uint8(v)
|
||||
e.mu.Unlock()
|
||||
return nil
|
||||
|
||||
case tcpip.IPv6TrafficClassOption:
|
||||
e.mu.Lock()
|
||||
e.sendTOS = uint8(v)
|
||||
e.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -731,6 +734,21 @@ func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
|
||||
// GetSockOptBool implements tcpip.Endpoint.GetSockOptBool.
|
||||
func (e *endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) {
|
||||
switch opt {
|
||||
case tcpip.BroadcastOption:
|
||||
e.mu.RLock()
|
||||
v := e.broadcast
|
||||
e.mu.RUnlock()
|
||||
return v, nil
|
||||
|
||||
case tcpip.KeepaliveEnabledOption:
|
||||
return false, nil
|
||||
|
||||
case tcpip.MulticastLoopOption:
|
||||
e.mu.RLock()
|
||||
v := e.multicastLoop
|
||||
e.mu.RUnlock()
|
||||
return v, nil
|
||||
|
||||
case tcpip.ReceiveTOSOption:
|
||||
e.mu.RLock()
|
||||
v := e.receiveTOS
|
||||
@@ -748,6 +766,22 @@ func (e *endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) {
|
||||
e.mu.RUnlock()
|
||||
return v, nil
|
||||
|
||||
case tcpip.ReceiveIPPacketInfoOption:
|
||||
e.mu.RLock()
|
||||
v := e.receiveIPPacketInfo
|
||||
e.mu.RUnlock()
|
||||
return v, nil
|
||||
|
||||
case tcpip.ReuseAddressOption:
|
||||
return false, nil
|
||||
|
||||
case tcpip.ReusePortOption:
|
||||
e.mu.RLock()
|
||||
v := e.reusePort
|
||||
e.mu.RUnlock()
|
||||
|
||||
return v, nil
|
||||
|
||||
case tcpip.V6OnlyOption:
|
||||
// We only recognize this option on v6 endpoints.
|
||||
if e.NetProto != header.IPv6ProtocolNumber {
|
||||
@@ -760,19 +794,32 @@ func (e *endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) {
|
||||
|
||||
return v, nil
|
||||
|
||||
case tcpip.ReceiveIPPacketInfoOption:
|
||||
e.mu.RLock()
|
||||
v := e.receiveIPPacketInfo
|
||||
e.mu.RUnlock()
|
||||
return v, nil
|
||||
default:
|
||||
return false, tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
|
||||
return false, tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
|
||||
// GetSockOptInt implements tcpip.Endpoint.GetSockOptInt.
|
||||
func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
|
||||
switch opt {
|
||||
case tcpip.IPv4TOSOption:
|
||||
e.mu.RLock()
|
||||
v := int(e.sendTOS)
|
||||
e.mu.RUnlock()
|
||||
return v, nil
|
||||
|
||||
case tcpip.IPv6TrafficClassOption:
|
||||
e.mu.RLock()
|
||||
v := int(e.sendTOS)
|
||||
e.mu.RUnlock()
|
||||
return v, nil
|
||||
|
||||
case tcpip.MulticastTTLOption:
|
||||
e.mu.Lock()
|
||||
v := int(e.multicastTTL)
|
||||
e.mu.Unlock()
|
||||
return v, nil
|
||||
|
||||
case tcpip.ReceiveQueueSizeOption:
|
||||
v := 0
|
||||
e.rcvMu.Lock()
|
||||
@@ -794,29 +841,22 @@ func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
|
||||
v := e.rcvBufSizeMax
|
||||
e.rcvMu.Unlock()
|
||||
return v, nil
|
||||
}
|
||||
|
||||
return -1, tcpip.ErrUnknownProtocolOption
|
||||
case tcpip.TTLOption:
|
||||
e.mu.Lock()
|
||||
v := int(e.ttl)
|
||||
e.mu.Unlock()
|
||||
return v, nil
|
||||
|
||||
default:
|
||||
return -1, tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
}
|
||||
|
||||
// GetSockOpt implements tcpip.Endpoint.GetSockOpt.
|
||||
func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error {
|
||||
switch o := opt.(type) {
|
||||
case tcpip.ErrorOption:
|
||||
return nil
|
||||
|
||||
case *tcpip.TTLOption:
|
||||
e.mu.Lock()
|
||||
*o = tcpip.TTLOption(e.ttl)
|
||||
e.mu.Unlock()
|
||||
return nil
|
||||
|
||||
case *tcpip.MulticastTTLOption:
|
||||
e.mu.Lock()
|
||||
*o = tcpip.MulticastTTLOption(e.multicastTTL)
|
||||
e.mu.Unlock()
|
||||
return nil
|
||||
|
||||
case *tcpip.MulticastInterfaceOption:
|
||||
e.mu.Lock()
|
||||
*o = tcpip.MulticastInterfaceOption{
|
||||
@@ -824,67 +864,16 @@ func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error {
|
||||
e.multicastAddr,
|
||||
}
|
||||
e.mu.Unlock()
|
||||
return nil
|
||||
|
||||
case *tcpip.MulticastLoopOption:
|
||||
e.mu.RLock()
|
||||
v := e.multicastLoop
|
||||
e.mu.RUnlock()
|
||||
|
||||
*o = tcpip.MulticastLoopOption(v)
|
||||
return nil
|
||||
|
||||
case *tcpip.ReuseAddressOption:
|
||||
*o = 0
|
||||
return nil
|
||||
|
||||
case *tcpip.ReusePortOption:
|
||||
e.mu.RLock()
|
||||
v := e.reusePort
|
||||
e.mu.RUnlock()
|
||||
|
||||
*o = 0
|
||||
if v {
|
||||
*o = 1
|
||||
}
|
||||
return nil
|
||||
|
||||
case *tcpip.BindToDeviceOption:
|
||||
e.mu.RLock()
|
||||
*o = tcpip.BindToDeviceOption(e.bindToDevice)
|
||||
e.mu.RUnlock()
|
||||
return nil
|
||||
|
||||
case *tcpip.KeepaliveEnabledOption:
|
||||
*o = 0
|
||||
return nil
|
||||
|
||||
case *tcpip.BroadcastOption:
|
||||
e.mu.RLock()
|
||||
v := e.broadcast
|
||||
e.mu.RUnlock()
|
||||
|
||||
*o = 0
|
||||
if v {
|
||||
*o = 1
|
||||
}
|
||||
return nil
|
||||
|
||||
case *tcpip.IPv4TOSOption:
|
||||
e.mu.RLock()
|
||||
*o = tcpip.IPv4TOSOption(e.sendTOS)
|
||||
e.mu.RUnlock()
|
||||
return nil
|
||||
|
||||
case *tcpip.IPv6TrafficClassOption:
|
||||
e.mu.RLock()
|
||||
*o = tcpip.IPv6TrafficClassOption(e.sendTOS)
|
||||
e.mu.RUnlock()
|
||||
return nil
|
||||
|
||||
default:
|
||||
return tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// sendUDP sends a UDP segment via the provided network endpoint and under the
|
||||
|
||||
@@ -343,11 +343,11 @@ func (c *testContext) createEndpointForFlow(flow testFlow) {
|
||||
c.createEndpoint(flow.sockProto())
|
||||
if flow.isV6Only() {
|
||||
if err := c.ep.SetSockOptBool(tcpip.V6OnlyOption, true); err != nil {
|
||||
c.t.Fatalf("SetSockOpt failed: %v", err)
|
||||
c.t.Fatalf("SetSockOptBool failed: %s", err)
|
||||
}
|
||||
} else if flow.isBroadcast() {
|
||||
if err := c.ep.SetSockOpt(tcpip.BroadcastOption(1)); err != nil {
|
||||
c.t.Fatal("SetSockOpt failed:", err)
|
||||
if err := c.ep.SetSockOptBool(tcpip.BroadcastOption, true); err != nil {
|
||||
c.t.Fatalf("SetSockOptBool failed: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1271,8 +1271,8 @@ func TestTTL(t *testing.T) {
|
||||
c.createEndpointForFlow(flow)
|
||||
|
||||
const multicastTTL = 42
|
||||
if err := c.ep.SetSockOpt(tcpip.MulticastTTLOption(multicastTTL)); err != nil {
|
||||
c.t.Fatalf("SetSockOpt failed: %v", err)
|
||||
if err := c.ep.SetSockOptInt(tcpip.MulticastTTLOption, multicastTTL); err != nil {
|
||||
c.t.Fatalf("SetSockOptInt failed: %s", err)
|
||||
}
|
||||
|
||||
var wantTTL uint8
|
||||
@@ -1311,8 +1311,8 @@ func TestSetTTL(t *testing.T) {
|
||||
|
||||
c.createEndpointForFlow(flow)
|
||||
|
||||
if err := c.ep.SetSockOpt(tcpip.TTLOption(wantTTL)); err != nil {
|
||||
c.t.Fatalf("SetSockOpt failed: %v", err)
|
||||
if err := c.ep.SetSockOptInt(tcpip.TTLOption, int(wantTTL)); err != nil {
|
||||
c.t.Fatalf("SetSockOptInt(TTLOption, %d) failed: %s", wantTTL, err)
|
||||
}
|
||||
|
||||
var p stack.NetworkProtocol
|
||||
@@ -1346,25 +1346,26 @@ func TestSetTOS(t *testing.T) {
|
||||
c.createEndpointForFlow(flow)
|
||||
|
||||
const tos = testTOS
|
||||
var v tcpip.IPv4TOSOption
|
||||
if err := c.ep.GetSockOpt(&v); err != nil {
|
||||
c.t.Errorf("GetSockopt(%T) failed: %s", v, err)
|
||||
v, err := c.ep.GetSockOptInt(tcpip.IPv4TOSOption)
|
||||
if err != nil {
|
||||
c.t.Errorf("GetSockOptInt(IPv4TOSOption) failed: %s", err)
|
||||
}
|
||||
// Test for expected default value.
|
||||
if v != 0 {
|
||||
c.t.Errorf("got GetSockOpt(%T) = 0x%x, want = 0x%x", v, v, 0)
|
||||
c.t.Errorf("got GetSockOpt(IPv4TOSOption) = 0x%x, want = 0x%x", v, 0)
|
||||
}
|
||||
|
||||
if err := c.ep.SetSockOpt(tcpip.IPv4TOSOption(tos)); err != nil {
|
||||
c.t.Errorf("SetSockOpt(%T, 0x%x) failed: %s", v, tcpip.IPv4TOSOption(tos), err)
|
||||
if err := c.ep.SetSockOptInt(tcpip.IPv4TOSOption, tos); err != nil {
|
||||
c.t.Errorf("SetSockOptInt(IPv4TOSOption, 0x%x) failed: %s", tos, err)
|
||||
}
|
||||
|
||||
if err := c.ep.GetSockOpt(&v); err != nil {
|
||||
c.t.Errorf("GetSockopt(%T) failed: %s", v, err)
|
||||
v, err = c.ep.GetSockOptInt(tcpip.IPv4TOSOption)
|
||||
if err != nil {
|
||||
c.t.Errorf("GetSockOptInt(IPv4TOSOption) failed: %s", err)
|
||||
}
|
||||
|
||||
if want := tcpip.IPv4TOSOption(tos); v != want {
|
||||
c.t.Errorf("got GetSockOpt(%T) = 0x%x, want = 0x%x", v, v, want)
|
||||
if v != tos {
|
||||
c.t.Errorf("got GetSockOptInt(IPv4TOSOption) = 0x%x, want = 0x%x", v, tos)
|
||||
}
|
||||
|
||||
testWrite(c, flow, checker.TOS(tos, 0))
|
||||
@@ -1381,25 +1382,26 @@ func TestSetTClass(t *testing.T) {
|
||||
c.createEndpointForFlow(flow)
|
||||
|
||||
const tClass = testTOS
|
||||
var v tcpip.IPv6TrafficClassOption
|
||||
if err := c.ep.GetSockOpt(&v); err != nil {
|
||||
c.t.Errorf("GetSockopt(%T) failed: %s", v, err)
|
||||
v, err := c.ep.GetSockOptInt(tcpip.IPv6TrafficClassOption)
|
||||
if err != nil {
|
||||
c.t.Errorf("GetSockOptInt(IPv6TrafficClassOption) failed: %s", err)
|
||||
}
|
||||
// Test for expected default value.
|
||||
if v != 0 {
|
||||
c.t.Errorf("got GetSockOpt(%T) = 0x%x, want = 0x%x", v, v, 0)
|
||||
c.t.Errorf("got GetSockOptInt(IPv6TrafficClassOption) = 0x%x, want = 0x%x", v, 0)
|
||||
}
|
||||
|
||||
if err := c.ep.SetSockOpt(tcpip.IPv6TrafficClassOption(tClass)); err != nil {
|
||||
c.t.Errorf("SetSockOpt(%T, 0x%x) failed: %s", v, tcpip.IPv6TrafficClassOption(tClass), err)
|
||||
if err := c.ep.SetSockOptInt(tcpip.IPv6TrafficClassOption, tClass); err != nil {
|
||||
c.t.Errorf("SetSockOptInt(IPv6TrafficClassOption, 0x%x) failed: %s", tClass, err)
|
||||
}
|
||||
|
||||
if err := c.ep.GetSockOpt(&v); err != nil {
|
||||
c.t.Errorf("GetSockopt(%T) failed: %s", v, err)
|
||||
v, err = c.ep.GetSockOptInt(tcpip.IPv6TrafficClassOption)
|
||||
if err != nil {
|
||||
c.t.Errorf("GetSockOptInt(IPv6TrafficClassOption) failed: %s", err)
|
||||
}
|
||||
|
||||
if want := tcpip.IPv6TrafficClassOption(tClass); v != want {
|
||||
c.t.Errorf("got GetSockOpt(%T) = 0x%x, want = 0x%x", v, v, want)
|
||||
if v != tClass {
|
||||
c.t.Errorf("got GetSockOptInt(IPv6TrafficClassOption) = 0x%x, want = 0x%x", v, tClass)
|
||||
}
|
||||
|
||||
// The header getter for TClass is called TOS, so use that checker.
|
||||
@@ -1430,7 +1432,7 @@ func TestReceiveTosTClass(t *testing.T) {
|
||||
// Verify that setting and reading the option works.
|
||||
v, err := c.ep.GetSockOptBool(option)
|
||||
if err != nil {
|
||||
c.t.Errorf("GetSockoptBool(%s) failed: %s", name, err)
|
||||
c.t.Errorf("GetSockOptBool(%s) failed: %s", name, err)
|
||||
}
|
||||
// Test for expected default value.
|
||||
if v != false {
|
||||
@@ -1444,7 +1446,7 @@ func TestReceiveTosTClass(t *testing.T) {
|
||||
|
||||
got, err := c.ep.GetSockOptBool(option)
|
||||
if err != nil {
|
||||
c.t.Errorf("GetSockoptBool(%s) failed: %s", name, err)
|
||||
c.t.Errorf("GetSockOptBool(%s) failed: %s", name, err)
|
||||
}
|
||||
|
||||
if got != want {
|
||||
|
||||
Reference in New Issue
Block a user