Пример #1
0
bool DefaultRoute(int32_t *if_index, IPV4Address *default_gateway) {
  *default_gateway = IPV4Address();
  *if_index = Interface::DEFAULT_INDEX;
#ifdef USE_SYSCTL_FOR_DEFAULT_ROUTE
  return GetDefaultRouteWithSysctl(if_index, default_gateway);
#elif defined(USE_NETLINK_FOR_DEFAULT_ROUTE)
  return GetDefaultRouteWithNetlink(if_index, default_gateway);
#elif defined(_WIN32)
  ULONG size = 4096;
  PMIB_IPFORWARDTABLE forward_table =
      reinterpret_cast<PMIB_IPFORWARDTABLE>(malloc(size));
  DWORD result = GetIpForwardTable(forward_table, &size, TRUE);
  if (result == NO_ERROR) {
    for (unsigned int i = 0; i < forward_table->dwNumEntries; ++i) {
      if (forward_table->table[i].dwForwardDest == 0) {
        *default_gateway =
            IPV4Address(forward_table->table[i].dwForwardNextHop);
        *if_index = forward_table->table[i].dwForwardIfIndex;
      }
    }
    free(forward_table);
    return true;
  } else {
    OLA_WARN << "GetIpForwardTable failed with " << GetLastError();
    return false;
  }
#else
#error "DefaultRoute not implemented for this platform, please report this."
  // TODO(Peter): Do something else on machines without Netlink
  // No Netlink, can't do anything
  return false;
#endif
}
Пример #2
0
bool IPV4Address::FromString(const std::string &address, IPV4Address *target) {
  struct in_addr addr;
  if (!StringToAddress(address, addr))
    return false;
  *target = IPV4Address(addr);
  return true;
}
Пример #3
0
/**
 * Try to extract an AF_INET address from a sockaddr. If successful, sa points
 * to the next sockaddr and true is returned.
 */
bool ExtractIPV4AddressFromSockAddr(const uint8_t **data,
                                    IPV4Address *ip) {
  const struct sockaddr *sa = reinterpret_cast<const struct sockaddr*>(*data);
  if (sa->sa_family != AF_INET) {
    return false;
  }

  *ip = IPV4Address(
      reinterpret_cast<const struct sockaddr_in*>(*data)->sin_addr.s_addr);
  *data += SockAddrLen(*sa);
  return true;
}
Пример #4
0
		virtual void receive(IPV4Address& source)
		{
			unsigned char buf[4096];
			sockaddr_in addr;
			socklen_t addrLen = sizeof(addr);
			ssize_t recvCount = recvfrom(fd, buf, 4096, 0, (struct sockaddr *)&addr, &addrLen);
			if (recvCount <= 0)
				fail(DashelException::ConnectionLost, errno, "UDP Socket read I/O error.");
			
			receptionBuffer.resize(recvCount);
			std::copy(buf, buf+recvCount, receptionBuffer.begin());
			
			source = IPV4Address(ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port));
		}
Пример #5
0
/**
 * Handle a netlink message. If this message is a routing table message and it
 * contains the default route, then either:
 *   i) default_gateway is updated with the address of the gateway.
 *   ii) if_index is updated with the interface index for the default route.
 * @param if_index[out] possibly updated with interface index for the default
 *   route.
 * @param default_gateway[out] possibly updated with the default gateway.
 * @param nl_hdr the netlink message.
 */
void MessageHandler(int32_t *if_index,
                    IPV4Address *default_gateway,
                    const struct nlmsghdr *nl_hdr) {
  // Unless RTA_DST is provided, an RTA_GATEWAY or RTA_OIF attribute implies
  // it's the default route.
  IPV4Address gateway;
  int32_t index = Interface::DEFAULT_INDEX;

  bool is_default_route = true;

  // Loop over the attributes looking for RTA_GATEWAY and/or RTA_DST
  const rtmsg *rt_msg = reinterpret_cast<const rtmsg*>(NLMSG_DATA(nl_hdr));
  if (rt_msg->rtm_family == AF_INET && rt_msg->rtm_table == RT_TABLE_MAIN) {
    int rt_len = RTM_PAYLOAD(nl_hdr);

    for (const rtattr* rt_attr = reinterpret_cast<const rtattr*>(
            RTM_RTA(rt_msg));
         RTA_OK(rt_attr, rt_len);
         rt_attr = RTA_NEXT(rt_attr, rt_len)) {
      switch (rt_attr->rta_type) {
        case RTA_OIF:
          index = *(reinterpret_cast<int32_t*>(RTA_DATA(rt_attr)));
          break;
        case RTA_GATEWAY:
          gateway = IPV4Address(
              reinterpret_cast<const in_addr*>(RTA_DATA(rt_attr))->s_addr);
          break;
        case RTA_DST:
          IPV4Address dest(
              reinterpret_cast<const in_addr*>(RTA_DATA(rt_attr))->s_addr);
          is_default_route = dest.IsWildcard();
          break;
      }
    }
  }

  if (is_default_route &&
      (!gateway.IsWildcard() || index != Interface::DEFAULT_INDEX)) {
    *default_gateway = gateway;
    *if_index = index;
  }
}
Пример #6
0
	bool Hub::step(const int timeout)
	{
		bool firstPoll = true;
		bool wasActivity = false;
		bool runInterrupted = false;
		
		pthread_mutex_lock((pthread_mutex_t*)streamsLock);
		
		do
		{
			wasActivity = false;
			size_t streamsCount = streams.size();
			valarray<struct pollfd> pollFdsArray(streamsCount+1);
			valarray<SelectableStream*> streamsArray(streamsCount);
			
			// add streams
			size_t i = 0;
			for (StreamsSet::iterator it = streams.begin(); it != streams.end(); ++it)
			{
				SelectableStream* stream = polymorphic_downcast<SelectableStream*>(*it);
				
				streamsArray[i] = stream;
				pollFdsArray[i].fd = stream->fd;
				pollFdsArray[i].events = 0;
				if ((!stream->failed()) && (!stream->writeOnly))
					pollFdsArray[i].events |= stream->pollEvent;
				
				i++;
			}
			// add pipe
			int *terminationPipes = (int*)hTerminate;
			pollFdsArray[i].fd = terminationPipes[0];
			pollFdsArray[i].events = POLLIN;
			
			// do poll and check for error
			int thisPollTimeout = firstPoll ? timeout : 0;
			firstPoll = false;
			
			pthread_mutex_unlock((pthread_mutex_t*)streamsLock);
			
			#ifndef USE_POLL_EMU
			int ret = poll(&pollFdsArray[0], pollFdsArray.size(), thisPollTimeout);
			#else
			int ret = poll_emu(&pollFdsArray[0], pollFdsArray.size(), thisPollTimeout);
			#endif
			if (ret < 0)
				throw DashelException(DashelException::SyncError, errno, "Error during poll.");
			
			pthread_mutex_lock((pthread_mutex_t*)streamsLock);
			
			// check streams for errors
			for (i = 0; i < streamsCount; i++)
			{
				SelectableStream* stream = streamsArray[i];
				
				// make sure we do not try to handle removed streams
				if (streams.find(stream) == streams.end())
					continue;
				
				assert((pollFdsArray[i].revents & POLLNVAL) == 0);
				
				if (pollFdsArray[i].revents & POLLERR)
				{
					//std::cerr << "POLLERR" << std::endl;
					wasActivity = true;
					
					try
					{
						stream->fail(DashelException::SyncError, 0, "Error on stream during poll.");
					}
					catch (DashelException e)
					{
						assert(e.stream);
					}
					
					try
					{
						connectionClosed(stream, true);
					}
					catch (DashelException e)
					{
						assert(e.stream);
					}
					
					closeStream(stream);
				}
				else if (pollFdsArray[i].revents & POLLHUP)
				{
					//std::cerr << "POLLHUP" << std::endl;
					wasActivity = true;
					
					try
					{
						connectionClosed(stream, false);
					}
					catch (DashelException e)
					{
						assert(e.stream);
					}
					
					closeStream(stream);
				}
				else if (pollFdsArray[i].revents & stream->pollEvent)
				{
					//std::cerr << "POLLIN" << std::endl;
					wasActivity = true;
					
					// test if listen stream
					SocketServerStream* serverStream = dynamic_cast<SocketServerStream*>(stream);
					
					if (serverStream)
					{	
						// accept connection
						struct sockaddr_in targetAddr;
						socklen_t l = sizeof (targetAddr);
						int targetFD = accept (stream->fd, (struct sockaddr *)&targetAddr, &l);
						if (targetFD < 0)
						{
							pthread_mutex_unlock((pthread_mutex_t*)streamsLock);
							throw DashelException(DashelException::SyncError, errno, "Cannot accept new stream.");
						}
						
						// create a target stream using the new file descriptor from accept
						ostringstream targetName;
						targetName << IPV4Address(ntohl(targetAddr.sin_addr.s_addr), ntohs(targetAddr.sin_port)).format(resolveIncomingNames);
						targetName << ";connectionPort=";
						targetName << atoi(serverStream->getTargetParameter("port").c_str());
						targetName << ";sock=";
						targetName << targetFD;
						connect(targetName.str());
					}
					else
					{
						bool streamClosed = false;
						try
						{
							if (stream->receiveDataAndCheckDisconnection())
							{
								//std::cerr << "connection closed" << std::endl;
								connectionClosed(stream, false);
								streamClosed = true;
							}
							else
							{
								// read all data available on this socket
								while (stream->isDataInRecvBuffer())
									incomingData(stream);
								//std::cerr << "incoming data" << std::endl;
							}
						}
						catch (DashelException e)
						{
							//std::cerr << "exception on POLLIN" << std::endl;
							assert(e.stream);
						}
						
						if (streamClosed)
							closeStream(stream);
					}
				}
			}
			// check pipe for termination
			if (pollFdsArray[i].revents)
			{
				char c;
				const ssize_t ret = read(pollFdsArray[i].fd, &c, 1);
				if (ret != 1)
					abort(); // poll did notify us that there was something to read, but we did not read anything, this is a bug
				runInterrupted = true;
			}
			
			// collect and remove all failed streams
			vector<Stream*> failedStreams;
			for (StreamsSet::iterator it = streams.begin(); it != streams.end();++it)
				if ((*it)->failed())
					failedStreams.push_back(*it);
			
			for (size_t i = 0; i < failedStreams.size(); i++)
			{
				Stream* stream = failedStreams[i];
				if (streams.find(stream) == streams.end())
					continue;
				if (stream->failed())
				{
					try
					{
						connectionClosed(stream, true);
					}
					catch (DashelException e)
					{
						assert(e.stream);
					}
					closeStream(stream);
				}
			}
		}
		while (wasActivity && !runInterrupted);
		
		pthread_mutex_unlock((pthread_mutex_t*)streamsLock);
		
		return !runInterrupted;
	}
Пример #7
0
bool NameServers(vector<IPV4Address> *name_servers) {
#if HAVE_DECL_RES_NINIT
  struct __res_state res;
  memset(&res, 0, sizeof(struct __res_state));

  // Init the resolver info each time so it's always current for the RDM
  // responders in case we've set it via RDM too
  if (res_ninit(&res) != 0) {
    OLA_WARN << "Error getting nameservers via res_ninit";
    return false;
  }

  for (int32_t i = 0; i < res.nscount; i++) {
    IPV4Address addr = IPV4Address(res.nsaddr_list[i].sin_addr.s_addr);
    OLA_DEBUG << "Found Nameserver " << i << ": " << addr;
    name_servers->push_back(addr);
  }

  res_nclose(&res);
#elif defined(_WIN32)
  ULONG size = sizeof(FIXED_INFO);
  PFIXED_INFO fixed_info = NULL;
  while (1) {
    fixed_info = reinterpret_cast<PFIXED_INFO>(new uint8_t[size]);
    DWORD result = GetNetworkParams(fixed_info, &size);
    if (result == ERROR_SUCCESS) {
      break;
    }

    if (result != ERROR_BUFFER_OVERFLOW) {
      OLA_WARN << "GetNetworkParams failed with: " << GetLastError();
      return false;
    }

    delete[] fixed_info;
  }

  IP_ADDR_STRING* addr = &(fixed_info->DnsServerList);
  for (; addr; addr = addr->Next) {
    IPV4Address ipv4addr = IPV4Address(inet_addr(addr->IpAddress.String));
    OLA_DEBUG << "Found nameserver: " << ipv4addr;
    name_servers->push_back(ipv4addr);
  }

  delete[] fixed_info;
#else
  // Init the resolver info each time so it's always current for the RDM
  // responders in case we've set it via RDM too
  if (res_init() != 0) {
    OLA_WARN << "Error getting nameservers via res_init";
    return false;
  }

  for (int32_t i = 0; i < _res.nscount; i++) {
    IPV4Address addr = IPV4Address(_res.nsaddr_list[i].sin_addr.s_addr);
    OLA_DEBUG << "Found Nameserver " << i << ": " << addr;
    name_servers->push_back(addr);
  }
#endif

  return true;
}