Esempio n. 1
0
void add_iface(char *iface)
{
	char errbuf[PCAP_ERRBUF_SIZE];
	char const *filter;
	struct iface_config *ifc;
	int rc;

	if (cfg.v4_flag)
		filter = ip4_filter;
	else if (cfg.v6_flag)
		filter = ip6_filter;
	else
		filter = def_filter;

	ifc = (struct iface_config *) calloc(1, sizeof(struct iface_config));

	ifc->name = iface;

	ifc->pcap_handle = pcap_open_live(iface, SNAP_LEN, cfg.promisc_flag, 1000, errbuf);
	if (ifc->pcap_handle == NULL) {
		log_msg(LOG_WARNING, "Skipping interface %s, %s", iface, errbuf);
		goto error;
	}

	rc = pcap_datalink(ifc->pcap_handle);
	if (rc != DLT_EN10MB) {
		log_msg(LOG_WARNING, "Skipping interface %s, invalid data link layer %s (%s).", 
			iface,
			pcap_datalink_val_to_name(rc),
			pcap_datalink_val_to_description(rc));
		goto error_pcap;
	}

	rc = pcap_compile(ifc->pcap_handle, &ifc->pcap_filter, filter, 0, 0);
	if (rc == -1) {
		log_msg(LOG_WARNING, "Skipping interface %s, %s",
			iface, pcap_geterr(ifc->pcap_handle));
		goto error_pcap;
	}

	rc = pcap_setfilter(ifc->pcap_handle, &ifc->pcap_filter);
	if (rc == -1) {
		log_msg(LOG_WARNING, "Skipping iface %s, %s",
			iface, pcap_geterr(ifc->pcap_handle));
		goto error_filter;
	}

	rc = pcap_fileno(ifc->pcap_handle);

#if HAVE_LIBEVENT2
	ifc->event = event_new(cfg.eb, rc, EV_READ|EV_PERSIST, read_cb, ifc);
	if(!ifc->event)
		log_msg(LOG_ERR, "%s: event_new(...)", __FUNCTION__);

	event_add(ifc->event, NULL);
#else
	event_set(&ifc->event, rc, EV_READ|EV_PERSIST, read_cb, ifc);
	event_add(&ifc->event, NULL);
#endif

	if (cfg.hashsize < 1 || cfg.hashsize > 65536)
		log_msg(LOG_ERR, "%s: hash size (%d) must be >= 1 and <= 65536", __FUNCTION__, cfg.hashsize);

	if (cfg.ratelimit) {
		ifc->cache = calloc(cfg.hashsize, sizeof(*ifc->cache));
		if (!ifc->cache)
			log_msg(LOG_ERR, "%s: unable to allocate memory for hash cache", __FUNCTION__);
	}

	ifc->next = cfg.interfaces;
	cfg.interfaces = ifc;

	log_msg(LOG_DEBUG, "Opened interface %s (%s)",
		iface,
		pcap_datalink_val_to_description(pcap_datalink(ifc->pcap_handle)));

	return;

error_filter:
	pcap_freecode(&ifc->pcap_filter);
error_pcap:
	pcap_close(ifc->pcap_handle);
error:
	free(ifc);
}
Esempio n. 2
0
int zizzania_start(struct zizzania *z) {
    struct sigaction sa;
    sigset_t set;
    struct bpf_program fp;
    const uint8_t *packet;
    struct pcap_pkthdr *packet_header;
    int dlt;
    uint8_t retval;
    int error = 0;

    /* get pcap handle live */
    if (z->setup.live) {
        int snaplen;

        *z->error_buffer = '\0';
        snaplen = *(z->setup.output) ? MAX_SNAPLEN : MIN_SNAPLEN;
        z->handler = pcap_open_live(z->setup.input, snaplen,
                                    1, READ_TIMEOUT, z->error_buffer);

        /* warning */
        if (*z->error_buffer) {
            PRINT(z->error_buffer);
        }
    }
    /* from file */
    else {
        z->handler = pcap_open_offline(z->setup.input, z->error_buffer);
        z->setup.passive = 1;
    }

    if (!z->handler) {
        return 0;
    }

    /* drop root privileges */
    zizzania_drop_root();

    /* check datalink type */
    dlt = pcap_datalink(z->handler);
    PRINTF("datalink type %s", pcap_datalink_val_to_name(dlt));

    if (pcap_datalink(z->handler) != DLT_IEEE802_11_RADIO) {
        const char *expected_dlt;

        expected_dlt = pcap_datalink_val_to_name (DLT_IEEE802_11_RADIO);
        zizzania_set_error_messagef(z, "wrong device type/mode %s; %s expected",
                                    pcap_datalink_val_to_name(dlt),
                                    expected_dlt);
        return 0;
    }

    /* set capture filter */
    pcap_compile(z->handler, &fp, BPF, 1, -1);
    pcap_setfilter(z->handler, &fp);
    pcap_freecode(&fp);

    /* open dumper */
    if (*(z->setup.output)) {
        PRINTF("dumping packets to %s", z->setup.output);

        z->dumper = pcap_dump_open(z->handler, z->setup.output);
        if (!z->dumper) {
            zizzania_set_error_messagef(z, pcap_geterr(z->handler));
            return 0;
        }
    }

    /* ignore signals */
    memset(&sa, 0, sizeof(struct sigaction));
    sa.sa_handler = SIG_IGN;
    if (sigaction(SIGINT, &sa, NULL) || sigaction(SIGTERM, &sa, NULL)) {
        zizzania_set_error_messagef(z, "unable to set signal action");
        return 0;
    }

    /* mask all signals (so everything is sent to the dispatcher, blocked on the
       sigtimedwait) */
    sigfillset(&set);
    if (pthread_sigmask(SIG_SETMASK, &set, NULL)) {
        zizzania_set_error_messagef(z, "unable to set signal mask");
        return 0;
    }

    /* start dispatcher */
    if (pthread_create(&z->dispatcher, NULL, zizzania_dispatcher, z)) {
        zizzania_set_error_messagef(z, "unable to start dispatcher thread");
        return 0;
    }

    /* packet loop */
    while (!z->stop) {
        switch (pcap_next_ex(z->handler, &packet_header, &packet)) {
        case 0: /* timeout */
            break; /* recheck flag and eventually start over */

        case 1: /* no problem */
            error = !zizzania_process_packet(z, packet_header, packet);
            break;

        case -1: /* error */
            PRINT(pcap_geterr(z->handler));
            zizzania_set_error_messagef(z, pcap_geterr(z->handler));
            error = z->stop = 1;
            break;

        case -2: /* end of file */
            PRINT("eof");
            z->stop = 1;
            break;
        }
    }

    PRINT("shuting down the dispatcher");

    /* force dispatcher wakeup on errors on this thread */
    pthread_kill(z->dispatcher, SIGTERM);

    /* join dispatcher thread */
    if (pthread_join(z->dispatcher, (void *)&retval)) {
        PRINT("cannot join the dispatcher");
        return 0;
    }

    return !error && retval;
}