pcap.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // Interface to both live and offline pcap parsing.
  2. package pcap
  3. /*
  4. #cgo linux LDFLAGS: -lpcap
  5. #cgo freebsd LDFLAGS: -lpcap
  6. #cgo darwin LDFLAGS: -lpcap
  7. #cgo windows CFLAGS: -I C:/WpdPack/Include
  8. #cgo windows,386 LDFLAGS: -L C:/WpdPack/Lib -lwpcap
  9. #cgo windows,amd64 LDFLAGS: -L C:/WpdPack/Lib/x64 -lwpcap
  10. #include <stdlib.h>
  11. #include <pcap.h>
  12. // Workaround for not knowing how to cast to const u_char**
  13. int hack_pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
  14. u_char **pkt_data) {
  15. return pcap_next_ex(p, pkt_header, (const u_char **)pkt_data);
  16. }
  17. */
  18. import "C"
  19. import (
  20. "errors"
  21. "net"
  22. "syscall"
  23. "time"
  24. "unsafe"
  25. )
  26. type Pcap struct {
  27. cptr *C.pcap_t
  28. }
  29. type Stat struct {
  30. PacketsReceived uint32
  31. PacketsDropped uint32
  32. PacketsIfDropped uint32
  33. }
  34. type Interface struct {
  35. Name string
  36. Description string
  37. Addresses []IFAddress
  38. // TODO: add more elements
  39. }
  40. type IFAddress struct {
  41. IP net.IP
  42. Netmask net.IPMask
  43. // TODO: add broadcast + PtP dst ?
  44. }
  45. func (p *Pcap) Next() (pkt *Packet) {
  46. rv, _ := p.NextEx()
  47. return rv
  48. }
  49. // Openlive opens a device and returns a *Pcap handler
  50. func Openlive(device string, snaplen int32, promisc bool, timeout_ms int32) (handle *Pcap, err error) {
  51. var buf *C.char
  52. buf = (*C.char)(C.calloc(ERRBUF_SIZE, 1))
  53. h := new(Pcap)
  54. var pro int32
  55. if promisc {
  56. pro = 1
  57. }
  58. dev := C.CString(device)
  59. defer C.free(unsafe.Pointer(dev))
  60. h.cptr = C.pcap_open_live(dev, C.int(snaplen), C.int(pro), C.int(timeout_ms), buf)
  61. if nil == h.cptr {
  62. handle = nil
  63. err = errors.New(C.GoString(buf))
  64. } else {
  65. handle = h
  66. }
  67. C.free(unsafe.Pointer(buf))
  68. return
  69. }
  70. func Openoffline(file string) (handle *Pcap, err error) {
  71. var buf *C.char
  72. buf = (*C.char)(C.calloc(ERRBUF_SIZE, 1))
  73. h := new(Pcap)
  74. cf := C.CString(file)
  75. defer C.free(unsafe.Pointer(cf))
  76. h.cptr = C.pcap_open_offline(cf, buf)
  77. if nil == h.cptr {
  78. handle = nil
  79. err = errors.New(C.GoString(buf))
  80. } else {
  81. handle = h
  82. }
  83. C.free(unsafe.Pointer(buf))
  84. return
  85. }
  86. func (p *Pcap) NextEx() (pkt *Packet, result int32) {
  87. var pkthdr *C.struct_pcap_pkthdr
  88. var buf_ptr *C.u_char
  89. var buf unsafe.Pointer
  90. result = int32(C.hack_pcap_next_ex(p.cptr, &pkthdr, &buf_ptr))
  91. buf = unsafe.Pointer(buf_ptr)
  92. if nil == buf {
  93. return
  94. }
  95. pkt = new(Packet)
  96. pkt.Time = time.Unix(int64(pkthdr.ts.tv_sec), int64(pkthdr.ts.tv_usec)*1000)
  97. pkt.Caplen = uint32(pkthdr.caplen)
  98. pkt.Len = uint32(pkthdr.len)
  99. pkt.Data = C.GoBytes(buf, C.int(pkthdr.caplen))
  100. return
  101. }
  102. func (p *Pcap) Close() {
  103. C.pcap_close(p.cptr)
  104. }
  105. func (p *Pcap) Geterror() error {
  106. return errors.New(C.GoString(C.pcap_geterr(p.cptr)))
  107. }
  108. func (p *Pcap) Getstats() (stat *Stat, err error) {
  109. var cstats _Ctype_struct_pcap_stat
  110. if -1 == C.pcap_stats(p.cptr, &cstats) {
  111. return nil, p.Geterror()
  112. }
  113. stats := new(Stat)
  114. stats.PacketsReceived = uint32(cstats.ps_recv)
  115. stats.PacketsDropped = uint32(cstats.ps_drop)
  116. stats.PacketsIfDropped = uint32(cstats.ps_ifdrop)
  117. return stats, nil
  118. }
  119. func (p *Pcap) Setfilter(expr string) (err error) {
  120. var bpf _Ctype_struct_bpf_program
  121. cexpr := C.CString(expr)
  122. defer C.free(unsafe.Pointer(cexpr))
  123. if -1 == C.pcap_compile(p.cptr, &bpf, cexpr, 1, 0) {
  124. return p.Geterror()
  125. }
  126. if -1 == C.pcap_setfilter(p.cptr, &bpf) {
  127. C.pcap_freecode(&bpf)
  128. return p.Geterror()
  129. }
  130. C.pcap_freecode(&bpf)
  131. return nil
  132. }
  133. func Version() string {
  134. return C.GoString(C.pcap_lib_version())
  135. }
  136. func (p *Pcap) Datalink() int {
  137. return int(C.pcap_datalink(p.cptr))
  138. }
  139. func (p *Pcap) Setdatalink(dlt int) error {
  140. if -1 == C.pcap_set_datalink(p.cptr, C.int(dlt)) {
  141. return p.Geterror()
  142. }
  143. return nil
  144. }
  145. func DatalinkValueToName(dlt int) string {
  146. if name := C.pcap_datalink_val_to_name(C.int(dlt)); name != nil {
  147. return C.GoString(name)
  148. }
  149. return ""
  150. }
  151. func DatalinkValueToDescription(dlt int) string {
  152. if desc := C.pcap_datalink_val_to_description(C.int(dlt)); desc != nil {
  153. return C.GoString(desc)
  154. }
  155. return ""
  156. }
  157. func Findalldevs() (ifs []Interface, err error) {
  158. var buf *C.char
  159. buf = (*C.char)(C.calloc(ERRBUF_SIZE, 1))
  160. defer C.free(unsafe.Pointer(buf))
  161. var alldevsp *C.pcap_if_t
  162. if -1 == C.pcap_findalldevs((**C.pcap_if_t)(&alldevsp), buf) {
  163. return nil, errors.New(C.GoString(buf))
  164. }
  165. defer C.pcap_freealldevs((*C.pcap_if_t)(alldevsp))
  166. dev := alldevsp
  167. var i uint32
  168. for i = 0; dev != nil; dev = (*C.pcap_if_t)(dev.next) {
  169. i++
  170. }
  171. ifs = make([]Interface, i)
  172. dev = alldevsp
  173. for j := uint32(0); dev != nil; dev = (*C.pcap_if_t)(dev.next) {
  174. var iface Interface
  175. iface.Name = C.GoString(dev.name)
  176. iface.Description = C.GoString(dev.description)
  177. iface.Addresses = findalladdresses(dev.addresses)
  178. // TODO: add more elements
  179. ifs[j] = iface
  180. j++
  181. }
  182. return
  183. }
  184. func findalladdresses(addresses *_Ctype_struct_pcap_addr) (retval []IFAddress) {
  185. // TODO - make it support more than IPv4 and IPv6?
  186. retval = make([]IFAddress, 0, 1)
  187. for curaddr := addresses; curaddr != nil; curaddr = (*_Ctype_struct_pcap_addr)(curaddr.next) {
  188. var a IFAddress
  189. var err error
  190. if a.IP, err = sockaddr_to_IP((*syscall.RawSockaddr)(unsafe.Pointer(curaddr.addr))); err != nil {
  191. continue
  192. }
  193. if a.Netmask, err = sockaddr_to_IP((*syscall.RawSockaddr)(unsafe.Pointer(curaddr.addr))); err != nil {
  194. continue
  195. }
  196. retval = append(retval, a)
  197. }
  198. return
  199. }
  200. func sockaddr_to_IP(rsa *syscall.RawSockaddr) (IP []byte, err error) {
  201. switch rsa.Family {
  202. case syscall.AF_INET:
  203. pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
  204. IP = make([]byte, 4)
  205. for i := 0; i < len(IP); i++ {
  206. IP[i] = pp.Addr[i]
  207. }
  208. return
  209. case syscall.AF_INET6:
  210. pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
  211. IP = make([]byte, 16)
  212. for i := 0; i < len(IP); i++ {
  213. IP[i] = pp.Addr[i]
  214. }
  215. return
  216. }
  217. err = errors.New("Unsupported address type")
  218. return
  219. }
  220. func (p *Pcap) Inject(data []byte) (err error) {
  221. buf := (*C.char)(C.malloc((C.size_t)(len(data))))
  222. for i := 0; i < len(data); i++ {
  223. *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(buf)) + uintptr(i))) = data[i]
  224. }
  225. if -1 == C.pcap_sendpacket(p.cptr, (*C.u_char)(unsafe.Pointer(buf)), (C.int)(len(data))) {
  226. err = p.Geterror()
  227. }
  228. C.free(unsafe.Pointer(buf))
  229. return
  230. }