Beispiel #1
0
/**
 * Disconnects all adapters
 */
static void disconnect_all_adapters()
{
	adapter_object *a;

	while (adapters()->first) {
		a = adapters()->first->element;
		disconnect_adapter(a->path);
	}

	llist_destroy(adapters(), NULL);
	_adapters = NULL;
}
Beispiel #2
0
/**
 * Remove adapter path from list
 */
static void remove_adapter(const char *path)
{
	adapter_object *a = get_adapter(path);

	if (a) {
		g_free(a->path);
		g_object_unref(a->proxy);
		g_free(a);
		llist_remove(adapters(), a);
	}
}
Beispiel #3
0
/**
 * Add adapter to list
 */
static void add_adapter(const char *path, DBusGProxy *proxy)
{
	adapter_object *a;

	if (get_adapter(path))
		remove_adapter(path);

	a = (adapter_object *) g_new(adapter_object, 1);
	a->path = g_strdup(path);
	a->proxy = proxy;

	llist_add(adapters(), a);
}
Beispiel #4
0
QueryData genInterfaceAddresses(QueryContext& context) {
  QueryData results;

  DWORD buffSize = kWorkingBufferSize;
  auto alloc_attempts = 0;
  size_t alloc_result = 0;
  const auto addrFamily = AF_UNSPEC;
  const auto addrFlags =
      GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST;
  std::unique_ptr<IP_ADAPTER_ADDRESSES> adapters(nullptr);

  // Buffer size can change between the query and malloc (if adapters are
  // added/removed), so shenanigans are required
  do {
    adapters.reset(static_cast<PIP_ADAPTER_ADDRESSES>(malloc(buffSize)));
    if (adapters == nullptr) {
      return results;
    }
    alloc_result = GetAdaptersAddresses(
        addrFamily, addrFlags, nullptr, adapters.get(), &buffSize);
    alloc_attempts++;
  } while (alloc_result == ERROR_BUFFER_OVERFLOW &&
           alloc_attempts < kMaxBufferAllocRetries);
  if (alloc_result != NO_ERROR) {
    return results;
  }

  const IP_ADAPTER_ADDRESSES* currAdapter = adapters.get();
  while (currAdapter != nullptr) {
    std::wstring wsAdapterName = std::wstring(currAdapter->FriendlyName);
    auto adapterName = std::string(wsAdapterName.begin(), wsAdapterName.end());

    const IP_ADAPTER_UNICAST_ADDRESS* ipaddr = currAdapter->FirstUnicastAddress;
    while (ipaddr != nullptr) {
      Row r;
      r["interface"] = SQL_TEXT(currAdapter->IfIndex);
      r["friendly_name"] = adapterName;
      genInterfaceAddress(ipaddr, r);
      ipaddr = ipaddr->Next;
      results.push_back(r);
    }
    currAdapter = currAdapter->Next;
  }
  return results;
}
void GFXInit::init()
{
   // init only once.
   static bool doneOnce = false;
   if(doneOnce)
      return;
   doneOnce = true;
   
   Con::printf( "GFX Init:" );

   //find our adapters
   Vector<GFXAdapter*> adapters( __FILE__, __LINE__ );
   GFXInit::enumerateAdapters();
   GFXInit::getAdapters(&adapters);

   if(!adapters.size())
       Con::errorf("Could not find a display adapter");

   //loop through and tell the user what kind of adapters we found
   _GFXInitReportAdapters(adapters);
   Con::printf( "" );
}
Beispiel #6
0
QueryData genInterfaceDetails(QueryContext& context) {
  QueryData results;

  DWORD buffSize = kWorkingBufferSize;
  auto alloc_attempts = 0;
  size_t alloc_result = 0;
  const auto addrFamily = AF_UNSPEC;
  const auto addrFlags =
      GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST;
  std::unique_ptr<IP_ADAPTER_ADDRESSES> adapters(nullptr);

  // Buffer size can change between the query and malloc (if adapters are
  // added/removed), so shenanigans are required
  do {
    adapters.reset(static_cast<PIP_ADAPTER_ADDRESSES>(malloc(buffSize)));
    if (adapters == nullptr) {
      return results;
    }
    alloc_result = GetAdaptersAddresses(
        addrFamily, addrFlags, nullptr, adapters.get(), &buffSize);
    alloc_attempts++;
  } while (alloc_result == ERROR_BUFFER_OVERFLOW &&
           alloc_attempts < kMaxBufferAllocRetries);
  if (alloc_result != NO_ERROR) {
    return results;
  }

  const IP_ADAPTER_ADDRESSES* currAdapter = adapters.get();
  while (currAdapter != nullptr) {
    Row r;
    genInterfaceDetail(currAdapter, r);
    currAdapter = currAdapter->Next;
    results.push_back(r);
  }
  return results;
}
Beispiel #7
0
/**
 * Fetch adapter struct from list
 */
static adapter_object *get_adapter(const char *path)
{
	return (adapter_object *) llist_search_first(adapters(), (void *) path, cmp_adapter);
}
Beispiel #8
0
// 1419 is the mtu using a 1500 byte ethernet mtu - ipv4 header - udp - dtls with default ciphersuite (I think)
// TODO: read mtu from interface on each OS instead of hard coding 1419 (also have installer set sensible interface MTU)
tuntap::tuntap() : mtu(1419)
{
// TODO: use configuration parameters for registry key names instead of hard coded values
// TODO: package TAP-Windows and change component ID or otherwise figure out how to make it not collide with what OpenVPN uses
	// see comment in %PROGRAMFILES%\TAP-Windows\driver\OemWin2k.inf after installing OpenVPN TAP driver
#ifdef WINDOWS
	sent_sync = true; // no async send in progress
	received_sync = 0;
	memset(&recv_overlapped, 0, sizeof(OVERLAPPED));
	memset(&send_overlapped, 0, sizeof(OVERLAPPED));
	recv_event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
	if(recv_event == INVALID_HANDLE_VALUE)
		throw check_err_exception("CreateEvent failed for tuntap recv_event");
	recv_overlapped.hEvent = recv_event;
	// default callback emits error
	read_ready_cb = []() { eout() << "BUG: tuntap read ready callback called but not set"; };
	if(RegisterWaitForSingleObject(&recv_wait, recv_event, &tuntap::read_event_cb, this, INFINITE, WT_EXECUTEINWAITTHREAD) == FALSE)
		throw check_err_exception("RegisterWaitForSingleObject on tuntap read event");
	adapter_GUID = snow::conf[snow::VIRTUAL_INTERFACE];
	if(adapter_GUID == "auto") {
		try {
			// open registry key for all network adapters
			registry_key adapters(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", KEY_READ);
			for(auto &it : adapters.subkeys()) {
				try {
					registry_key adapter = it.get(KEY_READ);
					// TODO: change ComponentId from "tap0901" to some other string to remove possible namespace collision with OpenVPN (this has to occur in the driver too)
					if(adapter.values().get_value_string("ComponentId") == "tap0901") {
						adapter_GUID = adapter.values().get_value_string("NetCfgInstanceId");
						break;
					}
				} catch(const registry_exception &re) {
					dout() << "Failed to access registry subkey: " << re;
				}
				
			}
		} catch (const registry_exception &re) {
			eout() << "FATAL: Failed to open network adapters registry key, cannot determine TUN adapter to use: " << re;
			throw;
		}
	}
	dout() << "Adapter GUID: " << adapter_GUID;
	if(adapter_GUID == "auto")
		throw e_not_found("no usable tuntap interface");
	// [at this point GUID is value of NetCfgInstanceId, although there could be more than one interface: check all against something else? (interface name?)]
	// TODO: probably the thing to do is: on install, create a TAP-Windows interface and set its name to 'snow tunnel interface' or so,
		// then set the GUID in the configuration file [or registry setting], and GUI config program can list interfaces by name and allow user to choose
		// then the configured GUID is the interface we use and all of this mess doesn't even need to go here -- it just goes once on install and in the config editor
		// what would then really be useful would be a way (other than changing the ComponentId) to tell other software (e.g. OpenVPN) not to use a particular interface
			// two possible solutions may be to either make sure that snow starts before the other service [somehow] and gets there first,
			// or setting permissions [somehow] so that only snow process has access
	std::string tap_filename("\\\\.\\Global\\");
	tap_filename += adapter_GUID + ".tap";
	fd = CreateFile(tap_filename.c_str(), GENERIC_READ | GENERIC_WRITE, 0/*no shared access*/, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, nullptr);
	if(fd == INVALID_HANDLE_VALUE)
		throw check_err_exception("Failed to open Windows TUN/TAP device");
	// name of specific instance of adapter as shown in control panel can be found in:
		// "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\" + adapter_GUID + "\\Connection"
		// value is "Name"
	
	// set to TUN mode
	// TAP_WIN_IOCTL_CONFIG_TUN takes three args: interface IP addr, network addr and netmask
	if_info ifinfo = get_if_info();
	uint32_t tun_addrs[3] = { ifinfo.if_addr, ifinfo.if_addr & ifinfo.netmask, ifinfo.netmask };
	DWORD rsize;
	if(DeviceIoControl(fd, TAP_WINDOWS_IOCTL_CONFIG_TUN, tun_addrs, sizeof(tun_addrs), tun_addrs, sizeof(tun_addrs), &rsize, nullptr))
		dout() << "TAP-Windows CONFIG_TUN success: " << ss_ipaddr(tun_addrs[0]) << " " << ss_ipaddr(tun_addrs[1]) << " " << ss_ipaddr(tun_addrs[2]);
	else
		eout() << "TAP-Windows CONFIG_TUN FAIL: " << ss_ipaddr(tun_addrs[0]) << " " << ss_ipaddr(tun_addrs[1]) << " " << ss_ipaddr(tun_addrs[2]);

	// set media status as connected
	ULONG connected = TRUE;
	if(DeviceIoControl(fd, TAP_WINDOWS_IOCTL_SET_MEDIA_STATUS, &connected, sizeof(connected), &connected, sizeof(connected), &rsize, nullptr) == FALSE)
		wout() << "Failed to set TAP-Windows media status to connected";
	ULONG ifmtu;
	if(DeviceIoControl(fd, TAP_WINDOWS_IOCTL_GET_MTU, &ifmtu, sizeof(ifmtu), &ifmtu, sizeof(ifmtu), &rsize, nullptr)) {
		dout() << "Read mtu from TAP-Windows interface: " << ifmtu;
		if(ifmtu > MIN_PMTU)
			mtu = ifmtu;
	} else {
		wout() << "Failed to get Tap-Windows MTU, assuming default";
	}
	
	// [flush ARP cache? -> probably unnecessary with tun, but maybe do it anyway? certainly don't want invalid ARP cache entries for pool addrs from before interface startup]
	
	// ... also (may) need to undo whatever configuration (remove addrs from if, routes, etc.) on destruction, CloseHandle on fd, set media status to disconnected, etc.

#else
	check_err((fd = open(snow::conf[snow::CLONE_DEVICE].c_str(), O_RDWR)), "opening tun/tap clone device");
	ifreq ifr;
	memset(&ifr, 0, sizeof(ifr));
	// check size manually instead of using strncpy: strncpy fails silently and doesn't null terminate if there is insufficient space
	if(snow::conf[snow::VIRTUAL_INTERFACE].size() >= IFNAMSIZ)
		throw check_err_exception("VIRTUAL_INTERFACE name is too long", false);
	strcpy(ifr.ifr_name, snow::conf[snow::VIRTUAL_INTERFACE].c_str());
	check_err(fcntl(fd, F_SETFL, O_NONBLOCK), "setting tuntap socket to non-blocking");
#ifdef __linux__
	ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
	check_err(ioctl(fd, TUNSETIFF, (void*) &ifr), "opening tun/tap interface");
#endif
	// note: Mac and BSD require a stupid hack to make tun behave properly because they insist on a single destination address being specified
		// solution is to exclude an address from the address pool and specify it as the destination when configuring the interface
		// then set a route specifying that address as the gateway for the entire snow subnet so OS will send them all to the tun interface
	// TODO: write code to do that programmatically for Mac/BSD
		// existing code seems to work on BSD if you set CLONE_DEVICE to e.g. /dev/tun0 and VIRTUAL_INTERFACE to e.g. tun0 and configure the tun interface manually, e.g.:
		// # ifconfig tun0 create 172.16.0.1 netmask 255.240.0.0 172.31.255.254 mtu 1419
		// # route add -net 172.16.0.0 172.31.255.254 255.240.0.0
		// (note: this must be done each time you start the daemon, when the daemon exits the interface remains but configuration is forgotten; same two commands w/o "create")
		// (note: 'ifconfig tun create' will create next tun# necessary, see if there is any simple way to replicate with API)
		// doing this programmatically requires call to ioctl passing SIOCSIFPHYADDR with in_aliasreq struct as follows:
			// ifra_name = "tun[#]"
			// ifra_addr as local interface addr
			// ifra_dstaddr as fake addr
			// ifra_mask as subnet mask
		// and then adding the route via some call to the BSD routing API
	csocket sock(AF_INET, SOCK_DGRAM); // need ordinary socket for SIOC[GS]*, can't use tun fd
	check_err(ioctl(sock.fd(), SIOCGIFFLAGS, (void*) &ifr), "getting tuntap interface flags");
	if((ifr.ifr_flags & IFF_UP) == 0) {
		dout() << "tuntap interface was not up, trying to bring it up";
		ifr.ifr_flags |= IFF_UP; // make sure interface is up
		check_err(ioctl(sock.fd(), SIOCSIFFLAGS, (void*) &ifr), "setting tuntap interface flags");
	} else {
		dout() << "tuntap interface was up";
	}
	// there are two possible ways of doing this which are both supported: either snow launches as root or with CAP_NET_ADMIN and sets these here,
		// or the interface is persistent and configured ahead of time, in which case only ownership of the interface is necessary
	// so what we do is check that everything is configured correctly and try to fix it if it isn't
	// that way everything is fine as long as the interface is correctly preconfigured -or- it isn't but we have rights to fix it
	in_addr addr, netmask;
	inet_pton(AF_INET, snow::conf[snow::NATPOOL_NETWORK].c_str(), &addr.s_addr);
	addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
	netmask.s_addr = ~htonl((1 << (32 - snow::conf[snow::NATPOOL_NETMASK_BITS])) - 1);
	ifr.ifr_addr.sa_family = AF_INET;
	// EADDRNOTAVAIL is returned if no address is assigned which just means we have to assign the address, so then ifr_addr will be zero and not match addr
	int rv = ioctl(sock.fd(), SIOCGIFADDR, &ifr);
	if(rv < 0 && errno != EADDRNOTAVAIL)
		throw check_err_exception("getting tun/tap interface IP address");
	sockaddrunion su;
	su.s = ifr.ifr_addr;
	dout() << "Got tuntap ifaddr " << ss_ipaddr(su.sa.sin_addr.s_addr);
	if(su.sa.sin_addr.s_addr != addr.s_addr) {
		dout() << "Virtual interface IP addr was " << ss_ipaddr(su.sa.sin_addr.s_addr) << ", should be " << ss_ipaddr(addr.s_addr) << ", trying to fix";
		su.sa.sin_addr = addr;
		ifr.ifr_addr = su.s;
		check_err(ioctl(sock.fd(), SIOCSIFADDR, &ifr), "setting tun/tap interface IP address");
	}
	check_err(ioctl(sock.fd(), SIOCGIFNETMASK, &ifr), "getting tun/tap interface netmask");
	su.s = ifr.ifr_addr;
	dout() << "Got tuntap netmask " << ss_ipaddr(su.sa.sin_addr.s_addr);
	if(su.sa.sin_addr.s_addr != netmask.s_addr) {
		dout() << "Virtual interface netmask was " << ss_ipaddr(su.sa.sin_addr.s_addr) << ", should be " << ss_ipaddr(netmask.s_addr) << ", trying to fix";
		su.sa.sin_addr = netmask;
		ifr.ifr_addr = su.s;
		check_err(ioctl(sock.fd(),  SIOCSIFNETMASK, &ifr), "setting tun/tap interface netmask");
	}
	mtu = snow::conf[snow::VIRTUAL_INTERFACE_MTU];
	check_err(ioctl(sock.fd(), SIOCGIFMTU, (void*) &ifr), "getting tun/tap interface MTU");
	dout() << "Existing tuntap interface MTU: " << ifr.ifr_mtu;
	if(ifr.ifr_mtu <  MIN_PMTU || mtu != static_cast<unsigned>(ifr.ifr_mtu)) {
		dout() << "Virtual interface mtu was " << ifr.ifr_mtu << ", should be " << mtu << ", trying to fix";
		ifr.ifr_mtu = mtu;
		check_err(ioctl(sock.fd(), SIOCSIFMTU, (void*) &ifr), "setting tun/tap interface MTU");
	}
	iout() << "Virtual interface configured with network " << ss_ipaddr(addr.s_addr&netmask.s_addr) << " netmask " << ss_ipaddr(netmask.s_addr) <<  " address " << ss_ipaddr(addr.s_addr) << " MTU " << mtu;	
#endif
}