2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008-2010 Herbert Haas
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.
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
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
23 // Starts an ARP RX thread for *every* device in the device_list.
24 // (Except for the loopback interface)
26 // RETURN VALUE: 0 upon success,
33 for (i
=0; i
<device_list_entries
; i
++) {
34 if (mz_strcmp(device_list
[i
].dev
, "lo", 2)==0) continue; // omit loopback!
35 if (pthread_create( &(device_list
[i
].arprx_thread
),
38 &device_list
[i
])) { // give thread a pointer to that device_list entry
39 printf("xxxxxxxxxx\n");
40 return 1; // Error creating thread
43 fprintf(stderr
, " Started ARP monitor on device %s.\n",
52 // Thread function to receive ARP responses for a given device.
53 // Runs forever - until Mausezahn stops (see clean_up())
55 // Argument: pointer to device_struct!
59 void *rx_arp (void *arg
)
61 char errbuf
[PCAP_ERRBUF_SIZE
];
63 struct bpf_program filter
;
64 char filter_str
[] = "arp"; // We want to analyze both requests and responses!
65 struct device_struct
*dev
= (struct device_struct
*) arg
;
67 // FYI, possible filter string is also:
68 // "eth.dst==00:05:4e:51:01:b5 and arp and arp.opcode==2";
70 p_arp
= pcap_open_live (dev
->dev
,
71 100, // max num of bytes to read
72 1, // 1 if promiscuous mode
73 PCAP_READ_TIMEOUT_MSEC
, // read timeout 'until error' (-1 = indefinitely)
77 fprintf(stderr
," rx_arp: [ERROR] %s\n",errbuf
);
78 return NULL
; // TODO: Should return pointer to error message or something similar
81 dev
->p_arp
= p_arp
; // also assign pointer to a global which is needed for clean_up
83 if ( pcap_compile(p_arp
,
84 &filter
, // the compiled version of the filter
85 filter_str
, // text version of filter
89 fprintf(stderr
," rx_arp: [ERROR] Error calling pcap_compile\n");
93 if ( pcap_setfilter(p_arp
, &filter
) == -1) {
94 fprintf(stderr
," rx_arp: [ERROR] Error setting pcap filter\n");
95 pcap_perror(p_arp
, " rx_arp: ");
99 if (pcap_setdirection(p_arp
, PCAP_D_IN
) == -1) {
100 pcap_perror(p_arp
, " rx_arp: ");
106 1, // number of packets to wait
107 got_arp_packet
, // name of callback function
108 (u_char
*) dev
); // optional additional arguments for callback function
111 pthread_exit(NULL
); // destroy thread
116 void got_arp_packet (u_char
*args
,
117 const struct pcap_pkthdr
*header
, // statistics about the packet (see 'struct pcap_pkthdr')
118 const u_char
*packet
) // the bytestring sniffed
120 const struct struct_ethernet
*ethernet
;
121 const struct struct_arp
*arp
;
122 int size_ethernet
= sizeof(struct struct_ethernet
);
123 struct device_struct
*dev
= (struct device_struct
*) args
;
128 smac
[6], // source hw address
129 sip
[4], // source protocol address
130 tmac
[6], // target hw address
131 tip
[4]; // target protocol address
132 u_int16_t op
; // operation
136 // These are the most important lines here:
137 ethernet
= (struct struct_ethernet
*)(packet
);
138 arp
= (struct struct_arp
*)(packet
+size_ethernet
);
139 sec
= (u_int32_t
) header
->ts
.tv_sec
;
140 nsec
= (u_int32_t
) ((header
->ts
.tv_usec
) * 1000);
142 op
= arp
->arp_op
; // note that we don't have network byte order anymore!
144 // 100 instead of 00:01 (request)
145 // 200 instead of 00:02 (response)
147 memcpy((void*) da
, (void*) ethernet
->eth_da
, 6);
148 memcpy((void*) sa
, (void*) ethernet
->eth_sa
, 6);
149 memcpy((void*) smac
, (void*) arp
->arp_smac
, 6);
150 memcpy((void*) sip
, (void*) arp
->arp_sip
, 4);
151 memcpy((void*) tmac
, (void*) arp
->arp_tmac
, 6);
152 memcpy((void*) tip
, (void*) arp
->arp_tip
, 4);
154 // Only handle the packet if it is really an ARP response!
155 ////AND if it is not sent by THIS host! (not possible, we only scan inbound!)
156 x
= (u_int8_t
*) & op
;
157 if (*(x
+1) == 0x02) {
158 // ARP RESPONSE: Update ARP table
159 arptable_add(dev
, sa
, da
, smac
, sip
, sec
, nsec
);
160 } else if (*(x
+1) == 0x01) {
161 // ARP REQUEST: Detect poisoning attacks
162 arpwatch(dev
, sa
, da
, smac
, sip
, tmac
, tip
, sec
, nsec
);
168 // ARP binding consists of: sip (IP) - smac (MAC)
170 // User alert, 2 possibilities:
172 // 1. Learned new binding: does smac belong to sip?
174 // 2. Alert: Mismatch of stored versus announced sip-to-smac binding
176 // In both cases user action: [Learn] [Ignore] [Attack] [Amok Attack]
177 // Countermeasures: Mausezahn him!
179 // ALSO correct ARP tables of other hosts, especially on the default gateway
180 // that is, send arp replies with true binding
182 // Finally: Create logging message
188 // Add new entry in device-specific ARP table
189 // but first check if already existing or change.
191 // RETURN VALUE: 0 upon success
194 int arptable_add(struct device_struct
*dev
,
202 struct arp_table_struct
*prev
=NULL
, *cur
= dev
->arp_table
;
205 // If SA and SMAC are different this might be a MITM !!!
206 if (compare_mac(smac
, sa
)) alert
=1;
208 // Check if IP (sip) is already existing in arp table:
210 if (compare_ip(sip
, cur
->sip
)==0) { // IP found!
211 timestamp_hms(cur
->when
);
212 if (da
[0]==0xff) cur
->bc_resp
++;
213 else cur
->uni_resp
++;
214 if (compare_mac(smac
, cur
->smac
)==0) {
220 // entry with other MAC address found !
221 if (cur
->locked
==0) {
223 memcpy((void*) cur
->smac_prev
, (void*) cur
->smac
, 6);
224 memcpy((void*) cur
->smac
, (void*) smac
, 6);
225 cur
->sec_prev
=cur
->sec
;
226 cur
->nsec_prev
=cur
->nsec
;
229 if (alert
) cur
->flags
|=0x02;
239 // If we get here, then there was no entry for that IP yet!
240 // Create new arp_table entry:
241 cur
= (struct arp_table_struct
*) malloc(sizeof(struct arp_table_struct
));
242 if (cur
==NULL
) return 1;
245 if (dev
->arp_table
==NULL
) dev
->arp_table
= cur
;
246 else prev
->next
= cur
;
248 memcpy((void*) cur
->sa
, (void*) sa
, 6);
249 memcpy((void*) cur
->smac
, (void*) smac
, 6);
250 cur
->smac_prev
[0]=0x00;
251 cur
->smac_prev
[1]=0x00;
252 cur
->smac_prev
[2]=0x00;
253 cur
->smac_prev
[3]=0x00;
254 cur
->smac_prev
[4]=0x00;
255 cur
->smac_prev
[5]=0x00;
256 memcpy((void*) cur
->sip
, (void*) sip
, 4);
272 cur
->index
=i
+1; // I assume users prefer to count from 1.
273 timestamp_hms(cur
->when
);
274 if (alert
) cur
->flags
|=0x02;
281 // Validate ARP requests
282 int arpwatch(struct device_struct
*dev
,
292 // Unicast requests are considered as anomaly
294 if ((da
[0]&0x01)==0) { // broadcast bit NOT set?
295 fprintf(stderr
, "NOTE: Non-broadcast ARP request from %02x:%02x:%02x:%02x:%02x:%02x\n",
296 sa
[0], sa
[1], sa
[2], sa
[3], sa
[4], sa
[5]);