150 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| --- a/pcap-linux.c
 | |
| +++ b/pcap-linux.c
 | |
| @@ -297,6 +297,12 @@ pcap_create(const char *device, char *eb
 | |
|  {
 | |
|  	pcap_t *handle;
 | |
|  
 | |
| +	/*
 | |
| +	 * A null device name is equivalent to the "any" device.
 | |
| +	 */
 | |
| +	if (device == NULL)
 | |
| +		device = "any";
 | |
| +
 | |
|  #ifdef HAVE_DAG_API
 | |
|  	if (strstr(device, "dag")) {
 | |
|  		return dag_create(device, ebuf);
 | |
| @@ -338,10 +344,9 @@ pcap_can_set_rfmon_linux(pcap_t *p)
 | |
|  	struct iwreq ireq;
 | |
|  #endif
 | |
|  
 | |
| -	if (p->opt.source == NULL) {
 | |
| +	if (strcmp(p->opt.source, "any") == 0) {
 | |
|  		/*
 | |
| -		 * This is equivalent to the "any" device, and we don't
 | |
| -		 * support monitor mode on it.
 | |
| +		 * Monitor mode makes no sense on the "any" device.
 | |
|  		 */
 | |
|  		return 0;
 | |
|  	}
 | |
| @@ -518,12 +523,11 @@ pcap_activate_linux(pcap_t *handle)
 | |
|  	handle->stats_op = pcap_stats_linux;
 | |
|  
 | |
|  	/*
 | |
| -	 * NULL and "any" are special devices which give us the hint to
 | |
| -	 * monitor all devices.
 | |
| +	 * The "any" device is a special device which causes us not
 | |
| +	 * to bind to a particular device and thus to look at all
 | |
| +	 * devices.
 | |
|  	 */
 | |
| -	if (!device || strcmp(device, "any") == 0) {
 | |
| -		device			= NULL;
 | |
| -		handle->md.device	= strdup("any");
 | |
| +	if (strcmp(device, "any") == 0) {
 | |
|  		if (handle->opt.promisc) {
 | |
|  			handle->opt.promisc = 0;
 | |
|  			/* Just a warning. */
 | |
| @@ -531,10 +535,9 @@ pcap_activate_linux(pcap_t *handle)
 | |
|  			    "Promiscuous mode not supported on the \"any\" device");
 | |
|  			status = PCAP_WARNING_PROMISC_NOTSUP;
 | |
|  		}
 | |
| +	}
 | |
|  
 | |
| -	} else
 | |
| -		handle->md.device	= strdup(device);
 | |
| -
 | |
| +	handle->md.device	= strdup(device);
 | |
|  	if (handle->md.device == NULL) {
 | |
|  		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
 | |
|  			 pcap_strerror(errno) );
 | |
| @@ -1657,19 +1660,21 @@ static int
 | |
|  activate_new(pcap_t *handle)
 | |
|  {
 | |
|  #ifdef HAVE_PF_PACKET_SOCKETS
 | |
| +	const char		*device = handle->opt.source;
 | |
| +	int			is_any_device = (strcmp(device, "any") == 0);
 | |
|  	int			sock_fd = -1, arptype, val;
 | |
|  	int			err = 0;
 | |
|  	struct packet_mreq	mr;
 | |
| -	const char* device = handle->opt.source;
 | |
|  
 | |
|  	/*
 | |
| -	 * Open a socket with protocol family packet. If a device is
 | |
| -	 * given we try to open it in raw mode otherwise we use
 | |
| -	 * the cooked interface.
 | |
| -	 */
 | |
| -	sock_fd = device ?
 | |
| -		socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
 | |
| -	      : socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL));
 | |
| +	 * Open a socket with protocol family packet. If the
 | |
| +	 * "any" device was specified, we open a SOCK_DGRAM
 | |
| +	 * socket for the cooked interface, otherwise we first
 | |
| +	 * try a SOCK_RAW socket for the raw interface.
 | |
| +	 */
 | |
| +	sock_fd = is_any_device ?
 | |
| +		socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) :
 | |
| +		socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
 | |
|  
 | |
|  	if (sock_fd == -1) {
 | |
|  		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
 | |
| @@ -1704,7 +1709,7 @@ activate_new(pcap_t *handle)
 | |
|  	 * to cooked mode if we have an unknown interface type
 | |
|  	 * or a type we know doesn't work well in raw mode.
 | |
|  	 */
 | |
| -	if (device) {
 | |
| +	if (!is_any_device) {
 | |
|  		/* Assume for now we don't need cooked mode. */
 | |
|  		handle->md.cooked = 0;
 | |
|  
 | |
| @@ -1819,15 +1824,23 @@ activate_new(pcap_t *handle)
 | |
|  		}
 | |
|  	} else {
 | |
|  		/*
 | |
| -		 * This is cooked mode.
 | |
| +		 * The "any" device.
 | |
| +		 */
 | |
| +		if (handle->opt.rfmon) {
 | |
| +			/*
 | |
| +			 * It doesn't support monitor mode.
 | |
| +			 */
 | |
| +			return PCAP_ERROR_RFMON_NOTSUP;
 | |
| +		}
 | |
| +
 | |
| +		/*
 | |
| +		 * It uses cooked mode.
 | |
|  		 */
 | |
|  		handle->md.cooked = 1;
 | |
|  		handle->linktype = DLT_LINUX_SLL;
 | |
|  
 | |
|  		/*
 | |
|  		 * We're not bound to a device.
 | |
| -		 * XXX - true?  Or true only if we're using
 | |
| -		 * the "any" device?
 | |
|  		 * For now, we're using this as an indication
 | |
|  		 * that we can't transmit; stop doing that only
 | |
|  		 * if we figure out how to transmit in cooked
 | |
| @@ -1852,10 +1865,13 @@ activate_new(pcap_t *handle)
 | |
|  
 | |
|  	/*
 | |
|  	 * Hmm, how can we set promiscuous mode on all interfaces?
 | |
| -	 * I am not sure if that is possible at all.
 | |
| +	 * I am not sure if that is possible at all.  For now, we
 | |
| +	 * silently ignore attempts to turn promiscuous mode on
 | |
| +	 * for the "any" device (so you don't have to explicitly
 | |
| +	 * disable it in programs such as tcpdump).
 | |
|  	 */
 | |
|  
 | |
| -	if (device && handle->opt.promisc) {
 | |
| +	if (!is_any_device && handle->opt.promisc) {
 | |
|  		memset(&mr, 0, sizeof(mr));
 | |
|  		mr.mr_ifindex = handle->md.ifindex;
 | |
|  		mr.mr_type    = PACKET_MR_PROMISC;
 | |
| @@ -3118,7 +3134,7 @@ activate_old(pcap_t *handle)
 | |
|  
 | |
|  	/* Bind to the given device */
 | |
|  
 | |
| -	if (!device) {
 | |
| +	if (strcmp(device, "any") == 0) {
 | |
|  		strncpy(handle->errbuf, "pcap_activate: The \"any\" device isn't supported on 2.0[.x]-kernel systems",
 | |
|  			PCAP_ERRBUF_SIZE);
 | |
|  		return PCAP_ERROR;
 | 
