Beispiel #1
0
static int nethogsmonitor_init() {
  process_init();

  device *devices = get_default_devices();
  if (devices == NULL) {
    std::cerr << "No devices to monitor" << std::endl;
    return NETHOGS_STATUS_NO_DEVICE;
  }

  device *current_dev = devices;

  bool promiscuous = false;

  int nb_devices = 0;
  int nb_failed_devices = 0;

  while (current_dev != NULL) {
    ++nb_devices;

    if (!getLocal(current_dev->name, false)) {
      std::cerr << "getifaddrs failed while establishing local IP."
                << std::endl;
      ++nb_failed_devices;
      continue;
    }

    char errbuf[PCAP_ERRBUF_SIZE];
    dp_handle *newhandle =
        dp_open_live(current_dev->name, BUFSIZ, promiscuous, 100, errbuf);
    if (newhandle != NULL) {
      dp_addcb(newhandle, dp_packet_ip, process_ip);
      dp_addcb(newhandle, dp_packet_ip6, process_ip6);
      dp_addcb(newhandle, dp_packet_tcp, process_tcp);
      dp_addcb(newhandle, dp_packet_udp, process_udp);

      /* The following code solves sf.net bug 1019381, but is only available
       * in newer versions (from 0.8 it seems) of libpcap
       *
       * update: version 0.7.2, which is in debian stable now, should be ok
       * also.
       */
      if (dp_setnonblock(newhandle, 1, errbuf) == -1) {
        fprintf(stderr, "Error putting libpcap in nonblocking mode\n");
      }
      handles = new handle(newhandle, current_dev->name, handles);

      if (pc_loop_use_select) {
        // some devices may not support pcap_get_selectable_fd
        int const fd = pcap_get_selectable_fd(newhandle->pcap_handle);
        if (fd != -1) {
          pc_loop_fd_list.push_back(fd);
        } else {
          pc_loop_use_select = false;
          pc_loop_fd_list.clear();
          fprintf(stderr, "failed to get selectable_fd for %s\n",
                  current_dev->name);
        }
      }
    } else {
      fprintf(stderr, "ERROR: opening handler for device %s: %s\n",
              current_dev->name, strerror(errno));
      ++nb_failed_devices;
    }

    current_dev = current_dev->next;
  }

  if (nb_devices == nb_failed_devices) {
    return NETHOGS_STATUS_FAILURE;
  }

  // use the Self-Pipe trick to interrupt the select() in the main loop
  if (pc_loop_use_select) {
    self_pipe = create_self_pipe();
    if (self_pipe.first == -1 || self_pipe.second == -1) {
      std::cerr << "Error creating pipe file descriptors\n";
      pc_loop_use_select = false;
    } else {
      pc_loop_fd_list.push_back(self_pipe.first);
    }
  }

  return NETHOGS_STATUS_OK;
}
Beispiel #2
0
int main (int argc, char** argv)
{
	process_init();

	device * devices = NULL;
	//dp_link_type linktype = dp_link_ethernet;
	int promisc = 0;

	int opt;
	while ((opt = getopt(argc, argv, "Vhbtpd:v:c:s")) != -1) {
		switch(opt) {
			case 'V':
				versiondisplay();
				exit(0);
			case 'h':
				help(false);
				exit(0);
			case 'b':
				bughuntmode = true;
				tracemode = true;
				break;
			case 't':
				tracemode = true;
				break;
			case 'p':
				promisc = 1;
				break;
			case 's':
				sortRecv = false;
				break;
			case 'd':
				refreshdelay = atoi(optarg);
				break;
			case 'v':
				viewMode = atoi(optarg) % VIEWMODE_COUNT;
				break;
			case 'c':
				refreshlimit = atoi(optarg);
				break;
			/*
			case 'f':
				argv++;
				if (strcmp (optarg, "ppp") == 0)
					linktype = dp_link_ppp;
				else if (strcmp (optarg, "eth") == 0)
					linktype = dp_link_ethernet;
				}
				break;
			*/
			default:
				help(true);
				exit(EXIT_FAILURE);
		}
	}

	while (optind < argc) {
		devices = new device (strdup(argv[optind++]), devices);
	}

	if (devices == NULL)
	{
		devices = get_default_devices();
        if ( devices == NULL )
        {
            std::cerr << "Not devices to monitor" << std::endl;
            return 0;
        }
	}

	if ((!tracemode) && (!DEBUG)){
		init_ui();
	}
	
	if (NEEDROOT && (geteuid() != 0))
		forceExit(false, "You need to be root to run NetHogs!");
		
	//use the Self-Pipe trick to interrupt the select() in the main loop
	self_pipe = create_self_pipe();
	if( self_pipe.first == -1 || self_pipe.second == -1 )
	{
		forceExit(false, "Error creating pipe file descriptors\n");
	}
	else
	{
		//add the self-pipe to allow interrupting select()
		pc_loop_fd_list.push_back(self_pipe.first);
	}

	char errbuf[PCAP_ERRBUF_SIZE];

	handle * handles = NULL;
	device * current_dev = devices;
	while (current_dev != NULL) {
		getLocal(current_dev->name, tracemode);

		dp_handle * newhandle = dp_open_live(current_dev->name, BUFSIZ, promisc, 100, errbuf);
		if (newhandle != NULL)
		{
			dp_addcb (newhandle, dp_packet_ip, process_ip);
			dp_addcb (newhandle, dp_packet_ip6, process_ip6);
			dp_addcb (newhandle, dp_packet_tcp, process_tcp);
			dp_addcb (newhandle, dp_packet_udp, process_udp);

			/* The following code solves sf.net bug 1019381, but is only available
			 * in newer versions (from 0.8 it seems) of libpcap
			 *
			 * update: version 0.7.2, which is in debian stable now, should be ok
			 * also.
			 */
			if (dp_setnonblock (newhandle, 1, errbuf) == -1)
			{
				fprintf(stderr, "Error putting libpcap in nonblocking mode\n");
			}
			handles = new handle (newhandle, current_dev->name, handles);
			
			if( pc_loop_use_select )
			{
				//some devices may not support pcap_get_selectable_fd
				int const fd = pcap_get_selectable_fd(newhandle->pcap_handle);
				if( fd != -1 )
				{
					pc_loop_fd_list.push_back(fd);
				}
				else
				{
					pc_loop_use_select = false;
					pc_loop_fd_list.clear();
					fprintf(stderr, "failed to get selectable_fd for %s\n", current_dev->name);
				}
			}			
		}
		else
		{
			fprintf(stderr, "Error opening handler for device %s\n", current_dev->name);
		}

		current_dev = current_dev->next;
	}

	signal (SIGINT, &quit_cb);

	fprintf(stderr, "Waiting for first packet to arrive (see sourceforge.net bug 1019381)\n");
	struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs));

	// Main loop:
	//
	//  Walks though the 'handles' list, which contains handles opened in non-blocking mode.
	//  This causes the CPU utilisation to go up to 100%. This is tricky:
	while (1)
	{
		bool packets_read = false;

		handle * current_handle = handles;
		while (current_handle != NULL)
		{
			userdata->device = current_handle->devicename;
			userdata->sa_family = AF_UNSPEC;
			int retval = dp_dispatch (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs));
			if (retval < 0)
			{
				std::cerr << "Error dispatching: " << retval << std::endl;
			}
			else if (retval != 0)
			{
				packets_read = true;
			}
			current_handle = current_handle->next;
		}

		time_t const now = ::time(NULL);
 		if( last_refresh_time + refreshdelay <= now )
 		{
 			last_refresh_time = now;
 			if ((!DEBUG)&&(!tracemode))
			{
				// handle user input
				ui_tick();
			}
			do_refresh();
		}
 
		//if not packets, do a select() until next packet
		if (!packets_read)
		{
			if( !wait_for_next_trigger() )
			{
				//Exit the loop
				break;
			}
		}
	}
	
	//clean up
	clean_up();
}