pcap_windows.go 23 KB

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