netsniff-ng: Allow to compile without libnl
[netsniff-ng-new.git] / staging / mopsrx_arp.c
blob132c7ef0c62b619dc168a82f579dd0d39f1c73bb
1 /*
2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008-2010 Herbert Haas
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License version 2 as published by the
7 * Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html
19 #include "mz.h"
20 #include "mops.h"
21 #include "cli.h"
22 #include "locking.h"
24 static struct mutexlock pcap_init_lock = MUTEXLOCK_INITIALIZER;
26 // Starts an ARP RX thread for *every* device in the device_list.
27 // (Except for the loopback interface)
28 //
29 // RETURN VALUE: 0 upon success,
30 // 1 upon error.
31 //
32 int mops_rx_arp(void)
34 int i;
36 for (i=0; i<device_list_entries; i++) {
37 if (mz_strcmp(device_list[i].dev, "lo", 2)==0) continue; // omit loopback!
38 if (pthread_create( &(device_list[i].arprx_thread),
39 NULL,
40 rx_arp,
41 &device_list[i])) { // give thread a pointer to that device_list entry
42 printf("xxxxxxxxxx\n");
43 return 1; // Error creating thread
44 } else {
45 if (verbose) {
46 fprintf(stderr, " Started ARP monitor on device %s.\n",
47 device_list[i].dev);
51 return 0;
55 // Thread function to receive ARP responses for a given device.
56 // Runs forever - until Mausezahn stops (see clean_up())
57 //
58 // Argument: pointer to device_struct!
59 //
60 //
61 //
62 void *rx_arp (void *arg)
64 char errbuf[PCAP_ERRBUF_SIZE];
65 struct pcap *p_arp;
66 struct bpf_program filter;
67 char filter_str[] = "arp"; // We want to analyze both requests and responses!
68 struct device_struct *dev = (struct device_struct*) arg;
70 // FYI, possible filter string is also:
71 // "eth.dst==00:05:4e:51:01:b5 and arp and arp.opcode==2";
73 mutexlock_lock(&pcap_init_lock);
75 p_arp = pcap_open_live (dev->dev,
76 100, // max num of bytes to read
77 1, // 1 if promiscuous mode
78 PCAP_READ_TIMEOUT_MSEC, // read timeout 'until error' (-1 = indefinitely)
79 errbuf);
81 if (p_arp == NULL) {
82 fprintf(stderr," rx_arp: [ERROR] %s\n",errbuf);
83 goto exit_unlock;
86 dev->p_arp = p_arp; // also assign pointer to a global which is needed for clean_up
88 if ( pcap_compile(p_arp,
89 &filter, // the compiled version of the filter
90 filter_str, // text version of filter
91 0, // 1 = optimize
92 0) // netmask
93 == -1) {
94 fprintf(stderr," rx_arp: [ERROR] Error calling pcap_compile\n");
95 goto exit_unlock;
98 if ( pcap_setfilter(p_arp, &filter) == -1) {
99 fprintf(stderr," rx_arp: [ERROR] Error setting pcap filter\n");
100 pcap_perror(p_arp, " rx_arp: ");
101 goto exit_unlock;
104 if (pcap_setdirection(p_arp, PCAP_D_IN) == -1) {
105 pcap_perror(p_arp, " rx_arp: ");
106 goto exit_unlock;
109 mutexlock_unlock(&pcap_init_lock);
111 again:
112 pcap_loop (p_arp,
113 1, // number of packets to wait
114 got_arp_packet, // name of callback function
115 (u_char*) dev); // optional additional arguments for callback function
116 goto again;
118 pthread_exit(NULL); // destroy thread
119 return NULL;
121 exit_unlock:
122 mutexlock_unlock(&pcap_init_lock);
123 return NULL;
127 void got_arp_packet (u_char *args,
128 const struct pcap_pkthdr *header, // statistics about the packet (see 'struct pcap_pkthdr')
129 const u_char *packet) // the bytestring sniffed
131 const struct struct_ethernet *ethernet;
132 const struct struct_arp *arp;
133 int size_ethernet = sizeof(struct struct_ethernet);
134 struct device_struct *dev = (struct device_struct*) args;
136 u_int8_t
137 da[6], // eth da
138 sa[6], // eth sa
139 smac[6], // source hw address
140 sip[4], // source protocol address
141 tmac[6], // target hw address
142 tip[4]; // target protocol address
143 u_int16_t op; // operation
144 u_int32_t sec, nsec;
145 u_int8_t *x;
147 // These are the most important lines here:
148 ethernet = (struct struct_ethernet*)(packet);
149 arp = (struct struct_arp*)(packet+size_ethernet);
150 sec = (u_int32_t) header->ts.tv_sec;
151 nsec = (u_int32_t) ((header->ts.tv_usec) * 1000);
153 op = arp->arp_op; // note that we don't have network byte order anymore!
154 // tmact is:
155 // 100 instead of 00:01 (request)
156 // 200 instead of 00:02 (response)
158 memcpy((void*) da, (void*) ethernet->eth_da, 6);
159 memcpy((void*) sa, (void*) ethernet->eth_sa, 6);
160 memcpy((void*) smac, (void*) arp->arp_smac, 6);
161 memcpy((void*) sip, (void*) arp->arp_sip, 4);
162 memcpy((void*) tmac, (void*) arp->arp_tmac, 6);
163 memcpy((void*) tip, (void*) arp->arp_tip, 4);
165 // Only handle the packet if it is really an ARP response!
166 ////AND if it is not sent by THIS host! (not possible, we only scan inbound!)
167 x = (u_int8_t*) & op;
168 if (*(x+1) == 0x02) {
169 // ARP RESPONSE: Update ARP table
170 arptable_add(dev, sa, da, smac, sip, sec, nsec);
171 } else if (*(x+1) == 0x01) {
172 // ARP REQUEST: Detect poisoning attacks
173 arpwatch(dev, sa, da, smac, sip, tmac, tip, sec, nsec);
179 // ARP binding consists of: sip (IP) - smac (MAC)
181 // User alert, 2 possibilities:
183 // 1. Learned new binding: does smac belong to sip?
185 // 2. Alert: Mismatch of stored versus announced sip-to-smac binding
187 // In both cases user action: [Learn] [Ignore] [Attack] [Amok Attack]
188 // Countermeasures: Mausezahn him!
190 // ALSO correct ARP tables of other hosts, especially on the default gateway
191 // that is, send arp replies with true binding
193 // Finally: Create logging message
199 // Add new entry in device-specific ARP table
200 // but first check if already existing or change.
202 // RETURN VALUE: 0 upon success
203 // 1 upon error
205 int arptable_add(struct device_struct *dev,
206 u_int8_t *sa,
207 u_int8_t *da,
208 u_int8_t *smac,
209 u_int8_t *sip,
210 u_int32_t sec,
211 u_int32_t nsec)
213 struct arp_table_struct *prev=NULL, *cur = dev->arp_table;
214 int i=0, alert=0;
216 // If SA and SMAC are different this might be a MITM !!!
217 if (compare_mac(smac, sa)) alert=1;
219 // Check if IP (sip) is already existing in arp table:
220 while (cur!=NULL) {
221 if (compare_ip(sip, cur->sip)==0) { // IP found!
222 timestamp_hms(cur->when);
223 if (da[0]==0xff) cur->bc_resp++;
224 else cur->uni_resp++;
225 if (compare_mac(smac, cur->smac)==0) {
226 // entry identical !
227 cur->sec=sec;
228 cur->nsec=nsec;
229 return 0;
230 } else {
231 // entry with other MAC address found !
232 if (cur->locked==0) {
233 cur->changed++;
234 memcpy((void*) cur->smac_prev, (void*) cur->smac, 6);
235 memcpy((void*) cur->smac, (void*) smac, 6);
236 cur->sec_prev=cur->sec;
237 cur->nsec_prev=cur->nsec;
238 cur->sec=sec;
239 cur->nsec=nsec;
240 if (alert) cur->flags|=0x02;
242 return 0;
245 prev = cur;
246 cur = cur->next;
247 i++;
250 // If we get here, then there was no entry for that IP yet!
251 // Create new arp_table entry:
252 cur = (struct arp_table_struct *) malloc(sizeof(struct arp_table_struct));
253 if (cur==NULL) return 1;
255 // Append element:
256 if (dev->arp_table==NULL) dev->arp_table = cur;
257 else prev->next = cur;
259 memcpy((void*) cur->sa, (void*) sa, 6);
260 memcpy((void*) cur->smac, (void*) smac, 6);
261 cur->smac_prev[0]=0x00;
262 cur->smac_prev[1]=0x00;
263 cur->smac_prev[2]=0x00;
264 cur->smac_prev[3]=0x00;
265 cur->smac_prev[4]=0x00;
266 cur->smac_prev[5]=0x00;
267 memcpy((void*) cur->sip, (void*) sip, 4);
268 if (da[0]==0xff) {
269 cur->bc_resp=1;
270 cur->uni_resp=0;
271 } else {
272 cur->bc_resp=0;
273 cur->uni_resp=1;
275 cur->changed=1;
276 cur->locked=0;
277 cur->dynamic=1;
278 cur->flags=0;
279 cur->sec=sec;
280 cur->nsec=nsec;
281 cur->sec_prev=0;
282 cur->nsec_prev=0;
283 cur->index=i+1; // I assume users prefer to count from 1.
284 timestamp_hms(cur->when);
285 if (alert) cur->flags|=0x02;
286 cur->next=NULL;
287 return 0;
292 // Validate ARP requests
293 int arpwatch(struct device_struct *dev,
294 u_int8_t *sa,
295 u_int8_t *da,
296 u_int8_t *smac,
297 u_int8_t *sip,
298 u_int8_t *tmac,
299 u_int8_t *tip,
300 u_int32_t sec,
301 u_int32_t nsec)
303 // Unicast requests are considered as anomaly
305 if ((da[0]&0x01)==0) { // broadcast bit NOT set?
306 fprintf(stderr, "NOTE: Non-broadcast ARP request from %02x:%02x:%02x:%02x:%02x:%02x\n",
307 sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
310 return 0;