1 /*
2 gre_relay -- ettercap plugin -- Tunnel broker for redirected GRE tunnels
3
4 Copyright (C) ALoR & NaGA
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 */
21
22
23 #include <ec.h> /* required for global variables */
24 #include <ec_plugins.h> /* required for plugin ops */
25 #include <ec_packet.h>
26 #include <ec_hook.h>
27 #include <ec_send.h>
28
29 struct ip_header {
30 #ifndef WORDS_BIGENDIAN
31 u_int8 ihl:4;
32 u_int8 version:4;
33 #else
34 u_int8 version:4;
35 u_int8 ihl:4;
36 #endif
37 u_int8 tos;
38 u_int16 tot_len;
39 u_int16 id;
40 u_int16 frag_off;
41 #define IP_DF 0x4000
42 #define IP_MF 0x2000
43 #define IP_FRAG 0x1fff
44 u_int8 ttl;
45 u_int8 protocol;
46 u_int16 csum;
47 u_int32 saddr;
48 u_int32 daddr;
49 /*The options start here. */
50 };
51
52
53 #ifdef WITH_IPV6
54 struct ip6_header {
55 #ifndef WORDS_BIGENDIAN
56 u_int8 version:4;
57 u_int8 priority:4;
58 #else
59 u_int8 priority:4;
60 u_int8 version:4;
61 #endif
62 u_int8 flow_lbl[3];
63 u_int16 payload_len;
64 u_int8 next_hdr;
65 u_int8 hop_limit;
66
67 u_int8 saddr[IP6_ADDR_LEN];
68 u_int8 daddr[IP6_ADDR_LEN];
69 };
70
71 struct icmp6_nsol {
72 u_int32 res;
73 u_int8 target[IP6_ADDR_LEN];
74 };
75 #endif
76
77
78 /* globals */
79 struct ip_addr fake_ip;
80
81 /* protos */
82 int plugin_load(void *);
83 static int gre_relay_init(void *);
84 static int gre_relay_fini(void *);
85
86 static void parse_gre(struct packet_object *po);
87 static void parse_arp(struct packet_object *po);
88
89 #ifdef WITH_IPV6
90 static void parse_nd(struct packet_object *po);
91 #endif
92
93 /* plugin operations */
94 struct plugin_ops gre_relay_ops = {
95 /* ettercap version MUST be the global EC_VERSION */
96 .ettercap_version = EC_VERSION,
97 /* the name of the plugin */
98 .name = "gre_relay",
99 /* a short description of the plugin (max 50 chars) */
100 .info = "Tunnel broker for redirected GRE tunnels",
101 /* the plugin version. */
102 .version = "1.1",
103 /* activation function */
104 .init = &gre_relay_init,
105 /* deactivation function */
106 .fini = &gre_relay_fini,
107 };
108
109 /**********************************************************/
110
111 /* this function is called on plugin load */
plugin_load(void * handle)112 int plugin_load(void *handle)
113 {
114 return plugin_register(handle, &gre_relay_ops);
115 }
116
117 /******************* STANDARD FUNCTIONS *******************/
118
gre_relay_init(void * dummy)119 static int gre_relay_init(void *dummy)
120 {
121 char tmp[MAX_ASCII_ADDR_LEN];
122
123 /* variable not used */
124 (void) dummy;
125
126 /* It doesn't work if unoffensive */
127 if (EC_GBL_OPTIONS->unoffensive) {
128 INSTANT_USER_MSG("gre_relay: plugin doesn't work in UNOFFENSIVE mode\n");
129 return PLUGIN_FINISHED;
130 }
131
132 /* don't display messages while operating */
133 EC_GBL_OPTIONS->quiet = 1;
134
135 memset(tmp, 0, sizeof(tmp));
136
137 ui_input("Unused IP address: ", tmp, sizeof(tmp), NULL);
138
139 /* convert IP string into ip_addr struct */
140 if (ip_addr_pton(tmp, &fake_ip) != E_SUCCESS) {
141 INSTANT_USER_MSG("gre_relay: Bad IP address\n");
142 return PLUGIN_FINISHED;
143 }
144
145 USER_MSG("gre_relay: plugin running...\n");
146
147 hook_add(HOOK_PACKET_GRE, &parse_gre);
148 hook_add(HOOK_PACKET_ARP_RQ, &parse_arp);
149 #ifdef WITH_IPV6
150 hook_add(HOOK_PACKET_ICMP6_NSOL, &parse_nd);
151 #endif
152
153 return PLUGIN_RUNNING;
154 }
155
156
gre_relay_fini(void * dummy)157 static int gre_relay_fini(void *dummy)
158 {
159 /* variable not used */
160 (void) dummy;
161
162 USER_MSG("gre_relay: plugin terminated...\n");
163
164 hook_del(HOOK_PACKET_GRE, &parse_gre);
165 hook_del(HOOK_PACKET_ARP_RQ, &parse_arp);
166 #ifdef WITH_IPV6
167 hook_del(HOOK_PACKET_ICMP6_NSOL, &parse_nd);
168 #endif
169
170 return PLUGIN_FINISHED;
171 }
172
173 /*********************************************************/
174
175 /* Send back GRE packets */
parse_gre(struct packet_object * po)176 static void parse_gre(struct packet_object *po)
177 {
178 struct ip_header *iph;
179 #ifdef WITH_IPV6
180 struct ip6_header *ip6h;
181 #endif
182
183 /* Chek if this is a packet for our fake host */
184 if (!(po->flags & PO_FORWARDABLE))
185 return;
186
187 if ( ip_addr_cmp(&po->L3.dst, &fake_ip) )
188 return;
189
190 if ( po->L3.header == NULL)
191 return;
192
193 /* Switch source and dest IP address */
194 switch (ntohs(po->L3.dst.addr_type)) {
195 case AF_INET:
196 iph = (struct ip_header*)po->L3.header;
197 iph->daddr = iph->saddr;
198 iph->saddr = fake_ip.addr32[0];
199 /* Increase ttl */
200 iph->ttl = 128;
201 break;
202 #ifdef WITH_IPV6
203 case AF_INET6:
204 ip6h = (struct ip6_header*)po->L3.header;
205 ip_addr_cpy(ip6h->daddr, &po->L3.src);
206 ip_addr_cpy(ip6h->saddr, &fake_ip);
207 /* Increase ttl */
208 ip6h->hop_limit = 128;
209 break;
210 #endif
211 default:
212 return;
213 }
214
215
216 po->flags |= PO_MODIFIED;
217 }
218
219
220 /* Reply to requests for our fake host */
parse_arp(struct packet_object * po)221 static void parse_arp(struct packet_object *po)
222 {
223 if (!ip_addr_cmp(&fake_ip, &po->L3.dst))
224 send_arp(ARPOP_REPLY, &fake_ip, EC_GBL_IFACE->mac, &po->L3.src, po->L2.src);
225 }
226
227 #ifdef WITH_IPV6
228 /* Reply to requests for our IPv6 fake host */
parse_nd(struct packet_object * po)229 static void parse_nd(struct packet_object *po)
230 {
231 struct icmp6_nsol* nsol;
232 struct ip_addr target;
233
234 nsol = (struct icmp6_nsol*)po->L4.options;
235 ip_addr_init(&target, AF_INET6, (u_char*)nsol->target);
236
237 if (!ip_addr_cmp(&fake_ip, &target))
238 send_L2_icmp6_nadv(&fake_ip, &po->L3.src, EC_GBL_IFACE->mac, 0, po->L2.src);
239 }
240 #endif
241
242 /* EOF */
243
244 // vim:ts=3:expandtab
245
246