~mysqlatfacebook/mysqlatfacebook/tools

« back to all changes in this revision

Viewing changes to esniff/esniff.c

  • Committer: Domas Mituzas
  • Date: 2014-09-23 22:26:58 UTC
  • Revision ID: domas@facebook.com-20140923222658-zts5mbiqwwydw1nx
adding tiny utility to sniff MySQL errors off the wire, supports ipv6 and ipv4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
    Copyright 2010 Domas Mituzas, Facebook
 
3
 
 
4
    This program is free software: you can redistribute it and/or modify
 
5
    it under the terms of the GNU General Public License as published by
 
6
    the Free Software Foundation, either version 3 of the License, or
 
7
    (at your option) any later version.
 
8
 
 
9
    This program is distributed in the hope that it will be useful,
 
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
    GNU General Public License for more details.
 
13
 
 
14
    You should have received a copy of the GNU General Public License
 
15
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
 
 
17
*/
 
18
 
 
19
 
 
20
#include <stdio.h>
 
21
#include <stdlib.h>
 
22
#include <pcap.h>
 
23
 
 
24
#include <sys/types.h>
 
25
#include <sys/socket.h>
 
26
#include <arpa/inet.h>
 
27
#include <net/ethernet.h>
 
28
#include <netinet/in.h>
 
29
#include <netinet/ip6.h>
 
30
#include <netinet/ip.h>
 
31
#include <netinet/tcp.h>
 
32
#include <netinet/ether.h>
 
33
 
 
34
void
 
35
handle_packet (u_char * args, const struct pcap_pkthdr *header,
 
36
               const u_char * packet)
 
37
{
 
38
 
 
39
  struct tcphdr *tcp = NULL;
 
40
  struct iphdr *ip = NULL;
 
41
  struct ip6_hdr *ip6 = NULL;
 
42
 
 
43
 
 
44
  u_char *payload;
 
45
  int payload_size;
 
46
  int mysql_header, ppos;
 
47
 
 
48
  const u_char *p = packet;
 
49
 
 
50
  struct ether_header *eh = (struct ether_header *) p;
 
51
  p += sizeof (*eh);
 
52
 
 
53
  switch (ntohs (eh->ether_type))
 
54
    {
 
55
    case ETHERTYPE_IP:
 
56
      ip = (struct iphdr *) p;
 
57
      p += ip->ihl * 4;
 
58
 
 
59
      tcp = (struct tcphdr *) p;
 
60
      p += tcp->doff * 4;
 
61
 
 
62
      payload = (u_char *) p;
 
63
      payload_size = ntohs (ip->tot_len) - (payload - (u_char *) ip);
 
64
      break;
 
65
    case ETHERTYPE_IPV6:
 
66
      ip6 = (struct ip6_hdr *) p;
 
67
      p += sizeof (*ip6);
 
68
 
 
69
      tcp = (struct tcphdr *) p;
 
70
      p += tcp->doff * 4;
 
71
 
 
72
      payload = (u_char *) p;
 
73
      payload_size = ntohs (ip6->ip6_plen) - (payload - (u_char *) tcp);
 
74
      break;
 
75
    }
 
76
 
 
77
  /* No payload or not an error */
 
78
  if (payload_size < 10 || (u_char) payload[4] != 255 || payload_size > 600)
 
79
    return;
 
80
 
 
81
  /* This actually tries to ensure this _is_ error packet, though not firmly :-) */
 
82
  mysql_header = (int) payload[0];
 
83
  if (mysql_header + 4 != payload_size)
 
84
    return;
 
85
 
 
86
  ppos = payload[7] == '#' ? 13 : 7;
 
87
 
 
88
  char s[INET6_ADDRSTRLEN];
 
89
  if (ip6)
 
90
    inet_ntop (AF_INET6, &ip6->ip6_dst, s, sizeof (s));
 
91
  else if (ip)
 
92
    inet_ntop (AF_INET, &ip->daddr, s, sizeof (s));
 
93
 
 
94
  printf ("%s: %.*s\n", s, payload_size - ppos, payload + ppos);
 
95
}
 
96
 
 
97
int
 
98
main (int argc, char *argv[])
 
99
{
 
100
  char *dev, errbuf[PCAP_ERRBUF_SIZE];
 
101
  char filter[] = "tcp src portrange 3300-3350";
 
102
  struct bpf_program fp;
 
103
 
 
104
  dev = pcap_lookupdev (errbuf);
 
105
  if (dev == NULL)
 
106
    {
 
107
      fprintf (stderr, "Couldn't find default device: %s\n", errbuf);
 
108
      return (2);
 
109
    }
 
110
 
 
111
  pcap_t *handle = pcap_open_live (dev, BUFSIZ, 0, 1000, errbuf);
 
112
  if (!handle)
 
113
    {
 
114
      fprintf (stderr, "Could not open device %s: %s\n", dev, errbuf);
 
115
    }
 
116
 
 
117
  if (pcap_compile (handle, &fp, filter, 0, 0) == -1)
 
118
    {
 
119
      fprintf (stderr, "Could not parse filter %s: %s\n", filter,
 
120
               pcap_geterr (handle));
 
121
      return (2);
 
122
    }
 
123
 
 
124
 
 
125
  if (pcap_setfilter (handle, &fp) == -1)
 
126
    {
 
127
      fprintf (stderr, "Couldn't install filter %s: %s\n", filter,
 
128
               pcap_geterr (handle));
 
129
      return (2);
 
130
    }
 
131
 
 
132
  pcap_loop (handle, -1, handle_packet, NULL);
 
133
 
 
134
  return (0);
 
135
}