]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/tools/ether_reflect/ether_reflect.c
sqlite3: Vendor import of sqlite3 3.43.1
[FreeBSD/FreeBSD.git] / tools / tools / ether_reflect / ether_reflect.c
1 /* 
2  * Copyright (c) 2008, Neville-Neil Consulting
3  * All rights reserved.
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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * Author: George V. Neville-Neil
27  *
28  * Purpose: This program uses libpcap to read packets from the network
29  * of a specific ethertype (default is 0x8822) and reflects them back
30  * out the same interface with their destination and source mac
31  * addresses reversed.
32  */
33
34 #include <sys/cdefs.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <strings.h>
38
39 #include <pcap-int.h>
40 #include <pcap.h>
41 #include <net/ethernet.h>
42
43 #define ETHER_TYPE_TEST "0x8822"
44 #define SNAPLEN 96
45 #define MAXPROG 128
46
47 char errbuf[PCAP_ERRBUF_SIZE];
48
49 void usage(char* message) {
50         if (message != NULL)
51                 printf ("error: %s\n", message);
52         printf("usage: ether_reflect -i interface -e ethertype "
53                "-a address -t timeout -p -d\n");
54         exit(1);
55 }
56
57 int main(int argc, char **argv)
58 {
59         int ch;
60         int debug = 0, promisc = 0;
61         int timeout = 100; 
62         bpf_u_int32 localnet=0, netmask=0;
63         unsigned int error = 0;
64         char *interface = NULL;
65         char *proto = ETHER_TYPE_TEST;
66         char in_string[MAXPROG];
67         char tmp[ETHER_ADDR_LEN];
68         char addr[ETHER_ADDR_LEN];
69         char *user_addr = NULL;
70         pcap_t *capture;
71         struct bpf_program program;
72         struct pcap_pkthdr *header;
73         unsigned char *packet = NULL;
74
75         while ((ch = getopt(argc, argv, "a:e:i:t:pd")) != -1) {
76                 switch (ch) {
77                 case 'a':
78                         user_addr = optarg;
79                         break;
80                 case 'e':
81                         proto = optarg;
82                         break;
83                 case 'i':
84                         interface = optarg;
85                         break;
86                 case 'p':
87                         promisc = 1;
88                         break;
89                 case 't':
90                         timeout = atoi(optarg);
91                         break;
92                 case 'd':
93                         debug = 1;
94                         break;
95                 case '?':
96                 default:
97                         usage("invalid arguments");
98                 }
99         }
100         argc -= optind;
101         argv += optind;
102
103         if (interface == NULL)
104                 usage("You must specify an interface");
105
106         if (user_addr != NULL)
107                 ether_aton_r(user_addr, (struct ether_addr *)&tmp);
108
109         if ((capture = pcap_open_live(interface, SNAPLEN, promisc, timeout, 
110                                       &errbuf[0])) == NULL)
111                 usage(errbuf);
112
113         snprintf(&in_string[0], MAXPROG, "ether proto %s\n", proto);
114
115         if (pcap_lookupnet(interface, &localnet, &netmask, errbuf) < 0)
116                 usage(errbuf);
117
118         if (pcap_compile(capture, &program, in_string, 1, netmask) < 0)
119                 usage(errbuf);
120
121         if (pcap_setfilter(capture, &program) < 0)
122                 usage(errbuf);
123
124         if (pcap_setdirection(capture, PCAP_D_IN) < 0)
125                 usage(errbuf);
126
127         while (1) {
128                 error = pcap_next_ex(capture, &header, 
129                                      (const unsigned char **)&packet);
130                 if (error == 0)
131                         continue;
132                 if (error == -1)
133                         usage("packet read error");
134                 if (error == -2)
135                         usage("savefile?  invalid!");
136
137                 if (debug) {
138                         printf ("got packet of %d length\n", header->len);
139                         printf ("header %s\n", 
140                                 ether_ntoa((const struct ether_addr*)
141                                            &packet[0]));
142                         printf ("header %s\n", 
143                                 ether_ntoa((const struct ether_addr*)
144                                            &packet[ETHER_ADDR_LEN]));
145                 }
146                 
147                 /*
148                  * If the user did not supply an address then we simply
149                  * reverse the source and destination addresses.
150                  */
151                 if (user_addr == NULL) {
152                         bcopy(packet, &tmp, ETHER_ADDR_LEN);
153                         bcopy(&packet[ETHER_ADDR_LEN], packet, ETHER_ADDR_LEN);
154                         bcopy(&tmp, &packet[ETHER_ADDR_LEN], ETHER_ADDR_LEN);
155                 } else {
156                         bcopy(&tmp, packet, ETHER_ADDR_LEN);
157                 }
158                 if (pcap_inject(capture, packet, header->len) < 0)
159                         if (debug)
160                                 pcap_perror(capture, "pcap_inject");
161         }
162 }