Changeset 394706e


Ignore:
Timestamp:
09/13/07 14:08:52 (14 years ago)
Author:
Scott Raynel <smr26@…>
Branches:
4.0.1-hotfixes, cachetimestamps, develop, dpdk-ndag, etsilive, getfragoff, help, libtrace4, master, ndag_format, pfring, rc-4.0.1, rc-4.0.2, rc-4.0.3, rc-4.0.4, ringdecrementfix, ringperformance, ringtimestampfixes
Children:
dd06159
Parents:
9e6b38b
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
  • lib/format_linux.c

    r27bd348 r394706e  
    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.