bool NBNSTask(TCPIP_NET_IF* pNetIf) { uint8_t i; TCPIP_UINT16_VAL Type, Class; NBNS_HEADER NBNSHeader; uint8_t NameString[16]; UDP_SOCKET s; int nbnsRxSize; int nbnsTxSize; s = nbnsDcpt.uSkt; switch(nbnsDcpt.sm) { case NBNS_HOME: nbnsDcpt.sm++; break; case NBNS_OPEN_SOCKET: s = UDPOpenServer(IP_ADDRESS_TYPE_IPV4, NBNS_PORT, 0); if(s == INVALID_UDP_SOCKET) break; if(!UDPRemoteBind(s, IP_ADDRESS_TYPE_IPV4, NBNS_PORT, 0)) { UDPClose(s); break; } nbnsDcpt.uSkt = s; nbnsDcpt.sm++; case NBNS_LISTEN: //if(!UDPIsGetReady(s)) nbnsRxSize = UDPIsGetReady(s); if(!nbnsRxSize) { break; } // Respond only to name requests sent to us from nodes on the same subnet // This prevents us from sending out the wrong IP address information if // we haven't gotten a DHCP lease yet. if((remoteNode.IPAddr.Val & pNetIf->netMask.Val) != (pNetIf->netIPAddr.Val & pNetIf->netMask.Val)) { UDPDiscard(s); break; } #ifdef _NBNS_DEBUG nbnsRxOks++; if(nbnsRxSize > nbnsRxMaxSize) { nbnsRxMaxSize = nbnsRxSize; } #endif // _NBNS_DEBUG // Retrieve the NBNS header and de-big-endian it UDPGet(s, &NBNSHeader.TransactionID.v[1]); UDPGet(s, &NBNSHeader.TransactionID.v[0]); UDPGet(s, &NBNSHeader.Flags.v[1]); UDPGet(s, &NBNSHeader.Flags.v[0]); UDPGet(s, &NBNSHeader.Questions.v[1]); UDPGet(s, &NBNSHeader.Questions.v[0]); UDPGet(s, &NBNSHeader.Answers.v[1]); UDPGet(s, &NBNSHeader.Answers.v[0]); UDPGet(s, &NBNSHeader.AuthoritativeRecords.v[1]); UDPGet(s, &NBNSHeader.AuthoritativeRecords.v[0]); UDPGet(s, &NBNSHeader.AdditionalRecords.v[1]); UDPGet(s, &NBNSHeader.AdditionalRecords.v[0]); // Remove all questions while(NBNSHeader.Questions.Val--) { NBNSGetName(s, NameString); UDPGet(s, &i); // <??> Trailing character on string UDPGet(s, &Type.v[1]); // Question type UDPGet(s, &Type.v[0]); UDPGet(s, &Class.v[1]); // Question class UDPGet(s, &Class.v[0]); if(Type.Val == 0x0020u && Class.Val == 0x0001u) { int nIfs, nIx; TCPIP_NET_IF* pIf; const char* netbName; nIfs = TCPIP_STACK_NetworksNo(); for(nIx = 0; nIx < nIfs; nIx++) { pIf = (TCPIP_NET_IF*)TCPIP_STACK_IxToNet(nIx); netbName = TCPIP_STACK_NetBIOSName(pIf); // this checks the IF is up! if(memcmp((void*)NameString, netbName, sizeof(pIf->NetBIOSName)) == 0) { // one of our interfaces has this name nbnsTxSize = UDPIsTxPutReady(s, 64); if(nbnsTxSize) { #ifdef _NBNS_DEBUG nbnsTxOks++; if(nbnsTxSize > nbnsTxMaxSize) { nbnsTxMaxSize = nbnsTxSize; } #endif // _NBNS_DEBUG NBNSHeader.Flags.Val = 0x8400; UDPPut(s, NBNSHeader.TransactionID.v[1]); UDPPut(s, NBNSHeader.TransactionID.v[0]); UDPPut(s, NBNSHeader.Flags.v[1]); UDPPut(s, NBNSHeader.Flags.v[0]); UDPPut(s, 0x00); // 0x0000 Questions UDPPut(s, 0x00); UDPPut(s, 0x00); // 0x0001 Answers UDPPut(s, 0x01); UDPPut(s, 0x00); // 0x0000 Athoritative records UDPPut(s, 0x00); UDPPut(s, 0x00); // 0x0000 Additional records UDPPut(s, 0x00); NBNSPutName(s, netbName); UDPPut(s, 0x00); // 0x0020 Type: NetBIOS UDPPut(s, 0x20); UDPPut(s, 0x00); // 0x0001 Class: Internet UDPPut(s, 0x01); UDPPut(s, 0x00); // 0x00000000 Time To Live UDPPut(s, 0x00); UDPPut(s, 0x00); UDPPut(s, 0x00); UDPPut(s, 0x00); // 0x0006 Data length UDPPut(s, 0x06); UDPPut(s, 0x60); // 0x6000 Flags: H-node, Unique UDPPut(s, 0x00); UDPPut(s, pIf->netIPAddr.v[0]); // Put out IP address UDPPut(s, pIf->netIPAddr.v[1]); UDPPut(s, pIf->netIPAddr.v[2]); UDPPut(s, pIf->netIPAddr.v[3]); // Change the destination address to the unicast address of the last received packet UDPSetDestinationIPAddress(s, IP_ADDRESS_TYPE_IPV4, (IP_MULTI_ADDRESS*)&remoteNode.IPAddr); memcpy((void*)&((IPV4_PACKET*)UDPSocketDcpt[s].pTxPkt)->remoteMACAddr, (const void*)&remoteNode.MACAddr, sizeof(remoteNode.MACAddr)); UDPFlush(s); } #ifdef _NBNS_DEBUG else { nbnsTxFails++; } #endif // _NBNS_DEBUG break; } } } } UDPDiscard(s); break; } return true; }
/***************************************************************************** Function: void DNSClientTask(void) Summary: DNS client state machine Description: Process the DNS client state machine Precondition: DNSClientInit has been called. Parameters: None Return Values: None ***************************************************************************/ void DNSClientTask(void) { uint8_t i; TCPIP_UINT16_VAL w; DNS_HEADER DNSHeader; DNS_ANSWER_HEADER DNSAnswerHeader; switch(smDNS) { case DNS_IDLE: break; // nothing to do case DNS_START: smDNS = DNSRetry(DNS_START); stateStartTime = 0; // flag the first Open try break; case DNS_OPEN_SOCKET: DNSSocket = UDPOpenClient(IP_ADDRESS_TYPE_IPV4, DNS_CLIENT_PORT, (IP_MULTI_ADDRESS*)(DNSServers + vDNSServerIx)); if(DNSSocket == INVALID_UDP_SOCKET) { if(stateStartTime == 0) { stateStartTime = SYS_TICK_Get(); } else if(SYS_TICK_Get() - stateStartTime > (DNS_CLIENT_OPEN_TMO * SYS_TICK_TicksPerSecondGet())) { smDNS = DNS_FAIL_OPEN_TMO; } break; } // got a valid UDP socket UDPSocketSetNet(DNSSocket, pDNSNet); stateStartTime = SYS_TICK_Get(); smDNS = DNS_QUERY; // no break, start sending the query; case DNS_QUERY: if(!UDPIsOpened(DNSSocket) || (UDPIsTxPutReady(DNSSocket, 18 + strlen (DNSHostName)) < (18 + strlen (DNSHostName)))) { if(SYS_TICK_Get() - stateStartTime > (DNS_CLIENT_OPEN_TMO * SYS_TICK_TicksPerSecondGet())) { smDNS = DNS_FAIL_OPEN_TMO; } break; // wait some more } // Put DNS query here SentTransactionID.Val = (uint16_t)rand(); UDPPut(DNSSocket, SentTransactionID.v[1]);// User chosen transaction ID UDPPut(DNSSocket, SentTransactionID.v[0]); UDPPut(DNSSocket, 0x01); // Standard query with recursion UDPPut(DNSSocket, 0x00); UDPPut(DNSSocket, 0x00); // 0x0001 questions UDPPut(DNSSocket, 0x01); UDPPut(DNSSocket, 0x00); // 0x0000 answers UDPPut(DNSSocket, 0x00); UDPPut(DNSSocket, 0x00); // 0x0000 name server resource records UDPPut(DNSSocket, 0x00); UDPPut(DNSSocket, 0x00); // 0x0000 additional records UDPPut(DNSSocket, 0x00); // Put hostname string to resolve DNSPutString(DNSSocket, DNSHostName); UDPPut(DNSSocket, 0x00); // Type: DNS_TYPE_A A (host address) or DNS_TYPE_MX for mail exchange UDPPut(DNSSocket, RecordType); UDPPut(DNSSocket, 0x00); // Class: IN (Internet) UDPPut(DNSSocket, 0x01); UDPFlush(DNSSocket); stateStartTime = SYS_TICK_Get(); smDNS = DNS_GET_RESULT; break; case DNS_GET_RESULT: if(!UDPIsGetReady(DNSSocket)) { if(SYS_TICK_Get() - stateStartTime > (DNS_CLIENT_SERVER_TMO * SYS_TICK_TicksPerSecondGet())) { smDNS = DNS_FAIL_SERVER; } break; } // Retrieve the DNS header and de-big-endian it UDPGet(DNSSocket, &DNSHeader.TransactionID.v[1]); UDPGet(DNSSocket, &DNSHeader.TransactionID.v[0]); // Throw this packet away if it isn't in response to our last query if(DNSHeader.TransactionID.Val != SentTransactionID.Val) { UDPDiscard(DNSSocket); break; } UDPGet(DNSSocket, &DNSHeader.Flags.v[1]); UDPGet(DNSSocket, &DNSHeader.Flags.v[0]); UDPGet(DNSSocket, &DNSHeader.Questions.v[1]); UDPGet(DNSSocket, &DNSHeader.Questions.v[0]); UDPGet(DNSSocket, &DNSHeader.Answers.v[1]); UDPGet(DNSSocket, &DNSHeader.Answers.v[0]); UDPGet(DNSSocket, &DNSHeader.AuthoritativeRecords.v[1]); UDPGet(DNSSocket, &DNSHeader.AuthoritativeRecords.v[0]); UDPGet(DNSSocket, &DNSHeader.AdditionalRecords.v[1]); UDPGet(DNSSocket, &DNSHeader.AdditionalRecords.v[0]); // Remove all questions (queries) while(DNSHeader.Questions.Val--) { DNSDiscardName(DNSSocket); UDPGet(DNSSocket, &w.v[1]); // Question type UDPGet(DNSSocket, &w.v[0]); UDPGet(DNSSocket, &w.v[1]); // Question class UDPGet(DNSSocket, &w.v[0]); } // Scan through answers while(DNSHeader.Answers.Val--) { DNSDiscardName(DNSSocket); // Throw away response name UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[1]); // Response type UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[0]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[1]); // Response class UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[0]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[3]); // Time to live UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[2]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[1]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[0]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[1]); // Response length UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[0]); // Make sure that this is a 4 byte IP address, response type A or MX, class 1 // Check if this is Type A, MX, or AAAA if( DNSAnswerHeader.ResponseClass.Val == 0x0001u) // Internet class { if (DNSAnswerHeader.ResponseType.Val == 0x0001u && DNSAnswerHeader.ResponseLen.Val == 0x0004u) { Flags.bits.AddressValid = true; Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV4; UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[0]); UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[1]); UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[2]); UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[3]); goto DoneSearchingRecords; } else if (DNSAnswerHeader.ResponseType.Val == 0x001Cu && DNSAnswerHeader.ResponseLen.Val == 0x0010u) { if (RecordType != DNS_TYPE_AAAA) { while(DNSAnswerHeader.ResponseLen.Val--) { UDPGet(DNSSocket, &i); } break; } Flags.bits.AddressValid = true; Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV6; UDPGetArray (DNSSocket, (void *)&ResolvedAddress.ipv6Address, sizeof (IPV6_ADDR)); goto DoneSearchingRecords; } else { while(DNSAnswerHeader.ResponseLen.Val--) { UDPGet(DNSSocket, &i); } } } else { while(DNSAnswerHeader.ResponseLen.Val--) { UDPGet(DNSSocket, &i); } } } // Remove all Authoritative Records while(DNSHeader.AuthoritativeRecords.Val--) { DNSDiscardName(DNSSocket); // Throw away response name UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[1]); // Response type UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[0]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[1]); // Response class UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[0]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[3]); // Time to live UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[2]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[1]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[0]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[1]); // Response length UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[0]); // Make sure that this is a 4 byte IP address, response type A or MX, class 1 // Check if this is Type A if( DNSAnswerHeader.ResponseClass.Val == 0x0001u) // Internet class { if (DNSAnswerHeader.ResponseType.Val == 0x0001u && DNSAnswerHeader.ResponseLen.Val == 0x0004u) { Flags.bits.AddressValid = true; Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV4; UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[0]); UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[1]); UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[2]); UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[3]); goto DoneSearchingRecords; } else if (DNSAnswerHeader.ResponseType.Val == 0x001Cu && DNSAnswerHeader.ResponseLen.Val == 0x0010u) { if (RecordType != DNS_TYPE_AAAA) { while(DNSAnswerHeader.ResponseLen.Val--) { UDPGet(DNSSocket, &i); } break; } Flags.bits.AddressValid = true; Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV6; UDPGetArray (DNSSocket, (void *)&ResolvedAddress.ipv6Address, sizeof (IPV6_ADDR)); goto DoneSearchingRecords; } else { while(DNSAnswerHeader.ResponseLen.Val--) { UDPGet(DNSSocket, &i); } } } else { while(DNSAnswerHeader.ResponseLen.Val--) { UDPGet(DNSSocket, &i); } } } // Remove all Additional Records while(DNSHeader.AdditionalRecords.Val--) { DNSDiscardName(DNSSocket); // Throw away response name UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[1]); // Response type UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[0]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[1]); // Response class UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[0]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[3]); // Time to live UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[2]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[1]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[0]); UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[1]); // Response length UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[0]); // Make sure that this is a 4 byte IP address, response type A or MX, class 1 // Check if this is Type A if( DNSAnswerHeader.ResponseClass.Val == 0x0001u) // Internet class { if (DNSAnswerHeader.ResponseType.Val == 0x0001u && DNSAnswerHeader.ResponseLen.Val == 0x0004u) { Flags.bits.AddressValid = true; Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV4; UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[0]); UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[1]); UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[2]); UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[3]); goto DoneSearchingRecords; } else if (DNSAnswerHeader.ResponseType.Val == 0x001Cu && DNSAnswerHeader.ResponseLen.Val == 0x0010u) { if (RecordType != DNS_TYPE_AAAA) { while(DNSAnswerHeader.ResponseLen.Val--) { UDPGet(DNSSocket, &i); } break; } Flags.bits.AddressValid = true; Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV6; UDPGetArray (DNSSocket, (void *)&ResolvedAddress.ipv6Address, sizeof (IPV6_ADDR)); goto DoneSearchingRecords; } else { while(DNSAnswerHeader.ResponseLen.Val--) { UDPGet(DNSSocket, &i); } } } else { while(DNSAnswerHeader.ResponseLen.Val--) { UDPGet(DNSSocket, &i); } } } DoneSearchingRecords: UDPDiscard(DNSSocket); _DNSReleaseSocket(); if(Flags.bits.AddressValid) { smDNS = DNS_DONE; } else { smDNS = DNSRetry(DNS_FAIL_SERVER); } break; // done case DNS_FAIL_ARP: // see if there is other server we may try smDNS = DNSRetry(DNS_FAIL_ARP); break; case DNS_FAIL_SERVER: smDNS = DNSRetry(DNS_FAIL_SERVER); break; default: // DNS_DONE, DNS_FAIL_ARP_TMO, DNS_FAIL_OPEN_TMO, DNS_FAIL_SERVER_TMO // either done or some error state break; } #if DNS_CLIENT_VERSION_NO >= 2 dnsTickPending = 0; #endif // DNS_CLIENT_VERSION_NO >= 2 }
// // Main application entry point. // int main(void) { #if defined(HOST_CM_TEST) DWORD t1 = 0; char st[80]; BOOL host_scan = FALSE; UINT16 scan_count = 0; #endif static IPV4_ADDR dwLastIP[sizeof (TCPIP_HOSTS_CONFIGURATION) / sizeof (*TCPIP_HOSTS_CONFIGURATION)]; int i, nNets; #if defined(SYS_USERIO_ENABLE) static SYS_TICK startTick = 0; int32_t LEDstate=SYS_USERIO_LED_DEASSERTED; #endif // defined(SYS_USERIO_ENABLE) TCPIP_NET_HANDLE netH; const char *netName=0; const char *netBiosName; #if defined (TCPIP_STACK_USE_ZEROCONF_MDNS_SD) char mDNSServiceName[] = "MyWebServiceNameX "; // base name of the service Must not exceed 16 bytes long // the last digit will be incremented by interface #endif // defined (TCPIP_STACK_USE_ZEROCONF_MDNS_SD) // perform system initialization if(!SYS_Initialize()) { return 0; } SYS_CONSOLE_MESSAGE("\r\n\n\n --- TCPIP Demo Starts! --- \r\n"); SYS_OUT_MESSAGE("TCPIPStack " TCPIP_STACK_VERSION " "" "); // Initialize the TCPIP stack if (!TCPIP_STACK_Init(TCPIP_HOSTS_CONFIGURATION, sizeof (TCPIP_HOSTS_CONFIGURATION) / sizeof (*TCPIP_HOSTS_CONFIGURATION), TCPIP_STACK_MODULE_CONFIG_TBL, sizeof (TCPIP_STACK_MODULE_CONFIG_TBL) / sizeof (*TCPIP_STACK_MODULE_CONFIG_TBL))) { return 0; } // Display the names associated with each interface // Perform mDNS registration if mDNS is enabled nNets = TCPIP_STACK_NetworksNo(); for(i = 0; i < nNets; i++) { netH = TCPIP_STACK_IxToNet(i); netName = TCPIP_STACK_NetName(netH); netBiosName = TCPIP_STACK_NetBIOSName(netH); #if defined(TCPIP_STACK_USE_NBNS) SYS_CONSOLE_PRINT(" Interface %s on host %s - NBNS enabled\r\n", netName, netBiosName); #else SYS_CONSOLE_PRINT(" Interface %s on host %s - NBNS disabled\r\n", netName, netBiosName); #endif // defined(TCPIP_STACK_USE_NBNS) #if defined (TCPIP_STACK_USE_ZEROCONF_MDNS_SD) mDNSServiceName[sizeof(mDNSServiceName) - 2] = '1' + i; mDNSServiceRegister( netH , mDNSServiceName // name of the service ,"_http._tcp.local" // type of the service ,80 // TCP or UDP port, at which this service is available ,((const BYTE *)"path=/index.htm") // TXT info ,1 // auto rename the service when if needed ,NULL // no callback function ,NULL); // no application context #endif //TCPIP_STACK_USE_ZEROCONF_MDNS_SD } #if defined (TCPIP_STACK_USE_IPV6) TCPIP_ICMPV6_RegisterCallback(ICMPv6Callback); #endif #if defined(TCPIP_STACK_USE_ICMP_CLIENT) ICMPRegisterCallback(PingProcessIPv4); #endif #if defined(TCPIP_STACK_USE_EVENT_NOTIFICATION) TCPIP_NET_HANDLE hWiFi = TCPIP_STACK_NetHandle("MRF24W"); if (hWiFi) { TCPIP_STACK_RegisterHandler(hWiFi, TCPIP_EV_RX_ALL | TCPIP_EV_TX_ALL | TCPIP_EV_RXTX_ERRORS, StackNotification, 0); } #endif // defined(TCPIP_STACK_USE_EVENT_NOTIFICATION) #if defined(WF_UPDATE_FIRMWARE_UART_24G) extern bool WF_FirmwareUpdate_Uart_24G(void); WF_FirmwareUpdate_Uart_24G(); #endif // Now that all items are initialized, begin the co-operative // multitasking loop. This infinite loop will continuously // execute all stack-related tasks, as well as your own // application's functions. Custom functions should be added // at the end of this loop. // Note that this is a "co-operative mult-tasking" mechanism // where every task performs its tasks (whether all in one shot // or part of it) and returns so that other tasks can do their // job. // If a task needs very long time to do its job, it must be broken // down into smaller pieces so that other tasks can have CPU time. while (1) { SYS_Tasks(); #if defined(SYS_USERIO_ENABLE) // Blink LED0 (right most one) every second. if (SYS_TICK_Get() - startTick >= SYS_TICK_TicksPerSecondGet() / 2ul) { startTick = SYS_TICK_Get(); LEDstate ^= SYS_USERIO_LED_ASSERTED; SYS_USERIO_SetLED(SYS_USERIO_LED_0, LEDstate); } #endif // defined(SYS_USERIO_ENABLE) // This task performs normal stack task including checking // for incoming packet, type of packet and calling // appropriate stack entity to process it. TCPIP_STACK_Task(); // Process application specific tasks here. // For this demo app, this will include the Generic TCP // client and servers, and the SNMP, Ping, and SNMP Trap // demos. Following that, we will process any IO from // the inputs on the board itself. // Any custom modules or processing you need to do should // go here. #if defined(TCPIP_STACK_USE_TCP) && defined(APP_USE_FTP_CLIENT_DEMO) FTPClient(); #endif #if defined(TCPIP_STACK_USE_TCP) && defined(APP_USE_GENERIC_TCP_CLIENT_DEMO) GenericTCPClient(); #endif #if defined(TCPIP_STACK_USE_TCP) && defined(APP_USE_GENERIC_TCP_SERVER_DEMO) GenericTCPServer(); #endif #if defined(TCPIP_STACK_USE_SMTP_CLIENT) && defined(APP_USE_SMTP_CLIENT_DEMO) SMTPDemo(); #endif #if (defined(TCPIP_STACK_USE_ICMP_CLIENT) || defined (TCPIP_STACK_USE_IPV6)) && defined(APP_USE_PING_DEMO) // use ping on the default interface PingDemoTask(); #endif #if defined(TCPIP_STACK_USE_SNMP_SERVER) && !defined(SNMP_TRAP_DISABLED) // User should use one of the following SNMP demo // This routine demonstrates V1 or V2 trap formats with one variable binding. //SNMPTrapDemo(); //This function sends the both SNMP trap version1 and 2 type of notifications #if defined(SNMP_STACK_USE_V2_TRAP) || defined(SNMP_V1_V2_TRAP_WITH_SNMPV3) //This routine provides V2 format notifications with multiple (3) variable bindings //User should modify this routine to send v2 trap format notifications with the required varbinds. SNMPV2TrapDemo(); //This function sends the SNMP trap version 2 type of notifications #endif /* SNMPSendTrap() is used to send trap notification to previously configured ip address if trap notification is enabled. There are different trap notification code. The current implementation sends trap for authentication failure (4). PreCondition: If application defined event occurs to send the trap. Declare a notification flag and update as the event occurs. Uncomment the below function if the application requires. if(notification flag is updated by the application as a predefined event occured) { SNMPSendTrap(); } */ #endif #if defined(TCPIP_STACK_USE_BERKELEY_API) && defined(APP_USE_BERKELEY_API_DEMO) BerkeleyTCPClientDemo(); BerkeleyTCPServerDemo(); BerkeleyUDPClientDemo(0); #endif // If the local IP address has changed (ex: due to DHCP lease change) // write the new IP address to the console display, UART, and Announce // service // We use the default interface for (i = 0; i < sizeof (TCPIP_HOSTS_CONFIGURATION) / sizeof (*TCPIP_HOSTS_CONFIGURATION); i++) { netH = TCPIP_STACK_NetHandle(TCPIP_HOSTS_CONFIGURATION[i].interface); if ((uint32_t) dwLastIP[i].Val != TCPIP_STACK_NetAddress(netH)) { dwLastIP[i].Val = TCPIP_STACK_NetAddress(netH); SYS_CONSOLE_PRINT("Interface Name is: %s\r\n", TCPIP_HOSTS_CONFIGURATION[i].interface); SYS_CONSOLE_MESSAGE("New IP Address is: "); DisplayIPValue(dwLastIP[i]); SYS_CONSOLE_MESSAGE("\r\n"); } } #if defined(TCPIP_STACK_USE_EVENT_NOTIFICATION) if (stackNotifyCnt) { stackNotifyCnt = 0; ProcessNotification(stackNotifyHandle); } #endif // defined(TCPIP_STACK_USE_EVENT_NOTIFICATION) #if defined(WF_UPDATE_FIRMWARE_TCPCLIENT_24G) void WF_FirmwareUpdate_TcpClient_24G(void); WF_FirmwareUpdate_TcpClient_24G(); #endif //defined(WF_UPDATE_FIRMWARE_TCPCLIENT_24G) #if defined(HOST_CM_TEST) switch (g_event) { case WF_EVENT_CONNECTION_PERMANENTLY_LOST: case WF_EVENT_CONNECTION_FAILED: g_event = 0xff; // clear current event // if host scan is active, it can be forced inactive by connection/re-connection process // so just reset host scan state to inactive. host_scan = FALSE; // host scan inactive SYS_CONSOLE_MESSAGE("Reconnecting....\r\n"); WF_Connect(); break; case WF_EVENT_CONNECTION_SUCCESSFUL: g_event = 0xff; // clear current event // if host scan is active, it can be forced inactive by connection/re-connection process // so just reset host scan state to inactive. host_scan = FALSE; // host scan inactive break; case WF_EVENT_SCAN_RESULTS_READY: g_event = 0xff; // clear current event host_scan = FALSE; // host scan inactive // Scan results are valid - OK to retrieve if (SCANCXT.numScanResults > 0) { SCAN_SET_DISPLAY(SCANCXT.scanState); SCANCXT.displayIdx = 0; while (IS_SCAN_STATE_DISPLAY(SCANCXT.scanState)) WFDisplayScanMgr(); } break; case WF_EVENT_CONNECTION_TEMPORARILY_LOST: // This event can happened when CM in module is enabled. g_event = 0xff; // clear current event // if host scan is active, it can be forced inactive by connection/re-connection process // so just reset host scan state to inactive. host_scan = FALSE; // host scan inactive break; default: //sprintf(st,"skip event = %d\r\n",g_event); //SYS_CONSOLE_MESSAGE(st); break; } if (g_DhcpSuccessful) { /* Send and Receive UDP packets */ if(UDPIsOpened(socket1)) { // UDP TX every 10 msec if(SYS_TICK_Get() - timeudp >= SYS_TICK_TicksPerSecondGet() / 100) { timeudp = SYS_TICK_Get(); tx_number++; LED0_IO ^= 1; sprintf(str,"rem=%12lu",tx_number); for(cntstr=16;cntstr<999;cntstr++) str[cntstr]=cntstr; str[999]=0; // Send tx_number (formatted in a string) if(UDPIsTxPutReady(socket1,1000)!=0) { UDPPutString(socket1,(BYTE *)str); UDPFlush(socket1); SYS_CONSOLE_MESSAGE("."); } } // UDP RX tx_number of remote board if(UDPIsGetReady(socket1)!=0) { LED1_IO ^= 1; UDPGetArray(socket1,(BYTE *)str,1000); str[16]=0; //sprintf((char*)LCDText,"%sloc=%12lu",str,tx_number); // Write on EXP16 LCD local and remote TX number //strcpypgm2ram(LCDText,str); //LCDUpdate(); SYS_CONSOLE_MESSAGE("Rx"); } } // Do host scan if((SYS_TICK_Get() - t1) >= SYS_TICK_TicksPerSecondGet() * 20) { t1 = SYS_TICK_Get(); if (!host_scan) // allow host scan if currently inactive { sprintf(st,"%d Scanning ..... event = %d\r\n",++scan_count, g_event); SYS_CONSOLE_MESSAGE(st); host_scan = TRUE; // host scan active WF_Scan(0xff); // scan on all channels } } } // DHCP status #endif //HOST_CM_TEST } }
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; } } }
/***************************************************************************** Function: int sendto(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen) Summary: This function used to send the data for both connection oriented and connection-less sockets. Description: The sendto function is used to send outgoing data on a socket. The destination address is given by to and tolen. Both Datagram and stream sockets are supported. Precondition: socket function should be called. Parameters: s - Socket descriptor returned from a previous call to socket. buf - application data buffer containing data to transmit. len - length of data in bytes. flags - message flags. Currently this field is not supported. to - Optional pointer to the the sockaddr structure containing the destination address. If NULL, the currently bound remote port and IP address are used as the destination. tolen - length of the sockaddr structure. Returns: On success, sendto returns number of bytes sent. In case of error returns SOCKET_ERROR (and errno set accordingly). Remarks: None. ***************************************************************************/ int sendto( SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen ) { struct BSDSocket *socket; UDP_SOCKET_DCPT* udpSkt; int size = SOCKET_ERROR; NODE_INFO remoteInfo; uint16_t wRemotePort; struct sockaddr_in local; if( s >= BSD_SOCKET_COUNT ) { errno = EBADF; return SOCKET_ERROR; } socket = &BSDSocketArray[s]; if(socket->bsdState == SKT_CLOSED) { errno = EBADF; return SOCKET_ERROR; } if(socket->SocketType == SOCK_DGRAM) //UDP { // Decide the destination IP address and port remoteInfo.IPAddr.Val = socket->remoteIP; wRemotePort = socket->remotePort; if(to) { if((unsigned int)tolen != sizeof(struct sockaddr_in)) { errno = EFAULT; return SOCKET_ERROR; } wRemotePort = ((struct sockaddr_in*)to)->sin_port; remoteInfo.IPAddr.Val = ((struct sockaddr_in*)to)->sin_addr.s_addr; // Implicitly bind the socket if it isn't already if(socket->bsdState == SKT_CREATED) { memset(&local, 0x00, sizeof(local)); if(bind(s, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR) return SOCKET_ERROR; } } if(remoteInfo.IPAddr.Val == IP_ADDR_ANY) remoteInfo.IPAddr.Val = 0xFFFFFFFFu; // Set the remote IP and MAC address if it is different from what we already have stored in the UDP socket udpSkt = UDPSocketDcpt + socket->SocketID; if(TCPIP_IPV4_GetDestAddress(udpSkt->pTxPkt).Val != remoteInfo.IPAddr.Val) { TCPIP_IPV4_SetDestAddress(udpSkt->pTxPkt, remoteInfo.IPAddr.Val); if(!ARPIsResolved(UDPSocketGetNet(socket->SocketID), &remoteInfo.IPAddr, &((IPV4_PACKET*)udpSkt->pTxPkt)->remoteMACAddr)) { errno = EINPROGRESS; return SOCKET_ERROR; } } // Select the UDP socket and see if we can write to it if(UDPIsTxPutReady(socket->SocketID, len)) { // Set the proper remote port udpSkt->remotePort = wRemotePort; // Write data and send UDP datagram size = UDPPutArray(socket->SocketID, (uint8_t*)buf, len); UDPFlush(socket->SocketID); return size; } } else if(socket->SocketType == SOCK_STREAM) //TCP will only send to the already established socket. { if(socket->bsdState != SKT_EST) { errno = ENOTCONN; return SOCKET_ERROR; } if(HandlePossibleTCPDisconnection(s)) { errno = ECONNRESET; return SOCKET_ERROR; } // Handle special case were 0 return value is okay if(len == 0) return 0; // Write data to the socket. If one or more bytes were written, then // return this value. Otherwise, fail and return SOCKET_ERROR. size = TCPPutArray(socket->SocketID, (uint8_t*)buf, len); if(size) return size; } errno = EWOULDBLOCK; return SOCKET_ERROR; }
/********************************************************************* * Function: void NBNSTask(NET_CONFIG* pConfig) * * PreCondition: None * * Input: pConfig - interface * * Output: None * * Side Effects: None * * Overview: Sends responses to NetBIOS name requests * * Note: None ********************************************************************/ void NBNSTask(NET_CONFIG* pConfig) { uint8_t i; TCPIP_UINT16_VAL Type, Class; NBNS_HEADER NBNSHeader; uint8_t NameString[16]; int netIx; UDP_SOCKET s; netIx = _TCPIPStackNetIx(pConfig); s = MySocket[netIx]; switch(smNBNS[netIx]) { case NBNS_HOME: smNBNS[netIx]++; break; case NBNS_OPEN_SOCKET: MySocket[netIx] = UDPOpen(0,UDP_OPEN_SERVER,NBNS_PORT,NBNS_PORT); if(MySocket[netIx] == INVALID_UDP_SOCKET) break; UDPSocketSetNet(MySocket[netIx], pConfig); smNBNS[netIx]++; case NBNS_LISTEN: if(!UDPIsGetReady(s)) { break; } // Respond only to name requests sent to us from nodes on the same subnet // This prevents us from sending out the wrong IP address information if // we haven't gotten a DHCP lease yet. if((remoteNode.IPAddr.Val & pConfig->MyMask.Val) != (pConfig->MyIPAddr.Val & pConfig->MyMask.Val)) { UDPDiscard(s); break; } // Retrieve the NBNS header and de-big-endian it UDPGet(s, &NBNSHeader.TransactionID.v[1]); UDPGet(s, &NBNSHeader.TransactionID.v[0]); UDPGet(s, &NBNSHeader.Flags.v[1]); UDPGet(s, &NBNSHeader.Flags.v[0]); UDPGet(s, &NBNSHeader.Questions.v[1]); UDPGet(s, &NBNSHeader.Questions.v[0]); UDPGet(s, &NBNSHeader.Answers.v[1]); UDPGet(s, &NBNSHeader.Answers.v[0]); UDPGet(s, &NBNSHeader.AuthoritativeRecords.v[1]); UDPGet(s, &NBNSHeader.AuthoritativeRecords.v[0]); UDPGet(s, &NBNSHeader.AdditionalRecords.v[1]); UDPGet(s, &NBNSHeader.AdditionalRecords.v[0]); // Remove all questions while(NBNSHeader.Questions.Val--) { NBNSGetName(s, NameString); UDPGet(s, &i); // <??> Trailing character on string UDPGet(s, &Type.v[1]); // Question type UDPGet(s, &Type.v[0]); UDPGet(s, &Class.v[1]); // Question class UDPGet(s, &Class.v[0]); if(Type.Val == 0x0020u && Class.Val == 0x0001u && memcmp((void*)NameString, (void*)pConfig->NetBIOSName, sizeof(pConfig->NetBIOSName)) == 0) { if(UDPIsTxPutReady(s, 64)) { NBNSHeader.Flags.Val = 0x8400; UDPPut(s, NBNSHeader.TransactionID.v[1]); UDPPut(s, NBNSHeader.TransactionID.v[0]); UDPPut(s, NBNSHeader.Flags.v[1]); UDPPut(s, NBNSHeader.Flags.v[0]); UDPPut(s, 0x00); // 0x0000 Questions UDPPut(s, 0x00); UDPPut(s, 0x00); // 0x0001 Answers UDPPut(s, 0x01); UDPPut(s, 0x00); // 0x0000 Athoritative records UDPPut(s, 0x00); UDPPut(s, 0x00); // 0x0000 Additional records UDPPut(s, 0x00); NBNSPutName(s, pConfig->NetBIOSName); UDPPut(s, 0x00); // 0x0020 Type: NetBIOS UDPPut(s, 0x20); UDPPut(s, 0x00); // 0x0001 Class: Internet UDPPut(s, 0x01); UDPPut(s, 0x00); // 0x00000000 Time To Live UDPPut(s, 0x00); UDPPut(s, 0x00); UDPPut(s, 0x00); UDPPut(s, 0x00); // 0x0006 Data length UDPPut(s, 0x06); UDPPut(s, 0x60); // 0x6000 Flags: H-node, Unique UDPPut(s, 0x00); UDPPut(s, pConfig->MyIPAddr.v[0]); // Put out IP address UDPPut(s, pConfig->MyIPAddr.v[1]); UDPPut(s, pConfig->MyIPAddr.v[2]); UDPPut(s, pConfig->MyIPAddr.v[3]); // Change the destination address to the unicast address of the last received packet TCPIP_IPV4_SetDestAddress(UDPSocketDcpt[s].pTxPkt,remoteNode.IPAddr.Val); memcpy((void*)&UDPSocketDcpt[s].pTxPkt->remoteMACAddr, (const void*)&remoteNode.MACAddr, sizeof(remoteNode.MACAddr)); UDPFlush(s); } } } UDPDiscard(s); break; } }