예제 #1
0
static int
monitor_mode(pcap_t *p, int set)
{
	int sock;
	struct ifmediareq req;
	int *media_list;
	int i;
	int can_do;
	struct ifreq ifr;

	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock == -1) {
		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't open socket: %s",
		    pcap_strerror(errno));
		return (PCAP_ERROR);
	}

	memset(&req, 0, sizeof req);
	(void)strlcpy(req.ifm_name, p->opt.source, sizeof req.ifm_name);

	/*
	 * Find out how many media types we have.
	 */
	if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
		/*
		 * Can't get the media types.
		 */
		switch (errno) {

		case ENXIO:
			/*
			 * There's no such device.
			 */
			close(sock);
			return (PCAP_ERROR_NO_SUCH_DEVICE);

		case EINVAL:
			/*
			 * Interface doesn't support SIOC{G,S}IFMEDIA.
			 */
			close(sock);
			return (PCAP_ERROR_RFMON_NOTSUP);

		default:
			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
			    "SIOCGIFMEDIA 1: %s", pcap_strerror(errno));
			close(sock);
			return (PCAP_ERROR);
		}
	}
	if (req.ifm_count == 0) {
		/*
		 * No media types.
		 */
		close(sock);
		return (PCAP_ERROR_RFMON_NOTSUP);
	}

	/*
	 * Allocate a buffer to hold all the media types, and
	 * get the media types.
	 */
	media_list = (int *) calloc(req.ifm_count, sizeof(int));
	if (media_list == NULL) {
		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
		    pcap_strerror(errno));
		close(sock);
		return (PCAP_ERROR);
	}
	req.ifm_ulist = media_list;
	if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA: %s",
		    pcap_strerror(errno));
		free(media_list);
		close(sock);
		return (PCAP_ERROR);
	}

	/*
	 * Look for an 802.11 "automatic" media type.
	 * We assume that all 802.11 adapters have that media type,
	 * and that it will carry the monitor mode supported flag.
	 */
	can_do = 0;
	for (i = 0; i < req.ifm_count; i++) {
		if (IFM_TYPE(media_list[i]) == IFM_IEEE80211
		    && IFM_SUBTYPE(media_list[i]) == IFM_AUTO) {
			/* OK, does it do monitor mode? */
			if (media_list[i] & IFM_IEEE80211_MONITOR) {
				can_do = 1;
				break;
			}
		}
	}
	free(media_list);
	if (!can_do) {
		/*
		 * This adapter doesn't support monitor mode.
		 */
		close(sock);
		return (PCAP_ERROR_RFMON_NOTSUP);
	}

	if (set) {
		/*
		 * Don't just check whether we can enable monitor mode,
		 * do so, if it's not already enabled.
		 */
		if ((req.ifm_current & IFM_IEEE80211_MONITOR) == 0) {
			/*
			 * Monitor mode isn't currently on, so turn it on,
			 * and remember that we should turn it off when the
			 * pcap_t is closed.
			 */

			/*
			 * If we haven't already done so, arrange to have
			 * "pcap_close_all()" called when we exit.
			 */
			if (!pcap_do_addexit(p)) {
				/*
				 * "atexit()" failed; don't put the interface
				 * in monitor mode, just give up.
				 */
				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
				     "atexit failed");
				close(sock);
				return (PCAP_ERROR);
			}
			memset(&ifr, 0, sizeof(ifr));
			(void)strlcpy(ifr.ifr_name, p->opt.source,
			    sizeof(ifr.ifr_name));
			ifr.ifr_media = req.ifm_current | IFM_IEEE80211_MONITOR;
			if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) {
				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
				     "SIOCSIFMEDIA: %s", pcap_strerror(errno));
				close(sock);
				return (PCAP_ERROR);
			}

			p->md.must_do_on_close |= MUST_CLEAR_RFMON;

			/*
			 * Add this to the list of pcaps to close when we exit.
			 */
			pcap_add_to_pcaps_to_close(p);
		}
	}
	return (0);
}
예제 #2
0
static int
pfq_activate_linux(pcap_t *handle)
{
	char *device = NULL, *config = NULL;
        const int maxlen = 1514;
	const int queue = Q_ANY_QUEUE;
	char *first_dev;

	handle->opt.pfq  = pfq_opt_default(handle);
	handle->linktype = DLT_EN10MB;

	config = pfq_get_config_file(handle->opt.source);
	device = pfq_get_devname(handle->opt.source);

        fprintf(stdout, "[PFQ] running on device %s...\n", device);
	fprintf(stdout, "[PFQ] configuration file %s...\n", config);

	if (config == NULL) {
		char *conf = getenv("PFQ_CONFIG");
		if (conf)
			config = strdup(conf);
	}

        if (config != NULL) {
		if (pfq_parse_config(&handle->opt.pfq, config) == -1) {
			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pfq: config error");
			return PCAP_ERROR;
		}
		free(config);
	}

	if (pfq_parse_env(&handle->opt.pfq) == -1) {
		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pfq: env error!");
		return PCAP_ERROR;
	}

        if (handle->opt.pfq.caplen > maxlen || handle->opt.pfq.caplen == 0) {
                fprintf(stdout, "[PFQ] capture length forced to %d\n", maxlen);
                handle->opt.pfq.caplen = maxlen;
        }

	if (handle->opt.buffer_size/handle->opt.pfq.caplen > handle->opt.pfq.rx_slots)
		handle->opt.pfq.rx_slots = handle->opt.buffer_size/handle->opt.pfq.caplen;


	fprintf(stdout, "[PFQ] buffer_size = %d caplen = %d, rx_slots = %d, tx_slots = %d, tx_fhint = %d\n",
		handle->opt.buffer_size,
		handle->opt.pfq.caplen,
		handle->opt.pfq.rx_slots,
		handle->opt.pfq.tx_slots,
		handle->opt.pfq.tx_fhint);

	handle->read_op		= pfq_read_linux;
	handle->inject_op	= pfq_inject_linux;
	handle->setfilter_op	= pfq_setfilter_linux;
	handle->setdirection_op	= pfq_setdirection_linux;
	handle->getnonblock_op	= pcap_getnonblock_fd;
	handle->setnonblock_op	= pcap_setnonblock_fd;
	handle->stats_op	= pfq_stats_linux;
	handle->cleanup_op	= pfq_cleanup_linux;
	handle->set_datalink_op	= NULL;	/* can't change data link type */


	handle->md.pfq.q	= NULL;
	handle->md.pfq.current	= NULL;
	pfq_net_queue_init(&handle->md.pfq.nq);
	handle->md.pfq.ifs_promisc = 0;

	handle->fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (handle->fd == -1) {
		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
			 "socket: %s", pcap_strerror(errno));
		if (errno == EPERM || errno == EACCES) {
			/*
			 * You don't have permission to open the
			 * socket.
			 */
			return PCAP_ERROR_PERM_DENIED;
		} else {
			/*
			 * Other error.
			 */
			return PCAP_ERROR;
		}
	}

	/*
	 * The "any" device is a special device which causes us not
	 * to bind to a particular device and thus to look at all
	 * devices of a given group.
	 */

	/* handle promisc */

	if (handle->opt.promisc) {

		/* put all devic(es) in promisc mode */
                int n = 0;

		int set_promisc(const char *dev)
		{
			struct ifreq ifr;

			memset(&ifr, 0, sizeof(ifr));
			strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
			if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
						"SIOCGIFFLAGS: %s", pcap_strerror(errno));
				return PCAP_ERROR;
			}
			if ((ifr.ifr_flags & IFF_PROMISC) == 0) {

				/*
				 * Promiscuous mode isn't currently on,
				 * so turn it on, and remember that
				 * we should turn it off when the
				 * pcap_t is closed.
				 */

				/*
				 * If we haven't already done so, arrange
				 * to have "pcap_close_all()" called when
				 * we exit.
				 */
				if (!pcap_do_addexit(handle)) {
					/*
					 * "atexit()" failed; don't put
					 * the interface in promiscuous
					 * mode, just give up.
					 */
					return PCAP_ERROR;
				}

				fprintf(stdout, "[PFQ] set promisc on dev %s...\n", dev);

				ifr.ifr_flags |= IFF_PROMISC;
				if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
					snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
							"SIOCSIFFLAGS: %s",
							pcap_strerror(errno));
					return PCAP_ERROR;
				}

				handle->md.pfq.ifs_promisc |= (1 << n);
				handle->md.must_do_on_close |= MUST_CLEAR_PROMISC;
			}

			n++;
			return 0;
		}

		if (strcmp(device, "any") != 0) {
			if (string_for_each_token(device, ":", set_promisc) < 0) {
				goto fail;
			}
		}
	}