1 /* interfaces.c
2 * Network interface utilities and main core for capturing packets
3 *
4 * Yersinia
5 * By David Barroso <tomac@yersinia.net> and Alfredo Andres <aandreswork@hotmail.com>
6 * Copyright 2005-2017 Alfredo Andres and David Barroso
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #ifndef _REENTRANT
28 #define _REENTRANT
29 #endif
30
31 #include <stdio.h>
32 #include <errno.h>
33
34 #ifdef HAVE_SYS_TYPES_H
35 #include <sys/types.h>
36 #endif
37
38 #ifdef HAVE_INTTYPES_H
39 #include <inttypes.h>
40 #endif
41
42 #include <sys/socket.h>
43
44 #ifdef HAVE_SYS_SOCKIO_H
45 #include <sys/sockio.h>
46 #endif
47
48 #include <sys/ioctl.h>
49
50 #ifdef HAVE_NET_IF_H
51 #include <net/if.h>
52 #endif
53
54 #ifdef HAVE_NETINET_IN_SYSTM_H
55 #include <netinet/in_systm.h>
56 #else
57 #ifdef HAVE_NETINET_IN_SYSTEM_H
58 #include <netinet/in_system.h>
59 #endif
60 #endif
61
62 #include <netinet/in.h>
63 #include <arpa/inet.h>
64 #include <time.h>
65
66 #ifdef TIME_WITH_SYS_TIME
67 #include <sys/time.h>
68 #endif
69
70 #ifdef HAVE_UNISTD_H
71 #include <unistd.h>
72 #endif
73
74 #ifdef HAVE_STRING_H
75 #include <string.h>
76 #endif
77
78 #ifdef HAVE_STRINGS_H
79 #include <strings.h>
80 #endif
81
82 #ifdef HAVE_BSTRING_H
83 #include <bstring.h>
84 #endif
85
86 #ifdef STDC_HEADERS
87 #include <stdlib.h>
88 #endif
89
90 #ifdef SOLARIS
91 #include <pthread.h>
92 #include <thread.h>
93 #else
94 #ifdef HAVE_PTHREAD_H
95 #include <pthread.h>
96 #endif
97 #endif
98
99 #ifdef HAVE_BPF
100 #include <net/bpf.h>
101 #endif
102
103 #include "interfaces.h"
104
105
106
107
108 ////////////////////////////////////////////////////////////////////////////////////////////////////
109
110
111 int8_t
interfaces_init_data_pcap_addr(pcap_if_t * index,struct interface_data * iface_data)112 interfaces_init_data_pcap_addr( pcap_if_t *index, struct interface_data *iface_data )
113 {
114 pcap_addr_t *pcap_addr;
115
116 pcap_addr = index->addresses;
117
118 while( pcap_addr )
119 {
120 if ( pcap_addr->addr && ( ( pcap_addr->addr->sa_family == AF_INET ) ||
121 ( pcap_addr->addr->sa_family == AF_INET6 ) ) )
122 {
123 if ( ! inet_ntop( pcap_addr->addr->sa_family, (void *)&pcap_addr->addr->sa_data[2],
124 iface_data->ipaddr, IPADDRSIZ ) )
125 thread_error( "inet_ntop error", errno );
126 }
127
128 if ( pcap_addr->netmask && ( ( pcap_addr->netmask->sa_family == AF_INET ) ||
129 ( pcap_addr->netmask->sa_family == AF_INET6 ) ) )
130 {
131 if ( ! inet_ntop( pcap_addr->netmask->sa_family, (void *)&pcap_addr->netmask->sa_data[2],
132 iface_data->netmask, IPADDRSIZ ) )
133 thread_error( "inet_ntop error", errno );
134 }
135
136 if ( pcap_addr->broadaddr && ( ( pcap_addr->broadaddr->sa_family == AF_INET ) ||
137 ( pcap_addr->broadaddr->sa_family == AF_INET6 ) ) )
138 {
139 if ( ! inet_ntop( pcap_addr->broadaddr->sa_family, (void *)&pcap_addr->broadaddr->sa_data[2],
140 iface_data->broadcast, IPADDRSIZ ) )
141 thread_error( "inet_ntop error", errno );
142 }
143
144 if ( pcap_addr->dstaddr && ( ( pcap_addr->dstaddr->sa_family == AF_INET ) ||
145 ( pcap_addr->dstaddr->sa_family == AF_INET6 ) ) )
146 {
147 if ( ! inet_ntop( pcap_addr->dstaddr->sa_family, (void *)&pcap_addr->dstaddr->sa_data[2],
148 iface_data->ptpaddr, IPADDRSIZ ) )
149 thread_error("inet_ntop error",errno);
150 }
151
152 pcap_addr = pcap_addr->next ;
153
154 }
155
156 return 0 ;
157 }
158
159
160 ////////////////////////////////////////////////////////////////////////////////////////////////////
161
162
163 int8_t
interfaces_init_data_pcap(struct interface_data * iface_data,pcap_if_t * index)164 interfaces_init_data_pcap( struct interface_data *iface_data, pcap_if_t *index )
165 {
166 char errbuf[PCAP_ERRBUF_SIZE];
167 pcap_t *pcap_hnd ;
168 int8_t ret = -1 ;
169
170 if ( ( pcap_hnd = pcap_open_live( iface_data->ifname, SNAPLEN, 0, 0, errbuf ) ) )
171 {
172 iface_data->iflink = pcap_datalink( pcap_hnd );
173
174 pcap_close( pcap_hnd );
175
176 if ( iface_data->iflink == DLT_EN10MB )
177 {
178 strncpy( iface_data->iflink_name, pcap_datalink_val_to_name( iface_data->iflink ), PCAP_DESC );
179 strncpy( iface_data->iflink_desc, pcap_datalink_val_to_description( iface_data->iflink ), PCAP_DESC );
180
181 write_log( 0, "\n %s iflinkname %s\n", iface_data->ifname, iface_data->iflink_name );
182 write_log( 0, " %s iflinkdesc %s\n", iface_data->ifname, iface_data->iflink_desc );
183
184 interfaces_init_data_pcap_addr( index, iface_data ) ;
185
186 if (tty_tmp->debug )
187 {
188 write_log( 0," %s ip is %s\n",iface_data->ifname, iface_data->ipaddr);
189 write_log( 0," %s mask is %s\n", iface_data->ifname, iface_data->netmask);
190 write_log( 0," %s broadcast is %s\n", iface_data->ifname, iface_data->broadcast);
191 write_log( 0," %s P-t-P is %s\n", iface_data->ifname, iface_data->ptpaddr );
192 }
193
194 ret = 0 ;
195 }
196
197 }
198 else
199 {
200 write_log( 0, "pcap_open_live failed: %s\n", errbuf );
201 }
202
203 return ret;
204 }
205
206
207 ////////////////////////////////////////////////////////////////////////////////////////////////////
208
209
210 int8_t
interfaces_init_data_libnet(struct interface_data * interface)211 interfaces_init_data_libnet( struct interface_data *interface )
212 {
213 char errbuflibnet[LIBNET_ERRBUF_SIZE];
214 struct libnet_ether_addr *etheraddr;
215 libnet_t *libnet_hnd;
216 int8_t ret = -1 ;
217
218 if ( ( libnet_hnd = libnet_init( LIBNET_LINK, interface->ifname, errbuflibnet ) ) )
219 {
220 etheraddr = libnet_get_hwaddr( libnet_hnd );
221
222 if ( etheraddr )
223 {
224 if ( memcmp( (void *)etheraddr, "\x0\x0\x0\x0\x0\x0", 6 ) )
225 memcpy( (void *)interface->etheraddr, (void *)etheraddr, ETHER_ADDR_LEN );
226
227 write_log( 0," %s MAC = %02x%02x.%02x%02x.%02x%02x\n", interface->ifname,
228 etheraddr->ether_addr_octet[0], etheraddr->ether_addr_octet[1],
229 etheraddr->ether_addr_octet[2], etheraddr->ether_addr_octet[3],
230 etheraddr->ether_addr_octet[4], etheraddr->ether_addr_octet[5]);
231 }
232
233 libnet_destroy( libnet_hnd );
234
235 ret = 0;
236 }
237 else
238 write_log( 0, "libnet_init failed on %s -> %s\n", interface->ifname, errbuflibnet );
239
240 return ret ;
241 }
242
243
244 ////////////////////////////////////////////////////////////////////////////////////////////////////
245
246
247 /*
248 * Initialize global interfaces list (interfaces).
249 */
interfaces_init(THREAD * pcap_th)250 int8_t interfaces_init( THREAD *pcap_th )
251 {
252 char errbuf[PCAP_ERRBUF_SIZE];
253 struct interface_data *iface_data = NULL;
254 pcap_if_t *alldevs;
255 pcap_if_t *index ;
256 u_int16_t i, j;
257
258 if (pcap_findalldevs(&alldevs, errbuf) == -1)
259 {
260 write_log(0,"interfaces_init pcap_findalldevs: %s\n", errbuf);
261 return -1;
262 }
263
264 if (tty_tmp->debug)
265 write_log(0,"\n interfaces_init start...\n");
266
267 if ((interfaces = (list_t *) calloc(1, sizeof(list_t))) == NULL) {
268 write_log(0, "interfaces_init calloc interfaces\n");
269 return -1;
270 }
271
272 if (pthread_mutex_init(&interfaces->mutex, NULL) != 0)
273 {
274 thread_error("interfaces_init pthread_mutex_init interfaces->mutex", errno);
275 free( interfaces );
276 interfaces = NULL ;
277 return -1;
278 }
279
280 interfaces->cmp = interfaces_compare;
281
282 index = (pcap_if_t *) alldevs;
283
284 while( index )
285 {
286 if ( ( strncmp( index->name, "any", strlen( index->name ) ) ) && ( index->flags != PCAP_IF_LOOPBACK ) )
287 {
288 if ( ( iface_data = (struct interface_data *)calloc( 1, sizeof( struct interface_data ) ) ) )
289 {
290 strncpy( iface_data->ifname, index->name, IFNAMSIZ );
291
292 write_log( 0, "Network Interface %s\n", index->name );
293
294 if ( interfaces_init_data_pcap( iface_data, index ) != -1 )
295 {
296 if ( interfaces_init_data_libnet( iface_data ) != -1 )
297 {
298 iface_data->up = 0;
299 iface_data->pcap_handler = NULL;
300 iface_data->pcap_file = 0;
301 iface_data->libnet_handler = NULL;
302 iface_data->users = 0;
303
304 for ( j = 0; j < MAX_PROTOCOLS ; j++ )
305 {
306 iface_data->packets[j] = 0 ;
307 iface_data->packets_out[j] = 0 ;
308 }
309
310 interfaces->list = dlist_append( interfaces->list, (void *)iface_data );
311 }
312 }
313 }
314 else
315 {
316 write_log( 0, "interfaces_init calloc iface_data\n" );
317 return -1;
318 }
319 }
320
321 index = index->next;
322 }
323
324 /* free alldevs memory */
325 pcap_freealldevs(alldevs);
326
327 packet_stats.global_counter.total_packets = 0;
328
329 /* Initialize the packets queues...*/
330 for ( i = 0 ; i < MAX_PROTOCOLS ; i++ )
331 {
332 queue[i].index = 0;
333 if ( pthread_mutex_init(&queue[i].mutex, NULL) != 0)
334 {
335 thread_error("pthread_mutex_init",errno);
336 return -1;
337 }
338
339 for ( j=0 ; j < MAX_QUEUE ; j++ )
340 {
341 if ( ( queue[i].data[j].packet = (u_char *) calloc( 1, SNAPLEN ) ) == NULL )
342 return -1;
343
344 if ( ( queue[i].data[j].header = (struct pcap_pkthdr *) calloc( 1, sizeof( struct pcap_pkthdr ) ) ) == NULL )
345 return -1;
346 }
347 }
348
349 if ( thread_create( pcap_th, &interfaces_th_pcap_listen, (void *)pcap_th ) )
350 return -1;
351
352 if (tty_tmp->debug)
353 write_log(0,"\n interfaces_init finish...\n");
354
355 return 0;
356 }
357
358
359 /*
360 * Enable a network interface in the global interfaces list
361 * Return interface index or -1 on error.
362 * Use global interfaces list (interfaces).
363 */
364 int16_t
interfaces_enable(char * iface)365 interfaces_enable(char *iface)
366 {
367 dlist_t *p;
368 u_int16_t i;
369 struct interface_data *iface_data;
370
371 if (pthread_mutex_lock(&interfaces->mutex) != 0)
372 {
373 thread_error("interfaces_enable pthread_mutex_lock",errno);
374 return -1;
375 }
376
377 for (i = 0, p = interfaces->list; p; i++, p = dlist_next(interfaces->list, p))
378 {
379 iface_data = (struct interface_data *) dlist_data(p);
380 if ((strncmp(iface_data->ifname, iface, strlen(iface))) == 0)
381 {
382 if (iface_data->users == 0)
383 {
384 iface_data->up = 1;
385 iface_data->users++;
386 if (iface_data->pcap_handler == NULL) {
387 if (interfaces_init_pcap(iface_data->ifname) == -1)
388 {
389 if (pthread_mutex_unlock(&interfaces->mutex) != 0)
390 thread_error("interfaces_enable pthread_mutex_unlock",errno);
391 return -1;
392 }
393 }
394
395 if (iface_data->libnet_handler == NULL) {
396 if (interfaces_init_libnet(iface_data->ifname) == -1)
397 {
398 if (pthread_mutex_unlock(&interfaces->mutex) != 0)
399 thread_error("interfaces_enable pthread_mutex_unlock",errno);
400 return -1;
401 }
402 }
403 }
404 else
405 iface_data->users++;
406
407 if (pthread_mutex_unlock(&interfaces->mutex) != 0)
408 {
409 thread_error("interfaces_enable pthread_mutex_unlock",errno);
410 return -1;
411 }
412
413 return i;
414 }
415 }
416
417 if (pthread_mutex_unlock(&interfaces->mutex) != 0)
418 thread_error("interfaces_enable pthread_mutex_unlock",errno);
419
420 return -1;
421 }
422
423
424 /*
425 * Search for interface name.
426 * Use global interfaces list (interfaces).
427 * Return interface index on success.
428 * Return -1 on error.
429 */
interfaces_get(char * iface)430 int16_t interfaces_get( char *iface )
431 {
432 dlist_t *p;
433 u_int16_t i;
434 struct interface_data *iface_data;
435
436 if ( pthread_mutex_lock( &interfaces->mutex ) != 0 )
437 {
438 thread_error( "interfaces_get pthread_mutex_lock", errno );
439 return -1;
440 }
441
442 for ( i = 0, p = interfaces->list; p ; i++, p = dlist_next( interfaces->list, p ) )
443 {
444 iface_data = (struct interface_data *) dlist_data(p);
445
446 if ( strncmp( iface_data->ifname, iface, strlen( iface ) ) == 0 )
447 {
448 if ( pthread_mutex_unlock( &interfaces->mutex ) != 0 )
449 {
450 thread_error( "interfaces_get pthread_mutex_unlock", errno );
451
452 return -1;
453 }
454
455 return i;
456 }
457 }
458
459 if (pthread_mutex_unlock(&interfaces->mutex) != 0)
460 thread_error("interfaces_get pthread_mutex_unlock",errno);
461
462 return -1;
463 }
464
465
466 /*
467 * Search for enabled interface by name
468 * Return interface index on success.
469 * Return -1 on error.
470 */
interfaces_get_enabled(char * iface)471 int16_t interfaces_get_enabled( char *iface )
472 {
473 dlist_t *p;
474 u_int16_t i;
475 struct interface_data *iface_data;
476
477 if ( pthread_mutex_lock( &interfaces->mutex ) != 0 )
478 {
479 thread_error( "interfaces_get pthread_mutex_lock", errno );
480 return -1;
481 }
482
483 for ( i = 0, p = interfaces->list; p ; i++, p = dlist_next( interfaces->list, p ) )
484 {
485 iface_data = (struct interface_data *) dlist_data(p);
486
487 if ( iface_data->up && ( strncmp( iface_data->ifname, iface, strlen( iface ) ) == 0 ) )
488 {
489 if ( pthread_mutex_unlock( &interfaces->mutex ) != 0 )
490 {
491 thread_error( "interfaces_get pthread_mutex_unlock", errno );
492
493 return -1;
494 }
495
496 return i;
497 }
498 }
499
500 if ( pthread_mutex_unlock(&interfaces->mutex) != 0 )
501 thread_error("interfaces_get pthread_mutex_unlock", errno );
502
503 return -1;
504 }
505
506
507 /*
508 * Search for interface name.
509 * Use global interfaces list (interfaces).
510 * Return interface_data * on success.
511 * Return NULL on error.
512 */
513 struct interface_data *
interfaces_get_struct(char * iface)514 interfaces_get_struct(char *iface)
515 {
516 dlist_t *p;
517 u_int16_t i;
518 struct interface_data *iface_data;
519
520 if (pthread_mutex_lock(&interfaces->mutex) != 0)
521 {
522 thread_error("interfaces_get pthread_mutex_lock",errno);
523 return NULL;
524 }
525
526 for (i = 0, p = interfaces->list; p ; i++, p = dlist_next(interfaces->list, p))
527 {
528 iface_data = (struct interface_data *) dlist_data(p);
529 if ((strncmp(iface_data->ifname, iface, strlen(iface))) == 0)
530 {
531 if (pthread_mutex_unlock(&interfaces->mutex) != 0)
532 {
533 thread_error("interfaces_get pthread_mutex_unlock",errno);
534 return NULL;
535 }
536 return iface_data;
537 }
538 }
539
540 if (pthread_mutex_unlock(&interfaces->mutex) != 0)
541 thread_error("interfaces_get pthread_mutex_unlock",errno);
542
543 return NULL;
544 }
545
546
547
548 /*
549 * Disable a network interface from the global interfaces list
550 * Return -1 on error, 0 on success.
551 * Use global interfaces list (interfaces).
552 */
interfaces_disable(char * iface)553 int8_t interfaces_disable( char *iface )
554 {
555 int8_t ret = -1 ;
556 dlist_t *node;
557 struct interface_data *iface_data;
558
559 if ( ! pthread_mutex_lock( &interfaces->mutex ) )
560 {
561 node = dlist_search( interfaces->list, interfaces->cmp, (void *)iface );
562
563 if ( node )
564 {
565 iface_data = (struct interface_data *) dlist_data(node);
566
567 if ( iface_data->users == 1 )
568 {
569 iface_data->up = 0;
570 iface_data->users = 0;
571 }
572 else
573 iface_data->users--;
574
575 ret = 0 ;
576 }
577 else
578 {
579 write_log(0, "Ohh I haven't found the interface %s\n", iface);
580 ret = -1;
581 }
582
583 if (pthread_mutex_unlock(&interfaces->mutex) != 0)
584 {
585 thread_error("interfaces_disable pthread_mutex_unlock",errno);
586 ret = -1;
587 }
588 }
589 else
590 thread_error("interfaces_disable pthread_mutex_lock",errno);
591
592 return ret ;
593 }
594
595
596 int8_t
interfaces_init_pcap(char * iface)597 interfaces_init_pcap(char *iface)
598 {
599 struct bpf_program filter_code;
600 dlist_t *node;
601 struct interface_data *iface_data;
602 bpf_u_int32 local_net, netmask;
603 char errbuf[PCAP_ERRBUF_SIZE];
604 #ifdef HAVE_BPF
605 u_int8_t one;
606 #endif
607
608 node = dlist_search(interfaces->list, interfaces->cmp, iface);
609 if (!node)
610 return -1;
611
612 iface_data = (struct interface_data *) dlist_data(node);
613
614 if ( (iface_data->pcap_handler = pcap_open_live(iface_data->ifname,
615 SNAPLEN, PROMISC, TIMEOUT, errbuf)) == NULL)
616 {
617 write_log(0, "pcap_open_live failed: %s\n", errbuf);
618 return -1;
619 }
620
621 if ( pcap_lookupnet(iface_data->ifname, &local_net, &netmask, errbuf) == -1)
622 {
623 write_log(0, "pcap_lookupnet failed: %s\n", errbuf);
624 /* Removed so we can sniff on interfaces without address... :) */
625 /* return -1; */
626 }
627
628 if (pcap_compile(iface_data->pcap_handler, &filter_code, FILTER, 0, netmask) == -1 )
629 {
630 write_log(0, "pcap_compile failed: %s", pcap_geterr(iface_data->pcap_handler));
631 return -1;
632 }
633
634 if (pcap_setfilter(iface_data->pcap_handler, &filter_code) == -1)
635 {
636 write_log(0, "pcap_setfilter failed: %s", pcap_geterr(iface_data->pcap_handler));
637 return -1;
638 }
639
640 iface_data->pcap_file = pcap_fileno(iface_data->pcap_handler);
641 #ifdef HAVE_BPF
642 one = 1;
643 if (ioctl(iface_data->pcap_file, BIOCIMMEDIATE, &one) < 0)
644 {
645 write_log(0, "ioctl(): BIOCIMMEDIATE: %s", strerror(errno));
646 return (-1);
647 }
648 #endif
649
650 return 0;
651 }
652
653
654 int8_t
interfaces_init_libnet(char * iface)655 interfaces_init_libnet(char *iface)
656 {
657 char errbuf[LIBNET_ERRBUF_SIZE];
658 dlist_t *node;
659 struct interface_data *iface_data;
660
661 node = dlist_search(interfaces->list, interfaces->cmp, (void *)iface);
662 iface_data = dlist_data(node);
663
664 iface_data->libnet_handler = libnet_init(LIBNET_LINK, iface_data->ifname, errbuf);
665
666 if (iface_data->libnet_handler == NULL)
667 {
668 write_log(0,"libnet_init failed on %s -> %s\n", iface_data->ifname, errbuf);
669 return -1;
670 }
671 /* we need 'pseudorandom' numbers ;) */
672 libnet_seed_prand(iface_data->libnet_handler);
673
674 return 0;
675 }
676
677
678 /*
679 * Thread body for listening in the network and serve the packets
680 * Use global struct 'queue'
681 */
interfaces_th_pcap_listen(void * arg)682 void interfaces_th_pcap_listen( void *arg )
683 {
684 THREAD *pcap_th = (THREAD *)arg;
685 struct interface_data *iface_data;
686 int32_t ret, max;
687 u_int16_t a;
688 int8_t proto;
689 fd_set read_set;
690 struct timeval timeout;
691 sigset_t mask;
692 struct pcap_data packet_data;
693 dlist_t *p;
694
695 if (tty_tmp->debug)
696 write_log(0,"\n interfaces_th_pcap_listen thread_id = %X\n",(int)pthread_self());
697
698 pthread_mutex_lock(&pcap_th->finished);
699
700 sigfillset(&mask);
701
702 if (pthread_sigmask(SIG_BLOCK, &mask, NULL))
703 {
704 thread_error("ints_th_pcap_listen pthread_sigmask()",errno);
705 interfaces_th_pcap_listen_exit(pcap_th);
706 }
707
708 while(!pcap_th->stop)
709 {
710 max = 0;
711 FD_ZERO(&read_set);
712 p = interfaces->list;
713 while(p)
714 {
715 iface_data = (struct interface_data *) dlist_data(p);
716 if (iface_data->up == 1)
717 {
718 FD_SET( iface_data->pcap_file, &read_set );
719 if (max < iface_data->pcap_file)
720 max = iface_data->pcap_file;
721 }
722 p = dlist_next(interfaces->list, p);
723 }
724
725 if (!max) /* For avoiding 100% CPU */
726 thread_usleep(150000);
727
728 if (max && !pcap_th->stop)
729 {
730 timeout.tv_sec = 0;
731 timeout.tv_usec = 500000;
732
733 if ( (ret=select( max+1, &read_set, NULL, NULL, &timeout ) ) == -1 )
734 {
735 thread_error("interfaces_th_pcap_listen select()",errno);
736 interfaces_th_pcap_listen_exit(pcap_th);
737 }
738
739 if ( ret ) /* Data on pcap... */
740 {
741 p = interfaces->list;
742 while( (p) && !pcap_th->stop )
743 {
744 iface_data = (struct interface_data *) dlist_data(p);
745 if (iface_data->up == 1)
746 {
747 if (FD_ISSET( iface_data->pcap_file, &read_set ))
748 {
749 if ((ret = pcap_next_ex(iface_data->pcap_handler, &packet_data.header, (const u_char **) &packet_data.packet)) < 0)
750 {
751 write_log(0, "interfaces_th_pcap_listen pcap_next_ex failed: (%d) %s", ret, pcap_geterr(iface_data->pcap_handler));
752 interfaces_th_pcap_listen_exit(pcap_th);
753
754 }
755 if (!ret) /* pcap_next_ex timeout...*/
756 continue;
757 } else {
758 p = dlist_next(interfaces->list, p);
759 continue;
760 }
761
762 /* save the interface that has received the packet */
763 strncpy(packet_data.iface, iface_data->ifname, IFNAMSIZ);
764
765 /* update stats */
766 if (tty_tmp->debug)
767 write_log(0, "Updating packet stats in interface %s...\n", iface_data->ifname);
768
769 proto = interfaces_update_stats(&packet_data);
770
771 if (tty_tmp->debug)
772 write_log(0, "Packet stats updated!\n");
773
774 if (proto != NO_PROTO)
775 {
776 /* update the user pcap_files...*/
777 if (pthread_mutex_lock(&terms->mutex) != 0)
778 thread_error("interfaces pthread_mutex_lock",errno);
779
780 for(a=0; a<MAX_TERMS; a++)
781 {
782 if (terms->list[a].up)
783 {
784 if (terms->list[a].pcap_file.pdumper && (terms->list[a].pcap_file.iflink == iface_data->iflink) )
785 pcap_dump((u_char *)terms->list[a].pcap_file.pdumper, packet_data.header, packet_data.packet);
786 if (terms->list[a].protocol[proto].pcap_file.pdumper &&
787 (terms->list[a].protocol[proto].pcap_file.iflink == iface_data->iflink) )
788 pcap_dump((u_char *)terms->list[a].protocol[proto].pcap_file.pdumper, packet_data.header, packet_data.packet);
789 }
790
791 }
792 if (pthread_mutex_unlock(&terms->mutex) != 0)
793 thread_error("ints_th_pcap_listen pthread_mutex_unlock",errno);
794
795 /* update the queue...*/
796 pthread_mutex_lock(&queue[proto].mutex);
797 memcpy(queue[proto].data[(queue[proto].index%MAX_QUEUE)].header, packet_data.header, sizeof(struct pcap_pkthdr));
798 memcpy(queue[proto].data[(queue[proto].index%MAX_QUEUE)].packet, packet_data.packet, packet_data.header->caplen);
799 strncpy(queue[proto].data[(queue[proto].index%MAX_QUEUE)].iface, packet_data.iface, IFNAMSIZ);
800 queue[proto].index++;
801 pthread_mutex_unlock(&queue[proto].mutex);
802 }
803 } /* if interfaces.up */
804 p = dlist_next(interfaces->list, p);
805 } /* while */
806 }
807 } /* if max */
808
809 } /* while(!stop)*/
810
811 interfaces_th_pcap_listen_exit( pcap_th );
812 }
813
814
815 /*
816 * We arrived here due to normal termination
817 * from thread pcap listener main routine...
818 * Release resources...
819 */
interfaces_th_pcap_listen_exit(THREAD * pcap_th)820 void interfaces_th_pcap_listen_exit( THREAD *pcap_th )
821 {
822 write_log(0,"\n ints_pcap_listen_exit started...\n");
823
824 pcap_th->stop = 0;
825 pcap_th->id = 0;
826
827 /* Tell parent that we are going to die... */
828 fatal_error--;
829
830 write_log(0,"\n ints_pcap_listen_exit finished...\n");
831
832 if (pthread_mutex_unlock(&pcap_th->finished) != 0)
833 thread_error("ints_pcap_listen_exit mutex_unlock",errno);
834
835 pthread_exit(NULL);
836 }
837
838
839 /*
840 * Get a packet from the protocol queue
841 * Use global struct 'queue'.
842 * Return a pointer to the interface that has received the packet (struct
843 * interface_data).
844 */
interfaces_get_packet(list_t * used_ints,struct interface_data * iface,u_int8_t * stop_attack,struct pcap_pkthdr * header,u_int8_t * packet,u_int16_t proto,time_t timeout)845 struct interface_data *interfaces_get_packet( list_t *used_ints, struct interface_data *iface,
846 u_int8_t *stop_attack, struct pcap_pkthdr *header,
847 u_int8_t *packet, u_int16_t proto, time_t timeout)
848 {
849 u_int8_t i;
850 time_t initial, secs;
851 dlist_t *p;
852
853 secs = initial = time(NULL);
854 while(!(*stop_attack) && ((secs - initial) <= timeout))
855 {
856 pthread_mutex_lock(&queue[proto].mutex);
857 for(i=0; i < MAX_QUEUE; i++)
858 {
859 if ( (queue[proto].data[i].header->ts.tv_sec > header->ts.tv_sec) ||
860 ( (queue[proto].data[i].header->ts.tv_sec == header->ts.tv_sec) &&
861 (queue[proto].data[i].header->ts.tv_usec > header->ts.tv_usec) )
862 )
863 {
864 /* Only accept packets from this interface */
865 if (iface) {
866 if (strncmp(iface->ifname, queue[proto].data[i].iface, IFNAMSIZ) == 0) {
867 memcpy(header, queue[proto].data[i].header, sizeof(struct pcap_pkthdr));
868 memcpy(packet, queue[proto].data[i].packet, queue[proto].data[i].header->caplen);
869 pthread_mutex_unlock(&queue[proto].mutex);
870
871 return (struct interface_data *) iface;
872 }
873 } else {
874 /* Accept packets from ALL intefarces used by the attack */
875 p = dlist_search(used_ints->list, used_ints->cmp, queue[proto].data[i].iface);
876 if (p) {
877 memcpy(header, queue[proto].data[i].header, sizeof(struct pcap_pkthdr));
878 memcpy(packet, queue[proto].data[i].packet, queue[proto].data[i].header->caplen);
879 pthread_mutex_unlock(&queue[proto].mutex);
880
881 return (struct interface_data *) dlist_data(p);
882 }
883 }
884 }
885 }
886 pthread_mutex_unlock(&queue[proto].mutex);
887
888 if (timeout)
889 secs = time(NULL);
890 thread_usleep(50000);
891 }
892
893 return NULL;
894 }
895
896
897 /*
898 * Update protocol statistics.
899 * Return protocol
900 */
901 u_int16_t
interfaces_update_stats(struct pcap_data * packet_data)902 interfaces_update_stats(struct pcap_data *packet_data)
903 {
904 struct timeval time_tmp;
905 struct pcap_data *thedata;
906 u_int16_t i, j, min_len;
907 u_int8_t found;
908 int8_t proto;
909 dlist_t *p;
910 struct interface_data *iface_data;
911
912 i = j = min_len = 0;
913 found = 0;
914 thedata = NULL;
915
916 if ((proto = interfaces_recognize_packet(packet_data->packet, packet_data->header)) < 0)
917 return -1;
918
919 thedata = protocols[proto].stats;
920 protocols[proto].packets++;
921 if ((p = dlist_search(interfaces->list, interfaces->cmp, (void *)packet_data->iface)) == NULL)
922 return -1;
923 iface_data = (struct interface_data *) dlist_data(p);
924 iface_data->packets[proto]++;
925 memcpy(&time_tmp, &thedata[0].header->ts, sizeof(struct timeval));
926
927 /* Discard corrupt packets */
928 /* if (packet_data->header->caplen < min_len) {
929 write_log(0, "Error when receiving packet from protocol %d and size %d and the \
930 minimum size is %d\n", proto, packet_data->header->caplen, min_len);
931 return NO_PROTO;
932 }*/
933
934 /* find if there is a similar packet */
935 while ((!found) && (i < MAX_PACKET_STATS)) {
936 if ((memcmp(thedata[i].packet, packet_data->packet, packet_data->header->caplen) == 0)
937 && (strncmp(thedata[i].iface, packet_data->iface, strlen(thedata[i].iface)) == 0)) {
938 memcpy(thedata[i].header, packet_data->header, sizeof(struct pcap_pkthdr));
939 found = 1;
940 /* increase the count */
941 thedata[i].total++;
942 } else {
943 if ( (thedata[i].header->ts.tv_sec < time_tmp.tv_sec) ||
944 ( (thedata[i].header->ts.tv_sec == time_tmp.tv_sec) && (thedata[i].header->ts.tv_usec < time_tmp.tv_usec))
945 )
946 {
947 memcpy(&time_tmp, &thedata[i].header->ts, sizeof(struct timeval));
948 j = i;
949 }
950 }
951 i++;
952 }
953
954 /* if not, remove the oldest one */
955 if (!found) {
956 memcpy(thedata[j].header, packet_data->header, sizeof(struct pcap_pkthdr));
957 memcpy(thedata[j].packet, packet_data->packet, packet_data->header->caplen);
958 strncpy(thedata[j].iface, packet_data->iface, IFNAMSIZ);
959 thedata[j].total = 1;
960 }
961
962 /* temporal fix until ARP is supported (will be?) */
963 if (proto != PROTO_ARP)
964 packet_stats.global_counter.total_packets++;
965 /* interfaces[packet_data->iface].total_packets++;*/
966
967 return proto;
968 }
969
970
971 int8_t
interfaces_recognize_packet(u_int8_t * packet,struct pcap_pkthdr * header)972 interfaces_recognize_packet(u_int8_t *packet, struct pcap_pkthdr *header)
973 {
974 u_int8_t i, j, *tmp1, isvalid;
975 int8_t result;
976
977 result = -1;
978 for (i = 0; i < MAX_PROTOCOLS; i++)
979 {
980 if (!protocols[i].active)
981 continue;
982
983 j = 0;
984 isvalid = 1;
985 while (protocols[i].features[j].field > 0) {
986 switch(protocols[i].features[j].field) {
987 case F_ETHERTYPE:
988 if (header->caplen >= 12) {
989 if (ntohs(*(u_int16_t *)(packet + 12)) == (u_int16_t)protocols[i].features[j].value)
990 result = protocols[i].proto;
991 else
992 isvalid = 0;
993 }
994 break;
995 case F_LLC_DSAP:
996 if (header->caplen >= LIBNET_802_3_H) {
997 if ((*(u_int8_t *)(packet + LIBNET_802_3_H)) == (u_int8_t)protocols[i].features[j].value)
998 result = protocols[i].proto;
999 else
1000 isvalid = 0;
1001 }
1002 break;
1003 case F_LLC_SSAP:
1004 if (header->caplen >= LIBNET_802_3_H + 1) {
1005 if ((*(u_int8_t *)(packet + LIBNET_802_3_H + 1)) == (u_int8_t)protocols[i].features[j].value)
1006 result = protocols[i].proto;
1007 else
1008 isvalid = 0;
1009 }
1010 break;
1011 case F_LLC_SNAP:
1012 if (header->caplen >= LIBNET_802_3_H + 2) {
1013 if ((*(u_int8_t *)(packet + LIBNET_802_3_H + 2)) == (u_int8_t)protocols[i].features[j].value)
1014 result = protocols[i].proto;
1015 else
1016 isvalid = 0;
1017 }
1018 break;
1019 case F_LLC_CISCO:
1020 if (header->caplen >= 20) {
1021 if (ntohs(*(u_int16_t *)(packet + 20)) == (u_int16_t)protocols[i].features[j].value)
1022 result = protocols[i].proto;
1023 else
1024 isvalid = 0;
1025 }
1026 break;
1027 case F_DMAC_1:
1028 if (header->caplen >= 1) {
1029 if ((*(u_int8_t *)(packet)) == (u_int8_t)protocols[i].features[j].value)
1030 result = protocols[i].proto;
1031 else
1032 isvalid = 0;
1033 }
1034 break;
1035 case F_DMAC_2:
1036 if (header->caplen >= 2) {
1037 if ((*(u_int8_t *)(packet + 1)) == (u_int8_t)protocols[i].features[j].value)
1038 result = protocols[i].proto;
1039 else
1040 isvalid = 0;
1041 }
1042 break;
1043 case F_DMAC_3:
1044 if (header->caplen >= 3) {
1045 if ((*(u_int8_t *)(packet+ 2)) == (u_int8_t)protocols[i].features[j].value)
1046 result = protocols[i].proto;
1047 else
1048 isvalid = 0;
1049 }
1050 break;
1051 case F_DMAC_4:
1052 if (header->caplen >= 4) {
1053 if ((*(u_int8_t *)(packet + 3)) == (u_int8_t)protocols[i].features[j].value)
1054 result = protocols[i].proto;
1055 else
1056 isvalid = 0;
1057 }
1058 break;
1059 case F_DMAC_5:
1060 if (header->caplen >= 5) {
1061 if ((*(u_int8_t *)(packet + 4)) == (u_int8_t)protocols[i].features[j].value)
1062 result = protocols[i].proto;
1063 else
1064 isvalid = 0;
1065 }
1066 break;
1067 case F_DMAC_6:
1068 if (header->caplen >= 6) {
1069 if ((*(u_int8_t *)(packet + 5)) == (u_int8_t)protocols[i].features[j].value)
1070 result = protocols[i].proto;
1071 else
1072 isvalid = 0;
1073 }
1074 break;
1075 case F_UDP_PORT:
1076 if (header->caplen >= LIBNET_ETH_H + (((*(packet + LIBNET_ETH_H))&0x0F)*4)) {
1077 /* IP */
1078 if (ntohs(*(u_int16_t *)(packet + 12)) == 0x0800) {
1079 /* UDP datagram */
1080 if (*(packet + LIBNET_ETH_H + 9) == IPPROTO_UDP) {
1081 /* take the ipv4 header length out */
1082 tmp1 = (packet + LIBNET_ETH_H + (((*(packet + LIBNET_ETH_H))&0x0F)*4));
1083 if ((ntohs(*(u_int16_t *)(tmp1)) == protocols[i].features[j].value) ||
1084 (ntohs(*(u_int16_t *)(tmp1 + 2)) == protocols[i].features[j].value))
1085 result = protocols[i].proto;
1086 else
1087 isvalid = 0;
1088 }
1089 }
1090 }
1091 break;
1092 default:
1093 break;
1094 }
1095 j++;
1096 }
1097 if ((isvalid) && (result >= 0))
1098 return result;
1099 }
1100
1101 return -1;
1102 }
1103
1104
1105 int8_t
interfaces_clear_stats(int8_t stats)1106 interfaces_clear_stats(int8_t stats)
1107 {
1108 int8_t i, j;
1109 dlist_t *p;
1110 struct interface_data *iface_data;
1111
1112 for (i = 0; i < MAX_PACKET_STATS; i++)
1113 {
1114 if (stats == PROTO_ALL)
1115 for (j = 0; j < MAX_PROTOCOLS; j++) {
1116 memset((void *)protocols[j].stats[i].header, 0, sizeof(struct pcap_pkthdr));
1117 memset((void *)protocols[j].stats[i].packet, 0, SNAPLEN);
1118 } else {
1119 memset((void *)protocols[stats].stats[i].header, 0, sizeof(struct pcap_pkthdr));
1120 memset((void *)protocols[stats].stats[i].packet, 0, SNAPLEN);
1121 }
1122 }
1123
1124 if (stats == PROTO_ALL) {
1125 packet_stats.global_counter.total_packets = 0;
1126 for (i = 0; i < MAX_PROTOCOLS; i++)
1127 protocols[i].packets = 0;
1128 } else
1129 protocols[stats].packets = 0;
1130
1131 for (p = interfaces->list; p; p = dlist_next(interfaces->list, p)) {
1132 iface_data = (struct interface_data *) dlist_data(p);
1133 if (stats == PROTO_ALL) {
1134 /* interfaces[i].total_packets = 0;*/
1135 for (j = 0; j < MAX_PROTOCOLS; j++) {
1136 iface_data->packets[j] = 0;
1137 iface_data->packets_out[j] = 0;
1138 }
1139 } else {
1140 iface_data->packets[stats] = 0;
1141 iface_data->packets_out[stats] = 0;
1142 }
1143 }
1144
1145 write_log(0, "Clearing stats for protocol(s) %d...\n", stats);
1146
1147 return 0;
1148 }
1149
1150
1151 int8_t
interfaces_destroy(THREAD * pcap_th)1152 interfaces_destroy(THREAD *pcap_th)
1153 {
1154 u_int16_t i, j;
1155 dlist_t *p;
1156 struct interface_data *iface_data;
1157
1158 write_log(0,"\n ints_destroy started...\n");
1159
1160 if (pcap_th->id)
1161 {
1162 write_log(0," ints_destroy killing pcap_listener(%d)...\n", (int)pcap_th->id);
1163 thread_destroy(pcap_th);
1164 }
1165
1166 for (i=0; i < MAX_PROTOCOLS; i++)
1167 {
1168 if (pthread_mutex_destroy(&queue[i].mutex) != 0)
1169 thread_error("pthread_mutex_destroy queue",errno);
1170 for (j=0; j < MAX_QUEUE; j++)
1171 {
1172 if (queue[i].data[j].packet)
1173 free(queue[i].data[j].packet);
1174 if (queue[i].data[j].header)
1175 free(queue[i].data[j].header);
1176 }
1177 }
1178
1179 /* destroy'em all!! I mean the libnet and pcap handlers :) */
1180 for (p = interfaces->list; p; p = dlist_next(interfaces->list, p))
1181 {
1182 iface_data = (struct interface_data *) dlist_data(p);
1183 if (iface_data->libnet_handler)
1184 libnet_destroy(iface_data->libnet_handler);
1185
1186 if (iface_data->pcap_handler)
1187 pcap_close(iface_data->pcap_handler);
1188 }
1189
1190
1191 dlist_delete(interfaces->list);
1192
1193 if (interfaces)
1194 {
1195 pthread_mutex_destroy(&interfaces->mutex);
1196 free(interfaces);
1197 }
1198
1199 write_log(0," ints_destroy finished...\n");
1200
1201 return 0;
1202 }
1203
1204
1205 /*
1206 * Open a pcap file for writing 'proto' packets
1207 * If proto == PROTO_ALL write packets from all protocols
1208 */
1209 int8_t
interfaces_pcap_file_open(struct term_node * node,u_int8_t proto,char * name,char * iface)1210 interfaces_pcap_file_open(struct term_node *node, u_int8_t proto, char *name, char *iface)
1211 {
1212 dlist_t *p;
1213 struct interface_data *iface_data;
1214
1215 if ((p = dlist_search(interfaces->list, interfaces->cmp, (void *)iface)) == NULL)
1216 return -1;
1217 iface_data = (struct interface_data *) dlist_data(p);
1218
1219 if (proto != PROTO_ALL)
1220 {
1221 if (strlen(name)>= FILENAME_MAX)
1222 {
1223 node->protocol[proto].pcap_file.name = (char *)calloc(1,FILENAME_MAX+1);
1224 if (node->protocol[proto].pcap_file.name == NULL)
1225 {
1226 thread_error("interfaces_pcap_file_open calloc",errno);
1227 return -1;
1228 }
1229 memcpy(node->protocol[proto].pcap_file.name,name,FILENAME_MAX);
1230 }
1231 else
1232 {
1233 node->protocol[proto].pcap_file.name = (char *)calloc(1,strlen(name)+1);
1234 if (node->protocol[proto].pcap_file.name == NULL)
1235 {
1236 thread_error("interfaces_pcap_file_open calloc",errno);
1237 return -1;
1238 }
1239 memcpy(node->protocol[proto].pcap_file.name,name,strlen(name));
1240 }
1241
1242 node->protocol[proto].pcap_file.pd = iface_data->pcap_handler;
1243 node->protocol[proto].pcap_file.pdumper = pcap_dump_open(node->protocol[proto].pcap_file.pd,
1244 node->protocol[proto].pcap_file.name);
1245 node->protocol[proto].pcap_file.iflink = iface_data->iflink;
1246
1247 if (node->protocol[proto].pcap_file.pdumper == NULL)
1248 {
1249 write_log(0,"pcap_dump_open: %s\n", pcap_geterr(node->protocol[proto].pcap_file.pd));
1250 node->protocol[proto].pcap_file.pd = NULL;
1251 free(node->protocol[proto].pcap_file.name);
1252 return -1;
1253 }
1254 }
1255 else
1256 {
1257 if (strlen(name)>= FILENAME_MAX)
1258 {
1259 node->pcap_file.name = (char *)calloc(1,FILENAME_MAX+1);
1260 if (node->pcap_file.name == NULL)
1261 {
1262 thread_error("interfaces_pcap_file_open calloc",errno);
1263 return -1;
1264 }
1265 memcpy(node->pcap_file.name,name,FILENAME_MAX);
1266 }
1267 else
1268 {
1269 node->pcap_file.name = (char *)calloc(1,strlen(name)+1);
1270 if (node->pcap_file.name == NULL)
1271 {
1272 thread_error("interfaces_pcap_file_open calloc",errno);
1273 return -1;
1274 }
1275 memcpy(node->pcap_file.name,name,strlen(name));
1276 }
1277
1278 node->pcap_file.pd = iface_data->pcap_handler;
1279 node->pcap_file.pdumper = pcap_dump_open(node->pcap_file.pd,
1280 node->pcap_file.name);
1281 node->pcap_file.iflink = iface_data->iflink;
1282
1283 if (node->pcap_file.pdumper == NULL)
1284 {
1285 write_log(0,"pcap_dump_open: %s\n", pcap_geterr(node->pcap_file.pd));
1286 node->pcap_file.pd = NULL;
1287 free(node->pcap_file.name);
1288 return -1;
1289 }
1290 }
1291
1292 return 0;
1293 }
1294
1295
1296 int8_t
interfaces_pcap_file_close(struct term_node * node,u_int8_t proto)1297 interfaces_pcap_file_close(struct term_node *node, u_int8_t proto)
1298 {
1299 if (proto != PROTO_ALL)
1300 {
1301 pcap_dump_flush(node->protocol[proto].pcap_file.pdumper);
1302 pcap_dump_close(node->protocol[proto].pcap_file.pdumper);
1303
1304 node->protocol[proto].pcap_file.pdumper = NULL;
1305 node->protocol[proto].pcap_file.pd = NULL;
1306 free(node->protocol[proto].pcap_file.name);
1307 node->protocol[proto].pcap_file.name = NULL;
1308 }
1309 else
1310 {
1311 pcap_dump_flush(node->pcap_file.pdumper);
1312 pcap_dump_close(node->pcap_file.pdumper);
1313
1314 node->pcap_file.pdumper = NULL;
1315 node->pcap_file.pd = NULL;
1316 free(node->pcap_file.name);
1317 node->pcap_file.name = NULL;
1318 }
1319
1320 return 0;
1321 }
1322
1323
1324 #ifndef HAVE_PCAP_DUMP_FLUSH
1325 int8_t
pcap_dump_flush(pcap_dumper_t * p)1326 pcap_dump_flush(pcap_dumper_t *p)
1327 {
1328 if (fflush((FILE *)p) == EOF)
1329 return (-1);
1330 else
1331 return (0);
1332 }
1333 #endif
1334
1335
1336
1337 /*
1338 * Get the last interface that has received a 'mode' packet.
1339 * If mode == PROTO_ALL take into account all the protocols.
1340 * Return 0 if no packet.
1341 */
1342 u_int8_t
interfaces_get_last_int(u_int8_t mode)1343 interfaces_get_last_int(u_int8_t mode)
1344 {
1345 u_int8_t i, a, last=0, proto;
1346 u_int32_t sec=0, usec=0;
1347
1348 for (a=0; a < MAX_PROTOCOLS; a++)
1349 {
1350 if (mode != PROTO_ALL)
1351 proto = mode;
1352 else
1353 proto = a;
1354 for (i=0; i < MAX_PACKET_STATS; i++)
1355 {
1356 if (protocols[proto].stats[i].header->ts.tv_sec > 0)
1357 {
1358 if ( (protocols[proto].stats[i].header->ts.tv_sec > sec) ||
1359 ( (protocols[proto].stats[i].header->ts.tv_sec == sec) &&
1360 (protocols[proto].stats[i].header->ts.tv_usec > usec) )
1361 )
1362 {
1363 sec = protocols[proto].stats[i].header->ts.tv_sec;
1364 usec = protocols[proto].stats[i].header->ts.tv_usec;
1365 last = interfaces_get(protocols[proto].stats[i].iface);
1366 }
1367 }
1368 }
1369 if (mode != PROTO_ALL)
1370 break;
1371 }
1372
1373 return last;
1374 }
1375
1376
interfaces_compare(void * data,void * pattern)1377 int interfaces_compare( void *data, void *pattern )
1378 {
1379 struct interface_data *iface_data;
1380
1381 iface_data = (struct interface_data *) data;
1382
1383 return( strncmp( (char *)iface_data->ifname, (char *)pattern, strlen( (char *)iface_data->ifname ) ) );
1384 }
1385
1386
1387