Esempio n. 1
0
int getLocalInterfaceList(InterfaceRefList& iflist, const bool onlyUp) 
{
        char buf[1024];
	int sock;
        struct ifconf ifc;
	struct ifreq *ifr;
	int n, i, num = 0;
        
        sock = socket(AF_INET, SOCK_DGRAM, 0);

	if (sock == INVALID_SOCKET) {
		HAGGLE_ERR("Could not calculate node id\n");
		return -1;
	}

	ifc.ifc_len = sizeof(buf);
	ifc.ifc_buf = buf;
        
	if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
		HAGGLE_ERR("SIOCGIFCONF failed\n");
		return -1;
	}
        
        ifr = ifc.ifc_req;
	n = ifc.ifc_len / sizeof(struct ifreq);
        
	for (i = 0; i < n; i++) {
                Addresses addrs;
		struct ifreq *item = &ifr[i];

                // if (ioctl(sock, SIOCGIFBRDADDR, item) < 0)
                //         continue;         
                
		//printf(", MAC %s\\n", ether_ntoa((struct ether_addr *)item->ifr_hwaddr.sa_data));
                if (onlyUp && !(item->ifr_flags & IFF_UP)) 
                        continue;

                addrs.add(new IPv4Address(((struct sockaddr_in *)&item->ifr_addr)->sin_addr));
		addrs.add(new IPv4BroadcastAddress(((struct sockaddr_in *)&item->ifr_broadaddr)->sin_addr));

		if (ioctl(sock, SIOCGIFHWADDR, item) < 0)
                        continue;
               
                addrs.add(new EthernetAddress((unsigned char *)item->ifr_hwaddr.sa_data));
		
		InterfaceRef iface = Interface::create<EthernetInterface>(item->ifr_hwaddr.sa_data, item->ifr_name, IFFLAG_LOCAL | ((item->ifr_flags & IFF_UP) ? IFFLAG_UP : 0));

		if (iface) {
			iface->addAddresses(addrs);
			iflist.push_back(iface);
			num++;
		}
        }
        
        close(sock);
              
        return num;
}
Esempio n. 2
0
bool NodeStore::update(NodeRef &node, NodeRefList *nl)
{
        Mutex::AutoLocker l(mutex);
	bool found = false;
	
	if (!node)
		return false;

	// There may be undefined nodes in the node store that should
	// be removed/merged with a 'defined' node that we create from a 
	// node description. We loop through all nodes in the store and
	// compare their interface lists with the one in the 'defined' node.
	// If any interfaces match, we remove the matching nodes in the store 
	// and eventually replace them with the new one.
	for (NodeStore::iterator it = begin(); it != end();) {
		NodeRecord *nr = *it;
		bool found_now = false;
		
		nr->node.lock();

		const InterfaceRefList *ifaces = nr->node->getInterfaces();

		for (InterfaceRefList::const_iterator it2 = ifaces->begin(); it2 != ifaces->end(); it2++) {
			InterfaceRef iface = *it2;

			if (node->hasInterface(iface)) {
				// Transfer all the "up" interface states to the updated node
				if (iface->isUp())
					node->setInterfaceUp(iface);

				found_now = true;
			}
		}
		nr->node.unlock();

		if (found_now) {
			if (nl)
				nl->push_back(nr->node);
			
			nr->node->setStored(false);

			node->setExchangedNodeDescription(nr->node->hasExchangedNodeDescription());
				
			it = erase(it);
			delete nr;
			found = true;
		} else {
			it++;
		}
	}
	if (found) {
		node->setStored(true);
		push_back(new NodeRecord(node));
	}

	return found;
}
Esempio n. 3
0
InterfaceRef InterfaceStore::addupdate(Interface *iface, const Interface *parent, ConnectivityInterfacePolicy *policy, bool *was_added)
{
	InterfaceRef parentStore;

	if (!iface)
		return NULL;

	if (was_added)
		*was_added = false;
	
	// Always use the parent reference which is already in the store.
	// The exception is if parent == NULL, which means that we are 
	// adding a parent interface (local connectivity).
	if (parent) {
		parentStore = retrieve(*parent);

		if (!parentStore)
			return NULL;
	}

        Mutex::AutoLocker l(mutex);

	for (InterfaceStore::iterator it = begin(); it != end(); it++) {
		InterfaceRecord *ir = *it;
		InterfaceRef& ifaceStore = ir->iface;

		if (ir->iface == *iface) {
			if (ir->cip) 
				delete ir->cip;
			
			ir->cip = policy;
			
			if (ir->iface->isSnooped()) {
				ir->iface->resetFlag(IFFLAG_SNOOPED);
				ir->parent = parentStore;
			}

			if (ir->cip) 
				ir->cip->update();

			return ifaceStore;
		}
	}

	InterfaceRef ifaceRef = iface->copy();
	InterfaceRecord *ir = new InterfaceRecord(ifaceRef, parentStore, policy);
	push_back(ir);
	
	if (was_added) {
		ifaceRef->setFlag(IFFLAG_STORED);
		*was_added = true;
	}

	return ifaceRef;
}
Esempio n. 4
0
/*
	On send events, the security manager 
 
 */
void SecurityManager::onSendDataObject(Event *e)
{
	if (!e || !e->hasData())
		return;

	DataObjectRef dObj = e->getDataObject();
	
	if (dObj->isThisNodeDescription()) {
		// This is our node description. Piggy-back our certificate.
		if (myCert) {
			Metadata *m;

			m = dObj->getMetadata()->getMetadata("Security");
			
			if (m) {
				HAGGLE_ERR("Node description already has a Security tag!\n");
			} else {
				m = dObj->getMetadata()->addMetadata("Security");
				
				if (m) {
					m->addMetadata(myCert->toMetadata());
				}
			}
		}
	}
	
	// In most cases the data object is already signed here (e.g., if it is generated by a local
	// application, or was received from another node). The only reason to check if we should
	// sign the data object here, is if a data object was generated internally by Haggle -- in
	// which case the data object might not have a signature (e.g., the data object is a node
	// description).
	InterfaceRef iface = dObj->getRemoteInterface();
	
	if (dObj->shouldSign() && !(iface && iface->getType() == Interface::TYPE_APPLICATION_PORT)) {
		// FIXME: data objects should really be signed in the SecurityHelper thread since
		// it is a potentially CPU intensive operation. But it is currently not possible
		// to ensure that the signing operation has finished in the helper thread before
		// the data object is actually sent on the wire by the protocol manager.
		// To handle this situation, we probably need to add a new public event for 
		// security related operations, after which the security manager generates the
		// real send event.
		
		if (helper->signDataObject(dObj, privKey)) {
			HAGGLE_DBG("Successfully signed data object %s\n", dObj->getIdStr());
		} else {
			HAGGLE_DBG("Signing of data object %s failed!\n", dObj->getIdStr());
		}
	}	
}
Esempio n. 5
0
/*
	Check incoming data objects for two reasons:
	1) whether they have an embedded certificate, in which case we verify 
	it and add it to our store in case it is not already there.
	2) sign any data objects that were generated by local applications.
 */
void SecurityManager::onIncomingDataObject(Event *e)
{
	DataObjectRef dObj;
	
	if (!e || !e->hasData())
		return;
	
	dObj = e->getDataObject();
	
	if (dObj->isDuplicate())
		return;

	Metadata *m = dObj->getMetadata()->getMetadata("Security");
	
	// Check if there is a certificate embedded that we do not already have stored
	if (m && m->getMetadata("Certificate")) {
		HAGGLE_DBG("Data object has embedded certificate, trying to verify it!\n");
		helper->addTask(new SecurityTask(SECURITY_TASK_VERIFY_CERTIFICATE, dObj));
	}
			
	InterfaceRef iface = dObj->getRemoteInterface();

	// Check if this data object came from an application, in that case we sign it.
	// In the future, the signing should potentially be handled by the application
	// itself. But this requires some major rethinking of how to manage certificates 
	// and keys, etc.
	if (iface && iface->getType() == Interface::TYPE_APPLICATION_PORT && dObj->shouldSign()) {
		HAGGLE_DBG("Data object should be signed\n");

		// FIXME: data objects should really be signed in the SecurityHelper thread since
		// it is a potentially CPU intensive operation. But it is currently not possible
		// to ensure that the signing operation has finished in the helper thread before
		// the data object is added to the data store.
		if (helper->signDataObject(dObj, privKey)) {
			HAGGLE_DBG("Successfully signed data object %s, which was added by an application.\n", 
				   dObj->getIdStr());
		} else {
			HAGGLE_DBG("Signing of data object %s, which was added by an application, failed!\n", 
				   dObj->getIdStr());
		}
	}
}
void ProtocolManager::onLocalInterfaceUp(Event *e)
{
	if (!e)
		return;

	InterfaceRef iface = e->getInterface();

	if (!iface)
		return;

	const Addresses *adds = iface->getAddresses();
	
	for (Addresses::const_iterator it = adds->begin() ; it != adds->end() ; it++) {
		switch((*it)->getType()) {
		case Address::TYPE_IPV4:
#if defined(ENABLE_IPv6)
		case Address::TYPE_IPV6:
#endif
			getServerProtocol(Protocol::TYPE_TCP, iface);
			return;			
#if defined(ENABLE_BLUETOOTH)
		case Address::TYPE_BLUETOOTH:
			getServerProtocol(Protocol::TYPE_RFCOMM, iface);
			return;
#endif			
#if defined(ENABLE_MEDIA)
			// FIXME: should probably separate loop interfaces from media interfaces somehow...
		case Address::TYPE_FILEPATH:
			getServerProtocol(Protocol::TYPE_MEDIA, iface);
			return;
#endif
			
		default:
			break;
		}
	}
	
	HAGGLE_DBG("Interface with no known address type - no server started\n");
}
Esempio n. 7
0
bool ProtocolUDP::isForInterface(const InterfaceRef& iface)
{
	/*
		FIXME:
		This is a pretty crude check. We simply assume that 
		if this protocol is our IPC mechanism to communicate
		with applications, and the interface to check is also 
		an application interface, then this is the protocol to
		use.
	*/
	if (iface->getType() == Interface::TYPE_APPLICATION_PORT &&
	    localIface->getType() == Interface::TYPE_APPLICATION_PORT)
		return true;
	else if (peerIface && iface == peerIface)
		return true;

	return false;
}
Esempio n. 8
0
void InterfaceStore::print()
{
        Mutex::AutoLocker l(mutex);
	InterfaceStore::iterator it = begin();

	printf("====== Interfaces ======\n");
	printf("<type> <identifier> <name> <flags> <age> <refcount> <parent interface>\n");
	printf("\t<addresses>\n");
	printf("------------------------------\n");
	
	while (it != end()) {
		InterfaceRecord *ir = *it;
		
		ir->iface.lock();
		InterfaceRef iface = ir->iface;
		
                printf("%s %s %s %s %s %lu %s\n", 
                       iface->getTypeStr(),
                       iface->getIdentifierStr(),
                       iface->getName(),
		       iface->getFlagsStr(),
                       ir->cip ? ir->cip->ageStr() : "undefined",
                       ir->iface.refcount(),
                       ir->parent ? ir->parent->getIdentifierStr() : "\'no parent\'");

		const Addresses *addrs = iface->getAddresses();
		
		for (Addresses::const_iterator itt = addrs->begin(); itt != addrs->end(); itt++) {
			const Address *addr = *itt;
			printf("\t%s\n", addr->getURI());
		}
		
		ir->iface.unlock();
		it++;
	}
		
	printf("==============================\n");
}
Esempio n. 9
0
UUExperimentSetup::UUExperimentSetup()
{
	InterfaceRefList iflist;
	InterfaceRef ethIface = NULL;

	// Get all local interfaces, even the ones which are not 'up'
	if (getLocalInterfaceList(iflist, false) < 0) {
		fprintf(stderr, "Could not find any local interfaces\n");
		return;
	}

	// Find the first one returned, it should be the interface we use 
	// for the experiments
	for (InterfaceRefList::iterator it = iflist.begin(); it != iflist.end(); it++) {
		ethIface = *it;

		if (ethIface->getType() == IFTYPE_ETHERNET || ethIface->getType() == IFTYPE_WIFI)
			break;
	}

	if (!ethIface) {
		fprintf(stderr, "No valid local interface to configure\n");
		return;
	}
#if 0
	HRESULT res = S_OK;
	HANDLE hConnMgrReady = ConnMgrApiReadyEvent();

	DWORD retval = WaitForSingleObject(hConnMgrReady, 5000);

	if (retval == WAIT_TIMEOUT) {
		fprintf(stderr, "Connection manager is not ready...\n");
	} else if (retval == WAIT_FAILED) {
		fprintf(stderr, "Wait for Connection manager failed!\n");
	} else {
		for (int i = 0; res == S_OK; i++) {
			CONNMGR_DESTINATION_INFO network_info;

			res = ConnMgrEnumDestinations(i, &network_info);

			if (res == S_OK) {
				printf("Network name %S\n", network_info.szDescription);
			}
		}
	}

	CloseHandle(hConnMgrReady);
#endif
	struct interface_config *ic = get_interface_config(ethIface->getIdentifier());

	if (!ic) {
		fprintf(stderr, "Could not find matching configuration for interface %s\n", 
			ethIface->getIdentifierStr());
		return;
	}

	printf("Configuring interface %s\n", ethIface->getIdentifierStr());

	unsigned long ifindex = 0;
	
	if (!WindowsWiFiUtils::getDeviceIndex(ethIface->getName(), &ifindex)) {
		fprintf(stderr, "Could not get interface index\n");
		return;
	}

	if (!WindowsWiFiUtils::setNetworkMode(ifindex, Ndis802_11IBSS)) {
		fprintf(stderr, "Could not set ad hoc mode\n");
		return;
	}

	if (!WindowsWiFiUtils::setWiFiSSID(ifindex, EXPERIMENT_SSID)) {
		fprintf(stderr, "Could not set WiFi SSID\n");
		return;
	}

	if (!WindowsWiFiUtils::setChannel(ifindex, EXPERIMENT_CHANNEL)) {
		fprintf(stderr, "Could not set WiFi channel to %u\n", EXPERIMENT_CHANNEL);
		return;
	}

	// Add the IPv4 address.
	/*
	if (!WindowsWiFiUtils::addIPv4Address(ifindex, ic->ip, ic->mask)) {
		fprintf(stderr, "Could not set IP address %s/%s\n", ic->ip, ic->mask);
		return false;;
	}
	*/
	printf("Interface %s with mac=%s was configured with ip=%s/%s and SSID=%s on channel=%u\n",
		ethIface->getName(), ethIface->getIdentifierStr(), ic->ip, ic->mask, 
		EXPERIMENT_SSID, EXPERIMENT_CHANNEL);
}
Esempio n. 10
0
void ProtocolManager::onSendDataObjectActual(Event *e)
{
	int numTx = 0;

	if (!e || !e->hasData())
		return;

	// Get a copy to work with
	DataObjectRef dObj = e->getDataObject();

	// Get target list:
	NodeRefList *targets = (e->getNodeList()).copy();

	if (!targets) {
		HAGGLE_ERR("no targets in data object when sending\n");
		return;
	}

	unsigned int numTargets = targets->size();

	// Go through all targets:
	while (!targets->empty()) {
		
		// A current target reference
		NodeRef targ = targets->pop();
		
		if (!targ) {
			HAGGLE_ERR("Target num %u is NULL!\n", numTargets);
			numTargets--;
			continue;
		}

		HAGGLE_DBG("Sending to target %u - %s \n", numTargets, targ->getName().c_str());
		
		// If we are going to loop through the node's interfaces, we need to lock the node.
		targ.lock();	
		
		const InterfaceRefList *interfaces = targ->getInterfaces();
		
		// Are there any interfaces here?
		if (interfaces == NULL || interfaces->size() == 0) {
			// No interfaces for target, so we generate a
			// send failure event and skip the target
		
			HAGGLE_DBG("Target %s has no interfaces\n", targ->getName().c_str());

			targ.unlock();

			kernel->addEvent(new Event(EVENT_TYPE_DATAOBJECT_SEND_FAILURE, dObj, targ));
			numTargets--;
			continue;
		}
		
		/*	
			Find the target interface that suits us best
			(we assume that for any remote target
			interface we have a corresponding local interface).
		*/
		InterfaceRef peerIface = NULL;
		bool done = false;
		
		InterfaceRefList::const_iterator it = interfaces->begin();
		
		//HAGGLE_DBG("Target node %s has %lu interfaces\n", targ->getName().c_str(), interfaces->size());

		for (; it != interfaces->end() && done == false; it++) {
			InterfaceRef iface = *it;
			
			// If this interface is up:
			if (iface->isUp()) {
				
				if (iface->getAddresses()->empty()) {
					HAGGLE_DBG("Interface %s:%s has no addresses - IGNORING.\n",
						   iface->getTypeStr(), iface->getIdentifierStr());
					continue;
				}
				
				switch (iface->getType()) {
#if defined(ENABLE_BLUETOOTH)
				case Interface::TYPE_BLUETOOTH:
					/*
					  Select Bluetooth only if there are no Ethernet or WiFi
					  interfaces.
					*/
					if (!iface->getAddress<BluetoothAddress>()) {
						HAGGLE_DBG("Interface %s:%s has no Bluetooth address - IGNORING.\n",
							   iface->getTypeStr(), iface->getIdentifierStr());
						break;
					}
					
					if (!peerIface)
						peerIface = iface;
					else if (peerIface->getType() != Interface::TYPE_ETHERNET &&
						 peerIface->getType() != Interface::TYPE_WIFI)
						peerIface = iface;
					break;
#endif
#if defined(ENABLE_ETHERNET)
				case Interface::TYPE_ETHERNET:
					/*
					  Let Ethernet take priority over the other types.
					*/
					if (!iface->getAddress<IPv4Address>()
#if defined(ENABLE_IPv6)
					    && !iface->getAddress<IPv6Address>()
#endif
						) {
						HAGGLE_DBG("Interface %s:%s has no IPv4 or IPv6 addresses - IGNORING.\n",
							   iface->getTypeStr(), iface->getIdentifierStr());
						break;
					}
					if (!peerIface)
						peerIface = iface;
					else if (peerIface->getType() == Interface::TYPE_BLUETOOTH ||
						 peerIface->getType() == Interface::TYPE_WIFI)
						peerIface = iface;
					break;
				case Interface::TYPE_WIFI:
					if (!iface->getAddress<IPv4Address>() 
#if defined(ENABLE_IPv6)
					    && !iface->getAddress<IPv6Address>()
#endif
						) {
						HAGGLE_DBG("Interface %s:%s has no IPv4 or IPv6 addresses - IGNORING.\n",
							   iface->getTypeStr(), iface->getIdentifierStr());
						break;
					}
					if (!peerIface)
						peerIface = iface;
					else if (peerIface->getType() == Interface::TYPE_BLUETOOTH &&
						 peerIface->getType() != Interface::TYPE_ETHERNET)
						peerIface = iface;
					break;
#endif // ENABLE_ETHERNET
				case Interface::TYPE_APPLICATION_PORT:
				case Interface::TYPE_APPLICATION_LOCAL:
                                        
					if (!iface->getAddress<IPv4Address>() 
#if defined(ENABLE_IPv6)
					    && !iface->getAddress<IPv6Address>()
#endif
						) {
						HAGGLE_DBG("Interface %s:%s has no IPv4 or IPv6 addresses - IGNORING.\n",
							   iface->getTypeStr(), iface->getIdentifierStr());
						break;
					}
					// Not much choise here.
					if (targ->getType() == Node::TYPE_APPLICATION) {
						peerIface = iface;
						done = true;
					} else {
						HAGGLE_DBG("ERROR: Node %s is not application, but its interface is\n",
							targ->getName().c_str());
					}
                                        
					break;
#if defined(ENABLE_MEDIA)
				case Interface::TYPE_MEDIA:
					break;
#endif
				case Interface::TYPE_UNDEFINED:
				default:
					break;
				}
			} else {
				//HAGGLE_DBG("Send interface %s was down, ignoring...\n", iface->getIdentifierStr());
			}
		}
		
		// We are done looking for a suitable send interface
		// among the node's interface list, so now we unlock
		// the node.
		targ.unlock();
		
		if (!peerIface) {
			HAGGLE_DBG("No send interface found for target %s. Aborting send of data object!!!\n", 
				targ->getName().c_str());
			// Failed to send to this target, send failure event:
			kernel->addEvent(new Event(EVENT_TYPE_DATAOBJECT_SEND_FAILURE, dObj, targ));
			numTargets--;
			continue;
		}

		// Ok, we now have a target and a suitable interface,
		// now we must figure out a protocol to use when we
		// transmit to that interface
		Protocol *p = NULL;
		
		// We make a copy of the addresses list here so that we do not
		// have to lock the peer interface while we call getSenderProtocol().
		// getSenderProtocol() might do a lookup in the interface store in order
		// to find the local interface which is parent of the peer interface.
		// This might cause a deadlock in case another thread also does a lookup
		// in the interface store while we hold the interface lock.
		const Addresses *adds = peerIface->getAddresses()->copy();
		
		// Figure out a suitable protocol given the addresses associated 
		// with the selected interface
		for (Addresses::const_iterator it = adds->begin(); p == NULL && it != adds->end(); it++) {
			
			switch ((*it)->getType()) {
#if defined(ENABLE_BLUETOOTH)
			case Address::TYPE_BLUETOOTH:
				p = getSenderProtocol(Protocol::TYPE_RFCOMM, peerIface);
				break;
#endif
			case Address::TYPE_IPV4:
#if defined(ENABLE_IPv6)
			case Address::TYPE_IPV6:
#endif
				if (peerIface->isApplication()) {
#ifdef USE_UNIX_APPLICATION_SOCKET
					p = getSenderProtocol(Protocol::TYPE_LOCAL, peerIface);
#else
					p = getSenderProtocol(Protocol::TYPE_UDP, peerIface);
#endif
				}
				else
					p = getSenderProtocol(Protocol::TYPE_TCP, peerIface);
				break;
#if defined(ENABLE_MEDIA)
			case Address::TYPE_FILEPATH:
				p = getSenderProtocol(Protocol::TYPE_MEDIA, peerIface);
				break;
#endif
			default:
				break;
			}
		}
		
		delete adds;
		
                // Send data object to the found protocol:

                if (p) {
			if (p->sendDataObject(dObj, targ, peerIface)) {
				numTx++;
			} else {
				// Failed to send to this target, send failure event:
                                kernel->addEvent(new Event(EVENT_TYPE_DATAOBJECT_SEND_FAILURE, dObj, targ));
			}
		} else {
			HAGGLE_DBG("No suitable protocol found for interface %s:%s!\n", 
				   peerIface->getTypeStr(), peerIface->getIdentifierStr());
			// Failed to send to this target, send failure event:
			kernel->addEvent(new Event(EVENT_TYPE_DATAOBJECT_SEND_FAILURE, dObj, targ));			
		}

		numTargets--;
	}
	HAGGLE_DBG("Scheduled %d data objects for sending\n", numTx);

	delete targets;
}