github.com/gopacket/gopacket@v1.1.0/pcap/pcap_unix.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 //go:build !windows 9 // +build !windows 10 11 package pcap 12 13 import ( 14 "errors" 15 "os" 16 "sync" 17 "syscall" 18 "time" 19 "unsafe" 20 21 "github.com/gopacket/gopacket" 22 23 "github.com/gopacket/gopacket/layers" 24 ) 25 26 /* 27 #cgo solaris LDFLAGS: -L /opt/local/lib -lpcap 28 #cgo linux LDFLAGS: -lpcap 29 #cgo dragonfly LDFLAGS: -lpcap 30 #cgo freebsd LDFLAGS: -lpcap 31 #cgo openbsd LDFLAGS: -lpcap 32 #cgo netbsd LDFLAGS: -lpcap 33 #cgo darwin LDFLAGS: -lpcap 34 #include <stdlib.h> 35 #include <pcap.h> 36 #include <stdint.h> 37 #include <poll.h> 38 39 // Some old versions of pcap don't define this constant. 40 #ifndef PCAP_NETMASK_UNKNOWN 41 #define PCAP_NETMASK_UNKNOWN 0xffffffff 42 #endif 43 44 // libpcap doesn't actually export its version in a #define-guardable way, 45 // so we have to use other defined things to differentiate versions. 46 // We assume at least libpcap v1.1 at the moment. 47 // See http://upstream-tracker.org/versions/libpcap.html 48 49 #ifndef PCAP_ERROR_TSTAMP_PRECISION_NOTSUP // < v1.5 50 #define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12 51 52 int pcap_set_immediate_mode(pcap_t *p, int mode) { 53 return PCAP_ERROR; 54 } 55 56 // libpcap version < v1.5 doesn't have timestamp precision (everything is microsecond) 57 // 58 // This means *_tstamp_* functions and macros are missing. Therefore, we emulate these 59 // functions here and pretend the setting the precision works. This is actually the way 60 // the pcap_open_offline_with_tstamp_precision works, because it doesn't return an error 61 // if it was not possible to set the precision, which depends on support by the given file. 62 // => The rest of the functions always pretend as if they could set nano precision and 63 // verify the actual precision with pcap_get_tstamp_precision, which is emulated for <v1.5 64 // to always return micro resolution. 65 66 #define PCAP_TSTAMP_PRECISION_MICRO 0 67 #define PCAP_TSTAMP_PRECISION_NANO 1 68 69 pcap_t *pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision, 70 char *errbuf) { 71 return pcap_open_offline(fname, errbuf); 72 } 73 74 pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision, 75 char *errbuf) { 76 return pcap_fopen_offline(fp, errbuf); 77 } 78 79 int pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision) { 80 if (tstamp_precision == PCAP_TSTAMP_PRECISION_MICRO) 81 return 0; 82 return PCAP_ERROR_TSTAMP_PRECISION_NOTSUP; 83 } 84 85 int pcap_get_tstamp_precision(pcap_t *p) { 86 return PCAP_TSTAMP_PRECISION_MICRO; 87 } 88 89 #ifndef PCAP_TSTAMP_HOST // < v1.2 90 91 int pcap_set_tstamp_type(pcap_t* p, int t) { return -1; } 92 int pcap_list_tstamp_types(pcap_t* p, int** t) { return 0; } 93 void pcap_free_tstamp_types(int *tstamp_types) {} 94 const char* pcap_tstamp_type_val_to_name(int t) { 95 return "pcap timestamp types not supported"; 96 } 97 int pcap_tstamp_type_name_to_val(const char* t) { 98 return PCAP_ERROR; 99 } 100 101 #endif // < v1.2 102 #endif // < v1.5 103 104 #ifndef PCAP_ERROR_PROMISC_PERM_DENIED 105 #define PCAP_ERROR_PROMISC_PERM_DENIED -11 106 #endif 107 108 // Windows, Macs, and Linux all use different time types. Joy. 109 #ifdef __APPLE__ 110 #define gopacket_time_secs_t __darwin_time_t 111 #define gopacket_time_usecs_t __darwin_suseconds_t 112 #elif __ANDROID__ 113 #define gopacket_time_secs_t __kernel_time_t 114 #define gopacket_time_usecs_t __kernel_suseconds_t 115 #elif __GLIBC__ 116 #define gopacket_time_secs_t __time_t 117 #define gopacket_time_usecs_t __suseconds_t 118 #else // Some form of linux/bsd/etc... 119 #include <sys/param.h> 120 #ifdef __OpenBSD__ 121 #define gopacket_time_secs_t u_int32_t 122 #define gopacket_time_usecs_t u_int32_t 123 #else 124 #define gopacket_time_secs_t time_t 125 #define gopacket_time_usecs_t suseconds_t 126 #endif 127 #endif 128 129 // The things we do to avoid pointers escaping to the heap... 130 // According to https://github.com/the-tcpdump-group/libpcap/blob/1131a7c26c6f4d4772e4a2beeaf7212f4dea74ac/pcap.c#L398-L406 , 131 // the return value of pcap_next_ex could be greater than 1 for success. 132 // Let's just make it 1 if it comes bigger than 1. 133 int pcap_next_ex_escaping(pcap_t *p, uintptr_t pkt_hdr, uintptr_t pkt_data) { 134 int ex = pcap_next_ex(p, (struct pcap_pkthdr**)(pkt_hdr), (const u_char**)(pkt_data)); 135 if (ex > 1) { 136 ex = 1; 137 } 138 return ex; 139 } 140 141 int pcap_offline_filter_escaping(struct bpf_program *fp, uintptr_t pkt_hdr, uintptr_t pkt) { 142 return pcap_offline_filter(fp, (struct pcap_pkthdr*)(pkt_hdr), (const u_char*)(pkt)); 143 } 144 145 // pcap_wait returns when the next packet is available or the timeout expires. 146 // Since it uses pcap_get_selectable_fd, it will not work in Windows. 147 int pcap_wait(pcap_t *p, int msec) { 148 struct pollfd fds[1]; 149 int fd; 150 151 fd = pcap_get_selectable_fd(p); 152 if(fd < 0) { 153 return fd; 154 } 155 156 fds[0].fd = fd; 157 fds[0].events = POLLIN; 158 159 if(msec != 0) { 160 return poll(fds, 1, msec); 161 } 162 163 // block indefinitely if no timeout provided 164 return poll(fds, 1, -1); 165 } 166 167 */ 168 import "C" 169 170 const errorBufferSize = C.PCAP_ERRBUF_SIZE 171 172 const ( 173 pcapErrorNotActivated = C.PCAP_ERROR_NOT_ACTIVATED 174 pcapErrorActivated = C.PCAP_ERROR_ACTIVATED 175 pcapWarningPromisc = C.PCAP_WARNING_PROMISC_NOTSUP 176 pcapErrorNoSuchDevice = C.PCAP_ERROR_NO_SUCH_DEVICE 177 pcapErrorDenied = C.PCAP_ERROR_PERM_DENIED 178 pcapErrorNotUp = C.PCAP_ERROR_IFACE_NOT_UP 179 pcapWarning = C.PCAP_WARNING 180 pcapError = C.PCAP_ERROR 181 pcapDIN = C.PCAP_D_IN 182 pcapDOUT = C.PCAP_D_OUT 183 pcapDINOUT = C.PCAP_D_INOUT 184 pcapNetmaskUnknown = C.PCAP_NETMASK_UNKNOWN 185 pcapTstampPrecisionMicro = C.PCAP_TSTAMP_PRECISION_MICRO 186 pcapTstampPrecisionNano = C.PCAP_TSTAMP_PRECISION_NANO 187 ) 188 189 type pcapPkthdr C.struct_pcap_pkthdr 190 type pcapTPtr *C.struct_pcap 191 type pcapBpfProgram C.struct_bpf_program 192 193 func (h *pcapPkthdr) getSec() int64 { 194 return int64(h.ts.tv_sec) 195 } 196 197 func (h *pcapPkthdr) getUsec() int64 { 198 return int64(h.ts.tv_usec) 199 } 200 201 func (h *pcapPkthdr) getLen() int { 202 return int(h.len) 203 } 204 205 func (h *pcapPkthdr) getCaplen() int { 206 return int(h.caplen) 207 } 208 209 func pcapGetTstampPrecision(cptr pcapTPtr) int { 210 return int(C.pcap_get_tstamp_precision(cptr)) 211 } 212 213 func pcapSetTstampPrecision(cptr pcapTPtr, precision int) error { 214 ret := C.pcap_set_tstamp_precision(cptr, C.int(precision)) 215 if ret < 0 { 216 return errors.New(C.GoString(C.pcap_geterr(cptr))) 217 } 218 return nil 219 } 220 221 func statusError(status C.int) error { 222 return errors.New(C.GoString(C.pcap_statustostr(status))) 223 } 224 225 func pcapOpenLive(device string, snaplen int, pro int, timeout int) (*Handle, error) { 226 buf := (*C.char)(C.calloc(errorBufferSize, 1)) 227 defer C.free(unsafe.Pointer(buf)) 228 229 dev := C.CString(device) 230 defer C.free(unsafe.Pointer(dev)) 231 232 cptr := C.pcap_open_live(dev, C.int(snaplen), C.int(pro), C.int(timeout), buf) 233 if cptr == nil { 234 return nil, errors.New(C.GoString(buf)) 235 } 236 return &Handle{cptr: cptr}, nil 237 } 238 239 func openOffline(file string) (handle *Handle, err error) { 240 buf := (*C.char)(C.calloc(errorBufferSize, 1)) 241 defer C.free(unsafe.Pointer(buf)) 242 cf := C.CString(file) 243 defer C.free(unsafe.Pointer(cf)) 244 245 cptr := C.pcap_open_offline_with_tstamp_precision(cf, C.PCAP_TSTAMP_PRECISION_NANO, buf) 246 if cptr == nil { 247 return nil, errors.New(C.GoString(buf)) 248 } 249 return &Handle{cptr: cptr}, nil 250 } 251 252 func (p *Handle) pcapClose() { 253 if p.cptr != nil { 254 C.pcap_close(p.cptr) 255 } 256 p.cptr = nil 257 } 258 259 func (p *Handle) pcapGeterr() error { 260 return errors.New(C.GoString(C.pcap_geterr(p.cptr))) 261 } 262 263 func (p *Handle) pcapStats() (*Stats, error) { 264 var cstats C.struct_pcap_stat 265 if C.pcap_stats(p.cptr, &cstats) < 0 { 266 return nil, p.pcapGeterr() 267 } 268 return &Stats{ 269 PacketsReceived: int(cstats.ps_recv), 270 PacketsDropped: int(cstats.ps_drop), 271 PacketsIfDropped: int(cstats.ps_ifdrop), 272 }, nil 273 } 274 275 // for libpcap < 1.8 pcap_compile is NOT thread-safe, so protect it. 276 var pcapCompileMu sync.Mutex 277 278 func (p *Handle) pcapCompile(expr string, maskp uint32) (pcapBpfProgram, error) { 279 var bpf pcapBpfProgram 280 cexpr := C.CString(expr) 281 defer C.free(unsafe.Pointer(cexpr)) 282 283 pcapCompileMu.Lock() 284 defer pcapCompileMu.Unlock() 285 if C.pcap_compile(p.cptr, (*C.struct_bpf_program)(&bpf), cexpr, 1, C.bpf_u_int32(maskp)) < 0 { 286 return bpf, p.pcapGeterr() 287 } 288 return bpf, nil 289 } 290 291 func (p pcapBpfProgram) free() { 292 C.pcap_freecode((*C.struct_bpf_program)(&p)) 293 } 294 295 func (p pcapBpfProgram) toBPFInstruction() []BPFInstruction { 296 bpfInsn := (*[bpfInstructionBufferSize]C.struct_bpf_insn)(unsafe.Pointer(p.bf_insns))[0:p.bf_len:p.bf_len] 297 bpfInstruction := make([]BPFInstruction, len(bpfInsn), len(bpfInsn)) 298 299 for i, v := range bpfInsn { 300 bpfInstruction[i].Code = uint16(v.code) 301 bpfInstruction[i].Jt = uint8(v.jt) 302 bpfInstruction[i].Jf = uint8(v.jf) 303 bpfInstruction[i].K = uint32(v.k) 304 } 305 return bpfInstruction 306 } 307 308 func pcapBpfProgramFromInstructions(bpfInstructions []BPFInstruction) pcapBpfProgram { 309 var bpf pcapBpfProgram 310 bpf.bf_len = C.u_int(len(bpfInstructions)) 311 cbpfInsns := C.calloc(C.size_t(len(bpfInstructions)), C.size_t(unsafe.Sizeof(bpfInstructions[0]))) 312 gbpfInsns := (*[bpfInstructionBufferSize]C.struct_bpf_insn)(cbpfInsns) 313 314 for i, v := range bpfInstructions { 315 gbpfInsns[i].code = C.u_short(v.Code) 316 gbpfInsns[i].jt = C.u_char(v.Jt) 317 gbpfInsns[i].jf = C.u_char(v.Jf) 318 gbpfInsns[i].k = C.bpf_u_int32(v.K) 319 } 320 321 bpf.bf_insns = (*C.struct_bpf_insn)(cbpfInsns) 322 return bpf 323 } 324 325 func pcapLookupnet(device string) (netp, maskp uint32, err error) { 326 errorBuf := (*C.char)(C.calloc(errorBufferSize, 1)) 327 defer C.free(unsafe.Pointer(errorBuf)) 328 dev := C.CString(device) 329 defer C.free(unsafe.Pointer(dev)) 330 if C.pcap_lookupnet( 331 dev, 332 (*C.bpf_u_int32)(unsafe.Pointer(&netp)), 333 (*C.bpf_u_int32)(unsafe.Pointer(&maskp)), 334 errorBuf, 335 ) < 0 { 336 return 0, 0, errors.New(C.GoString(errorBuf)) 337 // We can't lookup the network, but that could be because the interface 338 // doesn't have an IPv4. 339 } 340 return 341 } 342 343 func (b *BPF) pcapOfflineFilter(ci gopacket.CaptureInfo, data []byte) bool { 344 hdr := (*C.struct_pcap_pkthdr)(&b.hdr) 345 hdr.ts.tv_sec = C.gopacket_time_secs_t(ci.Timestamp.Unix()) 346 hdr.ts.tv_usec = C.gopacket_time_usecs_t(ci.Timestamp.Nanosecond() / 1000) 347 hdr.caplen = C.bpf_u_int32(len(data)) // Trust actual length over ci.Length. 348 hdr.len = C.bpf_u_int32(ci.Length) 349 dataptr := (*C.u_char)(unsafe.Pointer(&data[0])) 350 return C.pcap_offline_filter_escaping((*C.struct_bpf_program)(&b.bpf.bpf), 351 C.uintptr_t(uintptr(unsafe.Pointer(hdr))), 352 C.uintptr_t(uintptr(unsafe.Pointer(dataptr)))) != 0 353 } 354 355 func (p *Handle) pcapSetfilter(bpf pcapBpfProgram) error { 356 if C.pcap_setfilter(p.cptr, (*C.struct_bpf_program)(&bpf)) < 0 { 357 return p.pcapGeterr() 358 } 359 return nil 360 } 361 362 func (p *Handle) pcapListDatalinks() (datalinks []Datalink, err error) { 363 var dltbuf *C.int 364 365 n := int(C.pcap_list_datalinks(p.cptr, &dltbuf)) 366 if n < 0 { 367 return nil, p.pcapGeterr() 368 } 369 370 defer C.pcap_free_datalinks(dltbuf) 371 372 datalinks = make([]Datalink, n) 373 374 dltArray := (*[1 << 28]C.int)(unsafe.Pointer(dltbuf)) 375 376 for i := 0; i < n; i++ { 377 datalinks[i].Name = pcapDatalinkValToName(int((*dltArray)[i])) 378 datalinks[i].Description = pcapDatalinkValToDescription(int((*dltArray)[i])) 379 } 380 381 return datalinks, nil 382 } 383 384 func pcapOpenDead(linkType layers.LinkType, captureLength int) (*Handle, error) { 385 cptr := C.pcap_open_dead(C.int(linkType), C.int(captureLength)) 386 if cptr == nil { 387 return nil, errors.New("error opening dead capture") 388 } 389 390 return &Handle{cptr: cptr}, nil 391 } 392 393 func (p *Handle) pcapNextPacketEx() NextError { 394 // This horrible magic allows us to pass a ptr-to-ptr to pcap_next_ex 395 // without causing that ptr-to-ptr to itself be allocated on the heap. 396 // Since Handle itself survives through the duration of the pcap_next_ex 397 // call, this should be perfectly safe for GC stuff, etc. 398 399 return NextError(C.pcap_next_ex_escaping(p.cptr, C.uintptr_t(uintptr(unsafe.Pointer(&p.pkthdr))), C.uintptr_t(uintptr(unsafe.Pointer(&p.bufptr))))) 400 } 401 402 func (p *Handle) pcapDatalink() layers.LinkType { 403 return layers.LinkType(C.pcap_datalink(p.cptr)) 404 } 405 406 func (p *Handle) pcapSetDatalink(dlt layers.LinkType) error { 407 if C.pcap_set_datalink(p.cptr, C.int(dlt)) < 0 { 408 return p.pcapGeterr() 409 } 410 return nil 411 } 412 413 func pcapDatalinkValToName(dlt int) string { 414 return C.GoString(C.pcap_datalink_val_to_name(C.int(dlt))) 415 } 416 417 func pcapDatalinkValToDescription(dlt int) string { 418 return C.GoString(C.pcap_datalink_val_to_description(C.int(dlt))) 419 } 420 421 func pcapDatalinkNameToVal(name string) int { 422 cptr := C.CString(name) 423 defer C.free(unsafe.Pointer(cptr)) 424 return int(C.pcap_datalink_name_to_val(cptr)) 425 } 426 427 func pcapLibVersion() string { 428 return C.GoString(C.pcap_lib_version()) 429 } 430 431 func (p *Handle) isOpen() bool { 432 return p.cptr != nil 433 } 434 435 type pcapDevices struct { 436 all, cur *C.pcap_if_t 437 } 438 439 func (p pcapDevices) free() { 440 C.pcap_freealldevs((*C.pcap_if_t)(p.all)) 441 } 442 443 func (p *pcapDevices) next() bool { 444 if p.cur == nil { 445 p.cur = p.all 446 if p.cur == nil { 447 return false 448 } 449 return true 450 } 451 if p.cur.next == nil { 452 return false 453 } 454 p.cur = p.cur.next 455 return true 456 } 457 458 func (p pcapDevices) name() string { 459 return C.GoString(p.cur.name) 460 } 461 462 func (p pcapDevices) description() string { 463 return C.GoString(p.cur.description) 464 } 465 466 func (p pcapDevices) flags() uint32 { 467 return uint32(p.cur.flags) 468 } 469 470 type pcapAddresses struct { 471 all, cur *C.pcap_addr_t 472 } 473 474 func (p *pcapAddresses) next() bool { 475 if p.cur == nil { 476 p.cur = p.all 477 if p.cur == nil { 478 return false 479 } 480 return true 481 } 482 if p.cur.next == nil { 483 return false 484 } 485 p.cur = p.cur.next 486 return true 487 } 488 489 func (p pcapAddresses) addr() *syscall.RawSockaddr { 490 return (*syscall.RawSockaddr)(unsafe.Pointer(p.cur.addr)) 491 } 492 493 func (p pcapAddresses) netmask() *syscall.RawSockaddr { 494 return (*syscall.RawSockaddr)(unsafe.Pointer(p.cur.netmask)) 495 } 496 497 func (p pcapAddresses) broadaddr() *syscall.RawSockaddr { 498 return (*syscall.RawSockaddr)(unsafe.Pointer(p.cur.broadaddr)) 499 } 500 501 func (p pcapAddresses) dstaddr() *syscall.RawSockaddr { 502 return (*syscall.RawSockaddr)(unsafe.Pointer(p.cur.dstaddr)) 503 } 504 505 func (p pcapDevices) addresses() pcapAddresses { 506 return pcapAddresses{all: p.cur.addresses} 507 } 508 509 func pcapFindAllDevs() (pcapDevices, error) { 510 var buf *C.char 511 buf = (*C.char)(C.calloc(errorBufferSize, 1)) 512 defer C.free(unsafe.Pointer(buf)) 513 var alldevsp pcapDevices 514 515 if C.pcap_findalldevs((**C.pcap_if_t)(&alldevsp.all), buf) < 0 { 516 return pcapDevices{}, errors.New(C.GoString(buf)) 517 } 518 return alldevsp, nil 519 } 520 521 func (p *Handle) pcapSendpacket(data []byte) error { 522 if C.pcap_sendpacket(p.cptr, (*C.u_char)(&data[0]), (C.int)(len(data))) < 0 { 523 return p.pcapGeterr() 524 } 525 return nil 526 } 527 528 func (p *Handle) pcapSetdirection(direction Direction) error { 529 if status := C.pcap_setdirection(p.cptr, (C.pcap_direction_t)(direction)); status < 0 { 530 return statusError(status) 531 } 532 return nil 533 } 534 535 func (p *Handle) pcapSnapshot() int { 536 return int(C.pcap_snapshot(p.cptr)) 537 } 538 539 func (t TimestampSource) pcapTstampTypeValToName() string { 540 return C.GoString(C.pcap_tstamp_type_val_to_name(C.int(t))) 541 } 542 543 func pcapTstampTypeNameToVal(s string) (TimestampSource, error) { 544 cs := C.CString(s) 545 defer C.free(unsafe.Pointer(cs)) 546 t := C.pcap_tstamp_type_name_to_val(cs) 547 if t < 0 { 548 return 0, statusError(t) 549 } 550 return TimestampSource(t), nil 551 } 552 553 func (p *InactiveHandle) pcapGeterr() error { 554 return errors.New(C.GoString(C.pcap_geterr(p.cptr))) 555 } 556 557 func (p *InactiveHandle) pcapActivate() (*Handle, activateError) { 558 ret := activateError(C.pcap_activate(p.cptr)) 559 if ret != aeNoError { 560 return nil, ret 561 } 562 h := &Handle{ 563 cptr: p.cptr, 564 } 565 p.cptr = nil 566 return h, ret 567 } 568 569 func (p *InactiveHandle) pcapClose() { 570 if p.cptr != nil { 571 C.pcap_close(p.cptr) 572 } 573 } 574 575 func pcapCreate(device string) (*InactiveHandle, error) { 576 buf := (*C.char)(C.calloc(errorBufferSize, 1)) 577 defer C.free(unsafe.Pointer(buf)) 578 dev := C.CString(device) 579 defer C.free(unsafe.Pointer(dev)) 580 581 cptr := C.pcap_create(dev, buf) 582 if cptr == nil { 583 return nil, errors.New(C.GoString(buf)) 584 } 585 return &InactiveHandle{cptr: cptr}, nil 586 } 587 588 func (p *InactiveHandle) pcapSetSnaplen(snaplen int) error { 589 if status := C.pcap_set_snaplen(p.cptr, C.int(snaplen)); status < 0 { 590 return statusError(status) 591 } 592 return nil 593 } 594 595 func (p *InactiveHandle) pcapSetPromisc(promisc bool) error { 596 var pro C.int 597 if promisc { 598 pro = 1 599 } 600 if status := C.pcap_set_promisc(p.cptr, pro); status < 0 { 601 return statusError(status) 602 } 603 return nil 604 } 605 606 func (p *InactiveHandle) pcapSetTimeout(timeout time.Duration) error { 607 if status := C.pcap_set_timeout(p.cptr, C.int(timeoutMillis(timeout))); status < 0 { 608 return statusError(status) 609 } 610 return nil 611 } 612 613 func (p *InactiveHandle) pcapListTstampTypes() (out []TimestampSource) { 614 var types *C.int 615 n := int(C.pcap_list_tstamp_types(p.cptr, &types)) 616 if n < 0 { 617 return // public interface doesn't have error :( 618 } 619 defer C.pcap_free_tstamp_types(types) 620 typesArray := (*[1 << 28]C.int)(unsafe.Pointer(types)) 621 for i := 0; i < n; i++ { 622 out = append(out, TimestampSource((*typesArray)[i])) 623 } 624 return 625 } 626 627 func (p *InactiveHandle) pcapSetTstampType(t TimestampSource) error { 628 if status := C.pcap_set_tstamp_type(p.cptr, C.int(t)); status < 0 { 629 return statusError(status) 630 } 631 return nil 632 } 633 634 func (p *InactiveHandle) pcapSetRfmon(monitor bool) error { 635 var mon C.int 636 if monitor { 637 mon = 1 638 } 639 switch canset := C.pcap_can_set_rfmon(p.cptr); canset { 640 case 0: 641 return CannotSetRFMon 642 case 1: 643 // success 644 default: 645 return statusError(canset) 646 } 647 if status := C.pcap_set_rfmon(p.cptr, mon); status != 0 { 648 return statusError(status) 649 } 650 return nil 651 } 652 653 func (p *InactiveHandle) pcapSetBufferSize(bufferSize int) error { 654 if status := C.pcap_set_buffer_size(p.cptr, C.int(bufferSize)); status < 0 { 655 return statusError(status) 656 } 657 return nil 658 } 659 660 func (p *InactiveHandle) pcapSetImmediateMode(mode bool) error { 661 var md C.int 662 if mode { 663 md = 1 664 } 665 if status := C.pcap_set_immediate_mode(p.cptr, md); status < 0 { 666 return statusError(status) 667 } 668 return nil 669 } 670 671 func (p *Handle) setNonBlocking() error { 672 buf := (*C.char)(C.calloc(errorBufferSize, 1)) 673 defer C.free(unsafe.Pointer(buf)) 674 675 // Change the device to non-blocking, we'll use pcap_wait to wait until the 676 // handle is ready to read. 677 if v := C.pcap_setnonblock(p.cptr, 1, buf); v < -1 { 678 return errors.New(C.GoString(buf)) 679 } 680 681 return nil 682 } 683 684 // waitForPacket waits for a packet or for the timeout to expire. 685 func (p *Handle) waitForPacket() { 686 // According to pcap_get_selectable_fd() man page, there are some cases where it will 687 // return a file descriptor, but a simple call of select() or poll() will not indicate 688 // that the descriptor is readable until a full buffer's worth of packets is received, 689 // so the call must have a timeout less than *or equal* to the packet buffer timeout. 690 // The packet buffer timeout is set to timeoutMillis(p.timeout) in pcapOpenLive(), 691 // so we should be fine to use it here too. 692 C.pcap_wait(p.cptr, C.int(timeoutMillis(p.timeout))) 693 } 694 695 // openOfflineFile returns contents of input file as a *Handle. 696 func openOfflineFile(file *os.File) (handle *Handle, err error) { 697 buf := (*C.char)(C.calloc(errorBufferSize, 1)) 698 defer C.free(unsafe.Pointer(buf)) 699 cmode := C.CString("rb") 700 defer C.free(unsafe.Pointer(cmode)) 701 cf := C.fdopen(C.int(file.Fd()), cmode) 702 703 cptr := C.pcap_fopen_offline_with_tstamp_precision(cf, C.PCAP_TSTAMP_PRECISION_NANO, buf) 704 if cptr == nil { 705 return nil, errors.New(C.GoString(buf)) 706 } 707 return &Handle{cptr: cptr}, nil 708 }