Пример #1
1
CaptureReader::CaptureReader(const Params& params) : BaseReader{params.interface}
{
    char errbuf[PCAP_ERRBUF_SIZE]; // storage of error description
    const char* device {source.c_str()};
    handle = pcap_create(device, errbuf);
    if(!handle)
    {
        throw PcapError("pcap_create", errbuf);
    }

    if(int status {pcap_set_snaplen(handle, params.snaplen)})
    {
        throw PcapError("pcap_set_snaplen", pcap_statustostr(status));
    }

    if(int status {pcap_set_promisc(handle, params.promisc ? 1 : 0)})
    {
        throw PcapError("pcap_set_promisc", pcap_statustostr(status));
    }

    if(int status {pcap_set_timeout(handle, params.timeout_ms)})
    {
        throw PcapError("pcap_set_timeout", pcap_statustostr(status));
    }

    if(int status {pcap_set_buffer_size(handle, params.buffer_size)})
    {
        throw PcapError("pcap_set_buffer_size", pcap_statustostr(status));
    }

    if(int status {pcap_activate(handle)})
    {
        throw PcapError("pcap_activate", pcap_statustostr(status));
    }

    pcap_direction_t direction {PCAP_D_INOUT};
    switch(params.direction)
    {
        using Direction = CaptureReader::Direction;
        case Direction::IN   : direction = PCAP_D_IN;    break;
        case Direction::OUT  : direction = PCAP_D_OUT;   break;
        case Direction::INOUT: direction = PCAP_D_INOUT; break;
    }
    if(int status {pcap_setdirection(handle, direction)})
    {
        throw PcapError("pcap_setdirection", pcap_statustostr(status));
    }

    bpf_u_int32 localnet, netmask;
    if(pcap_lookupnet(device, &localnet, &netmask, errbuf) < 0)
    {
        throw PcapError("pcap_lookupnet", errbuf);
    }

    BPF bpf(handle, params.filter.c_str(), netmask);

    if(pcap_setfilter(handle, bpf) < 0)
    {
        throw PcapError("pcap_setfiltration", pcap_geterr(handle));
    }
}
Пример #2
0
int Interface::setdirection(pcap_direction_t d) {
	return pcap_setdirection(handle, d);
}
Пример #3
0
/* The pcap capture routine.
*/
int
pcap_capture(fko_srv_options_t *opts)
{
    pcap_t              *pcap;
    char                errstr[PCAP_ERRBUF_SIZE] = {0};
    struct bpf_program  fp;
    int                 res;
    int                 pcap_errcnt = 0;
    int                 pending_break = 0;
    int                 promisc = 0;
    int                 set_direction = 1;
    int                 pcap_file_mode = 0;
    int                 status;
    int                 useconds;
    int                 pcap_dispatch_count;
    int                 max_sniff_bytes;
    int                 is_err;
    pid_t               child_pid;

#if FIREWALL_IPFW
    time_t              now;
#endif

    useconds = strtol_wrapper(opts->config[CONF_PCAP_LOOP_SLEEP],
            0, RCHK_MAX_PCAP_LOOP_SLEEP, NO_EXIT_UPON_ERR, &is_err);
    if(is_err != FKO_SUCCESS)
    {
        log_msg(LOG_ERR, "[*] invalid PCAP_LOOP_SLEEP_value");
        clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
    }

    max_sniff_bytes = strtol_wrapper(opts->config[CONF_MAX_SNIFF_BYTES],
            0, RCHK_MAX_SNIFF_BYTES, NO_EXIT_UPON_ERR, &is_err);
    if(is_err != FKO_SUCCESS)
    {
        log_msg(LOG_ERR, "[*] invalid MAX_SNIFF_BYTES");
        clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
    }

    /* Set promiscuous mode if ENABLE_PCAP_PROMISC is set to 'Y'.
    */
    if(strncasecmp(opts->config[CONF_ENABLE_PCAP_PROMISC], "Y", 1) == 0)
        promisc = 1;

    if(opts->config[CONF_PCAP_FILE] != NULL
            && opts->config[CONF_PCAP_FILE][0] != '\0')
        pcap_file_mode = 1;

    if(pcap_file_mode == 1) {
        log_msg(LOG_INFO, "Reading pcap file: %s",
            opts->config[CONF_PCAP_FILE]);

        pcap = pcap_open_offline(opts->config[CONF_PCAP_FILE], errstr);

        if(pcap == NULL)
        {
            log_msg(LOG_ERR, "[*] pcap_open_offline() error: %s",
                    errstr);
            clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
        }
    }
    else
    {
        log_msg(LOG_INFO, "Sniffing interface: %s",
            opts->config[CONF_PCAP_INTF]);

        pcap = pcap_open_live(opts->config[CONF_PCAP_INTF],
            max_sniff_bytes, promisc, 100, errstr
        );

        if(pcap == NULL)
        {
            log_msg(LOG_ERR, "[*] pcap_open_live() error: %s", errstr);
            clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
        }
    }

    /* Set pcap filters, if any.
    */
    if (opts->config[CONF_PCAP_FILTER][0] != '\0')
    {
        if(pcap_compile(pcap, &fp, opts->config[CONF_PCAP_FILTER], 1, 0) == -1)
        {
            log_msg(LOG_ERR, "[*] Error compiling pcap filter: %s",
                pcap_geterr(pcap)
            );
            clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
        }

        if(pcap_setfilter(pcap, &fp) == -1)
        {
            log_msg(LOG_ERR, "[*] Error setting pcap filter: %s",
                pcap_geterr(pcap)
            );
            clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
        }

        log_msg(LOG_INFO, "PCAP filter is: '%s'", opts->config[CONF_PCAP_FILTER]);

        pcap_freecode(&fp);
    }

    /* Determine and set the data link encapsulation offset.
    */
    switch(pcap_datalink(pcap)) {
        case DLT_EN10MB:
            opts->data_link_offset = 14;
            break;
#if defined(__linux__)
        case DLT_LINUX_SLL:
            opts->data_link_offset = 16;
            break;
#elif defined(__OpenBSD__)
        case DLT_LOOP:
            set_direction = 0;
            opts->data_link_offset = 4;
            break;
#endif
        case DLT_NULL:
            set_direction = 0;
            opts->data_link_offset = 4;
            break;
        default:
            opts->data_link_offset = 0;
            break;
    }

    /* We are only interested on seeing packets coming into the interface.
    */
    if ((opts->pcap_any_direction == 0)
            && (set_direction == 1) && (pcap_file_mode == 0)
            && (pcap_setdirection(pcap, PCAP_D_IN) < 0))
        if(opts->verbose)
            log_msg(LOG_WARNING, "[*] Warning: pcap error on setdirection: %s.",
                pcap_geterr(pcap));

    /* Set our pcap handle nonblocking mode.
     *
     * NOTE: This is simply set to 0 for now until we find a need
     *       to actually use this mode (which when set on a FreeBSD
     *       system, it silently breaks the packet capture).
    */
    if((pcap_file_mode == 0)
            && (pcap_setnonblock(pcap, DEF_PCAP_NONBLOCK, errstr)) == -1)
    {
        log_msg(LOG_ERR, "[*] Error setting pcap nonblocking to %i: %s",
            0, errstr
        );
        clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
    }

    pcap_dispatch_count = strtol_wrapper(opts->config[CONF_PCAP_DISPATCH_COUNT],
            0, RCHK_MAX_PCAP_DISPATCH_COUNT, NO_EXIT_UPON_ERR, &is_err);
    if(is_err != FKO_SUCCESS)
    {
        log_msg(LOG_ERR, "[*] invalid PCAP_DISPATCH_COUNT");
        clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
    }

    /* Initialize our signal handlers. You can check the return value for
     * the number of signals that were *not* set.  Those that were not set
     * will be listed in the log/stderr output.
    */
    if(set_sig_handlers() > 0)
        log_msg(LOG_ERR, "Errors encountered when setting signal handlers.");

    log_msg(LOG_INFO, "Starting fwknopd main event loop.");

    /* Jump into our home-grown packet cature loop.
    */
    while(1)
    {
        /* If we got a SIGCHLD and it was the tcp server, then handle it here.
        */
        if(got_sigchld)
        {
            if(opts->tcp_server_pid > 0)
            {
                child_pid = waitpid(0, &status, WNOHANG);

                if(child_pid == opts->tcp_server_pid)
                {
                    if(WIFSIGNALED(status))
                        log_msg(LOG_WARNING, "TCP server got signal: %i",  WTERMSIG(status));

                    log_msg(LOG_WARNING,
                        "TCP server exited with status of %i. Attempting restart.",
                        WEXITSTATUS(status)
                    );

                    opts->tcp_server_pid = 0;

                    /* Attempt to restart tcp server ? */
                    usleep(1000000);
                    run_tcp_server(opts);
                }
            }

            got_sigchld = 0;
        }

        /* Any signal except USR1, USR2, and SIGCHLD mean break the loop.
        */
        if(got_signal != 0)
        {
            if(got_sigint || got_sigterm || got_sighup)
            {
                pcap_breakloop(pcap);
                pending_break = 1;
            }
            else if(got_sigusr1 || got_sigusr2)
            {
                /* Not doing anything with these yet.
                */
                got_sigusr1 = got_sigusr2 = 0;
                got_signal = 0;
            }
            else
                got_signal = 0;
        }

        res = pcap_dispatch(pcap, pcap_dispatch_count,
            (pcap_handler)&process_packet, (unsigned char *)opts);

        /* Count processed packets
        */
        if(res > 0)
        {
            if(opts->foreground == 1 && opts->verbose > 2)
                log_msg(LOG_DEBUG, "pcap_dispatch() processed: %d packets", res);

            /* Count the set of processed packets (pcap_dispatch() return
             * value) - we use this as a comparison for --packet-limit regardless
             * of SPA packet validity at this point.
            */
            opts->packet_ctr += res;
            if (opts->packet_ctr_limit && opts->packet_ctr >= opts->packet_ctr_limit)
            {
                log_msg(LOG_WARNING,
                    "* Incoming packet count limit of %i reached",
                    opts->packet_ctr_limit
                );

                pcap_breakloop(pcap);
                pending_break = 1;
            }
        }
        /* If there was an error, complain and go on (to an extent before
         * giving up).
        */
        else if(res == -1)
        {
            log_msg(LOG_ERR, "[*] Error from pcap_dispatch: %s",
                pcap_geterr(pcap)
            );

            if(pcap_errcnt++ > MAX_PCAP_ERRORS_BEFORE_BAIL)
            {
                log_msg(LOG_ERR, "[*] %i consecutive pcap errors.  Giving up",
                    pcap_errcnt
                );
                clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
            }
        }
        else if(pending_break == 1 || res == -2)
        {
            /* pcap_breakloop was called, so we bail. */
            log_msg(LOG_INFO, "Gracefully leaving the fwknopd event loop.");
            break;
        }
        else
            pcap_errcnt = 0;

        /* Check for any expired firewall rules and deal with them.
        */
        check_firewall_rules(opts);

#if FIREWALL_IPFW
        /* Purge expired rules that no longer have any corresponding
         * dynamic rules.
        */
        if(opts->fw_config->total_rules > 0)
        {
            time(&now);
            if(opts->fw_config->last_purge < (now - opts->fw_config->purge_interval))
            {
                ipfw_purge_expired_rules(opts);
                opts->fw_config->last_purge = now;
            }
        }
#endif

        usleep(useconds);
    }

    pcap_close(pcap);

    return(0);
}
Пример #4
0
static void packet_socket_setup(struct packet_socket *psock)
{
	int bpf_fd = -1, val = -1;

	DEBUGP("calling pcap_create() with %s\n", psock->name);
	psock->pcap_in = pcap_create(psock->name, psock->pcap_error);
	if (psock->pcap_in == NULL)
		die_pcap_perror(psock->pcap_in, "pcap_create");
	psock->pcap_out = pcap_create(psock->name, psock->pcap_error);
	if (psock->pcap_out == NULL)
		die_pcap_perror(psock->pcap_out, "pcap_create");

	if (pcap_set_snaplen(psock->pcap_in, PACKET_READ_BYTES) != 0)
		die_pcap_perror(psock->pcap_in, "pcap_set_snaplen");
	if (pcap_set_snaplen(psock->pcap_out, PACKET_READ_BYTES) != 0)
		die_pcap_perror(psock->pcap_out, "pcap_set_snaplen");

	if (pcap_activate(psock->pcap_in) != 0)
		die_pcap_perror(psock->pcap_in,
				"pcap_activate "
				"(OpenBSD: another process (tcpdump?) "
				"using bpf0?)");
	if (pcap_activate(psock->pcap_out) != 0)
		die_pcap_perror(psock->pcap_out,
				"pcap_activate "
				"(OpenBSD: another process (tcpdump?) "
				"using bpf0?)");

	if (pcap_setdirection(psock->pcap_in, PCAP_D_IN) != 0)
		die_pcap_perror(psock->pcap_in, "pcap_setdirection");
	if (pcap_setdirection(psock->pcap_out, PCAP_D_OUT) != 0)
		die_pcap_perror(psock->pcap_out, "pcap_setdirection");

	bpf_fd = pcap_get_selectable_fd(psock->pcap_in);
	if (bpf_fd < 0)
		die_pcap_perror(psock->pcap_in, "pcap_get_selectable_fd");

	/* By default libpcap with BPF waits until a read buffer fills
	 * up before returning any packets. We use BIOCIMMEDIATE to
	 * force the BPF device to return the first packet
	 * immediately.
	 */
	val = 1;
	if (ioctl(bpf_fd, BIOCIMMEDIATE, &val) < 0)
		die_perror("ioctl BIOCIMMEDIATE on bpf fd");
	bpf_fd = pcap_get_selectable_fd(psock->pcap_out);
	if (bpf_fd < 0)
		die_pcap_perror(psock->pcap_out, "pcap_get_selectable_fd");

	/* By default libpcap with BPF waits until a read buffer fills
	 * up before returning any packets. We use BIOCIMMEDIATE to
	 * force the BPF device to return the first packet
	 * immediately.
	 */
	val = 1;
	if (ioctl(bpf_fd, BIOCIMMEDIATE, &val) < 0)
		die_perror("ioctl BIOCIMMEDIATE on bpf fd");

	/* Find data link type. */
	psock->data_link = pcap_datalink(psock->pcap_in);
	DEBUGP("data_link: %d\n", psock->data_link);

	/* Based on the data_link type, calculate the offset of the
	 * packet data in the buffer.
	 */
	switch (psock->data_link) {
	case DLT_EN10MB:
		psock->pcap_offset = sizeof(struct ether_header);
		break;
	case DLT_LOOP:
	case DLT_NULL:
		psock->pcap_offset = sizeof(u32);
		break;
	default:
		die("Unknown data_link type %d\n", psock->data_link);
		break;
	}
}
Пример #5
0
ochannel & ochannel::Open () 

{

#if defined (__linux__) 

	struct ifreq ifreq;
	struct sockaddr_ll sockaddr_ll = 
	{
		PF_PACKET,
		0x0000,
		0x0000,
		ARPHRD_ETHER,
		PACKET_OTHERHOST,
		ETHER_ADDR_LEN,
		{
			0x00,
			0x00,
			0x00,
			0x00,
			0x00,
			0x00,
			0x00,
			0x00
		}
	};
	std::memset (& ifreq, 0, sizeof (ifreq));
	std::memcpy (ifreq.ifr_name, ointerface::Name (), sizeof (ifreq.ifr_name));
	if ((this->mfd = socket (sockaddr_ll.sll_family, SOCK_RAW, oethernet::Protocol ())) == -1) 
	{
		oerror::error (1, errno, "%s", ointerface::Name ());
	}
	if (bind (this->mfd, (struct sockaddr *) (& sockaddr_ll), sizeof (sockaddr_ll)) == -1) 
	{
		oerror::error (1, errno, "Can't bind socket to %s", ifreq.ifr_name);
	}

#if 1

	if (ioctl (this->mfd, SIOCGIFFLAGS, & ifreq) == -1) 
	{
		oerror::error (1, errno, "%s", ifreq.ifr_name);
	}
	ifreq.ifr_flags |= (IFF_UP | IFF_BROADCAST | IFF_MULTICAST);
	ifreq.ifr_flags &= ~IFF_ALLMULTI;
	if (ioctl (this->mfd, SIOCSIFFLAGS, & ifreq) == -1) 
	{
		oerror::error (1, errno, "%s", ifreq.ifr_name);
	}

#endif

#elif defined (__APPLE__)

	struct ifreq ifreq;
	struct timeval timer = 
	{
		0,
		0
	};
	static struct bpf_insn bpf_insn [] = 
	{
		{
			BPF_LD+ BPF_H + BPF_ABS,
			0,
			0,
			12
		},
		{
			BPF_JMP+ BPF_JEQ + BPF_K,
			0,
			13,
			ntohs (oCHANNEL_ETHERTYPE)
		},
		{
			BPF_LD+ BPF_B+BPF_ABS,
			0,
			0,
			0
		},
		{
			BPF_JMP+ BPF_JEQ+BPF_K,
			0,
			11,
			0
		},
		{
			BPF_LD+ BPF_B+BPF_ABS,
			0,
			0,
			1
		},
		{
			BPF_JMP+ BPF_JEQ+BPF_K,
			0,
			9,
			0
		},
		{
			BPF_LD+ BPF_B+BPF_ABS,
			0,
			0,
			2
		},
		{
			BPF_JMP+ BPF_JEQ+BPF_K,
			0,
			7,
			0
		},
		{
			BPF_LD+ BPF_B+BPF_ABS,
			0,
			0,
			3
		},
		{
			BPF_JMP+ BPF_JEQ+BPF_K,
			0,
			5,
			0
		},
		{
			BPF_LD+ BPF_B+BPF_ABS,
			0,
			0,
			4
		},
		{
			BPF_JMP+ BPF_JEQ+BPF_K,
			0,
			3,
			0
		},
		{
			BPF_LD+ BPF_B+BPF_ABS,
			0,
			0,
			5
		},
		{
			BPF_JMP+ BPF_JEQ+BPF_K,
			0,
			1,
			0
		},
		{
			BPF_RET+ BPF_K,
			0,
			0,
			4096
		},
		{
			BPF_RET+ BPF_K,
			0,
			0,
			0
		}
	};
	struct bpf_program bpf_program;
	char filename [sizeof (oCHANNEL_BPFDEVICE)];
	const uint8_t * hostaddr = ointerface::HostAddress ();
	unsigned count;
	unsigned state;
	for (count = 0; count < 100; count++) 
	{
		std::snprintf (filename, sizeof (filename), oCHANNEL_BPFDEVICE, count);
		if ((this->mfd =::open (filename, O_RDWR)) != -1) 
		{
			break;
		}
	}
	if (this->mfd == -1) 
	{
		oerror::error (1, ECANCELED, "No bpf counts available");
	}
	std::memcpy (ifreq.ifr_name, this->mname, sizeof (ifreq.ifr_name));
	if (ioctl (this->mfd, BIOCSETIF, & ifreq) == -1) 
	{
		oerror::error (1, errno, "%s", ifreq.ifr_name);
	}
	if (ioctl (this->mfd, BIOCGBLEN, & this->bpf_length) == -1) 
	{
		oerror::error (1, errno, "Can't determine buffer length");
	}
	state = true;
	if (ioctl (this->mfd, BIOCIMMEDIATE, & state) == -1) 
	{
		oerror::error (1, errno, "Can't activate immediate mode");
	}
	state = false;
	if (ioctl (this->mfd, BIOCSSEESENT, & state) == -1) 
	{
		oerror::error (1, errno, "Can't hide outgoing frames");
	}
	timer.tv_usec = this->mtimer * 1000;
	if (ioctl (this->mfd, BIOCSRTIMEOUT, & timer) == -1) 
	{
		oerror::error (1, errno, "Can't set timeout");
	}
	bpf_insn [3].k = hostaddr [0];
	bpf_insn [5].k = hostaddr [1];
	bpf_insn [7].k = hostaddr [2];
	bpf_insn [9].k = hostaddr [3];
	bpf_insn [11].k = hostaddr [4];
	bpf_insn [13].k = hostaddr [5];
	bpf_program.bf_len = sizeof (bpf_program)/sizeof (struct bpf_insn);
	bpf_program.bf_insns = bpf_insn;
	if (ioctl (this->mfd, BIOCSETF, & bpf_program) == -1) 
	{
		oerror::error (1, errno, "Can't use filter program");
	}

#elif defined (__OpenBSD__)

	struct ifreq ifreq;
	std::memset (& ifreq, 0, sizeof (ifreq));
	if ((this->mfd = std::socket (sockaddr->sdl_family, SOCK_RAW, oethernet::Protocol ())) == -1) 
	{
		oerror::error (1, errno, "%s", ointerface::Name ());
	}
	std::memcpy (ifreq.ifr_name, interface, sizeof (ifreq.ifr_name));

#if 0

	if (ioctl (this->mfd, SIOCGIFINDEX, & ifreq) == -1) 
	{
		oerror::error (1, errno, "%s", ifreq.ifr_name);
	}
	sockaddr->sdl_ifindex = ifreq.ifr_ifindex;
	if (ioctl (this->mfd, OSIOCGIFADDR, & ifreq) == -1) 
	{
		oerror::error (1, errno, "%s", ifreq.ifr_name);
	}
	std::memcpy (sockaddr->sdl_data, ifreq.ifr_ifru.ifru_addr.sa_data, sizeof (sockaddr->sdl_data));
	if (std::bind (this->mfd, (struct sockaddr *) (sockaddr), sizeof (struct sockaddr_dl)) == -1) 
	{
		oerror::error (1, errno, "Can't bind socket to %s", interface);
	}

#endif

	if (ioctl (this->mfd, SIOCGIFFLAGS, & ifreq) == -1) 
	{
		oerror::error (1, errno, "Can't read state of %s", ifreq.ifr_name);
	}
	if (!(ifreq.ifr_flags & IFF_UP)) 
	{
		ifreq.ifr_flags |= IFF_UP;
		ifreq.ifr_flags |= IFF_BROADCAST;
		ifreq.ifr_flags |= IFF_MULTICAST;
		ifreq.ifr_flags &= ~IFF_ALLMULTI;
		if (ioctl (this->mfd, SIOCSIFFLAGS, & ifreq) == -1) 
		{
			oerror::error (1, errno, "Can't save state of %s", ifreq.ifr_name);
		}
	}

#elif defined (WINPCAP)

	struct bpf_program bpf_program;
	this->msocket = pcap_open_live (ointerface::Name (), 65536, 0, this->mtimer, this->merrbuf);
	if (!this->msocket) 
	{
		oerror::error (1, errno, "can't open adaptor: %s", ointerface::Name ());
	}
	_snprintf (this->mfilter, sizeof (this->mfilter), "ether proto 0x%04x and not ether src %s", oethernet::Protocol (), ointerface::HardwareAddressString ());
	if (pcap_compile (this->msocket, & bpf_program, this->mfilter, 1, 0xffffff) < 0) 
	{
		oerror::error (1, errno, "Can't compile pcap filter: %s", ointerface::Name);
	}
	if (pcap_setfilter (this->msocket, & bpf_program) < 0) 
	{
		oerror::error (1, errno, "Can't install pcap filter: %s", ointerface::Name ());
	}
	if (pcap_setmintocopy (this->msocket, ETHER_MAX_LEN)) 
	{
		oerror::error (1, errno, "Can't set minimum data: %s", ointerface::Name ());
	}

#if 0

	if (pcap_setdirection (this->msocket, PCAP_D_IN)) 
	{
		oerror::error (1, errno, "Can't set packet direction: %s", ointerface::Name ());
	}

#endif

#else
#error "Unknown Environment."
#endif

	return (* this);
}
Пример #6
0
void sniff(char *in_if, char *out_if, char *in_file, char *out_file, TableStateMachine *machine, int num_workers, int no_report, int batch) {
	pcap_t *hpcap[2];
	char errbuf[PCAP_ERRBUF_SIZE];
	char *device_in = NULL, *device_out = NULL;
	pcap_if_t *devices, *next_device;
	int res;
	struct bpf_program bpf;
	ProcessorData *processor;
    int linktype[2], linkHdrLen, i;
    char *mode;

	memset(errbuf, 0, PCAP_ERRBUF_SIZE);

	if (in_if || out_if) {
		// Find available interfaces
		if (pcap_findalldevs(&devices, errbuf)) {
			fprintf(stderr, "[Sniffer] ERROR: Cannot find network interface (pcap_findalldevs error: %s)\n", errbuf);
			exit(1);
		}

		// Find requested interface
		next_device = devices;
		while (next_device) {
			printf("[Sniffer] Found network interface: %s\n", next_device->name);
			if (in_if && (strcmp(in_if, next_device->name) == 0)) {
				device_in = in_if;
			}
			if (out_if && (strcmp(out_if, next_device->name) == 0)) {
				device_out = out_if;
			}
			next_device = next_device->next;
		}
		pcap_freealldevs(devices);
		if (in_if && (strcmp(in_if, STR_ANY) == 0)) {
			device_in = STR_ANY;
		}

		if (in_if && !device_in) {
			fprintf(stderr, "[Sniffer] ERROR: Cannot find input network interface\n");
			exit(1);
		}
		if (out_if && !device_out) {
			fprintf(stderr, "[Sniffer] ERROR: Cannot find output network interface\n");
			exit(1);
		}
	}

	if (in_if) {
		printf("[Sniffer] Sniffer is capturing from device: %s\n", device_in);
	} else {
		printf("[Sniffer] Sniffer is reading packets from file: %s\n", in_file);
	}
	if (out_if) {
		printf("[Sniffer] Packets are sent on device: %s\n", device_out);
	} else {
		printf("[Sniffer] Packets written to file: %s\n", out_file);
	}

	if (in_if) {
		hpcap[0] = pcap_create(device_in, errbuf);
	} else {
		hpcap[0] = pcap_open_offline(in_file, errbuf);
	}
	if (out_if) {
		hpcap[1] = pcap_create(device_out, errbuf);
	} else {
		//hpcap[1] = pcap_dump_fopen(out_file, errbuf);
	}

	for (i = 0; i < 2; i++) {
		mode = (i == 0) ? "input" : "output";
		// Check pcap handle
		if (!hpcap[i]) {
			fprintf(stderr, "[Sniffer] ERROR: Cannot create %s pcap handle (pcap_create/pcap_open_offline error: %s)\n", mode ,errbuf);
			exit(1);
		}

		if (in_if && i == 0) {
			// Set promiscuous mode
			pcap_set_promisc(hpcap[0], 1);
		}

		// Activate PCAP
		if ((in_if && i == 0) || (out_if && i == 1)) {
			res = pcap_activate(hpcap[i]);
			switch (res) {
			case 0:
				// Success
				break;
			case PCAP_WARNING_PROMISC_NOTSUP:
				fprintf(stderr, "[Sniffer] WARNING: Promiscuous mode is not supported\n");
				exit(1);
				break;
			case PCAP_WARNING:
				fprintf(stderr, "[Sniffer] WARNING: Unknown (%s)\n", pcap_geterr(hpcap[i]));
				exit(1);
				break;
			case PCAP_ERROR_NO_SUCH_DEVICE:
				fprintf(stderr, "[Sniffer] ERROR: Device not found\n");
				exit(1);
				break;
			case PCAP_ERROR_PERM_DENIED:
				fprintf(stderr, "[Sniffer] ERROR: Permission denied\n");
				exit(1);
				break;
			case PCAP_ERROR_PROMISC_PERM_DENIED:
				fprintf(stderr, "[Sniffer] ERROR: Permission denied for promiscuous mode\n");
				exit(1);
				break;
			case PCAP_ERROR_RFMON_NOTSUP:
				fprintf(stderr, "[Sniffer] ERROR: Monitor mode is not supported\n");
				exit(1);
				break;
			case PCAP_ERROR_IFACE_NOT_UP:
				fprintf(stderr, "[Sniffer] ERROR: Interface %s is not available\n", (i == 0) ? device_in : device_out);
				exit(1);
				break;
			default:
				fprintf(stderr, "[Sniffer] ERROR: Unknown (%s)\n", pcap_geterr(hpcap[i]));
				exit(1);
				break;
			}
		}

		if (i == 0) {
			if (in_if) {
				// Set capture direction (ingress only)
				res = pcap_setdirection(hpcap[0], PCAP_D_IN);
				if (res) {
					fprintf(stderr, "[Sniffer] ERROR: Cannot set capture direction (pcap_setdirection error: %s, return value: %d)\n", pcap_geterr(hpcap[0]), res);
					exit(1);
				}
			}
			// Compile PCAP filter (IP packets)
			res = pcap_compile(hpcap[0], &bpf, STR_FILTER, 0, PCAP_NETMASK_UNKNOWN);
			if (res) {
				fprintf(stderr, "[Sniffer] ERROR: Cannot compile packet filter (pcap_compile error: %s)\n", pcap_geterr(hpcap[0]));
				exit(1);
			}

			res = pcap_setfilter(hpcap[0], &bpf);
			if (res) {
				fprintf(stderr, "[Sniffer] ERROR: Cannot set packet filter (pcap_setfilter error: %s, return value: %d)\n", pcap_geterr(hpcap[0]), res);
				exit(1);
			}
			pcap_freecode(&bpf);
		}

		// Find data link type
		if ((linktype[i] = pcap_datalink(hpcap[i])) < 0)
		{
			fprintf(stderr, "[Sniffer] Cannot determine data link type (pcap_datalink error: %s)\n", pcap_geterr(hpcap[i]));
			exit(1);
		}
		if (i == 1 && linktype[0] != linktype[1]) {
			fprintf(stderr, "[Sniffer] Incompatible link types (input=%d, output=%d)\n", linktype[0], linktype[1]);
			exit(1);
		}
	}

	linkHdrLen = 0;
	switch (linktype[0])
	{
	case DLT_NULL:
		linkHdrLen = 4;
		break;

	case DLT_EN10MB:
		linkHdrLen = 14;
		break;

	case DLT_SLIP:
	case DLT_PPP:
		linkHdrLen = 24;
		break;

	default:
		fprintf(stderr, "[Sniffer] Unsupported data link type: %d\n", linktype[0]);
		exit(1);
	}

	// Prepare processor
	processor = init_processor(machine, hpcap[0], hpcap[1], linkHdrLen, num_workers, no_report, batch);
	_global_processor = processor;

	// Set signal handler
	signal(SIGINT, stop);
	signal(SIGTERM, stop);
	signal(SIGQUIT, stop);

	// Run sniffer
	gettimeofday(&(processor->start), NULL);
	printf("[Sniffer] Sniffer is running (input: %s, outout: %s)...\n", in_if, out_if);
	res = pcap_loop(hpcap[0], -1, process_packet, (unsigned char *)(processor));

	stop(res);
}
Пример #7
0
bool BaseSniffer::set_direction(pcap_direction_t d) {
	bool result = pcap_setdirection(handle, d) != -1;
	return result;
}
Пример #8
0
inline void set_capture_direction(pcap_t *source,
                                  const capture_direction &dir) {
  if (pcap_setdirection(source, static_cast<pcap_direction_t>(dir)) != 0) {
    throw error{"pcap_setdirection error\n" + error_string(source)};
  }
}
Пример #9
0
PcapPort::PortMonitor::PortMonitor(const char *device, Direction direction,
        AbstractPort::PortStats *stats)
{
    int ret;
    char errbuf[PCAP_ERRBUF_SIZE] = "";
    bool noLocalCapture;

    direction_ = direction;
    isDirectional_ = true;
    isPromisc_ = true;
    noLocalCapture = true;
    stats_ = stats;
    stop_ = false;

_retry:
#ifdef Q_OS_WIN32
    int flags = 0;

    if (isPromisc_)
        flags |= PCAP_OPENFLAG_PROMISCUOUS;
    if (noLocalCapture)
        flags |= PCAP_OPENFLAG_NOCAPTURE_LOCAL;

    handle_ = pcap_open(device, 64 /* FIXME */, flags,
                1000 /* ms */, NULL, errbuf);
#else
    handle_ = pcap_open_live(device, 64 /* FIXME */, int(isPromisc_),
                1000 /* ms */, errbuf);
#endif

    if (handle_ == NULL)
    {
        if (isPromisc_ && QString(errbuf).contains("promiscuous"))
        {
            qDebug("Can't set promiscuous mode, trying non-promisc %s", device);
            isPromisc_ = false;
            goto _retry;
        }
        else if (noLocalCapture && QString(errbuf).contains("loopback"))
        {
            qDebug("Can't set no local capture mode %s", device);
            noLocalCapture = false;
            goto _retry;
        }
        else
            goto _open_error;
    }
#ifdef Q_OS_WIN32
    // pcap_setdirection() API is not supported in Windows.
    // NOTE: WinPcap 4.1.1 and above exports a dummy API that returns -1
    // but since we would like to work with previous versions of WinPcap
    // also, we assume the API does not exist
    ret = -1;
#else
    switch (direction_)
    {
    case kDirectionRx:
        ret = pcap_setdirection(handle_, PCAP_D_IN);
        break;
    case kDirectionTx:
        ret = pcap_setdirection(handle_, PCAP_D_OUT);
        break;
    default:
        ret = -1; // avoid 'may be used uninitialized' warning
        Q_ASSERT(false);
    }
#endif

    if (ret < 0)
        goto _set_direction_error;

    return;

_set_direction_error:
    qDebug("Error setting direction(%d) %s: %s\n", direction, device, 
            pcap_geterr(handle_));
    isDirectional_ = false;
    return;

_open_error:
    qDebug("%s: Error opening port %s: %s\n", __FUNCTION__, device, errbuf);
} 
Пример #10
0
/**
 *  Set up pcap listener for the given interfaces and protocols.
 *  @return a properly configured pcap_t* object for listening for the given protocols - NULL on error
 *  @see pcap_protocols
 */
pcap_t*
create_pcap_listener(const char * dev		///<[in] Device name to listen on
,		     gboolean blocking		///<[in] TRUE if this is a blocking connection
,		     unsigned listenmask	///<[in] Bit mask of protocols to listen for
						///< (see @ref pcap_protocols "list of valid bits")
,		     struct bpf_program*prog)	///<[out] Compiled PCAP program
{
	pcap_t*			pcdescr = NULL;
	bpf_u_int32		maskp = 0;
	bpf_u_int32		netp = 0;
	char			errbuf[PCAP_ERRBUF_SIZE];
	char *			expr = NULL;
	int			filterlen = 1;
	unsigned		j;
	int			cnt=0;
	int			rc;
	const char ORWORD [] = " or ";
	gboolean		need_promisc = FALSE;

	BINDDEBUG(pcap_t);
//	setbuf(stdout, NULL);
	setvbuf(stdout, NULL, _IONBF, 0);
	errbuf[0] = '\0';

	// Search the list of valid bits so we can construct the libpcap filter
	// for the given set of protocols on the fly...
	// On this pass we just compute the amount of memory we'll need...
	for (j = 0, cnt = 0; j < DIMOF(filterinfo); ++j) {
		if (listenmask & filterinfo[j].filterbit) {
			++cnt;
			if (cnt > 1) {
				filterlen += sizeof(ORWORD);
			}
			filterlen += strlen(filterinfo[j].filter);
		}
	}
	
	if (filterlen < 2) {
		g_warning("Constructed filter is too short - invalid mask argument.");
		return NULL;
	}
	if (NULL == (expr = malloc(filterlen))) {
		g_error("Out of memory!");
		return NULL;
	}
	// Same song, different verse...
	// This time around, we construct the filter
	expr[0] = '\0';
	for (j = 0, cnt = 0; j < DIMOF(filterinfo); ++j) {
		if (listenmask & filterinfo[j].filterbit) {
			++cnt;
			if (cnt > 1) {
				g_strlcat(expr, ORWORD, filterlen);
			}
			g_strlcat(expr, filterinfo[j].filter, filterlen);
		}
	}
	if (pcap_lookupnet(dev, &netp, &maskp, errbuf) != 0) {
		// This is not a problem for non-IPv4 protocols...
		// It just looks up the ipv4 address - which we mostly don't care about.
		g_info("%s.%d: pcap_lookupnet(\"%s\") failed: [%s]"
		,	__FUNCTION__, __LINE__, dev, errbuf);
	}
	
	if (NULL == (pcdescr = pcap_create(dev, errbuf))) {
		g_warning("pcap_create failed: [%s]", errbuf);
		goto oopsie;
	}
	//pcap_set_promisc(pcdescr, FALSE);
	for (j = 0; j < DIMOF(filterinfo); ++j) {
		if (listenmask & filterinfo[j].filterbit) {
			const char * addrstring = filterinfo[j].mcastaddr;
			if (addrstring && !_enable_mcast_address(addrstring, dev, TRUE)) {
				need_promisc = TRUE;
			}
		}
	}
	pcap_set_promisc(pcdescr, need_promisc);
#ifdef HAVE_PCAP_SET_RFMON
	pcap_set_rfmon(pcdescr, FALSE);
#endif
	pcap_setdirection(pcdescr, PCAP_D_IN);
	// Weird bug - returns -3 and doesn't show an error message...
	// And pcap_getnonblock also returns -3... Neither should happen AFAIK...
	errbuf[0] = '\0';
	if ((rc = pcap_setnonblock(pcdescr, !blocking, errbuf)) < 0 && errbuf[0] != '\0') {
		g_warning("pcap_setnonblock(%d) failed: [%s] [rc=%d]", !blocking, errbuf, rc);
		g_warning("Have no idea why this happens - current blocking state is: %d."
		,	pcap_getnonblock(pcdescr, errbuf));
	}
	pcap_set_snaplen(pcdescr, 1500);
	/// @todo deal with pcap_set_timeout() call here.
	if (blocking) {
		pcap_set_timeout(pcdescr, 240*1000);
	}else{
		pcap_set_timeout(pcdescr, 1);
	}
	//pcap_set_buffer_size(pcdescr, 1500);
      
	if (pcap_activate(pcdescr) != 0) {
		g_warning("pcap_activate failed: [%s]", pcap_geterr(pcdescr));
		goto oopsie;
	}
	if (pcap_compile(pcdescr, prog, expr, FALSE, maskp) < 0) {
		g_warning("pcap_compile of [%s] failed: [%s]", expr, pcap_geterr(pcdescr));
		goto oopsie;
	}
	if (pcap_setfilter(pcdescr, prog) < 0) {
		g_warning("pcap_setfilter on [%s] failed: [%s]", expr, pcap_geterr(pcdescr));
		goto oopsie;
	}
	DEBUGMSG1("Compile of [%s] worked!", expr);
	g_info("Compile of [%s] worked! Returning %p", expr, pcdescr);
	free(expr); expr = NULL;
	return(pcdescr);

oopsie:	// Some kind of failure - free things up and return NULL

	g_warning("%s.%d: Could not set up PCAP on %s"
	,	__FUNCTION__, __LINE__, dev);
	if (expr) {
		free(expr);
		expr = NULL;
	}
	if (pcdescr) {
		close_pcap_listener(pcdescr, dev, listenmask);
		pcdescr = NULL;
	}
	return NULL;
}
Пример #11
0
void *sniffer_thread(void *params) {
    
    struct sniffer_thread_parameter *p = (struct sniffer_thread_parameter *) params;
    struct interface *sniff_interface = p->sniff_interface; //i/p interface
    struct route **routes = p->routes; //o/p interface
    
    char errbuf[PCAP_ERRBUF_SIZE];		/* error buffer */
    pcap_t *handle;                     /* packet capture handle */
    
   //char filter_exp[64];                /* filter expression [3] */
   //strcpy(filter_exp,"ip");
   // sprintf(filter_exp, "ip and ether dst %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", PRINT_MAC(sniff_interface->interface_macaddress));
    
  // struct bpf_program fp;             /* compiled filter program (expression) */
    
    struct got_packet_parameter got_packet_param;
    struct sockaddr_ll sa_in, sa_out[3];
    
    int i;

    /* open capture device */
    handle = pcap_open_live(sniff_interface->interface_name, SNAP_LEN, 1, 1000, errbuf);
    if (handle == NULL) {
        fprintf(stderr, "Couldn't open device %s: %s\n", sniff_interface->interface_name, errbuf);
        exit(EXIT_FAILURE);
    }

    /* make sure we're capturing on an Ethernet device [2] */
    if (pcap_datalink(handle) != DLT_EN10MB) {
        fprintf(stderr, "%s is not an Ethernet\n", sniff_interface->interface_name);
        exit(EXIT_FAILURE);
    }

    if (pcap_setdirection(handle,PCAP_D_IN)!=0) {
        fprintf(stderr, "error in setting direction for %s\n", sniff_interface->interface_name);
        exit(EXIT_FAILURE);
    }

    /* compile the filter expression */
  /*if (pcap_compile(handle, &fp, filter_exp, 0, sniff_interface->interface_netaddress) == -1) {
        fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
        exit(EXIT_FAILURE);
    }*/
    
    /* apply the compiled filter */
   /*if (pcap_setfilter(handle, &fp) == -1) {
        fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
        exit(EXIT_FAILURE);
    }*/
    
    // Open socket for sniffing interface
    sa_in.sll_family = PF_PACKET;
    sa_in.sll_ifindex = sniff_interface->interface_index;
    sa_in.sll_halen = ETHER_ADDR_LEN;
    sa_in.sll_protocol = htons(ETH_P_ALL);
    sa_in.sll_hatype = 0;
    sa_in.sll_pkttype = 0;
    memcpy(sa_in.sll_addr, sniff_interface->interface_macaddress, ETHER_ADDR_LEN);
    sniff_interface->sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    //printf(" sniff socket %d \n",sniff_interface->sockfd);
    if (sniff_interface->sockfd == -1) {
        fprintf(stderr, "Cannot create raw socket for sniffing interface in sniffer_thread\n");
        fprintf(stderr, "%s\n", strerror(errno));
	exit(-1);
    }
    else{
    	if (bind(sniff_interface->sockfd, (struct sockaddr *)&sa_in, sizeof(sa_in)) != 0){  //WARNING
        	fprintf(stderr, "Cannot bind to raw socket for sniffing interface in sniffer_thread\n");
	 	fprintf(stderr, "%s\n", strerror(errno));
    	}

    
    // Open socket for all output interface
    for (i=0; i<p->num_ifs; i++) {
        
        sa_out[i].sll_family = PF_PACKET;
        sa_out[i].sll_ifindex = (*routes)[i].interface.interface_index;
        //sa_out[i].sll_ifindex = 4;
        //printf(" opened socket ifindex %d \n",sa_out[i].sll_ifindex);
	sa_out[i].sll_halen = ETHER_ADDR_LEN;
        sa_out[i].sll_protocol = htons(ETH_P_ALL);
        sa_out[i].sll_hatype = 0;
        sa_out[i].sll_pkttype = 0;
        memcpy(sa_out[i].sll_addr, (*routes)[i].interface.interface_macaddress, ETHER_ADDR_LEN);
       	//printf("opened socket ifname %s \n",(*routes)[i].interface.interface_name); 
        (*routes)[i].interface.sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
        if ((*routes)[i].interface.sockfd == -1) {
            fprintf(stderr, "Cannot create raw socket for output interface in sniffer_thread\n");
            fprintf(stderr, "%s\n", strerror(errno));
            exit(-1);
	}
    	else{
       		//printf("opened socket  %d \n",(*routes)[i].interface.sockfd); 
        	if (bind((*routes)[i].interface.sockfd, (struct sockaddr *)&sa_out[i], sizeof(sa_out[i])) != 0){  //WARNING
       		     	fprintf(stderr, "Cannot bind to raw socket for output interface in sniffer_thread\n");
        	}
        }
    }
    }
    // Parse information to got_packet handler
    got_packet_param.sniff_interface = sniff_interface;
    //got_packet_param.num_routes = num_routes;
    got_packet_param.routes = routes;
    got_packet_param.num_ifs = p->num_ifs;
    //got_packet_param.arp_table_root = arp_table_root;


    pcap_loop(handle, -1, got_packet, (u_char *) &got_packet_param);

    
    /* cleanup */
   //pcap_freecode(&fp);
    pcap_close(handle);

    fprintf(stderr, "\nCapture complete.\n");
    
    return 0;
    
}
Пример #12
0
void recv_packet(void) {
	char errbuf[PCAP_ERRBUF_SIZE], *pfilter=NULL;
	struct bpf_program filter;
	bpf_u_int32 net, mask;
	int ac_s=0, ret=0, worktodo=1;
	uint8_t msg_type=0, status=0, *ptr=NULL;
	size_t msg_len=0;
	xpoll_t spdf[2];
	union {
		recv_workunit_t *r;
		uint8_t *cr;
		uint32_t *magic;
	} wk_u;
	union {
		listener_info_t *l;
		uint8_t *ptr;
	} l_u;
	union {
		drone_version_t *v;
		uint8_t *ptr;
	} d_u;
	drone_version_t dv;
	struct pcap_stat pcs;

	r_queue=fifo_init();

	close_output_modules();
	close_report_modules();
	close_payload_modules();

	DBG(M_IPC, "creating server socket");

	memset(s->ss, 0, sizeof(scan_settings_t));

	memset(&dv, 0, sizeof(dv));
	d_u.v=&dv;
	dv.magic=DRONE_MAGIC;
	dv.maj=DRONE_MAJ;
	dv.min=DRONE_MIN;
	recv_stats_t recv_stats;

	/* heh */
	if ((ac_s=socktrans_bind(s->ipcuri)) < 0) {
		terminate("cant create listener socket");
	}

	DBG(M_IPC, "waiting for main to connect");

	parent_sync();

	lc_s=socktrans_accept(ac_s, DEF_SOCK_TIMEOUT);
	if (lc_s < 0) {
		terminate("main didnt connect, exiting");
	}

	DBG(M_IPC, "got connection");

	if (get_singlemessage(lc_s, &msg_type, &status, &ptr, &msg_len) != 1) {
		terminate("unexpected sequence of messages from parent waiting for ident request, exiting");
	}

	if (msg_type != MSG_IDENT || status != MSG_STATUS_OK) {
		ERR("got an unknown message type `%s' or bad status %d from parent, exiting", strmsgtype(msg_type), status);
	}

	if (send_message(lc_s, MSG_IDENTLISTENER, MSG_STATUS_OK, d_u.ptr, sizeof(drone_version_t)) < 0) {
		terminate("cant send back msgident to parent");
	}

	if (get_singlemessage(lc_s, &msg_type, &status, &ptr, &msg_len) != 1) {
		terminate("cant read ident ack message from parent, exiting");
	}
	if (msg_type != MSG_ACK || status != MSG_STATUS_OK) {
		ERR("got an unknown message type `%s' or bad status %d from parent, exiting", strmsgtype(msg_type), status);
	}

	DBG(M_IPC, "sending ready message to parent");

	l_u.l=(listener_info_t *)xmalloc(sizeof(listener_info_t));

	memcpy(&l_u.l->myaddr, &s->vi[0]->myaddr, sizeof(struct sockaddr_storage));
	memcpy(&l_u.l->mymask, &s->vi[0]->mymask, sizeof(struct sockaddr_storage));
	memcpy(l_u.l->hwaddr, s->vi[0]->hwaddr, THE_ONLY_SUPPORTED_HWADDR_LEN);
	l_u.l->mtu=s->vi[0]->mtu;

	assert(s->interface_str != NULL);

	if (pcap_lookupnet(s->interface_str, &net, &mask, errbuf) < 0) {
		ERR("pcap_lookupnet fails, ignoring: %s", errbuf);
	}

	if (s->pcap_readfile == NULL) {
		pdev=pcap_open_live(s->interface_str, /* XXX haha */ s->vi[0]->mtu + 64, (GET_PROMISC() ? 1 : 0), 0, errbuf);
		if (pdev == NULL) {
			ERR("pcap open live: %s", errbuf);

			DBG(M_IPC, "sending ready error message to parent");
			if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
				terminate("cant send message ready error");
			}
			terminate("informed parent, exiting");
		}
	}
	else {
		pdev=pcap_open_offline(s->pcap_readfile, errbuf);
		if (pdev == NULL) {
			ERR("pcap open offline: %s", errbuf);

			DBG(M_IPC, "sending ready error message to parent");
			if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
				terminate("cant send message ready error");
			}
			terminate("informed parent, exiting");
		}
	}

	ret=util_getheadersize(pdev, errbuf);
	if (ret < 0 || ret > 0xffff) {
		ERR("error getting link header size: %s", errbuf);

		DBG(M_IPC, "sending ready error message to parent");
		if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
			terminate("cant send message ready error");
		}
		terminate("informed parent, exiting");
	}
	s->ss->header_len=(uint16_t)ret;

	if (s->pcap_dumpfile != NULL) {
		VRB(0, "opening `%s' for pcap log", s->pcap_dumpfile);
		pdump=pcap_dump_open(pdev, s->pcap_dumpfile);
		if (pdump == NULL) {
			ERR("cant log to pcap file `%s'", pcap_geterr(pdev));

			DBG(M_IPC, "sending ready error message to parent");
			if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
				terminate("cant send message ready error");
			}
			terminate("informed parent, exiting");
		}
	}
	else {
		DBG(M_CLD, "not logging to pcap file");
	}

	if (util_preparepcap(pdev, errbuf) < 0) {
		ERR("cant setup pcap filedesc to immediate mode: %s", errbuf);

		DBG(M_IPC, "sending ready error message to parent");
		if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
			terminate("cant send message ready error");
		}
		terminate("informed parent, exiting");
	}

	/* pcap_fd will be -1 for a pcap file */
	pcap_fd=pcap_get_selectable_fd(pdev);

	if (pcap_fd < 0 && s->pcap_readfile == NULL) {
		ERR("cant get selectable fd from pcap device, exiting");

		DBG(M_IPC, "sending ready error message to parent");
		if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
			terminate("sant send message ready error");
		}
		terminate("informed parent, exiting");
	}

#ifdef PCAP_D_IN
	if (pcap_setdirection(pdev, PCAP_D_IN) < 0) {
		ERR("cant set pcap direction to in, exiting");

		DBG(M_IPC, "sending ready error message to parent");
		if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
			terminate("sant send message ready error");
		}
		terminate("informed parent, exiting");
	}
#endif

	DBG(M_CLD, "listener dropping privs");

	if (drop_privs() < 0) {
		terminate("cant drop privs");
	}

	if (send_message(lc_s, MSG_READY, MSG_STATUS_OK, l_u.ptr, sizeof(listener_info_t)) < 0) {
		terminate("cant send message ready");
	}

	xfree(l_u.l);

	/* XXX */
	s->ss->syn_key=0;

	do {
		if (get_singlemessage(lc_s, &msg_type, &status, &wk_u.cr, &msg_len) != 1) {
			terminate("unexpected sequence of messages from parent looking for a workunit");
		}

		if (status != MSG_STATUS_OK) {
			terminate("bad message status %u", status);
		}

		if (msg_type == MSG_QUIT) {
			worktodo=0;
			break;
		}
		else if (msg_type == MSG_WORKUNIT) {
			;
		}
		else {
			terminate("unexpected message, expecting workunit or quit message");
		}

		if (msg_len < sizeof(uint32_t)) {
			terminate("bad message, too short [" STFMT "]", msg_len);
		}

		if (msg_len < sizeof(recv_workunit_t)) {
			terminate("short workunit");
		}

		worktodo=1;

		DBG(M_WRK, "workunit `%s'", strworkunit(wk_u.cr, msg_len));

		s->ss->recv_timeout=wk_u.r->recv_timeout;
		s->ss->ret_layers=wk_u.r->ret_layers;
		s->recv_opts=wk_u.r->recv_opts;
		s->ss->window_size=wk_u.r->window_size;

		s->ss->syn_key=wk_u.r->syn_key;

		if (wk_u.r->pcap_len) {
			if ((msg_len - sizeof(recv_workunit_t)) == wk_u.r->pcap_len) {
				extract_pcapfilter(wk_u.cr + sizeof(recv_workunit_t), wk_u.r->pcap_len);
			}
			else {
				terminate("pcap option length illegal");
			}
		}

		switch (*wk_u.magic) {
			case UDP_RECV_MAGIC:
				s->ss->mode=MODE_UDPSCAN;
				break;

			case TCP_RECV_MAGIC:
				s->ss->mode=MODE_TCPSCAN;
				break;

			case ARP_RECV_MAGIC:
				s->ss->mode=MODE_ARPSCAN;
				break;

			default:
				terminate("unknown recv workunit type");
				break;
		}

		DBG(M_IPC, "from ipc, got workunit: %s", strworkunit((const void *)wk_u.cr, msg_len));

		if (s->ss->mode == MODE_ARPSCAN) {
			if (s->ss->header_len != 14) {

				DBG(M_IPC, "sending msg error");
				if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
					terminate("cant send message ready");
				}
				terminate("wrong linktype for arp scan");
			}
		}

		if (s->ss->ret_layers > 0) {
			DBG(M_CLD, "setting up packet queue");
			p_queue=fifo_init();
		}

		pfilter=get_pcapfilterstr();

		VRB(1, "using pcap filter: `%s'", pfilter);

		memset(&filter, 0, sizeof(filter));
		if (pcap_compile(pdev, &filter, pfilter, 0, net) < 0) {
			ERR("error compiling filter: %s",  pcap_geterr(pdev));

			if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
				ERR("cant send message ready error");
			}
			terminate("cant compile pcap filter");
		}

		if (pcap_setfilter(pdev, &filter) < 0) {
			ERR("error setting compiled filter: %s", pcap_geterr(pdev));

			if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
				ERR("cant send message ready error");
			}
			terminate("cant set compiled pcap filter");
		}

		pcap_freecode(&filter);

		if (s->ss->ret_layers > 0) {
			DBG(M_IPC, "returning whole packet via ipc");
		}

		DBG(M_IPC, "sending ready message to parent");

		if (pcap_setnonblock(pdev, 1, errbuf) < 0) {
			terminate("cant set pcap non-blocking mode");
		}

		if (send_message(lc_s, MSG_READY, MSG_STATUS_OK, NULL, 0) < 0) {
			terminate("cant send message ready");
		}

		while (1) {
			spdf[0].fd=lc_s;
			spdf[1].fd=pcap_fd;

			/* if pdev is a socket  ( ! -1 ) */
			if (xpoll(&spdf[0], 2, -1) < 0) {
				ERR("xpoll fails: %s", strerror(errno));
			}

			if (spdf[1].rw & XPOLL_READABLE) {
				pcap_dispatch(pdev, 1, parse_packet, NULL);
			}

			/* no packets, better drain the queue */
			drain_pqueue();

			if (spdf[0].rw & XPOLL_READABLE) {
				if (get_singlemessage(lc_s, &msg_type, &status, &ptr, &msg_len) != 1) {
					ERR("unexpected sequence of messages from parent in main read loop, exiting");
					worktodo=0;
					break;
				}

				if (msg_type == MSG_TERMINATE) {
					DBG(M_IPC, "parent wants me to stop listening, breaking");
					break;
				}
				else if (msg_type == MSG_QUIT) {
					DBG(M_IPC, "Parent wants me to quit, breaking");
					worktodo=0;
					break;
				}
				else {
					ERR("got strange message `%s' from parent, exiting", strmsgtype(msg_type));
					worktodo=0;
					break;
				}
			}
		}

		memset(&recv_stats, 0, sizeof(recv_stats));

		if (pcap_stats(pdev, &pcs) != -1) {

			recv_stats.packets_recv=pcs.ps_recv;
			recv_stats.packets_dropped=pcs.ps_drop;
			recv_stats.packets_dropped=pcs.ps_ifdrop;
		}

		if (send_message(lc_s, MSG_WORKDONE, MSG_STATUS_OK, (void *)&recv_stats, sizeof(recv_stats)) < 0) {
			terminate("cant send workdone message to parent, exiting");
		}

	} while (worktodo);

	pcap_close(pdev);
	if (s->pcap_dumpfile) {
		pcap_dump_close(pdump);
	}


	DBG(M_CLD, "listener exiting");

	shutdown(lc_s, SHUT_RDWR);
	close(lc_s);
 
	uexit(0);
}
Пример #13
0
int main(int argc, char *argv[])
{
	signal (SIGINT, signal_handler);
	//printf("\033[?1049h\033[H");

	clear_log();
	my_log("Software switch starting...");
	my_log(pcap_lib_version());

	int option = 0, ret;
	char c;
	pthread_t config_thread;
	char errbuf[PCAP_ERRBUF_SIZE];
	p1 = create_port_struct(1);
	p2 = create_port_struct(2);

	while ((option = getopt(argc, argv,"h l 1:2: m")) != -1) {
		switch (option) {
			case '1' :
				strcpy(p1->name, optarg);
				break;
			case '2' :
				strcpy(p2->name, optarg);
				break;
			case 'l':
				list_interfaces();
				exit(0);
			case 'm':
				mock_rule();
				break;
			case 'h':
			default: print_usage();
				exit(EXIT_FAILURE);
		}
	}

	p1->handle = pcap_create(p1->name, errbuf);
	if ( (ret = pcap_setdirection(p1->handle, PCAP_D_IN)) != 0){
		printf("pcap_setdirection returned %i\n", ret);
		my_log("pcap_setdirection failed");
		pcap_perror(p1->handle, 0);
		//exit(-1);
	}
	if ( pcap_set_promisc(p1->handle, 1) != 0){
		printf("pcap_set_promisc returned \n%s\n", pcap_geterr(p1->handle));

		my_log("pcap_set_promisc failed");
		pcap_perror(p1->handle, 0);
		exit(-1);
	}
	if ( pcap_set_immediate_mode(p1->handle, 1) != 0){
		printf("pcap_set_immediate_mode returned \n%s\n", pcap_geterr(p1->handle));
		my_log("pcap_set_immediate_mode failed");
		pcap_perror(p1->handle, 0);
		exit(-1);
	}
	if ( pcap_activate(p1->handle)){
		printf("Failed to open interface %s\n", pcap_geterr(p1->handle));
		exit(-1);
	} else {
		sprintf(log_b, "Handle activated for %s", p1->name);
		my_log(log_b);
	}




	p2->handle = pcap_create(p2->name, errbuf);
	if ( pcap_setdirection(p2->handle, PCAP_D_OUT) != 0){
		my_log("pcap_setdirection failed");
		pcap_perror(p2->handle, 0);
		//exit(-1);
	}
	if ( pcap_set_promisc(p2->handle, 1) != 0){
		my_log("pcap_set_promisc failed");
		pcap_perror(p2->handle, 0);
		exit(-1);
	}
	if ( pcap_set_immediate_mode(p2->handle, 1) != 0){
		my_log("pcap_set_immediate_mode failed");
		pcap_perror(p2->handle, 0);
		exit(-1);
	}
	if ( pcap_activate(p2->handle)){
		printf("Failed to open interface %s\n", pcap_geterr(p2->handle));
		exit(-1);
	} else {
		sprintf(log_b, "Handle activated for %s", p2->name);
		my_log(log_b);
	}

	//exit(0);

	my_log("Deleting mac table..");
	clear_mac();
	sprintf(log_b, "Default action is %s", (DEFAULT_ACTION == R_ALLOW)? "R_ALLOW" : "R_DENY");
	my_log(log_b);

	my_log("Creating threads...");
	pthread_mutex_init(&mutex, NULL);
	if ( pthread_create(&(p1->thread), 0, port_listener, (void *)p1) ){
		my_log("Error creating p1 thread");
		exit(-1);
	}
	if ( pthread_create(&(p2->thread), 0, port_listener, (void *)p2) ){
		my_log("Error creating p2 thread");
		exit(-1);
	}

	pthread_create(&config_thread, 0, config, 0);

	while (1) {
		mac_delete_old_entries(5);
		if(pause_rendering == 1)
			continue;

		// render here
		system("clear");
		print_mac();
		print_rules();
		print_stats_header();
		print_stats(p1->in, "1 IN");
		print_stats(p1->out, "1 OUT");
		print_stats(p2->in, "2 IN");
		print_stats(p2->out, "2 OUT");
		printf("p1in: %i\tp1out: %i\tp2in: %i\tp2out: %i\n", p1in, p1out, p2in, p2out);
		sleep(1);

	}

	pthread_join(config_thread, 0);
	pthread_join(p1->thread, 0);
	pthread_join(p2->thread, 0);

	//printf("\033[?1049l"); // go back

	return 0;
}
//------------------------------------------------------------------------------
tOplkError edrv_init(const tEdrvInitParam* pEdrvInitParam_p)
{
    struct sched_param  schedParam;

    // Check parameter validity
    ASSERT(pEdrvInitParam_p != NULL);

    // clear instance structure
    OPLK_MEMSET(&edrvInstance_l, 0, sizeof(edrvInstance_l));

    if (pEdrvInitParam_p->pDevName == NULL)
        return kErrorEdrvInit;

    // save the init data
    edrvInstance_l.initParam = *pEdrvInitParam_p;

    /* if no MAC address was specified read MAC address of used
     * Ethernet interface
     */
    if ((edrvInstance_l.initParam.aMacAddr[0] == 0) &&
        (edrvInstance_l.initParam.aMacAddr[1] == 0) &&
        (edrvInstance_l.initParam.aMacAddr[2] == 0) &&
        (edrvInstance_l.initParam.aMacAddr[3] == 0) &&
        (edrvInstance_l.initParam.aMacAddr[4] == 0) &&
        (edrvInstance_l.initParam.aMacAddr[5] == 0))
    {   // read MAC address from controller
        getMacAdrs(edrvInstance_l.initParam.pDevName,
                   edrvInstance_l.initParam.aMacAddr);
    }

    // Set up and activate the pcap live capture handle
    edrvInstance_l.pPcap = startPcap();
    if (edrvInstance_l.pPcap == NULL)
    {
        return kErrorEdrvInit;
    }

    if (pcap_setdirection(edrvInstance_l.pPcap, PCAP_D_OUT) < 0)
    {
        DEBUG_LVL_ERROR_TRACE("%s() couldn't set PCAP direction\n", __func__);
        return kErrorEdrvInit;
    }

    if (pthread_mutex_init(&edrvInstance_l.mutex, NULL) != 0)
    {
        DEBUG_LVL_ERROR_TRACE("%s() couldn't init mutex\n", __func__);
        return kErrorEdrvInit;
    }

    if (sem_init(&edrvInstance_l.syncSem, 0, 0) != 0)
    {
        DEBUG_LVL_ERROR_TRACE("%s() couldn't init semaphore\n", __func__);
        return kErrorEdrvInit;
    }

    if (pthread_create(&edrvInstance_l.hThread, NULL,
                       workerThread,  &edrvInstance_l) != 0)
    {
        DEBUG_LVL_ERROR_TRACE("%s() Couldn't create worker thread!\n", __func__);
        return kErrorEdrvInit;
    }

    schedParam.sched_priority = CONFIG_THREAD_PRIORITY_MEDIUM;
    if (pthread_setschedparam(edrvInstance_l.hThread, SCHED_FIFO, &schedParam) != 0)
    {
        DEBUG_LVL_ERROR_TRACE("%s() couldn't set thread scheduling parameters!\n", __func__);
    }

#if (defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 12))
    pthread_setname_np(edrvInstance_l.hThread, "oplk-edrvpcap");
#endif

    /* wait until thread is started */
    sem_wait(&edrvInstance_l.syncSem);

    return kErrorOk;
}