1 /* packet.c
2 *
3 * Copyright (c) 2010 SeaD <sead at deep.perm.ru>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: packet.c,v 1.19 2010/07/12 03:46:36 sead Exp $
27 *
28 */
29
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33
34 #ifdef __OpenBSD__
35 # include <net/if.h>
36 # include <net/if_arp.h>
37 #endif /* __OpenBSD__ */
38
39 #ifdef __linux__
40 # include <time.h>
41 # include <netinet/ether.h>
42 #else /* __linux__ */
43 # include <netinet/if_ether.h>
44 #endif /* __linux__ */
45
46 #include <pcap.h>
47
48 #ifndef __GLIBC__
49 # define __GLIBC__ 1
50 # include <libnet.h>
51 # undef __GLIBC__
52 #else /* __GLIBC__ */
53 # include <libnet.h>
54 #endif /* __GLIBC__ */
55
56 #include "ipguard.h"
57
58 static struct ether_addr se_addr, te_addr, sh_addr, th_addr, bh_addr, zh_addr,
59 fake_addr, pfake_addr;
60 static struct in_addr sp_addr, tp_addr, zp_addr;
61
62 static pcap_t *pcap = NULL;
63 static libnet_t *ln = NULL;
64 static char ifname[IFNAMSIZ];
65
66 static struct pair_t {
67 struct ether_addr mac;
68 struct in_addr ip;
69 struct in_addr mask;
70 } *pairs = NULL;
71 static int pair_num = 0;
72
73 static struct buffer_t {
74 struct ether_addr mac;
75 struct in_addr ip;
76 int num;
77 time_t last;
78 } *buffer = NULL;
79
buffer_init(void)80 void buffer_init(void) {
81 if ((buffer = (struct buffer_t *) malloc(sizeof(struct buffer_t) * buffer_num)) == NULL) {
82 log_str(ERROR, "malloc():", strerror(errno));
83 exit(EXIT_FAILURE);
84 }
85 }
86
buffer_destroy(void)87 void buffer_destroy(void) {
88 free(buffer);
89 }
90
buffer_add(void)91 void buffer_add(void) {
92 struct buffer_t *p = NULL, *pn = NULL;
93 register int n;
94
95 for (n = 0, p = buffer; n < buffer_num; n++, p++)
96 if (!memcmp(&sh_addr, &p->mac, sizeof(struct ether_addr))) {
97 memcpy(&p->ip, &sp_addr, sizeof(struct in_addr));
98 p->num++; p->last = time(&p->last); return;
99 }
100
101 for (n = 0, p = buffer, pn = p + 1; n < buffer_num - 1; n++, p++, pn++)
102 memcpy(p, pn, sizeof(struct buffer_t));
103 memcpy(&p->mac, &sh_addr, sizeof(struct ether_addr));
104 memcpy(&p->ip, &sp_addr, sizeof(struct in_addr));
105 p->num = 1; p->last = time(&p->last);
106 }
107
buffer_dump(void)108 void buffer_dump(void) {
109 struct buffer_t *p = NULL;
110 register int n;
111
112 snprintf(s, 64, "Bad MAC-IP buffer (%d pairs)", buffer_num);
113 log_str(INFO, s, "");
114
115 for (n = 0, p = buffer + buffer_num - 1; n < buffer_num && p->num > 0; n++, p--) {
116 snprintf(s, 64, "%03d %s %-15s %2d %lu",
117 n+1, ether_ntoa(&p->mac), inet_ntoa(p->ip), p->num, (unsigned long) p->last);
118 log_str(INFO, "dump:", s);
119 }
120 }
121
buffer_dump2ethers(void)122 void buffer_dump2ethers(void) {
123 struct buffer_t *p = NULL;
124 register int n;
125
126 for (n = 0, p = buffer + buffer_num - 1; n < buffer_num && p->num > 0; n++, p--) {
127 snprintf(s, 64, "%-17s %-15s", ether_ntoa(&p->mac), inet_ntoa(p->ip));
128 log_str(INFO, s, "");
129 }
130 }
131
bit_2mask(int bit)132 uint32_t bit_2mask(int bit) {
133 uint32_t mask = 0;
134 register int n;
135
136 for (n = 0; n < bit; n++) { mask >>= 1; mask |= 0x80000000; }
137
138 return mask;
139 }
140
pair_init(void)141 void pair_init(void) {
142 struct libnet_ether_addr *ha = NULL;
143 uint32_t pa = 0, mask;
144 int bit = 0;
145
146 if ((pairs = (struct pair_t *) malloc(sizeof(struct pair_t))) == NULL) {
147 log_str(ERROR, "malloc():", strerror(errno));
148 exit(EXIT_FAILURE);
149 }
150 if ((ha = libnet_get_hwaddr(ln)) == NULL) {
151 log_str(ERROR, libnet_geterror(ln), "");
152 exit(EXIT_FAILURE);
153 }
154 if (!(pa = libnet_get_ipaddr4(ln))) {
155 log_str(ERROR, libnet_geterror(ln), "");
156 exit(EXIT_FAILURE);
157 }
158 mask = htonl(bit_2mask(bit));
159 if (!nofirst) {
160 memcpy(&pairs->mac, ha, sizeof(struct ether_addr));
161 memcpy(&pairs->ip, &pa, sizeof(struct in_addr));
162 memcpy(&pairs->mask, &mask, sizeof(struct in_addr));
163 pair_num++;
164
165 if (debug > 1)
166 fprintf(stderr, "PAIR ADD FIRST: %s %s %u\n",
167 ether_ntoa(&pairs->mac), inet_ntoa(pairs->ip), bit);
168 }
169 }
170
pair_destroy(void)171 void pair_destroy(void) {
172 free(pairs);
173 pair_num = 0;
174 }
175
pair_add(char * mac,char * ip)176 void pair_add(char *mac, char *ip) {
177 struct pair_t *p = NULL;
178 struct ether_addr *fmac = NULL;
179 uint32_t fip, mask;
180 char *m;
181 int bit;
182
183 if ((m = strchr(ip, '/'))) {
184 *m++ = '\0'; bit = atoi(m);
185 if (!bit || (bit < 0) || (bit > 32)) {
186 log_str(NOTICE, "Wrong mask", m); return;
187 }
188 if (debug > 2) fprintf(stderr, "NETWORK MASK: %s %u\n", ip, bit);
189 } else bit = 0;
190
191 if ((fmac = ether_aton(mac)) == NULL) {
192 if (verbose) log_str(WARNING, "Invalid MAC:", mac); return;
193 }
194 if ((fip = libnet_name2addr4(ln, ip, LIBNET_RESOLVE)) == -1) {
195 if (verbose) log_str(WARNING, "Host unknown:", ip); return;
196 }
197
198 mask = htonl(bit_2mask(bit));
199 if (mask) fip &= mask;
200
201 if ((pairs = realloc(pairs, ++pair_num * sizeof(struct pair_t))) == NULL) {
202 log_str(ERROR, "realloc():", strerror(errno));
203 exit(EXIT_FAILURE);
204 }
205 p = pairs + pair_num - 1;
206
207 memcpy(&p->mac, fmac, sizeof(struct ether_addr));
208 memcpy(&p->ip, &fip, sizeof(struct in_addr));
209 memcpy(&p->mask, &mask, sizeof(struct in_addr));
210
211 if (debug > 1)
212 fprintf(stderr, "PAIR ADD: %s %s %u\n",
213 ether_ntoa(&p->mac), inet_ntoa(p->ip), bit);
214 }
215
pair_dump(void)216 void pair_dump(void) {
217 struct pair_t *p = pairs;
218 char ntoasw[16];
219 register int n;
220
221 snprintf(s, 64, "Current MAC-IP table (%d pairs)", pair_num);
222 log_str(INFO, s, "");
223
224 for (n = 0; n < pair_num; n++, p++) {
225 strncpy(ntoasw, inet_ntoa(p->mask), 16);
226 snprintf(s, 64, "%s %s %s",
227 ether_ntoa(&p->mac), inet_ntoa(p->ip), ntoasw);
228 log_str(INFO, "dump:", s);
229 }
230 }
231
packet_fmacs(int op)232 void packet_fmacs(int op) {
233 switch (op) {
234 /* init */
235 case 1: mac_rand(fmac); strncpy(pfmac, fmac, 18); break;
236 /* regenerate */
237 case 2: strncpy(pfmac, fmac, 18); mac_regen(fmac); break;
238 }
239
240 memcpy(&fake_addr, ether_aton(fmac), sizeof(struct ether_addr));
241 memcpy(&pfake_addr, ether_aton(pfmac), sizeof(struct ether_addr));
242 }
243
packet_init(char * iface)244 void packet_init(char *iface) {
245 struct bpf_program arp_p;
246 char ebuf[PCAP_ERRBUF_SIZE] = "\0";
247
248 strncpy(ifname, iface, IFNAMSIZ);
249 memset(&bh_addr, 0xff, sizeof(struct ether_addr));
250 memset(&zh_addr, 0x00, sizeof(struct ether_addr));
251 memset(&zp_addr, 0x00, sizeof(struct in_addr));
252 packet_fmacs(1);
253
254 /* pcap init */
255 if (!(pcap = pcap_open_live(ifname, 100, promisc, 10, ebuf))) {
256 debug = 2; log_str(ERROR, "pcap_open_live():", ebuf);
257 exit(EXIT_FAILURE);
258 }
259 if (strlen(ebuf)) fprintf(stderr, "warning: %s\n", ebuf);
260 if (pcap_compile(pcap, &arp_p, pcapf, 0, -1) == -1) {
261 snprintf(s, 128, "pcap_compile(%s):", pcapf);
262 debug = 2; log_str(ERROR, s, "wrong expression");
263 exit(EXIT_FAILURE);
264 }
265 if (pcap_setfilter(pcap, &arp_p) == -1) {
266 debug = 2; log_str(ERROR, "pcap_setfilter():", "failed");
267 exit(EXIT_FAILURE);
268 }
269
270 /* libnet init */
271 if (!(ln = libnet_init(LIBNET_LINK_ADV, ifname, ebuf))) {
272 debug = 2; log_str(ERROR, ebuf, "");
273 exit(EXIT_FAILURE);
274 }
275
276 pair_init();
277 if (buffer_num) buffer_init();
278 ethers_init();
279
280 snprintf(s, 128, "%s %s %s (%d pairs) fake %s%s",
281 iface, ether_ntoa(&pairs->mac), inet_ntoa(pairs->ip), pair_num, fmac,
282 (read_only ? " RO mode" : ""));
283 log_str(NOTICE, s, "");
284 if (verbose) pair_dump();
285 }
286
packet_destroy(void)287 void packet_destroy (void) {
288 if (buffer_num) buffer_destroy();
289 pair_destroy();
290 libnet_destroy(ln);
291 pcap_close(pcap);
292 }
293
packet_send(int op,int num)294 void packet_send(int op, int num) {
295 register int n;
296
297 if (libnet_build_arp(ARPHRD_ETHER, ETHERTYPE_IP, 6, 4, op,
298 (u_char *) &sh_addr, (u_char *) &sp_addr,
299 (u_char *) &th_addr, (u_char *) &tp_addr,
300 NULL, 0, ln, 0) == -1) {
301 log_str(ERROR, libnet_geterror(ln), "");
302 exit(EXIT_FAILURE);
303 }
304
305 if (libnet_build_ethernet(
306 (u_char *) &te_addr, (u_char *) &se_addr,
307 ETHERTYPE_ARP, NULL, 0, ln, 0) == -1) {
308 log_str(ERROR, libnet_geterror(ln), "");
309 exit(EXIT_FAILURE);
310 }
311
312 if ((n = num)) while (1) {
313 if (debug > 1) {
314 fprintf(stderr, "SEND ARP %u: ", op);
315 fprintf(stderr, "%-17s -> ", ether_ntoa(&se_addr)); fprintf(stderr, "%-17s\n ", ether_ntoa(&te_addr));
316 fprintf(stderr, "sdr %-17s %-15s ", ether_ntoa(&sh_addr), inet_ntoa(sp_addr));
317 fprintf(stderr, "trg %-17s %-15s\n", ether_ntoa(&th_addr), inet_ntoa(tp_addr));
318 }
319 if (!read_only)
320 if (libnet_write(ln) == -1) {
321 log_str(ERROR, libnet_geterror(ln), "");
322 exit_ipguard(EXIT_FAILURE);
323 }
324 if (--n <= 0) break; else usleep(fake_time * 1000);
325 }
326
327 libnet_clear_packet(ln);
328 }
329
packet_check(void)330 void packet_check(void) {
331 struct pair_t *p = NULL;
332 struct pair_t *se_ch = NULL, *te_ch = NULL, *sp_ch = NULL, *tp_ch = NULL;
333 uint32_t fsip, ftip, fmask, swip;
334 int bsdr = 0;
335 char ntoasw[16];
336 register int n;
337
338 /* count mismatch MACs between ether and ARP headers */
339 if (memcmp(&se_addr, &sh_addr, sizeof(struct ether_addr))) {
340 if (debug > 1) {
341 strncpy(ntoasw, inet_ntoa(tp_addr), 16);
342 fprintf(stderr, "MISMATCH SOURCE: %-17s %-15s %-15s\n", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
343 }
344 mis++;
345 }
346 /* count non-zero target MAC in ARP who-has */
347 if (memcmp(&zh_addr, &th_addr, sizeof(struct ether_addr))) {
348 if (debug > 1) {
349 strncpy(ntoasw, inet_ntoa(tp_addr), 16);
350 fprintf(stderr, "NON-ZERO TARGET: %-17s %-15s %-15s\n", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
351 }
352 nzh++;
353 }
354 /* count non-bcast target ether MAC */
355 if (memcmp(&bh_addr, &te_addr, sizeof(struct ether_addr))) {
356 if (debug > 1) {
357 strncpy(ntoasw, inet_ntoa(tp_addr), 16);
358 fprintf(stderr, "NON-BCAST WHO-HAS: %-17s %-15s %-15s\n", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
359 }
360 nbe++;
361 }
362
363 /* return if sdr MAC is ours */
364 if (!memcmp(&se_addr, &pairs->mac, sizeof(struct ether_addr))) {
365 if (debug > 2) fprintf(stderr, "MY MAC PASSED: %s\n", ether_ntoa(&se_addr));
366 mymac++; return;
367 }
368 /* return if sdr MAC is our fake MAC */
369 if (!memcmp(&se_addr, &fake_addr, sizeof(struct ether_addr))) {
370 if (debug > 2) fprintf(stderr, "FAKE MAC PASSED: %s\n", ether_ntoa(&se_addr));
371 fake++; return;
372 }
373 /* return if sdr MAC is previous fake MAC */
374 if (fake_regen)
375 if (!memcmp(&se_addr, &pfake_addr, sizeof(struct ether_addr))) {
376 if (debug > 2) fprintf(stderr, "PRE FAKE MAC PASSED: %s\n", ether_ntoa(&se_addr));
377 pfake++; return;
378 }
379 /* fill weird gratuitous ARP sdr IP 0.0.0.0 (Linux/MacOS/Vista) */
380 if (!memcmp(&sp_addr, &zp_addr, sizeof(struct in_addr))) {
381 if (debug > 2) fprintf(stderr, "WEIRD GRATUITOUS FILL: %s\n", inet_ntoa(tp_addr));
382 memcpy(&sp_addr, &tp_addr, sizeof(struct in_addr));
383 wgrat++;
384 }
385
386 /* check if IP/MAC is listed */
387 for (n = 0, p = pairs; n < pair_num; n++, p++) {
388 memcpy(&fsip, &sp_addr, sizeof(struct in_addr));
389 memcpy(&ftip, &tp_addr, sizeof(struct in_addr));
390 memcpy(&fmask, &p->mask, sizeof(struct in_addr));
391 if (fmask) { fsip &= fmask; ftip &= fmask; }
392 if (!memcmp(&se_addr, &p->mac, sizeof(struct ether_addr))) {
393 if (!se_ch) se_ch = p;
394 if (!memcmp(&fsip, &p->ip, sizeof(struct in_addr))) se_ch = sp_ch = p;
395 }
396 if (!memcmp(&te_addr, &p->mac, sizeof(struct ether_addr))) {
397 if (!te_ch) te_ch = p;
398 if (!memcmp(&ftip, &p->ip, sizeof(struct in_addr))) te_ch = tp_ch = p;
399 }
400 if (!sp_ch && !memcmp(&fsip, &p->ip, sizeof(struct in_addr))) sp_ch = p;
401 if (!tp_ch && !memcmp(&ftip, &p->ip, sizeof(struct in_addr))) tp_ch = p;
402 }
403
404 if (debug > 2) {
405 if (se_ch) fprintf(stderr, "MATCH MAC SDR: %-18s -> %-18s\n", ether_ntoa(&se_ch->mac), inet_ntoa(se_ch->ip));
406 else fprintf(stderr, "UNKNOWN MAC SDR: %-18s\n", ether_ntoa(&se_addr));
407 if (te_ch) fprintf(stderr, "MATCH MAC TRG: %-18s -> %-18s\n", ether_ntoa(&te_ch->mac), inet_ntoa(te_ch->ip));
408 else {
409 if (!memcmp(&te_addr, &bh_addr, sizeof(struct ether_addr)))
410 fprintf(stderr, "BCAST MAC TRG: %-18s\n", "ff:ff:ff:ff:ff:ff");
411 else
412 fprintf(stderr, "UNKNOWN MAC TRG: %-18s\n", ether_ntoa(&te_addr));
413 }
414 if (sp_ch) fprintf(stderr, "MATCH IP SDR: %-18s -> %-18s\n", inet_ntoa(sp_ch->ip), ether_ntoa(&sp_ch->mac));
415 else fprintf(stderr, "UNKNOWN IP SDR: %-18s\n", inet_ntoa(sp_addr));
416 if (tp_ch) fprintf(stderr, "MATCH IP TRG: %-18s -> %-18s\n", inet_ntoa(tp_ch->ip), ether_ntoa(&tp_ch->mac));
417 else fprintf(stderr, "UNKNOWN IP TRG: %-18s\n", inet_ntoa(tp_addr));
418 }
419
420 /* gratuitous ARP packets */
421 if (se_ch && (se_ch == tp_ch) &&
422 !memcmp(&sp_addr, &tp_addr, sizeof(struct in_addr))) {
423 if (debug > 2) fprintf(stderr, "GOOD PASSED: grat\n");
424 grat++; return;
425 }
426
427 /* wildcard trg MAC 00:00:00:00:00:00 */
428 if (sp_ch && !memcmp(&sp_ch->mac, &zh_addr, sizeof(struct ether_addr))) {
429 if (debug > 2) fprintf(stderr, "GOOD PASSED: zmac\n");
430 zmac++; if (!addr_nosubst) return;
431 }
432 /* wildcard sdr IP 0.0.0.0 */
433 if (se_ch && !memcmp(&se_ch->ip, &zp_addr, sizeof(struct in_addr))) {
434 if (debug > 2) fprintf(stderr, "GOOD PASSED: zip\n");
435 zip++; if (!addr_nosubst) return;
436 }
437
438 /* correct pair - sdr MAC pos == sdr IP pos and listed trg IP pos or not duplex */
439 if (se_ch && (se_ch == sp_ch) && (tp_ch || !duplex)) {
440 if (debug > 2) fprintf(stderr, "GOOD PASSED: good\n");
441 good++; return;
442 }
443
444 /* sdr MAC and sdr IP are both not listed - new pair */
445 if (!se_ch && (se_ch == sp_ch)) {
446 if (verbose) {
447 strncpy(ntoasw, inet_ntoa(tp_addr), 16);
448 snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
449 log_str(NOTICE, "bnew:", s);
450 }
451 bnew++; bsdr++; if (grant) return;
452 }
453
454 /* sdr MAC is listed but IP is not */
455 if (se_ch && (se_ch != sp_ch)) {
456 if (verbose) {
457 strncpy(ntoasw, inet_ntoa(tp_addr), 16);
458 snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
459 log_str(NOTICE, "bsip:", s);
460 }
461 bsip++; bsdr++;
462 }
463 /* sdr IP is listed but MAC is not */
464 if (sp_ch && (se_ch != sp_ch)) {
465 if (verbose) {
466 strncpy(ntoasw, inet_ntoa(tp_addr), 16);
467 snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
468 log_str(NOTICE, "bmac:", s);
469 }
470 bmac++; bsdr++;
471 }
472
473 /* do not block gratuitous ARP in hidden mode */
474 if (!memcmp(&sp_addr, &tp_addr, sizeof(struct in_addr))) {
475 if (verbose) {
476 strncpy(ntoasw, inet_ntoa(tp_addr), 16);
477 snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
478 log_str(NOTICE, "bgrt:", s);
479 }
480 bgrat++; if (hidden) return;
481 }
482
483 /* if duplex and trg IP is not listed then block */
484 if (!tp_ch) {
485 if (verbose) {
486 strncpy(ntoasw, inet_ntoa(tp_addr), 16);
487 snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
488 log_str(NOTICE, "btip:", s);
489 }
490 btip++; if (!bsdr && !duplex) return;
491 }
492
493 /* add pirate pair to bad buffer */
494 if (bsdr && buffer_num) buffer_add();
495
496 strncpy(ntoasw, inet_ntoa(tp_addr), 16);
497 snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
498 log_str(NOTICE, "xxxx:", s);
499
500 /* block pirate
501 eth fake MAC -> pirate MAC
502 sdr fake MAC - target IP
503 trg pirate MAC - pirate IP
504 */
505 memcpy(&te_addr, &se_addr, sizeof(struct ether_addr));
506 memcpy(&se_addr, &fake_addr, sizeof(struct ether_addr));
507 memcpy(&th_addr, &sh_addr, sizeof(struct ether_addr));
508 memcpy(&sh_addr, &fake_addr, sizeof(struct ether_addr));
509 memcpy(&swip, &tp_addr, sizeof(struct in_addr));
510 memcpy(&tp_addr, &sp_addr, sizeof(struct in_addr));
511 memcpy(&sp_addr, &swip, sizeof(struct in_addr));
512 packet_send(ARPOP_REPLY, fake_num);
513
514 if (bsdr) {
515 /* control headshot
516 eth fake MAC -> pirate MAC
517 sdr fake MAC - pirate IP
518 trg pirate MAC - pirate IP
519 */
520 memcpy(&sp_addr, &tp_addr, sizeof(struct in_addr));
521 packet_send(ARPOP_REPLY, 1);
522 }
523
524 /* and fix broken ARP caches by broadcast */
525 if (bsdr && fixbc) {
526 memcpy(&te_addr, &bh_addr, sizeof(struct ether_addr));
527 memcpy(&th_addr, &zh_addr, sizeof(struct ether_addr));
528 if (sp_ch) {
529 /* sdr IP is valid
530 eth ethers MAC -> broadcast
531 sdr ethers MAC - ethers IP
532 trg zero MAC - ethers IP
533 */
534 memcpy(&se_addr, &sp_ch->mac, sizeof(struct ether_addr));
535 memcpy(&sh_addr, &sp_ch->mac, sizeof(struct ether_addr));
536 memcpy(&sp_addr, &sp_ch->ip, sizeof(struct in_addr));
537 } else if (se_ch) {
538 /* sdr MAC is valid
539 eth ethers MAC -> broadcast
540 sdr ethers MAC - ethers IP
541 trg zero MAC - ethers IP
542 ** disabled as probably useless **
543 memcpy(&se_addr, &se_ch->mac, sizeof(struct ether_addr));
544 memcpy(&sh_addr, &se_ch->mac, sizeof(struct ether_addr));
545 memcpy(&sp_addr, &se_ch->ip, sizeof(struct in_addr));
546 */
547 } else {
548 /* invalid sender
549 eth fake MAC -> broadcast
550 sdr fake MAC - pirate IP
551 trg zero MAC - pirate IP
552 */
553 memcpy(&se_addr, &fake_addr, sizeof(struct ether_addr));
554 memcpy(&sh_addr, &fake_addr, sizeof(struct ether_addr));
555 }
556 memcpy(&tp_addr, &sp_addr, sizeof(struct in_addr));
557 packet_send(ARPOP_REQUEST, 1);
558 }
559
560 bad++;
561 if (debug > 2)
562 fprintf(stderr, "STATS: god %-6d new %-6d bmc %-6d bip %-6d btg %-6d all %-6d\n",
563 good+mymac+fake+pfake+grat+wgrat+zmac+zip, bnew, bmac, bsip, btip, all);
564 }
565
packet_handle(char * blah,struct pcap_pkthdr * blah2,u_char * recv)566 void packet_handle(char *blah, struct pcap_pkthdr *blah2, u_char *recv) {
567 struct ether_header *eth_h = NULL;
568 struct ether_arp *arp_h = NULL;
569 int op;
570
571 sig_catch();
572 if (ethers_update) ethers_stat();
573 if (fake_regen) packet_fmacs(2);
574
575 eth_h = (struct ether_header *) recv;
576 if (htons(eth_h->ether_type) != ETHERTYPE_ARP) {
577 snprintf(s, 8, "0x%x", eth_h->ether_type);
578 log_str(WARNING, "wrong ethertype:", s); return;
579 }
580
581 memcpy(&se_addr, ð_h->ether_shost, sizeof(struct ether_addr));
582 memcpy(&te_addr, ð_h->ether_dhost, sizeof(struct ether_addr));
583
584 arp_h = (struct ether_arp *) ((char *) eth_h + ETHER_HDR_LEN);
585 if (htons(arp_h->ea_hdr.ar_hrd) != ARPHRD_ETHER) {
586 snprintf(s, 8, "0x%x", arp_h->ea_hdr.ar_hrd);
587 log_str(WARNING, "wrong hw address:", s); return;
588 }
589 if (htons(arp_h->ea_hdr.ar_pro) != ETHERTYPE_IP) {
590 snprintf(s, 8, "0x%x", arp_h->ea_hdr.ar_pro);
591 log_str(WARNING, "wrong proto address:", s); return;
592 }
593 op = htons(arp_h->ea_hdr.ar_op);
594
595 memcpy(&sh_addr, &arp_h->arp_sha, sizeof(struct ether_addr));
596 memcpy(&sp_addr, &arp_h->arp_spa, sizeof(struct in_addr));
597 memcpy(&th_addr, &arp_h->arp_tha, sizeof(struct ether_addr));
598 memcpy(&tp_addr, &arp_h->arp_tpa, sizeof(struct in_addr));
599
600 if (debug > 1) {
601 fprintf(stderr, "RECV ARP %u: ", op);
602 fprintf(stderr, "%-17s -> ", ether_ntoa(&se_addr)); fprintf(stderr, "%-17s\n ", ether_ntoa(&te_addr));
603 fprintf(stderr, "sdr %-17s %-15s ", ether_ntoa(&sh_addr), inet_ntoa(sp_addr));
604 fprintf(stderr, "trg %-17s %-15s\n", ether_ntoa(&th_addr), inet_ntoa(tp_addr));
605 }
606
607 if (op == ARPOP_REPLY) return;
608 if (op != ARPOP_REQUEST) {
609 snprintf(s, 8, "0x%x", op);
610 log_str(WARNING, "wrong arp op:", s);
611 return;
612 }
613
614 all++;
615 packet_check();
616 }
617
packet_recv(void)618 void packet_recv(void) {
619 if (pcap_loop(pcap, -1, (pcap_handler) packet_handle, NULL) == -1) {
620 log_str(ERROR, "pcap_loop()", "failed");
621 exit_ipguard(EXIT_FAILURE);
622 }
623 }
624
stat_dump(void)625 void stat_dump(void) {
626 struct pcap_stat ps;
627
628 snprintf(s, 64, "ARP statistics:");
629 log_str(INFO, s, "");
630 snprintf(s, 64, "Total ARP who-has packets %u", all);
631 log_str(INFO, s, "");
632 snprintf(s, 64, "Good MAC-IP pairs %u", good);
633 log_str(INFO, s, "");
634 snprintf(s, 64, "Gratuitous MAC-IP/weird %u/%u", grat, wgrat);
635 log_str(INFO, s, "");
636 snprintf(s, 64, "Zero MAC/IP %u/%u", zmac, zip);
637 log_str(INFO, s, "");
638 snprintf(s, 64, "New MAC-IP pairs %u", bnew);
639 log_str(INFO, s, "");
640 snprintf(s, 64, "Bad MAC-IP pairs %u", bad);
641 log_str(INFO, s, "");
642 snprintf(s, 64, "Bad MAC/IP %u/%u", bmac, bsip);
643 log_str(INFO, s, "");
644 if (duplex) {
645 snprintf(s, 64, "Bad target IP %u", btip);
646 log_str(INFO, s, "");
647 }
648 snprintf(s, 64, "Bad gratuitous MAC-IP %u", bgrat);
649 log_str(INFO, s, "");
650 snprintf(s, 64, "My/Fake/PreFake MAC %u/%u/%u", mymac, fake, pfake);
651 log_str(INFO, s, "");
652 snprintf(s, 64, "Mismatch sender Ether/ARP MAC %u", mis);
653 log_str(INFO, s, "");
654 snprintf(s, 64, "Non-zero target ARP MAC %u", nzh);
655 log_str(INFO, s, "");
656 snprintf(s, 64, "Non-bcast target Ether MAC %u", nbe);
657 log_str(INFO, s, "");
658
659 if (pcap_stats(pcap, &ps) == -1) {
660 log_str(WARNING, "pcap_stat()", "failed"); return;
661 }
662 snprintf(s, 64, "PCAP statistics:");
663 log_str(INFO, s, "");
664 snprintf(s, 64, "Received/Dropped packets %u/%u", ps.ps_recv, ps.ps_drop);
665 log_str(INFO, s, "");
666 }
667
668