Repository: pires/go-proxyproto
Pull request #46 (2020-10-17 17:52:11)

Change addresses to net.Addr
The motivation is to allow Header to hold Unix socket addresses.

Instead of using an IP and a port, use net.Addr, which allows to
represent any network address.

The Header.{Local,Remote}Addr methods are removed since users can now
just access Header.{Source,Destination}Addr.

New helpers (TCPAddrs, UDPAddrs, UnixAddrs, IPs, Ports) allows users to
easily extract data from the generic net.Addr fields.

Closes: https://github.com/pires/go-proxyproto/issues/34
Closes: https://github.com/pires/go-proxyproto/issues/43

* * *

Tests haven't been updated yet, but I'd like to gather some feedback because this is a quite radical change. What do you think?

coveralls: 
[![Coverage Status](https://coveralls.io/builds/34452625/badge)](https://coveralls.io/builds/34452625)

Coverage decreased (-0.08%) to 92.047% when pulling **d640724d570098d713174ffa2c9eed8cadd68066 on emersion:header-addr** into **528b59d6162fc5463728b0e48a5ff5e73151eb38 on pires:master**.

emersion: All done! This is ready for another review.

Patch:
diff --git a/README.md b/README.md
index 05c3178..1aedea5 100644
--- a/README.md
+++ b/README.md
@@ -60,10 +60,14 @@ func main() {
 		Version:            1,
 		Command:            proxyproto.PROXY,
 		TransportProtocol:  proxyproto.TCPv4,
-		SourceAddress:      net.ParseIP("10.1.1.1"),
-		SourcePort:         1000,
-		DestinationAddress: net.ParseIP("20.2.2.2"),
-		DestinationPort:    2000,
+		SourceAddr: &net.TCPAddr{
+			IP:   net.ParseIP("10.1.1.1"),
+			Port: 1000,
+		},
+		DestinationAddr: &net.TCPAddr{
+			IP:   net.ParseIP("20.2.2.2"),
+			Port: 2000,
+		},
 	}
 	// After the connection was created write the proxy headers first
 	_, err = header.WriteTo(conn)
diff --git a/header.go b/header.go
index 23351e8..f22bbc2 100644
--- a/header.go
+++ b/header.go
@@ -33,14 +33,12 @@ var (
 
 // Header is the placeholder for proxy protocol header.
 type Header struct {
-	Version            byte
-	Command            ProtocolVersionAndCommand
-	TransportProtocol  AddressFamilyAndProtocol
-	SourceAddress      net.IP
-	DestinationAddress net.IP
-	SourcePort         uint16
-	DestinationPort    uint16
-	rawTLVs            []byte
+	Version           byte
+	Command           ProtocolVersionAndCommand
+	TransportProtocol AddressFamilyAndProtocol
+	SourceAddr        net.Addr
+	DestinationAddr   net.Addr
+	rawTLVs           []byte
 }
 
 // HeaderProxyFromAddrs creates a new PROXY header from a source and a
@@ -60,40 +58,25 @@ func HeaderProxyFromAddrs(version byte, sourceAddr, destAddr net.Addr) *Header {
 	}
 	switch sourceAddr := sourceAddr.(type) {
 	case *net.TCPAddr:
-		destAddr, ok := destAddr.(*net.TCPAddr)
-		if !ok {
+		if _, ok := destAddr.(*net.TCPAddr); !ok {
 			break
 		}
 		if len(sourceAddr.IP.To4()) == net.IPv4len {
 			h.TransportProtocol = TCPv4
 		} else if len(sourceAddr.IP) == net.IPv6len {
 			h.TransportProtocol = TCPv6
-		} else {
-			break
 		}
-		h.SourceAddress = sourceAddr.IP
-		h.DestinationAddress = destAddr.IP
-		h.SourcePort = uint16(sourceAddr.Port)
-		h.DestinationPort = uint16(destAddr.Port)
 	case *net.UDPAddr:
-		destAddr, ok := destAddr.(*net.UDPAddr)
-		if !ok {
+		if _, ok := destAddr.(*net.UDPAddr); !ok {
 			break
 		}
 		if len(sourceAddr.IP.To4()) == net.IPv4len {
 			h.TransportProtocol = UDPv4
 		} else if len(sourceAddr.IP) == net.IPv6len {
 			h.TransportProtocol = UDPv6
-		} else {
-			break
 		}
-		h.SourceAddress = sourceAddr.IP
-		h.DestinationAddress = destAddr.IP
-		h.SourcePort = uint16(sourceAddr.Port)
-		h.DestinationPort = uint16(destAddr.Port)
 	case *net.UnixAddr:
-		_, ok := destAddr.(*net.UnixAddr)
-		if !ok {
+		if _, ok := destAddr.(*net.UnixAddr); !ok {
 			break
 		}
 		switch sourceAddr.Net {
@@ -103,22 +86,57 @@ func HeaderProxyFromAddrs(version byte, sourceAddr, destAddr net.Addr) *Header {
 			h.TransportProtocol = UnixDatagram
 		}
 	}
+	if h.TransportProtocol != UNSPEC {
+		h.SourceAddr = sourceAddr
+		h.DestinationAddr = destAddr
+	}
 	return h
 }
 
-// RemoteAddr returns the address of the remote endpoint of the connection.
-func (header *Header) RemoteAddr() net.Addr {
-	return &net.TCPAddr{
-		IP:   header.SourceAddress,
-		Port: int(header.SourcePort),
+func (header *Header) TCPAddrs() (sourceAddr, destAddr *net.TCPAddr, ok bool) {
+	if !header.TransportProtocol.IsStream() {
+		return nil, nil, false
+	}
+	sourceAddr, sourceOK := header.SourceAddr.(*net.TCPAddr)
+	destAddr, destOK := header.DestinationAddr.(*net.TCPAddr)
+	return sourceAddr, destAddr, sourceOK && destOK
+}
+
+func (header *Header) UDPAddrs() (sourceAddr, destAddr *net.UDPAddr, ok bool) {
+	if !header.TransportProtocol.IsDatagram() {
+		return nil, nil, false
+	}
+	sourceAddr, sourceOK := header.SourceAddr.(*net.UDPAddr)
+	destAddr, destOK := header.DestinationAddr.(*net.UDPAddr)
+	return sourceAddr, destAddr, sourceOK && destOK
+}
+
+func (header *Header) UnixAddrs() (sourceAddr, destAddr *net.UnixAddr, ok bool) {
+	if !header.TransportProtocol.IsUnix() {
+		return nil, nil, false
+	}
+	sourceAddr, sourceOK := header.SourceAddr.(*net.UnixAddr)
+	destAddr, destOK := header.DestinationAddr.(*net.UnixAddr)
+	return sourceAddr, destAddr, sourceOK && destOK
+}
+
+func (header *Header) IPs() (sourceIP, destIP net.IP, ok bool) {
+	if sourceAddr, destAddr, ok := header.TCPAddrs(); ok {
+		return sourceAddr.IP, destAddr.IP, true
+	} else if sourceAddr, destAddr, ok := header.UDPAddrs(); ok {
+		return sourceAddr.IP, destAddr.IP, true
+	} else {
+		return nil, nil, false
 	}
 }
 
-// LocalAddr returns the address of the local endpoint of the connection.
-func (header *Header) LocalAddr() net.Addr {
-	return &net.TCPAddr{
-		IP:   header.DestinationAddress,
-		Port: int(header.DestinationPort),
+func (header *Header) Ports() (sourcePort, destPort int, ok bool) {
+	if sourceAddr, destAddr, ok := header.TCPAddrs(); ok {
+		return sourceAddr.Port, destAddr.Port, true
+	} else if sourceAddr, destAddr, ok := header.UDPAddrs(); ok {
+		return sourceAddr.Port, destAddr.Port, true
+	} else {
+		return 0, 0, false
 	}
 }
 
@@ -140,12 +158,14 @@ func (header *Header) EqualsTo(otherHeader *Header) bool {
 	if header.Version == 0x02 && !bytes.Equal(header.rawTLVs, otherHeader.rawTLVs) {
 		return false
 	}
-	return header.Version == otherHeader.Version &&
-		header.TransportProtocol == otherHeader.TransportProtocol &&
-		header.SourceAddress.String() == otherHeader.SourceAddress.String() &&
-		header.DestinationAddress.String() == otherHeader.DestinationAddress.String() &&
-		header.SourcePort == otherHeader.SourcePort &&
-		header.DestinationPort == otherHeader.DestinationPort
+	if header.Version != otherHeader.Version || header.TransportProtocol != otherHeader.TransportProtocol {
+		return false
+	}
+	if header.TransportProtocol == UNSPEC {
+		return true
+	}
+	return header.SourceAddr.String() == otherHeader.SourceAddr.String() &&
+		header.DestinationAddr.String() == otherHeader.DestinationAddr.String()
 }
 
 // WriteTo renders a proxy protocol header in a format and writes it to an io.Writer.
diff --git a/protocol.go b/protocol.go
index 4f44323..a686e8e 100644
--- a/protocol.go
+++ b/protocol.go
@@ -129,7 +129,7 @@ func (p *Conn) LocalAddr() net.Addr {
 		return p.conn.LocalAddr()
 	}
 
-	return p.header.LocalAddr()
+	return p.header.DestinationAddr
 }
 
 // RemoteAddr returns the address of the client if the proxy
@@ -144,7 +144,7 @@ func (p *Conn) RemoteAddr() net.Addr {
 		return p.conn.RemoteAddr()
 	}
 
-	return p.header.RemoteAddr()
+	return p.header.SourceAddr
 }
 
 // SetDeadline wraps original conn.SetDeadline
diff --git a/tlv.go b/tlv.go
index 3bba207..6873aa0 100644
--- a/tlv.go
+++ b/tlv.go
@@ -44,8 +44,9 @@ type PP2Type byte
 
 // TLV is a uninterpreted Type-Length-Value for V2 protocol, see section 2.2
 type TLV struct {
-	Type  PP2Type
-	Value []byte
+	Type   PP2Type
+	Length int
+	Value  []byte
 }
 
 // SplitTLVs splits the Type-Length-Value vector, returns the vector or an error.
@@ -58,17 +59,17 @@ func SplitTLVs(raw []byte) ([]TLV, error) {
 		if len(raw)-i <= 3 {
 			return nil, ErrTruncatedTLV
 		}
-		tlvLen := int(binary.BigEndian.Uint16(raw[i+1 : i+3])) // Max length = 65K
+		tlv.Length = int(binary.BigEndian.Uint16(raw[i+1 : i+3])) // Max length = 65K
 		i += 3
-		if i+tlvLen > len(raw) {
+		if i+tlv.Length > len(raw) {
 			return nil, ErrTruncatedTLV
 		}
 		// Ignore no-op padding
 		if tlv.Type != PP2_TYPE_NOOP {
-			tlv.Value = make([]byte, tlvLen)
-			copy(tlv.Value, raw[i:i+tlvLen])
+			tlv.Value = make([]byte, tlv.Length)
+			copy(tlv.Value, raw[i:i+tlv.Length])
 		}
-		i += tlvLen
+		i += tlv.Length
 		tlvs = append(tlvs, tlv)
 	}
 	return tlvs, nil
@@ -78,11 +79,14 @@ func SplitTLVs(raw []byte) ([]TLV, error) {
 func JoinTLVs(tlvs []TLV) ([]byte, error) {
 	var raw []byte
 	for _, tlv := range tlvs {
-		if len(tlv.Value) > math.MaxUint16 {
-			return nil, fmt.Errorf("proxyproto: cannot format TLV %v with length %d", tlv.Type, len(tlv.Value))
+		if tlv.Length > math.MaxUint16 {
+			return nil, fmt.Errorf("proxyproto: cannot format TLV %v with length %d", tlv.Type, tlv.Length)
+		}
+		if tlv.Length != len(tlv.Value) {
+			return nil, fmt.Errorf("proxyproto: TLV %v length doesn't match value length", tlv.Type)
 		}
 		var length [2]byte
-		binary.BigEndian.PutUint16(length[:], uint16(len(tlv.Value)))
+		binary.BigEndian.PutUint16(length[:], uint16(tlv.Length))
 		raw = append(raw, byte(tlv.Type))
 		raw = append(raw, length[:]...)
 		raw = append(raw, tlv.Value...)
diff --git a/tlvparse/aws.go b/tlvparse/aws.go
index 97d3d93..0b43150 100644
--- a/tlvparse/aws.go
+++ b/tlvparse/aws.go
@@ -18,7 +18,7 @@ const (
 var vpceRe = regexp.MustCompile("^[A-Za-z0-9-]*$")
 
 func IsAWSVPCEndpointID(tlv proxyproto.TLV) bool {
-	return tlv.Type == PP2_TYPE_AWS && len(tlv.Value) > 0 && tlv.Value[0] == PP2_SUBTYPE_AWS_VPCE_ID
+	return tlv.Type == PP2_TYPE_AWS && tlv.Length >= 1 && tlv.Value[0] == PP2_SUBTYPE_AWS_VPCE_ID
 }
 
 func AWSVPCEndpointID(tlv proxyproto.TLV) (string, error) {
diff --git a/tlvparse/azure.go b/tlvparse/azure.go
index 1803e42..d1a151c 100644
--- a/tlvparse/azure.go
+++ b/tlvparse/azure.go
@@ -17,7 +17,7 @@ const (
 
 // IsAzurePrivateEndpointLinkID returns true if given TLV matches Azure Private Endpoint LinkID format
 func isAzurePrivateEndpointLinkID(tlv proxyproto.TLV) bool {
-	return tlv.Type == PP2_TYPE_AZURE && len(tlv.Value) == 5 && tlv.Value[0] == PP2_SUBTYPE_AZURE_PRIVATEENDPOINT_LINKID
+	return tlv.Type == PP2_TYPE_AZURE && tlv.Length == 5 && tlv.Value[0] == PP2_SUBTYPE_AZURE_PRIVATEENDPOINT_LINKID
 }
 
 // AzurePrivateEndpointLinkID returns linkID if given TLV matches Azure Private Endpoint LinkID format
diff --git a/tlvparse/ssl.go b/tlvparse/ssl.go
index f09cbfd..ba08af9 100644
--- a/tlvparse/ssl.go
+++ b/tlvparse/ssl.go
@@ -78,8 +78,9 @@ func (s PP2SSL) Marshal() (proxyproto.TLV, error) {
 	v = append(v, tlvs...)
 
 	return proxyproto.TLV{
-		Type:  proxyproto.PP2_TYPE_SSL,
-		Value: v,
+		Type:   proxyproto.PP2_TYPE_SSL,
+		Length: len(v),
+		Value:  v,
 	}, nil
 }
 
@@ -96,7 +97,7 @@ func (s PP2SSL) ClientCN() (string, bool) {
 
 // SSLType is true if the TLV is type SSL
 func IsSSL(t proxyproto.TLV) bool {
-	return t.Type == proxyproto.PP2_TYPE_SSL && len(t.Value) >= tlvSSLMinLen
+	return t.Type == proxyproto.PP2_TYPE_SSL && t.Length >= tlvSSLMinLen
 }
 
 // SSL returns the pp2_tlv_ssl from section 2.2.5 or errors with ErrIncompatibleTLV or ErrMalformedTLV
@@ -105,7 +106,7 @@ func SSL(t proxyproto.TLV) (PP2SSL, error) {
 	if !IsSSL(t) {
 		return ssl, proxyproto.ErrIncompatibleTLV
 	}
-	if len(t.Value) < tlvSSLMinLen {
+	if t.Length < tlvSSLMinLen {
 		return ssl, proxyproto.ErrMalformedTLV
 	}
 	ssl.Client = t.Value[0]
@@ -126,7 +127,7 @@ func SSL(t proxyproto.TLV) (PP2SSL, error) {
 				appended at the end of the field in the TLV format using the type
 				PP2_SUBTYPE_SSL_VERSION.
 			*/
-			if len(tlv.Value) == 0 || !isASCII(tlv.Value) {
+			if tlv.Length == 0 || !isASCII(tlv.Value) {
 				return PP2SSL{}, proxyproto.ErrMalformedTLV
 			}
 			versionFound = true
@@ -136,7 +137,7 @@ func SSL(t proxyproto.TLV) (PP2SSL, error) {
 				(OID: 2.5.4.3) of the client certificate's Distinguished Name, is appended
 				using the TLV format and the type PP2_SUBTYPE_SSL_CN. E.g. "example.com".
 			*/
-			if len(tlv.Value) == 0 || !utf8.Valid(tlv.Value) {
+			if tlv.Length == 0 || !utf8.Valid(tlv.Value) {
 				return PP2SSL{}, proxyproto.ErrMalformedTLV
 			}
 			cnFound = true
diff --git a/v1.go b/v1.go
index a8ba25b..49d23c6 100644
--- a/v1.go
+++ b/v1.go
@@ -45,22 +45,31 @@ func parseVersion1(reader *bufio.Reader) (*Header, error) {
 	}
 
 	// Read addresses and ports
-	header.SourceAddress, err = parseV1IPAddress(header.TransportProtocol, tokens[2])
+	sourceIP, err := parseV1IPAddress(header.TransportProtocol, tokens[2])
 	if err != nil {
 		return nil, err
 	}
-	header.DestinationAddress, err = parseV1IPAddress(header.TransportProtocol, tokens[3])
+	destIP, err := parseV1IPAddress(header.TransportProtocol, tokens[3])
 	if err != nil {
 		return nil, err
 	}
-	header.SourcePort, err = parseV1PortNumber(tokens[4])
+	sourcePort, err := parseV1PortNumber(tokens[4])
 	if err != nil {
 		return nil, err
 	}
-	header.DestinationPort, err = parseV1PortNumber(tokens[5])
+	destPort, err := parseV1PortNumber(tokens[5])
 	if err != nil {
 		return nil, err
 	}
+	header.SourceAddr = &net.TCPAddr{
+		IP:   sourceIP,
+		Port: sourcePort,
+	}
+	header.DestinationAddr = &net.TCPAddr{
+		IP:   destIP,
+		Port: destPort,
+	}
+
 	return header, nil
 }
 
@@ -77,36 +86,32 @@ func (header *Header) formatVersion1() ([]byte, error) {
 		return []byte("PROXY UNKNOWN\r\n"), nil
 	}
 
+	sourceAddr := header.SourceAddr.(*net.TCPAddr)
+	destAddr := header.DestinationAddr.(*net.TCPAddr)
+
 	buf := bytes.NewBuffer(make([]byte, 0, 108))
 	buf.Write(SIGV1)
 	buf.WriteString(separator)
 	buf.WriteString(proto)
 	buf.WriteString(separator)
-	buf.WriteString(header.SourceAddress.String())
+	buf.WriteString(sourceAddr.IP.String())
 	buf.WriteString(separator)
-	buf.WriteString(header.DestinationAddress.String())
+	buf.WriteString(destAddr.IP.String())
 	buf.WriteString(separator)
-	buf.WriteString(strconv.Itoa(int(header.SourcePort)))
+	buf.WriteString(strconv.Itoa(sourceAddr.Port))
 	buf.WriteString(separator)
-	buf.WriteString(strconv.Itoa(int(header.DestinationPort)))
+	buf.WriteString(strconv.Itoa(destAddr.Port))
 	buf.WriteString(crlf)
 
 	return buf.Bytes(), nil
 }
 
-func parseV1PortNumber(portStr string) (port uint16, err error) {
-	_port, _err := strconv.Atoi(portStr)
-	if _err == nil {
-		if _port < 0 || _port > 65535 {
-			err = ErrInvalidPortNumber
-		} else {
-			port = uint16(_port)
-		}
-	} else {
-		err = ErrInvalidPortNumber
+func parseV1PortNumber(portStr string) (int, error) {
+	port, err := strconv.Atoi(portStr)
+	if err != nil || port < 0 || port > 65535 {
+		return 0, ErrInvalidPortNumber
 	}
-
-	return
+	return port, nil
 }
 
 func parseV1IPAddress(protocol AddressFamilyAndProtocol, addrStr string) (addr net.IP, err error) {
diff --git a/v2.go b/v2.go
index 1450b5d..7c281e3 100644
--- a/v2.go
+++ b/v2.go
@@ -6,12 +6,13 @@ import (
 	"encoding/binary"
 	"errors"
 	"io"
+	"net"
 )
 
 var (
 	lengthV4   = uint16(12)
 	lengthV6   = uint16(36)
-	lengthUnix = uint16(218)
+	lengthUnix = uint16(216)
 
 	lengthV4Bytes = func() []byte {
 		a := make([]byte, 2)
@@ -107,34 +108,35 @@ func parseVersion2(reader *bufio.Reader) (header *Header, err error) {
 		if err := binary.Read(payloadReader, binary.BigEndian, &addr); err != nil {
 			return nil, ErrInvalidAddress
 		}
-		header.SourceAddress = addr.Src[:]
-		header.DestinationAddress = addr.Dst[:]
-		header.SourcePort = addr.SrcPort
-		header.DestinationPort = addr.DstPort
+		header.SourceAddr = newIPAddr(header.TransportProtocol, addr.Src[:], addr.SrcPort)
+		header.DestinationAddr = newIPAddr(header.TransportProtocol, addr.Dst[:], addr.DstPort)
 	} else if header.TransportProtocol.IsIPv6() {
 		var addr _addr6
 		if err := binary.Read(payloadReader, binary.BigEndian, &addr); err != nil {
 			return nil, ErrInvalidAddress
 		}
-		header.SourceAddress = addr.Src[:]
-		header.DestinationAddress = addr.Dst[:]
-		header.SourcePort = addr.SrcPort
-		header.DestinationPort = addr.DstPort
-	}
-	// TODO fully support Unix addresses
-	//	else if header.TransportProtocol.IsUnix() {
-	//		var addr _addrUnix
-	//		if err := binary.Read(payloadReader, binary.BigEndian, &addr); err != nil {
-	//			return nil, ErrInvalidAddress
-	//		}
-	//
-	//if header.SourceAddress, err = net.ResolveUnixAddr("unix", string(addr.Src[:])); err != nil {
-	//	return nil, ErrCantResolveSourceUnixAddress
-	//}
-	//if header.DestinationAddress, err = net.ResolveUnixAddr("unix", string(addr.Dst[:])); err != nil {
-	//	return nil, ErrCantResolveDestinationUnixAddress
-	//}
-	//}
+		header.SourceAddr = newIPAddr(header.TransportProtocol, addr.Src[:], addr.SrcPort)
+		header.DestinationAddr = newIPAddr(header.TransportProtocol, addr.Dst[:], addr.DstPort)
+	} else if header.TransportProtocol.IsUnix() {
+		var addr _addrUnix
+		if err := binary.Read(payloadReader, binary.BigEndian, &addr); err != nil {
+			return nil, ErrInvalidAddress
+		}
+
+		network := "unix"
+		if header.TransportProtocol.IsDatagram() {
+			network = "unixgram"
+		}
+
+		header.SourceAddr = &net.UnixAddr{
+			Net:  network,
+			Name: parseUnixName(addr.Src[:]),
+		}
+		header.DestinationAddr = &net.UnixAddr{
+			Net:  network,
+			Name: parseUnixName(addr.Dst[:]),
+		}
+	}
 
 	// Copy bytes for optional Type-Length-Value vector
 	header.rawTLVs = make([]byte, payloadReader.N) // Allocate minimum size slice
@@ -157,38 +159,43 @@ func (header *Header) formatVersion2() ([]byte, error) {
 			return nil, err
 		}
 		buf.Write(hdrLen)
-		addrSrc = header.SourceAddress.To4()
-		addrDst = header.DestinationAddress.To4()
+		sourceIP, destIP, _ := header.IPs()
+		addrSrc = sourceIP.To4()
+		addrDst = destIP.To4()
 	} else if header.TransportProtocol.IsIPv6() {
 		hdrLen, err := addTLVLen(lengthV6Bytes, len(header.rawTLVs))
 		if err != nil {
 			return nil, err
 		}
 		buf.Write(hdrLen)
-		addrSrc = header.SourceAddress.To16()
-		addrDst = header.DestinationAddress.To16()
+		sourceIP, destIP, _ := header.IPs()
+		addrSrc = sourceIP.To16()
+		addrDst = destIP.To16()
 	} else if header.TransportProtocol.IsUnix() {
 		buf.Write(lengthUnixBytes)
-		// TODO is below right?
-		addrSrc = []byte(header.SourceAddress.String())
-		addrDst = []byte(header.DestinationAddress.String())
+		sourceAddr, destAddr, ok := header.UnixAddrs()
+		if !ok {
+			return nil, ErrInvalidAddress
+		}
+		addrSrc = formatUnixName(sourceAddr.Name)
+		addrDst = formatUnixName(destAddr.Name)
+	}
+	if addrSrc == nil || addrDst == nil {
+		return nil, ErrInvalidAddress
 	}
 	buf.Write(addrSrc)
 	buf.Write(addrDst)
 
-	portSrcBytes := func() []byte {
-		a := make([]byte, 2)
-		binary.BigEndian.PutUint16(a, header.SourcePort)
-		return a
-	}()
-	buf.Write(portSrcBytes)
+	if sourcePort, destPort, ok := header.Ports(); ok {
+		portBytes := make([]byte, 2)
+
+		binary.BigEndian.PutUint16(portBytes, uint16(sourcePort))
+		buf.Write(portBytes)
+
+		binary.BigEndian.PutUint16(portBytes, uint16(destPort))
+		buf.Write(portBytes)
+	}
 
-	portDstBytes := func() []byte {
-		a := make([]byte, 2)
-		binary.BigEndian.PutUint16(a, header.DestinationPort)
-		return a
-	}()
-	buf.Write(portDstBytes)
 	if len(header.rawTLVs) > 0 {
 		buf.Write(header.rawTLVs)
 	}
@@ -221,3 +228,30 @@ func addTLVLen(cur []byte, tlvLen int) ([]byte, error) {
 	binary.BigEndian.PutUint16(a, uint16(newLen))
 	return a, nil
 }
+
+func newIPAddr(transport AddressFamilyAndProtocol, ip net.IP, port uint16) net.Addr {
+	if transport.IsStream() {
+		return &net.TCPAddr{IP: ip, Port: int(port)}
+	} else if transport.IsDatagram() {
+		return &net.UDPAddr{IP: ip, Port: int(port)}
+	} else {
+		return nil
+	}
+}
+
+func parseUnixName(b []byte) string {
+	i := bytes.IndexByte(b, 0)
+	if i < 0 {
+		return string(b)
+	}
+	return string(b[:i])
+}
+
+func formatUnixName(name string) []byte {
+	n := int(lengthUnix) / 2
+	if len(name) >= n {
+		return []byte(name[:n])
+	}
+	pad := make([]byte, n-len(name))
+	return append([]byte(name), pad...)
+}


Test patch:
diff --git a/header_test.go b/header_test.go
index b90366f..6090153 100644
--- a/header_test.go
+++ b/header_test.go
@@ -5,6 +5,7 @@ import (
 	"bytes"
 	"errors"
 	"net"
+	"reflect"
 	"testing"
 	"time"
 )
@@ -20,8 +21,17 @@ const (
 )
 
 var (
-	v4addr = net.ParseIP(IP4_ADDR).To4()
-	v6addr = net.ParseIP(IP6_ADDR).To16()
+	v4ip = net.ParseIP(IP4_ADDR).To4()
+	v6ip = net.ParseIP(IP6_ADDR).To16()
+
+	v4addr net.Addr = &net.TCPAddr{IP: v4ip, Port: PORT}
+	v6addr net.Addr = &net.TCPAddr{IP: v6ip, Port: PORT}
+
+	v4UDPAddr net.Addr = &net.UDPAddr{IP: v4ip, Port: PORT}
+	v6UDPAddr net.Addr = &net.UDPAddr{IP: v6ip, Port: PORT}
+
+	unixStreamAddr   net.Addr = &net.UnixAddr{Net: "unix", Name: "socket"}
+	unixDatagramAddr net.Addr = &net.UnixAddr{Net: "unixgram", Name: "socket"}
 
 	errReadIntentionallyBroken = errors.New("read is intentionally broken")
 )
@@ -69,56 +79,76 @@ func TestEqualsTo(t *testing.T) {
 	}{
 		{
 			&Header{
-				Version:            1,
-				Command:            PROXY,
-				TransportProtocol:  TCPv4,
-				SourceAddress:      net.ParseIP("10.1.1.1"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("20.2.2.2"),
-				DestinationPort:    2000,
+				Version:           1,
+				Command:           PROXY,
+				TransportProtocol: TCPv4,
+				SourceAddr: &net.TCPAddr{
+					IP:   net.ParseIP("10.1.1.1"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.TCPAddr{
+					IP:   net.ParseIP("20.2.2.2"),
+					Port: 2000,
+				},
 			},
 			nil,
 			false,
 		},
 		{
 			&Header{
-				Version:            1,
-				Command:            PROXY,
-				TransportProtocol:  TCPv4,
-				SourceAddress:      net.ParseIP("10.1.1.1"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("20.2.2.2"),
-				DestinationPort:    2000,
+				Version:           1,
+				Command:           PROXY,
+				TransportProtocol: TCPv4,
+				SourceAddr: &net.TCPAddr{
+					IP:   net.ParseIP("10.1.1.1"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.TCPAddr{
+					IP:   net.ParseIP("20.2.2.2"),
+					Port: 2000,
+				},
 			},
 			&Header{
-				Version:            2,
-				Command:            PROXY,
-				TransportProtocol:  TCPv4,
-				SourceAddress:      net.ParseIP("10.1.1.1"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("20.2.2.2"),
-				DestinationPort:    2000,
+				Version:           2,
+				Command:           PROXY,
+				TransportProtocol: TCPv4,
+				SourceAddr: &net.TCPAddr{
+					IP:   net.ParseIP("10.1.1.1"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.TCPAddr{
+					IP:   net.ParseIP("20.2.2.2"),
+					Port: 2000,
+				},
 			},
 			false,
 		},
 		{
 			&Header{
-				Version:            1,
-				Command:            PROXY,
-				TransportProtocol:  TCPv4,
-				SourceAddress:      net.ParseIP("10.1.1.1"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("20.2.2.2"),
-				DestinationPort:    2000,
+				Version:           1,
+				Command:           PROXY,
+				TransportProtocol: TCPv4,
+				SourceAddr: &net.TCPAddr{
+					IP:   net.ParseIP("10.1.1.1"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.TCPAddr{
+					IP:   net.ParseIP("20.2.2.2"),
+					Port: 2000,
+				},
 			},
 			&Header{
-				Version:            1,
-				Command:            PROXY,
-				TransportProtocol:  TCPv4,
-				SourceAddress:      net.ParseIP("10.1.1.1"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("20.2.2.2"),
-				DestinationPort:    2000,
+				Version:           1,
+				Command:           PROXY,
+				TransportProtocol: TCPv4,
+				SourceAddr: &net.TCPAddr{
+					IP:   net.ParseIP("10.1.1.1"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.TCPAddr{
+					IP:   net.ParseIP("20.2.2.2"),
+					Port: 2000,
+				},
 			},
 			true,
 		},
@@ -136,51 +166,172 @@ func TestEqualTo(t *testing.T) {
 	TestEqualsTo(t)
 }
 
-func TestLocalAddr(t *testing.T) {
-	var headers = []struct {
-		header       *Header
-		expectedAddr net.Addr
-		expected     bool
+func TestGetters(t *testing.T) {
+	var tests = []struct {
+		name                         string
+		header                       *Header
+		tcpSourceAddr, tcpDestAddr   *net.TCPAddr
+		udpSourceAddr, udpDestAddr   *net.UDPAddr
+		unixSourceAddr, unixDestAddr *net.UnixAddr
+		ipSource, ipDest             net.IP
+		portSource, portDest         int
 	}{
 		{
-			&Header{
-				Version:            1,
-				Command:            PROXY,
-				TransportProtocol:  TCPv4,
-				SourceAddress:      net.ParseIP("10.1.1.1"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("20.2.2.2"),
-				DestinationPort:    2000,
-			},
-			&net.TCPAddr{
+			name: "TCPv4",
+			header: &Header{
+				Version:           1,
+				Command:           PROXY,
+				TransportProtocol: TCPv4,
+				SourceAddr: &net.TCPAddr{
+					IP:   net.ParseIP("10.1.1.1"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.TCPAddr{
+					IP:   net.ParseIP("20.2.2.2"),
+					Port: 2000,
+				},
+			},
+			tcpSourceAddr: &net.TCPAddr{
+				IP:   net.ParseIP("10.1.1.1"),
+				Port: 1000,
+			},
+			tcpDestAddr: &net.TCPAddr{
 				IP:   net.ParseIP("20.2.2.2"),
 				Port: 2000,
 			},
-			true,
+			ipSource:   net.ParseIP("10.1.1.1"),
+			ipDest:     net.ParseIP("20.2.2.2"),
+			portSource: 1000,
+			portDest:   2000,
 		},
 		{
-			&Header{
-				Version:            1,
-				Command:            PROXY,
-				TransportProtocol:  TCPv4,
-				SourceAddress:      net.ParseIP("10.1.1.1"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("20.2.2.2"),
-				DestinationPort:    2000,
-			},
-			&net.TCPAddr{
+			name: "UDPv4",
+			header: &Header{
+				Version:           2,
+				Command:           PROXY,
+				TransportProtocol: UDPv6,
+				SourceAddr: &net.UDPAddr{
+					IP:   net.ParseIP("10.1.1.1"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.UDPAddr{
+					IP:   net.ParseIP("20.2.2.2"),
+					Port: 2000,
+				},
+			},
+			udpSourceAddr: &net.UDPAddr{
 				IP:   net.ParseIP("10.1.1.1"),
 				Port: 1000,
 			},
-			false,
+			udpDestAddr: &net.UDPAddr{
+				IP:   net.ParseIP("20.2.2.2"),
+				Port: 2000,
+			},
+			ipSource:   net.ParseIP("10.1.1.1"),
+			ipDest:     net.ParseIP("20.2.2.2"),
+			portSource: 1000,
+			portDest:   2000,
+		},
+		{
+			name: "UnixStream",
+			header: &Header{
+				Version:           2,
+				Command:           PROXY,
+				TransportProtocol: UnixStream,
+				SourceAddr: &net.UnixAddr{
+					Net:  "unix",
+					Name: "src",
+				},
+				DestinationAddr: &net.UnixAddr{
+					Net:  "unix",
+					Name: "dst",
+				},
+			},
+			unixSourceAddr: &net.UnixAddr{
+				Net:  "unix",
+				Name: "src",
+			},
+			unixDestAddr: &net.UnixAddr{
+				Net:  "unix",
+				Name: "dst",
+			},
+		},
+		{
+			name: "UnixDatagram",
+			header: &Header{
+				Version:           2,
+				Command:           PROXY,
+				TransportProtocol: UnixDatagram,
+				SourceAddr: &net.UnixAddr{
+					Net:  "unix",
+					Name: "src",
+				},
+				DestinationAddr: &net.UnixAddr{
+					Net:  "unix",
+					Name: "dst",
+				},
+			},
+			unixSourceAddr: &net.UnixAddr{
+				Net:  "unix",
+				Name: "src",
+			},
+			unixDestAddr: &net.UnixAddr{
+				Net:  "unix",
+				Name: "dst",
+			},
+		},
+		{
+			name: "Unspec",
+			header: &Header{
+				Version:           1,
+				Command:           PROXY,
+				TransportProtocol: UNSPEC,
+			},
 		},
 	}
 
-	for _, tt := range headers {
-		actualAddr := tt.header.LocalAddr()
-		if actual := actualAddr.String() == tt.expectedAddr.String(); actual != tt.expected {
-			t.Fatalf("expected %t, actual %t for expectedAddr %+v and actualAddr %+v", tt.expected, actual, tt.expectedAddr, actualAddr)
-		}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			tcpSourceAddr, tcpDestAddr, _ := test.header.TCPAddrs()
+			if test.tcpSourceAddr != nil && !reflect.DeepEqual(tcpSourceAddr, test.tcpSourceAddr) {
+				t.Errorf("TCPAddrs() source = %v, want %v", tcpSourceAddr, test.tcpSourceAddr)
+			}
+			if test.tcpDestAddr != nil && !reflect.DeepEqual(tcpDestAddr, test.tcpDestAddr) {
+				t.Errorf("TCPAddrs() dest = %v, want %v", tcpDestAddr, test.tcpDestAddr)
+			}
+
+			udpSourceAddr, udpDestAddr, _ := test.header.UDPAddrs()
+			if test.udpSourceAddr != nil && !reflect.DeepEqual(udpSourceAddr, test.udpSourceAddr) {
+				t.Errorf("TCPAddrs() source = %v, want %v", udpSourceAddr, test.udpSourceAddr)
+			}
+			if test.udpDestAddr != nil && !reflect.DeepEqual(udpDestAddr, test.udpDestAddr) {
+				t.Errorf("TCPAddrs() dest = %v, want %v", udpDestAddr, test.udpDestAddr)
+			}
+
+			unixSourceAddr, unixDestAddr, _ := test.header.UnixAddrs()
+			if test.unixSourceAddr != nil && !reflect.DeepEqual(unixSourceAddr, test.unixSourceAddr) {
+				t.Errorf("UnixAddrs() source = %v, want %v", unixSourceAddr, test.unixSourceAddr)
+			}
+			if test.unixDestAddr != nil && !reflect.DeepEqual(unixDestAddr, test.unixDestAddr) {
+				t.Errorf("UnixAddrs() dest = %v, want %v", unixDestAddr, test.unixDestAddr)
+			}
+
+			ipSource, ipDest, _ := test.header.IPs()
+			if test.ipSource != nil && !ipSource.Equal(test.ipSource) {
+				t.Errorf("IPs() source = %v, want %v", ipSource, test.ipSource)
+			}
+			if test.ipDest != nil && !ipDest.Equal(test.ipDest) {
+				t.Errorf("IPs() dest = %v, want %v", ipDest, test.ipDest)
+			}
+
+			portSource, portDest, _ := test.header.Ports()
+			if test.portSource != 0 && portSource != test.portSource {
+				t.Errorf("Ports() source = %v, want %v", portSource, test.portSource)
+			}
+			if test.portDest != 0 && portDest != test.portDest {
+				t.Errorf("Ports() dest = %v, want %v", portDest, test.portDest)
+			}
+		})
 	}
 }
 
@@ -194,33 +345,43 @@ func TestSetTLVs(t *testing.T) {
 		{
 			name: "add authority TLV",
 			header: &Header{
-				Version:            1,
-				Command:            PROXY,
-				TransportProtocol:  TCPv4,
-				SourceAddress:      net.ParseIP("10.1.1.1"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("20.2.2.2"),
-				DestinationPort:    2000,
+				Version:           1,
+				Command:           PROXY,
+				TransportProtocol: TCPv4,
+				SourceAddr: &net.TCPAddr{
+					IP:   net.ParseIP("10.1.1.1"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.TCPAddr{
+					IP:   net.ParseIP("20.2.2.2"),
+					Port: 2000,
+				},
 			},
 			tlvs: []TLV{{
-				Type:  PP2_TYPE_AUTHORITY,
-				Value: []byte("example.org"),
+				Type:   PP2_TYPE_AUTHORITY,
+				Length: 11,
+				Value:  []byte("example.org"),
 			}},
 		},
 		{
-			name: "add too long TLV",
+			name: "add wrong length",
 			header: &Header{
-				Version:            1,
-				Command:            PROXY,
-				TransportProtocol:  TCPv4,
-				SourceAddress:      net.ParseIP("10.1.1.1"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("20.2.2.2"),
-				DestinationPort:    2000,
+				Version:           1,
+				Command:           PROXY,
+				TransportProtocol: TCPv4,
+				SourceAddr: &net.TCPAddr{
+					IP:   net.ParseIP("10.1.1.1"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.TCPAddr{
+					IP:   net.ParseIP("20.2.2.2"),
+					Port: 2000,
+				},
 			},
 			tlvs: []TLV{{
-				Type:  PP2_TYPE_AUTHORITY,
-				Value: append(bytes.Repeat([]byte("a"), 0xFFFF), []byte(".example.org")...),
+				Type:   PP2_TYPE_AUTHORITY,
+				Length: 1,
+				Value:  []byte("example.org"),
 			}},
 			expectErr: true,
 		},
@@ -233,65 +394,21 @@ func TestSetTLVs(t *testing.T) {
 	}
 }
 
-func TestRemoteAddr(t *testing.T) {
-	var headers = []struct {
-		header       *Header
-		expectedAddr net.Addr
-		expected     bool
-	}{
-		{
-			&Header{
-				Version:            1,
-				Command:            PROXY,
-				TransportProtocol:  TCPv4,
-				SourceAddress:      net.ParseIP("10.1.1.1"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("20.2.2.2"),
-				DestinationPort:    2000,
-			},
-			&net.TCPAddr{
-				IP:   net.ParseIP("20.2.2.2"),
-				Port: 2000,
-			},
-			true,
-		},
-		{
-			&Header{
-				Version:            1,
-				Command:            PROXY,
-				TransportProtocol:  TCPv4,
-				SourceAddress:      net.ParseIP("10.1.1.1"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("20.2.2.2"),
-				DestinationPort:    2000,
-			},
-			&net.TCPAddr{
-				IP:   net.ParseIP("10.1.1.1"),
-				Port: 1000,
-			},
-			false,
-		},
-	}
-
-	for _, tt := range headers {
-		actualAddr := tt.header.LocalAddr()
-		if actual := actualAddr.String() == tt.expectedAddr.String(); actual != tt.expected {
-			t.Fatalf("expected %t, actual %t for expectedAddr %+v and actualAddr %+v", tt.expected, actual, tt.expectedAddr, actualAddr)
-		}
-	}
-}
-
 func TestWriteTo(t *testing.T) {
 	var buf bytes.Buffer
 
 	validHeader := &Header{
-		Version:            1,
-		Command:            PROXY,
-		TransportProtocol:  TCPv4,
-		SourceAddress:      net.ParseIP("10.1.1.1"),
-		SourcePort:         1000,
-		DestinationAddress: net.ParseIP("20.2.2.2"),
-		DestinationPort:    2000,
+		Version:           1,
+		Command:           PROXY,
+		TransportProtocol: TCPv4,
+		SourceAddr: &net.TCPAddr{
+			IP:   net.ParseIP("10.1.1.1"),
+			Port: 1000,
+		},
+		DestinationAddr: &net.TCPAddr{
+			IP:   net.ParseIP("20.2.2.2"),
+			Port: 2000,
+		},
 	}
 
 	if _, err := validHeader.WriteTo(&buf); err != nil {
@@ -299,10 +416,14 @@ func TestWriteTo(t *testing.T) {
 	}
 
 	invalidHeader := &Header{
-		SourceAddress:      net.ParseIP("10.1.1.1"),
-		SourcePort:         1000,
-		DestinationAddress: net.ParseIP("20.2.2.2"),
-		DestinationPort:    2000,
+		SourceAddr: &net.TCPAddr{
+			IP:   net.ParseIP("10.1.1.1"),
+			Port: 1000,
+		},
+		DestinationAddr: &net.TCPAddr{
+			IP:   net.ParseIP("20.2.2.2"),
+			Port: 2000,
+		},
 	}
 
 	if _, err := invalidHeader.WriteTo(&buf); err == nil {
@@ -312,13 +433,17 @@ func TestWriteTo(t *testing.T) {
 
 func TestFormat(t *testing.T) {
 	validHeader := &Header{
-		Version:            1,
-		Command:            PROXY,
-		TransportProtocol:  TCPv4,
-		SourceAddress:      net.ParseIP("10.1.1.1"),
-		SourcePort:         1000,
-		DestinationAddress: net.ParseIP("20.2.2.2"),
-		DestinationPort:    2000,
+		Version:           1,
+		Command:           PROXY,
+		TransportProtocol: TCPv4,
+		SourceAddr: &net.TCPAddr{
+			IP:   net.ParseIP("10.1.1.1"),
+			Port: 1000,
+		},
+		DestinationAddr: &net.TCPAddr{
+			IP:   net.ParseIP("20.2.2.2"),
+			Port: 2000,
+		},
 	}
 
 	if _, err := validHeader.Format(); err != nil {
@@ -326,13 +451,17 @@ func TestFormat(t *testing.T) {
 	}
 
 	invalidHeader := &Header{
-		Version:            3,
-		Command:            PROXY,
-		TransportProtocol:  TCPv4,
-		SourceAddress:      net.ParseIP("10.1.1.1"),
-		SourcePort:         1000,
-		DestinationAddress: net.ParseIP("20.2.2.2"),
-		DestinationPort:    2000,
+		Version:           3,
+		Command:           PROXY,
+		TransportProtocol: TCPv4,
+		SourceAddr: &net.TCPAddr{
+			IP:   net.ParseIP("10.1.1.1"),
+			Port: 1000,
+		},
+		DestinationAddr: &net.TCPAddr{
+			IP:   net.ParseIP("20.2.2.2"),
+			Port: 2000,
+		},
 	}
 
 	if _, err := invalidHeader.Format(); err == nil {
@@ -368,13 +497,17 @@ func TestHeaderProxyFromAddrs(t *testing.T) {
 				Port: 2000,
 			},
 			expected: &Header{
-				Version:            2,
-				Command:            PROXY,
-				TransportProtocol:  TCPv4,
-				SourceAddress:      net.ParseIP("10.1.1.1"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("20.2.2.2"),
-				DestinationPort:    2000,
+				Version:           2,
+				Command:           PROXY,
+				TransportProtocol: TCPv4,
+				SourceAddr: &net.TCPAddr{
+					IP:   net.ParseIP("10.1.1.1"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.TCPAddr{
+					IP:   net.ParseIP("20.2.2.2"),
+					Port: 2000,
+				},
 			},
 		},
 		{
@@ -388,13 +521,17 @@ func TestHeaderProxyFromAddrs(t *testing.T) {
 				Port: 2000,
 			},
 			expected: &Header{
-				Version:            2,
-				Command:            PROXY,
-				TransportProtocol:  TCPv6,
-				SourceAddress:      net.ParseIP("fde7::372"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("fde7::1"),
-				DestinationPort:    2000,
+				Version:           2,
+				Command:           PROXY,
+				TransportProtocol: TCPv6,
+				SourceAddr: &net.TCPAddr{
+					IP:   net.ParseIP("fde7::372"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.TCPAddr{
+					IP:   net.ParseIP("fde7::1"),
+					Port: 2000,
+				},
 			},
 		},
 		{
@@ -408,13 +545,17 @@ func TestHeaderProxyFromAddrs(t *testing.T) {
 				Port: 2000,
 			},
 			expected: &Header{
-				Version:            2,
-				Command:            PROXY,
-				TransportProtocol:  UDPv4,
-				SourceAddress:      net.ParseIP("10.1.1.1"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("20.2.2.2"),
-				DestinationPort:    2000,
+				Version:           2,
+				Command:           PROXY,
+				TransportProtocol: UDPv4,
+				SourceAddr: &net.TCPAddr{
+					IP:   net.ParseIP("10.1.1.1"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.TCPAddr{
+					IP:   net.ParseIP("20.2.2.2"),
+					Port: 2000,
+				},
 			},
 		},
 		{
@@ -428,56 +569,90 @@ func TestHeaderProxyFromAddrs(t *testing.T) {
 				Port: 2000,
 			},
 			expected: &Header{
-				Version:            2,
-				Command:            PROXY,
-				TransportProtocol:  UDPv6,
-				SourceAddress:      net.ParseIP("fde7::372"),
-				SourcePort:         1000,
-				DestinationAddress: net.ParseIP("fde7::1"),
-				DestinationPort:    2000,
+				Version:           2,
+				Command:           PROXY,
+				TransportProtocol: UDPv6,
+				SourceAddr: &net.TCPAddr{
+					IP:   net.ParseIP("fde7::372"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.TCPAddr{
+					IP:   net.ParseIP("fde7::1"),
+					Port: 2000,
+				},
 			},
 		},
 		{
 			name: "UnixStream",
 			sourceAddr: &net.UnixAddr{
-				Net: "unix",
+				Net:  "unix",
+				Name: "src",
 			},
 			destAddr: &net.UnixAddr{
-				Net: "unix",
+				Net:  "unix",
+				Name: "dst",
 			},
 			expected: &Header{
 				Version:           2,
 				Command:           PROXY,
 				TransportProtocol: UnixStream,
+				SourceAddr: &net.UnixAddr{
+					Net:  "unix",
+					Name: "src",
+				},
+				DestinationAddr: &net.UnixAddr{
+					Net:  "unix",
+					Name: "dst",
+				},
 			},
 		},
 		{
 			name: "UnixDatagram",
 			sourceAddr: &net.UnixAddr{
-				Net: "unixgram",
+				Net:  "unixgram",
+				Name: "src",
 			},
 			destAddr: &net.UnixAddr{
-				Net: "unixgram",
+				Net:  "unixgram",
+				Name: "dst",
 			},
 			expected: &Header{
 				Version:           2,
 				Command:           PROXY,
 				TransportProtocol: UnixDatagram,
+				SourceAddr: &net.UnixAddr{
+					Net:  "unixgram",
+					Name: "src",
+				},
+				DestinationAddr: &net.UnixAddr{
+					Net:  "unixgram",
+					Name: "dst",
+				},
 			},
 		},
 		{
 			name:    "Version1",
 			version: 1,
-			sourceAddr: &net.UnixAddr{
-				Net: "unix",
+			sourceAddr: &net.TCPAddr{
+				IP:   net.ParseIP("10.1.1.1"),
+				Port: 1000,
 			},
-			destAddr: &net.UnixAddr{
-				Net: "unix",
+			destAddr: &net.TCPAddr{
+				IP:   net.ParseIP("20.2.2.2"),
+				Port: 2000,
 			},
 			expected: &Header{
 				Version:           1,
 				Command:           PROXY,
-				TransportProtocol: UnixStream,
+				TransportProtocol: TCPv4,
+				SourceAddr: &net.TCPAddr{
+					IP:   net.ParseIP("10.1.1.1"),
+					Port: 1000,
+				},
+				DestinationAddr: &net.TCPAddr{
+					IP:   net.ParseIP("20.2.2.2"),
+					Port: 2000,
+				},
 			},
 		},
 		{
diff --git a/protocol_test.go b/protocol_test.go
index a35bf20..025b485 100644
--- a/protocol_test.go
+++ b/protocol_test.go
@@ -76,13 +76,17 @@ func TestParse_ipv4(t *testing.T) {
 
 		// Write out the header!
 		header := &Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  TCPv4,
-			SourceAddress:      net.ParseIP("10.1.1.1"),
-			SourcePort:         1000,
-			DestinationAddress: net.ParseIP("20.2.2.2"),
-			DestinationPort:    2000,
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: TCPv4,
+			SourceAddr: &net.TCPAddr{
+				IP:   net.ParseIP("10.1.1.1"),
+				Port: 1000,
+			},
+			DestinationAddr: &net.TCPAddr{
+				IP:   net.ParseIP("20.2.2.2"),
+				Port: 2000,
+			},
 		}
 		header.WriteTo(conn)
 
@@ -143,13 +147,17 @@ func TestParse_ipv6(t *testing.T) {
 
 		// Write out the header!
 		header := &Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  TCPv6,
-			SourceAddress:      net.ParseIP("ffff::ffff"),
-			SourcePort:         1000,
-			DestinationAddress: net.ParseIP("ffff::ffff"),
-			DestinationPort:    2000,
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: TCPv6,
+			SourceAddr: &net.TCPAddr{
+				IP:   net.ParseIP("ffff::ffff"),
+				Port: 1000,
+			},
+			DestinationAddr: &net.TCPAddr{
+				IP:   net.ParseIP("ffff::ffff"),
+				Port: 2000,
+			},
 		}
 		header.WriteTo(conn)
 
@@ -271,13 +279,17 @@ func TestReadingIsRefusedWhenProxyHeaderPresentButNotAllowed(t *testing.T) {
 		}
 		defer conn.Close()
 		header := &Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  TCPv4,
-			SourceAddress:      net.ParseIP("10.1.1.1"),
-			SourcePort:         1000,
-			DestinationAddress: net.ParseIP("20.2.2.2"),
-			DestinationPort:    2000,
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: TCPv4,
+			SourceAddr: &net.TCPAddr{
+				IP:   net.ParseIP("10.1.1.1"),
+				Port: 1000,
+			},
+			DestinationAddr: &net.TCPAddr{
+				IP:   net.ParseIP("20.2.2.2"),
+				Port: 2000,
+			},
 		}
 		header.WriteTo(conn)
 	}()
@@ -313,13 +325,17 @@ func TestIgnorePolicyIgnoresIpFromProxyHeader(t *testing.T) {
 
 		// Write out the header!
 		header := &Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  TCPv4,
-			SourceAddress:      net.ParseIP("10.1.1.1"),
-			SourcePort:         1000,
-			DestinationAddress: net.ParseIP("20.2.2.2"),
-			DestinationPort:    2000,
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: TCPv4,
+			SourceAddr: &net.TCPAddr{
+				IP:   net.ParseIP("10.1.1.1"),
+				Port: 1000,
+			},
+			DestinationAddr: &net.TCPAddr{
+				IP:   net.ParseIP("20.2.2.2"),
+				Port: 2000,
+			},
 		}
 		header.WriteTo(conn)
 
@@ -472,13 +488,17 @@ func Test_ConnectionErrorsWhenHeaderValidationFails(t *testing.T) {
 
 		// Write out the header!
 		header := &Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  TCPv4,
-			SourceAddress:      net.ParseIP("10.1.1.1"),
-			SourcePort:         1000,
-			DestinationAddress: net.ParseIP("20.2.2.2"),
-			DestinationPort:    2000,
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: TCPv4,
+			SourceAddr: &net.TCPAddr{
+				IP:   net.ParseIP("10.1.1.1"),
+				Port: 1000,
+			},
+			DestinationAddr: &net.TCPAddr{
+				IP:   net.ParseIP("20.2.2.2"),
+				Port: 2000,
+			},
 		}
 		header.WriteTo(conn)
 	}()
@@ -567,13 +587,17 @@ func Test_TLSServer(t *testing.T) {
 
 		// Write out the header!
 		header := &Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  TCPv4,
-			SourceAddress:      net.ParseIP("10.1.1.1"),
-			SourcePort:         1000,
-			DestinationAddress: net.ParseIP("20.2.2.2"),
-			DestinationPort:    2000,
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: TCPv4,
+			SourceAddr: &net.TCPAddr{
+				IP:   net.ParseIP("10.1.1.1"),
+				Port: 1000,
+			},
+			DestinationAddr: &net.TCPAddr{
+				IP:   net.ParseIP("20.2.2.2"),
+				Port: 2000,
+			},
 		}
 		header.WriteTo(conn)
 
@@ -632,13 +656,17 @@ func Test_MisconfiguredTLSServerRespondsWithUnderlyingError(t *testing.T) {
 
 		// Write out the header!
 		header := &Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  TCPv4,
-			SourceAddress:      net.ParseIP("10.1.1.1"),
-			SourcePort:         1000,
-			DestinationAddress: net.ParseIP("20.2.2.2"),
-			DestinationPort:    2000,
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: TCPv4,
+			SourceAddr: &net.TCPAddr{
+				IP:   net.ParseIP("10.1.1.1"),
+				Port: 1000,
+			},
+			DestinationAddr: &net.TCPAddr{
+				IP:   net.ParseIP("20.2.2.2"),
+				Port: 2000,
+			},
 		}
 		header.WriteTo(conn)
 
diff --git a/tlv_test.go b/tlv_test.go
index 04a3fd9..8968473 100644
--- a/tlv_test.go
+++ b/tlv_test.go
@@ -131,16 +131,18 @@ func TestJoinTLVs(t *testing.T) {
 			name: "authority TLV",
 			raw:  append([]byte{byte(PP2_TYPE_AUTHORITY), 0x00, 0x0B}, []byte("example.org")...),
 			tlvs: []TLV{{
-				Type:  PP2_TYPE_AUTHORITY,
-				Value: []byte("example.org"),
+				Type:   PP2_TYPE_AUTHORITY,
+				Length: 11,
+				Value:  []byte("example.org"),
 			}},
 		},
 		{
 			name: "empty TLV",
 			raw:  []byte{byte(PP2_TYPE_NOOP), 0x00, 0x00},
 			tlvs: []TLV{{
-				Type:  PP2_TYPE_NOOP,
-				Value: nil,
+				Type:   PP2_TYPE_NOOP,
+				Length: 0,
+				Value:  nil,
 			}},
 		},
 	}
diff --git a/tlvparse/azure_test.go b/tlvparse/azure_test.go
index c418b3d..c71adfd 100644
--- a/tlvparse/azure_test.go
+++ b/tlvparse/azure_test.go
@@ -29,8 +29,9 @@ func TestFindAzurePrivateEndpointLinkID(t *testing.T) {
 			name: "AWS VPC endpoint ID",
 			tlvs: []proxyproto.TLV{
 				{
-					Type:  0xEA,
-					Value: []byte{0x01, 0x76, 0x70, 0x63, 0x65, 0x2d, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33},
+					Type:   0xEA,
+					Length: 12,
+					Value:  []byte{0x01, 0x76, 0x70, 0x63, 0x65, 0x2d, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33},
 				},
 			},
 			wantLinkID: 0,
@@ -40,8 +41,9 @@ func TestFindAzurePrivateEndpointLinkID(t *testing.T) {
 			name: "Azure but wrong subtype",
 			tlvs: []proxyproto.TLV{
 				{
-					Type:  0xEE,
-					Value: []byte{0x02, 0x01, 0x01, 0x01, 0x01},
+					Type:   0xEE,
+					Length: 5,
+					Value:  []byte{0x02, 0x01, 0x01, 0x01, 0x01},
 				},
 			},
 			wantLinkID: 0,
@@ -51,8 +53,9 @@ func TestFindAzurePrivateEndpointLinkID(t *testing.T) {
 			name: "Azure but wrong length",
 			tlvs: []proxyproto.TLV{
 				{
-					Type:  0xEE,
-					Value: []byte{0x02, 0x01, 0x01},
+					Type:   0xEE,
+					Length: 3,
+					Value:  []byte{0x02, 0x01, 0x01},
 				},
 			},
 			wantLinkID: 0,
@@ -62,8 +65,9 @@ func TestFindAzurePrivateEndpointLinkID(t *testing.T) {
 			name: "Azure link ID",
 			tlvs: []proxyproto.TLV{
 				{
-					Type:  0xEE,
-					Value: []byte{0x1, 0xc1, 0x45, 0x0, 0x21},
+					Type:   0xEE,
+					Length: 5,
+					Value:  []byte{0x1, 0xc1, 0x45, 0x0, 0x21},
 				},
 			},
 			wantLinkID: 0x210045c1,
@@ -73,24 +77,29 @@ func TestFindAzurePrivateEndpointLinkID(t *testing.T) {
 			name: "Multiple TLVs",
 			tlvs: []proxyproto.TLV{
 				{ // AWS
-					Type:  0xEA,
-					Value: []byte{0x01, 0x76, 0x70, 0x63, 0x65, 0x2d, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33},
+					Type:   0xEA,
+					Length: 12,
+					Value:  []byte{0x01, 0x76, 0x70, 0x63, 0x65, 0x2d, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33},
 				},
 				{ // Azure but wrong subtype
-					Type:  0xEE,
-					Value: []byte{0x02, 0x01, 0x01, 0x01, 0x01},
+					Type:   0xEE,
+					Length: 5,
+					Value:  []byte{0x02, 0x01, 0x01, 0x01, 0x01},
 				},
 				{ // Azure but wrong length
-					Type:  0xEE,
-					Value: []byte{0x02, 0x01, 0x01},
+					Type:   0xEE,
+					Length: 3,
+					Value:  []byte{0x02, 0x01, 0x01},
 				},
 				{ // Correct
-					Type:  0xEE,
-					Value: []byte{0x1, 0xc1, 0x45, 0x0, 0x21},
+					Type:   0xEE,
+					Length: 5,
+					Value:  []byte{0x1, 0xc1, 0x45, 0x0, 0x21},
 				},
 				{ // Also correct, but second in line
-					Type:  0xEE,
-					Value: []byte{0x1, 0xc1, 0x45, 0x0, 0x22},
+					Type:   0xEE,
+					Length: 5,
+					Value:  []byte{0x1, 0xc1, 0x45, 0x0, 0x22},
 				},
 			},
 			wantLinkID: 0x210045c1,
diff --git a/tlvparse/ssl_test.go b/tlvparse/ssl_test.go
index e98f87b..0e2ce3b 100644
--- a/tlvparse/ssl_test.go
+++ b/tlvparse/ssl_test.go
@@ -98,20 +98,23 @@ func TestPP2SSLMarshal(t *testing.T) {
 		Verify: 0,
 		TLV: []proxyproto.TLV{
 			{
-				Type:  proxyproto.PP2_SUBTYPE_SSL_VERSION,
-				Value: []byte(ver),
+				Type:   proxyproto.PP2_SUBTYPE_SSL_VERSION,
+				Length: len(ver),
+				Value:  []byte(ver),
 			},
 			{
-				Type:  proxyproto.PP2_SUBTYPE_SSL_CN,
-				Value: []byte(cn),
+				Type:   proxyproto.PP2_SUBTYPE_SSL_CN,
+				Length: len(cn),
+				Value:  []byte(cn),
 			},
 		},
 	}
 
 	raw := []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x21, 0x0, 0x7, 0x54, 0x4c, 0x53, 0x76, 0x31, 0x2e, 0x33, 0x22, 0x0, 0xb, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6f, 0x72, 0x67}
 	want := proxyproto.TLV{
-		Type:  proxyproto.PP2_TYPE_SSL,
-		Value: raw,
+		Type:   proxyproto.PP2_TYPE_SSL,
+		Length: len(raw),
+		Value:  raw,
 	}
 
 	tlv, err := pp2.Marshal()
diff --git a/v1_test.go b/v1_test.go
index 4a35df7..9b72a79 100644
--- a/v1_test.go
+++ b/v1_test.go
@@ -66,25 +66,21 @@ var validParseAndWriteV1Tests = []struct {
 	{
 		bufio.NewReader(strings.NewReader(fixtureTCP4V1)),
 		&Header{
-			Version:            1,
-			Command:            PROXY,
-			TransportProtocol:  TCPv4,
-			SourceAddress:      v4addr,
-			DestinationAddress: v4addr,
-			SourcePort:         PORT,
-			DestinationPort:    PORT,
+			Version:           1,
+			Command:           PROXY,
+			TransportProtocol: TCPv4,
+			SourceAddr:        v4addr,
+			DestinationAddr:   v4addr,
 		},
 	},
 	{
 		bufio.NewReader(strings.NewReader(fixtureTCP6V1)),
 		&Header{
-			Version:            1,
-			Command:            PROXY,
-			TransportProtocol:  TCPv6,
-			SourceAddress:      v6addr,
-			DestinationAddress: v6addr,
-			SourcePort:         PORT,
-			DestinationPort:    PORT,
+			Version:           1,
+			Command:           PROXY,
+			TransportProtocol: TCPv6,
+			SourceAddr:        v6addr,
+			DestinationAddr:   v6addr,
 		},
 	},
 }
diff --git a/v2_test.go b/v2_test.go
index e812e46..9aa2c99 100644
--- a/v2_test.go
+++ b/v2_test.go
@@ -33,9 +33,11 @@ var (
 		return a
 	}()
 
+	unixBytes = pad([]byte("socket"), 108)
+
 	// Tests don't care if source and destination addresses and ports are the same
-	addressesIPv4 = append(v4addr.To4(), v4addr.To4()...)
-	addressesIPv6 = append(v6addr.To16(), v6addr.To16()...)
+	addressesIPv4 = append(v4ip.To4(), v4ip.To4()...)
+	addressesIPv6 = append(v6ip.To16(), v6ip.To16()...)
 	ports         = append(portBytes, portBytes...)
 
 	// Fixtures to use in tests
@@ -45,6 +47,8 @@ var (
 	fixtureIPv6Address  = append(addressesIPv6, ports...)
 	fixtureIPv6V2       = append(lengthV6Bytes, fixtureIPv6Address...)
 	fixtureIPv6V2Padded = append(append(lengthPaddedBytes, fixtureIPv6Address...), make([]byte, lengthPadded-lengthV6)...)
+	fixtureUnixAddress  = append(unixBytes, unixBytes...)
+	fixtureUnixV2       = append(lengthUnixBytes, fixtureUnixAddress...)
 	fixtureTLV          = func() []byte {
 		tlv := make([]byte, 2+rand.Intn(1<<12)) // Not enough to overflow, at least size two
 		rand.Read(tlv)
@@ -57,6 +61,11 @@ var (
 	arbitraryTailBytes = []byte{'\x99', '\x97', '\x98'}
 )
 
+func pad(b []byte, n int) []byte {
+	padding := make([]byte, n-len(b))
+	return append(b, padding...)
+}
+
 var invalidParseV2Tests = []struct {
 	reader        *bufio.Reader
 	expectedError error
@@ -127,96 +136,103 @@ var validParseAndWriteV2Tests = []struct {
 	{
 		newBufioReader(append(append(SIGV2, byte(LOCAL), byte(TCPv4)), fixtureIPv4V2...)),
 		&Header{
-			Version:            2,
-			Command:            LOCAL,
-			TransportProtocol:  TCPv4,
-			SourceAddress:      v4addr,
-			DestinationAddress: v4addr,
-			SourcePort:         PORT,
-			DestinationPort:    PORT,
+			Version:           2,
+			Command:           LOCAL,
+			TransportProtocol: TCPv4,
+			SourceAddr:        v4addr,
+			DestinationAddr:   v4addr,
 		},
 	},
 	// PROXY TCP IPv4
 	{
 		newBufioReader(append(append(SIGV2, byte(PROXY), byte(TCPv4)), fixtureIPv4V2...)),
 		&Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  TCPv4,
-			SourceAddress:      v4addr,
-			DestinationAddress: v4addr,
-			SourcePort:         PORT,
-			DestinationPort:    PORT,
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: TCPv4,
+			SourceAddr:        v4addr,
+			DestinationAddr:   v4addr,
 		},
 	},
 	// PROXY TCP IPv6
 	{
 		newBufioReader(append(append(SIGV2, byte(PROXY), byte(TCPv6)), fixtureIPv6V2...)),
 		&Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  TCPv6,
-			SourceAddress:      v6addr,
-			DestinationAddress: v6addr,
-			SourcePort:         PORT,
-			DestinationPort:    PORT,
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: TCPv6,
+			SourceAddr:        v6addr,
+			DestinationAddr:   v6addr,
 		},
 	},
 	// PROXY TCP IPv4 with TLV
 	{
 		newBufioReader(append(append(SIGV2, byte(PROXY), byte(TCPv4)), fixtureIPv4V2TLV...)),
 		&Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  TCPv4,
-			SourceAddress:      v4addr,
-			DestinationAddress: v4addr,
-			SourcePort:         PORT,
-			DestinationPort:    PORT,
-			rawTLVs:            fixtureTLV,
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: TCPv4,
+			SourceAddr:        v4addr,
+			DestinationAddr:   v4addr,
+			rawTLVs:           fixtureTLV,
 		},
 	},
 	// PROXY TCP IPv6 with TLV
 	{
 		newBufioReader(append(append(SIGV2, byte(PROXY), byte(TCPv6)), fixtureIPv6V2TLV...)),
 		&Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  TCPv6,
-			SourceAddress:      v6addr,
-			DestinationAddress: v6addr,
-			SourcePort:         PORT,
-			DestinationPort:    PORT,
-			rawTLVs:            fixtureTLV,
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: TCPv6,
+			SourceAddr:        v6addr,
+			DestinationAddr:   v6addr,
+			rawTLVs:           fixtureTLV,
 		},
 	},
 	// PROXY UDP IPv4
 	{
 		newBufioReader(append(append(SIGV2, byte(PROXY), byte(UDPv4)), fixtureIPv4V2...)),
 		&Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  UDPv4,
-			SourceAddress:      v4addr,
-			DestinationAddress: v4addr,
-			SourcePort:         PORT,
-			DestinationPort:    PORT,
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: UDPv4,
+			SourceAddr:        v4UDPAddr,
+			DestinationAddr:   v4UDPAddr,
 		},
 	},
 	// PROXY UDP IPv6
 	{
 		newBufioReader(append(append(SIGV2, byte(PROXY), byte(UDPv6)), fixtureIPv6V2...)),
 		&Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  UDPv6,
-			SourceAddress:      v6addr,
-			DestinationAddress: v6addr,
-			SourcePort:         PORT,
-			DestinationPort:    PORT,
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: UDPv6,
+			SourceAddr:        v6UDPAddr,
+			DestinationAddr:   v6UDPAddr,
+		},
+	},
+	// PROXY UNIX STREAM
+	{
+		newBufioReader(append(append(SIGV2, byte(PROXY), byte(UnixStream)), fixtureUnixV2...)),
+		&Header{
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: UnixStream,
+			SourceAddr:        unixStreamAddr,
+			DestinationAddr:   unixStreamAddr,
+		},
+	},
+	// PROXY UNIX DATAGRAM
+	{
+		newBufioReader(append(append(SIGV2, byte(PROXY), byte(UnixDatagram)), fixtureUnixV2...)),
+		&Header{
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: UnixDatagram,
+			SourceAddr:        unixDatagramAddr,
+			DestinationAddr:   unixDatagramAddr,
 		},
 	},
-	// TODO add tests for Unix stream and datagram
 }
 
 func TestParseV2Valid(t *testing.T) {
@@ -261,56 +277,48 @@ var validParseV2PaddedTests = []struct {
 	{
 		append(append(SIGV2, byte(PROXY), byte(TCPv4)), fixtureIPv4V2Padded...),
 		&Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  TCPv4,
-			SourceAddress:      v4addr,
-			DestinationAddress: v4addr,
-			SourcePort:         PORT,
-			DestinationPort:    PORT,
-			rawTLVs:            make([]byte, lengthPadded-lengthV4),
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: TCPv4,
+			SourceAddr:        v4addr,
+			DestinationAddr:   v4addr,
+			rawTLVs:           make([]byte, lengthPadded-lengthV4),
 		},
 	},
 	// PROXY TCP IPv6
 	{
 		append(append(SIGV2, byte(PROXY), byte(TCPv6)), fixtureIPv6V2Padded...),
 		&Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  TCPv6,
-			SourceAddress:      v6addr,
-			DestinationAddress: v6addr,
-			SourcePort:         PORT,
-			DestinationPort:    PORT,
-			rawTLVs:            make([]byte, lengthPadded-lengthV6),
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: TCPv6,
+			SourceAddr:        v6addr,
+			DestinationAddr:   v6addr,
+			rawTLVs:           make([]byte, lengthPadded-lengthV6),
 		},
 	},
 	// PROXY UDP IPv4
 	{
 		append(append(SIGV2, byte(PROXY), byte(UDPv4)), fixtureIPv4V2Padded...),
 		&Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  UDPv4,
-			SourceAddress:      v4addr,
-			DestinationAddress: v4addr,
-			SourcePort:         PORT,
-			DestinationPort:    PORT,
-			rawTLVs:            make([]byte, lengthPadded-lengthV4),
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: UDPv4,
+			SourceAddr:        v4addr,
+			DestinationAddr:   v4addr,
+			rawTLVs:           make([]byte, lengthPadded-lengthV4),
 		},
 	},
 	// PROXY UDP IPv6
 	{
 		append(append(SIGV2, byte(PROXY), byte(UDPv6)), fixtureIPv6V2Padded...),
 		&Header{
-			Version:            2,
-			Command:            PROXY,
-			TransportProtocol:  UDPv6,
-			SourceAddress:      v6addr,
-			DestinationAddress: v6addr,
-			SourcePort:         PORT,
-			DestinationPort:    PORT,
-			rawTLVs:            make([]byte, lengthPadded-lengthV6),
+			Version:           2,
+			Command:           PROXY,
+			TransportProtocol: UDPv6,
+			SourceAddr:        v6addr,
+			DestinationAddr:   v6addr,
+			rawTLVs:           make([]byte, lengthPadded-lengthV6),
 		},
 	},
 }
@@ -340,13 +348,11 @@ func TestParseV2Padded(t *testing.T) {
 
 func TestV2EqualsToTLV(t *testing.T) {
 	eHdr := &Header{
-		Version:            2,
-		Command:            PROXY,
-		TransportProtocol:  TCPv4,
-		SourceAddress:      v4addr,
-		DestinationAddress: v4addr,
-		SourcePort:         PORT,
-		DestinationPort:    PORT,
+		Version:           2,
+		Command:           PROXY,
+		TransportProtocol: TCPv4,
+		SourceAddr:        v4addr,
+		DestinationAddr:   v4addr,
 	}
 	hdr, err := Read(newBufioReader(append(append(SIGV2, byte(PROXY), byte(TCPv4)), fixtureIPv4V2TLV...)))
 	if err != nil {
@@ -370,47 +376,39 @@ func TestV2EqualsToTLV(t *testing.T) {
 var tlvFormatTests = []*Header{
 	// PROXY TCP IPv4
 	&Header{
-		Version:            2,
-		Command:            PROXY,
-		TransportProtocol:  TCPv4,
-		SourceAddress:      v4addr,
-		DestinationAddress: v4addr,
-		SourcePort:         PORT,
-		DestinationPort:    PORT,
-		rawTLVs:            make([]byte, 1<<16),
+		Version:           2,
+		Command:           PROXY,
+		TransportProtocol: TCPv4,
+		SourceAddr:        v4addr,
+		DestinationAddr:   v4addr,
+		rawTLVs:           make([]byte, 1<<16),
 	},
 	// PROXY TCP IPv6
 	&Header{
-		Version:            2,
-		Command:            PROXY,
-		TransportProtocol:  TCPv6,
-		SourceAddress:      v6addr,
-		DestinationAddress: v6addr,
-		SourcePort:         PORT,
-		DestinationPort:    PORT,
-		rawTLVs:            make([]byte, 1<<16),
+		Version:           2,
+		Command:           PROXY,
+		TransportProtocol: TCPv6,
+		SourceAddr:        v6addr,
+		DestinationAddr:   v6addr,
+		rawTLVs:           make([]byte, 1<<16),
 	},
 	// PROXY UDP IPv4
 	&Header{
-		Version:            2,
-		Command:            PROXY,
-		TransportProtocol:  UDPv4,
-		SourceAddress:      v4addr,
-		DestinationAddress: v4addr,
-		SourcePort:         PORT,
-		DestinationPort:    PORT,
-		rawTLVs:            make([]byte, 1<<16),
+		Version:           2,
+		Command:           PROXY,
+		TransportProtocol: UDPv4,
+		SourceAddr:        v4addr,
+		DestinationAddr:   v4addr,
+		rawTLVs:           make([]byte, 1<<16),
 	},
 	// PROXY UDP IPv6
 	&Header{
-		Version:            2,
-		Command:            PROXY,
-		TransportProtocol:  UDPv6,
-		SourceAddress:      v6addr,
-		DestinationAddress: v6addr,
-		SourcePort:         PORT,
-		DestinationPort:    PORT,
-		rawTLVs:            make([]byte, 1<<16),
+		Version:           2,
+		Command:           PROXY,
+		TransportProtocol: UDPv6,
+		SourceAddr:        v6addr,
+		DestinationAddr:   v6addr,
+		rawTLVs:           make([]byte, 1<<16),
 	},
 }