@@ -44,17 +44,19 @@ var LogPackets atomicbitops.Uint32 = atomicbitops.FromUint32(1)
44
44
// sniffer was created for this flag to have effect.
45
45
var LogPacketsToPCAP atomicbitops.Uint32 = atomicbitops .FromUint32 (1 )
46
46
47
+ // Endpoint is used to sniff and log network traffic.
48
+ //
47
49
// +stateify savable
48
- type endpoint struct {
50
+ type Endpoint struct {
49
51
nested.Endpoint
50
52
writer io.Writer
51
53
maxPCAPLen uint32
52
54
logPrefix string
53
55
}
54
56
55
- var _ stack.GSOEndpoint = (* endpoint )(nil )
56
- var _ stack.LinkEndpoint = (* endpoint )(nil )
57
- var _ stack.NetworkDispatcher = (* endpoint )(nil )
57
+ var _ stack.GSOEndpoint = (* Endpoint )(nil )
58
+ var _ stack.LinkEndpoint = (* Endpoint )(nil )
59
+ var _ stack.NetworkDispatcher = (* Endpoint )(nil )
58
60
59
61
// A Direction indicates whether the packing is being sent or received.
60
62
type Direction int
@@ -66,9 +68,20 @@ const (
66
68
DirectionRecv
67
69
)
68
70
71
+ func (dr Direction ) String () string {
72
+ switch dr {
73
+ case DirectionSend :
74
+ return "send"
75
+ case DirectionRecv :
76
+ return "recv"
77
+ default :
78
+ panic (fmt .Sprintf ("invalid Direction %d" , dr ))
79
+ }
80
+ }
81
+
69
82
// New creates a new sniffer link-layer endpoint. It wraps around another
70
83
// endpoint and logs packets and they traverse the endpoint.
71
- func New (lower stack.LinkEndpoint ) stack. LinkEndpoint {
84
+ func New (lower stack.LinkEndpoint ) * Endpoint {
72
85
return NewWithPrefix (lower , "" )
73
86
}
74
87
@@ -79,8 +92,8 @@ func New(lower stack.LinkEndpoint) stack.LinkEndpoint {
79
92
// logPrefix is prepended to the log line without any separators.
80
93
// E.g. logPrefix = "NIC:en0/" will produce log lines like
81
94
// "NIC:en0/send udp [...]".
82
- func NewWithPrefix (lower stack.LinkEndpoint , logPrefix string ) stack. LinkEndpoint {
83
- sniffer := & endpoint {logPrefix : logPrefix }
95
+ func NewWithPrefix (lower stack.LinkEndpoint , logPrefix string ) * Endpoint {
96
+ sniffer := & Endpoint {logPrefix : logPrefix }
84
97
sniffer .Endpoint .Init (lower , sniffer )
85
98
return sniffer
86
99
}
@@ -119,11 +132,11 @@ func writePCAPHeader(w io.Writer, maxLen uint32) error {
119
132
// snapLen is the maximum amount of a packet to be saved. Packets with a length
120
133
// less than or equal to snapLen will be saved in their entirety. Longer
121
134
// packets will be truncated to snapLen.
122
- func NewWithWriter (lower stack.LinkEndpoint , writer io.Writer , snapLen uint32 ) (stack. LinkEndpoint , error ) {
135
+ func NewWithWriter (lower stack.LinkEndpoint , writer io.Writer , snapLen uint32 ) (* Endpoint , error ) {
123
136
if err := writePCAPHeader (writer , snapLen ); err != nil {
124
137
return nil , err
125
138
}
126
- sniffer := & endpoint {
139
+ sniffer := & Endpoint {
127
140
writer : writer ,
128
141
maxPCAPLen : snapLen ,
129
142
}
@@ -134,22 +147,28 @@ func NewWithWriter(lower stack.LinkEndpoint, writer io.Writer, snapLen uint32) (
134
147
// DeliverNetworkPacket implements the stack.NetworkDispatcher interface. It is
135
148
// called by the link-layer endpoint being wrapped when a packet arrives, and
136
149
// logs the packet before forwarding to the actual dispatcher.
137
- func (e * endpoint ) DeliverNetworkPacket (protocol tcpip.NetworkProtocolNumber , pkt * stack.PacketBuffer ) {
138
- e .dumpPacket (DirectionRecv , protocol , pkt )
150
+ func (e * Endpoint ) DeliverNetworkPacket (protocol tcpip.NetworkProtocolNumber , pkt * stack.PacketBuffer ) {
151
+ e .DumpPacket (DirectionRecv , protocol , pkt , nil )
139
152
e .Endpoint .DeliverNetworkPacket (protocol , pkt )
140
153
}
141
154
142
- func (e * endpoint ) dumpPacket (dir Direction , protocol tcpip.NetworkProtocolNumber , pkt * stack.PacketBuffer ) {
155
+ // DumpPacket logs a packet, depending on configuration, to stderr and/or a
156
+ // pcap file. ts is an optional timestamp for the packet.
157
+ func (e * Endpoint ) DumpPacket (dir Direction , protocol tcpip.NetworkProtocolNumber , pkt * stack.PacketBuffer , ts * time.Time ) {
143
158
writer := e .writer
144
159
if LogPackets .Load () == 1 {
145
160
LogPacket (e .logPrefix , dir , protocol , pkt )
146
161
}
147
162
if writer != nil && LogPacketsToPCAP .Load () == 1 {
148
163
packet := pcapPacket {
149
- timestamp : time .Now (),
150
164
packet : pkt ,
151
165
maxCaptureLen : int (e .maxPCAPLen ),
152
166
}
167
+ if ts == nil {
168
+ packet .timestamp = time .Now ()
169
+ } else {
170
+ packet .timestamp = * ts
171
+ }
153
172
b , err := packet .MarshalBinary ()
154
173
if err != nil {
155
174
panic (err )
@@ -163,9 +182,9 @@ func (e *endpoint) dumpPacket(dir Direction, protocol tcpip.NetworkProtocolNumbe
163
182
// WritePackets implements the stack.LinkEndpoint interface. It is called by
164
183
// higher-level protocols to write packets; it just logs the packet and
165
184
// forwards the request to the lower endpoint.
166
- func (e * endpoint ) WritePackets (pkts stack.PacketBufferList ) (int , tcpip.Error ) {
185
+ func (e * Endpoint ) WritePackets (pkts stack.PacketBufferList ) (int , tcpip.Error ) {
167
186
for _ , pkt := range pkts .AsSlice () {
168
- e .dumpPacket (DirectionSend , pkt .NetworkProtocolNumber , pkt )
187
+ e .DumpPacket (DirectionSend , pkt .NetworkProtocolNumber , pkt , nil )
169
188
}
170
189
return e .Endpoint .WritePackets (pkts )
171
190
}
@@ -181,16 +200,6 @@ func LogPacket(prefix string, dir Direction, protocol tcpip.NetworkProtocolNumbe
181
200
var fragmentOffset uint16
182
201
var moreFragments bool
183
202
184
- var directionPrefix string
185
- switch dir {
186
- case DirectionSend :
187
- directionPrefix = "send"
188
- case DirectionRecv :
189
- directionPrefix = "recv"
190
- default :
191
- panic (fmt .Sprintf ("unrecognized direction: %d" , dir ))
192
- }
193
-
194
203
clone := trimmedClone (pkt )
195
204
defer clone .DecRef ()
196
205
switch protocol {
@@ -232,14 +241,14 @@ func LogPacket(prefix string, dir Direction, protocol tcpip.NetworkProtocolNumbe
232
241
log .Infof (
233
242
"%s%s arp %s (%s) -> %s (%s) valid:%t" ,
234
243
prefix ,
235
- directionPrefix ,
244
+ dir ,
236
245
tcpip .AddrFromSlice (arp .ProtocolAddressSender ()), tcpip .LinkAddress (arp .HardwareAddressSender ()),
237
246
tcpip .AddrFromSlice (arp .ProtocolAddressTarget ()), tcpip .LinkAddress (arp .HardwareAddressTarget ()),
238
247
arp .IsValid (),
239
248
)
240
249
return
241
250
default :
242
- log .Infof ("%s%s unknown network protocol: %d" , prefix , directionPrefix , protocol )
251
+ log .Infof ("%s%s unknown network protocol: %d" , prefix , dir , protocol )
243
252
return
244
253
}
245
254
@@ -283,7 +292,7 @@ func LogPacket(prefix string, dir Direction, protocol tcpip.NetworkProtocolNumbe
283
292
icmpType = "info reply"
284
293
}
285
294
}
286
- log .Infof ("%s%s %s %s -> %s %s len:%d id:%04x code:%d" , prefix , directionPrefix , transName , src , dst , icmpType , size , id , icmp .Code ())
295
+ log .Infof ("%s%s %s %s -> %s %s len:%d id:%04x code:%d" , prefix , dir , transName , src , dst , icmpType , size , id , icmp .Code ())
287
296
return
288
297
289
298
case header .ICMPv6ProtocolNumber :
@@ -318,7 +327,7 @@ func LogPacket(prefix string, dir Direction, protocol tcpip.NetworkProtocolNumbe
318
327
case header .ICMPv6RedirectMsg :
319
328
icmpType = "redirect message"
320
329
}
321
- log .Infof ("%s%s %s %s -> %s %s len:%d id:%04x code:%d" , prefix , directionPrefix , transName , src , dst , icmpType , size , id , icmp .Code ())
330
+ log .Infof ("%s%s %s %s -> %s %s len:%d id:%04x code:%d" , prefix , dir , transName , src , dst , icmpType , size , id , icmp .Code ())
322
331
return
323
332
324
333
case header .UDPProtocolNumber :
@@ -359,24 +368,24 @@ func LogPacket(prefix string, dir Direction, protocol tcpip.NetworkProtocolNumbe
359
368
360
369
// Initialize the TCP flags.
361
370
flags := tcp .Flags ()
362
- details = fmt .Sprintf ("flags: %s seqnum: %d ack: %d win: %d xsum:0x%x" , flags , tcp .SequenceNumber (), tcp .AckNumber (), tcp .WindowSize (), tcp .Checksum ())
371
+ details = fmt .Sprintf ("flags:%s seqnum:%d ack:%d win:%d xsum:0x%x" , flags , tcp .SequenceNumber (), tcp .AckNumber (), tcp .WindowSize (), tcp .Checksum ())
363
372
if flags & header .TCPFlagSyn != 0 {
364
- details += fmt .Sprintf (" options: %+v" , header .ParseSynOptions (tcp .Options (), flags & header .TCPFlagAck != 0 ))
373
+ details += fmt .Sprintf (" options:%+v" , header .ParseSynOptions (tcp .Options (), flags & header .TCPFlagAck != 0 ))
365
374
} else {
366
- details += fmt .Sprintf (" options: %+v" , tcp .ParsedOptions ())
375
+ details += fmt .Sprintf (" options:%+v" , tcp .ParsedOptions ())
367
376
}
368
377
}
369
378
370
379
default :
371
- log .Infof ("%s%s %s -> %s unknown transport protocol: %d" , prefix , directionPrefix , src , dst , transProto )
380
+ log .Infof ("%s%s %s -> %s unknown transport protocol: %d" , prefix , dir , src , dst , transProto )
372
381
return
373
382
}
374
383
375
384
if pkt .GSOOptions .Type != stack .GSONone {
376
- details += fmt .Sprintf (" gso: %#v" , pkt .GSOOptions )
385
+ details += fmt .Sprintf (" gso:%#v" , pkt .GSOOptions )
377
386
}
378
387
379
- log .Infof ("%s%s %s %s:%d -> %s:%d len:%d id:%04x %s" , prefix , directionPrefix , transName , src , srcPort , dst , dstPort , size , id , details )
388
+ log .Infof ("%s%s %s %s:%d -> %s:%d len:%d id:0x %04x %s" , prefix , dir , transName , src , srcPort , dst , dstPort , size , id , details )
380
389
}
381
390
382
391
// trimmedClone clones the packet buffer to not modify the original. It trims
0 commit comments