123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810 |
- // Copyright 2012 Google, Inc. All rights reserved.
- // Copyright 2009-2011 Andreas Krennmair. All rights reserved.
- //
- // Use of this source code is governed by a BSD-style license
- // that can be found in the LICENSE file in the root of the source
- // tree.
- package pcap
- import (
- "errors"
- "fmt"
- "os"
- "runtime"
- "sync"
- "syscall"
- "time"
- "unsafe"
- "github.com/google/gopacket"
- "github.com/google/gopacket/layers"
- )
- const npcapPath = "\\Npcap"
- func initDllPath(kernel32 syscall.Handle) {
- setDllDirectory, err := syscall.GetProcAddress(kernel32, "SetDllDirectoryA")
- if err != nil {
- // we can't do anything since SetDllDirectoryA is missing - fall back to use first wpcap.dll we encounter
- return
- }
- getSystemDirectory, err := syscall.GetProcAddress(kernel32, "GetSystemDirectoryA")
- if err != nil {
- // we can't do anything since SetDllDirectoryA is missing - fall back to use first wpcap.dll we encounter
- return
- }
- buf := make([]byte, 4096)
- r, _, _ := syscall.Syscall(getSystemDirectory, 2, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
- if r == 0 || r > 4096-uintptr(len(npcapPath))-1 {
- // we can't do anything since SetDllDirectoryA is missing - fall back to use first wpcap.dll we encounter
- return
- }
- copy(buf[r:], npcapPath)
- _, _, _ = syscall.Syscall(setDllDirectory, 1, uintptr(unsafe.Pointer(&buf[0])), 0, 0)
- // ignore errors here - we just fallback to load wpcap.dll from default locations
- }
- // loadedDllPath will hold the full pathname of the loaded wpcap.dll after init if possible
- var loadedDllPath = "wpcap.dll"
- func initLoadedDllPath(kernel32 syscall.Handle) {
- getModuleFileName, err := syscall.GetProcAddress(kernel32, "GetModuleFileNameA")
- if err != nil {
- // we can't get the filename of the loaded module in this case - just leave default of wpcap.dll
- return
- }
- buf := make([]byte, 4096)
- r, _, _ := syscall.Syscall(getModuleFileName, 3, uintptr(wpcapHandle), uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)))
- if r == 0 {
- // we can't get the filename of the loaded module in this case - just leave default of wpcap.dll
- return
- }
- loadedDllPath = string(buf[:int(r)])
- }
- func mustLoad(fun string) uintptr {
- addr, err := syscall.GetProcAddress(wpcapHandle, fun)
- if err != nil {
- panic(fmt.Sprintf("Couldn't load function %s from %s", fun, loadedDllPath))
- }
- return addr
- }
- func mightLoad(fun string) uintptr {
- addr, err := syscall.GetProcAddress(wpcapHandle, fun)
- if err != nil {
- return 0
- }
- return addr
- }
- func byteSliceToString(bval []byte) string {
- for i := range bval {
- if bval[i] == 0 {
- return string(bval[:i])
- }
- }
- return string(bval[:])
- }
- // bytePtrToString returns a string copied from pointer to a null terminated byte array
- // WARNING: ONLY SAFE WITH IF r POINTS TO C MEMORY!
- // govet will complain about this function for the reason stated above
- func bytePtrToString(r uintptr) string {
- if r == 0 {
- return ""
- }
- bval := (*[1 << 30]byte)(unsafe.Pointer(r))
- return byteSliceToString(bval[:])
- }
- var wpcapHandle syscall.Handle
- var msvcrtHandle syscall.Handle
- var (
- callocPtr,
- pcapStrerrorPtr,
- pcapStatustostrPtr,
- pcapOpenLivePtr,
- pcapOpenOfflinePtr,
- pcapClosePtr,
- pcapGeterrPtr,
- pcapStatsPtr,
- pcapCompilePtr,
- pcapFreecodePtr,
- pcapLookupnetPtr,
- pcapOfflineFilterPtr,
- pcapSetfilterPtr,
- pcapListDatalinksPtr,
- pcapFreeDatalinksPtr,
- pcapDatalinkValToNamePtr,
- pcapDatalinkValToDescriptionPtr,
- pcapOpenDeadPtr,
- pcapNextExPtr,
- pcapDatalinkPtr,
- pcapSetDatalinkPtr,
- pcapDatalinkNameToValPtr,
- pcapLibVersionPtr,
- pcapFreealldevsPtr,
- pcapFindalldevsPtr,
- pcapSendpacketPtr,
- pcapSetdirectionPtr,
- pcapSnapshotPtr,
- pcapTstampTypeValToNamePtr,
- pcapTstampTypeNameToValPtr,
- pcapListTstampTypesPtr,
- pcapFreeTstampTypesPtr,
- pcapSetTstampTypePtr,
- pcapGetTstampPrecisionPtr,
- pcapSetTstampPrecisionPtr,
- pcapOpenOfflineWithTstampPrecisionPtr,
- pcapHOpenOfflineWithTstampPrecisionPtr,
- pcapActivatePtr,
- pcapCreatePtr,
- pcapSetSnaplenPtr,
- pcapSetPromiscPtr,
- pcapSetTimeoutPtr,
- pcapCanSetRfmonPtr,
- pcapSetRfmonPtr,
- pcapSetBufferSizePtr,
- pcapSetImmediateModePtr,
- pcapHopenOfflinePtr uintptr
- )
- func init() {
- kernel32, err := syscall.LoadLibrary("kernel32.dll")
- if err != nil {
- panic("couldn't load kernel32.dll")
- }
- defer syscall.FreeLibrary(kernel32)
- initDllPath(kernel32)
- wpcapHandle, err = syscall.LoadLibrary("wpcap.dll")
- if err != nil {
- panic("Couldn't load wpcap.dll")
- }
- initLoadedDllPath(kernel32)
- msvcrtHandle, err = syscall.LoadLibrary("msvcrt.dll")
- if err != nil {
- panic("Couldn't load msvcrt.dll")
- }
- callocPtr, err = syscall.GetProcAddress(msvcrtHandle, "calloc")
- if err != nil {
- panic("Couldn't get calloc function")
- }
- pcapStrerrorPtr = mustLoad("pcap_strerror")
- pcapStatustostrPtr = mightLoad("pcap_statustostr") // not available on winpcap
- pcapOpenLivePtr = mustLoad("pcap_open_live")
- pcapOpenOfflinePtr = mustLoad("pcap_open_offline")
- pcapClosePtr = mustLoad("pcap_close")
- pcapGeterrPtr = mustLoad("pcap_geterr")
- pcapStatsPtr = mustLoad("pcap_stats")
- pcapCompilePtr = mustLoad("pcap_compile")
- pcapFreecodePtr = mustLoad("pcap_freecode")
- pcapLookupnetPtr = mustLoad("pcap_lookupnet")
- pcapOfflineFilterPtr = mustLoad("pcap_offline_filter")
- pcapSetfilterPtr = mustLoad("pcap_setfilter")
- pcapListDatalinksPtr = mustLoad("pcap_list_datalinks")
- pcapFreeDatalinksPtr = mustLoad("pcap_free_datalinks")
- pcapDatalinkValToNamePtr = mustLoad("pcap_datalink_val_to_name")
- pcapDatalinkValToDescriptionPtr = mustLoad("pcap_datalink_val_to_description")
- pcapOpenDeadPtr = mustLoad("pcap_open_dead")
- pcapNextExPtr = mustLoad("pcap_next_ex")
- pcapDatalinkPtr = mustLoad("pcap_datalink")
- pcapSetDatalinkPtr = mustLoad("pcap_set_datalink")
- pcapDatalinkNameToValPtr = mustLoad("pcap_datalink_name_to_val")
- pcapLibVersionPtr = mustLoad("pcap_lib_version")
- pcapFreealldevsPtr = mustLoad("pcap_freealldevs")
- pcapFindalldevsPtr = mustLoad("pcap_findalldevs")
- pcapSendpacketPtr = mustLoad("pcap_sendpacket")
- pcapSetdirectionPtr = mustLoad("pcap_setdirection")
- pcapSnapshotPtr = mustLoad("pcap_snapshot")
- //libpcap <1.2 doesn't have pcap_*_tstamp_* functions
- pcapTstampTypeValToNamePtr = mightLoad("pcap_tstamp_type_val_to_name")
- pcapTstampTypeNameToValPtr = mightLoad("pcap_tstamp_type_name_to_val")
- pcapListTstampTypesPtr = mightLoad("pcap_list_tstamp_types")
- pcapFreeTstampTypesPtr = mightLoad("pcap_free_tstamp_types")
- pcapSetTstampTypePtr = mightLoad("pcap_set_tstamp_type")
- pcapGetTstampPrecisionPtr = mightLoad("pcap_get_tstamp_precision")
- pcapSetTstampPrecisionPtr = mightLoad("pcap_set_tstamp_precision")
- pcapOpenOfflineWithTstampPrecisionPtr = mightLoad("pcap_open_offline_with_tstamp_precision")
- pcapHOpenOfflineWithTstampPrecisionPtr = mightLoad("pcap_hopen_offline_with_tstamp_precision")
- pcapActivatePtr = mustLoad("pcap_activate")
- pcapCreatePtr = mustLoad("pcap_create")
- pcapSetSnaplenPtr = mustLoad("pcap_set_snaplen")
- pcapSetPromiscPtr = mustLoad("pcap_set_promisc")
- pcapSetTimeoutPtr = mustLoad("pcap_set_timeout")
- //winpcap does not support rfmon
- pcapCanSetRfmonPtr = mightLoad("pcap_can_set_rfmon")
- pcapSetRfmonPtr = mightLoad("pcap_set_rfmon")
- pcapSetBufferSizePtr = mustLoad("pcap_set_buffer_size")
- //libpcap <1.5 does not have pcap_set_immediate_mode
- pcapSetImmediateModePtr = mightLoad("pcap_set_immediate_mode")
- pcapHopenOfflinePtr = mustLoad("pcap_hopen_offline")
- }
- func (h *pcapPkthdr) getSec() int64 {
- return int64(h.Ts.Sec)
- }
- func (h *pcapPkthdr) getUsec() int64 {
- return int64(h.Ts.Usec)
- }
- func (h *pcapPkthdr) getLen() int {
- return int(h.Len)
- }
- func (h *pcapPkthdr) getCaplen() int {
- return int(h.Caplen)
- }
- func statusError(status pcapCint) error {
- var ret uintptr
- if pcapStatustostrPtr == 0 {
- ret, _, _ = syscall.Syscall(pcapStrerrorPtr, 1, uintptr(status), 0, 0)
- } else {
- ret, _, _ = syscall.Syscall(pcapStatustostrPtr, 1, uintptr(status), 0, 0)
- }
- return errors.New(bytePtrToString(ret))
- }
- func pcapGetTstampPrecision(cptr pcapTPtr) int {
- if pcapGetTstampPrecisionPtr == 0 {
- return pcapTstampPrecisionMicro
- }
- ret, _, _ := syscall.Syscall(pcapGetTstampPrecisionPtr, 1, uintptr(cptr), 0, 0)
- return int(pcapCint(ret))
- }
- func pcapSetTstampPrecision(cptr pcapTPtr, precision int) error {
- if pcapSetTstampPrecisionPtr == 0 {
- return errors.New("Not supported")
- }
- ret, _, _ := syscall.Syscall(pcapSetTstampPrecisionPtr, 2, uintptr(cptr), uintptr(precision), 0)
- if pcapCint(ret) < 0 {
- return errors.New("Not supported")
- }
- return nil
- }
- func pcapOpenLive(device string, snaplen int, pro int, timeout int) (*Handle, error) {
- buf := make([]byte, errorBufferSize)
- dev, err := syscall.BytePtrFromString(device)
- if err != nil {
- return nil, err
- }
- cptr, _, _ := syscall.Syscall6(pcapOpenLivePtr, 5, uintptr(unsafe.Pointer(dev)), uintptr(snaplen), uintptr(pro), uintptr(timeout), uintptr(unsafe.Pointer(&buf[0])), 0)
- if cptr == 0 {
- return nil, errors.New(byteSliceToString(buf))
- }
- return &Handle{cptr: pcapTPtr(cptr)}, nil
- }
- func openOffline(file string) (handle *Handle, err error) {
- buf := make([]byte, errorBufferSize)
- f, err := syscall.BytePtrFromString(file)
- if err != nil {
- return nil, err
- }
- var cptr uintptr
- if pcapOpenOfflineWithTstampPrecisionPtr == 0 {
- cptr, _, _ = syscall.Syscall(pcapOpenOfflinePtr, 2, uintptr(unsafe.Pointer(f)), uintptr(unsafe.Pointer(&buf[0])), 0)
- } else {
- cptr, _, _ = syscall.Syscall(pcapOpenOfflineWithTstampPrecisionPtr, 3, uintptr(unsafe.Pointer(f)), uintptr(pcapTstampPrecisionNano), uintptr(unsafe.Pointer(&buf[0])))
- }
- if cptr == 0 {
- return nil, errors.New(byteSliceToString(buf))
- }
- h := &Handle{cptr: pcapTPtr(cptr)}
- return h, nil
- }
- func (p *Handle) pcapClose() {
- if p.cptr != 0 {
- _, _, _ = syscall.Syscall(pcapClosePtr, 1, uintptr(p.cptr), 0, 0)
- }
- p.cptr = 0
- }
- func (p *Handle) pcapGeterr() error {
- ret, _, _ := syscall.Syscall(pcapGeterrPtr, 1, uintptr(p.cptr), 0, 0)
- return errors.New(bytePtrToString(ret))
- }
- func (p *Handle) pcapStats() (*Stats, error) {
- var cstats pcapStats
- ret, _, _ := syscall.Syscall(pcapStatsPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&cstats)), 0)
- if pcapCint(ret) < 0 {
- return nil, p.pcapGeterr()
- }
- return &Stats{
- PacketsReceived: int(cstats.Recv),
- PacketsDropped: int(cstats.Drop),
- PacketsIfDropped: int(cstats.Ifdrop),
- }, nil
- }
- // for libpcap < 1.8 pcap_compile is NOT thread-safe, so protect it.
- var pcapCompileMu sync.Mutex
- func (p *Handle) pcapCompile(expr string, maskp uint32) (pcapBpfProgram, error) {
- var bpf pcapBpfProgram
- cexpr, err := syscall.BytePtrFromString(expr)
- if err != nil {
- return pcapBpfProgram{}, err
- }
- pcapCompileMu.Lock()
- defer pcapCompileMu.Unlock()
- res, _, _ := syscall.Syscall6(pcapCompilePtr, 5, uintptr(p.cptr), uintptr(unsafe.Pointer(&bpf)), uintptr(unsafe.Pointer(cexpr)), uintptr(1), uintptr(maskp), 0)
- if pcapCint(res) < 0 {
- return bpf, p.pcapGeterr()
- }
- return bpf, nil
- }
- func (p pcapBpfProgram) free() {
- _, _, _ = syscall.Syscall(pcapFreecodePtr, 1, uintptr(unsafe.Pointer(&p)), 0, 0)
- }
- func (p pcapBpfProgram) toBPFInstruction() []BPFInstruction {
- bpfInsn := (*[bpfInstructionBufferSize]pcapBpfInstruction)(unsafe.Pointer(p.Insns))[0:p.Len:p.Len]
- bpfInstruction := make([]BPFInstruction, len(bpfInsn), len(bpfInsn))
- for i, v := range bpfInsn {
- bpfInstruction[i].Code = v.Code
- bpfInstruction[i].Jt = v.Jt
- bpfInstruction[i].Jf = v.Jf
- bpfInstruction[i].K = v.K
- }
- return bpfInstruction
- }
- func pcapBpfProgramFromInstructions(bpfInstructions []BPFInstruction) pcapBpfProgram {
- var bpf pcapBpfProgram
- bpf.Len = uint32(len(bpfInstructions))
- cbpfInsns, _, _ := syscall.Syscall(callocPtr, 2, uintptr(len(bpfInstructions)), uintptr(unsafe.Sizeof(bpfInstructions[0])), 0)
- gbpfInsns := (*[bpfInstructionBufferSize]pcapBpfInstruction)(unsafe.Pointer(cbpfInsns))
- for i, v := range bpfInstructions {
- gbpfInsns[i].Code = v.Code
- gbpfInsns[i].Jt = v.Jt
- gbpfInsns[i].Jf = v.Jf
- gbpfInsns[i].K = v.K
- }
- bpf.Insns = (*pcapBpfInstruction)(unsafe.Pointer(cbpfInsns))
- return bpf
- }
- func pcapLookupnet(device string) (netp, maskp uint32, err error) {
- buf := make([]byte, errorBufferSize)
- dev, err := syscall.BytePtrFromString(device)
- if err != nil {
- return 0, 0, err
- }
- e, _, _ := syscall.Syscall6(pcapLookupnetPtr, 4, uintptr(unsafe.Pointer(dev)), uintptr(unsafe.Pointer(&netp)), uintptr(unsafe.Pointer(&maskp)), uintptr(unsafe.Pointer(&buf[0])), 0, 0)
- if pcapCint(e) < 0 {
- return 0, 0, errors.New(byteSliceToString(buf))
- }
- return
- }
- func (b *BPF) pcapOfflineFilter(ci gopacket.CaptureInfo, data []byte) bool {
- var hdr pcapPkthdr
- hdr.Ts.Sec = int32(ci.Timestamp.Unix())
- hdr.Ts.Usec = int32(ci.Timestamp.Nanosecond() / 1000)
- hdr.Caplen = uint32(len(data)) // Trust actual length over ci.Length.
- hdr.Len = uint32(ci.Length)
- e, _, _ := syscall.Syscall(pcapOfflineFilterPtr, 3, uintptr(unsafe.Pointer(&b.bpf)), uintptr(unsafe.Pointer(&hdr)), uintptr(unsafe.Pointer(&data[0])))
- return e != 0
- }
- func (p *Handle) pcapSetfilter(bpf pcapBpfProgram) error {
- e, _, _ := syscall.Syscall(pcapSetfilterPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&bpf)), 0)
- if pcapCint(e) < 0 {
- return p.pcapGeterr()
- }
- return nil
- }
- func (p *Handle) pcapListDatalinks() (datalinks []Datalink, err error) {
- var dltbuf *pcapCint
- ret, _, _ := syscall.Syscall(pcapListDatalinksPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&dltbuf)), 0)
- n := int(pcapCint(ret))
- if n < 0 {
- return nil, p.pcapGeterr()
- }
- defer syscall.Syscall(pcapFreeDatalinksPtr, 1, uintptr(unsafe.Pointer(dltbuf)), 0, 0)
- datalinks = make([]Datalink, n)
- dltArray := (*[1 << 28]pcapCint)(unsafe.Pointer(dltbuf))
- for i := 0; i < n; i++ {
- datalinks[i].Name = pcapDatalinkValToName(int((*dltArray)[i]))
- datalinks[i].Description = pcapDatalinkValToDescription(int((*dltArray)[i]))
- }
- return datalinks, nil
- }
- func pcapOpenDead(linkType layers.LinkType, captureLength int) (*Handle, error) {
- cptr, _, _ := syscall.Syscall(pcapOpenDeadPtr, 2, uintptr(linkType), uintptr(captureLength), 0)
- if cptr == 0 {
- return nil, errors.New("error opening dead capture")
- }
- return &Handle{cptr: pcapTPtr(cptr)}, nil
- }
- func (p *Handle) pcapNextPacketEx() NextError {
- r, _, _ := syscall.Syscall(pcapNextExPtr, 3, uintptr(p.cptr), uintptr(unsafe.Pointer(&p.pkthdr)), uintptr(unsafe.Pointer(&p.bufptr)))
- ret := pcapCint(r)
- // According to https://github.com/the-tcpdump-group/libpcap/blob/1131a7c26c6f4d4772e4a2beeaf7212f4dea74ac/pcap.c#L398-L406 ,
- // the return value of pcap_next_ex could be greater than 1 for success.
- // Let's just make it 1 if it comes bigger than 1.
- if ret > 1 {
- ret = 1
- }
- return NextError(ret)
- }
- func (p *Handle) pcapDatalink() layers.LinkType {
- ret, _, _ := syscall.Syscall(pcapDatalinkPtr, 1, uintptr(p.cptr), 0, 0)
- return layers.LinkType(ret)
- }
- func (p *Handle) pcapSetDatalink(dlt layers.LinkType) error {
- ret, _, _ := syscall.Syscall(pcapSetDatalinkPtr, 2, uintptr(p.cptr), uintptr(dlt), 0)
- if pcapCint(ret) < 0 {
- return p.pcapGeterr()
- }
- return nil
- }
- func pcapDatalinkValToName(dlt int) string {
- ret, _, _ := syscall.Syscall(pcapDatalinkValToNamePtr, 1, uintptr(dlt), 0, 0)
- return bytePtrToString(ret)
- }
- func pcapDatalinkValToDescription(dlt int) string {
- ret, _, _ := syscall.Syscall(pcapDatalinkValToDescriptionPtr, 1, uintptr(dlt), 0, 0)
- return bytePtrToString(ret)
- }
- func pcapDatalinkNameToVal(name string) int {
- cptr, err := syscall.BytePtrFromString(name)
- if err != nil {
- return 0
- }
- ret, _, _ := syscall.Syscall(pcapDatalinkNameToValPtr, 1, uintptr(unsafe.Pointer(cptr)), 0, 0)
- return int(pcapCint(ret))
- }
- func pcapLibVersion() string {
- ret, _, _ := syscall.Syscall(pcapLibVersionPtr, 0, 0, 0, 0)
- return bytePtrToString(ret)
- }
- func (p *Handle) isOpen() bool {
- return p.cptr != 0
- }
- type pcapDevices struct {
- all, cur *pcapIf
- }
- func (p pcapDevices) free() {
- syscall.Syscall(pcapFreealldevsPtr, 1, uintptr(unsafe.Pointer(p.all)), 0, 0)
- }
- func (p *pcapDevices) next() bool {
- if p.cur == nil {
- p.cur = p.all
- if p.cur == nil {
- return false
- }
- return true
- }
- if p.cur.Next == nil {
- return false
- }
- p.cur = p.cur.Next
- return true
- }
- func (p pcapDevices) name() string {
- return bytePtrToString(uintptr(unsafe.Pointer(p.cur.Name)))
- }
- func (p pcapDevices) description() string {
- return bytePtrToString(uintptr(unsafe.Pointer(p.cur.Description)))
- }
- func (p pcapDevices) flags() uint32 {
- return p.cur.Flags
- }
- type pcapAddresses struct {
- all, cur *pcapAddr
- }
- func (p *pcapAddresses) next() bool {
- if p.cur == nil {
- p.cur = p.all
- if p.cur == nil {
- return false
- }
- return true
- }
- if p.cur.Next == nil {
- return false
- }
- p.cur = p.cur.Next
- return true
- }
- func (p pcapAddresses) addr() *syscall.RawSockaddr {
- return p.cur.Addr
- }
- func (p pcapAddresses) netmask() *syscall.RawSockaddr {
- return p.cur.Netmask
- }
- func (p pcapAddresses) broadaddr() *syscall.RawSockaddr {
- return p.cur.Broadaddr
- }
- func (p pcapAddresses) dstaddr() *syscall.RawSockaddr {
- return p.cur.Dstaddr
- }
- func (p pcapDevices) addresses() pcapAddresses {
- return pcapAddresses{all: p.cur.Addresses}
- }
- func pcapFindAllDevs() (pcapDevices, error) {
- buf := make([]byte, errorBufferSize)
- var alldevsp pcapDevices
- ret, _, _ := syscall.Syscall(pcapFindalldevsPtr, 2, uintptr(unsafe.Pointer(&alldevsp.all)), uintptr(unsafe.Pointer(&buf[0])), 0)
- if pcapCint(ret) < 0 {
- return pcapDevices{}, errors.New(byteSliceToString(buf))
- }
- return alldevsp, nil
- }
- func (p *Handle) pcapSendpacket(data []byte) error {
- ret, _, _ := syscall.Syscall(pcapSendpacketPtr, 3, uintptr(p.cptr), uintptr(unsafe.Pointer(&data[0])), uintptr(len(data)))
- if pcapCint(ret) < 0 {
- return p.pcapGeterr()
- }
- return nil
- }
- func (p *Handle) pcapSetdirection(direction Direction) error {
- status, _, _ := syscall.Syscall(pcapSetdirectionPtr, 2, uintptr(p.cptr), uintptr(direction), 0)
- if pcapCint(status) < 0 {
- return statusError(pcapCint(status))
- }
- return nil
- }
- func (p *Handle) pcapSnapshot() int {
- ret, _, _ := syscall.Syscall(pcapSnapshotPtr, 1, uintptr(p.cptr), 0, 0)
- return int(pcapCint(ret))
- }
- func (t TimestampSource) pcapTstampTypeValToName() string {
- //libpcap <1.2 doesn't have pcap_*_tstamp_* functions
- if pcapTstampTypeValToNamePtr == 0 {
- return "pcap timestamp types not supported"
- }
- ret, _, _ := syscall.Syscall(pcapTstampTypeValToNamePtr, 1, uintptr(t), 0, 0)
- return bytePtrToString(ret)
- }
- func pcapTstampTypeNameToVal(s string) (TimestampSource, error) {
- //libpcap <1.2 doesn't have pcap_*_tstamp_* functions
- if pcapTstampTypeNameToValPtr == 0 {
- return 0, statusError(pcapCint(pcapError))
- }
- cs, err := syscall.BytePtrFromString(s)
- if err != nil {
- return 0, err
- }
- ret, _, _ := syscall.Syscall(pcapTstampTypeNameToValPtr, 1, uintptr(unsafe.Pointer(cs)), 0, 0)
- t := pcapCint(ret)
- if t < 0 {
- return 0, statusError(pcapCint(t))
- }
- return TimestampSource(t), nil
- }
- func (p *InactiveHandle) pcapGeterr() error {
- ret, _, _ := syscall.Syscall(pcapGeterrPtr, 1, uintptr(p.cptr), 0, 0)
- return errors.New(bytePtrToString(ret))
- }
- func (p *InactiveHandle) pcapActivate() (*Handle, activateError) {
- r, _, _ := syscall.Syscall(pcapActivatePtr, 1, uintptr(p.cptr), 0, 0)
- ret := activateError(pcapCint(r))
- if ret != aeNoError {
- return nil, ret
- }
- h := &Handle{
- cptr: p.cptr,
- }
- p.cptr = 0
- return h, ret
- }
- func (p *InactiveHandle) pcapClose() {
- if p.cptr != 0 {
- _, _, _ = syscall.Syscall(pcapClosePtr, 1, uintptr(p.cptr), 0, 0)
- }
- p.cptr = 0
- }
- func pcapCreate(device string) (*InactiveHandle, error) {
- buf := make([]byte, errorBufferSize)
- dev, err := syscall.BytePtrFromString(device)
- if err != nil {
- return nil, err
- }
- cptr, _, _ := syscall.Syscall(pcapCreatePtr, 2, uintptr(unsafe.Pointer(dev)), uintptr(unsafe.Pointer(&buf[0])), 0)
- if cptr == 0 {
- return nil, errors.New(byteSliceToString(buf))
- }
- return &InactiveHandle{cptr: pcapTPtr(cptr)}, nil
- }
- func (p *InactiveHandle) pcapSetSnaplen(snaplen int) error {
- status, _, _ := syscall.Syscall(pcapSetSnaplenPtr, 2, uintptr(p.cptr), uintptr(snaplen), 0)
- if pcapCint(status) < 0 {
- return statusError(pcapCint(status))
- }
- return nil
- }
- func (p *InactiveHandle) pcapSetPromisc(promisc bool) error {
- var pro uintptr
- if promisc {
- pro = 1
- }
- status, _, _ := syscall.Syscall(pcapSetPromiscPtr, 2, uintptr(p.cptr), pro, 0)
- if pcapCint(status) < 0 {
- return statusError(pcapCint(status))
- }
- return nil
- }
- func (p *InactiveHandle) pcapSetTimeout(timeout time.Duration) error {
- status, _, _ := syscall.Syscall(pcapSetTimeoutPtr, 2, uintptr(p.cptr), uintptr(timeoutMillis(timeout)), 0)
- if pcapCint(status) < 0 {
- return statusError(pcapCint(status))
- }
- return nil
- }
- func (p *InactiveHandle) pcapListTstampTypes() (out []TimestampSource) {
- //libpcap <1.2 doesn't have pcap_*_tstamp_* functions
- if pcapListTstampTypesPtr == 0 {
- return
- }
- var types *pcapCint
- ret, _, _ := syscall.Syscall(pcapListTstampTypesPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&types)), 0)
- n := int(pcapCint(ret))
- if n < 0 {
- return // public interface doesn't have error :(
- }
- defer syscall.Syscall(pcapFreeTstampTypesPtr, 1, uintptr(unsafe.Pointer(types)), 0, 0)
- typesArray := (*[1 << 28]pcapCint)(unsafe.Pointer(types))
- for i := 0; i < n; i++ {
- out = append(out, TimestampSource((*typesArray)[i]))
- }
- return
- }
- func (p *InactiveHandle) pcapSetTstampType(t TimestampSource) error {
- //libpcap <1.2 doesn't have pcap_*_tstamp_* functions
- if pcapSetTstampTypePtr == 0 {
- return statusError(pcapError)
- }
- status, _, _ := syscall.Syscall(pcapSetTstampTypePtr, 2, uintptr(p.cptr), uintptr(t), 0)
- if pcapCint(status) < 0 {
- return statusError(pcapCint(status))
- }
- return nil
- }
- func (p *InactiveHandle) pcapSetRfmon(monitor bool) error {
- //winpcap does not support rfmon
- if pcapCanSetRfmonPtr == 0 {
- return CannotSetRFMon
- }
- var mon uintptr
- if monitor {
- mon = 1
- }
- canset, _, _ := syscall.Syscall(pcapCanSetRfmonPtr, 1, uintptr(p.cptr), 0, 0)
- switch canset {
- case 0:
- return CannotSetRFMon
- case 1:
- // success
- default:
- return statusError(pcapCint(canset))
- }
- status, _, _ := syscall.Syscall(pcapSetRfmonPtr, 2, uintptr(p.cptr), mon, 0)
- if status != 0 {
- return statusError(pcapCint(status))
- }
- return nil
- }
- func (p *InactiveHandle) pcapSetBufferSize(bufferSize int) error {
- status, _, _ := syscall.Syscall(pcapSetBufferSizePtr, 2, uintptr(p.cptr), uintptr(bufferSize), 0)
- if pcapCint(status) < 0 {
- return statusError(pcapCint(status))
- }
- return nil
- }
- func (p *InactiveHandle) pcapSetImmediateMode(mode bool) error {
- //libpcap <1.5 does not have pcap_set_immediate_mode
- if pcapSetImmediateModePtr == 0 {
- return statusError(pcapError)
- }
- var md uintptr
- if mode {
- md = 1
- }
- status, _, _ := syscall.Syscall(pcapSetImmediateModePtr, 2, uintptr(p.cptr), md, 0)
- if pcapCint(status) < 0 {
- return statusError(pcapCint(status))
- }
- return nil
- }
- func (p *Handle) setNonBlocking() error {
- // do nothing
- return nil
- }
- // waitForPacket waits for a packet or for the timeout to expire.
- func (p *Handle) waitForPacket() {
- // can't use select() so instead just switch goroutines
- runtime.Gosched()
- }
- // openOfflineFile returns contents of input file as a *Handle.
- func openOfflineFile(file *os.File) (handle *Handle, err error) {
- buf := make([]byte, errorBufferSize)
- cf := file.Fd()
- var cptr uintptr
- if pcapOpenOfflineWithTstampPrecisionPtr == 0 {
- cptr, _, _ = syscall.Syscall(pcapHopenOfflinePtr, 2, cf, uintptr(unsafe.Pointer(&buf[0])), 0)
- } else {
- cptr, _, _ = syscall.Syscall(pcapHOpenOfflineWithTstampPrecisionPtr, 3, cf, uintptr(pcapTstampPrecisionNano), uintptr(unsafe.Pointer(&buf[0])))
- }
- if cptr == 0 {
- return nil, errors.New(byteSliceToString(buf))
- }
- return &Handle{cptr: pcapTPtr(cptr)}, nil
- }
|