Esempio n. 1
0
bool Discovery::processMessage(const NodeAddr& remote, const char *message, std::vector<NodeDevice> &newNodes)
{
	bool sendNow = false;
	std::string act((const char*)message);
	NodeDevice nd(remote);
	nd.name = std::string((const char*)&message[act.length() + 1]);
	nd.id = std::string((const char*)&message[act.length() + nd.name.length() + 2]);
	nd.sinceVitalSign = 0;

	// check if we somehow received our own broadcast
	if (nd.id == getHwAddress()) {
		return false;
	}

	if ("ULLTRA_DEV_R" == act) { // register
		auto ex = m_discovered.find(nd.id);
		if (ex != m_discovered.end()) { // already there?
			ex->second.sinceVitalSign = 0;
			return false;
		}

		LOG(logINFO) << "Discovered node " << nd;
		m_discovered.insert(std::pair<std::string, NodeDevice>(nd.id, nd));
		send("ULLTRA_DEV_R", nd); // send a discovery message back
		sendNow = true;
		newNodes.push_back(m_discovered.find(nd.id)->second);
	}
	else if ("ULLTRA_DEV_Z" == act) { // unregister
		auto it = m_discovered.find(nd.id);
		if (it != m_discovered.end()) {
			LOG(logINFO) << "Lost node " << nd;
			if (onNodeLost)
				onNodeLost(it->second);
			m_discovered.erase(m_discovered.find(nd.id));
			sendNow = true;
		}
	}
	else if ("ULLTRA_DEV_U" == act) { // heartbeat
		LOG(logINFO) << "Heartbeat node " << nd;
		//ProcessHeartbeat(remote.sin_addr, ((HeartBeatData*)&recvBuffer[10]));
	}
	else if (m_customHandlers.find(act) != m_customHandlers.end() && m_customHandlers[act])
	{
		auto ex = m_discovered.find(nd.id);
		if (ex == m_discovered.end()) {
			LOG(logDEBUG1) << "Received custom message " << act << " from unknown " << nd;
			return false;
		}

		ex->second.sinceVitalSign = 0;

		LOG(logINFO) << "Custom handler for message " << act << " from node " << nd;
		m_customHandlers[act](ex->second);
	}
	else {
		LOG(logDEBUG1) << "Received unknown message from " << nd;
	}

	return sendNow;
}
Esempio n. 2
0
File: net.c Progetto: DomChey/ptpd
static Boolean getInterfaceInfo(char* ifaceName, InterfaceInfo* ifaceInfo)
{

    int res;

    res = interfaceExists(ifaceName);

    if (res == -1) {

	return FALSE;

    } else if (res == 0) {

	ERROR("Interface %s does not exist.\n", ifaceName);
	return FALSE;
    }

    res = getInterfaceAddress(ifaceName, ifaceInfo->addressFamily, &ifaceInfo->afAddress);

    if (res == -1) {

	return FALSE;

    }

    ifaceInfo->hasAfAddress = res;

    res = getHwAddress(ifaceName, (unsigned char*)ifaceInfo->hwAddress, 6);

    if (res == -1) {

	return FALSE;

    }

    ifaceInfo->hasHwAddress = res;

    res = getInterfaceFlags(ifaceName, &ifaceInfo->flags);

    if (res == -1) {

	return FALSE;

    }

    return TRUE;

}
Esempio n. 3
0
bool Discovery::start(int broadcastPort)
{
	if (m_broadcastPort)
		return false;

	auto hwid = getHwAddress();
	if (hwid.empty()) {
		LOG(logERROR) << "Not hardware id available!";
		return false;
	}

	LOG(logDEBUG) << "HWID: " << hwid;

	m_broadcastPort = broadcastPort;
	m_updateCounter = 0;

	m_receiver = SimpleUdpReceiver::create(broadcastPort, true);
	if (!m_receiver) {
		LOG(logERROR) << ("Error: could not create receiver socket!") << lastError();
		return false;
	}

	SOCKET soc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (soc == -1) {
		LOG(logERROR) << ("Error: could not create broadcast socket!") << lastError();
		return false;
	}
#ifdef _WIN32
	char yes = 1;
#else
	int yes = 1;
#endif
	// allow broadcast
	int rv = setsockopt(soc, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));
	if (rv == -1) {
		LOG(logERROR) << ("Error: could not set broadcast socket options!") << lastError();
		return false;
	}

	m_soc = soc;


	return true;
}
Esempio n. 4
0
bool Discovery::start(int broadcastPort)
{
	if (m_broadcastPort)
		return false;



   // LOG(logDEBUG) << "default bind address set to " << NodeDevice::localAny;

	m_broadcastPort = broadcastPort;
	m_updateCounter = 0;

	auto hwid = getHwAddress();
	if (hwid.empty()) {
		LOG(logERROR) << "Not hardware id available!";
		return false;
	}
	LOG(logDEBUG4) << "HWID: " << hwid;

	initBroadcast(broadcastPort);
    //initMulticast(broadcastPort+1);

	return true;
}
/*******************************************************************-o-******
 * setup_engineID
 *
 * Parameters:
 *	**eidp
 *	 *text	Printable (?) text to be plugged into the snmpEngineID.
 *
 * Return:
 *	Length of allocated engineID string in bytes,  -OR-
 *	-1 on error.
 *
 *
 * Create an snmpEngineID using text and the local IP address.  If eidp
 * is defined, use it to return a pointer to the newly allocated data.
 * Otherwise, use the result to define engineID defined in this module.
 *
 * Line syntax:
 *	engineID <text> | NULL
 *
 * XXX	What if a node has multiple interfaces?
 * XXX	What if multiple engines all choose the same address?
 *      (answer:  You're screwed, because you might need a kul database
 *       which is dependant on the current engineID.  Enumeration and other
 *       tricks won't work). 
 */
int
setup_engineID(u_char ** eidp, const char *text)
{
    int             enterpriseid = htonl(NETSNMP_ENTERPRISE_OID),
        netsnmpoid = htonl(NETSNMP_OID),
        localsetup = (eidp) ? 0 : 1;

    /*
     * Use local engineID if *eidp == NULL.  
     */
#ifdef HAVE_GETHOSTNAME
    u_char          buf[SNMP_MAXBUF_SMALL];
    struct hostent *hent = NULL;
#endif
    u_char         *bufp = NULL;
    size_t          len;
    int             localEngineIDType = engineIDType;
    int             tmpint;
    time_t          tmptime;

    engineIDIsSet = 1;

#ifdef HAVE_GETHOSTNAME
#ifdef AF_INET6
    /*
     * see if they selected IPV4 or IPV6 support 
     */
    if ((ENGINEID_TYPE_IPV6 == localEngineIDType) ||
        (ENGINEID_TYPE_IPV4 == localEngineIDType)) {
        /*
         * get the host name and save the information 
         */
        gethostname((char *) buf, sizeof(buf));
        hent = gethostbyname((char *) buf);
        if (hent && hent->h_addrtype == AF_INET6) {
            localEngineIDType = ENGINEID_TYPE_IPV6;
        } else {
            /*
             * Not IPV6 so we go with default 
             */
            localEngineIDType = ENGINEID_TYPE_IPV4;
        }
    }
#else
    /*
     * No IPV6 support.  Check if they selected IPV6 engineID type.
     *  If so make it IPV4 instead 
     */
    if (ENGINEID_TYPE_IPV6 == localEngineIDType) {
        localEngineIDType = ENGINEID_TYPE_IPV4;
    }
    if (ENGINEID_TYPE_IPV4 == localEngineIDType) {
        /*
         * get the host name and save the information 
         */
        gethostname((char *) buf, sizeof(buf));
        hent = gethostbyname((char *) buf);
    }
#endif
#endif                          /* HAVE_GETHOSTNAME */

    /*
     * Determine if we have text and if so setup our localEngineIDType
     * * appropriately.  
     */
    if (NULL != text) {
        engineIDType = localEngineIDType = ENGINEID_TYPE_TEXT;
    }
    /*
     * Determine length of the engineID string. 
     */
    len = 5;                    /* always have 5 leading bytes */
    switch (localEngineIDType) {
    case ENGINEID_TYPE_TEXT:
        if (NULL == text) {
            snmp_log(LOG_ERR,
                     "Can't set up engineID of type text from an empty string.\n");
            return -1;
        }
        len += strlen(text);    /* 5 leading bytes+text. No NULL char */
        break;
#if defined(IFHWADDRLEN) && defined(SIOCGIFHWADDR)
    case ENGINEID_TYPE_MACADDR:        /* MAC address */
        len += 6;               /* + 6 bytes for MAC address */
        break;
#endif
    case ENGINEID_TYPE_IPV4:   /* IPv4 */
        len += 4;               /* + 4 byte IPV4 address */
        break;
    case ENGINEID_TYPE_IPV6:   /* IPv6 */
        len += 16;              /* + 16 byte IPV6 address */
        break;
    case ENGINEID_TYPE_NETSNMP_RND:        /* Net-SNMP specific encoding */
        if (engineID)           /* already setup, keep current value */
            return engineIDLength;
        if (oldEngineID) {
            len = oldEngineIDLength;
        } else {
            len += sizeof(int) + sizeof(time_t);
        }
        break;
    default:
        snmp_log(LOG_ERR,
                 "Unknown EngineID type requested for setup (%d).  Using IPv4.\n",
                 localEngineIDType);
        localEngineIDType = ENGINEID_TYPE_IPV4; /* make into IPV4 */
        len += 4;               /* + 4 byte IPv4 address */
        break;
    }                           /* switch */


    /*
     * Allocate memory and store enterprise ID.
     */
    if ((bufp = (u_char *) malloc(len)) == NULL) {
        snmp_log_perror("setup_engineID malloc");
        return -1;
    }
    if (localEngineIDType == ENGINEID_TYPE_NETSNMP_RND)
        /*
         * we must use the net-snmp enterprise id here, regardless 
         */
        memcpy(bufp, &netsnmpoid, sizeof(netsnmpoid));    /* XXX Must be 4 bytes! */
    else
        memcpy(bufp, &enterpriseid, sizeof(enterpriseid));      /* XXX Must be 4 bytes! */

    bufp[0] |= 0x80;


    /*
     * Store the given text  -OR-   the first found IP address
     *  -OR-  the MAC address  -OR-  random elements
     * (the latter being the recommended default)
     */
    switch (localEngineIDType) {
    case ENGINEID_TYPE_NETSNMP_RND:
        if (oldEngineID) {
            /*
             * keep our previous notion of the engineID 
             */
            memcpy(bufp, oldEngineID, oldEngineIDLength);
        } else {
            /*
             * Here we've desigend our own ENGINEID that is not based on
             * an address which may change and may even become conflicting
             * in the future like most of the default v3 engineID types
             * suffer from.
             * 
             * Ours is built from 2 fairly random elements: a random number and
             * the current time in seconds.  This method suffers from boxes
             * that may not have a correct clock setting and random number
             * seed at startup, but few OSes should have that problem.
             */
            bufp[4] = ENGINEID_TYPE_NETSNMP_RND;
            tmpint = random();
            memcpy(bufp + 5, &tmpint, sizeof(tmpint));
            tmptime = time(NULL);
            memcpy(bufp + 5 + sizeof(tmpint), &tmptime, sizeof(tmptime));
        }
        break;
    case ENGINEID_TYPE_TEXT:
        bufp[4] = ENGINEID_TYPE_TEXT;
        memcpy((char *) bufp + 5, (text), strlen(text));
        break;
#ifdef HAVE_GETHOSTNAME
#ifdef AF_INET6
    case ENGINEID_TYPE_IPV6:
        bufp[4] = ENGINEID_TYPE_IPV6;
        memcpy(bufp + 5, hent->h_addr_list[0], hent->h_length);
        break;
#endif
#endif
#if defined(IFHWADDRLEN) && defined(SIOCGIFHWADDR)
    case ENGINEID_TYPE_MACADDR:
        {
            int             x;
            bufp[4] = ENGINEID_TYPE_MACADDR;
            /*
             * use default NIC if none provided 
             */
            if (NULL == engineIDNic) {
	      x = getHwAddress(DEFAULT_NIC, (char *)&bufp[5]);
            } else {
	      x = getHwAddress((char *)engineIDNic, (char *)&bufp[5]);
            }
            if (0 != x)
                /*
                 * function failed fill MAC address with zeros 
                 */
            {
                memset(&bufp[5], 0, 6);
            }
        }
        break;
#endif
    case ENGINEID_TYPE_IPV4:
    default:
        bufp[4] = ENGINEID_TYPE_IPV4;
#ifdef HAVE_GETHOSTNAME
        if (hent && hent->h_addrtype == AF_INET) {
            memcpy(bufp + 5, hent->h_addr_list[0], hent->h_length);
        } else {                /* Unknown address type.  Default to 127.0.0.1. */

            bufp[5] = 127;
            bufp[6] = 0;
            bufp[7] = 0;
            bufp[8] = 1;
        }
#else                           /* HAVE_GETHOSTNAME */
        /*
         * Unknown address type.  Default to 127.0.0.1. 
         */
        bufp[5] = 127;
        bufp[6] = 0;
        bufp[7] = 0;
        bufp[8] = 1;
#endif                          /* HAVE_GETHOSTNAME */
        break;
    }

    /*
     * Pass the string back to the calling environment, or use it for
     * our local engineID.
     */
    if (localsetup) {
        SNMP_FREE(engineID);
        engineID = bufp;
        engineIDLength = len;

    } else {
        *eidp = bufp;
    }


    return len;

}                               /* end setup_engineID() */
Esempio n. 6
0
bool  Discovery::send(const std::string &msg, const NodeDevice &node)
{
	bool isMulticast = !node.exists();

	char data[500];
	char *dp = &data[0];

	auto devName = UP::getDeviceName();
	// create 0-seperated string list
	strcpy(dp, msg.c_str()); dp += msg.length() + 1;
	strcpy(dp, devName.c_str()); dp += devName.length() + 1;
	strcpy(dp, getHwAddress().c_str());  dp += getHwAddress().length() + 1;

	int dataLen = dp - &data[0];


	if (!isMulticast) {
		auto na = node.getAddr(m_broadcastPort);
		bool ipv6 = (na.getFamily() == AF_INET6);
		if (sendto(ipv6 ? m_socMulticast : m_socBroadcast4, data, dataLen, 0, (struct sockaddr*)&na, sizeof(na)) != dataLen) {
			LOG(logERROR) << "Could not send broadcast message to " << node << lastError();
			return false;
		}
	}
	else
	{
		// ipv4 udp broadcast
		if (m_socBroadcast4 != -1) {
			struct sockaddr_in addr4;
			memset(&addr4, 0, sizeof(addr4));
			addr4.sin_family = AF_INET;
			addr4.sin_port = htons(m_broadcastPort);
			addr4.sin_addr.s_addr = htonl(INADDR_BROADCAST);

			if (sendto(m_socBroadcast4, data, dataLen, 0, (struct sockaddr*)&addr4, sizeof(addr4)) != dataLen) {
				LOG(logERROR) << "Could not send broadcast message on INADDR_BROADCAST! " << lastError();
				return false;
			}

			// Windows broadcast fix (for ipv4): send broadcast on each host addr
			char ac[1000];
			if (gethostname(ac, sizeof(ac)) == -1)
				return false;

			// TODO bug gethostbyname causes seg fault on windows in release (maybe mongoose?)
			addrinfo *ai;
			if (getaddrinfo(ac, NULL, NULL, &ai) != 0) {
				return false;
			}
			
			for (auto cai = ai; cai != 0; cai = cai->ai_next) {
				struct in_addr daddr;
                memcpy(&daddr, cai->ai_addr, std::min(sizeof(daddr), (size_t)cai->ai_addrlen));
				addr4.sin_addr.s_addr = daddr.s_addr | (255) << (8 * 3);

				std::string ip4(inet_ntoa(addr4.sin_addr));
				//std::cout << "broadcast message to " << ip4 << ":" << ntohs(addr4.sin_port) << "" << std::endl;

				if (sendto(m_socBroadcast4, data, dataLen, 0, (struct sockaddr*)&addr4, sizeof(addr4)) != dataLen) {
					LOG(logERROR) << "Could not send broadcast message  to " << ip4 << "!" << std::endl;
				}
			}

			freeaddrinfo(ai);
		}

		// ipv6 multicast
		if (m_socMulticast != -1) {
			if (sendto(m_socMulticast, data, dataLen, 0,
				(struct sockaddr *)&m_multicastAddrSend, sizeof(m_multicastAddrSend))
				!= dataLen) {
				LOG(logERROR) << "sending ipv6 multicast message on " << m_multicastAddrSend << " failed! " << lastError();
				return false;
			}
		}

		// send to explicit nodes
		for (NodeDevice n : m_explicitNodes) {
			send(msg, n);
		}
	}

	return true;
}
Esempio n. 7
0
void  Discovery::send(const std::string &msg, const NodeDevice &node)
{
	SOCKET soc = (SOCKET)m_soc;

	char data[500];

	char hostname[32];
	gethostname(hostname, 31);

	auto hwAddress = getHwAddress();

	char *dp = &data[0];



	// create 0-seperated string list
	strcpy(dp, msg.c_str()); dp += strlen(dp) + 1;
	strcpy(dp, hostname); dp += strlen(hostname) + 1;
	strcpy(dp, hwAddress.c_str());  dp += hwAddress.length() + 1;

	int dataLen = dp - &data[0];

	struct sockaddr_in s;
	memset(&s, 0, sizeof(struct sockaddr_in));
	s.sin_family = AF_INET;
	s.sin_port = htons(m_broadcastPort);
	s.sin_addr.s_addr = node.exists() ? node.addr.s_addr : htonl(INADDR_BROADCAST);

	int sent = sendto(soc, data, dataLen, 0, (struct sockaddr*)&s, sizeof(struct sockaddr_in));

	if (sent != dataLen) {
		LOG(logERROR) << "Could not send broadcast message!";
	}

	//#ifdef _WIN32
	// win32 broadcast fix
	// use this on linux too?
	char ac[200];
	if (gethostname(ac, sizeof(ac)) == -1)
		return;

	struct hostent *phe = gethostbyname(ac);
	if (phe == 0)
		return;

	for (int i = 0; phe->h_addr_list[i] != 0; ++i) {
		struct in_addr addr;
		memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr));
		addr.s_addr = addr.s_addr | (255) << (8 * 3);
		s.sin_addr.s_addr = addr.s_addr | (255) << (8 * 3);

		std::string ip4(inet_ntoa(s.sin_addr));
		//std::cout << "broadcast message to " << ip4 << ":" << ntohs(s.sin_port) << "!" << std::endl;

		sent = sendto(soc, data, dataLen, 0, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
		if (sent != dataLen) {
			LOG(logERROR) << "Could not send broadcast message  to " << ip4 << "!" << std::endl;
		}
	}
	//#else
	//	inet_aton("10.0.0.255", &s.sin_addr);
	//	sendto(soc, data, 16 + 32, 0, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
	//#endif
}
Esempio n. 8
0
bool Discovery::update(time_t now)
{
	bool sendNow = false;

	std::map<std::string, NodeDevice> newlyDiscovered;

	while (true) {
		struct sockaddr_in remote;
		int len;

		const uint8_t * recvBuffer = m_receiver->receive(len, remote);

		// would block? 
		if (len == -1 || !recvBuffer)
			break;	

		if (len < 20)
			continue;


		std::string act((const char*)recvBuffer);
		
		NodeDevice nd;
		nd.name = std::string((const char*)&recvBuffer[act.length() + 1]);
		nd.id = std::string((const char*)&recvBuffer[act.length() + nd.name.length() + 2]);
		nd.addr = remote.sin_addr;

		// check if we somehow received our own broadcast
		if (nd.id == getHwAddress()) {
			continue;
		}

		if ("ULLTRA_DEV_R" == act) { // register
			auto &exN = getNode(nd.id);
			// already there?
			if (exN.exists()) {
				exN.vitalSign = now;
				continue;
			}

			nd.vitalSign = now;

			if (newlyDiscovered.find(nd.id) == newlyDiscovered.end()) {
				newlyDiscovered[nd.id] = nd;
				LOG(logINFO) << "Discovered node " << nd;

				send("ULLTRA_DEV_R", nd);

				sendNow = true;
			}
		}
		else if ("ULLTRA_DEV_Z" == act) { // unregister
			for (auto it = m_discovered.begin(); it != m_discovered.end(); it++) {
				if (it->id == nd.id || it->addr.s_addr == nd.addr.s_addr) {
										
					{ LOG(logINFO) << "Lost node " << nd; }
					sendNow = true;

					if (onNodeLost)
						onNodeLost(*it);

					m_discovered.erase(it);
					break;
				}
			}
		}
		else if ("ULLTRA_DEV_H" == act) { // heartbeat
			LOG(logINFO) << "Heartbeat node " << nd;
			//ProcessHeartbeat(remote.sin_addr, ((HeartBeatData*)&recvBuffer[10]));
		}
		else if (m_customHandlers.find(act) != m_customHandlers.end() && m_customHandlers[act])
		{
			// only accept custom messages from known nodes
			auto &exN = getNode(nd.id);
			if (!exN.exists() && newlyDiscovered.find(nd.id) == newlyDiscovered.end()) {
				{ LOG(logDEBUG1) << "Received custom message " << act << " from unknown " << nd; }
				continue;
			}

			exN.vitalSign = now;

			{ LOG(logINFO) << "Custom handler for message " << act << " from node " << nd; }
			m_customHandlers[act](nd);

			exN.vitalSign = UP::getMicroSeconds();
		}
		else {
			{ LOG(logDEBUG1) << "Received unknown message from " << nd; }
		}
	}


	// auto-purge dead nodes
	for (auto it = m_discovered.begin(); it != m_discovered.end(); it++) {
		if(difftime(now, it->vitalSign) > (UlltraProto::BroadcastInterval*3)) {
			LOG(logINFO) << "Dead node " << (*it);
			m_discovered.erase(it);
			sendNow = true;
			break;
		}
	}
	
	// broadcast a discovery packet every 10 updates or if something changed
	// e.g. if a new node appears make current node visible
	// this needs to be done beffore onNodeDiscovered() call!
	if (difftime(now, m_lastBroadcast) >= UlltraProto::BroadcastInterval || sendNow) {
		usleep(1000 * 100);
		send("ULLTRA_DEV_R");
		m_lastBroadcast = now;
		usleep(1000 * 100);
	}

	for (auto &nd : newlyDiscovered) {
		if (onNodeDiscovered)
			onNodeDiscovered(nd.second);
		m_discovered.push_back(nd.second);
	}

	m_updateCounter++;

	return true;
}