@@ -10,10 +10,15 @@ import (
10
10
)
11
11
12
12
var (
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
+ }()
17
22
lengthV4Bytes = func () []byte {
18
23
a := make ([]byte , 2 )
19
24
binary .BigEndian .PutUint16 (a , lengthV4 )
@@ -82,13 +87,9 @@ func parseVersion2(reader *bufio.Reader) (header *Header, err error) {
82
87
return nil , ErrCantReadAddressFamilyAndProtocol
83
88
}
84
89
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
92
93
}
93
94
94
95
// Make sure there are bytes available as specified in length
@@ -100,46 +101,56 @@ func parseVersion2(reader *bufio.Reader) (header *Header, err error) {
100
101
return nil , ErrInvalidLength
101
102
}
102
103
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
+
103
110
if _ , err := reader .Peek (int (length )); err != nil {
104
111
return nil , ErrInvalidLength
105
112
}
106
113
107
114
// Length-limited reader for payload section
108
115
payloadReader := io .LimitReader (reader , int64 (length )).(* io.LimitedReader )
109
116
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
+ }
130
140
131
- network := "unix"
132
- if header .TransportProtocol .IsDatagram () {
133
- network = "unixgram"
134
- }
141
+ network := "unix"
142
+ if header .TransportProtocol .IsDatagram () {
143
+ network = "unixgram"
144
+ }
135
145
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
+ }
143
154
}
144
155
}
145
156
@@ -157,9 +168,14 @@ func (header *Header) formatVersion2() ([]byte, error) {
157
168
buf .Write (SIGV2 )
158
169
buf .WriteByte (header .Command .toByte ())
159
170
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 {
163
179
var addrSrc , addrDst []byte
164
180
if header .TransportProtocol .IsIPv4 () {
165
181
hdrLen , err := addTLVLen (lengthV4Bytes , len (header .rawTLVs ))
@@ -221,6 +237,8 @@ func (header *Header) validateLength(length uint16) bool {
221
237
return length >= lengthV6
222
238
} else if header .TransportProtocol .IsUnix () {
223
239
return length >= lengthUnix
240
+ } else if header .TransportProtocol .IsUnspec () {
241
+ return length >= lengthUnspec
224
242
}
225
243
return false
226
244
}
0 commit comments