error_t ipv4SelectSourceAddr(NetInterface **interface, Ipv4Addr destAddr, Ipv4Addr *srcAddr) { //Use default network interface? if(*interface == NULL) *interface = tcpIpStackGetDefaultInterface(); //Select the most appropriate source address *srcAddr = (*interface)->ipv4Config.addr; //Successful processing return NO_ERROR; }
error_t dnsResolve(NetInterface *interface, const char_t *name, IpAddr *ipAddr) { error_t error; uint_t i; size_t length; uint16_t identifier; IpAddr serverIpAddr; Socket *socket; DnsHeader *dnsMessage; //Debug message TRACE_INFO("Trying to resolve %s...\r\n", name); //Use default network interface? if(!interface) interface = tcpIpStackGetDefaultInterface(); //Allocate a memory buffer to hold DNS messages dnsMessage = memPoolAlloc(DNS_MESSAGE_MAX_SIZE); //Failed to allocate memory? if(!dnsMessage) return ERROR_OUT_OF_MEMORY; //Open a UDP socket socket = socketOpen(SOCKET_TYPE_DGRAM, SOCKET_PROTOCOL_UDP); //Failed to open socket? if(!socket) { //Free previously allocated memory osMemFree(dnsMessage); //Return status code return ERROR_OPEN_FAILED; } #if (IPV4_SUPPORT == ENABLED) //IP address of the DNS server serverIpAddr.length = sizeof(Ipv4Addr); serverIpAddr.ipv4Addr = interface->ipv4Config.dnsServer[0]; #elif (IPV6_SUPPORT == ENABLED) //IP address of the DNS server serverIpAddr.length = sizeof(Ipv6Addr); serverIpAddr.ipv6Addr = interface->ipv6Config.dnsServer[0]; #endif //Associate the socket with the relevant interface error = socketBindToInterface(socket, interface); //Any error to report? if(error) { //Free previously allocated memory osMemFree(dnsMessage); //Close socket socketClose(socket); //Return status code return error; } //Connect the newly created socket to the primary DNS server error = socketConnect(socket, &serverIpAddr, DNS_PORT); //Failed to connect? if(error) { //Free previously allocated memory osMemFree(dnsMessage); //Close socket socketClose(socket); //Return status code return error; } //An identifier is used by the client to match replies //with corresponding requests identifier = rand(); //Try to retransmit the DNS message if the previous query timed out for(i = 0; i < DNS_MAX_RETRIES; i++) { //Send DNS query message error = dnsSendQuery(socket, dnsMessage, identifier, name); //Failed to send message ? if(error) break; //Adjust receive timeout error = socketSetTimeout(socket, DNS_REQUEST_TIMEOUT); //Any error to report? if(error) break; //Wait for the server response error = socketReceive(socket, dnsMessage, DNS_MESSAGE_MAX_SIZE, &length, 0); //Any response from the specified DNS server? if(!error) { //Parse DNS response error = dnsParseResponse(dnsMessage, length, identifier, ipAddr); //DNS response successfully decoded? if(!error) break; } } //The maximum number of retransmissions has been reached? if(i >= DNS_MAX_RETRIES) error = ERROR_TIMEOUT; //Free previously allocated memory osMemFree(dnsMessage); //Close socket socketClose(socket); //Debug message if(!error) { //Name resolution succeeds TRACE_INFO("Host name resolved to %s...\r\n", ipAddrToString(ipAddr, NULL)); } else { //Report an error TRACE_ERROR("DNS resolution failed!\r\n"); } //Return status code return error; }
error_t rawSocketSendEthPacket(Socket *socket, const void *data, size_t length, size_t *written) { error_t error; uint32_t crc; ChunkedBuffer *buffer; NetInterface *interface; //Select the relevant network interface if(!socket->interface) interface = tcpIpStackGetDefaultInterface(); else interface = socket->interface; //Allocate a buffer memory to hold the raw Ethernet packet buffer = chunkedBufferAlloc(0); //Failed to allocate buffer? if(!buffer) return ERROR_OUT_OF_MEMORY; //Copy the raw data error = chunkedBufferAppend(buffer, data, length); //Successful processing? if(!error) { //Automatic padding not supported by hardware? if(!interface->nicDriver->autoPadding) { //The host controller should manually add padding //to the packet before transmitting it if(length < (ETH_MIN_FRAME_SIZE - ETH_CRC_SIZE)) { //Add padding as necessary size_t n = (ETH_MIN_FRAME_SIZE - ETH_CRC_SIZE) - length; //Append padding bytes error = chunkedBufferAppend(buffer, ethPadding, n); //Any error to report? if(error) return error; //Adjust frame length length += n; } } //CRC generation not supported by hardware? if(!interface->nicDriver->autoCrcGen) { //Compute CRC over the header and payload crc = ethCalcCrcEx(buffer, 0, length); //Convert from host byte order to little-endian byte order crc = htole32(crc); //Append the calculated CRC value error = chunkedBufferAppend(buffer, &crc, sizeof(crc)); //Any error to report? if(error) return error; //Adjust frame length length += sizeof(crc); } //Debug message TRACE_DEBUG("Sending raw Ethernet frame (%" PRIuSIZE " bytes)...\r\n", length); //Send the resulting packet over the specified link error = nicSendPacket(interface, buffer, 0); } //Successful processing? if(!error) { //Total number of bytes successfully transmitted if(written != NULL) *written = length; } //Free previously allocated memory block chunkedBufferFree(buffer); //Return status code return error; }