-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathsidmat.c
More file actions
135 lines (108 loc) · 3.11 KB
/
sidmat.c
File metadata and controls
135 lines (108 loc) · 3.11 KB
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 "sidmat_common.h"
#include <pcap.h>
/* default snap length (maximum bytes per packet to capture) */
#define SNAP_LEN 1518
/* ethernet headers are always exactly 14 bytes [1] */
#define SIZE_ETHERNET 14
/*
* print help text
*/
static void
print_app_usage(char *prog)
{
printf("Usage: %s interface regex\n", prog);
printf("\n");
printf("Options:\n");
printf(" interface Listen on <interface> for packets.\n");
printf(" regex Regular expression for which you want to select DNS responses.\n");
printf("\n");
}
void
got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
/* declare pointers to packet headers */
const struct sniff_ip *ip; /* The IP header */
int size_ip;
struct user_data *data;
(void)header;
data = (struct user_data *)args;
/* define/compute ip header offset */
ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
size_ip = IP_HL(ip)*4;
if (size_ip < 20) {
fprintf(stderr, " * Invalid IP header length: %u bytes\n", size_ip);
return;
}
if (ip->ip_p != IPPROTO_UDP) {
/* Handle only UDP */
return;
}
dns_ip_packet((char *)packet + SIZE_ETHERNET, data);
}
int
main(int argc, char *argv[])
{
char *dev = NULL; /* capture device name */
char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
pcap_t *handle; /* packet capture handle */
char filter_exp[] = "port 53"; /* filter expression [3] */
struct bpf_program fp; /* compiled filter program (expression) */
bpf_u_int32 mask; /* subnet mask */
bpf_u_int32 net; /* ip */
char *opt = NULL;
struct user_data data;
data.addrs = NULL;
data.naddrs = 0;
if (argc < 3) {
print_app_usage(argv[0]);
return EXIT_FAILURE;
}
/* additional options */
if (argc == 4) {
opt = argv[3];
}
if (!sidmat_init(&data, argv[2], opt)) {
return EXIT_FAILURE;
}
dev = argv[1];
/* get network number and mask associated with capture device */
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
dev, errbuf);
net = 0;
mask = 0;
}
/* open capture device */
handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
return EXIT_FAILURE;
}
/* make sure we're capturing on an Ethernet device [2] */
if (pcap_datalink(handle) != DLT_EN10MB) {
fprintf(stderr, "%s is not an Ethernet\n", dev);
return EXIT_FAILURE;
}
/* compile the filter expression */
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n",
filter_exp, pcap_geterr(handle));
return EXIT_FAILURE;
}
/* apply the compiled filter */
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n",
filter_exp, pcap_geterr(handle));
return EXIT_FAILURE;
}
/* set output buffering mode */
setvbuf(stdout, NULL, _IOLBF, 1024);
/* now we can set our callback function */
pcap_loop(handle, 0, got_packet, (u_char *)&data);
/* FIXME: unreachable code */
/* cleanup */
pcap_freecode(&fp);
pcap_close(handle);
regfree(&data.re);
return EXIT_SUCCESS;
}