github.com/gopacket/gopacket@v1.1.0/pcap/pcap.go (about) 1 // Copyright 2012 Google, Inc. All rights reserved. 2 // Copyright 2009-2011 Andreas Krennmair. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style license 5 // that can be found in the LICENSE file in the root of the source 6 // tree. 7 8 package pcap 9 10 import ( 11 "errors" 12 "fmt" 13 "io" 14 "net" 15 "os" 16 "reflect" 17 "runtime" 18 "strconv" 19 "sync" 20 "sync/atomic" 21 "syscall" 22 "time" 23 "unsafe" 24 25 "github.com/gopacket/gopacket" 26 "github.com/gopacket/gopacket/layers" 27 ) 28 29 // ErrNotActive is returned if handle is not activated 30 const ErrNotActive = pcapErrorNotActivated 31 32 // MaxBpfInstructions is the maximum number of BPF instructions supported (BPF_MAXINSNS), 33 // taken from Linux kernel: include/uapi/linux/bpf_common.h 34 // 35 // https://github.com/torvalds/linux/blob/master/include/uapi/linux/bpf_common.h 36 const MaxBpfInstructions = 4096 37 38 // 8 bytes per instruction, max 4096 instructions 39 const bpfInstructionBufferSize = 8 * MaxBpfInstructions 40 41 // Handle provides a connection to a pcap handle, allowing users to read packets 42 // off the wire (Next), inject packets onto the wire (Inject), and 43 // perform a number of other functions to affect and understand packet output. 44 // 45 // Handles are already pcap_activate'd 46 type Handle struct { 47 // stop is set to a non-zero value by Handle.Close to signal to 48 // getNextBufPtrLocked to stop trying to read packets 49 // This must be the first entry to ensure alignment for sync.atomic 50 stop uint64 51 // cptr is the handle for the actual pcap C object. 52 cptr pcapTPtr 53 timeout time.Duration 54 device string 55 deviceIndex int 56 mu sync.Mutex 57 closeMu sync.Mutex 58 nanoSecsFactor int64 59 60 // Since pointers to these objects are passed into a C function, if 61 // they're declared locally then the Go compiler thinks they may have 62 // escaped into C-land, so it allocates them on the heap. This causes a 63 // huge memory hit, so to handle that we store them here instead. 64 pkthdr *pcapPkthdr 65 bufptr *uint8 66 } 67 68 // Stats contains statistics on how many packets were handled by a pcap handle, 69 // and what was done with those packets. 70 type Stats struct { 71 PacketsReceived int 72 PacketsDropped int 73 PacketsIfDropped int 74 } 75 76 // Interface describes a single network interface on a machine. 77 type Interface struct { 78 Name string 79 Description string 80 Flags uint32 81 Addresses []InterfaceAddress 82 } 83 84 // Datalink describes the datalink 85 type Datalink struct { 86 Name string 87 Description string 88 } 89 90 // InterfaceAddress describes an address associated with an Interface. 91 // Currently, it's IPv4/6 specific. 92 type InterfaceAddress struct { 93 IP net.IP 94 Netmask net.IPMask // Netmask may be nil if we were unable to retrieve it. 95 Broadaddr net.IP // Broadcast address for this IP may be nil 96 P2P net.IP // P2P destination address for this IP may be nil 97 } 98 99 // bpfFilter keeps C.struct_bpf_program separate from BPF.orig which might be a pointer to go memory. 100 // This is a workaround for https://github.com/golang/go/issues/32970 which will be fixed in go1.14. 101 // (type conversion is in pcap_unix.go pcapOfflineFilter) 102 type bpfFilter struct { 103 bpf pcapBpfProgram // takes a finalizer, not overriden by outsiders 104 } 105 106 // BPF is a compiled filter program, useful for offline packet matching. 107 type BPF struct { 108 orig string 109 bpf *bpfFilter 110 hdr pcapPkthdr // allocate on the heap to enable optimizations 111 } 112 113 // BPFInstruction is a byte encoded structure holding a BPF instruction 114 type BPFInstruction struct { 115 Code uint16 116 Jt uint8 117 Jf uint8 118 K uint32 119 } 120 121 // BlockForever causes it to block forever waiting for packets, when passed 122 // into SetTimeout or OpenLive, while still returning incoming packets to userland relatively 123 // quickly. 124 const BlockForever = -time.Millisecond * 10 125 126 func timeoutMillis(timeout time.Duration) int { 127 // Flip sign if necessary. See package docs on timeout for reasoning behind this. 128 if timeout < 0 { 129 timeout *= -1 130 } 131 // Round up 132 if timeout != 0 && timeout < time.Millisecond { 133 timeout = time.Millisecond 134 } 135 return int(timeout / time.Millisecond) 136 } 137 138 // OpenLive opens a device and returns a *Handle. 139 // It takes as arguments the name of the device ("eth0"), the maximum size to 140 // read for each packet (snaplen), whether to put the interface in promiscuous 141 // mode, and a timeout. Warning: this function supports only microsecond timestamps. 142 // For nanosecond resolution use an InactiveHandle. 143 // 144 // See the package documentation for important details regarding 'timeout'. 145 func OpenLive(device string, snaplen int32, promisc bool, timeout time.Duration) (handle *Handle, _ error) { 146 var pro int 147 if promisc { 148 pro = 1 149 } 150 151 p, err := pcapOpenLive(device, int(snaplen), pro, timeoutMillis(timeout)) 152 if err != nil { 153 return nil, err 154 } 155 p.timeout = timeout 156 p.device = device 157 158 ifc, err := net.InterfaceByName(device) 159 if err != nil { 160 // The device wasn't found in the OS, but could be "any" 161 // Set index to 0 162 p.deviceIndex = 0 163 } else { 164 p.deviceIndex = ifc.Index 165 } 166 167 p.nanoSecsFactor = 1000 168 169 // Only set the PCAP handle into non-blocking mode if we have a timeout 170 // greater than zero. If the user wants to block forever, we'll let libpcap 171 // handle that. 172 if p.timeout > 0 { 173 if err := p.setNonBlocking(); err != nil { 174 p.pcapClose() 175 return nil, err 176 } 177 } 178 179 return p, nil 180 } 181 182 // OpenOffline opens a file and returns its contents as a *Handle. Depending on libpcap support and 183 // on the timestamp resolution used in the file, nanosecond or microsecond resolution is used 184 // internally. All returned timestamps are scaled to nanosecond resolution. Resolution() can be used 185 // to query the actual resolution used. 186 func OpenOffline(file string) (handle *Handle, err error) { 187 handle, err = openOffline(file) 188 if err != nil { 189 return 190 } 191 if pcapGetTstampPrecision(handle.cptr) == pcapTstampPrecisionNano { 192 handle.nanoSecsFactor = 1 193 } else { 194 handle.nanoSecsFactor = 1000 195 } 196 return 197 } 198 199 // OpenOfflineFile returns contents of input file as a *Handle. Depending on libpcap support and 200 // on the timestamp resolution used in the file, nanosecond or microsecond resolution is used 201 // internally. All returned timestamps are scaled to nanosecond resolution. Resolution() can be used 202 // to query the actual resolution used. 203 func OpenOfflineFile(file *os.File) (handle *Handle, err error) { 204 handle, err = openOfflineFile(file) 205 if err != nil { 206 return 207 } 208 if pcapGetTstampPrecision(handle.cptr) == pcapTstampPrecisionNano { 209 handle.nanoSecsFactor = 1 210 } else { 211 handle.nanoSecsFactor = 1000 212 } 213 return 214 } 215 216 // NextError is the return code from a call to Next. 217 type NextError int32 218 219 // NextError implements the error interface. 220 func (n NextError) Error() string { 221 switch n { 222 case NextErrorOk: 223 return "OK" 224 case NextErrorTimeoutExpired: 225 return "Timeout Expired" 226 case NextErrorReadError: 227 return "Read Error" 228 case NextErrorNoMorePackets: 229 return "No More Packets In File" 230 case NextErrorNotActivated: 231 return "Not Activated" 232 } 233 return strconv.Itoa(int(n)) 234 } 235 236 // NextError values. 237 const ( 238 NextErrorOk NextError = 1 239 NextErrorTimeoutExpired NextError = 0 240 NextErrorReadError NextError = -1 241 // NextErrorNoMorePackets is returned when reading from a file (OpenOffline) and 242 // EOF is reached. When this happens, Next() returns io.EOF instead of this. 243 NextErrorNoMorePackets NextError = -2 244 NextErrorNotActivated NextError = -3 245 ) 246 247 // ReadPacketData returns the next packet read from the pcap handle, along with an error 248 // code associated with that packet. If the packet is read successfully, the 249 // returned error is nil. 250 func (p *Handle) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) { 251 p.mu.Lock() 252 err = p.getNextBufPtrLocked(&ci) 253 if err == nil { 254 data = make([]byte, ci.CaptureLength) 255 copy(data, (*(*[1 << 30]byte)(unsafe.Pointer(p.bufptr)))[:]) 256 } 257 p.mu.Unlock() 258 if err == NextErrorTimeoutExpired { 259 runtime.Gosched() 260 } 261 return 262 } 263 264 type activateError int 265 266 const ( 267 aeNoError = activateError(0) 268 aeActivated = activateError(pcapErrorActivated) 269 aePromisc = activateError(pcapWarningPromisc) 270 aeNoSuchDevice = activateError(pcapErrorNoSuchDevice) 271 aeDenied = activateError(pcapErrorDenied) 272 aeNotUp = activateError(pcapErrorNotUp) 273 aeWarning = activateError(pcapWarning) 274 aeError = activateError(pcapError) 275 ) 276 277 func (a activateError) Error() string { 278 switch a { 279 case aeNoError: 280 return "No Error" 281 case aeActivated: 282 return "Already Activated" 283 case aePromisc: 284 return "Cannot set as promisc" 285 case aeNoSuchDevice: 286 return "No Such Device" 287 case aeDenied: 288 return "Permission Denied" 289 case aeNotUp: 290 return "Interface Not Up" 291 case aeWarning: 292 return fmt.Sprintf("Warning: %v", activateErrMsg.Error()) 293 case aeError: 294 return fmt.Sprintf("Error: %v", activateErrMsg.Error()) 295 default: 296 return fmt.Sprintf("unknown activated error: %d", a) 297 } 298 } 299 300 // getNextBufPtrLocked is shared code for ReadPacketData and 301 // ZeroCopyReadPacketData. 302 func (p *Handle) getNextBufPtrLocked(ci *gopacket.CaptureInfo) error { 303 if !p.isOpen() { 304 return io.EOF 305 } 306 307 // set after we have call waitForPacket for the first time 308 var waited bool 309 310 for atomic.LoadUint64(&p.stop) == 0 { 311 // try to read a packet if one is immediately available 312 result := p.pcapNextPacketEx() 313 314 switch result { 315 case NextErrorOk: 316 sec := p.pkthdr.getSec() 317 // convert micros to nanos 318 nanos := int64(p.pkthdr.getUsec()) * p.nanoSecsFactor 319 320 ci.Timestamp = time.Unix(sec, nanos) 321 ci.CaptureLength = p.pkthdr.getCaplen() 322 ci.Length = p.pkthdr.getLen() 323 ci.InterfaceIndex = p.deviceIndex 324 325 return nil 326 case NextErrorNoMorePackets: 327 // no more packets, return EOF rather than libpcap-specific error 328 return io.EOF 329 case NextErrorTimeoutExpired: 330 // we've already waited for a packet and we're supposed to time out 331 // 332 // we should never actually hit this if we were passed BlockForever 333 // since we should block on C.pcap_next_ex until there's a packet 334 // to read. 335 if waited && p.timeout > 0 { 336 return result 337 } 338 339 // wait for packet before trying again 340 p.waitForPacket() 341 waited = true 342 default: 343 return result 344 } 345 } 346 347 // stop must be set 348 return io.EOF 349 } 350 351 // ZeroCopyReadPacketData reads the next packet off the wire, and returns its data. 352 // The slice returned by ZeroCopyReadPacketData points to bytes owned by the 353 // the Handle. Each call to ZeroCopyReadPacketData invalidates any data previously 354 // returned by ZeroCopyReadPacketData. Care must be taken not to keep pointers 355 // to old bytes when using ZeroCopyReadPacketData... if you need to keep data past 356 // the next time you call ZeroCopyReadPacketData, use ReadPacketData, which copies 357 // the bytes into a new buffer for you. 358 // 359 // data1, _, _ := handle.ZeroCopyReadPacketData() 360 // // do everything you want with data1 here, copying bytes out of it if you'd like to keep them around. 361 // data2, _, _ := handle.ZeroCopyReadPacketData() // invalidates bytes in data1 362 func (p *Handle) ZeroCopyReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) { 363 p.mu.Lock() 364 err = p.getNextBufPtrLocked(&ci) 365 if err == nil { 366 slice := (*reflect.SliceHeader)(unsafe.Pointer(&data)) 367 slice.Data = uintptr(unsafe.Pointer(p.bufptr)) 368 slice.Len = ci.CaptureLength 369 slice.Cap = ci.CaptureLength 370 } 371 p.mu.Unlock() 372 if err == NextErrorTimeoutExpired { 373 runtime.Gosched() 374 } 375 return 376 } 377 378 // Close closes the underlying pcap handle. 379 func (p *Handle) Close() { 380 p.closeMu.Lock() 381 defer p.closeMu.Unlock() 382 383 if !p.isOpen() { 384 return 385 } 386 387 atomic.StoreUint64(&p.stop, 1) 388 389 // wait for packet reader to stop 390 p.mu.Lock() 391 defer p.mu.Unlock() 392 393 p.pcapClose() 394 } 395 396 // Error returns the current error associated with a pcap handle (pcap_geterr). 397 func (p *Handle) Error() error { 398 return p.pcapGeterr() 399 } 400 401 // Stats returns statistics on the underlying pcap handle. 402 func (p *Handle) Stats() (stat *Stats, err error) { 403 return p.pcapStats() 404 } 405 406 // ListDataLinks obtains a list of all possible data link types supported for an interface. 407 func (p *Handle) ListDataLinks() (datalinks []Datalink, err error) { 408 return p.pcapListDatalinks() 409 } 410 411 // compileBPFFilter always returns an allocated C.struct_bpf_program 412 // It is the callers responsibility to free the memory again, e.g. 413 // 414 // C.pcap_freecode(&bpf) 415 func (p *Handle) compileBPFFilter(expr string) (pcapBpfProgram, error) { 416 var maskp = uint32(pcapNetmaskUnknown) 417 418 // Only do the lookup on network interfaces. 419 // No device indicates we're handling a pcap file. 420 if len(p.device) > 0 { 421 var err error 422 _, maskp, err = pcapLookupnet(p.device) 423 if err != nil { 424 // We can't lookup the network, but that could be because the interface 425 // doesn't have an IPv4. 426 maskp = uint32(pcapNetmaskUnknown) 427 } 428 } 429 430 return p.pcapCompile(expr, maskp) 431 } 432 433 // CompileBPFFilter compiles and returns a BPF filter with given a link type and capture length. 434 func CompileBPFFilter(linkType layers.LinkType, captureLength int, expr string) ([]BPFInstruction, error) { 435 h, err := pcapOpenDead(linkType, captureLength) 436 if err != nil { 437 return nil, err 438 } 439 defer h.Close() 440 return h.CompileBPFFilter(expr) 441 } 442 443 // CompileBPFFilter compiles and returns a BPF filter for the pcap handle. 444 func (p *Handle) CompileBPFFilter(expr string) ([]BPFInstruction, error) { 445 bpf, err := p.compileBPFFilter(expr) 446 defer bpf.free() 447 if err != nil { 448 return nil, err 449 } 450 451 return bpf.toBPFInstruction(), nil 452 } 453 454 // SetBPFFilter compiles and sets a BPF filter for the pcap handle. 455 func (p *Handle) SetBPFFilter(expr string) (err error) { 456 bpf, err := p.compileBPFFilter(expr) 457 defer bpf.free() 458 if err != nil { 459 return err 460 } 461 462 return p.pcapSetfilter(bpf) 463 } 464 465 // SetBPFInstructionFilter may be used to apply a filter in BPF asm byte code format. 466 // 467 // Simplest way to generate BPF asm byte code is with tcpdump: 468 // 469 // tcpdump -dd 'udp' 470 // 471 // The output may be used directly to add a filter, e.g.: 472 // 473 // bpfInstructions := []pcap.BpfInstruction{ 474 // {0x28, 0, 0, 0x0000000c}, 475 // {0x15, 0, 9, 0x00000800}, 476 // {0x30, 0, 0, 0x00000017}, 477 // {0x15, 0, 7, 0x00000006}, 478 // {0x28, 0, 0, 0x00000014}, 479 // {0x45, 5, 0, 0x00001fff}, 480 // {0xb1, 0, 0, 0x0000000e}, 481 // {0x50, 0, 0, 0x0000001b}, 482 // {0x54, 0, 0, 0x00000012}, 483 // {0x15, 0, 1, 0x00000012}, 484 // {0x6, 0, 0, 0x0000ffff}, 485 // {0x6, 0, 0, 0x00000000}, 486 // } 487 // 488 // An other posibility is to write the bpf code in bpf asm. 489 // Documentation: https://www.kernel.org/doc/Documentation/networking/filter.txt 490 // 491 // To compile the code use bpf_asm from 492 // https://github.com/torvalds/linux/tree/master/tools/net 493 // 494 // The following command may be used to convert bpf_asm output to c/go struct, usable for SetBPFFilterByte: 495 // bpf_asm -c tcp.bpf 496 func (p *Handle) SetBPFInstructionFilter(bpfInstructions []BPFInstruction) (err error) { 497 bpf, err := bpfInstructionFilter(bpfInstructions) 498 if err != nil { 499 return err 500 } 501 defer bpf.free() 502 503 return p.pcapSetfilter(bpf) 504 } 505 506 func bpfInstructionFilter(bpfInstructions []BPFInstruction) (bpf pcapBpfProgram, err error) { 507 if len(bpfInstructions) < 1 { 508 return bpf, errors.New("bpfInstructions must not be empty") 509 } 510 511 if len(bpfInstructions) > MaxBpfInstructions { 512 return bpf, fmt.Errorf("bpfInstructions must not be larger than %d", MaxBpfInstructions) 513 } 514 515 return pcapBpfProgramFromInstructions(bpfInstructions), nil 516 } 517 518 // NewBPF compiles the given string into a new filter program. 519 // 520 // BPF filters need to be created from activated handles, because they need to 521 // know the underlying link type to correctly compile their offsets. 522 func (p *Handle) NewBPF(expr string) (*BPF, error) { 523 bpf := &BPF{orig: expr, bpf: new(bpfFilter)} 524 525 var err error 526 bpf.bpf.bpf, err = p.pcapCompile(expr, pcapNetmaskUnknown) 527 if err != nil { 528 return nil, err 529 } 530 531 runtime.SetFinalizer(bpf, destroyBPF) 532 return bpf, nil 533 } 534 535 // NewBPF allows to create a BPF without requiring an existing handle. 536 // This allows to match packets obtained from a-non GoPacket capture source 537 // to be matched. 538 // 539 // buf := make([]byte, MaxFrameSize) 540 // bpfi, _ := pcap.NewBPF(layers.LinkTypeEthernet, MaxFrameSize, "icmp") 541 // n, _ := someIO.Read(buf) 542 // ci := gopacket.CaptureInfo{CaptureLength: n, Length: n} 543 // if bpfi.Matches(ci, buf) { 544 // doSomething() 545 // } 546 func NewBPF(linkType layers.LinkType, captureLength int, expr string) (*BPF, error) { 547 h, err := pcapOpenDead(linkType, captureLength) 548 if err != nil { 549 return nil, err 550 } 551 defer h.Close() 552 return h.NewBPF(expr) 553 } 554 555 // NewBPFInstructionFilter sets the given BPFInstructions as new filter program. 556 // 557 // # More details see func SetBPFInstructionFilter 558 // 559 // BPF filters need to be created from activated handles, because they need to 560 // know the underlying link type to correctly compile their offsets. 561 func (p *Handle) NewBPFInstructionFilter(bpfInstructions []BPFInstruction) (*BPF, error) { 562 var err error 563 bpf := &BPF{orig: "BPF Instruction Filter", bpf: new(bpfFilter)} 564 565 bpf.bpf.bpf, err = bpfInstructionFilter(bpfInstructions) 566 if err != nil { 567 return nil, err 568 } 569 570 runtime.SetFinalizer(bpf, destroyBPF) 571 return bpf, nil 572 } 573 func destroyBPF(bpf *BPF) { 574 bpf.bpf.bpf.free() 575 } 576 577 // String returns the original string this BPF filter was compiled from. 578 func (b *BPF) String() string { 579 return b.orig 580 } 581 582 // Matches returns true if the given packet data matches this filter. 583 func (b *BPF) Matches(ci gopacket.CaptureInfo, data []byte) bool { 584 return b.pcapOfflineFilter(ci, data) 585 } 586 587 // Version returns pcap_lib_version. 588 func Version() string { 589 return pcapLibVersion() 590 } 591 592 // LinkType returns pcap_datalink, as a layers.LinkType. 593 func (p *Handle) LinkType() layers.LinkType { 594 return p.pcapDatalink() 595 } 596 597 // SetLinkType calls pcap_set_datalink on the pcap handle. 598 func (p *Handle) SetLinkType(dlt layers.LinkType) error { 599 return p.pcapSetDatalink(dlt) 600 } 601 602 // DatalinkValToName returns pcap_datalink_val_to_name as string 603 func DatalinkValToName(dlt int) string { 604 return pcapDatalinkValToName(dlt) 605 } 606 607 // DatalinkValToDescription returns pcap_datalink_val_to_description as string 608 func DatalinkValToDescription(dlt int) string { 609 return pcapDatalinkValToDescription(dlt) 610 } 611 612 // DatalinkNameToVal returns pcap_datalink_name_to_val as int 613 func DatalinkNameToVal(name string) int { 614 return pcapDatalinkNameToVal(name) 615 } 616 617 // FindAllDevs attempts to enumerate all interfaces on the current machine. 618 func FindAllDevs() (ifs []Interface, err error) { 619 alldevsp, err := pcapFindAllDevs() 620 if err != nil { 621 return nil, err 622 } 623 defer alldevsp.free() 624 625 for alldevsp.next() { 626 var iface Interface 627 iface.Name = alldevsp.name() 628 iface.Description = alldevsp.description() 629 iface.Addresses = findalladdresses(alldevsp.addresses()) 630 iface.Flags = alldevsp.flags() 631 ifs = append(ifs, iface) 632 } 633 return 634 } 635 636 func findalladdresses(addresses pcapAddresses) (retval []InterfaceAddress) { 637 // TODO - make it support more than IPv4 and IPv6? 638 retval = make([]InterfaceAddress, 0, 1) 639 for addresses.next() { 640 // Strangely, it appears that in some cases, we get a pcap address back from 641 // pcap_findalldevs with a nil .addr. It appears that we can skip over 642 // these. 643 if addresses.addr() == nil { 644 continue 645 } 646 var a InterfaceAddress 647 var err error 648 if a.IP, err = sockaddrToIP(addresses.addr()); err != nil { 649 continue 650 } 651 // To be safe, we'll also check for netmask. 652 if addresses.netmask() == nil { 653 continue 654 } 655 if a.Netmask, err = sockaddrToIP(addresses.netmask()); err != nil { 656 // If we got an IP address but we can't get a netmask, just return the IP 657 // address. 658 a.Netmask = nil 659 } 660 if a.Broadaddr, err = sockaddrToIP(addresses.broadaddr()); err != nil { 661 a.Broadaddr = nil 662 } 663 if a.P2P, err = sockaddrToIP(addresses.dstaddr()); err != nil { 664 a.P2P = nil 665 } 666 retval = append(retval, a) 667 } 668 return 669 } 670 671 func sockaddrToIP(rsa *syscall.RawSockaddr) (IP []byte, err error) { 672 if rsa == nil { 673 err = errors.New("Value not set") 674 return 675 } 676 switch rsa.Family { 677 case syscall.AF_INET: 678 pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa)) 679 IP = make([]byte, 4) 680 for i := 0; i < len(IP); i++ { 681 IP[i] = pp.Addr[i] 682 } 683 return 684 case syscall.AF_INET6: 685 pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa)) 686 IP = make([]byte, 16) 687 for i := 0; i < len(IP); i++ { 688 IP[i] = pp.Addr[i] 689 } 690 return 691 } 692 err = errors.New("Unsupported address type") 693 return 694 } 695 696 // WritePacketData calls pcap_sendpacket, injecting the given data into the pcap handle. 697 func (p *Handle) WritePacketData(data []byte) (err error) { 698 return p.pcapSendpacket(data) 699 } 700 701 // Direction is used by Handle.SetDirection. 702 type Direction uint8 703 704 // Direction values for Handle.SetDirection. 705 const ( 706 DirectionIn = Direction(pcapDIN) 707 DirectionOut = Direction(pcapDOUT) 708 DirectionInOut = Direction(pcapDINOUT) 709 ) 710 711 // SetDirection sets the direction for which packets will be captured. 712 func (p *Handle) SetDirection(direction Direction) error { 713 if direction != DirectionIn && direction != DirectionOut && direction != DirectionInOut { 714 return fmt.Errorf("Invalid direction: %v", direction) 715 } 716 return p.pcapSetdirection(direction) 717 } 718 719 // SnapLen returns the snapshot length 720 func (p *Handle) SnapLen() int { 721 return p.pcapSnapshot() 722 } 723 724 // Resolution returns the timestamp resolution of acquired timestamps before scaling to NanosecondTimestampResolution. 725 func (p *Handle) Resolution() gopacket.TimestampResolution { 726 if p.nanoSecsFactor == 1 { 727 return gopacket.TimestampResolutionMicrosecond 728 } 729 return gopacket.TimestampResolutionNanosecond 730 } 731 732 // TimestampSource tells PCAP which type of timestamp to use for packets. 733 type TimestampSource int 734 735 // String returns the timestamp type as a human-readable string. 736 func (t TimestampSource) String() string { 737 return t.pcapTstampTypeValToName() 738 } 739 740 // TimestampSourceFromString translates a string into a timestamp type, case 741 // insensitive. 742 func TimestampSourceFromString(s string) (TimestampSource, error) { 743 return pcapTstampTypeNameToVal(s) 744 } 745 746 // InactiveHandle allows you to call pre-pcap_activate functions on your pcap 747 // handle to set it up just the way you'd like. 748 type InactiveHandle struct { 749 // cptr is the handle for the actual pcap C object. 750 cptr pcapTPtr 751 device string 752 deviceIndex int 753 timeout time.Duration 754 } 755 756 // holds the err messoge in case activation returned a Warning 757 var activateErrMsg error 758 759 // Error returns the current error associated with a pcap handle (pcap_geterr). 760 func (p *InactiveHandle) Error() error { 761 return p.pcapGeterr() 762 } 763 764 // Activate activates the handle. The current InactiveHandle becomes invalid 765 // and all future function calls on it will fail. 766 func (p *InactiveHandle) Activate() (*Handle, error) { 767 // ignore error with set_tstamp_precision, since the actual precision is queried later anyway 768 pcapSetTstampPrecision(p.cptr, pcapTstampPrecisionNano) 769 handle, err := p.pcapActivate() 770 if err != aeNoError { 771 if err == aeWarning || err == aeError { 772 activateErrMsg = p.Error() 773 } 774 return nil, err 775 } 776 handle.timeout = p.timeout 777 if p.timeout > 0 { 778 if err := handle.setNonBlocking(); err != nil { 779 handle.pcapClose() 780 return nil, err 781 } 782 } 783 handle.device = p.device 784 handle.deviceIndex = p.deviceIndex 785 if pcapGetTstampPrecision(handle.cptr) == pcapTstampPrecisionNano { 786 handle.nanoSecsFactor = 1 787 } else { 788 handle.nanoSecsFactor = 1000 789 } 790 return handle, nil 791 } 792 793 // CleanUp cleans up any stuff left over from a successful or failed building 794 // of a handle. 795 func (p *InactiveHandle) CleanUp() { 796 p.pcapClose() 797 } 798 799 // NewInactiveHandle creates a new InactiveHandle, which wraps an un-activated PCAP handle. 800 // Callers of NewInactiveHandle should immediately defer 'CleanUp', as in: 801 // 802 // inactive := NewInactiveHandle("eth0") 803 // defer inactive.CleanUp() 804 func NewInactiveHandle(device string) (*InactiveHandle, error) { 805 // Try to get the interface index, but iy could be something like "any" 806 // in which case use 0, which doesn't exist in nature 807 deviceIndex := 0 808 ifc, err := net.InterfaceByName(device) 809 if err == nil { 810 deviceIndex = ifc.Index 811 } 812 813 // This copies a bunch of the pcap_open_live implementation from pcap.c: 814 handle, err := pcapCreate(device) 815 if err != nil { 816 return nil, err 817 } 818 handle.device = device 819 handle.deviceIndex = deviceIndex 820 return handle, nil 821 } 822 823 // SetSnapLen sets the snap length (max bytes per packet to capture). 824 func (p *InactiveHandle) SetSnapLen(snaplen int) error { 825 return p.pcapSetSnaplen(snaplen) 826 } 827 828 // SetPromisc sets the handle to either be promiscuous (capture packets 829 // unrelated to this host) or not. 830 func (p *InactiveHandle) SetPromisc(promisc bool) error { 831 return p.pcapSetPromisc(promisc) 832 } 833 834 // SetTimeout sets the read timeout for the handle. 835 // 836 // See the package documentation for important details regarding 'timeout'. 837 func (p *InactiveHandle) SetTimeout(timeout time.Duration) error { 838 err := p.pcapSetTimeout(timeout) 839 if err != nil { 840 return err 841 } 842 p.timeout = timeout 843 return nil 844 } 845 846 // SupportedTimestamps returns a list of supported timstamp types for this 847 // handle. 848 func (p *InactiveHandle) SupportedTimestamps() (out []TimestampSource) { 849 return p.pcapListTstampTypes() 850 } 851 852 // SetTimestampSource sets the type of timestamp generator PCAP uses when 853 // attaching timestamps to packets. 854 func (p *InactiveHandle) SetTimestampSource(t TimestampSource) error { 855 return p.pcapSetTstampType(t) 856 } 857 858 // CannotSetRFMon is returned by SetRFMon if the handle does not allow 859 // setting RFMon because pcap_can_set_rfmon returns 0. 860 var CannotSetRFMon = errors.New("Cannot set rfmon for this handle") 861 862 // SetRFMon turns on radio monitoring mode, similar to promiscuous mode but for 863 // wireless networks. If this mode is enabled, the interface will not need to 864 // associate with an access point before it can receive traffic. 865 func (p *InactiveHandle) SetRFMon(monitor bool) error { 866 return p.pcapSetRfmon(monitor) 867 } 868 869 // SetBufferSize sets the buffer size (in bytes) of the handle. 870 func (p *InactiveHandle) SetBufferSize(bufferSize int) error { 871 return p.pcapSetBufferSize(bufferSize) 872 } 873 874 // SetImmediateMode sets (or unsets) the immediate mode of the 875 // handle. In immediate mode, packets are delivered to the application 876 // as soon as they arrive. In other words, this overrides SetTimeout. 877 func (p *InactiveHandle) SetImmediateMode(mode bool) error { 878 return p.pcapSetImmediateMode(mode) 879 }