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 }
bool IPV4Address::FromString(const std::string &address, IPV4Address *target) { struct in_addr addr; if (!StringToAddress(address, addr)) return false; *target = IPV4Address(addr); return true; }
/** * 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; }
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)); }
/** * 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; } }
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; }
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; }