error_t ipv4SelectSourceAddr(NetInterface **interface, Ipv4Addr destAddr, Ipv4Addr *srcAddr) { //Use default network interface? if(*interface == NULL) *interface = netGetDefaultInterface(); //Select the most appropriate source address *srcAddr = (*interface)->ipv4Config.addr; //Successful processing return NO_ERROR; }
error_t getHostByName(NetInterface *interface, const char_t *name, IpAddr *ipAddr, uint_t flags) { error_t error; //Default address type depends on TCP/IP stack configuration #if (IPV4_SUPPORT == ENABLED) HostType type = HOST_TYPE_IPV4; #elif (IPV6_SUPPORT == ENABLED) HostType type = HOST_TYPE_IPV6; #else HostType type = HOST_TYPE_ANY; #endif //Default name resolution protocol depends on TCP/IP stack configuration #if (DNS_CLIENT_SUPPORT == ENABLED) HostnameResolver protocol = HOST_NAME_RESOLVER_DNS; #elif (MDNS_CLIENT_SUPPORT == ENABLED) HostnameResolver protocol = HOST_NAME_RESOLVER_MDNS; #elif (NBNS_CLIENT_SUPPORT == ENABLED) HostnameResolver protocol = HOST_NAME_RESOLVER_NBNS; #else HostnameResolver protocol = HOST_NAME_RESOLVER_ANY; #endif //Check parameters if(name == NULL || ipAddr == NULL) return ERROR_INVALID_PARAMETER; //Use default network interface? if(interface == NULL) interface = netGetDefaultInterface(); //The specified name can be either an IP or a host name error = ipStringToAddr(name, ipAddr); //Perform name resolution if necessary if(error) { //The user may provide a hint to choose between IPv4 and IPv6 if(flags & HOST_TYPE_IPV4) type = HOST_TYPE_IPV4; else if(flags & HOST_TYPE_IPV6) type = HOST_TYPE_IPV6; //The user may provide a hint to to select the desired protocol to be used if(flags & HOST_NAME_RESOLVER_DNS) { //Use DNS to resolve the specified host name protocol = HOST_NAME_RESOLVER_DNS; } else if(flags & HOST_NAME_RESOLVER_MDNS) { //Use mDNS to resolve the specified host name protocol = HOST_NAME_RESOLVER_MDNS; } else if(flags & HOST_NAME_RESOLVER_NBNS) { //Use NBNS to resolve the specified host name protocol = HOST_NAME_RESOLVER_NBNS; } else { //Retrieve the length of the host name to be resolved size_t n = strlen(name); //Select the most suitable protocol if(n >= 6 && !strcasecmp(name + n - 6, ".local")) { #if (MDNS_CLIENT_SUPPORT == ENABLED) //Use mDNS to resolve the specified host name protocol = HOST_NAME_RESOLVER_MDNS; #endif } else if(n <= 15 && !strchr(name, '.') && type == HOST_TYPE_IPV4) { #if (NBNS_CLIENT_SUPPORT == ENABLED) //Use NetBIOS Name Service to resolve the specified host name protocol = HOST_NAME_RESOLVER_NBNS; #endif } } #if (DNS_CLIENT_SUPPORT == ENABLED) //Use DNS protocol? if(protocol == HOST_NAME_RESOLVER_DNS) { //Perform host name resolution error = dnsResolve(interface, name, type, ipAddr); } else #endif #if (MDNS_CLIENT_SUPPORT == ENABLED) //Use mDNS protocol? if(protocol == HOST_NAME_RESOLVER_MDNS) { //Perform host name resolution error = mdnsResolve(interface, name, type, ipAddr); } else #endif #if (NBNS_CLIENT_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED) //Use NetBIOS Name Service protocol? if(protocol == HOST_NAME_RESOLVER_NBNS) { //Perform host name resolution error = nbnsResolve(interface, name, ipAddr); } else #endif //Invalid protocol? { //Report an error error = ERROR_INVALID_PARAMETER; } } //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; NetBuffer *buffer; NetInterface *interface; //Select the relevant network interface if(!socket->interface) interface = netGetDefaultInterface(); else interface = socket->interface; //Allocate a buffer memory to hold the raw Ethernet packet buffer = netBufferAlloc(0); //Failed to allocate buffer? if(!buffer) return ERROR_OUT_OF_MEMORY; //Copy the raw data error = netBufferAppend(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 = netBufferAppend(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 = netBufferAppend(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 netBufferFree(buffer); //Return status code return error; }
error_t sntpClientGetTimestamp(NetInterface *interface, const IpAddr *serverIpAddr, NtpTimestamp *timestamp) { error_t error; uint_t i; systime_t timeout; SntpClientContext context; //Check parameters if(serverIpAddr == NULL || timestamp == NULL) return ERROR_INVALID_PARAMETER; //Use default network interface? if(!interface) interface = netGetDefaultInterface(); //Open a UDP socket context.socket = socketOpen(SOCKET_TYPE_DGRAM, SOCKET_IP_PROTO_UDP); //Failed to open socket? if(!context.socket) return ERROR_OPEN_FAILED; //Associate the socket with the relevant interface error = socketBindToInterface(context.socket, interface); //Any error to report? if(error) { //Close socket socketClose(context.socket); //Return status code return error; } //Only accept datagrams from the specified NTP server error = socketConnect(context.socket, serverIpAddr, NTP_PORT); //Any error to report? if(error) { //Close socket socketClose(context.socket); //Return status code return error; } //Initial timeout value timeout = SNTP_CLIENT_INIT_TIMEOUT; //Retransmission loop for(i = 0; i < SNTP_CLIENT_MAX_RETRIES; i++) { //Send NTP request message error = sntpSendRequest(&context); //Failed to send message ? if(error) break; //Wait for a valid NTP response message error = sntpWaitForResponse(&context, timeout); //Valid NTP response received? if(!error) break; //The timeout value is doubled for each subsequent retransmission timeout = MIN(timeout * 2, SNTP_CLIENT_MAX_TIMEOUT); } //Successful processing? if(!error) { //Save server timestamp timestamp->seconds = ntohl(context.message.transmitTimestamp.seconds); timestamp->fraction = ntohl(context.message.transmitTimestamp.fraction); } //Close socket socketClose(context.socket); //Return status code return error; }