hftsniff.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /******
  2. * HFTSniff simple sniffer using pcap
  3. * xorg62@gmail.com
  4. ******/
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <stdbool.h>
  8. #include <unistd.h>
  9. #include <string.h>
  10. #include <limits.h>
  11. #include <ctype.h>
  12. #include <pcap.h>
  13. #include <sys/socket.h>
  14. #include <netinet/in.h>
  15. #include <netinet/if_ether.h>
  16. #include <arpa/inet.h>
  17. /* Macros */
  18. #define LEN(x) (sizeof(x) / sizeof(*x))
  19. /* Using ANSI escape codes to use bold in simple text mode */
  20. #define IP_SRCDEST(src, psrc, dest, pdest) \
  21. do { \
  22. printf("%s:\e[1m%d\e[0m ==> %s:\e[1m%d\e[0m\n", \
  23. src, psrc, dest, pdest); \
  24. } while(/* CONSTCOND */ 0);
  25. #define DISP_PROTO(s) \
  26. do { \
  27. printf("( \e[1m%s\e[0m ) ", s); \
  28. } while(/* CONSTCOND */ 0);
  29. #define DISP_PAYLOAD(p, l) \
  30. do { \
  31. int i = 0; \
  32. for(; i < (l) && (p); ++i, ++(p)) \
  33. if(isprint(*(p))) \
  34. putchar((char)*(p)); \
  35. } while(/* CONSTCOND */ 0);
  36. #define BYE(s, er) \
  37. do { \
  38. fprintf(stderr, s": (%s)\n", er); \
  39. exit(EXIT_FAILURE); \
  40. } while(/* CONSTCOND */ 0);
  41. #define PKT_ERROR(r, s, a) \
  42. do { \
  43. fprintf(stderr, " PKT_ERROR: %s (%u)\n", s, a); \
  44. return r; \
  45. } while(/* CONSTCOND */ 0); \
  46. /* Option const */
  47. #define FILTER "ip"
  48. #define TIMEOUT (10)
  49. #define SNAPLEN (SHRT_MAX)
  50. /*
  51. * Ethernet packet format
  52. */
  53. #define ETHERNET_SIZE (14)
  54. #define ETHERNET_ALEN (6)
  55. struct ethernet_header
  56. {
  57. unsigned char ether_dhost[ETHERNET_ALEN]; /* Destination ethernet address */
  58. unsigned char ether_shost[ETHERNET_ALEN]; /* Source ethernet adress */
  59. unsigned short ether_type; /* Packet type, id field */
  60. };
  61. /*
  62. * Ip packet format (tcpdump way)
  63. */
  64. #define IP_V(ip) (((ip)->ip_vhl & 0xf0) >> 4)
  65. #define IP_HL(ip) ((ip)->ip_vhl & 0x0f)
  66. #define IP_DF (0x4000) /* Dont fragment flag */
  67. #define IP_MF (0x2000) /* More fragments flag */
  68. #define IP_OFFMASK (0x1fff) /* Mask for fragmenting bits */
  69. struct ip_header
  70. {
  71. unsigned char ip_vhl; /* Header length, version */
  72. unsigned char ip_tos; /* Type of service */
  73. unsigned short ip_len; /* Total length */
  74. unsigned short ip_id; /* Identification */
  75. unsigned short ip_off; /* Fragment offset field */
  76. unsigned char ip_ttl; /* Time to live */
  77. unsigned char ip_p; /* Protocol */
  78. unsigned short ip_sum; /* Checksum */
  79. struct in_addr ip_src, ip_dst; /* Source and dest address */
  80. };
  81. /*
  82. * TCP packet format
  83. */
  84. #define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
  85. #define TH_FIN (0x01)
  86. #define TH_SYN (0x02)
  87. #define TH_RST (0x04)
  88. #define TH_PUSH (0x08)
  89. #define TH_ACK (0x10)
  90. #define TH_URG (0x20)
  91. #define TH_ECE (0x40)
  92. #define TH_CWR (0x80)
  93. #define TH_FLAGS (0xf7) /* TH_* */
  94. struct tcp_header
  95. {
  96. unsigned short th_sport; /* Source port */
  97. unsigned short th_dport; /* Destination port */
  98. unsigned int th_seq; /* Sequence number */
  99. unsigned int th_ack; /* Acknowledgement number */
  100. unsigned char th_offx2; /* Data offset, rsvd */
  101. unsigned char th_flags; /* Flags bitfield */
  102. unsigned short th_win; /* Window */
  103. unsigned short th_sum; /* Checksum */
  104. unsigned short th_urp; /* Urgent pointer */
  105. };
  106. /* Function protos */
  107. int pkt_tcp_handle(void *, void *);
  108. /* Usefull things */
  109. const struct
  110. {
  111. unsigned int p;
  112. int (*f)(void *, void*);
  113. char name[32];
  114. } protos[] =
  115. {
  116. { IPPROTO_IP, NULL, "IP" }, /* _IP 0 */
  117. { IPPROTO_ICMP, NULL, "ICMP" }, /* _ICMP 1 */
  118. { IPPROTO_TCP, pkt_tcp_handle, "TCP" }, /* _TCP 6 */
  119. { IPPROTO_UDP, NULL, "UDP" }, /* _UDP 17 */
  120. { -1, NULL, ""}
  121. };
  122. /* As defined in man: */
  123. char errbuf[PCAP_ERRBUF_SIZE];
  124. /*
  125. * Handle TCP packets
  126. */
  127. int
  128. pkt_tcp_handle(void *pkt, void *prev_pkt)
  129. {
  130. const struct tcp_header *tcp;
  131. const struct ip_header *ip;
  132. int len;
  133. ip = (struct ip_header*)prev_pkt;
  134. tcp = (struct tcp_header*)(pkt + ETHERNET_SIZE + (IP_HL(ip) << 2));
  135. if((len = TH_OFF(tcp) << 2) < 20)
  136. PKT_ERROR(0, "Invalid IP header length:", len);
  137. IP_SRCDEST(inet_ntoa(ip->ip_src), ntohs(tcp->th_sport), /* src */
  138. inet_ntoa(ip->ip_dst), ntohs(tcp->th_dport)); /* dest */
  139. return len;
  140. }
  141. /*
  142. * Handle every packet, point it to corresponding pkt_proto_handle
  143. */
  144. void
  145. pkt_handle(unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet)
  146. {
  147. struct ethernet_header *eth;
  148. struct ip_header *ip;
  149. const unsigned char *payload;
  150. int len, plen, paylen, i = 0;
  151. bool pfound = false;
  152. /* Translate ethernet pkt */
  153. eth = (struct ethernet_header*)packet;
  154. /* Translate ip pkt */
  155. ip = (struct ip_header*)(packet + ETHERNET_SIZE);
  156. /* Check ipv4 */
  157. if((len = IP_HL(ip) << 2) < 20)
  158. PKT_ERROR(, "Invalid IP header length:", len);
  159. /* Protocol */
  160. for(; i < LEN(protos); ++i)
  161. if(ip->ip_p == protos[i].p)
  162. {
  163. DISP_PROTO(protos[i].name);
  164. if(protos[i].f)
  165. plen = protos[i].f((void*)packet, (void*)ip);
  166. pfound = true;
  167. break;
  168. }
  169. /* Unknown protocol */
  170. if(!pfound)
  171. {
  172. DISP_PROTO("unknown");
  173. IP_SRCDEST(inet_ntoa(ip->ip_src), -1, /* src */
  174. inet_ntoa(ip->ip_dst), -1); /* dest */
  175. puts("\n");
  176. return;
  177. }
  178. /* Get / Display payload */
  179. payload = (unsigned char*)(packet + ETHERNET_SIZE + len + plen);
  180. if((paylen = ntohs(ip->ip_len) - (len + plen)) > 0)
  181. DISP_PAYLOAD(payload, paylen);
  182. puts("\n");
  183. return;
  184. }
  185. int
  186. main(int argc, char **argv)
  187. {
  188. char *dev;
  189. bpf_u_int32 mask;
  190. bpf_u_int32 netip;
  191. pcap_t *descr;
  192. struct bpf_program bpf;
  193. if(argc < 2)
  194. {
  195. fprintf(stderr, "%s usage: %s <interface>\n", argv[0], argv[0]);
  196. exit(EXIT_FAILURE);
  197. }
  198. /* Find adress & mask */
  199. if(pcap_lookupnet(argv[1], &netip, &mask, errbuf) < 0)
  200. {
  201. fprintf(stderr, "Can't find Adress or Mask: (%s)\n", errbuf);
  202. netip = mask = 0;
  203. }
  204. /* Open device and reaaad */
  205. if(!(descr = pcap_open_live(argv[1], SNAPLEN, true, TIMEOUT, errbuf)))
  206. BYE("Fail at opening and reading device", errbuf);
  207. /* Check if packet is from ethernet device */
  208. if(pcap_datalink(descr) != DLT_EN10MB)
  209. BYE("Device is not an Ethernet", dev);
  210. /* Parse & set pcap with option expression */
  211. if(pcap_compile(descr, &bpf, FILTER, 0, netip) < 0)
  212. BYE("Option parse error", pcap_geterr(descr));
  213. if(pcap_setfilter(descr, &bpf) < 0)
  214. BYE("Can't use option", pcap_geterr(descr));
  215. printf("%d\n", 1<<1);
  216. pcap_loop(descr, 10, pkt_handle, NULL);
  217. pcap_freecode(&bpf);
  218. pcap_close(descr);
  219. return 0;
  220. }