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