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