示例#1
0
static void prvConfigureCaptureBehaviour( void )
{
    struct bpf_program xFilterCode;
    const long lMinBytesToCopy = 10L, lBlocking = 1L;
    unsigned long ulNetMask;

    /* Unblock a read as soon as anything is received. */
    pcap_setmintocopy( pxOpenedInterfaceHandle, lMinBytesToCopy );

    /* Allow blocking. */
    pcap_setnonblock( pxOpenedInterfaceHandle, lBlocking, cErrorBuffer );

    /* Set up a filter so only the packets of interest are passed to the lwIP
    stack.  cErrorBuffer is used for convenience to create the string.  Don't
    confuse this with an error message. */
    sprintf( cErrorBuffer, "broadcast or multicast or host %d.%d.%d.%d", configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );

    ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;

    if( pcap_compile(pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 ) {
        printf( "\r\nThe packet filter string is invalid\r\n" );
    } else {
        if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 ) {
            printf( "\r\nAn error occurred setting the packet filter.\r\n" );
        }
    }

    /* Create a task that simulates an interrupt in a real system.  This will
    block waiting for packets, then send a message to the uIP task when data
    is available. */
    xTaskCreate( prvInterruptSimulator, "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, configMAC_ISR_SIMULATOR_PRIORITY, NULL );
}
示例#2
0
int
pcap_ex_immediate(pcap_t *pcap)
{
#ifdef _WIN32
    return pcap_setmintocopy(pcap, 1);
#elif defined BIOCIMMEDIATE
    int n = 1;
    return ioctl(pcap_fileno(pcap), BIOCIMMEDIATE, &n);
#else /* XXX On OSX Yosemite (10.10.3) BIOCIMMEDIATE is not defined) */
    int n = 1;
    return ioctl(pcap_fileno(pcap), _IOW('B',112, u_int), &n);
#endif
}
示例#3
0
int
pcap_ex_immediate(pcap_t *pcap)
{
#ifdef BIOCIMMEDIATE
	int n = 1;
	
	return ioctl(pcap_fileno(pcap), BIOCIMMEDIATE, &n);
#elif defined _WIN32
	return pcap_setmintocopy(pcap, 1);
#else
	return (0);
#endif
}
示例#4
0
u08 eth_init_interface( u08 iface, u08 real_iface )
{
	pcap_if_t * alldevs;
	pcap_if_t * d;
	char errbuf[ PCAP_ERRBUF_SIZE ];

	interfaces[ iface ] = 0;

	if (pcap_findalldevs( &alldevs, errbuf ) == -1)
	{
		log_printf( "hal: error in pcap_findalldevs: %s\n", errbuf );
		return 0;
	}

	if (!alldevs)
	{
		log_printf( "hal: looks like there's no network cards, or pcap isnt running.\n" );
		return 0;
	}

	d = alldevs;
	while( real_iface-- )
		d = d->next;

	interfaces[ iface ] = pcap_open_live( d->name, 65536, 1, 1000, errbuf );

	if (!interfaces[iface])
	{
		log_printf( "hal: failed opening interface %s\n", d->name );
		return 0;
	}

	log_printf( "hal: iface=%d -> %s\n", 
		iface, d->description );

	pcap_setmintocopy( interfaces[iface], 1 );

	interface_handles[ iface ] = (HANDLE)pcap_getevent( interfaces[ iface ] );

	pcap_freealldevs( alldevs );
	return 1;
}
示例#5
0
static pcap_t *select_interface_by_id(int id) 
{
	pcap_if_t *alldevs;
	pcap_if_t *dev;
	pcap_t *res = NULL;
	char errbuf[PCAP_ERRBUF_SIZE + 1];
	int i;

	if(pcap_findalldevs_ex("rpcap://", NULL, &alldevs, errbuf) == -1) { /* TODO: "rpcap://" -> PCAP_SRC_IF_STRING */
		fprintf(stderr,"Error in pcap_findalldevs_ex: %s\n", errbuf);
		return NULL;
	}

	for(dev=alldevs, i=0; dev != NULL; dev=dev->next, i++ ) {
		if(i == id) {
			res = pcap_open(dev->name,
					2048,	/* TODO: ? */
					1 | 16,	/* TODO: 1 | 16 -> PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_MAX_RESPONSIVENESS */
					1000,
					NULL,
					errbuf);

			if(!res) {
				fprintf(stderr,"Unable to open the adapter.\n");
				return NULL;
			}

			pcap_setmintocopy(res, 0);

			break;
		}
	}

	if(dev == 0) {
		printf("No interfaces found!\n");
		return NULL;
	}

	pcap_freealldevs(alldevs);

	return res;
}
示例#6
0
文件: pcapy.c 项目: neirbowj/pcapy
static PyObject*
open_live(PyObject *self, PyObject *args)
{
  char errbuff[PCAP_ERRBUF_SIZE];
  char * device;
  int  snaplen;
  int  promisc;
  int  to_ms;

  bpf_u_int32 net, mask;


  if(!PyArg_ParseTuple(args,"sipi:open_live",&device,&snaplen,&promisc,&to_ms))
    return NULL;

  int status = pcap_lookupnet(device, &net, &mask, errbuff);
  if(status)
    {
      net = 0;
      mask = 0;
    }

  pcap_t* pt;

  pt = pcap_open_live(device, snaplen, promisc!=0, to_ms, errbuff);
  if(!pt)
    {
      PyErr_SetString(PcapError, errbuff);
      return NULL;
    }
#ifdef WIN32
  pcap_setmintocopy(pt, 0);
#endif

  return new_pcapobject( pt, net, mask );
}
示例#7
0
文件: pcapy.c 项目: neirbowj/pcapy
static PyObject*
open_offline(PyObject *self, PyObject *args)
{
  char errbuff[PCAP_ERRBUF_SIZE];
  char * filename;


  if(!PyArg_ParseTuple(args,"s",&filename))
    return NULL;

  pcap_t* pt;

  pt = pcap_open_offline(filename, errbuff);
  if(!pt)
    {
      PyErr_SetString(PcapError, errbuff);
      return NULL;
    }
#ifdef WIN32
  pcap_setmintocopy(pt, 0);
#endif

  return new_pcapobject( pt, /*net=*/0, /*mask=*/0 );
}
示例#8
0
signed openchannel (struct channel * channel)

{

#if defined (__linux__)

	struct ifreq ifreq;
	struct sockaddr_ll sockaddr_ll =
	{
		PF_PACKET,
		0x0000,
		0x0000,
		ARPHRD_ETHER,
		PACKET_HOST,
		ETHER_ADDR_LEN,
		{
			0x00,
			0x00,
			0x00,
			0x00,
			0x00,
			0x00,
			0x00,
			0x00
		}
	};

/*
 *      raw packets require root privileges on linux; one does not have to be
 *      root when this program is installed setuid using 'chown root:root' and
 *      'chmod 4555';
 */

	if (geteuid ())
	{
		error (1, EPERM, ERROR_NOTROOT);
	}

	memset (&ifreq, 0, sizeof (ifreq));
	sockaddr_ll.sll_protocol = htons (channel->type);
	if ((channel->fd = socket (sockaddr_ll.sll_family, SOCK_RAW, sockaddr_ll.sll_protocol)) == -1)
	{
		error (1, errno, "%s", channel->ifname);
	}
	memcpy (ifreq.ifr_name, channel->ifname, sizeof (ifreq.ifr_name));
	if (ioctl (channel->fd, SIOCGIFINDEX, &ifreq) == -1)
	{
		error (1, errno, "%s", ifreq.ifr_name);
	}
	channel->ifindex = sockaddr_ll.sll_ifindex = ifreq.ifr_ifindex;
	if (ioctl (channel->fd, SIOCGIFHWADDR, &ifreq) == -1)
	{
		error (1, errno, "%s", ifreq.ifr_name);
	}
	memcpy (sockaddr_ll.sll_addr, ifreq.ifr_ifru.ifru_hwaddr.sa_data, sizeof (sockaddr_ll.sll_addr));
	if (bind (channel->fd, (struct sockaddr *) (&sockaddr_ll), sizeof (sockaddr_ll)) == -1)
	{
		error (1, errno, "%s", ifreq.ifr_name);
	}
	memcpy (channel->host, sockaddr_ll.sll_addr, sizeof (channel->host));
	if (ioctl (channel->fd, SIOCGIFFLAGS, &ifreq) == -1)
	{
		error (1, errno, "%s", ifreq.ifr_name);
	}
	channel->ifstate = ifreq.ifr_flags;
	_setbits (ifreq.ifr_flags, (IFF_UP | IFF_BROADCAST | IFF_MULTICAST));
	_clrbits (ifreq.ifr_flags, (IFF_ALLMULTI | IFF_PROMISC));
	if (ioctl (channel->fd, SIOCSIFFLAGS, &ifreq) == -1)
	{
		error (1, errno, "%s", ifreq.ifr_name);
	}

#else

	struct bpf_program bpf_program;
	static struct bpf_insn bpf_insn [] =
	{
		{
			BPF_LD + BPF_H + BPF_ABS,
			0,
			0,
			12
		},
		{
			BPF_JMP + BPF_JEQ + BPF_K,
			0,
			18,
			0
		},
		{
			BPF_LD + BPF_B + BPF_ABS,
			0,
			0,
			0
		},
		{
			BPF_JMP + BPF_JEQ + BPF_K,
			0,
			10,
			0
		},
		{
			BPF_LD + BPF_B + BPF_ABS,
			0,
			0,
			1
		},
		{
			BPF_JMP + BPF_JEQ + BPF_K,
			0,
			8,
			0
		},
		{
			BPF_LD + BPF_B + BPF_ABS,
			0,
			0,
			2
		},
		{
			BPF_JMP + BPF_JEQ + BPF_K,
			0,
			6,
			0
		},
		{
			BPF_LD + BPF_B + BPF_ABS,
			0,
			0,
			3
		},
		{
			BPF_JMP + BPF_JEQ + BPF_K,
			0,
			4,
			0
		},
		{
			BPF_LD + BPF_B + BPF_ABS,
			0,
			0,
			4
		},
		{
			BPF_JMP + BPF_JEQ + BPF_K,
			0,
			2,
			0
		},
		{
			BPF_LD + BPF_B + BPF_ABS,
			0,
			0,
			5
		},
		{
			BPF_JMP + BPF_JEQ + BPF_K,
			4,
			0,
			0
		},
		{
			BPF_LD + BPF_W + BPF_ABS,
			0,
			0,
			0
		},
		{
			BPF_JMP + BPF_JEQ + BPF_K,
			0,
			4,
			0xFFFFFFFF
		},
		{
			BPF_LD + BPF_H + BPF_ABS,
			0,
			0,
			4
		},
		{
			BPF_JMP + BPF_JEQ + BPF_K,
			0,
			2,
			0xFFFF
		},
		{
			BPF_LD + BPF_W + BPF_LEN,
			0,
			0,
			0
		},
		{
			BPF_RET + BPF_A,
			0,
			0,
			0
		},
		{
			BPF_RET + BPF_K,
			0,
			0,
			0
		}
	};

#if defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)

	struct ifreq ifreq;
	struct timeval timeval;
	struct bpf * bpf;
	char filename [sizeof (CHANNEL_BPFDEVICE) + 1];
	unsigned count;
	unsigned state;
	int stat_errno = 0;
	int open_errno = 0;
	for (count = 0; count < 100; count++)
	{
		struct stat st;
		snprintf (filename, sizeof (filename), CHANNEL_BPFDEVICE, count);
		if (stat(filename, &st) == -1)
		{
			stat_errno = errno;
			continue;
		}
		if ((channel->fd = open (filename, O_RDWR)) != -1)
		{
			break;
		}
		else
		{
			open_errno = errno;
		}
	}
	if (channel->fd == -1)
	{
		if (open_errno)
		{
			error (1, open_errno, "Could not open bpf device");
		}
		else
		{
			error (1, stat_errno, "No bpf device found");
		}
	}
	memcpy (ifreq.ifr_name, channel->ifname, sizeof (ifreq.ifr_name));
	if (ioctl (channel->fd, BIOCSETIF, &ifreq) == -1)
	{
		error (1, errno, "%s", ifreq.ifr_name);
	}
	channel->bpf = bpf = malloc (sizeof (* bpf));
	if (ioctl (channel->fd, BIOCGBLEN, &bpf->bpf_length) == -1)
	{
		error (1, errno, "Can't determine buffer length: %s", ifreq.ifr_name);
	}
	bpf->bpf_bp = bpf->bpf_buffer = malloc (bpf->bpf_length);
	if (bpf->bpf_buffer == NULL)
	{
		error (1, errno, "Can't allocate receive buffer");
	}

#if defined (__APPLE__) || defined (__NetBSD__)

	state = 0;
	if (ioctl (channel->fd, BIOCSSEESENT, &state) == -1)
	{
		error (1, errno, "Can't hide outgoing frames: %s", ifreq.ifr_name);
	}

#elif defined (__OpenBSD__)

	state = BPF_DIRECTION_OUT;
	if (ioctl (channel->fd, BIOCSDIRFILT, &state) == -1)
	{
		error (0, errno, "Can't hide outgoing frames");
	}

#else
#error "Abandon all hope"
#endif

	if (channel->capture > 1000)
	{
		timeval.tv_sec = channel->capture / 1000;
		timeval.tv_usec = 0;
	}
	else
	{

#if defined (__MAC_10_6)

/*
 *	accommodate known bug in BPF on MAC OS X 10.6; shorter times cause socket read
 *	operations to block indefinitely if no frames are waiting because tv_usec gets
 *      clobbered;
 */

		timeval.tv_sec = 1;
		timeval.tv_usec = 0;

#else

		timeval.tv_sec = 0;
		timeval.tv_usec = channel->capture * 1000;

#endif

	}
	if (ioctl (channel->fd, BIOCSRTIMEOUT, &timeval) == -1)
	{
		error (1, errno, "Can't set channel timeout: %s", ifreq.ifr_name);
	}
	state = 1;
	if (ioctl (channel->fd, BIOCIMMEDIATE, &state) == -1)
	{
		error (1, errno, "Can't set immediate mode: %s", ifreq.ifr_name);
	}

#if 1

	state = 1;
	if (ioctl (channel->fd, BIOCSHDRCMPLT, &state) == -1)
	{
		error (1, errno, "Can't set header complete mode: %s", ifreq.ifr_name);
	}

#endif

#if 1

	gethwaddr (channel->host, channel->ifname);

#else

	if (ioctl (channel->fd, SIOCGIFADDR, &ifreq) > 0)
	{
		error (1, errno, "%s", ifreq.ifr_name);
	}
	memcpy (channel->host, LLADDR (ifreq.ifr_ifru.ifru_addr), sizeof (channel->host));

#endif

	bpf_program.bf_len = sizeof (bpf_insn) / sizeof (struct bpf_insn);
	bpf_program.bf_insns = bpf_insn;
	if (channel->type == ETH_P_802_2)
	{
		bpf_insn [1].code = BPF_JMP + BPF_JGT + BPF_K;
		bpf_insn [1].jt = 18;
		bpf_insn [1].jf = 0;
		bpf_insn [1].k = ETHERMTU;
	}
	else
	{
		bpf_insn [1].code = BPF_JMP + BPF_JEQ + BPF_K;
		bpf_insn [1].jt = 0;
		bpf_insn [1].jf = 18;
		bpf_insn [1].k = channel->type;
	}
	bpf_insn [3].k = channel->host [0];
	bpf_insn [5].k = channel->host [1];
	bpf_insn [7].k = channel->host [2];
	bpf_insn [9].k = channel->host [3];
	bpf_insn [11].k = channel->host [4];
	bpf_insn [13].k = channel->host [5];
	if (ioctl (channel->fd, BIOCSETF, &bpf_program) == -1)
	{
		error (1, errno, "Can't store filter: %s", channel->ifname);
	}

#elif defined (WINPCAP) || defined (LIBPCAP)

	channel->ifname = getifname (channel->ifindex);
	gethwaddr (channel->host, channel->ifname);
	channel->socket = pcap_open_live (channel->ifname, 65536, 0, channel->capture, channel->errbuf);
	snprintf ((char *)(channel->ifname), strlen (channel->ifname), "nic%d", channel->ifindex);
	if (!channel->socket)
	{
		error (1, errno, "Can't open interface: %s", channel->ifname);
	}
	bpf_program.bf_len = sizeof (bpf_insn)/sizeof (struct bpf_insn);
	bpf_program.bf_insns = bpf_insn;
	if (channel->type == ETH_P_802_2)
	{
		bpf_insn [1].code = BPF_JMP + BPF_JGT + BPF_K;
		bpf_insn [1].jt = 18;
		bpf_insn [1].jf = 0;
		bpf_insn [1].k = ETHERMTU;
	}
	else
	{
		bpf_insn [1].code = BPF_JMP + BPF_JEQ + BPF_K;
		bpf_insn [1].jt = 0;
		bpf_insn [1].jf = 18;
		bpf_insn [1].k = channel->type;
	}
	bpf_insn [3].k = channel->host [0];
	bpf_insn [5].k = channel->host [1];
	bpf_insn [7].k = channel->host [2];
	bpf_insn [9].k = channel->host [3];
	bpf_insn [11].k = channel->host [4];
	bpf_insn [13].k = channel->host [5];
	if (pcap_setfilter (channel->socket, &bpf_program) < 0)
	{
		error (1, errno, "Can't store filter: %s", channel->ifname);
	}
	if (pcap_setmintocopy (channel->socket, ETHER_MIN_LEN) < 0)
	{
		error (1, errno, "Can't set pcap mintocopy: %s", channel->ifname);
	}

#else
#error "Unknown Environment"
#endif
#endif

	return (0);
}
示例#9
0
/* Convert new nsiod to pcap descriptor. Other parameters have the same meaning
 * as for pcap_open_live in pcap(3).
 *   device   : pcap-style device name
 *   snaplen  : size of packet to be copied to hanler
 *   promisc  : whether to open device in promiscuous mode
 *   bpf_fmt   : berkeley filter
 * return value: NULL if everything was okay, or error string if error occurred. */
char* nsock_pcap_open(nsock_pool nsp, nsock_iod nsiod, const char *pcap_device, int snaplen,
                      int promisc, const char *bpf_fmt, ...) {
  msiod *nsi = (msiod *)nsiod;
  mspool *ms = (mspool *)nsp;
  mspcap *mp = (mspcap *)nsi->pcap;
  static char errorbuf[128];
  char err0r[PCAP_ERRBUF_SIZE];
  /* packet filter string */
  char bpf[4096];
  va_list ap;
  int failed, datalink;
  char *e;

  gettimeofday(&nsock_tod, NULL);

#ifdef PCAP_CAN_DO_SELECT

#if PCAP_BSD_SELECT_HACK
  /* MacOsX reports error if to_ms is too big (like INT_MAX) with error
   *  FAILED. Reported error: BIOCSRTIMEOUT: Invalid argument
   *  INT_MAX/6 (=357913941) seems to be working... */
  int to_ms = 357913941;
#else
  int to_ms = 200;
#endif /* PCAP_BSD_SELECT_HACK */

#else
  int to_ms = 1;
#endif

  if (mp)
    return "nsock-pcap: this nsi already has pcap device opened";

  mp = (mspcap *)safe_zalloc(sizeof(mspcap));
  nsi->pcap = (void *)mp;

  va_start(ap, bpf_fmt);
  if (Vsnprintf(bpf, sizeof(bpf), bpf_fmt, ap) >= (int)sizeof(bpf)) {
    va_end(ap);
    return "nsock-pcap: nsock_pcap_open called with too-large bpf filter arg";
  }
  va_end(ap);

  if (ms->tracelevel > 0)
      nsock_trace(ms,
                  "PCAP requested on device '%s' with berkeley filter '%s' (promisc=%i snaplen=%i to_ms=%i) (IOD #%li)",
                  pcap_device,bpf, promisc, snaplen, to_ms, nsi->id);

  failed = 0;
  do {
    mp->pt = pcap_open_live((char* )pcap_device, snaplen, promisc, to_ms, err0r);
    if (mp->pt)  /* okay, opened!*/
      break;

    /* sorry, something failed*/
    if (++failed >= 3) {
      mp->pcap_device = strdup(pcap_device);
      fprintf(stderr,
              "Call to pcap_open_live(%s, %d, %d, %d) failed three times. Reported error: %s\n"
              "There are several possible reasons for this, depending on your operating system:\n"
              "LINUX: If you are getting Socket type not supported, try modprobe af_packet or recompile your kernel with PACKET enabled.\n"
              "*BSD:  If you are getting device not configured, you need to recompile your kernel with Berkeley Packet Filter support.  If you are getting No such file or directory, try creating the device (eg cd /dev; MAKEDEV <device>; or use mknod).\n"
              "*WINDOWS:  Nmap only supports ethernet interfaces on Windows for most operations because Microsoft disabled raw sockets as of Windows XP SP2.  Depending on the reason for this error, it is possible that the --unprivileged command-line argument will help.\n"
              "SOLARIS:  If you are trying to scan localhost and getting '/dev/lo0: No such file or directory', complain to Sun.  I don't think Solaris can support advanced localhost scans.  You can probably use \"-PN -sT localhost\" though.\n\n",
        pcap_device, snaplen, promisc, to_ms, err0r);
      return "nsock-pcap: can't open pcap! Are you root?";
    }

    fprintf(stderr,
            "pcap_open_live(%s, %d, %d, %d) FAILED. Reported error: %s. Will wait %d seconds then retry.\n",
            pcap_device, snaplen, promisc, to_ms, err0r, 4*failed);
    sleep(4* failed);
  } while (1);

  e = nsock_pcap_set_filter(mp->pt, pcap_device, bpf);
  if (e)
    return e;

#ifdef WIN32
  /* We want any responses back ASAP */
  pcap_setmintocopy(mp->pt, 1);
#endif

  mp->l3_offset = nsock_pcap_get_l3_offset(mp->pt, &datalink);
  mp->snaplen = snaplen;
  mp->datalink = datalink;
  mp->pcap_device = strdup(pcap_device);
#ifdef PCAP_CAN_DO_SELECT
  mp->pcap_desc = pcap_get_selectable_fd(mp->pt);
#else
  mp->pcap_desc = -1;
#endif
  mp->readsd_count = 0;

  /* Without setting this ioctl, some systems (BSDs, though it depends on the
   * release) will buffer packets in non-blocking mode and only return them in a
   * bunch when the buffer is full. Setting the ioctl makes each one be
   * delivered immediately. This is how Linux works by default. See the comments
   * surrounding the setting of BIOCIMMEDIATE in libpcap/pcap-bpf.c. */
#ifdef BIOCIMMEDIATE
  if (mp->pcap_desc != -1) {
    int immediate = 1;

    if (ioctl(mp->pcap_desc, BIOCIMMEDIATE, &immediate) < 0)
      fatal("Cannot set BIOCIMMEDIATE on pcap descriptor");
  }
#endif

  /* Set device non-blocking */
  if (pcap_setnonblock(mp->pt, 1, err0r) < 0) {
    /* I can't do select() on pcap! blocking + no_select is fatal */
    if(mp->pcap_desc < 0){
      Snprintf(errorbuf, sizeof(errorbuf),
               "nsock-pcap: Failed to set pcap descriptor on device %s to nonblocking state: %s",
               pcap_device, err0r);
      return errorbuf;
    }

    /* When we use bsd hack we also need to set non-blocking */
#ifdef PCAP_BSD_SELECT_HACK
    Snprintf(errorbuf, sizeof(errorbuf),
             "nsock-pcap: Failed to set pcap descriptor on device %s to nonblocking state: %s",
             pcap_device, err0r);
    return errorbuf;
#endif

    /* in other case, we can accept blocking pcap */
    fprintf(stderr, "Failed to set pcap descriptor on device %s to nonblocking state: %s",
            pcap_device, err0r);
  }

  if (ms->tracelevel > 0)
      nsock_trace(ms, "PCAP created successfully on device '%s' (pcap_desc=%i bsd_hack=%i to_valid=%i l3_offset=%i) (IOD #%li)",
      pcap_device,
      mp->pcap_desc,
#if PCAP_BSD_SELECT_HACK
      1,
#else
      0,
#endif
#if PCAP_RECV_TIMEVAL_VALID
      1,
#else
      0,
#endif
      mp->l3_offset,
      nsi->id);

  return NULL;
}
示例#10
0
文件: nsock_pcap.c 项目: Abhikos/nmap
/* Convert new nsiod to pcap descriptor. Other parameters have
 * the same meaning as for pcap_open_live in pcap(3).
 *   device   : pcap-style device name
 *   snaplen  : size of packet to be copied to handler
 *   promisc  : whether to open device in promiscuous mode
 *   bpf_fmt   : berkeley filter
 * return value: NULL if everything was okay, or error string
 * if error occurred. */
int nsock_pcap_open(nsock_pool nsp, nsock_iod nsiod, const char *pcap_device,
                    int snaplen, int promisc, const char *bpf_fmt, ...) {
  struct niod *nsi = (struct niod *)nsiod;
  struct npool *ms = (struct npool *)nsp;
  mspcap *mp = (mspcap *)nsi->pcap;
  char errbuf[PCAP_ERRBUF_SIZE];
  char bpf[4096];
  va_list ap;
  int failed, datalink;
  int rc;

#ifdef PCAP_CAN_DO_SELECT
#if PCAP_BSD_SELECT_HACK
  /* MacOsX reports error if to_ms is too big (like INT_MAX) with error
   * FAILED. Reported error: BIOCSRTIMEOUT: Invalid argument
   * INT_MAX/6 (=357913941) seems to be working... */
  int to_ms = 357913941;
#else
  int to_ms = 200;
#endif /* PCAP_BSD_SELECT_HACK */

#else
  int to_ms = 1;
#endif

  gettimeofday(&nsock_tod, NULL);

  if (mp) {
    nsock_log_error(ms, "This nsi already has pcap device opened");
    return -1;
  }

  mp = (mspcap *)safe_zalloc(sizeof(mspcap));
  nsi->pcap = (void *)mp;

  va_start(ap, bpf_fmt);
  rc = Vsnprintf(bpf, sizeof(bpf), bpf_fmt, ap);
  va_end(ap);

  if (rc >= (int)sizeof(bpf)) {
    nsock_log_error(ms, "Too-large bpf filter argument");
    return -1;
  }

  nsock_log_info(ms, "PCAP requested on device '%s' with berkeley filter '%s' "
                 "(promisc=%i snaplen=%i to_ms=%i) (IOD #%li)",
                 pcap_device,bpf, promisc, snaplen, to_ms, nsi->id);

  failed = 0;
  do {
    rc = nsock_pcap_try_open(ms, mp, pcap_device, snaplen, promisc, to_ms, errbuf);
    if (rc) {
      failed++;
      nsock_log_error(ms, "Will wait %d seconds then retry.", 4 * failed);
      sleep(4 * failed);
    }
  } while (rc && failed < PCAP_OPEN_MAX_RETRIES);

  if (rc) {
    nsock_log_error(ms, "pcap_open_live(%s, %d, %d, %d) failed %d times.",
                    pcap_device, snaplen, promisc, to_ms, failed);
    nsock_log_error(ms, PCAP_FAILURE_EXPL_MESSAGE);
    nsock_log_error(ms, "Can't open pcap! Are you root?");
    return -1;
  }

  rc = nsock_pcap_set_filter(ms, mp->pt, pcap_device, bpf);
  if (rc)
    return rc;

#ifdef WIN32
  /* We want any responses back ASAP */
  pcap_setmintocopy(mp->pt, 1);
#endif

  mp->l3_offset = nsock_pcap_get_l3_offset(mp->pt, &datalink);
  mp->snaplen = snaplen;
  mp->datalink = datalink;
  mp->pcap_device = strdup(pcap_device);
#ifdef PCAP_CAN_DO_SELECT
  mp->pcap_desc = pcap_get_selectable_fd(mp->pt);
#else
  mp->pcap_desc = -1;
#endif
  mp->readsd_count = 0;

  /* Without setting this ioctl, some systems (BSDs, though it depends on the
   * release) will buffer packets in non-blocking mode and only return them in a
   * bunch when the buffer is full. Setting the ioctl makes each one be
   * delivered immediately. This is how Linux works by default. See the comments
   * surrounding the setting of BIOCIMMEDIATE in libpcap/pcap-bpf.c. */
#ifdef BIOCIMMEDIATE
  if (mp->pcap_desc != -1) {
    int immediate = 1;

    if (ioctl(mp->pcap_desc, BIOCIMMEDIATE, &immediate) < 0)
      fatal("Cannot set BIOCIMMEDIATE on pcap descriptor");
  }
#endif

  /* Set device non-blocking */
  rc = pcap_setnonblock(mp->pt, 1, errbuf);
  if (rc) {

    /* I can't do select() on pcap!
     * blocking + no_select is fatal */
#ifndef PCAP_BSD_SELECT_HACK
    if (mp->pcap_desc < 0)
#endif
    {
      nsock_log_error(ms, "Failed to set pcap descriptor on device %s "
                      "to nonblocking mode: %s", pcap_device, errbuf);
      return -1;
    }
    /* in other case, we can accept blocking pcap */
    nsock_log_info(ms, "Failed to set pcap descriptor on device %s "
                   "to nonblocking state: %s", pcap_device, errbuf);
  }

  if (ms->loglevel <= NSOCK_LOG_INFO) {
    #if PCAP_BSD_SELECT_HACK
      int bsd_select_hack = 1;
    #else
      int bsd_select_hack = 0;
    #endif

    #if PCAP_RECV_TIMEVAL_VALID
      int recv_timeval_valid = 1;
    #else
      int recv_timeval_valid = 0;
    #endif

    nsock_log_info(ms, "PCAP created successfully on device '%s' "
                   "(pcap_desc=%i bsd_hack=%i to_valid=%i l3_offset=%i) (IOD #%li)",
                   pcap_device, mp->pcap_desc, bsd_select_hack,
                   recv_timeval_valid, mp->l3_offset, nsi->id);
  }
  return 0;
}
示例#11
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);
}
//------------------------------------------------------------------------------
tOplkError edrv_init(const tEdrvInitParam* pEdrvInitParam_p)
{
    char                errorMessage[PCAP_ERRBUF_SIZE];
    char                aDevicePcapName[256];
    DWORD               threadId;

    // 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);
    }

    // Add string specific for WinPCap
    strcpy(aDevicePcapName, "\\Device\\NPF_");
    strcat(aDevicePcapName, edrvInstance_l.initParam.pDevName);
    edrvInstance_l.pPcap = pcap_open_live(
                        aDevicePcapName,
                        65535,  // snaplen
                        1,      // promiscuous mode
                        1,      // milliseconds read timeout
                        errorMessage
                    );

    if (edrvInstance_l.pPcap == NULL)
    {
        DEBUG_LVL_ERROR_TRACE("%s() Error!! Can't open pcap: %s\n", __func__, errorMessage);
        return kErrorEdrvInit;
    }

    // configure pcap for maximum responsiveness
    if (pcap_setmintocopy(edrvInstance_l.pPcap, 0) != 0)
    {
        DEBUG_LVL_ERROR_TRACE("pcap_setmintocopy failed\n");
    }

    // Initialize critical section
    InitializeCriticalSection(&edrvInstance_l.criticalSection);

    // Create the thread to begin execution on its own.
    edrvInstance_l.hThread = CreateThread(NULL, 0, edrvWorkerThread, &edrvInstance_l, 0, &threadId);
    if (edrvInstance_l.hThread == NULL)
        return kErrorEdrvInit;

    return kErrorOk;
}