-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsnooper.c
202 lines (186 loc) · 7.9 KB
/
snooper.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/* snooper.c
*
* Copyright (c) 2000 Sean Walton and Macmillan Publishers. Use may be in
* whole or in part in accordance to the General Public License (GPL).
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*****************************************************************************/
/*** snooper.c ***/
/*** ***/
/*** This program captures *all* packets that the network interface sees. ***/
/*** Be very careful with this tool, because you may see all lot of info. ***/
/*** Also, it uses the deprecated SOCK_PACKET socket type. The newer and ***/
/*** preferred method is with PF_PACKET. ***/
/*****************************************************************************/
#include <stdio.h>
#include <sys/socket.h>
#include <resolv.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/types.h>
#include <linux/if_ether.h>
#define IP_SIZE 4
#define ETH_SIZE 6
typedef enum { eETH_ADDR, eIP_ADDR } EAddress;
typedef unsigned char uchar;
/*--------------------------------------------------------------------*/
/* Ethernet Frame */
/* */
/* This structure defines the fields within the ethernet frame. Since */
/* this programs gets the lowest-level packet, fragmented packets are */
/* not reassembled. The first few fields contain the MAC addresses */
/* of the source and destination. Note that this structure is set for */
/* little-endian format. */
/*--------------------------------------------------------------------*/
struct ip_packet {
struct {
uchar dst_eth[ETH_SIZE];
uchar src_eth[ETH_SIZE];
uchar __unknwn[2];
} hw_header; /* hardware header */
uint header_len:4; /* header length in words in 32bit words */
uint version:4; /* 4-bit version */
uint serve_type:8; /* how to service packet */
uint packet_len:16; /* total size of packet in bytes */
uint ID:16; /* fragment ID */
uint frag_offset:13; /* to help reassembly */
uint more_frags:1; /* flag for "more frags to follow" */
uint dont_frag:1; /* flag to permit fragmentation */
uint __reserved:1; /* always zero */
uint time_to_live:8; /* maximum router hop count */
uint protocol:8; /* ICMP, UDP, TCP */
uint hdr_chksum:16; /* ones-comp. checksum of header */
uchar IPv4_src[IP_SIZE]; /* IP address of originator */
uchar IPv4_dst[IP_SIZE]; /* IP address of destination */
uchar options[0]; /* up to 40 bytes */
uchar data[0]; /* message data up to 64KB */
};
/*--------------------------------------------------------------------*/
/* dump */
/* */
/* Dump a block of data in hex & ascii. */
/*--------------------------------------------------------------------*/
void dump(void* b, int len)
{ unsigned char *buf = b;
int i, cnt=0;
char str[17];
memset(str, 0, 17);
for ( i = 0; i < len; i++ )
{
if ( cnt % 16 == 0 )
{
printf(" %s\nX: ", str, cnt);
memset(str, 0, 17);
}
if ( buf[cnt] < ' ' || buf[cnt] >= 127 )
str[cnt] = '.';
else
str[cnt] = buf[cnt];
printf("X ", buf[cnt++]);
}
printf(" %*s\n\n", 16+(16-len)*2, str);
}
/*--------------------------------------------------------------------*/
/* PrintAddr */
/* */
/* Print the different types of address (MAC or IP). */
/*--------------------------------------------------------------------*/
void PrintAddr(char* msg, uchar *addr, EAddress is_ip)
{ int i;
static struct {
int len;
char *fmt;
char delim;
} addr_fmt[] = {{ETH_SIZE, "%x", ':'}, {IP_SIZE, "%d", '.'}};
printf("%s", msg);
for ( i = 0; i < addr_fmt[is_ip].len; i++ )
{
printf(addr_fmt[is_ip].fmt, addr[i]);
if ( i < addr_fmt[is_ip].len-1 )
putchar(addr_fmt[is_ip].delim);
}
}
/*--------------------------------------------------------------------*/
/* GetProtocol */
/* */
/* Convert the protocol value into the alphabetic representation. */
/*--------------------------------------------------------------------*/
char* GetProtocol(int value)
{
switch (value)
{
case IPPROTO_IP: return "IP";
case IPPROTO_ICMP: return "ICMP";
case IPPROTO_IGMP: return "IGMP";
case IPPROTO_IPIP: return "IPIP";
case IPPROTO_TCP: return "TCP";
case IPPROTO_EGP: return "EGP";
case IPPROTO_PUP: return "PUP";
case IPPROTO_UDP: return "UDP";
case IPPROTO_IDP: return "IDP";
case IPPROTO_RSVP: return "RSVP";
case IPPROTO_GRE: return "GRE";
case IPPROTO_IPV6: return "IPV6/4";
case IPPROTO_PIM: return "PIM";
case IPPROTO_RAW: return "RAW";
default: return "???";
}
}
/*--------------------------------------------------------------------*/
/* DumpPacket */
/* */
/* Display the read packet with data and fields. */
/*--------------------------------------------------------------------*/
void DumpPacket(char *buffer, int len)
{ struct ip_packet *ip=(void*)buffer;
printf("-------------------------------------------------\n");
dump(buffer, len);
PrintAddr("Destination EtherID=", ip->hw_header.dst_eth, eETH_ADDR);
PrintAddr(", Source EtherID=", ip->hw_header.src_eth, eETH_ADDR);
printf("\nIPv%d: header-len=%d, type=%d, packet-size=%d, ID=%d\n",
ip->version, ip->header_len*4, ip->serve_type,
ntohs(ip->packet_len), ntohs(ip->ID));
printf("frag=%c, more=%c, offset=%d, TTL=%d, protocol=%s\n",
(ip->dont_frag? 'N': 'Y'),
(ip->more_frags? 'N': 'Y'),
ip->frag_offset,
ip->time_to_live, GetProtocol(ip->protocol));
printf("checksum=%d, ", ntohs(ip->hdr_chksum));
PrintAddr("source=", ip->IPv4_src, eIP_ADDR);
PrintAddr(", destination=", ip->IPv4_dst, eIP_ADDR);
printf("\n");
fflush(stdout);
}
void PANIC(char *msg);
#define PANIC(msg) {perror(msg);exit(0);}
/*--------------------------------------------------------------------*/
/* main */
/* */
/* Open socket. Repeatedly read and display records. */
/*--------------------------------------------------------------------*/
int main()
{ int sd, bytes_read;
char data[1024];
sd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
if ( sd < 0 )
PANIC("Snooper socket");
do
{
bytes_read = recvfrom(sd, data, sizeof(data), 0, 0, 0);
if ( bytes_read > 0 )
DumpPacket(data, bytes_read);
}
while ( bytes_read > 0 );
return 0;
}