void ANNOUNCE_DeInit(const TCPIP_STACK_MODULE_CTRL* const stackData) { SGL_LIST_NODE* node; announceEventPending = false; if (announceDHCPHandler != NULL) { DHCPDeRegisterHandler(announceDHCPHandler); announceDHCPHandler = NULL; } #if defined (TCPIP_STACK_USE_IPV6) if (announceIPV6Handler != NULL) { TCPIP_IPV6_DeRegisterHandler(announceIPV6Handler); announceIPV6Handler = NULL; } #endif // Free all announce events while ((node = SingleListRemoveHead(&announceEvents)) != NULL) { TCPIP_HEAP_Free (announceMemH, node); } announceMemH = 0; }
static void _ARPCleanupClients(void) { SGL_LIST_NODE* aNode; while( (aNode = SingleListRemoveHead(&arpRegisteredUsers)) != 0 ) { TCPIP_HEAP_Free(arpMemH, aNode); } }
// Deletes an entry to make room in the hash table. // This shouldn't normally occur if ARPTask() // does its job of periodically performing the cache clean-up. // However, since the threshold can be dynamically adjusted, // the situation could still occur OA_HASH_ENTRY* OAHashDeleteEntry(OA_HASH_DCPT* pOH) { ARP_CACHE_DCPT *pArpDcpt; ARP_HASH_ENTRY *pE; SGL_LIST_NODE *pN; SINGLE_LIST *pRemList = 0; pArpDcpt = (ARP_CACHE_DCPT*)pOH; if( (pN = pArpDcpt->incompleteList.head) != 0) { pE = (ARP_HASH_ENTRY*) ((uint8_t*)pN - offsetof(ARP_HASH_ENTRY, next)); if( (arpTimeSeconds - pE->tInsert) >= ARP_CACHE_PENDING_ENTRY_TMO) { // we remove this one pRemList = &pArpDcpt->incompleteList; } } if(pRemList == 0) { // no luck with the incomplete list; use the complete one pRemList = &pArpDcpt->completeList; } pN = SingleListRemoveHead(pRemList); if(pN) { pE = (ARP_HASH_ENTRY*) ((uint8_t*)pN - offsetof(ARP_HASH_ENTRY, next)); return &pE->hEntry; } // it's possible to be unable to make room in the cache // for example, too many permanent entries added... return 0; }
// called after service needed reported // maintain the queues void ARPTask(void) { int netIx, purgeIx; ARP_HASH_ENTRY *pE; ARP_CACHE_DCPT *pArpDcpt; SGL_LIST_NODE *pN; NET_CONFIG *pIf; int nArpIfs; nArpIfs = TCPIP_STACK_NetworksNo(); for(netIx = 0, pArpDcpt = arpCache; netIx < nArpIfs; netIx++, pArpDcpt++) { pIf = (NET_CONFIG*)TCPIP_STACK_IxToNet(netIx); // process the incomplete queue // see if there's something to remove while( (pN = pArpDcpt->incompleteList.head) != 0) { pE = (ARP_HASH_ENTRY*) ((uint8_t*)pN - offsetof(ARP_HASH_ENTRY, next)); if( (arpTimeSeconds - pE->tInsert) >= ARP_CACHE_PENDING_ENTRY_TMO) { // expired, remove it OAHashRemoveEntry(pArpDcpt->cacheDcpt, &pE->hEntry); SingleListRemoveHead(&pArpDcpt->incompleteList); } else { // this list is ordered, we can safely break out break; } } // see if we have to query again for(pN = pArpDcpt->incompleteList.head; pN != 0; pN = pN->next) { pE = (ARP_HASH_ENTRY*) ((uint8_t*)pN - offsetof(ARP_HASH_ENTRY, next)); if( (arpTimeSeconds - pE->tInsert) >= pE->nRetries * ARP_CACHE_PENDING_RETRY_TMO) { // expired, retry it ARP_SendIfPkt(pIf, ARP_OPERATION_REQ, (uint32_t)pIf->MyIPAddr.Val, pE->ipAddress, &arpBcastAdd); pE->nRetries++; } } // see the completed entries queue while( (pN = pArpDcpt->completeList.head) != 0) { pE = (ARP_HASH_ENTRY*) ((uint8_t*)pN - offsetof(ARP_HASH_ENTRY, next)); if( (arpTimeSeconds - pE->tInsert) >= ARP_CACHE_SOLVED_ENTRY_TMO) { // expired, remove it OAHashRemoveEntry(pArpDcpt->cacheDcpt, &pE->hEntry); SingleListRemoveHead(&pArpDcpt->completeList); } else { // this list is ordered, we can safely break out break; } } // finally purge, if needed if(pArpDcpt->cacheDcpt->fullSlots >= pArpDcpt->purgeThres) { for(purgeIx = 0; purgeIx < pArpDcpt->purgeQuanta; purgeIx++) { pN = SingleListRemoveHead(&pArpDcpt->completeList); if(pN) { pE = (ARP_HASH_ENTRY*) ((uint8_t*)pN - offsetof(ARP_HASH_ENTRY, next)); OAHashRemoveEntry(pArpDcpt->cacheDcpt, &pE->hEntry); } else { // no more entries break; } } } } arpTickPending = 0; }
void ANNOUNCE_Send(void) { UDP_SOCKET announceSocket; int netIx; uint16_t dataLen; uint16_t minimumDataLen; uint16_t txLen; bool truncated; NET_CONFIG * pNetIf; ANNOUNCE_LIST_NODE * node = (ANNOUNCE_LIST_NODE *)announceEvents.head; ANNOUNCE_FIELD_PAYLOAD payloadType; uint16_t terminatorLen = strlen ((const char *)announceFieldTerminator); #if defined (TCPIP_STACK_USE_IPV6) IPV6_ADDR_STRUCT * addressPointer; #endif while (node != NULL) { pNetIf = (NET_CONFIG *)node->handle; netIx = TCPIP_STACK_NetIx (pNetIf); truncated = false; dataLen = ((terminatorLen + 1) * 4) + sizeof (IPV4_ADDR) + sizeof (MAC_ADDR); dataLen += strlen(TCPIP_HOSTS_CONFIGURATION[netIx].interface); dataLen += strlen((char *)pNetIf->NetBIOSName); minimumDataLen = dataLen + 1 + terminatorLen; if(!MACIsLinked(_TCPIPStackNetToMac(pNetIf))) // Check for link before blindly opening and transmitting (similar to DHCP case) { return; } announceSocket = UDPOpenClient(IP_ADDRESS_TYPE_IPV4, ANNOUNCE_PORT, 0); if (announceSocket == INVALID_UDP_SOCKET) { return; } UDPSocketSetNet (announceSocket, pNetIf); #if defined (TCPIP_STACK_USE_IPV6) addressPointer = (IPV6_ADDR_STRUCT *)ipv6Config[netIx].listIpv6UnicastAddresses.head; while(addressPointer != NULL) { dataLen += sizeof (IPV6_ADDR) + 1 + terminatorLen; addressPointer = addressPointer->next; } addressPointer = (IPV6_ADDR_STRUCT *)ipv6Config[netIx].listIpv6MulticastAddresses.head; while(addressPointer != NULL) { dataLen += sizeof (IPV6_ADDR) + 1 + terminatorLen; addressPointer = addressPointer->next; } #endif if (dataLen > ANNOUNCE_MAX_PAYLOAD) { dataLen = ANNOUNCE_MAX_PAYLOAD; } if ((txLen = UDPIsTxPutReady(announceSocket, dataLen)) < dataLen) { truncated = true; if ((txLen = UDPIsTxPutReady(announceSocket, minimumDataLen)) < minimumDataLen) { UDPClose (announceSocket); return; } } // Put Mac Address payloadType = ANNOUNCE_FIELD_MAC_ADDR; UDPPut (announceSocket, payloadType); UDPPutArray(announceSocket, (const uint8_t *)&pNetIf->MyMACAddr, sizeof (MAC_ADDR)); UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen); if (truncated) { payloadType = ANNOUNCE_FIELD_TRUNCATED; UDPPut (announceSocket, payloadType); UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen); } // Put Mac Type payloadType = ANNOUNCE_FIELD_MAC_TYPE; UDPPut (announceSocket, payloadType); UDPPutArray(announceSocket, (const uint8_t *)TCPIP_HOSTS_CONFIGURATION[netIx].interface, strlen ((const char *)TCPIP_HOSTS_CONFIGURATION[netIx].interface)); UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen); // Put Host Name payloadType = ANNOUNCE_FIELD_HOST_NAME; UDPPut (announceSocket, payloadType); UDPPutArray(announceSocket, (const uint8_t *)&pNetIf->NetBIOSName, strlen((char*)pNetIf->NetBIOSName)); UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen); // Put IPv4 Address payloadType = ANNOUNCE_FIELD_IPV4_ADDRESS; UDPPut (announceSocket, payloadType); UDPPutArray(announceSocket, (const uint8_t *)&pNetIf->MyIPAddr, sizeof (IP_ADDR)); UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen); #if defined (TCPIP_STACK_USE_IPV6) // Put IPv6 unicast addresses minimumDataLen = sizeof (IPV6_ADDR) + 1 + terminatorLen; addressPointer = (IPV6_ADDR_STRUCT *)ipv6Config[netIx].listIpv6UnicastAddresses.head; payloadType = ANNOUNCE_FIELD_IPV6_UNICAST; while(addressPointer != NULL && (UDPIsTxPutReady(announceSocket, minimumDataLen) >= minimumDataLen)) { UDPPut (announceSocket, payloadType); UDPPutArray(announceSocket, (const uint8_t *)&addressPointer->address, sizeof (IPV6_ADDR)); UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen); addressPointer = addressPointer->next; } // Put IPv6 multicast listeners addressPointer = (IPV6_ADDR_STRUCT *)ipv6Config[netIx].listIpv6MulticastAddresses.head; payloadType = ANNOUNCE_FIELD_IPV6_MULTICAST; while(addressPointer != NULL && (UDPIsTxPutReady(announceSocket, minimumDataLen) >= minimumDataLen)) { UDPPut (announceSocket, payloadType); UDPPutArray(announceSocket, (const uint8_t *)&addressPointer->address, sizeof (IPV6_ADDR)); UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen); addressPointer = addressPointer->next; } #endif UDPFlush (announceSocket); UDPClose (announceSocket); SingleListRemoveHead(&announceEvents); TCPIP_HEAP_Free (announceMemH, node); node = (ANNOUNCE_LIST_NODE *)announceEvents.head; if (node == NULL) { announceEventPending = false; } } }