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, &eth_h->ether_shost, sizeof(struct ether_addr));
582     memcpy(&te_addr, &eth_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