]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/tools/ether_reflect/ether_reflect.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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 __FBSDID("$FreeBSD$");
36
37 #include <unistd.h>
38 #include <stdlib.h>
39 #include <strings.h>
40
41 #include <pcap-int.h>
42 #include <pcap.h>
43 #include <net/ethernet.h>
44
45 #define ETHER_TYPE_TEST "0x8822"
46 #define SNAPLEN 96
47 #define MAXPROG 128
48
49 char errbuf[PCAP_ERRBUF_SIZE];
50
51 void usage(char* message) {
52         if (message != NULL)
53                 printf ("error: %s\n", message);
54         printf("usage: ether_reflect -i interface -e ethertype "
55                "-a address -t timeout -p -d\n");
56         exit(1);
57 }
58
59 int main(int argc, char **argv)
60 {
61         int ch;
62         int debug = 0, promisc = 0;
63         int timeout = 100; 
64         bpf_u_int32 localnet=0, netmask=0;
65         unsigned int error = 0;
66         char *interface = NULL;
67         char *proto = ETHER_TYPE_TEST;
68         char in_string[MAXPROG];
69         char tmp[ETHER_ADDR_LEN];
70         char addr[ETHER_ADDR_LEN];
71         char *user_addr = NULL;
72         pcap_t *capture;
73         struct bpf_program program;
74         struct pcap_pkthdr *header;
75         unsigned char *packet = NULL;
76
77         while ((ch = getopt(argc, argv, "a:e:i:t:pd")) != -1) {
78                 switch (ch) {
79                 case 'a':
80                         user_addr = optarg;
81                         break;
82                 case 'e':
83                         proto = optarg;
84                         break;
85                 case 'i':
86                         interface = optarg;
87                         break;
88                 case 'p':
89                         promisc = 1;
90                         break;
91                 case 't':
92                         timeout = atoi(optarg);
93                         break;
94                 case 'd':
95                         debug = 1;
96                         break;
97                 case '?':
98                 default:
99                         usage("invalid arguments");
100                 }
101         }
102         argc -= optind;
103         argv += optind;
104
105         if (interface == NULL)
106                 usage("You must specify an interface");
107
108         if (user_addr != NULL)
109                 ether_aton_r(user_addr, (struct ether_addr *)&tmp);
110
111         if ((capture = pcap_open_live(interface, SNAPLEN, promisc, timeout, 
112                                       &errbuf[0])) == NULL)
113                 usage(errbuf);
114
115         snprintf(&in_string[0], MAXPROG, "ether proto %s\n", proto);
116
117         if (pcap_lookupnet(interface, &localnet, &netmask, errbuf) < 0)
118                 usage(errbuf);
119
120         if (pcap_compile(capture, &program, in_string, 1, netmask) < 0)
121                 usage(errbuf);
122
123         if (pcap_setfilter(capture, &program) < 0)
124                 usage(errbuf);
125
126         if (pcap_setdirection(capture, PCAP_D_IN) < 0)
127                 usage(errbuf);
128
129         while (1) {
130                 error = pcap_next_ex(capture, &header, 
131                                      (const unsigned char **)&packet);
132                 if (error == 0)
133                         continue;
134                 if (error == -1)
135                         usage("packet read error");
136                 if (error == -2)
137                         usage("savefile?  invalid!");
138
139                 if (debug) {
140                         printf ("got packet of %d length\n", header->len);
141                         printf ("header %s\n", 
142                                 ether_ntoa((const struct ether_addr*)
143                                            &packet[0]));
144                         printf ("header %s\n", 
145                                 ether_ntoa((const struct ether_addr*)
146                                            &packet[ETHER_ADDR_LEN]));
147                 }
148                 
149                 /*
150                  * If the user did not supply an address then we simply
151                  * reverse the source and destination addresses.
152                  */
153                 if (user_addr == NULL) {
154                         bcopy(packet, &tmp, ETHER_ADDR_LEN);
155                         bcopy(&packet[ETHER_ADDR_LEN], packet, ETHER_ADDR_LEN);
156                         bcopy(&tmp, &packet[ETHER_ADDR_LEN], ETHER_ADDR_LEN);
157                 } else {
158                         bcopy(&tmp, packet, ETHER_ADDR_LEN);
159                 }
160                 if (pcap_inject(capture, packet, header->len) < 0)
161                         if (debug)
162                                 pcap_perror(capture, "pcap_inject");
163         }
164 }