示例#1
0
int
pcap_activate(pcap_t *p)
{
	int status = 0;
	int fd;
	struct ifreq ifr;
	struct bpf_version bv;
	struct bpf_dltlist bdl;
	int new_dlt;
	u_int v;

	fd = bpf_open(p);
	if (fd < 0) {
		status = fd;
		goto bad;
	}

	p->fd = fd;

	if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
		    pcap_strerror(errno));
		status = PCAP_ERROR;
		goto bad;
	}
	if (bv.bv_major != BPF_MAJOR_VERSION ||
	    bv.bv_minor < BPF_MINOR_VERSION) {
		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
		    "kernel bpf filter out of date");
		status = PCAP_ERROR;
		goto bad;
	}

#if 0
	/* Just use the kernel default */
	v = 32768;	/* XXX this should be a user-accessible hook */
	/* Ignore the return value - this is because the call fails on
	 * BPF systems that don't have kernel malloc.  And if the call
	 * fails, it's no big deal, we just continue to use the standard
	 * buffer size.
	 */
	(void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
#endif

	/*
	 * Set the buffer size.
	 */
	if (p->opt.buffer_size != 0) {
		/*
		 * A buffer size was explicitly specified; use it.
		 */
		if (ioctl(fd, BIOCSBLEN,
		    (caddr_t)&p->opt.buffer_size) < 0) {
			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
			    "BIOCSBLEN: %s: %s", p->opt.source,
			    pcap_strerror(errno));
			status = PCAP_ERROR;
			goto bad;
		}
	}

	/*
	 * Now bind to the device.
	 */
	(void)strlcpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
	if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
		status = check_setif_failure(p, errno);
		goto bad;
	}
	/* Get the data link layer type. */
	if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
		    pcap_strerror(errno));
		status = PCAP_ERROR;
		goto bad;
	}
#if _BSDI_VERSION - 0 >= 199510
	/* The SLIP and PPP link layer header changed in BSD/OS 2.1 */
	switch (v) {

	case DLT_SLIP:
		v = DLT_SLIP_BSDOS;
		break;

	case DLT_PPP:
		v = DLT_PPP_BSDOS;
		break;

	case 11:	/*DLT_FR*/
		v = DLT_FRELAY;
		break;

	case 12:	/*DLT_C_HDLC*/
		v = DLT_CHDLC;
		break;
	}
#endif

	/*
	 * We know the default link type -- now determine all the DLTs
	 * this interface supports.  If this fails with EINVAL, it's
	 * not fatal; we just don't get to use the feature later.
	 */
	if (get_dlt_list(fd, v, &bdl, p->errbuf) == -1) {
		status = PCAP_ERROR;
		goto bad;
	}
	p->dlt_count = bdl.bfl_len;
	p->dlt_list = bdl.bfl_list;

	/*
	 * *BSD with the new 802.11 ioctls.
	 * Do we want monitor mode?
	 */
	if (p->opt.rfmon) {
		/*
		 * Try to put the interface into monitor mode.
		 */
		status = monitor_mode(p, 1);
		if (status != 0) {
			/*
			 * We failed.
			 */
			goto bad;
		}

		/*
		 * We're in monitor mode.
		 * Try to find the best 802.11 DLT_ value and, if we
		 * succeed, try to switch to that mode if we're not
		 * already in that mode.
		 */
		new_dlt = find_802_11(&bdl);
		if (new_dlt != -1) {
			/*
			 * We have at least one 802.11 DLT_ value.
			 * new_dlt is the best of the 802.11
			 * DLT_ values in the list.
			 *
			 * If the new mode we want isn't the default mode,
			 * attempt to select the new mode.
			 */
			if (new_dlt != v) {
				if (ioctl(p->fd, BIOCSDLT, &new_dlt) != -1) {
					/*
					 * We succeeded; make this the
					 * new DLT_ value.
					 */
					v = new_dlt;
				}
			}
		}
	}
	p->linktype = v;

	/* set timeout */
	if (p->md.timeout) {
		struct timeval to;
		to.tv_sec = p->md.timeout / 1000;
		to.tv_usec = (p->md.timeout * 1000) % 1000000;
		if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
			    "BIOCSRTIMEOUT: %s", pcap_strerror(errno));
			status = PCAP_ERROR;
			goto bad;
		}
	}

	if (p->opt.promisc) {
		/* set promiscuous mode, just warn if it fails */
		if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) {
			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s",
			    pcap_strerror(errno));
			status = PCAP_WARNING_PROMISC_NOTSUP;
		}
	}

	if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
		    pcap_strerror(errno));
		status = PCAP_ERROR;
		goto bad;
	}
	p->bufsize = v;
	p->buffer = (u_char *)malloc(p->bufsize);
	if (p->buffer == NULL) {
		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
		    pcap_strerror(errno));
		status = PCAP_ERROR;
		goto bad;
	}

	if (status < 0)
		goto bad;

	p->activated = 1;

	return (status);
 bad:
	pcap_cleanup_bpf(p);

	if (p->errbuf[0] == '\0') {
		/*
		 * No error message supplied by the activate routine;
		 * for the benefit of programs that don't specially
		 * handle errors other than PCAP_ERROR, return the
		 * error message corresponding to the status.
		 */
		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
		    pcap_statustostr(status));
	}

	return (status);
}
示例#2
0
#ifdef BIOCSETLIF
if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) < 0)
#else
			if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0)
#endif
			{
				status = check_setif_failure(p, errno);
				goto bad;
			}