// // Open a listener which will create new links when messages arrive and queue them appropriately. // Listeners are inherently insecure, as an adversary could easily create many connections that are never closed. // static AthenaTransportLink * _UDPOpenListener(AthenaTransportLinkModule *athenaTransportLinkModule, const char *linkName, struct sockaddr_in *destination, size_t mtu) { const char *derivedLinkName; _UDPLinkData *linkData = _UDPLinkData_Create(); linkData->multiplexTable = parcHashCodeTable_Create(_connectionEquals, _connectionHashCode, NULL, _closeConnection); assertNotNull(linkData->multiplexTable, "Could not create multiplex table for new listener"); linkData->link.myAddress = *destination; linkData->link.myAddressLength = sizeof(struct sockaddr_in); linkData->link.mtu = mtu; linkData->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (linkData->fd < 0) { parcLog_Error(athenaTransportLinkModule_GetLogger(athenaTransportLinkModule), "socket error (%s)", strerror(errno)); _UDPLinkData_Destroy(&linkData); return NULL; } int result = _setSocketOptions(athenaTransportLinkModule, linkData->fd); if (result) { close(linkData->fd); _UDPLinkData_Destroy(&linkData); return NULL; } // Set non-blocking flag int flags = fcntl(linkData->fd, F_GETFL, NULL); if (flags < 0) { parcLog_Error(athenaTransportLinkModule_GetLogger(athenaTransportLinkModule), "fcntl failed to get non-blocking flag (%s)", strerror(errno)); close(linkData->fd); _UDPLinkData_Destroy(&linkData); return NULL; } result = fcntl(linkData->fd, F_SETFL, flags | O_NONBLOCK); if (result) { parcLog_Error(athenaTransportLinkModule_GetLogger(athenaTransportLinkModule), "fcntl failed to set non-blocking flag (%s)", strerror(errno)); close(linkData->fd); _UDPLinkData_Destroy(&linkData); return NULL; } // bind to listen on requested address result = bind(linkData->fd, (struct sockaddr *) &linkData->link.myAddress, linkData->link.myAddressLength); if (result) { parcLog_Error(athenaTransportLinkModule_GetLogger(athenaTransportLinkModule), "bind error (%s)", strerror(errno)); close(linkData->fd); _UDPLinkData_Destroy(&linkData); return NULL; } derivedLinkName = _createNameFromLinkData(&linkData->link); if (linkName == NULL) { linkName = derivedLinkName; } // Listener doesn't require a send method. The receive method is used to establish new connections. AthenaTransportLink *athenaTransportLink = athenaTransportLink_Create(linkName, NULL, _UDPReceiveListener, _UDPClose); if (athenaTransportLink == NULL) { parcLog_Error(athenaTransportLink_GetLogger(athenaTransportLink), "athenaTransportLink_Create failed"); parcMemory_Deallocate(&derivedLinkName); close(linkData->fd); _UDPLinkData_Destroy(&linkData); return athenaTransportLink; } athenaTransportLink_SetPrivateData(athenaTransportLink, linkData); athenaTransportLink_SetEventFd(athenaTransportLink, linkData->fd); // Links established for listening are not used to route messages. // They can be kept in a listener list that doesn't consume a linkId. athenaTransportLink_SetRoutable(athenaTransportLink, false); parcLog_Info(athenaTransportLink_GetLogger(athenaTransportLink), "new listener established: Name=\"%s\" (%s)", linkName, derivedLinkName); parcMemory_Deallocate(&derivedLinkName); return athenaTransportLink; }
// // Open a listener which will create new links when messages arrive and queue them appropriately. // Listeners are inherently insecure, as an adversary could easily create many connections that are never closed. // static AthenaTransportLink * _ETHOpenListener(AthenaTransportLinkModule *athenaTransportLinkModule, const char *linkName, const char *device, struct ether_addr *source, size_t mtu) { const char *derivedLinkName; _ETHLinkData *linkData = _ETHLinkData_Create(); linkData->multiplexTable = parcHashCodeTable_Create(_connectionEquals, _connectionHashCode, NULL, _closeConnection); assertNotNull(linkData->multiplexTable, "Could not create multiplex table for new listener"); linkData->athenaEthernet = athenaEthernet_Create(athenaTransportLinkModule_GetLogger(athenaTransportLinkModule), device, CCNX_ETHERTYPE); if (linkData->athenaEthernet == NULL) { _ETHLinkData_Destroy(&linkData); return NULL; } // Use specified source MAC address, or default to device MAC if (source) { memcpy(&(linkData->link.myAddress), source, sizeof(struct ether_addr)); } else { athenaEthernet_GetMAC(linkData->athenaEthernet, &(linkData->link.myAddress)); } linkData->link.myAddressLength = ETHER_ADDR_LEN; if (linkData->athenaEthernet == NULL) { parcLog_Error(athenaTransportLinkModule_GetLogger(athenaTransportLinkModule), "athenaEthernet_Create error"); _ETHLinkData_Destroy(&linkData); return NULL; } derivedLinkName = _createNameFromLinkData(&linkData->link, true); if (linkName == NULL) { linkName = derivedLinkName; } // Listener doesn't require a send method. The receive method is used to establish new connections. AthenaTransportLink *athenaTransportLink = athenaTransportLink_Create(linkName, NULL, _ETHReceiveListener, _ETHClose); if (athenaTransportLink == NULL) { parcLog_Error(athenaTransportLink_GetLogger(athenaTransportLink), "athenaTransportLink_Create failed"); parcMemory_Deallocate(&derivedLinkName); _ETHLinkData_Destroy(&linkData); return athenaTransportLink; } athenaTransportLink_SetPrivateData(athenaTransportLink, linkData); athenaTransportLink_SetEventFd(athenaTransportLink, athenaEthernet_GetDescriptor(linkData->athenaEthernet)); // Links established for listening are not used to route messages. // They can be kept in a listener list that doesn't consume a linkId. athenaTransportLink_SetRoutable(athenaTransportLink, false); parcLog_Info(athenaTransportLink_GetLogger(athenaTransportLink), "new listener established: Name=\"%s\" (%s)", linkName, derivedLinkName); parcMemory_Deallocate(&derivedLinkName); return athenaTransportLink; }