pcap_unix.go 19 KB

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