github.com/gopacket/gopacket@v1.1.0/pcap/pcap_windows.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 "os" 14 "runtime" 15 "sync" 16 "syscall" 17 "time" 18 "unsafe" 19 20 "github.com/gopacket/gopacket" 21 "github.com/gopacket/gopacket/layers" 22 "golang.org/x/sys/windows" 23 ) 24 25 var pcapLoaded = false 26 27 const npcapPath = "\\Npcap" 28 29 func initDllPath(kernel32 syscall.Handle) { 30 setDllDirectory, err := syscall.GetProcAddress(kernel32, "SetDllDirectoryA") 31 if err != nil { 32 // we can't do anything since SetDllDirectoryA is missing - fall back to use first wpcap.dll we encounter 33 return 34 } 35 getSystemDirectory, err := syscall.GetProcAddress(kernel32, "GetSystemDirectoryA") 36 if err != nil { 37 // we can't do anything since SetDllDirectoryA is missing - fall back to use first wpcap.dll we encounter 38 return 39 } 40 buf := make([]byte, 4096) 41 r, _, _ := syscall.Syscall(getSystemDirectory, 2, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0) 42 if r == 0 || r > 4096-uintptr(len(npcapPath))-1 { 43 // we can't do anything since SetDllDirectoryA is missing - fall back to use first wpcap.dll we encounter 44 return 45 } 46 copy(buf[r:], npcapPath) 47 _, _, _ = syscall.Syscall(setDllDirectory, 1, uintptr(unsafe.Pointer(&buf[0])), 0, 0) 48 // ignore errors here - we just fallback to load wpcap.dll from default locations 49 } 50 51 // loadedDllPath will hold the full pathname of the loaded wpcap.dll after init if possible 52 var loadedDllPath = "wpcap.dll" 53 54 func initLoadedDllPath(kernel32 syscall.Handle) { 55 getModuleFileName, err := syscall.GetProcAddress(kernel32, "GetModuleFileNameA") 56 if err != nil { 57 // we can't get the filename of the loaded module in this case - just leave default of wpcap.dll 58 return 59 } 60 buf := make([]byte, 4096) 61 r, _, _ := syscall.Syscall(getModuleFileName, 3, uintptr(wpcapHandle), uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf))) 62 if r == 0 { 63 // we can't get the filename of the loaded module in this case - just leave default of wpcap.dll 64 return 65 } 66 loadedDllPath = string(buf[:int(r)]) 67 } 68 69 func mustLoad(fun string) uintptr { 70 addr, err := windows.GetProcAddress(wpcapHandle, fun) 71 if err != nil { 72 panic(fmt.Sprintf("Couldn't load function %s from %s", fun, loadedDllPath)) 73 } 74 return addr 75 } 76 77 func mightLoad(fun string) uintptr { 78 addr, err := windows.GetProcAddress(wpcapHandle, fun) 79 if err != nil { 80 return 0 81 } 82 return addr 83 } 84 85 func byteSliceToString(bval []byte) string { 86 for i := range bval { 87 if bval[i] == 0 { 88 return string(bval[:i]) 89 } 90 } 91 return string(bval[:]) 92 } 93 94 // bytePtrToString returns a string copied from pointer to a null terminated byte array 95 // WARNING: ONLY SAFE WITH IF r POINTS TO C MEMORY! 96 // govet will complain about this function for the reason stated above 97 func bytePtrToString(r uintptr) string { 98 if r == 0 { 99 return "" 100 } 101 bval := (*[1 << 30]byte)(unsafe.Pointer(r)) 102 return byteSliceToString(bval[:]) 103 } 104 105 var wpcapHandle windows.Handle 106 var msvcrtHandle syscall.Handle 107 var ( 108 callocPtr, 109 pcapStrerrorPtr, 110 pcapStatustostrPtr, 111 pcapOpenLivePtr, 112 pcapOpenOfflinePtr, 113 pcapClosePtr, 114 pcapGeterrPtr, 115 pcapStatsPtr, 116 pcapCompilePtr, 117 pcapFreecodePtr, 118 pcapLookupnetPtr, 119 pcapOfflineFilterPtr, 120 pcapSetfilterPtr, 121 pcapListDatalinksPtr, 122 pcapFreeDatalinksPtr, 123 pcapDatalinkValToNamePtr, 124 pcapDatalinkValToDescriptionPtr, 125 pcapOpenDeadPtr, 126 pcapNextExPtr, 127 pcapDatalinkPtr, 128 pcapSetDatalinkPtr, 129 pcapDatalinkNameToValPtr, 130 pcapLibVersionPtr, 131 pcapFreealldevsPtr, 132 pcapFindalldevsPtr, 133 pcapSendpacketPtr, 134 pcapSetdirectionPtr, 135 pcapSnapshotPtr, 136 pcapTstampTypeValToNamePtr, 137 pcapTstampTypeNameToValPtr, 138 pcapListTstampTypesPtr, 139 pcapFreeTstampTypesPtr, 140 pcapSetTstampTypePtr, 141 pcapGetTstampPrecisionPtr, 142 pcapSetTstampPrecisionPtr, 143 pcapOpenOfflineWithTstampPrecisionPtr, 144 pcapHOpenOfflineWithTstampPrecisionPtr, 145 pcapActivatePtr, 146 pcapCreatePtr, 147 pcapSetSnaplenPtr, 148 pcapSetPromiscPtr, 149 pcapSetTimeoutPtr, 150 pcapCanSetRfmonPtr, 151 pcapSetRfmonPtr, 152 pcapSetBufferSizePtr, 153 pcapSetImmediateModePtr, 154 pcapHopenOfflinePtr uintptr 155 ) 156 157 func init() { 158 LoadWinPCAP() 159 } 160 161 // LoadWinPCAP attempts to dynamically load the wpcap DLL and resolve necessary functions 162 func LoadWinPCAP() error { 163 if pcapLoaded { 164 return nil 165 } 166 167 kernel32, err := syscall.LoadLibrary("kernel32.dll") 168 if err != nil { 169 return fmt.Errorf("couldn't load kernel32.dll") 170 } 171 defer syscall.FreeLibrary(kernel32) 172 173 initDllPath(kernel32) 174 175 if haveSearch, _ := syscall.GetProcAddress(kernel32, "AddDllDirectory"); haveSearch != 0 { 176 // if AddDllDirectory is present, we can use LOAD_LIBRARY_* stuff with LoadLibraryEx to avoid wpcap.dll hijacking 177 // see: https://msdn.microsoft.com/en-us/library/ff919712%28VS.85%29.aspx 178 const LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400 179 const LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800 180 wpcapHandle, err = windows.LoadLibraryEx("wpcap.dll", 0, LOAD_LIBRARY_SEARCH_USER_DIRS|LOAD_LIBRARY_SEARCH_SYSTEM32) 181 if err != nil { 182 return fmt.Errorf("couldn't load wpcap.dll") 183 } 184 } else { 185 // otherwise fall back to load it with the unsafe search cause by SetDllDirectory 186 wpcapHandle, err = windows.LoadLibrary("wpcap.dll") 187 if err != nil { 188 return fmt.Errorf("couldn't load wpcap.dll") 189 } 190 } 191 initLoadedDllPath(kernel32) 192 msvcrtHandle, err = syscall.LoadLibrary("msvcrt.dll") 193 if err != nil { 194 return fmt.Errorf("couldn't load msvcrt.dll") 195 } 196 callocPtr, err = syscall.GetProcAddress(msvcrtHandle, "calloc") 197 if err != nil { 198 return fmt.Errorf("couldn't get calloc function") 199 } 200 201 pcapStrerrorPtr = mustLoad("pcap_strerror") 202 pcapStatustostrPtr = mightLoad("pcap_statustostr") // not available on winpcap 203 pcapOpenLivePtr = mustLoad("pcap_open_live") 204 pcapOpenOfflinePtr = mustLoad("pcap_open_offline") 205 pcapClosePtr = mustLoad("pcap_close") 206 pcapGeterrPtr = mustLoad("pcap_geterr") 207 pcapStatsPtr = mustLoad("pcap_stats") 208 pcapCompilePtr = mustLoad("pcap_compile") 209 pcapFreecodePtr = mustLoad("pcap_freecode") 210 pcapLookupnetPtr = mustLoad("pcap_lookupnet") 211 pcapOfflineFilterPtr = mustLoad("pcap_offline_filter") 212 pcapSetfilterPtr = mustLoad("pcap_setfilter") 213 pcapListDatalinksPtr = mustLoad("pcap_list_datalinks") 214 pcapFreeDatalinksPtr = mustLoad("pcap_free_datalinks") 215 pcapDatalinkValToNamePtr = mustLoad("pcap_datalink_val_to_name") 216 pcapDatalinkValToDescriptionPtr = mustLoad("pcap_datalink_val_to_description") 217 pcapOpenDeadPtr = mustLoad("pcap_open_dead") 218 pcapNextExPtr = mustLoad("pcap_next_ex") 219 pcapDatalinkPtr = mustLoad("pcap_datalink") 220 pcapSetDatalinkPtr = mustLoad("pcap_set_datalink") 221 pcapDatalinkNameToValPtr = mustLoad("pcap_datalink_name_to_val") 222 pcapLibVersionPtr = mustLoad("pcap_lib_version") 223 pcapFreealldevsPtr = mustLoad("pcap_freealldevs") 224 pcapFindalldevsPtr = mustLoad("pcap_findalldevs") 225 pcapSendpacketPtr = mustLoad("pcap_sendpacket") 226 pcapSetdirectionPtr = mustLoad("pcap_setdirection") 227 pcapSnapshotPtr = mustLoad("pcap_snapshot") 228 //libpcap <1.2 doesn't have pcap_*_tstamp_* functions 229 pcapTstampTypeValToNamePtr = mightLoad("pcap_tstamp_type_val_to_name") 230 pcapTstampTypeNameToValPtr = mightLoad("pcap_tstamp_type_name_to_val") 231 pcapListTstampTypesPtr = mightLoad("pcap_list_tstamp_types") 232 pcapFreeTstampTypesPtr = mightLoad("pcap_free_tstamp_types") 233 pcapSetTstampTypePtr = mightLoad("pcap_set_tstamp_type") 234 pcapGetTstampPrecisionPtr = mightLoad("pcap_get_tstamp_precision") 235 pcapSetTstampPrecisionPtr = mightLoad("pcap_set_tstamp_precision") 236 pcapOpenOfflineWithTstampPrecisionPtr = mightLoad("pcap_open_offline_with_tstamp_precision") 237 pcapHOpenOfflineWithTstampPrecisionPtr = mightLoad("pcap_hopen_offline_with_tstamp_precision") 238 pcapActivatePtr = mustLoad("pcap_activate") 239 pcapCreatePtr = mustLoad("pcap_create") 240 pcapSetSnaplenPtr = mustLoad("pcap_set_snaplen") 241 pcapSetPromiscPtr = mustLoad("pcap_set_promisc") 242 pcapSetTimeoutPtr = mustLoad("pcap_set_timeout") 243 //winpcap does not support rfmon 244 pcapCanSetRfmonPtr = mightLoad("pcap_can_set_rfmon") 245 pcapSetRfmonPtr = mightLoad("pcap_set_rfmon") 246 pcapSetBufferSizePtr = mustLoad("pcap_set_buffer_size") 247 //libpcap <1.5 does not have pcap_set_immediate_mode 248 pcapSetImmediateModePtr = mightLoad("pcap_set_immediate_mode") 249 pcapHopenOfflinePtr = mustLoad("pcap_hopen_offline") 250 251 pcapLoaded = true 252 return nil 253 } 254 255 func (h *pcapPkthdr) getSec() int64 { 256 return int64(h.Ts.Sec) 257 } 258 259 func (h *pcapPkthdr) getUsec() int64 { 260 return int64(h.Ts.Usec) 261 } 262 263 func (h *pcapPkthdr) getLen() int { 264 return int(h.Len) 265 } 266 267 func (h *pcapPkthdr) getCaplen() int { 268 return int(h.Caplen) 269 } 270 271 func statusError(status pcapCint) error { 272 var ret uintptr 273 if pcapStatustostrPtr == 0 { 274 ret, _, _ = syscall.Syscall(pcapStrerrorPtr, 1, uintptr(status), 0, 0) 275 } else { 276 ret, _, _ = syscall.Syscall(pcapStatustostrPtr, 1, uintptr(status), 0, 0) 277 } 278 return errors.New(bytePtrToString(ret)) 279 } 280 281 func pcapGetTstampPrecision(cptr pcapTPtr) int { 282 if pcapGetTstampPrecisionPtr == 0 { 283 return pcapTstampPrecisionMicro 284 } 285 ret, _, _ := syscall.Syscall(pcapGetTstampPrecisionPtr, 1, uintptr(cptr), 0, 0) 286 return int(pcapCint(ret)) 287 } 288 289 func pcapSetTstampPrecision(cptr pcapTPtr, precision int) error { 290 if pcapSetTstampPrecisionPtr == 0 { 291 return errors.New("Not supported") 292 } 293 ret, _, _ := syscall.Syscall(pcapSetTstampPrecisionPtr, 2, uintptr(cptr), uintptr(precision), 0) 294 if pcapCint(ret) < 0 { 295 return errors.New("Not supported") 296 } 297 return nil 298 } 299 300 func pcapOpenLive(device string, snaplen int, pro int, timeout int) (*Handle, error) { 301 err := LoadWinPCAP() 302 if err != nil { 303 return nil, err 304 } 305 306 buf := make([]byte, errorBufferSize) 307 dev, err := syscall.BytePtrFromString(device) 308 if err != nil { 309 return nil, err 310 } 311 312 cptr, _, _ := syscall.Syscall6(pcapOpenLivePtr, 5, uintptr(unsafe.Pointer(dev)), uintptr(snaplen), uintptr(pro), uintptr(timeout), uintptr(unsafe.Pointer(&buf[0])), 0) 313 314 if cptr == 0 { 315 return nil, errors.New(byteSliceToString(buf)) 316 } 317 return &Handle{cptr: pcapTPtr(cptr)}, nil 318 } 319 320 func openOffline(file string) (handle *Handle, err error) { 321 err = LoadWinPCAP() 322 if err != nil { 323 return nil, err 324 } 325 326 buf := make([]byte, errorBufferSize) 327 f, err := syscall.BytePtrFromString(file) 328 if err != nil { 329 return nil, err 330 } 331 332 var cptr uintptr 333 if pcapOpenOfflineWithTstampPrecisionPtr == 0 { 334 cptr, _, _ = syscall.Syscall(pcapOpenOfflinePtr, 2, uintptr(unsafe.Pointer(f)), uintptr(unsafe.Pointer(&buf[0])), 0) 335 } else { 336 cptr, _, _ = syscall.Syscall(pcapOpenOfflineWithTstampPrecisionPtr, 3, uintptr(unsafe.Pointer(f)), uintptr(pcapTstampPrecisionNano), uintptr(unsafe.Pointer(&buf[0]))) 337 } 338 339 if cptr == 0 { 340 return nil, errors.New(byteSliceToString(buf)) 341 } 342 343 h := &Handle{cptr: pcapTPtr(cptr)} 344 return h, nil 345 } 346 347 func (p *Handle) pcapClose() { 348 if p.cptr != 0 { 349 _, _, _ = syscall.Syscall(pcapClosePtr, 1, uintptr(p.cptr), 0, 0) 350 } 351 p.cptr = 0 352 } 353 354 func (p *Handle) pcapGeterr() error { 355 ret, _, _ := syscall.Syscall(pcapGeterrPtr, 1, uintptr(p.cptr), 0, 0) 356 return errors.New(bytePtrToString(ret)) 357 } 358 359 func (p *Handle) pcapStats() (*Stats, error) { 360 var cstats pcapStats 361 ret, _, _ := syscall.Syscall(pcapStatsPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&cstats)), 0) 362 if pcapCint(ret) < 0 { 363 return nil, p.pcapGeterr() 364 } 365 return &Stats{ 366 PacketsReceived: int(cstats.Recv), 367 PacketsDropped: int(cstats.Drop), 368 PacketsIfDropped: int(cstats.Ifdrop), 369 }, nil 370 } 371 372 // for libpcap < 1.8 pcap_compile is NOT thread-safe, so protect it. 373 var pcapCompileMu sync.Mutex 374 375 func (p *Handle) pcapCompile(expr string, maskp uint32) (pcapBpfProgram, error) { 376 var bpf pcapBpfProgram 377 cexpr, err := syscall.BytePtrFromString(expr) 378 if err != nil { 379 return pcapBpfProgram{}, err 380 } 381 pcapCompileMu.Lock() 382 defer pcapCompileMu.Unlock() 383 res, _, _ := syscall.Syscall6(pcapCompilePtr, 5, uintptr(p.cptr), uintptr(unsafe.Pointer(&bpf)), uintptr(unsafe.Pointer(cexpr)), uintptr(1), uintptr(maskp), 0) 384 if pcapCint(res) < 0 { 385 return bpf, p.pcapGeterr() 386 } 387 return bpf, nil 388 } 389 390 func (p pcapBpfProgram) free() { 391 _, _, _ = syscall.Syscall(pcapFreecodePtr, 1, uintptr(unsafe.Pointer(&p)), 0, 0) 392 } 393 394 func (p pcapBpfProgram) toBPFInstruction() []BPFInstruction { 395 bpfInsn := (*[bpfInstructionBufferSize]pcapBpfInstruction)(unsafe.Pointer(p.Insns))[0:p.Len:p.Len] 396 bpfInstruction := make([]BPFInstruction, len(bpfInsn), len(bpfInsn)) 397 398 for i, v := range bpfInsn { 399 bpfInstruction[i].Code = v.Code 400 bpfInstruction[i].Jt = v.Jt 401 bpfInstruction[i].Jf = v.Jf 402 bpfInstruction[i].K = v.K 403 } 404 return bpfInstruction 405 } 406 407 func pcapBpfProgramFromInstructions(bpfInstructions []BPFInstruction) pcapBpfProgram { 408 var bpf pcapBpfProgram 409 bpf.Len = uint32(len(bpfInstructions)) 410 cbpfInsns, _, _ := syscall.Syscall(callocPtr, 2, uintptr(len(bpfInstructions)), uintptr(unsafe.Sizeof(bpfInstructions[0])), 0) 411 gbpfInsns := (*[bpfInstructionBufferSize]pcapBpfInstruction)(unsafe.Pointer(cbpfInsns)) 412 413 for i, v := range bpfInstructions { 414 gbpfInsns[i].Code = v.Code 415 gbpfInsns[i].Jt = v.Jt 416 gbpfInsns[i].Jf = v.Jf 417 gbpfInsns[i].K = v.K 418 } 419 420 bpf.Insns = (*pcapBpfInstruction)(unsafe.Pointer(cbpfInsns)) 421 return bpf 422 } 423 424 func pcapLookupnet(device string) (netp, maskp uint32, err error) { 425 err = LoadWinPCAP() 426 if err != nil { 427 return 0, 0, err 428 } 429 430 buf := make([]byte, errorBufferSize) 431 dev, err := syscall.BytePtrFromString(device) 432 if err != nil { 433 return 0, 0, err 434 } 435 e, _, _ := syscall.Syscall6(pcapLookupnetPtr, 4, uintptr(unsafe.Pointer(dev)), uintptr(unsafe.Pointer(&netp)), uintptr(unsafe.Pointer(&maskp)), uintptr(unsafe.Pointer(&buf[0])), 0, 0) 436 if pcapCint(e) < 0 { 437 return 0, 0, errors.New(byteSliceToString(buf)) 438 } 439 return 440 } 441 442 func (b *BPF) pcapOfflineFilter(ci gopacket.CaptureInfo, data []byte) bool { 443 var hdr pcapPkthdr 444 hdr.Ts.Sec = int32(ci.Timestamp.Unix()) 445 hdr.Ts.Usec = int32(ci.Timestamp.Nanosecond() / 1000) 446 hdr.Caplen = uint32(len(data)) // Trust actual length over ci.Length. 447 hdr.Len = uint32(ci.Length) 448 e, _, _ := syscall.Syscall(pcapOfflineFilterPtr, 3, uintptr(unsafe.Pointer(&b.bpf.bpf)), uintptr(unsafe.Pointer(&hdr)), uintptr(unsafe.Pointer(&data[0]))) 449 return e != 0 450 } 451 452 func (p *Handle) pcapSetfilter(bpf pcapBpfProgram) error { 453 e, _, _ := syscall.Syscall(pcapSetfilterPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&bpf)), 0) 454 if pcapCint(e) < 0 { 455 return p.pcapGeterr() 456 } 457 return nil 458 } 459 460 func (p *Handle) pcapListDatalinks() (datalinks []Datalink, err error) { 461 var dltbuf *pcapCint 462 ret, _, _ := syscall.Syscall(pcapListDatalinksPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&dltbuf)), 0) 463 464 n := int(pcapCint(ret)) 465 466 if n < 0 { 467 return nil, p.pcapGeterr() 468 } 469 defer syscall.Syscall(pcapFreeDatalinksPtr, 1, uintptr(unsafe.Pointer(dltbuf)), 0, 0) 470 471 datalinks = make([]Datalink, n) 472 473 dltArray := (*[1 << 28]pcapCint)(unsafe.Pointer(dltbuf)) 474 475 for i := 0; i < n; i++ { 476 datalinks[i].Name = pcapDatalinkValToName(int((*dltArray)[i])) 477 datalinks[i].Description = pcapDatalinkValToDescription(int((*dltArray)[i])) 478 } 479 480 return datalinks, nil 481 } 482 483 func pcapOpenDead(linkType layers.LinkType, captureLength int) (*Handle, error) { 484 err := LoadWinPCAP() 485 if err != nil { 486 return nil, err 487 } 488 489 cptr, _, _ := syscall.Syscall(pcapOpenDeadPtr, 2, uintptr(linkType), uintptr(captureLength), 0) 490 if cptr == 0 { 491 return nil, errors.New("error opening dead capture") 492 } 493 494 return &Handle{cptr: pcapTPtr(cptr)}, nil 495 } 496 497 func (p *Handle) pcapNextPacketEx() NextError { 498 r, _, _ := syscall.Syscall(pcapNextExPtr, 3, uintptr(p.cptr), uintptr(unsafe.Pointer(&p.pkthdr)), uintptr(unsafe.Pointer(&p.bufptr))) 499 ret := pcapCint(r) 500 // According to https://github.com/the-tcpdump-group/libpcap/blob/1131a7c26c6f4d4772e4a2beeaf7212f4dea74ac/pcap.c#L398-L406 , 501 // the return value of pcap_next_ex could be greater than 1 for success. 502 // Let's just make it 1 if it comes bigger than 1. 503 if ret > 1 { 504 ret = 1 505 } 506 return NextError(ret) 507 } 508 509 func (p *Handle) pcapDatalink() layers.LinkType { 510 ret, _, _ := syscall.Syscall(pcapDatalinkPtr, 1, uintptr(p.cptr), 0, 0) 511 return layers.LinkType(ret) 512 } 513 514 func (p *Handle) pcapSetDatalink(dlt layers.LinkType) error { 515 ret, _, _ := syscall.Syscall(pcapSetDatalinkPtr, 2, uintptr(p.cptr), uintptr(dlt), 0) 516 if pcapCint(ret) < 0 { 517 return p.pcapGeterr() 518 } 519 return nil 520 } 521 522 func pcapDatalinkValToName(dlt int) string { 523 err := LoadWinPCAP() 524 if err != nil { 525 panic(err) 526 } 527 ret, _, _ := syscall.Syscall(pcapDatalinkValToNamePtr, 1, uintptr(dlt), 0, 0) 528 return bytePtrToString(ret) 529 } 530 531 func pcapDatalinkValToDescription(dlt int) string { 532 err := LoadWinPCAP() 533 if err != nil { 534 panic(err) 535 } 536 ret, _, _ := syscall.Syscall(pcapDatalinkValToDescriptionPtr, 1, uintptr(dlt), 0, 0) 537 return bytePtrToString(ret) 538 } 539 540 func pcapDatalinkNameToVal(name string) int { 541 err := LoadWinPCAP() 542 if err != nil { 543 panic(err) 544 } 545 cptr, err := syscall.BytePtrFromString(name) 546 if err != nil { 547 return 0 548 } 549 ret, _, _ := syscall.Syscall(pcapDatalinkNameToValPtr, 1, uintptr(unsafe.Pointer(cptr)), 0, 0) 550 return int(pcapCint(ret)) 551 } 552 553 func pcapLibVersion() string { 554 err := LoadWinPCAP() 555 if err != nil { 556 panic(err) 557 } 558 ret, _, _ := syscall.Syscall(pcapLibVersionPtr, 0, 0, 0, 0) 559 return bytePtrToString(ret) 560 } 561 562 func (p *Handle) isOpen() bool { 563 return p.cptr != 0 564 } 565 566 type pcapDevices struct { 567 all, cur *pcapIf 568 } 569 570 func (p pcapDevices) free() { 571 syscall.Syscall(pcapFreealldevsPtr, 1, uintptr(unsafe.Pointer(p.all)), 0, 0) 572 } 573 574 func (p *pcapDevices) next() bool { 575 if p.cur == nil { 576 p.cur = p.all 577 if p.cur == nil { 578 return false 579 } 580 return true 581 } 582 if p.cur.Next == nil { 583 return false 584 } 585 p.cur = p.cur.Next 586 return true 587 } 588 589 func (p pcapDevices) name() string { 590 return bytePtrToString(uintptr(unsafe.Pointer(p.cur.Name))) 591 } 592 593 func (p pcapDevices) description() string { 594 return bytePtrToString(uintptr(unsafe.Pointer(p.cur.Description))) 595 } 596 597 func (p pcapDevices) flags() uint32 { 598 return p.cur.Flags 599 } 600 601 type pcapAddresses struct { 602 all, cur *pcapAddr 603 } 604 605 func (p *pcapAddresses) next() bool { 606 if p.cur == nil { 607 p.cur = p.all 608 if p.cur == nil { 609 return false 610 } 611 return true 612 } 613 if p.cur.Next == nil { 614 return false 615 } 616 p.cur = p.cur.Next 617 return true 618 } 619 620 func (p pcapAddresses) addr() *syscall.RawSockaddr { 621 return p.cur.Addr 622 } 623 624 func (p pcapAddresses) netmask() *syscall.RawSockaddr { 625 return p.cur.Netmask 626 } 627 628 func (p pcapAddresses) broadaddr() *syscall.RawSockaddr { 629 return p.cur.Broadaddr 630 } 631 632 func (p pcapAddresses) dstaddr() *syscall.RawSockaddr { 633 return p.cur.Dstaddr 634 } 635 636 func (p pcapDevices) addresses() pcapAddresses { 637 return pcapAddresses{all: p.cur.Addresses} 638 } 639 640 func pcapFindAllDevs() (pcapDevices, error) { 641 var alldevsp pcapDevices 642 err := LoadWinPCAP() 643 if err != nil { 644 return alldevsp, err 645 } 646 647 buf := make([]byte, errorBufferSize) 648 649 ret, _, _ := syscall.Syscall(pcapFindalldevsPtr, 2, uintptr(unsafe.Pointer(&alldevsp.all)), uintptr(unsafe.Pointer(&buf[0])), 0) 650 651 if pcapCint(ret) < 0 { 652 return pcapDevices{}, errors.New(byteSliceToString(buf)) 653 } 654 return alldevsp, nil 655 } 656 657 func (p *Handle) pcapSendpacket(data []byte) error { 658 ret, _, _ := syscall.Syscall(pcapSendpacketPtr, 3, uintptr(p.cptr), uintptr(unsafe.Pointer(&data[0])), uintptr(len(data))) 659 if pcapCint(ret) < 0 { 660 return p.pcapGeterr() 661 } 662 return nil 663 } 664 665 func (p *Handle) pcapSetdirection(direction Direction) error { 666 status, _, _ := syscall.Syscall(pcapSetdirectionPtr, 2, uintptr(p.cptr), uintptr(direction), 0) 667 if pcapCint(status) < 0 { 668 return statusError(pcapCint(status)) 669 } 670 return nil 671 } 672 673 func (p *Handle) pcapSnapshot() int { 674 ret, _, _ := syscall.Syscall(pcapSnapshotPtr, 1, uintptr(p.cptr), 0, 0) 675 return int(pcapCint(ret)) 676 } 677 678 func (t TimestampSource) pcapTstampTypeValToName() string { 679 err := LoadWinPCAP() 680 if err != nil { 681 return err.Error() 682 } 683 684 //libpcap <1.2 doesn't have pcap_*_tstamp_* functions 685 if pcapTstampTypeValToNamePtr == 0 { 686 return "pcap timestamp types not supported" 687 } 688 ret, _, _ := syscall.Syscall(pcapTstampTypeValToNamePtr, 1, uintptr(t), 0, 0) 689 return bytePtrToString(ret) 690 } 691 692 func pcapTstampTypeNameToVal(s string) (TimestampSource, error) { 693 err := LoadWinPCAP() 694 if err != nil { 695 return 0, err 696 } 697 698 //libpcap <1.2 doesn't have pcap_*_tstamp_* functions 699 if pcapTstampTypeNameToValPtr == 0 { 700 return 0, statusError(pcapCint(pcapError)) 701 } 702 cs, err := syscall.BytePtrFromString(s) 703 if err != nil { 704 return 0, err 705 } 706 ret, _, _ := syscall.Syscall(pcapTstampTypeNameToValPtr, 1, uintptr(unsafe.Pointer(cs)), 0, 0) 707 t := pcapCint(ret) 708 if t < 0 { 709 return 0, statusError(pcapCint(t)) 710 } 711 return TimestampSource(t), nil 712 } 713 714 func (p *InactiveHandle) pcapGeterr() error { 715 ret, _, _ := syscall.Syscall(pcapGeterrPtr, 1, uintptr(p.cptr), 0, 0) 716 return errors.New(bytePtrToString(ret)) 717 } 718 719 func (p *InactiveHandle) pcapActivate() (*Handle, activateError) { 720 r, _, _ := syscall.Syscall(pcapActivatePtr, 1, uintptr(p.cptr), 0, 0) 721 ret := activateError(pcapCint(r)) 722 if ret != aeNoError { 723 return nil, ret 724 } 725 h := &Handle{ 726 cptr: p.cptr, 727 } 728 p.cptr = 0 729 return h, ret 730 } 731 732 func (p *InactiveHandle) pcapClose() { 733 if p.cptr != 0 { 734 _, _, _ = syscall.Syscall(pcapClosePtr, 1, uintptr(p.cptr), 0, 0) 735 } 736 p.cptr = 0 737 } 738 739 func pcapCreate(device string) (*InactiveHandle, error) { 740 err := LoadWinPCAP() 741 if err != nil { 742 return nil, err 743 } 744 745 buf := make([]byte, errorBufferSize) 746 dev, err := syscall.BytePtrFromString(device) 747 if err != nil { 748 return nil, err 749 } 750 cptr, _, _ := syscall.Syscall(pcapCreatePtr, 2, uintptr(unsafe.Pointer(dev)), uintptr(unsafe.Pointer(&buf[0])), 0) 751 if cptr == 0 { 752 return nil, errors.New(byteSliceToString(buf)) 753 } 754 return &InactiveHandle{cptr: pcapTPtr(cptr)}, nil 755 } 756 757 func (p *InactiveHandle) pcapSetSnaplen(snaplen int) error { 758 status, _, _ := syscall.Syscall(pcapSetSnaplenPtr, 2, uintptr(p.cptr), uintptr(snaplen), 0) 759 if pcapCint(status) < 0 { 760 return statusError(pcapCint(status)) 761 } 762 return nil 763 } 764 765 func (p *InactiveHandle) pcapSetPromisc(promisc bool) error { 766 var pro uintptr 767 if promisc { 768 pro = 1 769 } 770 status, _, _ := syscall.Syscall(pcapSetPromiscPtr, 2, uintptr(p.cptr), pro, 0) 771 if pcapCint(status) < 0 { 772 return statusError(pcapCint(status)) 773 } 774 return nil 775 } 776 777 func (p *InactiveHandle) pcapSetTimeout(timeout time.Duration) error { 778 status, _, _ := syscall.Syscall(pcapSetTimeoutPtr, 2, uintptr(p.cptr), uintptr(timeoutMillis(timeout)), 0) 779 780 if pcapCint(status) < 0 { 781 return statusError(pcapCint(status)) 782 } 783 return nil 784 } 785 786 func (p *InactiveHandle) pcapListTstampTypes() (out []TimestampSource) { 787 //libpcap <1.2 doesn't have pcap_*_tstamp_* functions 788 if pcapListTstampTypesPtr == 0 { 789 return 790 } 791 var types *pcapCint 792 ret, _, _ := syscall.Syscall(pcapListTstampTypesPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&types)), 0) 793 n := int(pcapCint(ret)) 794 if n < 0 { 795 return // public interface doesn't have error :( 796 } 797 defer syscall.Syscall(pcapFreeTstampTypesPtr, 1, uintptr(unsafe.Pointer(types)), 0, 0) 798 typesArray := (*[1 << 28]pcapCint)(unsafe.Pointer(types)) 799 for i := 0; i < n; i++ { 800 out = append(out, TimestampSource((*typesArray)[i])) 801 } 802 return 803 } 804 805 func (p *InactiveHandle) pcapSetTstampType(t TimestampSource) error { 806 //libpcap <1.2 doesn't have pcap_*_tstamp_* functions 807 if pcapSetTstampTypePtr == 0 { 808 return statusError(pcapError) 809 } 810 status, _, _ := syscall.Syscall(pcapSetTstampTypePtr, 2, uintptr(p.cptr), uintptr(t), 0) 811 if pcapCint(status) < 0 { 812 return statusError(pcapCint(status)) 813 } 814 return nil 815 } 816 817 func (p *InactiveHandle) pcapSetRfmon(monitor bool) error { 818 //winpcap does not support rfmon 819 if pcapCanSetRfmonPtr == 0 { 820 return CannotSetRFMon 821 } 822 var mon uintptr 823 if monitor { 824 mon = 1 825 } 826 canset, _, _ := syscall.Syscall(pcapCanSetRfmonPtr, 1, uintptr(p.cptr), 0, 0) 827 switch canset { 828 case 0: 829 return CannotSetRFMon 830 case 1: 831 // success 832 default: 833 return statusError(pcapCint(canset)) 834 } 835 status, _, _ := syscall.Syscall(pcapSetRfmonPtr, 2, uintptr(p.cptr), mon, 0) 836 if status != 0 { 837 return statusError(pcapCint(status)) 838 } 839 return nil 840 } 841 842 func (p *InactiveHandle) pcapSetBufferSize(bufferSize int) error { 843 status, _, _ := syscall.Syscall(pcapSetBufferSizePtr, 2, uintptr(p.cptr), uintptr(bufferSize), 0) 844 if pcapCint(status) < 0 { 845 return statusError(pcapCint(status)) 846 } 847 return nil 848 } 849 850 func (p *InactiveHandle) pcapSetImmediateMode(mode bool) error { 851 //libpcap <1.5 does not have pcap_set_immediate_mode 852 if pcapSetImmediateModePtr == 0 { 853 return statusError(pcapError) 854 } 855 var md uintptr 856 if mode { 857 md = 1 858 } 859 status, _, _ := syscall.Syscall(pcapSetImmediateModePtr, 2, uintptr(p.cptr), md, 0) 860 if pcapCint(status) < 0 { 861 return statusError(pcapCint(status)) 862 } 863 return nil 864 } 865 866 func (p *Handle) setNonBlocking() error { 867 // do nothing 868 return nil 869 } 870 871 // waitForPacket waits for a packet or for the timeout to expire. 872 func (p *Handle) waitForPacket() { 873 // can't use select() so instead just switch goroutines 874 runtime.Gosched() 875 } 876 877 // openOfflineFile returns contents of input file as a *Handle. 878 func openOfflineFile(file *os.File) (handle *Handle, err error) { 879 err = LoadWinPCAP() 880 if err != nil { 881 return nil, err 882 } 883 884 buf := make([]byte, errorBufferSize) 885 cf := file.Fd() 886 887 var cptr uintptr 888 if pcapOpenOfflineWithTstampPrecisionPtr == 0 { 889 cptr, _, _ = syscall.Syscall(pcapHopenOfflinePtr, 2, cf, uintptr(unsafe.Pointer(&buf[0])), 0) 890 } else { 891 cptr, _, _ = syscall.Syscall(pcapHOpenOfflineWithTstampPrecisionPtr, 3, cf, uintptr(pcapTstampPrecisionNano), uintptr(unsafe.Pointer(&buf[0]))) 892 } 893 894 if cptr == 0 { 895 return nil, errors.New(byteSliceToString(buf)) 896 } 897 return &Handle{cptr: pcapTPtr(cptr)}, nil 898 }