"Fossies" - the Fresh Open Source Software Archive 
Member "ettercap-0.8.3.1/src/ec_network.c" (1 Aug 2020, 13657 Bytes) of package /linux/privat/ettercap-0.8.3.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "ec_network.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
0.8.3_vs_0.8.3.1.
1 #include <ec.h>
2 #include <ec_capture.h>
3 #include <ec_decode.h>
4 #include <ec_queue.h>
5 #include <ec_network.h>
6 #include <ec_threads.h>
7
8 #include <pcap.h>
9 #include <libnet.h>
10 #if !defined(OS_WINDOWS)
11 #include <ifaddrs.h>
12 #endif
13
14 #if defined(OS_BSD_OPEN)
15 /* OPENBSD needs 0 */
16 #define PCAP_TIMEOUT 0
17 #elif defined(OS_SOLARIS)
18 /* SOLARIS needs > 1 */
19 #define PCAP_TIMEOUT 10
20 #else
21 /* LINUX needs > 0 */
22 /* FREEBSD needs 1 */
23 /* MACOSX needs 1 */
24 #define PCAP_TIMEOUT 1
25 #endif
26
27 struct source_entry {
28 struct iface_env iface;
29 LIST_ENTRY(source_entry) next;
30 };
31
32 /* globals */
33 static LIST_HEAD(,source_entry) sources_list;
34 static pthread_mutex_t sl_mutex = PTHREAD_MUTEX_INITIALIZER;
35 #define SOURCES_LIST_LOCK do{ pthread_mutex_lock(&sl_mutex); }while(0)
36 #define SOURCES_LIST_UNLOCK do{ pthread_mutex_unlock(&sl_mutex); }while(0)
37
38 /* protos */
39 static void close_network();
40 static void pcap_winit(pcap_t *pcap);
41 static void source_print(struct iface_env *source);
42 static int source_init(char *name, struct iface_env *source, bool primary, bool live);
43 static void source_close(struct iface_env *iface);
44 static int secondary_sources_init(char **sources);
45 static void close_secondary_sources(void);
46 static void l3_init(void);
47 static void l3_close(void);
48
49 /* the code */
50
51 void network_init()
52 {
53 char *iface;
54
55 DEBUG_MSG("init_network");
56
57 EC_GBL_PCAP->snaplen = UINT16_MAX;
58
59 if(EC_GBL_OPTIONS->read) {
60 source_init(EC_GBL_OPTIONS->pcapfile_in, EC_GBL_IFACE, true, false);
61 source_print(EC_GBL_IFACE);
62 } else {
63 iface = EC_GBL_OPTIONS->iface ? EC_GBL_OPTIONS->iface : (EC_GBL_OPTIONS->iface = capture_default_if());
64 ON_ERROR(iface, NULL, "No suitable interface found...");
65 source_init(iface, EC_GBL_IFACE, true, true);
66 source_print(EC_GBL_IFACE);
67 if(EC_GBL_SNIFF->type == SM_BRIDGED) {
68 source_init(EC_GBL_OPTIONS->iface_bridge, EC_GBL_BRIDGE, true, true);
69 source_print(EC_GBL_BRIDGE);
70 if(EC_GBL_BRIDGE->dlt != EC_GBL_IFACE->dlt)
71 FATAL_ERROR("Can't bridge interfaces of different types");
72 }
73 }
74
75 if(get_decoder(LINK_LAYER, EC_GBL_IFACE->dlt) == NULL) {
76 if(EC_GBL_OPTIONS->read)
77 FATAL_ERROR("Dump file not supported (%s)", pcap_datalink_val_to_description(EC_GBL_PCAP->dlt));
78 else
79 FATAL_ERROR("Interface \"%s\" not supported (%s)", EC_GBL_OPTIONS->iface, pcap_datalink_val_to_description(EC_GBL_PCAP->dlt));
80 }
81
82 if(EC_GBL_OPTIONS->write)
83 pcap_winit(EC_GBL_IFACE->pcap);
84
85 /* determine alignment margin and allocate packet buffer per interface */
86 EC_GBL_PCAP->align = get_alignment(EC_GBL_PCAP->dlt);
87 SAFE_CALLOC(EC_GBL_IFACE->pbuf, UINT16_MAX + EC_GBL_PCAP->align + 256, sizeof(char));
88 if (!EC_GBL_OPTIONS->read && EC_GBL_SNIFF->type == SM_BRIDGED)
89 SAFE_CALLOC(EC_GBL_BRIDGE->pbuf, UINT16_MAX + EC_GBL_PCAP->align + 256, sizeof(char));
90
91 if(EC_GBL_OPTIONS->secondary) {
92 secondary_sources_init(EC_GBL_OPTIONS->secondary);
93 atexit(close_secondary_sources);
94 }
95
96 /* Layer 3 handlers initialization */
97 if(!EC_GBL_OPTIONS->unoffensive)
98 l3_init();
99
100 atexit(close_network);
101 }
102
103 static void close_network()
104 {
105 pcap_close(EC_GBL_IFACE->pcap);
106 SAFE_FREE(EC_GBL_IFACE->pbuf);
107 if(EC_GBL_SNIFF->type == SM_BRIDGED) {
108 pcap_close(EC_GBL_BRIDGE->pcap);
109 SAFE_FREE(EC_GBL_BRIDGE->pbuf);
110 }
111
112 if(EC_GBL_OPTIONS->write)
113 pcap_dump_close(EC_GBL_PCAP->dump);
114
115 libnet_destroy(EC_GBL_IFACE->lnet);
116 libnet_destroy(EC_GBL_BRIDGE->lnet);
117
118 DEBUG_MSG("ATEXIT: close_network");
119 }
120
121 static void pcap_winit(pcap_t *pcap)
122 {
123 pcap_dumper_t *pdump;
124 pdump = pcap_dump_open(pcap, EC_GBL_OPTIONS->pcapfile_out);
125 ON_ERROR(pdump, NULL, "pcap_dump_open: %s", pcap_geterr(pcap));
126 EC_GBL_PCAP->dump = pdump;
127 }
128
129 static void source_print(struct iface_env *source)
130 {
131 char strbuf[256];
132 struct net_list *ip6;
133
134 if(source->is_live) {
135 USER_MSG("Listening on:\n");
136 USER_MSG("%6s -> %s\n", source->name, mac_addr_ntoa(source->mac, strbuf));
137 if(source->has_ipv4) {
138 USER_MSG("\t %s/", ip_addr_ntoa(&source->ip, strbuf));
139 USER_MSG("%s\n", ip_addr_ntoa(&source->netmask, strbuf));
140 }
141 if(source->has_ipv6) {
142 LIST_FOREACH(ip6, &source->ip6_list, next) {
143 USER_MSG("\t %s/%d\n", ip_addr_ntoa(&ip6->ip, strbuf), ip6->prefix);
144 }
145 USER_MSG("\n");
146 } else {
147 USER_MSG("\n\n");
148 }
149 } else {
150 USER_MSG("Reading from %s\n", source->name);
151 }
152
153 }
154
155 static int source_init(char *name, struct iface_env *source, bool primary, bool live)
156 {
157 int ret;
158 pcap_t *pcap = NULL;
159 libnet_t *lnet = NULL;
160 struct bpf_program bpf;
161 char pcap_errbuf[PCAP_ERRBUF_SIZE];
162 char lnet_errbuf[LIBNET_ERRBUF_SIZE];
163 int snaplen;
164
165 struct libnet_ether_addr *mac;
166 struct sockaddr_in *sa4;
167 struct sockaddr_in6 *sa6;
168 struct net_list *ip6;
169
170 #if !defined(OS_WINDOWS)
171 struct ifaddrs *ifaddrs, *ifaddr;
172 #endif
173
174 DEBUG_MSG("source_init %s", name);
175
176 BUG_IF(source == NULL);
177
178 /* ===pcap initialization=== */
179 if(live) {
180 pcap = pcap_open_live(name, EC_GBL_PCAP->snaplen, EC_GBL_PCAP->promisc, PCAP_TIMEOUT, pcap_errbuf);
181 if(pcap == NULL) {
182 if(primary)
183 ON_ERROR(pcap, NULL, "pcap_open_live: %s", pcap_errbuf);
184 else
185 return -E_INITFAIL;
186 }
187 } else {
188 /* secondary sources must not be offline */
189 if(!primary)
190 return -E_NOTHANDLED;
191
192 struct stat st;
193 int stat_result;
194 FILE* pcap_file_h;
195
196 pcap = pcap_open_offline(name, pcap_errbuf);
197 ON_ERROR(pcap, NULL, "pcap_open_offline: %s", pcap_errbuf);
198
199 pcap_file_h = pcap_file(pcap);
200 ON_ERROR(pcap_file_h, 0, "pcap_fileno returned an invalid file handle");
201
202 stat_result = fstat(fileno(pcap_file_h), &st);
203 ON_ERROR(stat_result, -1, "fstat failed.");
204
205 EC_GBL_PCAP->dump_size = st.st_size;
206 }
207 source->dlt = pcap_datalink(pcap);
208 if(primary)
209 EC_GBL_PCAP->dlt = source->dlt;
210 if(source->dlt == DLT_IEEE802_11) {
211 DEBUG_MSG("Wireless monitor mode used, switching to unoffensive mode");
212 source->unoffensive = 1;
213 if(primary)
214 EC_GBL_OPTIONS->unoffensive = 1;
215 }
216 if(!strcmp(name, "lo")) {
217 DEBUG_MSG("Loopback interface used, switching to unoffensive mode");
218 source->unoffensive = 1;
219 if(primary)
220 EC_GBL_OPTIONS->unoffensive = 1;
221 }
222
223 if(EC_GBL_PCAP->filter && strcmp(EC_GBL_PCAP->filter, "") && live) {
224 u_int net, mask;
225 if(pcap_lookupnet(name, &net, &mask, pcap_errbuf) == -1)
226 ERROR_MSG("%s - %s", name, pcap_errbuf);
227 if(pcap_compile(pcap, &bpf, EC_GBL_PCAP->filter, 1, mask) < 0)
228 ERROR_MSG("Wrong pcap filter: %s - %s", name, pcap_geterr(pcap));
229 if(pcap_setfilter(pcap, &bpf) == 1)
230 ERROR_MSG("Cannot set pcap filter: %s - %s", name, pcap_geterr(pcap));
231 }
232
233 snaplen = pcap_snapshot(pcap);
234 DEBUG_MSG("requested snaplen for %s: %d, assigned snaplen: %d", name, EC_GBL_PCAP->snaplen, snaplen);
235 if(primary)
236 EC_GBL_PCAP->snaplen = snaplen;
237 source->pcap = pcap;
238
239 SAFE_STRDUP(source->name, name);
240
241 if(live) {
242 source->is_live = 1;
243 } else {
244 source->is_ready = 1;
245 return E_SUCCESS;
246 }
247
248 if(!EC_GBL_OPTIONS->unoffensive && !source->unoffensive) {
249 lnet = libnet_init(LIBNET_LINK_ADV, name, lnet_errbuf);
250 ON_ERROR(lnet, NULL, "libnet_init: %s", lnet_errbuf);
251
252 mac = libnet_get_hwaddr(lnet);
253 memcpy(&source->mac, mac, MEDIA_ADDR_LEN);
254 }
255
256 source->lnet = lnet;
257
258 source->mtu = get_iface_mtu(name);
259 #if defined(OS_WINDOWS)
260 pcap_if_t *dev;
261
262 for (dev = (pcap_if_t *)EC_GBL_PCAP->ifs; dev; dev = dev->next) {
263 if(strcmp(dev->name, name))
264 continue;
265
266 if(dev->addresses->addr->sa_family == AF_INET) {
267 sa4 = (struct sockaddr_in*) dev->addresses->addr;
268
269 ip_addr_init(&source->ip, AF_INET, (u_char*)&sa4->sin_addr);
270 if(EC_GBL_OPTIONS->netmask) {
271 if(ip_addr_pton(EC_GBL_OPTIONS->netmask, &source->netmask) != E_SUCCESS)
272 FATAL_ERROR("Invalid netmask %s", EC_GBL_OPTIONS->netmask);
273 } else {
274 sa4 = (struct sockaddr_in*) dev->addresses->netmask;
275 ip_addr_init(&source->netmask, AF_INET, (u_char*)&sa4->sin_addr);
276 }
277 ip_addr_get_network(&source->ip, &source->netmask, &source->network);
278 source->has_ipv4 = 1;
279 }
280 else if(dev->addresses->addr->sa_family == AF_INET6) {
281 SAFE_CALLOC(ip6, 1, sizeof(*ip6));
282 sa6 = (struct sockaddr_in6*) dev->addresses->addr;
283 ip_addr_init(&ip6->ip, AF_INET6, (u_char*)&sa6->sin6_addr);
284
285 sa6 = (struct sockaddr_in6*) dev->addresses->netmask;
286 ip_addr_init(&ip6->netmask, AF_INET6, (u_char*)&sa6->sin6_addr);
287 ip_addr_get_network(&ip6->ip, &ip6->netmask, &ip6->network);
288 ip6->prefix = ip_addr_get_prefix(&ip6->netmask);
289 LIST_INSERT_HEAD(&source->ip6_list, ip6, next);
290 source->has_ipv6 = 1;
291 }
292 }
293
294 #else
295 ret = getifaddrs(&ifaddrs);
296 ON_ERROR(ret, -1, "getifaddrs: %s", strerror(errno));
297
298 for(ifaddr = ifaddrs; ifaddr; ifaddr = ifaddr->ifa_next) {
299 if (ifaddr->ifa_addr == NULL)
300 continue;
301 if(strcmp(ifaddr->ifa_name, name))
302 continue;
303
304 if(ifaddr->ifa_addr->sa_family == AF_INET) {
305 sa4 = (struct sockaddr_in*)ifaddr->ifa_addr;
306 ip_addr_init(&source->ip, AF_INET, (u_char*)&sa4->sin_addr);
307 if(EC_GBL_OPTIONS->netmask) {
308 if(ip_addr_pton(EC_GBL_OPTIONS->netmask, &source->netmask) != E_SUCCESS)
309 FATAL_ERROR("Invalid netmask %s", EC_GBL_OPTIONS->netmask);
310 } else {
311 sa4 = (struct sockaddr_in*)ifaddr->ifa_netmask;
312 ip_addr_init(&source->netmask, AF_INET, (u_char*)&sa4->sin_addr);
313 }
314 ip_addr_get_network(&source->ip, &source->netmask, &source->network);
315 source->has_ipv4 = 1;
316 } else if(ifaddr->ifa_addr->sa_family == AF_INET6) {
317 SAFE_CALLOC(ip6, 1, sizeof(*ip6));
318 sa6 = (struct sockaddr_in6*)ifaddr->ifa_addr;
319 ip_addr_init(&ip6->ip, AF_INET6, (u_char*)&sa6->sin6_addr);
320 sa6 = (struct sockaddr_in6*)ifaddr->ifa_netmask;
321 ip_addr_init(&ip6->netmask, AF_INET6, (u_char*)&sa6->sin6_addr);
322 ip_addr_get_network(&ip6->ip, &ip6->netmask, &ip6->network);
323 ip6->prefix = ip_addr_get_prefix(&ip6->netmask);
324 LIST_INSERT_HEAD(&source->ip6_list, ip6, next);
325 source->has_ipv6 = 1;
326 }
327 }
328
329 freeifaddrs(ifaddrs);
330 #endif /* OS_WINDOWS */
331
332 source->is_ready = 1;
333
334 return E_SUCCESS;
335 }
336
337 static void source_close(struct iface_env *iface)
338 {
339 #ifdef WITH_IPV6
340 struct net_list *n;
341 #endif
342
343 iface->is_ready = 0;
344
345 if(iface->pcap != NULL)
346 pcap_close(iface->pcap);
347
348 if(iface->lnet != NULL)
349 libnet_destroy(iface->lnet);
350
351 #ifdef WITH_IPV6
352 LIST_FOREACH(n, &iface->ip6_list, next) {
353 LIST_REMOVE(n, next);
354 SAFE_FREE(n);
355 }
356 #endif
357
358 SAFE_FREE(iface->name);
359 memset(iface, 0, sizeof(*iface));
360 }
361
362 static int secondary_sources_init(char **sources)
363 {
364 struct source_entry *se;
365 int n = 0;
366
367 SOURCES_LIST_LOCK;
368
369 for(n = 0; sources[n] != NULL; n++) {
370 SAFE_CALLOC(se, 1, sizeof(*se));
371
372 /* secondary interfaces are always live */
373 source_init(sources[n], &se->iface, true, false);
374 if(se->iface.is_ready)
375 LIST_INSERT_HEAD(&sources_list, se, next);
376 else
377 SAFE_FREE(se);
378 }
379
380 SOURCES_LIST_UNLOCK;
381
382 return n;
383 }
384
385 void secondary_sources_foreach(void (*callback)(struct iface_env*))
386 {
387 struct source_entry *se;
388
389 SOURCES_LIST_LOCK;
390
391 LIST_FOREACH(se, &sources_list, next) {
392 callback(&se->iface);
393 }
394
395 SOURCES_LIST_UNLOCK;
396 }
397
398 static void close_secondary_sources(void)
399 {
400 struct source_entry *se;
401
402 SOURCES_LIST_LOCK;
403
404 LIST_FOREACH(se, &sources_list, next) {
405 LIST_REMOVE(se, next);
406 source_close(&se->iface);
407 SAFE_FREE(se);
408 }
409
410 SOURCES_LIST_UNLOCK;
411 }
412
413 static void l3_init(void)
414 {
415 libnet_t *l4;
416 #ifdef WITH_IPV6
417 libnet_t *l6;
418 #endif
419 #ifdef OS_WINDOWS
420 char *name = EC_GBL_OPTIONS->iface;
421 #else
422 char *name = NULL;
423 #endif
424
425
426 char lnet_errbuf[LIBNET_ERRBUF_SIZE];
427
428 DEBUG_MSG("l3_init");
429
430 /* open the socket at layer 3 */
431 l4 = libnet_init(LIBNET_RAW4_ADV, name, lnet_errbuf);
432 if (l4 == NULL) {
433 DEBUG_MSG("send_init: libnet_init(LIBNET_RAW4_ADV) failed: %s", lnet_errbuf);
434 USER_MSG("Libnet failed IPv4 initialization. Don't send IPv4 packets.\n");
435 }
436
437 EC_GBL_LNET->lnet_IP4 = l4;
438
439 #ifdef WITH_IPV6
440 /* open the socket at layer 3 for IPv6 */
441 l6 = libnet_init(LIBNET_RAW6_ADV, name, lnet_errbuf);
442 if(l6 == NULL) {
443 DEBUG_MSG("%s: libnet_init(LIBNET_RAW6_ADV) failed: %s", __func__, lnet_errbuf);
444 USER_MSG("Libnet failed IPv6 initialization. Don't send IPv6 packets.\n");
445 }
446
447 EC_GBL_LNET->lnet_IP6 = l6;
448 #endif
449
450 atexit(l3_close);
451 }
452
453 static void l3_close(void)
454 {
455 if(EC_GBL_LNET->lnet_IP4)
456 libnet_destroy(EC_GBL_LNET->lnet_IP4);
457 #ifdef WITH_IPV6
458 if(EC_GBL_LNET->lnet_IP6)
459 libnet_destroy(EC_GBL_LNET->lnet_IP6);
460 #endif
461
462 DEBUG_MSG("ATEXIT: send_closed");
463 }
464
465 struct iface_env* iface_by_mac(u_int8 mac[MEDIA_ADDR_LEN])
466 {
467 struct source_entry *se;
468
469 SOURCES_LIST_LOCK;
470
471 LIST_FOREACH(se, &sources_list, next) {
472 if(!memcmp(se->iface.mac, mac, MEDIA_ADDR_LEN)) {
473 SOURCES_LIST_UNLOCK;
474 return &se->iface;
475 }
476 }
477
478 SOURCES_LIST_UNLOCK;
479 return NULL;
480 }
481