diff options
Diffstat (limited to 'pcap-usb-linux.c')
| -rw-r--r-- | pcap-usb-linux.c | 194 | 
1 files changed, 119 insertions, 75 deletions
| diff --git a/pcap-usb-linux.c b/pcap-usb-linux.c index bdabf005ccae..fb1188a7d33c 100644 --- a/pcap-usb-linux.c +++ b/pcap-usb-linux.c @@ -11,8 +11,8 @@   * 2. Redistributions in binary form must reproduce the above copyright   * notice, this list of conditions and the following disclaimer in the   * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote  - * products derived from this software without specific prior written  + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written   * permission.   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -32,7 +32,7 @@   * Modifications: Kris Katterjohn <katterjohn@gmail.com>   *   */ -  +  #ifdef HAVE_CONFIG_H  #include "config.h"  #endif @@ -139,23 +139,24 @@ static int usb_setdirection_linux(pcap_t *, pcap_direction_t);  static void usb_cleanup_linux_mmap(pcap_t *);  /* facility to add an USB device to the device list*/ -static int  +static int  usb_dev_add(pcap_if_t** alldevsp, int n, char *err_str)  {  	char dev_name[10]; -	char dev_descr[30];  -	snprintf(dev_name, 10, USB_IFACE"%d", n); -	snprintf(dev_descr, 30, "USB bus number %d", n); +	char dev_descr[30]; +	pcap_snprintf(dev_name, 10, USB_IFACE"%d", n); +	pcap_snprintf(dev_descr, 30, "USB bus number %d", n); -	if (pcap_add_if(alldevsp, dev_name, 0,  +	if (pcap_add_if(alldevsp, dev_name, 0,  	    dev_descr, err_str) < 0)  		return -1; -	return 0;  +	return 0;  } -int  +int  usb_findalldevs(pcap_if_t **alldevsp, char *err_str)  { +	int fd;  	struct dirent* data;  	int ret = 0;  	DIR* dir; @@ -163,7 +164,46 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str)  	char* name;  	size_t len; -	/* try scanning sysfs usb bus directory */ +	/* +	 * Do we have a "scan all buses" device? +	 * First, try the binary device. +	 */ +	fd = open(LINUX_USB_MON_DEV"0", O_RDONLY, 0); +	if (fd >= 0) { +		/* +		 * Yes. +		 */ +		close(fd); +		if (pcap_add_if(alldevsp, "usbmon0", 0, "All USB buses", +		    err_str) < 0) +			return -1; +	} else { +		/* +		 * No binary device; do we have the text device? +		 */ +		fd = open(USB_TEXT_DIR"/0t", O_RDONLY, 0); +		if (fd < 0) { +			/* +			 * Not at the new location; try the old location. +			 */ +			fd = open(USB_TEXT_DIR_OLD"/0t", O_RDONLY, 0); +		} +		if (fd >= 0) { +			/* +			 * We found it. +			 */ +			close(fd); +			if (pcap_add_if(alldevsp, "usbmon0", 0, "All USB buses", +			    err_str) < 0) +				return -1; +		} +	} + +	/* +	 * Now look for individual USB buses. +	 * +	 * First, try scanning sysfs USB bus directory. +	 */  	dir = opendir(SYS_USB_BUS_DIR);  	if (dir != NULL) {  		while ((ret == 0) && ((data = readdir(dir)) != 0)) { @@ -172,7 +212,7 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str)  			if (strncmp(name, "usb", 3) != 0)  				continue; -			if (sscanf(&name[3], "%d", &n) == 0)  +			if (sscanf(&name[3], "%d", &n) == 0)  				continue;  			ret = usb_dev_add(alldevsp, n, err_str); @@ -182,7 +222,7 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str)  		return ret;  	} -	/* that didn't work; try scanning procfs usb bus directory */ +	/* That didn't work; try scanning procfs USB bus directory. */  	dir = opendir(PROC_USB_BUS_DIR);  	if (dir != NULL) {  		while ((ret == 0) && ((data = readdir(dir)) != 0)) { @@ -193,7 +233,7 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str)  			if ((len < 1) || !isdigit(name[--len]))  				continue;  			while (isdigit(name[--len])); -			if (sscanf(&name[len+1], "%d", &n) != 1)  +			if (sscanf(&name[len+1], "%d", &n) != 1)  				continue;  			ret = usb_dev_add(alldevsp, n, err_str); @@ -207,12 +247,12 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str)  	return 0;  } -static  +static  int usb_mmap(pcap_t* handle)  {  	struct pcap_usb_linux *handlep = handle->priv;  	int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE); -	if (len < 0)  +	if (len < 0)  		return 0;  	handlep->mmapbuflen = len; @@ -247,7 +287,7 @@ probe_devices(int bus)  	DIR* dir;  	/* scan usb bus directories for device nodes */ -	snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d", bus); +	pcap_snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d", bus);  	dir = opendir(buf);  	if (!dir)  		return; @@ -259,8 +299,8 @@ probe_devices(int bus)  		if (name[0] == '.')  			continue; -		snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name); -		 +		pcap_snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name); +  		fd = open(buf, O_RDWR);  		if (fd == -1)  			continue; @@ -328,7 +368,7 @@ usb_create(const char *device, char *ebuf, int *is_ours)  	/* OK, it's probably ours. */  	*is_ours = 1; -	p = pcap_create_common(device, ebuf, sizeof (struct pcap_usb_linux)); +	p = pcap_create_common(ebuf, sizeof (struct pcap_usb_linux));  	if (p == NULL)  		return (NULL); @@ -355,15 +395,15 @@ usb_activate(pcap_t* handle)  	handle->setnonblock_op = pcap_setnonblock_fd;  	/*get usb bus index from device name */ -	if (sscanf(handle->opt.source, USB_IFACE"%d", &handlep->bus_index) != 1) +	if (sscanf(handle->opt.device, USB_IFACE"%d", &handlep->bus_index) != 1)  	{ -		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, -			"Can't get USB bus index from %s", handle->opt.source); +		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +			"Can't get USB bus index from %s", handle->opt.device);  		return PCAP_ERROR;  	}  	/*now select the read method: try to open binary interface */ -	snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index);   +	pcap_snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index);  	handle->fd = open(full_path, O_RDONLY, 0);  	if (handle->fd >= 0)  	{ @@ -402,7 +442,7 @@ usb_activate(pcap_t* handle)  	}  	else {  		/*Binary interface not available, try open text interface */ -		snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index);   +		pcap_snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index);  		handle->fd = open(full_path, O_RDONLY, 0);  		if (handle->fd < 0)  		{ @@ -412,12 +452,12 @@ usb_activate(pcap_t* handle)  				 * Not found at the new location; try  				 * the old location.  				 */ -				snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index);   +				pcap_snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index);  				handle->fd = open(full_path, O_RDONLY, 0);  			}  			if (handle->fd < 0) {  				/* no more fallback, give it up*/ -				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,  					"Can't open USB bus file %s: %s", full_path, strerror(errno));  				return PCAP_ERROR;  			} @@ -445,7 +485,7 @@ usb_activate(pcap_t* handle)  	 * buffer */  	handle->buffer = malloc(handle->bufsize);  	if (!handle->buffer) { -		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,  			 "malloc: %s", pcap_strerror(errno));  		close(handle->fd);  		return PCAP_ERROR; @@ -453,22 +493,22 @@ usb_activate(pcap_t* handle)  	return 0;  } -static inline int  +static inline int  ascii_to_int(char c)  {  	return c < 'A' ? c- '0': ((c<'a') ? c - 'A' + 10: c-'a'+10);  }  /* - * see <linux-kernel-source>/Documentation/usb/usbmon.txt and  - * <linux-kernel-source>/drivers/usb/mon/mon_text.c for urb string  + * see <linux-kernel-source>/Documentation/usb/usbmon.txt and + * <linux-kernel-source>/drivers/usb/mon/mon_text.c for urb string   * format description   */  static int  usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)  {  	/* see: -	* /usr/src/linux/Documentation/usb/usbmon.txt  +	* /usr/src/linux/Documentation/usb/usbmon.txt  	* for message format  	*/  	struct pcap_usb_linux *handlep = handle->priv; @@ -496,20 +536,20 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u  		if (errno == EAGAIN)  			return 0;	/* no data there */ -		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,  		    "Can't read from fd %d: %s", handle->fd, strerror(errno));  		return -1;  	} -	/* read urb header; %n argument may increment return value, but it's  +	/* read urb header; %n argument may increment return value, but it's  	* not mandatory, so does not count on it*/  	string[ret] = 0; -	ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, ×tamp, &etype,  -		&pipeid1, &pipeid2, &dev_addr, &ep_num, status,  +	ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, ×tamp, &etype, +		&pipeid1, &pipeid2, &dev_addr, &ep_num, status,  		&cnt);  	if (ret < 8)  	{ -		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,  		    "Can't parse USB bus message '%s', too few tokens (expected 8 got %d)",  		    string, ret);  		return -1; @@ -521,10 +561,10 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u  	string += cnt;  	/* don't use usbmon provided timestamp, since it have low precision*/ -	if (gettimeofday(&pkth.ts, NULL) < 0)  +	if (gettimeofday(&pkth.ts, NULL) < 0)  	{ -		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, -			"Can't get timestamp for message '%s' %d:%s",  +		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +			"Can't get timestamp for message '%s' %d:%s",  			string, errno, strerror(errno));  		return -1;  	} @@ -567,15 +607,15 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u  	if (ret != 1)  	{  		/* this a setup packet, setup data can be filled with underscore if -		* usbmon has not been able to read them, so we must parse this fields as  +		* usbmon has not been able to read them, so we must parse this fields as  		* strings */  		pcap_usb_setup* shdr;  		char str1[3], str2[3], str3[5], str4[5], str5[5]; -		ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4,  +		ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4,  		str5, &cnt);  		if (ret < 5)  		{ -			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,  				"Can't parse USB bus message '%s', too few tokens (expected 5 got %d)",  				string, ret);  			return -1; @@ -592,20 +632,20 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u  		uhdr->setup_flag = 0;  	} -	else  +	else  		uhdr->setup_flag = 1;  	/* read urb data */  	ret = sscanf(string, " %d%n", &urb_len, &cnt);  	if (ret < 1)  	{ -		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,  		  "Can't parse urb length from '%s'", string);  		return -1;  	}  	string += cnt; -	/* urb tag is not present if urb length is 0, so we can stop here  +	/* urb tag is not present if urb length is 0, so we can stop here  	 * text parsing */  	pkth.len = urb_len+pkth.caplen;  	uhdr->urb_len = urb_len; @@ -617,12 +657,12 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u  	/* check for data presence; data is present if and only if urb tag is '=' */  	if (sscanf(string, " %c", &urb_tag) != 1)  	{ -		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,  			"Can't parse urb tag from '%s'", string);  		return -1;  	} -	if (urb_tag != '=')  +	if (urb_tag != '=')  		goto got;  	/* skip urb tag and following space */ @@ -631,12 +671,12 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u  	/* if we reach this point we got some urb data*/  	uhdr->data_flag = 0; -	/* read all urb data; if urb length is greater then the usbmon internal  +	/* read all urb data; if urb length is greater then the usbmon internal  	 * buffer length used by the kernel to spool the URB, we get only  	 * a partial information.  	 * At least until linux 2.6.17 there is no way to set usbmon intenal buffer  	 * length and default value is 130. */ -	while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < handle->snapshot)) +	while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < (bpf_u_int32)handle->snapshot))  	{  		rawdata[0] = ascii_to_int(string[0]) * 16 + ascii_to_int(string[1]);  		rawdata++; @@ -649,8 +689,8 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u  got:  	uhdr->data_len = data_len; -	if (pkth.caplen > handle->snapshot) -		pkth.caplen = handle->snapshot; +	if (pkth.caplen > (bpf_u_int32)handle->snapshot) +		pkth.caplen = (bpf_u_int32)handle->snapshot;  	if (handle->fcode.bf_insns == NULL ||  	    bpf_filter(handle->fcode.bf_insns, handle->buffer, @@ -665,12 +705,12 @@ got:  static int  usb_inject_linux(pcap_t *handle, const void *buf, size_t size)  { -	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on " +	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "  		"USB devices");  	return (-1);  } -static int  +static int  usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)  {  	struct pcap_usb_linux *handlep = handle->priv; @@ -680,7 +720,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)  	char * ptr = string;  	int fd; -	snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index); +	pcap_snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index);  	fd = open(string, O_RDONLY, 0);  	if (fd < 0)  	{ @@ -690,12 +730,12 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)  			 * Not found at the new location; try the old  			 * location.  			 */ -			snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index); +			pcap_snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index);  			fd = open(string, O_RDONLY, 0);  		}  		if (fd < 0) { -			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, -				"Can't open USB stats file %s: %s",  +			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +				"Can't open USB stats file %s: %s",  				string, strerror(errno));  			return -1;  		} @@ -709,7 +749,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)  	if (ret < 0)  	{ -		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,  			"Can't read stats from fd %d ", fd);  		return -1;  	} @@ -717,11 +757,11 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)  	/* extract info on dropped urbs */  	for (consumed=0; consumed < ret; ) { -		/* from the sscanf man page:  - 		 * The C standard says: "Execution of a %n directive does  +		/* from the sscanf man page: + 		 * The C standard says: "Execution of a %n directive does   		 * not increment the assignment count returned at the completion  		 * of  execution" but the Corrigendum seems to contradict this. -		 * Do not make any assumptions on the effect of %n conversions  +		 * Do not make any assumptions on the effect of %n conversions  		 * on the return value and explicitly check for cnt assignmet*/  		int ntok; @@ -733,7 +773,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)  		ptr += cnt;  		if (strcmp(token, "nreaders") == 0)  			ret = sscanf(ptr, "%d", &stats->ps_drop); -		else  +		else  			ret = sscanf(ptr, "%d", &dummy);  		if (ntok != 1)  			break; @@ -746,7 +786,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)  	return 0;  } -static int  +static int  usb_setdirection_linux(pcap_t *p, pcap_direction_t d)  {  	p->direction = d; @@ -754,7 +794,7 @@ usb_setdirection_linux(pcap_t *p, pcap_direction_t d)  } -static int  +static int  usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)  {  	struct pcap_usb_linux *handlep = handle->priv; @@ -763,7 +803,7 @@ usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)  	ret = ioctl(handle->fd, MON_IOCG_STATS, &st);  	if (ret < 0)  	{ -		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,  			"Can't read stats from fd %d:%s ", handle->fd, strerror(errno));  		return -1;  	} @@ -775,7 +815,7 @@ usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)  }  /* - * see <linux-kernel-source>/Documentation/usb/usbmon.txt and  + * see <linux-kernel-source>/Documentation/usb/usbmon.txt and   * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI   */  static int @@ -785,11 +825,11 @@ usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_cha  	struct mon_bin_get info;  	int ret;  	struct pcap_pkthdr pkth; -	int clen = handle->snapshot - sizeof(pcap_usb_header); +	u_int clen = handle->snapshot - sizeof(pcap_usb_header);  	/* the usb header is going to be part of 'packet' data*/  	info.hdr = (pcap_usb_header*) handle->buffer; -	info.data = handle->buffer + sizeof(pcap_usb_header); +	info.data = (u_char *)handle->buffer + sizeof(pcap_usb_header);  	info.data_len = clen;  	/* ignore interrupt system call errors */ @@ -806,7 +846,7 @@ usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_cha  		if (errno == EAGAIN)  			return 0;	/* no data there */ -		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,  		    "Can't read from fd %d: %s", handle->fd, strerror(errno));  		return -1;  	} @@ -833,7 +873,7 @@ usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_cha  }  /* - * see <linux-kernel-source>/Documentation/usb/usbmon.txt and  + * see <linux-kernel-source>/Documentation/usb/usbmon.txt and   * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI   */  #define VEC_SIZE 32 @@ -847,7 +887,7 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch  	pcap_usb_header* hdr;  	int nflush = 0;  	int packets = 0; -	int clen, max_clen; +	u_int clen, max_clen;  	max_clen = handle->snapshot - sizeof(pcap_usb_header); @@ -877,7 +917,7 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch  			if (errno == EAGAIN)  				return 0;	/* no data there */ -			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,  			    "Can't mfetch fd %d: %s", handle->fd, strerror(errno));  			return -1;  		} @@ -887,7 +927,7 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch  		for (i=0; i<fetch.nfetch; ++i) {  			/* discard filler */  			hdr = (pcap_usb_header*) &handlep->mmapbuf[vec[i]]; -			if (hdr->event_type == '@')  +			if (hdr->event_type == '@')  				continue;  			/* we can get less that than really captured from kernel, depending on @@ -917,7 +957,11 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch  	}  	/* flush pending events*/ -	ioctl(handle->fd, MON_IOCH_MFLUSH, nflush); +	if (ioctl(handle->fd, MON_IOCH_MFLUSH, nflush) == -1) { +		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, +		    "Can't mflush fd %d: %s", handle->fd, strerror(errno)); +		return -1; +	}  	return packets;  } | 
