@@ -10,10 +10,15 @@ import (
1010)
1111
1212var (
13- lengthV4 = uint16 (12 )
14- lengthV6 = uint16 (36 )
15- lengthUnix = uint16 (216 )
16-
13+ lengthUnspec = uint16 (0 )
14+ lengthV4 = uint16 (12 )
15+ lengthV6 = uint16 (36 )
16+ lengthUnix = uint16 (216 )
17+ lengthUnspecBytes = func () []byte {
18+ a := make ([]byte , 2 )
19+ binary .BigEndian .PutUint16 (a , lengthUnspec )
20+ return a
21+ }()
1722 lengthV4Bytes = func () []byte {
1823 a := make ([]byte , 2 )
1924 binary .BigEndian .PutUint16 (a , lengthV4 )
@@ -82,13 +87,9 @@ func parseVersion2(reader *bufio.Reader) (header *Header, err error) {
8287 return nil , ErrCantReadAddressFamilyAndProtocol
8388 }
8489 header .TransportProtocol = AddressFamilyAndProtocol (b14 )
85- // UNSPEC is only supported when LOCAL is set.
86- if header .TransportProtocol == UNSPEC {
87- if header .Command != LOCAL {
88- return nil , ErrUnsupportedAddressFamilyAndProtocol
89- }
90- // Ignore everything else.
91- return header , nil
90+ // UNSPEC is only supported when LOCAL is set.
91+ if header .TransportProtocol == UNSPEC && header .Command != LOCAL {
92+ return nil , ErrUnsupportedAddressFamilyAndProtocol
9293 }
9394
9495 // Make sure there are bytes available as specified in length
@@ -100,46 +101,56 @@ func parseVersion2(reader *bufio.Reader) (header *Header, err error) {
100101 return nil , ErrInvalidLength
101102 }
102103
104+ // Return early if the length is zero, which means that
105+ // there's no address information and TLVs present for UNSPEC.
106+ if length == 0 {
107+ return header , nil
108+ }
109+
103110 if _ , err := reader .Peek (int (length )); err != nil {
104111 return nil , ErrInvalidLength
105112 }
106113
107114 // Length-limited reader for payload section
108115 payloadReader := io .LimitReader (reader , int64 (length )).(* io.LimitedReader )
109116
110- // Read addresses and ports
111- if header .TransportProtocol .IsIPv4 () {
112- var addr _addr4
113- if err := binary .Read (payloadReader , binary .BigEndian , & addr ); err != nil {
114- return nil , ErrInvalidAddress
115- }
116- header .SourceAddr = newIPAddr (header .TransportProtocol , addr .Src [:], addr .SrcPort )
117- header .DestinationAddr = newIPAddr (header .TransportProtocol , addr .Dst [:], addr .DstPort )
118- } else if header .TransportProtocol .IsIPv6 () {
119- var addr _addr6
120- if err := binary .Read (payloadReader , binary .BigEndian , & addr ); err != nil {
121- return nil , ErrInvalidAddress
122- }
123- header .SourceAddr = newIPAddr (header .TransportProtocol , addr .Src [:], addr .SrcPort )
124- header .DestinationAddr = newIPAddr (header .TransportProtocol , addr .Dst [:], addr .DstPort )
125- } else if header .TransportProtocol .IsUnix () {
126- var addr _addrUnix
127- if err := binary .Read (payloadReader , binary .BigEndian , & addr ); err != nil {
128- return nil , ErrInvalidAddress
129- }
117+ // Read addresses and ports for protocols other than UNSPEC.
118+ // Ignore address information for UNSPEC, and skip straight to read TLVs,
119+ // since the length is greater than zero.
120+ if header .TransportProtocol != UNSPEC {
121+ if header .TransportProtocol .IsIPv4 () {
122+ var addr _addr4
123+ if err := binary .Read (payloadReader , binary .BigEndian , & addr ); err != nil {
124+ return nil , ErrInvalidAddress
125+ }
126+ header .SourceAddr = newIPAddr (header .TransportProtocol , addr .Src [:], addr .SrcPort )
127+ header .DestinationAddr = newIPAddr (header .TransportProtocol , addr .Dst [:], addr .DstPort )
128+ } else if header .TransportProtocol .IsIPv6 () {
129+ var addr _addr6
130+ if err := binary .Read (payloadReader , binary .BigEndian , & addr ); err != nil {
131+ return nil , ErrInvalidAddress
132+ }
133+ header .SourceAddr = newIPAddr (header .TransportProtocol , addr .Src [:], addr .SrcPort )
134+ header .DestinationAddr = newIPAddr (header .TransportProtocol , addr .Dst [:], addr .DstPort )
135+ } else if header .TransportProtocol .IsUnix () {
136+ var addr _addrUnix
137+ if err := binary .Read (payloadReader , binary .BigEndian , & addr ); err != nil {
138+ return nil , ErrInvalidAddress
139+ }
130140
131- network := "unix"
132- if header .TransportProtocol .IsDatagram () {
133- network = "unixgram"
134- }
141+ network := "unix"
142+ if header .TransportProtocol .IsDatagram () {
143+ network = "unixgram"
144+ }
135145
136- header .SourceAddr = & net.UnixAddr {
137- Net : network ,
138- Name : parseUnixName (addr .Src [:]),
139- }
140- header .DestinationAddr = & net.UnixAddr {
141- Net : network ,
142- Name : parseUnixName (addr .Dst [:]),
146+ header .SourceAddr = & net.UnixAddr {
147+ Net : network ,
148+ Name : parseUnixName (addr .Src [:]),
149+ }
150+ header .DestinationAddr = & net.UnixAddr {
151+ Net : network ,
152+ Name : parseUnixName (addr .Dst [:]),
153+ }
143154 }
144155 }
145156
@@ -157,9 +168,14 @@ func (header *Header) formatVersion2() ([]byte, error) {
157168 buf .Write (SIGV2 )
158169 buf .WriteByte (header .Command .toByte ())
159170 buf .WriteByte (header .TransportProtocol .toByte ())
160- // When UNSPEC, the receiver must ignore addresses and ports.
161- // Therefore there's no point in writing it.
162- if ! header .TransportProtocol .IsUnspec () {
171+ if header .TransportProtocol .IsUnspec () {
172+ // For UNSPEC, write no addresses and ports but only TLVs if they are present
173+ hdrLen , err := addTLVLen (lengthUnspecBytes , len (header .rawTLVs ))
174+ if err != nil {
175+ return nil , err
176+ }
177+ buf .Write (hdrLen )
178+ } else {
163179 var addrSrc , addrDst []byte
164180 if header .TransportProtocol .IsIPv4 () {
165181 hdrLen , err := addTLVLen (lengthV4Bytes , len (header .rawTLVs ))
@@ -221,6 +237,8 @@ func (header *Header) validateLength(length uint16) bool {
221237 return length >= lengthV6
222238 } else if header .TransportProtocol .IsUnix () {
223239 return length >= lengthUnix
240+ } else if header .TransportProtocol .IsUnspec () {
241+ return length >= lengthUnspec
224242 }
225243 return false
226244}
0 commit comments