Changeset 1275


Ignore:
Timestamp:
09/13/07 14:08:52 (6 years ago)
Author:
smr26
Message:

Support for in-kernel BPF processing for the linux native capture format.
Requires libpcap to compile the filterstring.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/format_linux.c

    r1258 r1275  
    5656        int snaplen; 
    5757        int promisc; 
     58        libtrace_filter_t *filter; 
    5859}; 
    5960 
     
    7980        FORMAT(libtrace->format_data)->promisc = -1; 
    8081        FORMAT(libtrace->format_data)->snaplen = 65536; 
     82        FORMAT(libtrace->format_data)->filter = NULL; 
    8183 
    8284        return 0; 
     
    9799        int one = 1; 
    98100        memset(&addr,0,sizeof(addr)); 
     101        libtrace_filter_t *filter = FORMAT(libtrace->format_data)->filter; 
    99102        FORMAT(libtrace->format_data)->fd =  
    100103                                socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 
     
    158161        } 
    159162 
     163        /* Push BPF filter into the kernel. 
     164         */ 
     165        if (filter != NULL) { 
     166                if (setsockopt(FORMAT(libtrace->format_data)->fd, 
     167                                        SOL_SOCKET, 
     168                                        SO_ATTACH_FILTER, 
     169                                        &filter->filter, 
     170                                        sizeof(filter->filter)) == -1) { 
     171                        perror("setsockopt(SO_ATTACH_FILTER)"); 
     172                } else {  
     173                        /* The socket accepted the filter, so we need to 
     174                         * consume any buffered packets that were received 
     175                         * between opening the socket and applying the filter. 
     176                         */ 
     177                        void *buf = malloc((size_t)LIBTRACE_PACKET_BUFSIZE); 
     178                        while(recv(FORMAT(libtrace->format_data)->fd, 
     179                                        buf, 
     180                                        (size_t) LIBTRACE_PACKET_BUFSIZE, 
     181                                        MSG_DONTWAIT) != -1) { } 
     182                        free(buf); 
     183                } 
     184        } 
     185                                         
    160186        return 0; 
    161187} 
     
    183209static int linuxnative_fin_input(libtrace_t *libtrace)  
    184210{ 
     211        if (FORMAT(libtrace->format_data)->filter != NULL) 
     212                free(FORMAT(libtrace->format_data)->filter); 
    185213        free(libtrace->format_data); 
     214         
    186215        return 0; 
    187216} 
     
    195224} 
    196225 
     226static int linuxnative_configure_bpf(libtrace_t *libtrace,  
     227                libtrace_filter_t *filter) { 
     228#ifdef HAVE_LIBPCAP  
     229        struct ifreq ifr; 
     230        unsigned int arphrd; 
     231        libtrace_dlt_t dlt; 
     232        libtrace_filter_t *f; 
     233        int sock; 
     234        pcap_t *pcap; 
     235 
     236        /* We've been passed a filter, which hasn't been compiled yet. We need 
     237         * to figure out the linktype of the socket, compile the filter, check 
     238         * to make sure it's sane, then save it for trace_start() to push down 
     239         * into the kernel. 
     240         */ 
     241        sock = socket(PF_INET, SOCK_STREAM, 0); 
     242        memset(&ifr, 0, sizeof(struct ifreq)); 
     243        strncpy(ifr.ifr_name, libtrace->uridata, IF_NAMESIZE); 
     244        if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0) { 
     245                perror("Can't get HWADDR for interface"); 
     246                return -1; 
     247        } 
     248        close(socket); 
     249 
     250        arphrd = ifr.ifr_hwaddr.sa_family; 
     251        dlt = libtrace_to_pcap_dlt(arphrd_type_to_libtrace(arphrd)); 
     252 
     253        f = (libtrace_filter_t *) malloc(sizeof(libtrace_filter_t)); 
     254        memcpy(f, filter, sizeof(libtrace_filter_t)); 
     255 
     256        pcap = pcap_open_dead(dlt, FORMAT(libtrace->format_data)->snaplen); 
     257         
     258        if (pcap_compile(pcap, &f->filter, f->filterstring, 0, 0) == -1) { 
     259                perror("PCAP failed to compile the filterstring"); 
     260                return -1; 
     261        } 
     262 
     263        pcap_close(pcap); 
     264 
     265        if (FORMAT(libtrace->format_data)->filter != NULL) 
     266                free(FORMAT(libtrace->format_data)->filter); 
     267         
     268        FORMAT(libtrace->format_data)->filter = f; 
     269        return 0; 
     270#else 
     271        return -1 
     272#endif 
     273} 
    197274static int linuxnative_config_input(libtrace_t *libtrace, 
    198275                trace_option_t option, 
     
    207284                        return 0; 
    208285                case TRACE_OPTION_FILTER: 
    209                         /* We don't support bpf filters in any special way 
    210                          * so return an error and let libtrace deal with 
    211                          * emulating it 
    212                          */ 
    213                         break; 
     286                        return linuxnative_configure_bpf(libtrace,  
     287                                        (libtrace_filter_t *) data); 
    214288                case TRACE_OPTION_META_FREQ: 
    215289                        /* No meta-data for this format */ 
Note: See TracChangeset for help on using the changeset viewer.