forked from timbrom/simple_sniffer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
simple_sniffer.c
134 lines (115 loc) · 3.79 KB
/
simple_sniffer.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
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <netinet/if_ether.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
/** PCAP file header */
typedef struct pcap_hdr_s {
uint32_t magic_number; /* magic number */
uint16_t version_major; /* major version number */
uint16_t version_minor; /* minor version number */
int32_t thiszone; /* GMT to local correction */
uint32_t sigfigs; /* accuracy of timestamps */
uint32_t snaplen; /* max length of captured packets, in octets */
uint32_t network; /* data link type */
} pcap_hdr_t;
/** PCAP packet header */
typedef struct pcaprec_hdr_s {
uint32_t ts_sec; /* timestamp seconds */
uint32_t ts_usec; /* timestamp microseconds */
uint32_t incl_len; /* number of octets of packet saved in file */
uint32_t orig_len; /* actual length of packet */
} pcaprec_hdr_t;
const int MAX_SIZE = 16384;
static uint8_t keepRunning = 1;
void intHandler(int foo) {
keepRunning = 0;
}
int main(int argc, char** argv)
{
int saddr_size, data_size;
struct sockaddr saddr;
char buffer[MAX_SIZE];
/* Catch ctrl-c to exit cleanly */
struct sigaction act;
act.sa_handler = intHandler;
sigaction(SIGINT, &act, NULL);
/* Check arguments */
if (argc < 2)
{
printf("Usage: %s filename [interface_name]\n", argv[0]);
printf("\tIf no interface_name is specified, packets will be captured from all available interfaces");
exit(-1);
}
// Open the file to save data to
FILE *outfile = fopen(argv[1], "wb");
if(outfile == NULL)
{
perror("Unable to open file: ");
exit(-1);
}
// Set up the PCAP file header (Magic Number, Major Version, Minor Version, UTC Timezone, Accuracy, Snaplen, Link Type Ethernet)
pcap_hdr_t pcap_hdr = {0xa1b2c3d4, 2, 4, 0, 0, MAX_SIZE, 1};
fwrite((char*)&pcap_hdr, 1, sizeof(pcap_hdr_t), outfile);
int sock_raw = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(sock_raw < 0)
{
perror("Socket Error");
exit(-1);
}
if(argc == 3)
{
struct sockaddr_ll sll;
struct ifreq ifr;
printf("Sniffing on interface %s\n", argv[2]);
bzero(&sll , sizeof(sll));
bzero(&ifr , sizeof(ifr));
strncpy((char *)ifr.ifr_name, argv[2], IFNAMSIZ);
//copy device name to ifr
if((ioctl(sock_raw, SIOCGIFINDEX , &ifr)) == -1)
{
perror("Unable to find interface index");
exit(-1);
}
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
sll.sll_protocol = htons(ETH_P_ALL);
if((bind(sock_raw, (struct sockaddr *)&sll, sizeof(sll))) == -1)
{
perror("Failed to bind: ");
exit(-1);
}
}
while(keepRunning == 1)
{
saddr_size = sizeof(saddr);
data_size = recvfrom(sock_raw, buffer, MAX_SIZE, 0, &saddr, (socklen_t*)&saddr_size);
if(data_size < 0)
{
printf("Recvfrom error , failed to get packets\n");
exit(-1);
}
pcaprec_hdr_t packet_hdr;
struct timeval tv;
gettimeofday(&tv, NULL);
packet_hdr.incl_len = data_size;
packet_hdr.orig_len = data_size; // FIXME: This could be wrong if packet length was > MAX_SIZE
packet_hdr.ts_sec = tv.tv_sec;
packet_hdr.ts_usec = tv.tv_usec;
fwrite((char*)&packet_hdr, 1, sizeof(pcaprec_hdr_t), outfile);
fwrite(buffer, 1, data_size, outfile);
}
fclose(outfile);
close(sock_raw);
return 0;
}