pcap_unix.go 19 KB

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