2020-03-17 15:52:14 +00:00
// Copyright 2020 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 testbench has utilities to send and receive packets and also command
// the DUT to run POSIX functions.
package testbench
import (
"fmt"
"math/rand"
"net"
"testing"
"time"
"github.com/mohae/deepcopy"
2020-04-16 22:14:44 +00:00
"go.uber.org/multierr"
2020-03-17 15:52:14 +00:00
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/seqnum"
)
2020-04-29 01:49:19 +00:00
func portFromSockaddr ( sa unix . Sockaddr ) ( uint16 , error ) {
switch sa := sa . ( type ) {
case * unix . SockaddrInet4 :
return uint16 ( sa . Port ) , nil
case * unix . SockaddrInet6 :
return uint16 ( sa . Port ) , nil
}
return 0 , fmt . Errorf ( "sockaddr type %T does not contain port" , sa )
}
2020-07-10 05:37:11 +00:00
// pickPort makes a new socket and returns the socket FD and port. The domain
// should be AF_INET or AF_INET6. The caller must close the FD when done with
2020-04-24 22:55:11 +00:00
// the port if there is no error.
2020-07-14 18:48:26 +00:00
func pickPort ( domain , typ int ) ( fd int , port uint16 , err error ) {
fd , err = unix . Socket ( domain , typ , 0 )
2020-03-17 15:52:14 +00:00
if err != nil {
2020-07-14 18:48:26 +00:00
return - 1 , 0 , fmt . Errorf ( "creating socket: %w" , err )
2020-03-17 15:52:14 +00:00
}
2020-04-24 22:55:11 +00:00
defer func ( ) {
if err != nil {
2020-07-14 18:48:26 +00:00
if cerr := unix . Close ( fd ) ; cerr != nil {
err = multierr . Append ( err , fmt . Errorf ( "failed to close socket %d: %w" , fd , cerr ) )
}
2020-04-24 22:55:11 +00:00
}
} ( )
2020-06-11 20:46:56 +00:00
var sa unix . Sockaddr
2020-04-24 22:55:11 +00:00
switch domain {
case unix . AF_INET :
var sa4 unix . SockaddrInet4
2020-05-11 22:52:42 +00:00
copy ( sa4 . Addr [ : ] , net . ParseIP ( LocalIPv4 ) . To4 ( ) )
2020-04-24 22:55:11 +00:00
sa = & sa4
case unix . AF_INET6 :
2020-07-14 18:48:26 +00:00
sa6 := unix . SockaddrInet6 { ZoneId : uint32 ( LocalInterfaceID ) }
2020-05-11 22:52:42 +00:00
copy ( sa6 . Addr [ : ] , net . ParseIP ( LocalIPv6 ) . To16 ( ) )
2020-04-24 22:55:11 +00:00
sa = & sa6
default :
2020-06-11 20:46:56 +00:00
return - 1 , 0 , fmt . Errorf ( "invalid domain %d, it should be one of unix.AF_INET or unix.AF_INET6" , domain )
2020-04-24 22:55:11 +00:00
}
if err = unix . Bind ( fd , sa ) ; err != nil {
2020-07-14 18:48:26 +00:00
return - 1 , 0 , fmt . Errorf ( "binding to %+v: %w" , sa , err )
2020-03-17 15:52:14 +00:00
}
2020-04-29 01:49:19 +00:00
sa , err = unix . Getsockname ( fd )
2020-03-17 15:52:14 +00:00
if err != nil {
2020-07-14 18:48:26 +00:00
return - 1 , 0 , fmt . Errorf ( "Getsocketname(%d): %w" , fd , err )
2020-03-17 15:52:14 +00:00
}
2020-07-14 18:48:26 +00:00
port , err = portFromSockaddr ( sa )
2020-06-11 20:46:56 +00:00
if err != nil {
2020-07-14 18:48:26 +00:00
return - 1 , 0 , fmt . Errorf ( "extracting port from socket address %+v: %w" , sa , err )
2020-06-11 20:46:56 +00:00
}
return fd , port , nil
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
// layerState stores the state of a layer of a connection.
type layerState interface {
2020-04-24 22:02:33 +00:00
// outgoing returns an outgoing layer to be sent in a frame. It should not
// update layerState, that is done in layerState.sent.
2020-04-15 19:59:58 +00:00
outgoing ( ) Layer
// incoming creates an expected Layer for comparing against a received Layer.
// Because the expectation can depend on values in the received Layer, it is
// an input to incoming. For example, the ACK number needs to be checked in a
2020-04-24 22:02:33 +00:00
// TCP packet but only if the ACK flag is set in the received packet. It
// should not update layerState, that is done in layerState.received. The
// caller takes ownership of the returned Layer.
2020-04-15 19:59:58 +00:00
incoming ( received Layer ) Layer
// sent updates the layerState based on the Layer that was sent. The input is
// a Layer with all prev and next pointers populated so that the entire frame
// as it was sent is available.
sent ( sent Layer ) error
// received updates the layerState based on a Layer that is receieved. The
// input is a Layer with all prev and next pointers populated so that the
// entire frame as it was receieved is available.
received ( received Layer ) error
// close frees associated resources held by the LayerState.
close ( ) error
2020-04-01 02:51:52 +00:00
}
2020-04-15 19:59:58 +00:00
// etherState maintains state about an Ethernet connection.
type etherState struct {
out , in Ether
}
2020-03-17 15:52:14 +00:00
2020-04-15 19:59:58 +00:00
var _ layerState = ( * etherState ) ( nil )
// newEtherState creates a new etherState.
func newEtherState ( out , in Ether ) ( * etherState , error ) {
2020-05-11 22:52:42 +00:00
lMAC , err := tcpip . ParseMACAddress ( LocalMAC )
2020-03-17 15:52:14 +00:00
if err != nil {
2020-05-27 00:39:19 +00:00
return nil , fmt . Errorf ( "parsing local MAC: %q: %w" , LocalMAC , err )
2020-03-17 15:52:14 +00:00
}
2020-05-11 22:52:42 +00:00
rMAC , err := tcpip . ParseMACAddress ( RemoteMAC )
2020-03-17 15:52:14 +00:00
if err != nil {
2020-05-27 00:39:19 +00:00
return nil , fmt . Errorf ( "parsing remote MAC: %q: %w" , RemoteMAC , err )
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
s := etherState {
out : Ether { SrcAddr : & lMAC , DstAddr : & rMAC } ,
in : Ether { SrcAddr : & rMAC , DstAddr : & lMAC } ,
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
if err := s . out . merge ( & out ) ; err != nil {
return nil , err
}
if err := s . in . merge ( & in ) ; err != nil {
return nil , err
}
return & s , nil
}
func ( s * etherState ) outgoing ( ) Layer {
2020-04-24 22:55:11 +00:00
return deepcopy . Copy ( & s . out ) . ( Layer )
2020-04-15 19:59:58 +00:00
}
2020-04-22 14:27:34 +00:00
// incoming implements layerState.incoming.
2020-04-15 19:59:58 +00:00
func ( s * etherState ) incoming ( Layer ) Layer {
return deepcopy . Copy ( & s . in ) . ( Layer )
}
func ( * etherState ) sent ( Layer ) error {
return nil
}
func ( * etherState ) received ( Layer ) error {
return nil
}
func ( * etherState ) close ( ) error {
return nil
}
// ipv4State maintains state about an IPv4 connection.
type ipv4State struct {
out , in IPv4
}
var _ layerState = ( * ipv4State ) ( nil )
// newIPv4State creates a new ipv4State.
func newIPv4State ( out , in IPv4 ) ( * ipv4State , error ) {
2020-05-11 22:52:42 +00:00
lIP := tcpip . Address ( net . ParseIP ( LocalIPv4 ) . To4 ( ) )
rIP := tcpip . Address ( net . ParseIP ( RemoteIPv4 ) . To4 ( ) )
2020-04-15 19:59:58 +00:00
s := ipv4State {
out : IPv4 { SrcAddr : & lIP , DstAddr : & rIP } ,
in : IPv4 { SrcAddr : & rIP , DstAddr : & lIP } ,
}
if err := s . out . merge ( & out ) ; err != nil {
return nil , err
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
if err := s . in . merge ( & in ) ; err != nil {
return nil , err
}
return & s , nil
}
2020-03-17 15:52:14 +00:00
2020-04-15 19:59:58 +00:00
func ( s * ipv4State ) outgoing ( ) Layer {
2020-04-24 22:55:11 +00:00
return deepcopy . Copy ( & s . out ) . ( Layer )
2020-04-15 19:59:58 +00:00
}
2020-04-22 14:27:34 +00:00
// incoming implements layerState.incoming.
2020-04-15 19:59:58 +00:00
func ( s * ipv4State ) incoming ( Layer ) Layer {
return deepcopy . Copy ( & s . in ) . ( Layer )
}
func ( * ipv4State ) sent ( Layer ) error {
return nil
}
func ( * ipv4State ) received ( Layer ) error {
return nil
}
func ( * ipv4State ) close ( ) error {
return nil
}
2020-04-24 22:55:11 +00:00
// ipv6State maintains state about an IPv6 connection.
type ipv6State struct {
out , in IPv6
}
var _ layerState = ( * ipv6State ) ( nil )
// newIPv6State creates a new ipv6State.
func newIPv6State ( out , in IPv6 ) ( * ipv6State , error ) {
2020-05-11 22:52:42 +00:00
lIP := tcpip . Address ( net . ParseIP ( LocalIPv6 ) . To16 ( ) )
rIP := tcpip . Address ( net . ParseIP ( RemoteIPv6 ) . To16 ( ) )
2020-04-24 22:55:11 +00:00
s := ipv6State {
out : IPv6 { SrcAddr : & lIP , DstAddr : & rIP } ,
in : IPv6 { SrcAddr : & rIP , DstAddr : & lIP } ,
}
if err := s . out . merge ( & out ) ; err != nil {
return nil , err
}
if err := s . in . merge ( & in ) ; err != nil {
return nil , err
}
return & s , nil
}
// outgoing returns an outgoing layer to be sent in a frame.
func ( s * ipv6State ) outgoing ( ) Layer {
return deepcopy . Copy ( & s . out ) . ( Layer )
}
func ( s * ipv6State ) incoming ( Layer ) Layer {
return deepcopy . Copy ( & s . in ) . ( Layer )
}
func ( s * ipv6State ) sent ( Layer ) error {
// Nothing to do.
return nil
}
func ( s * ipv6State ) received ( Layer ) error {
// Nothing to do.
return nil
}
// close cleans up any resources held.
func ( s * ipv6State ) close ( ) error {
return nil
}
2020-04-15 19:59:58 +00:00
// tcpState maintains state about a TCP connection.
type tcpState struct {
out , in TCP
localSeqNum , remoteSeqNum * seqnum . Value
synAck * TCP
portPickerFD int
2020-04-16 19:21:06 +00:00
finSent bool
2020-04-15 19:59:58 +00:00
}
var _ layerState = ( * tcpState ) ( nil )
// SeqNumValue is a helper routine that allocates a new seqnum.Value value to
// store v and returns a pointer to it.
func SeqNumValue ( v seqnum . Value ) * seqnum . Value {
return & v
}
// newTCPState creates a new TCPState.
2020-06-11 20:46:56 +00:00
func newTCPState ( domain int , out , in TCP ) ( * tcpState , error ) {
portPickerFD , localPort , err := pickPort ( domain , unix . SOCK_STREAM )
2020-03-17 15:52:14 +00:00
if err != nil {
2020-06-11 20:46:56 +00:00
return nil , err
2020-04-15 19:59:58 +00:00
}
s := tcpState {
out : TCP { SrcPort : & localPort } ,
in : TCP { DstPort : & localPort } ,
localSeqNum : SeqNumValue ( seqnum . Value ( rand . Uint32 ( ) ) ) ,
portPickerFD : portPickerFD ,
2020-04-16 19:21:06 +00:00
finSent : false ,
2020-04-15 19:59:58 +00:00
}
if err := s . out . merge ( & out ) ; err != nil {
2020-06-11 20:46:56 +00:00
return nil , err
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
if err := s . in . merge ( & in ) ; err != nil {
2020-06-11 20:46:56 +00:00
return nil , err
2020-04-15 19:59:58 +00:00
}
2020-06-11 20:46:56 +00:00
return & s , nil
2020-04-15 19:59:58 +00:00
}
2020-03-17 15:52:14 +00:00
2020-04-15 19:59:58 +00:00
func ( s * tcpState ) outgoing ( ) Layer {
newOutgoing := deepcopy . Copy ( s . out ) . ( TCP )
if s . localSeqNum != nil {
newOutgoing . SeqNum = Uint32 ( uint32 ( * s . localSeqNum ) )
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
if s . remoteSeqNum != nil {
newOutgoing . AckNum = Uint32 ( uint32 ( * s . remoteSeqNum ) )
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
return & newOutgoing
}
2020-04-22 14:27:34 +00:00
// incoming implements layerState.incoming.
2020-04-15 19:59:58 +00:00
func ( s * tcpState ) incoming ( received Layer ) Layer {
tcpReceived , ok := received . ( * TCP )
if ! ok {
return nil
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
newIn := deepcopy . Copy ( s . in ) . ( TCP )
if s . remoteSeqNum != nil {
newIn . SeqNum = Uint32 ( uint32 ( * s . remoteSeqNum ) )
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
if s . localSeqNum != nil && ( * tcpReceived . Flags & header . TCPFlagAck ) != 0 {
// The caller didn't specify an AckNum so we'll expect the calculated one,
// but only if the ACK flag is set because the AckNum is not valid in a
// header if ACK is not set.
newIn . AckNum = Uint32 ( uint32 ( * s . localSeqNum ) )
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
return & newIn
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
func ( s * tcpState ) sent ( sent Layer ) error {
tcp , ok := sent . ( * TCP )
if ! ok {
return fmt . Errorf ( "can't update tcpState with %T Layer" , sent )
2020-03-17 15:52:14 +00:00
}
2020-04-16 19:21:06 +00:00
if ! s . finSent {
// update localSeqNum by the payload only when FIN is not yet sent by us
for current := tcp . next ( ) ; current != nil ; current = current . next ( ) {
s . localSeqNum . UpdateForward ( seqnum . Size ( current . length ( ) ) )
}
2020-04-15 19:59:58 +00:00
}
if tcp . Flags != nil && * tcp . Flags & ( header . TCPFlagSyn | header . TCPFlagFin ) != 0 {
s . localSeqNum . UpdateForward ( 1 )
}
2020-04-16 19:21:06 +00:00
if * tcp . Flags & ( header . TCPFlagFin ) != 0 {
s . finSent = true
}
2020-04-15 19:59:58 +00:00
return nil
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
func ( s * tcpState ) received ( l Layer ) error {
tcp , ok := l . ( * TCP )
if ! ok {
return fmt . Errorf ( "can't update tcpState with %T Layer" , l )
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
s . remoteSeqNum = SeqNumValue ( seqnum . Value ( * tcp . SeqNum ) )
if * tcp . Flags & ( header . TCPFlagSyn | header . TCPFlagFin ) != 0 {
s . remoteSeqNum . UpdateForward ( 1 )
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
for current := tcp . next ( ) ; current != nil ; current = current . next ( ) {
s . remoteSeqNum . UpdateForward ( seqnum . Size ( current . length ( ) ) )
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
return nil
2020-04-01 02:51:52 +00:00
}
2020-04-15 19:59:58 +00:00
// close frees the port associated with this connection.
func ( s * tcpState ) close ( ) error {
if err := unix . Close ( s . portPickerFD ) ; err != nil {
return err
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
s . portPickerFD = - 1
return nil
}
// udpState maintains state about a UDP connection.
type udpState struct {
out , in UDP
portPickerFD int
}
2020-03-17 15:52:14 +00:00
2020-04-15 19:59:58 +00:00
var _ layerState = ( * udpState ) ( nil )
// newUDPState creates a new udpState.
2020-06-11 20:46:56 +00:00
func newUDPState ( domain int , out , in UDP ) ( * udpState , error ) {
portPickerFD , localPort , err := pickPort ( domain , unix . SOCK_DGRAM )
2020-04-15 19:59:58 +00:00
if err != nil {
2020-07-14 18:48:26 +00:00
return nil , fmt . Errorf ( "picking port: %w" , err )
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
s := udpState {
out : UDP { SrcPort : & localPort } ,
in : UDP { DstPort : & localPort } ,
portPickerFD : portPickerFD ,
}
if err := s . out . merge ( & out ) ; err != nil {
2020-06-11 20:46:56 +00:00
return nil , err
2020-04-15 19:59:58 +00:00
}
if err := s . in . merge ( & in ) ; err != nil {
2020-06-11 20:46:56 +00:00
return nil , err
2020-03-17 15:52:14 +00:00
}
2020-06-11 20:46:56 +00:00
return & s , nil
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
func ( s * udpState ) outgoing ( ) Layer {
2020-04-24 22:55:11 +00:00
return deepcopy . Copy ( & s . out ) . ( Layer )
2020-04-15 19:59:58 +00:00
}
2020-04-22 14:27:34 +00:00
// incoming implements layerState.incoming.
2020-04-15 19:59:58 +00:00
func ( s * udpState ) incoming ( Layer ) Layer {
return deepcopy . Copy ( & s . in ) . ( Layer )
}
func ( * udpState ) sent ( l Layer ) error {
return nil
2020-04-01 02:51:52 +00:00
}
2020-04-15 19:59:58 +00:00
func ( * udpState ) received ( l Layer ) error {
return nil
}
// close frees the port associated with this connection.
func ( s * udpState ) close ( ) error {
if err := unix . Close ( s . portPickerFD ) ; err != nil {
return err
2020-04-08 00:48:06 +00:00
}
2020-04-15 19:59:58 +00:00
s . portPickerFD = - 1
2020-04-08 00:48:06 +00:00
return nil
}
2020-04-15 19:59:58 +00:00
// Connection holds a collection of layer states for maintaining a connection
// along with sockets for sniffer and injecting packets.
type Connection struct {
layerStates [ ] layerState
injector Injector
sniffer Sniffer
}
2020-04-24 22:02:33 +00:00
// Returns the default incoming frame against which to match. If received is
// longer than layerStates then that may still count as a match. The reverse is
// never a match and nil is returned.
func ( conn * Connection ) incoming ( received Layers ) Layers {
if len ( received ) < len ( conn . layerStates ) {
return nil
}
in := Layers { }
for i , s := range conn . layerStates {
toMatch := s . incoming ( received [ i ] )
if toMatch == nil {
return nil
2020-03-17 15:52:14 +00:00
}
2020-04-24 22:02:33 +00:00
in = append ( in , toMatch )
2020-04-15 19:59:58 +00:00
}
2020-04-24 22:02:33 +00:00
return in
}
func ( conn * Connection ) match ( override , received Layers ) bool {
toMatch := conn . incoming ( received )
if toMatch == nil {
return false // Not enough layers in gotLayers for matching.
}
if err := toMatch . merge ( override ) ; err != nil {
return false // Failing to merge is not matching.
}
return toMatch . match ( received )
2020-04-15 19:59:58 +00:00
}
// Close frees associated resources held by the Connection.
2020-07-27 13:37:11 +00:00
func ( conn * Connection ) Close ( t * testing . T ) {
t . Helper ( )
2020-04-16 22:14:44 +00:00
errs := multierr . Combine ( conn . sniffer . close ( ) , conn . injector . close ( ) )
2020-04-15 19:59:58 +00:00
for _ , s := range conn . layerStates {
if err := s . close ( ) ; err != nil {
2020-04-16 22:14:44 +00:00
errs = multierr . Append ( errs , fmt . Errorf ( "unable to close %+v: %s" , s , err ) )
2020-03-17 15:52:14 +00:00
}
}
2020-04-16 22:14:44 +00:00
if errs != nil {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "unable to close %+v: %s" , conn , errs )
2020-04-16 22:14:44 +00:00
}
2020-03-17 15:52:14 +00:00
}
2020-06-11 20:46:56 +00:00
// CreateFrame builds a frame for the connection with defaults overriden
// from the innermost layer out, and additionalLayers added after it.
//
// Note that overrideLayers can have a length that is less than the number
// of layers in this connection, and in such cases the innermost layers are
// overriden first. As an example, valid values of overrideLayers for a TCP-
// over-IPv4-over-Ethernet connection are: nil, [TCP], [IPv4, TCP], and
// [Ethernet, IPv4, TCP].
2020-07-27 13:37:11 +00:00
func ( conn * Connection ) CreateFrame ( t * testing . T , overrideLayers Layers , additionalLayers ... Layer ) Layers {
t . Helper ( )
2020-04-15 19:59:58 +00:00
var layersToSend Layers
2020-06-11 20:46:56 +00:00
for i , s := range conn . layerStates {
layer := s . outgoing ( )
// overrideLayers and conn.layerStates have their tails aligned, so
// to find the index we move backwards by the distance i is to the
// end.
if j := len ( overrideLayers ) - ( len ( conn . layerStates ) - i ) ; j >= 0 {
if err := layer . merge ( overrideLayers [ j ] ) ; err != nil {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "can't merge %+v into %+v: %s" , layer , overrideLayers [ j ] , err )
2020-06-11 20:46:56 +00:00
}
}
layersToSend = append ( layersToSend , layer )
2020-04-15 19:59:58 +00:00
}
layersToSend = append ( layersToSend , additionalLayers ... )
return layersToSend
2020-04-14 06:04:01 +00:00
}
2020-06-11 20:46:56 +00:00
// SendFrameStateless sends a frame without updating any of the layer states.
//
// This method is useful for sending out-of-band control messages such as
// ICMP packets, where it would not make sense to update the transport layer's
// state using the ICMP header.
2020-07-27 13:37:11 +00:00
func ( conn * Connection ) SendFrameStateless ( t * testing . T , frame Layers ) {
t . Helper ( )
2020-06-11 20:46:56 +00:00
outBytes , err := frame . ToBytes ( )
if err != nil {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "can't build outgoing packet: %s" , err )
2020-06-11 20:46:56 +00:00
}
2020-07-27 13:37:11 +00:00
conn . injector . Send ( t , outBytes )
2020-06-11 20:46:56 +00:00
}
2020-04-15 19:59:58 +00:00
// SendFrame sends a frame on the wire and updates the state of all layers.
2020-07-27 13:37:11 +00:00
func ( conn * Connection ) SendFrame ( t * testing . T , frame Layers ) {
t . Helper ( )
2020-04-24 22:55:11 +00:00
outBytes , err := frame . ToBytes ( )
2020-04-15 19:59:58 +00:00
if err != nil {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "can't build outgoing packet: %s" , err )
2020-04-15 19:59:58 +00:00
}
2020-07-27 13:37:11 +00:00
conn . injector . Send ( t , outBytes )
2020-04-15 19:59:58 +00:00
// frame might have nil values where the caller wanted to use default values.
// sentFrame will have no nil values in it because it comes from parsing the
// bytes that were actually sent.
sentFrame := parse ( parseEther , outBytes )
// Update the state of each layer based on what was sent.
for i , s := range conn . layerStates {
if err := s . sent ( sentFrame [ i ] ) ; err != nil {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "Unable to update the state of %+v with %s: %s" , s , sentFrame [ i ] , err )
2020-03-17 15:52:14 +00:00
}
}
}
2020-06-11 20:46:56 +00:00
// send sends a packet, possibly with layers of this connection overridden and
// additional layers added.
//
// Types defined with Connection as the underlying type should expose
// type-safe versions of this method.
2020-07-27 13:37:11 +00:00
func ( conn * Connection ) send ( t * testing . T , overrideLayers Layers , additionalLayers ... Layer ) {
t . Helper ( )
conn . SendFrame ( t , conn . CreateFrame ( t , overrideLayers , additionalLayers ... ) )
2020-04-15 19:59:58 +00:00
}
// recvFrame gets the next successfully parsed frame (of type Layers) within the
// timeout provided. If no parsable frame arrives before the timeout, it returns
// nil.
2020-07-27 13:37:11 +00:00
func ( conn * Connection ) recvFrame ( t * testing . T , timeout time . Duration ) Layers {
t . Helper ( )
2020-04-15 19:59:58 +00:00
if timeout <= 0 {
return nil
}
2020-07-27 13:37:11 +00:00
b := conn . sniffer . Recv ( t , timeout )
2020-04-15 19:59:58 +00:00
if b == nil {
return nil
}
return parse ( parseEther , b )
}
2020-04-24 22:02:33 +00:00
// layersError stores the Layers that we got and the Layers that we wanted to
// match.
type layersError struct {
got , want Layers
}
func ( e * layersError ) Error ( ) string {
return e . got . diff ( e . want )
}
2020-04-29 01:49:19 +00:00
// Expect expects a frame with the final layerStates layer matching the
// provided Layer within the timeout specified. If it doesn't arrive in time,
// an error is returned.
2020-07-27 13:37:11 +00:00
func ( conn * Connection ) Expect ( t * testing . T , layer Layer , timeout time . Duration ) ( Layer , error ) {
t . Helper ( )
2020-04-15 19:59:58 +00:00
// Make a frame that will ignore all but the final layer.
layers := make ( [ ] Layer , len ( conn . layerStates ) )
layers [ len ( layers ) - 1 ] = layer
2020-07-27 13:37:11 +00:00
gotFrame , err := conn . ExpectFrame ( t , layers , timeout )
2020-04-15 19:59:58 +00:00
if err != nil {
return nil , err
}
if len ( conn . layerStates ) - 1 < len ( gotFrame ) {
return gotFrame [ len ( conn . layerStates ) - 1 ] , nil
}
2020-07-27 13:37:11 +00:00
t . Fatalf ( "the received frame should be at least as long as the expected layers, got %d layers, want at least %d layers, got frame: %#v" , len ( gotFrame ) , len ( conn . layerStates ) , gotFrame )
2020-04-24 22:02:33 +00:00
panic ( "unreachable" )
2020-04-15 19:59:58 +00:00
}
// ExpectFrame expects a frame that matches the provided Layers within the
2020-04-24 22:02:33 +00:00
// timeout specified. If one arrives in time, the Layers is returned without an
// error. If it doesn't arrive in time, it returns nil and error is non-nil.
2020-07-27 13:37:11 +00:00
func ( conn * Connection ) ExpectFrame ( t * testing . T , layers Layers , timeout time . Duration ) ( Layers , error ) {
t . Helper ( )
2020-04-08 00:48:06 +00:00
deadline := time . Now ( ) . Add ( timeout )
2020-04-24 22:02:33 +00:00
var errs error
2020-04-08 00:48:06 +00:00
for {
2020-04-15 19:59:58 +00:00
var gotLayers Layers
if timeout = time . Until ( deadline ) ; timeout > 0 {
2020-07-27 13:37:11 +00:00
gotLayers = conn . recvFrame ( t , timeout )
2020-04-15 19:59:58 +00:00
}
if gotLayers == nil {
2020-04-24 22:02:33 +00:00
if errs == nil {
return nil , fmt . Errorf ( "got no frames matching %v during %s" , layers , timeout )
}
2020-09-02 00:40:28 +00:00
return nil , fmt . Errorf ( "got frames %w want %v during %s" , errs , layers , timeout )
2020-04-08 00:48:06 +00:00
}
2020-04-15 19:59:58 +00:00
if conn . match ( layers , gotLayers ) {
for i , s := range conn . layerStates {
if err := s . received ( gotLayers [ i ] ) ; err != nil {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "failed to update test connection's layer states based on received frame: %s" , err )
2020-04-15 19:59:58 +00:00
}
}
return gotLayers , nil
2020-04-08 00:48:06 +00:00
}
2020-04-24 22:02:33 +00:00
errs = multierr . Combine ( errs , & layersError { got : gotLayers , want : conn . incoming ( gotLayers ) } )
2020-04-08 00:48:06 +00:00
}
}
2020-04-15 19:59:58 +00:00
// Drain drains the sniffer's receive buffer by receiving packets until there's
// nothing else to receive.
2020-07-27 13:37:11 +00:00
func ( conn * Connection ) Drain ( t * testing . T ) {
t . Helper ( )
conn . sniffer . Drain ( t )
2020-04-15 19:59:58 +00:00
}
// TCPIPv4 maintains the state for all the layers in a TCP/IPv4 connection.
type TCPIPv4 Connection
// NewTCPIPv4 creates a new TCPIPv4 connection with reasonable defaults.
func NewTCPIPv4 ( t * testing . T , outgoingTCP , incomingTCP TCP ) TCPIPv4 {
2020-07-27 13:37:11 +00:00
t . Helper ( )
2020-04-15 19:59:58 +00:00
etherState , err := newEtherState ( Ether { } , Ether { } )
if err != nil {
t . Fatalf ( "can't make etherState: %s" , err )
}
ipv4State , err := newIPv4State ( IPv4 { } , IPv4 { } )
if err != nil {
t . Fatalf ( "can't make ipv4State: %s" , err )
}
2020-06-11 20:46:56 +00:00
tcpState , err := newTCPState ( unix . AF_INET , outgoingTCP , incomingTCP )
2020-04-15 19:59:58 +00:00
if err != nil {
t . Fatalf ( "can't make tcpState: %s" , err )
2020-04-08 00:48:06 +00:00
}
2020-04-15 19:59:58 +00:00
injector , err := NewInjector ( t )
if err != nil {
t . Fatalf ( "can't make injector: %s" , err )
}
sniffer , err := NewSniffer ( t )
if err != nil {
t . Fatalf ( "can't make sniffer: %s" , err )
}
return TCPIPv4 {
layerStates : [ ] layerState { etherState , ipv4State , tcpState } ,
injector : injector ,
sniffer : sniffer ,
2020-04-08 00:48:06 +00:00
}
}
2020-06-04 21:22:46 +00:00
// Connect performs a TCP 3-way handshake. The input Connection should have a
2020-04-15 19:59:58 +00:00
// final TCP Layer.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) Connect ( t * testing . T ) {
t . Helper ( )
2020-06-04 21:22:46 +00:00
2020-03-17 15:52:14 +00:00
// Send the SYN.
2020-07-27 13:37:11 +00:00
conn . Send ( t , TCP { Flags : Uint8 ( header . TCPFlagSyn ) } )
2020-03-17 15:52:14 +00:00
// Wait for the SYN-ACK.
2020-07-27 13:37:11 +00:00
synAck , err := conn . Expect ( t , TCP { Flags : Uint8 ( header . TCPFlagSyn | header . TCPFlagAck ) } , time . Second )
2020-06-04 21:22:46 +00:00
if err != nil {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "didn't get synack during handshake: %s" , err )
2020-06-04 21:22:46 +00:00
}
conn . layerStates [ len ( conn . layerStates ) - 1 ] . ( * tcpState ) . synAck = synAck
// Send an ACK.
2020-07-27 13:37:11 +00:00
conn . Send ( t , TCP { Flags : Uint8 ( header . TCPFlagAck ) } )
2020-06-04 21:22:46 +00:00
}
// ConnectWithOptions performs a TCP 3-way handshake with given TCP options.
// The input Connection should have a final TCP Layer.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) ConnectWithOptions ( t * testing . T , options [ ] byte ) {
t . Helper ( )
2020-06-04 21:22:46 +00:00
// Send the SYN.
2020-07-27 13:37:11 +00:00
conn . Send ( t , TCP { Flags : Uint8 ( header . TCPFlagSyn ) , Options : options } )
2020-06-04 21:22:46 +00:00
// Wait for the SYN-ACK.
2020-07-27 13:37:11 +00:00
synAck , err := conn . Expect ( t , TCP { Flags : Uint8 ( header . TCPFlagSyn | header . TCPFlagAck ) } , time . Second )
2020-06-04 21:22:46 +00:00
if err != nil {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "didn't get synack during handshake: %s" , err )
2020-03-17 15:52:14 +00:00
}
2020-04-15 19:59:58 +00:00
conn . layerStates [ len ( conn . layerStates ) - 1 ] . ( * tcpState ) . synAck = synAck
2020-03-17 15:52:14 +00:00
// Send an ACK.
2020-07-27 13:37:11 +00:00
conn . Send ( t , TCP { Flags : Uint8 ( header . TCPFlagAck ) } )
2020-03-17 15:52:14 +00:00
}
2020-04-01 02:51:52 +00:00
2020-04-15 19:59:58 +00:00
// ExpectData is a convenient method that expects a Layer and the Layer after
// it. If it doens't arrive in time, it returns nil.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) ExpectData ( t * testing . T , tcp * TCP , payload * Payload , timeout time . Duration ) ( Layers , error ) {
t . Helper ( )
2020-04-15 19:59:58 +00:00
expected := make ( [ ] Layer , len ( conn . layerStates ) )
expected [ len ( expected ) - 1 ] = tcp
if payload != nil {
expected = append ( expected , payload )
}
2020-07-27 13:37:11 +00:00
return ( * Connection ) ( conn ) . ExpectFrame ( t , expected , timeout )
2020-04-15 19:59:58 +00:00
}
2020-06-04 21:22:46 +00:00
// ExpectNextData attempts to receive the next incoming segment for the
// connection and expects that to match the given layers.
//
// It differs from ExpectData() in that here we are only interested in the next
// received segment, while ExpectData() can receive multiple segments for the
// connection until there is a match with given layers or a timeout.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) ExpectNextData ( t * testing . T , tcp * TCP , payload * Payload , timeout time . Duration ) ( Layers , error ) {
t . Helper ( )
2020-06-04 21:22:46 +00:00
// Receive the first incoming TCP segment for this connection.
2020-07-27 13:37:11 +00:00
got , err := conn . ExpectData ( t , & TCP { } , nil , timeout )
2020-06-04 21:22:46 +00:00
if err != nil {
return nil , err
}
expected := make ( [ ] Layer , len ( conn . layerStates ) )
expected [ len ( expected ) - 1 ] = tcp
if payload != nil {
expected = append ( expected , payload )
2020-07-27 13:37:11 +00:00
tcp . SeqNum = Uint32 ( uint32 ( * conn . RemoteSeqNum ( t ) ) - uint32 ( payload . Length ( ) ) )
2020-06-04 21:22:46 +00:00
}
if ! ( * Connection ) ( conn ) . match ( expected , got ) {
return nil , fmt . Errorf ( "next frame is not matching %s during %s: got %s" , expected , timeout , got )
}
return got , nil
}
2020-04-15 19:59:58 +00:00
// Send a packet with reasonable defaults. Potentially override the TCP layer in
// the connection with the provided layer and add additionLayers.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) Send ( t * testing . T , tcp TCP , additionalLayers ... Layer ) {
t . Helper ( )
( * Connection ) ( conn ) . send ( t , Layers { & tcp } , additionalLayers ... )
2020-04-01 02:51:52 +00:00
}
2020-04-15 19:59:58 +00:00
// Close frees associated resources held by the TCPIPv4 connection.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) Close ( t * testing . T ) {
t . Helper ( )
( * Connection ) ( conn ) . Close ( t )
2020-04-15 19:59:58 +00:00
}
2020-04-29 01:49:19 +00:00
// Expect expects a frame with the TCP layer matching the provided TCP within
// the timeout specified. If it doesn't arrive in time, an error is returned.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) Expect ( t * testing . T , tcp TCP , timeout time . Duration ) ( * TCP , error ) {
t . Helper ( )
layer , err := ( * Connection ) ( conn ) . Expect ( t , & tcp , timeout )
2020-04-15 19:59:58 +00:00
if layer == nil {
return nil , err
}
gotTCP , ok := layer . ( * TCP )
if ! ok {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "expected %s to be TCP" , layer )
2020-04-15 19:59:58 +00:00
}
return gotTCP , err
}
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) tcpState ( t * testing . T ) * tcpState {
t . Helper ( )
2020-06-11 20:46:56 +00:00
state , ok := conn . layerStates [ 2 ] . ( * tcpState )
if ! ok {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "got transport-layer state type=%T, expected tcpState" , conn . layerStates [ 2 ] )
2020-06-11 20:46:56 +00:00
}
return state
}
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) ipv4State ( t * testing . T ) * ipv4State {
t . Helper ( )
2020-06-11 20:46:56 +00:00
state , ok := conn . layerStates [ 1 ] . ( * ipv4State )
2020-04-15 19:59:58 +00:00
if ! ok {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "expected network-layer state type=%T, expected ipv4State" , conn . layerStates [ 1 ] )
2020-04-15 19:59:58 +00:00
}
2020-04-16 02:36:03 +00:00
return state
}
// RemoteSeqNum returns the next expected sequence number from the DUT.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) RemoteSeqNum ( t * testing . T ) * seqnum . Value {
t . Helper ( )
return conn . tcpState ( t ) . remoteSeqNum
2020-04-16 02:36:03 +00:00
}
2020-04-16 19:21:06 +00:00
// LocalSeqNum returns the next sequence number to send from the testbench.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) LocalSeqNum ( t * testing . T ) * seqnum . Value {
t . Helper ( )
return conn . tcpState ( t ) . localSeqNum
2020-04-16 02:36:03 +00:00
}
// SynAck returns the SynAck that was part of the handshake.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) SynAck ( t * testing . T ) * TCP {
t . Helper ( )
return conn . tcpState ( t ) . synAck
2020-04-15 19:59:58 +00:00
}
2020-05-30 00:22:56 +00:00
// LocalAddr gets the local socket address of this connection.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) LocalAddr ( t * testing . T ) * unix . SockaddrInet4 {
t . Helper ( )
sa := & unix . SockaddrInet4 { Port : int ( * conn . tcpState ( t ) . out . SrcPort ) }
copy ( sa . Addr [ : ] , * conn . ipv4State ( t ) . out . SrcAddr )
2020-06-11 20:46:56 +00:00
return sa
}
// Drain drains the sniffer's receive buffer by receiving packets until there's
// nothing else to receive.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv4 ) Drain ( t * testing . T ) {
t . Helper ( )
conn . sniffer . Drain ( t )
2020-05-30 00:22:56 +00:00
}
2020-10-29 17:42:39 +00:00
// IPv4Conn maintains the state for all the layers in a IPv4 connection.
type IPv4Conn Connection
// NewIPv4Conn creates a new IPv4Conn connection with reasonable defaults.
func NewIPv4Conn ( t * testing . T , outgoingIPv4 , incomingIPv4 IPv4 ) IPv4Conn {
t . Helper ( )
etherState , err := newEtherState ( Ether { } , Ether { } )
if err != nil {
t . Fatalf ( "can't make EtherState: %s" , err )
}
ipv4State , err := newIPv4State ( outgoingIPv4 , incomingIPv4 )
if err != nil {
t . Fatalf ( "can't make IPv4State: %s" , err )
}
injector , err := NewInjector ( t )
if err != nil {
t . Fatalf ( "can't make injector: %s" , err )
}
sniffer , err := NewSniffer ( t )
if err != nil {
t . Fatalf ( "can't make sniffer: %s" , err )
}
return IPv4Conn {
layerStates : [ ] layerState { etherState , ipv4State } ,
injector : injector ,
sniffer : sniffer ,
}
}
// Send sends a frame with ipv4 overriding the IPv4 layer defaults and
// additionalLayers added after it.
func ( c * IPv4Conn ) Send ( t * testing . T , ipv4 IPv4 , additionalLayers ... Layer ) {
t . Helper ( )
( * Connection ) ( c ) . send ( t , Layers { & ipv4 } , additionalLayers ... )
}
// Close cleans up any resources held.
func ( c * IPv4Conn ) Close ( t * testing . T ) {
t . Helper ( )
( * Connection ) ( c ) . Close ( t )
}
// ExpectFrame expects a frame that matches the provided Layers within the
// timeout specified. If it doesn't arrive in time, an error is returned.
func ( c * IPv4Conn ) ExpectFrame ( t * testing . T , frame Layers , timeout time . Duration ) ( Layers , error ) {
t . Helper ( )
return ( * Connection ) ( c ) . ExpectFrame ( t , frame , timeout )
}
2020-04-24 22:55:11 +00:00
// IPv6Conn maintains the state for all the layers in a IPv6 connection.
type IPv6Conn Connection
// NewIPv6Conn creates a new IPv6Conn connection with reasonable defaults.
func NewIPv6Conn ( t * testing . T , outgoingIPv6 , incomingIPv6 IPv6 ) IPv6Conn {
2020-07-27 13:37:11 +00:00
t . Helper ( )
2020-04-24 22:55:11 +00:00
etherState , err := newEtherState ( Ether { } , Ether { } )
if err != nil {
t . Fatalf ( "can't make EtherState: %s" , err )
}
ipv6State , err := newIPv6State ( outgoingIPv6 , incomingIPv6 )
if err != nil {
t . Fatalf ( "can't make IPv6State: %s" , err )
}
injector , err := NewInjector ( t )
if err != nil {
t . Fatalf ( "can't make injector: %s" , err )
}
sniffer , err := NewSniffer ( t )
if err != nil {
t . Fatalf ( "can't make sniffer: %s" , err )
}
return IPv6Conn {
layerStates : [ ] layerState { etherState , ipv6State } ,
injector : injector ,
sniffer : sniffer ,
}
}
2020-06-11 20:46:56 +00:00
// Send sends a frame with ipv6 overriding the IPv6 layer defaults and
// additionalLayers added after it.
2020-07-27 13:37:11 +00:00
func ( conn * IPv6Conn ) Send ( t * testing . T , ipv6 IPv6 , additionalLayers ... Layer ) {
t . Helper ( )
( * Connection ) ( conn ) . send ( t , Layers { & ipv6 } , additionalLayers ... )
2020-04-24 22:55:11 +00:00
}
// Close to clean up any resources held.
2020-07-27 13:37:11 +00:00
func ( conn * IPv6Conn ) Close ( t * testing . T ) {
t . Helper ( )
( * Connection ) ( conn ) . Close ( t )
2020-04-24 22:55:11 +00:00
}
// ExpectFrame expects a frame that matches the provided Layers within the
2020-04-29 01:49:19 +00:00
// timeout specified. If it doesn't arrive in time, an error is returned.
2020-07-27 13:37:11 +00:00
func ( conn * IPv6Conn ) ExpectFrame ( t * testing . T , frame Layers , timeout time . Duration ) ( Layers , error ) {
t . Helper ( )
return ( * Connection ) ( conn ) . ExpectFrame ( t , frame , timeout )
2020-04-24 22:55:11 +00:00
}
2020-04-15 19:59:58 +00:00
// UDPIPv4 maintains the state for all the layers in a UDP/IPv4 connection.
type UDPIPv4 Connection
2020-04-01 02:51:52 +00:00
// NewUDPIPv4 creates a new UDPIPv4 connection with reasonable defaults.
func NewUDPIPv4 ( t * testing . T , outgoingUDP , incomingUDP UDP ) UDPIPv4 {
2020-07-27 13:37:11 +00:00
t . Helper ( )
2020-04-15 19:59:58 +00:00
etherState , err := newEtherState ( Ether { } , Ether { } )
2020-04-01 02:51:52 +00:00
if err != nil {
2020-04-15 19:59:58 +00:00
t . Fatalf ( "can't make etherState: %s" , err )
2020-04-01 02:51:52 +00:00
}
2020-04-15 19:59:58 +00:00
ipv4State , err := newIPv4State ( IPv4 { } , IPv4 { } )
2020-04-01 02:51:52 +00:00
if err != nil {
2020-04-15 19:59:58 +00:00
t . Fatalf ( "can't make ipv4State: %s" , err )
2020-04-01 02:51:52 +00:00
}
2020-06-11 20:46:56 +00:00
udpState , err := newUDPState ( unix . AF_INET , outgoingUDP , incomingUDP )
2020-04-01 02:51:52 +00:00
if err != nil {
2020-04-15 19:59:58 +00:00
t . Fatalf ( "can't make udpState: %s" , err )
2020-04-01 02:51:52 +00:00
}
2020-04-15 19:59:58 +00:00
injector , err := NewInjector ( t )
2020-04-01 02:51:52 +00:00
if err != nil {
2020-04-15 19:59:58 +00:00
t . Fatalf ( "can't make injector: %s" , err )
2020-04-01 02:51:52 +00:00
}
2020-04-15 19:59:58 +00:00
sniffer , err := NewSniffer ( t )
2020-04-01 02:51:52 +00:00
if err != nil {
2020-04-15 19:59:58 +00:00
t . Fatalf ( "can't make sniffer: %s" , err )
2020-04-01 02:51:52 +00:00
}
return UDPIPv4 {
2020-04-29 01:49:19 +00:00
layerStates : [ ] layerState { etherState , ipv4State , udpState } ,
2020-04-15 19:59:58 +00:00
injector : injector ,
sniffer : sniffer ,
2020-04-01 02:51:52 +00:00
}
}
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv4 ) udpState ( t * testing . T ) * udpState {
t . Helper ( )
2020-06-11 20:46:56 +00:00
state , ok := conn . layerStates [ 2 ] . ( * udpState )
if ! ok {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "got transport-layer state type=%T, expected udpState" , conn . layerStates [ 2 ] )
2020-06-11 20:46:56 +00:00
}
return state
2020-04-29 01:49:19 +00:00
}
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv4 ) ipv4State ( t * testing . T ) * ipv4State {
t . Helper ( )
2020-06-11 20:46:56 +00:00
state , ok := conn . layerStates [ 1 ] . ( * ipv4State )
if ! ok {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "got network-layer state type=%T, expected ipv4State" , conn . layerStates [ 1 ] )
2020-06-11 20:46:56 +00:00
}
return state
2020-04-01 02:51:52 +00:00
}
2020-06-11 20:46:56 +00:00
// LocalAddr gets the local socket address of this connection.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv4 ) LocalAddr ( t * testing . T ) * unix . SockaddrInet4 {
t . Helper ( )
sa := & unix . SockaddrInet4 { Port : int ( * conn . udpState ( t ) . out . SrcPort ) }
copy ( sa . Addr [ : ] , * conn . ipv4State ( t ) . out . SrcAddr )
2020-06-11 20:46:56 +00:00
return sa
2020-04-29 01:49:19 +00:00
}
2020-06-11 20:46:56 +00:00
// Send sends a packet with reasonable defaults, potentially overriding the UDP
// layer and adding additionLayers.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv4 ) Send ( t * testing . T , udp UDP , additionalLayers ... Layer ) {
t . Helper ( )
( * Connection ) ( conn ) . send ( t , Layers { & udp } , additionalLayers ... )
2020-04-01 02:51:52 +00:00
}
2020-06-11 20:46:56 +00:00
// SendIP sends a packet with reasonable defaults, potentially overriding the
// UDP and IPv4 headers and adding additionLayers.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv4 ) SendIP ( t * testing . T , ip IPv4 , udp UDP , additionalLayers ... Layer ) {
t . Helper ( )
( * Connection ) ( conn ) . send ( t , Layers { & ip , & udp } , additionalLayers ... )
2020-04-29 01:49:19 +00:00
}
// Expect expects a frame with the UDP layer matching the provided UDP within
// the timeout specified. If it doesn't arrive in time, an error is returned.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv4 ) Expect ( t * testing . T , udp UDP , timeout time . Duration ) ( * UDP , error ) {
t . Helper ( )
layer , err := ( * Connection ) ( conn ) . Expect ( t , & udp , timeout )
2020-07-14 18:48:26 +00:00
if err != nil {
2020-04-29 01:49:19 +00:00
return nil , err
}
gotUDP , ok := layer . ( * UDP )
if ! ok {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "expected %s to be UDP" , layer )
2020-04-29 01:49:19 +00:00
}
2020-07-14 18:48:26 +00:00
return gotUDP , nil
2020-04-29 01:49:19 +00:00
}
2020-05-08 22:38:42 +00:00
// ExpectData is a convenient method that expects a Layer and the Layer after
// it. If it doens't arrive in time, it returns nil.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv4 ) ExpectData ( t * testing . T , udp UDP , payload Payload , timeout time . Duration ) ( Layers , error ) {
t . Helper ( )
2020-05-08 22:38:42 +00:00
expected := make ( [ ] Layer , len ( conn . layerStates ) )
expected [ len ( expected ) - 1 ] = & udp
if payload . length ( ) != 0 {
expected = append ( expected , & payload )
}
2020-07-27 13:37:11 +00:00
return ( * Connection ) ( conn ) . ExpectFrame ( t , expected , timeout )
2020-05-08 22:38:42 +00:00
}
2020-04-15 19:59:58 +00:00
// Close frees associated resources held by the UDPIPv4 connection.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv4 ) Close ( t * testing . T ) {
t . Helper ( )
( * Connection ) ( conn ) . Close ( t )
2020-04-01 02:51:52 +00:00
}
2020-04-14 06:04:01 +00:00
// Drain drains the sniffer's receive buffer by receiving packets until there's
// nothing else to receive.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv4 ) Drain ( t * testing . T ) {
t . Helper ( )
conn . sniffer . Drain ( t )
2020-04-14 06:04:01 +00:00
}
2020-07-14 18:48:26 +00:00
// UDPIPv6 maintains the state for all the layers in a UDP/IPv6 connection.
type UDPIPv6 Connection
// NewUDPIPv6 creates a new UDPIPv6 connection with reasonable defaults.
func NewUDPIPv6 ( t * testing . T , outgoingUDP , incomingUDP UDP ) UDPIPv6 {
2020-07-27 13:37:11 +00:00
t . Helper ( )
2020-07-14 18:48:26 +00:00
etherState , err := newEtherState ( Ether { } , Ether { } )
if err != nil {
t . Fatalf ( "can't make etherState: %s" , err )
}
ipv6State , err := newIPv6State ( IPv6 { } , IPv6 { } )
if err != nil {
t . Fatalf ( "can't make IPv6State: %s" , err )
}
udpState , err := newUDPState ( unix . AF_INET6 , outgoingUDP , incomingUDP )
if err != nil {
t . Fatalf ( "can't make udpState: %s" , err )
}
injector , err := NewInjector ( t )
if err != nil {
t . Fatalf ( "can't make injector: %s" , err )
}
sniffer , err := NewSniffer ( t )
if err != nil {
t . Fatalf ( "can't make sniffer: %s" , err )
}
return UDPIPv6 {
layerStates : [ ] layerState { etherState , ipv6State , udpState } ,
injector : injector ,
sniffer : sniffer ,
}
}
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv6 ) udpState ( t * testing . T ) * udpState {
t . Helper ( )
2020-07-14 18:48:26 +00:00
state , ok := conn . layerStates [ 2 ] . ( * udpState )
if ! ok {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "got transport-layer state type=%T, expected udpState" , conn . layerStates [ 2 ] )
2020-07-14 18:48:26 +00:00
}
return state
}
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv6 ) ipv6State ( t * testing . T ) * ipv6State {
t . Helper ( )
2020-07-14 18:48:26 +00:00
state , ok := conn . layerStates [ 1 ] . ( * ipv6State )
if ! ok {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "got network-layer state type=%T, expected ipv6State" , conn . layerStates [ 1 ] )
2020-07-14 18:48:26 +00:00
}
return state
}
// LocalAddr gets the local socket address of this connection.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv6 ) LocalAddr ( t * testing . T ) * unix . SockaddrInet6 {
t . Helper ( )
2020-07-14 18:48:26 +00:00
sa := & unix . SockaddrInet6 {
2020-07-27 13:37:11 +00:00
Port : int ( * conn . udpState ( t ) . out . SrcPort ) ,
2020-07-14 18:48:26 +00:00
// Local address is in perspective to the remote host, so it's scoped to the
// ID of the remote interface.
ZoneId : uint32 ( RemoteInterfaceID ) ,
}
2020-07-27 13:37:11 +00:00
copy ( sa . Addr [ : ] , * conn . ipv6State ( t ) . out . SrcAddr )
2020-07-14 18:48:26 +00:00
return sa
}
// Send sends a packet with reasonable defaults, potentially overriding the UDP
// layer and adding additionLayers.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv6 ) Send ( t * testing . T , udp UDP , additionalLayers ... Layer ) {
t . Helper ( )
( * Connection ) ( conn ) . send ( t , Layers { & udp } , additionalLayers ... )
2020-07-14 18:48:26 +00:00
}
// SendIPv6 sends a packet with reasonable defaults, potentially overriding the
// UDP and IPv6 headers and adding additionLayers.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv6 ) SendIPv6 ( t * testing . T , ip IPv6 , udp UDP , additionalLayers ... Layer ) {
t . Helper ( )
( * Connection ) ( conn ) . send ( t , Layers { & ip , & udp } , additionalLayers ... )
2020-07-14 18:48:26 +00:00
}
// Expect expects a frame with the UDP layer matching the provided UDP within
// the timeout specified. If it doesn't arrive in time, an error is returned.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv6 ) Expect ( t * testing . T , udp UDP , timeout time . Duration ) ( * UDP , error ) {
t . Helper ( )
layer , err := ( * Connection ) ( conn ) . Expect ( t , & udp , timeout )
2020-07-14 18:48:26 +00:00
if err != nil {
return nil , err
}
gotUDP , ok := layer . ( * UDP )
if ! ok {
2020-07-27 13:37:11 +00:00
t . Fatalf ( "expected %s to be UDP" , layer )
2020-07-14 18:48:26 +00:00
}
return gotUDP , nil
}
// ExpectData is a convenient method that expects a Layer and the Layer after
// it. If it doens't arrive in time, it returns nil.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv6 ) ExpectData ( t * testing . T , udp UDP , payload Payload , timeout time . Duration ) ( Layers , error ) {
t . Helper ( )
2020-07-14 18:48:26 +00:00
expected := make ( [ ] Layer , len ( conn . layerStates ) )
expected [ len ( expected ) - 1 ] = & udp
if payload . length ( ) != 0 {
expected = append ( expected , & payload )
}
2020-07-27 13:37:11 +00:00
return ( * Connection ) ( conn ) . ExpectFrame ( t , expected , timeout )
2020-07-14 18:48:26 +00:00
}
// Close frees associated resources held by the UDPIPv6 connection.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv6 ) Close ( t * testing . T ) {
t . Helper ( )
( * Connection ) ( conn ) . Close ( t )
2020-07-14 18:48:26 +00:00
}
// Drain drains the sniffer's receive buffer by receiving packets until there's
// nothing else to receive.
2020-07-27 13:37:11 +00:00
func ( conn * UDPIPv6 ) Drain ( t * testing . T ) {
t . Helper ( )
conn . sniffer . Drain ( t )
2020-07-14 18:48:26 +00:00
}
2020-07-10 05:37:11 +00:00
// TCPIPv6 maintains the state for all the layers in a TCP/IPv6 connection.
type TCPIPv6 Connection
// NewTCPIPv6 creates a new TCPIPv6 connection with reasonable defaults.
func NewTCPIPv6 ( t * testing . T , outgoingTCP , incomingTCP TCP ) TCPIPv6 {
etherState , err := newEtherState ( Ether { } , Ether { } )
if err != nil {
t . Fatalf ( "can't make etherState: %s" , err )
}
ipv6State , err := newIPv6State ( IPv6 { } , IPv6 { } )
if err != nil {
t . Fatalf ( "can't make ipv6State: %s" , err )
}
tcpState , err := newTCPState ( unix . AF_INET6 , outgoingTCP , incomingTCP )
if err != nil {
t . Fatalf ( "can't make tcpState: %s" , err )
}
injector , err := NewInjector ( t )
if err != nil {
t . Fatalf ( "can't make injector: %s" , err )
}
sniffer , err := NewSniffer ( t )
if err != nil {
t . Fatalf ( "can't make sniffer: %s" , err )
}
return TCPIPv6 {
layerStates : [ ] layerState { etherState , ipv6State , tcpState } ,
injector : injector ,
sniffer : sniffer ,
}
}
func ( conn * TCPIPv6 ) SrcPort ( ) uint16 {
state := conn . layerStates [ 2 ] . ( * tcpState )
return * state . out . SrcPort
}
// ExpectData is a convenient method that expects a Layer and the Layer after
// it. If it doens't arrive in time, it returns nil.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv6 ) ExpectData ( t * testing . T , tcp * TCP , payload * Payload , timeout time . Duration ) ( Layers , error ) {
t . Helper ( )
2020-07-10 05:37:11 +00:00
expected := make ( [ ] Layer , len ( conn . layerStates ) )
expected [ len ( expected ) - 1 ] = tcp
if payload != nil {
expected = append ( expected , payload )
}
2020-07-27 13:37:11 +00:00
return ( * Connection ) ( conn ) . ExpectFrame ( t , expected , timeout )
2020-07-10 05:37:11 +00:00
}
// Close frees associated resources held by the TCPIPv6 connection.
2020-07-27 13:37:11 +00:00
func ( conn * TCPIPv6 ) Close ( t * testing . T ) {
t . Helper ( )
( * Connection ) ( conn ) . Close ( t )
2020-07-10 05:37:11 +00:00
}