123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- /******
- * HFTSniff simple sniffer using pcap
- * xorg62@gmail.com
- ******/
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include <unistd.h>
- #include <string.h>
- #include <limits.h>
- #include <ctype.h>
- #include <pcap.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netinet/if_ether.h>
- #include <arpa/inet.h>
- /* Macros */
- #define LEN(x) (sizeof(x) / sizeof(*x))
- /* Using ANSI escape codes to use bold in simple text mode */
- #define IP_SRCDEST(src, psrc, dest, pdest) \
- do { \
- printf("%s:\e[1m%d\e[0m ==> %s:\e[1m%d\e[0m\n", \
- src, psrc, dest, pdest); \
- } while(/* CONSTCOND */ 0);
- #define DISP_PROTO(s) \
- do { \
- printf("( \e[1m%s\e[0m ) ", s); \
- } while(/* CONSTCOND */ 0);
- #define DISP_PAYLOAD(p, l) \
- do { \
- int i = 0; \
- for(; i < (l) && (p); ++i, ++(p)) \
- if(isprint(*(p))) \
- putchar((char)*(p)); \
- } while(/* CONSTCOND */ 0);
- #define BYE(s, er) \
- do { \
- fprintf(stderr, s": (%s)\n", er); \
- exit(EXIT_FAILURE); \
- } while(/* CONSTCOND */ 0);
- #define PKT_ERROR(r, s, a) \
- do { \
- fprintf(stderr, " PKT_ERROR: %s (%u)\n", s, a); \
- return r; \
- } while(/* CONSTCOND */ 0); \
- /* Option const */
- #define FILTER "ip"
- #define TIMEOUT (10)
- #define SNAPLEN (SHRT_MAX)
- /*
- * Ethernet packet format
- */
- #define ETHERNET_SIZE (14)
- #define ETHERNET_ALEN (6)
- struct ethernet_header
- {
- unsigned char ether_dhost[ETHERNET_ALEN]; /* Destination ethernet address */
- unsigned char ether_shost[ETHERNET_ALEN]; /* Source ethernet adress */
- unsigned short ether_type; /* Packet type, id field */
- };
- /*
- * Ip packet format (tcpdump way)
- */
- #define IP_V(ip) (((ip)->ip_vhl & 0xf0) >> 4)
- #define IP_HL(ip) ((ip)->ip_vhl & 0x0f)
- #define IP_DF (0x4000) /* Dont fragment flag */
- #define IP_MF (0x2000) /* More fragments flag */
- #define IP_OFFMASK (0x1fff) /* Mask for fragmenting bits */
- struct ip_header
- {
- unsigned char ip_vhl; /* Header length, version */
- unsigned char ip_tos; /* Type of service */
- unsigned short ip_len; /* Total length */
- unsigned short ip_id; /* Identification */
- unsigned short ip_off; /* Fragment offset field */
- unsigned char ip_ttl; /* Time to live */
- unsigned char ip_p; /* Protocol */
- unsigned short ip_sum; /* Checksum */
- struct in_addr ip_src, ip_dst; /* Source and dest address */
- };
- /*
- * TCP packet format
- */
- #define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
- #define TH_FIN (0x01)
- #define TH_SYN (0x02)
- #define TH_RST (0x04)
- #define TH_PUSH (0x08)
- #define TH_ACK (0x10)
- #define TH_URG (0x20)
- #define TH_ECE (0x40)
- #define TH_CWR (0x80)
- #define TH_FLAGS (0xf7) /* TH_* */
- struct tcp_header
- {
- unsigned short th_sport; /* Source port */
- unsigned short th_dport; /* Destination port */
- unsigned int th_seq; /* Sequence number */
- unsigned int th_ack; /* Acknowledgement number */
- unsigned char th_offx2; /* Data offset, rsvd */
- unsigned char th_flags; /* Flags bitfield */
- unsigned short th_win; /* Window */
- unsigned short th_sum; /* Checksum */
- unsigned short th_urp; /* Urgent pointer */
- };
- /* Function protos */
- int pkt_tcp_handle(void *, void *);
- /* Usefull things */
- const struct
- {
- unsigned int p;
- int (*f)(void *, void*);
- char name[32];
- } protos[] =
- {
- { IPPROTO_IP, NULL, "IP" }, /* _IP 0 */
- { IPPROTO_ICMP, NULL, "ICMP" }, /* _ICMP 1 */
- { IPPROTO_TCP, pkt_tcp_handle, "TCP" }, /* _TCP 6 */
- { IPPROTO_UDP, NULL, "UDP" }, /* _UDP 17 */
- { -1, NULL, ""}
- };
- /* As defined in man: */
- char errbuf[PCAP_ERRBUF_SIZE];
- /*
- * Handle TCP packets
- */
- int
- pkt_tcp_handle(void *pkt, void *prev_pkt)
- {
- const struct tcp_header *tcp;
- const struct ip_header *ip;
- int len;
- ip = (struct ip_header*)prev_pkt;
- tcp = (struct tcp_header*)(pkt + ETHERNET_SIZE + (IP_HL(ip) << 2));
- if((len = TH_OFF(tcp) << 2) < 20)
- PKT_ERROR(0, "Invalid IP header length:", len);
- IP_SRCDEST(inet_ntoa(ip->ip_src), ntohs(tcp->th_sport), /* src */
- inet_ntoa(ip->ip_dst), ntohs(tcp->th_dport)); /* dest */
- return len;
- }
- /*
- * Handle every packet, point it to corresponding pkt_proto_handle
- */
- void
- pkt_handle(unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet)
- {
- struct ethernet_header *eth;
- struct ip_header *ip;
- const unsigned char *payload;
- int len, plen, paylen, i = 0;
- bool pfound = false;
- /* Translate ethernet pkt */
- eth = (struct ethernet_header*)packet;
- /* Translate ip pkt */
- ip = (struct ip_header*)(packet + ETHERNET_SIZE);
- /* Check ipv4 */
- if((len = IP_HL(ip) << 2) < 20)
- PKT_ERROR(, "Invalid IP header length:", len);
- /* Protocol */
- for(; i < LEN(protos); ++i)
- if(ip->ip_p == protos[i].p)
- {
- DISP_PROTO(protos[i].name);
- if(protos[i].f)
- plen = protos[i].f((void*)packet, (void*)ip);
- pfound = true;
- break;
- }
- /* Unknown protocol */
- if(!pfound)
- {
- DISP_PROTO("unknown");
- IP_SRCDEST(inet_ntoa(ip->ip_src), -1, /* src */
- inet_ntoa(ip->ip_dst), -1); /* dest */
- puts("\n");
- return;
- }
- /* Get / Display payload */
- payload = (unsigned char*)(packet + ETHERNET_SIZE + len + plen);
- if((paylen = ntohs(ip->ip_len) - (len + plen)) > 0)
- DISP_PAYLOAD(payload, paylen);
- puts("\n");
- return;
- }
- int
- main(int argc, char **argv)
- {
- char *dev;
- bpf_u_int32 mask;
- bpf_u_int32 netip;
- pcap_t *descr;
- struct bpf_program bpf;
- if(argc < 2)
- {
- fprintf(stderr, "%s usage: %s <interface>\n", argv[0], argv[0]);
- exit(EXIT_FAILURE);
- }
- /* Find adress & mask */
- if(pcap_lookupnet(argv[1], &netip, &mask, errbuf) < 0)
- {
- fprintf(stderr, "Can't find Adress or Mask: (%s)\n", errbuf);
- netip = mask = 0;
- }
- /* Open device and reaaad */
- if(!(descr = pcap_open_live(argv[1], SNAPLEN, true, TIMEOUT, errbuf)))
- BYE("Fail at opening and reading device", errbuf);
- /* Check if packet is from ethernet device */
- if(pcap_datalink(descr) != DLT_EN10MB)
- BYE("Device is not an Ethernet", dev);
- /* Parse & set pcap with option expression */
- if(pcap_compile(descr, &bpf, FILTER, 0, netip) < 0)
- BYE("Option parse error", pcap_geterr(descr));
- if(pcap_setfilter(descr, &bpf) < 0)
- BYE("Can't use option", pcap_geterr(descr));
- printf("%d\n", 1<<1);
- pcap_loop(descr, 10, pkt_handle, NULL);
- pcap_freecode(&bpf);
- pcap_close(descr);
- return 0;
- }
|