Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
nbns_client.c
Go to the documentation of this file.
00001 /** 00002 * @file nbns_client.c 00003 * @brief NBNS client (NetBIOS Name Service) 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 //Switch to the appropriate trace level 00030 #define TRACE_LEVEL NBNS_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include "core/net.h" 00034 #include "netbios/nbns_client.h" 00035 #include "netbios/nbns_common.h" 00036 #include "dns/dns_debug.h" 00037 #include "debug.h" 00038 00039 //Check TCP/IP stack configuration 00040 #if (NBNS_CLIENT_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED) 00041 00042 00043 /** 00044 * @brief Resolve a host name using NBNS 00045 * @param[in] interface Underlying network interface 00046 * @param[in] name Name of the host to be resolved 00047 * @param[out] ipAddr IP address corresponding to the specified host name 00048 **/ 00049 00050 error_t nbnsResolve(NetInterface *interface, const char_t *name, IpAddr *ipAddr) 00051 { 00052 error_t error; 00053 DnsCacheEntry *entry; 00054 00055 #if (NET_RTOS_SUPPORT == ENABLED) 00056 systime_t delay; 00057 00058 //Debug message 00059 TRACE_INFO("Resolving host name %s (NBNS resolver)...\r\n", name); 00060 #endif 00061 00062 //Get exclusive access 00063 osAcquireMutex(&netMutex); 00064 00065 //Search the DNS cache for the specified host name 00066 entry = dnsFindEntry(interface, name, HOST_TYPE_IPV4, HOST_NAME_RESOLVER_NBNS); 00067 00068 //Check whether a matching entry has been found 00069 if(entry) 00070 { 00071 //Host name already resolved? 00072 if(entry->state == DNS_STATE_RESOLVED || 00073 entry->state == DNS_STATE_PERMANENT) 00074 { 00075 //Return the corresponding IP address 00076 *ipAddr = entry->ipAddr; 00077 //Successful host name resolution 00078 error = NO_ERROR; 00079 } 00080 else 00081 { 00082 //Host name resolution is in progress... 00083 error = ERROR_IN_PROGRESS; 00084 } 00085 } 00086 else 00087 { 00088 //If no entry exists, then create a new one 00089 entry = dnsCreateEntry(); 00090 00091 //Record the host name whose IP address is unknown 00092 strcpy(entry->name, name); 00093 00094 //Initialize DNS cache entry 00095 entry->type = HOST_TYPE_IPV4; 00096 entry->protocol = HOST_NAME_RESOLVER_NBNS; 00097 entry->interface = interface; 00098 00099 //Initialize retransmission counter 00100 entry->retransmitCount = NBNS_CLIENT_MAX_RETRIES; 00101 //Send NBNS query 00102 error = nbnsSendQuery(entry); 00103 00104 //NBNS message successfully sent? 00105 if(!error) 00106 { 00107 //Save the time at which the query message was sent 00108 entry->timestamp = osGetSystemTime(); 00109 //Set timeout value 00110 entry->timeout = NBNS_CLIENT_INIT_TIMEOUT; 00111 entry->maxTimeout = NBNS_CLIENT_MAX_TIMEOUT; 00112 //Decrement retransmission counter 00113 entry->retransmitCount--; 00114 00115 //Switch state 00116 entry->state = DNS_STATE_IN_PROGRESS; 00117 //Host name resolution is in progress 00118 error = ERROR_IN_PROGRESS; 00119 } 00120 } 00121 00122 //Release exclusive access 00123 osReleaseMutex(&netMutex); 00124 00125 #if (NET_RTOS_SUPPORT == ENABLED) 00126 //Set default polling interval 00127 delay = DNS_CACHE_INIT_POLLING_INTERVAL; 00128 00129 //Wait the host name resolution to complete 00130 while(error == ERROR_IN_PROGRESS) 00131 { 00132 //Wait until the next polling period 00133 osDelayTask(delay); 00134 00135 //Get exclusive access 00136 osAcquireMutex(&netMutex); 00137 00138 //Search the DNS cache for the specified host name 00139 entry = dnsFindEntry(interface, name, HOST_TYPE_IPV4, HOST_NAME_RESOLVER_NBNS); 00140 00141 //Check whether a matching entry has been found 00142 if(entry) 00143 { 00144 //Host name successfully resolved? 00145 if(entry->state == DNS_STATE_RESOLVED) 00146 { 00147 //Return the corresponding IP address 00148 *ipAddr = entry->ipAddr; 00149 //Successful host name resolution 00150 error = NO_ERROR; 00151 } 00152 } 00153 else 00154 { 00155 //Host name resolution failed 00156 error = ERROR_FAILURE; 00157 } 00158 00159 //Release exclusive access 00160 osReleaseMutex(&netMutex); 00161 00162 //Backoff support for less aggressive polling 00163 delay = MIN(delay * 2, DNS_CACHE_MAX_POLLING_INTERVAL); 00164 } 00165 00166 //Check status code 00167 if(error) 00168 { 00169 //Failed to resolve host name 00170 TRACE_INFO("Host name resolution failed!\r\n"); 00171 } 00172 else 00173 { 00174 //Successful host name resolution 00175 TRACE_INFO("Host name resolved to %s...\r\n", ipAddrToString(ipAddr, NULL)); 00176 } 00177 #endif 00178 00179 //Return status code 00180 return error; 00181 } 00182 00183 00184 /** 00185 * @brief Send a NBNS query message 00186 * @param[in] entry Pointer to a valid DNS cache entry 00187 * @return Error code 00188 **/ 00189 00190 error_t nbnsSendQuery(DnsCacheEntry *entry) 00191 { 00192 error_t error; 00193 size_t length; 00194 size_t offset; 00195 NetBuffer *buffer; 00196 NbnsHeader *message; 00197 DnsQuestion *dnsQuestion; 00198 IpAddr destIpAddr; 00199 00200 //Allocate a memory buffer to hold the NBNS query message 00201 buffer = udpAllocBuffer(DNS_MESSAGE_MAX_SIZE, &offset); 00202 //Failed to allocate buffer? 00203 if(buffer == NULL) 00204 return ERROR_OUT_OF_MEMORY; 00205 00206 //Point to the NBNS header 00207 message = netBufferAt(buffer, offset); 00208 00209 //Format NBNS query message 00210 message->id = htons(entry->id); 00211 message->qr = 0; 00212 message->opcode = DNS_OPCODE_QUERY; 00213 message->aa = 0; 00214 message->tc = 0; 00215 message->rd = 0; 00216 message->ra = 0; 00217 message->z = 0; 00218 message->b = 1; 00219 message->rcode = DNS_RCODE_NO_ERROR; 00220 00221 //The NBNS query contains one question 00222 message->qdcount = HTONS(1); 00223 message->ancount = 0; 00224 message->nscount = 0; 00225 message->arcount = 0; 00226 00227 //Length of the NBNS query message 00228 length = sizeof(DnsHeader); 00229 00230 //Encode the NetBIOS name 00231 length += nbnsEncodeName(entry->name, message->questions); 00232 00233 //Point to the corresponding question structure 00234 dnsQuestion = DNS_GET_QUESTION(message, length); 00235 //Fill in question structure 00236 dnsQuestion->qtype = HTONS(DNS_RR_TYPE_NB); 00237 dnsQuestion->qclass = HTONS(DNS_RR_CLASS_IN); 00238 00239 //Update the length of the NBNS query message 00240 length += sizeof(DnsQuestion); 00241 00242 //Adjust the length of the multi-part buffer 00243 netBufferSetLength(buffer, offset + length); 00244 00245 //Debug message 00246 TRACE_INFO("Sending NBNS message (%" PRIuSIZE " bytes)...\r\n", length); 00247 //Dump message 00248 dnsDumpMessage((DnsHeader *) message, length); 00249 00250 //The destination address is the broadcast address 00251 destIpAddr.length = sizeof(Ipv4Addr); 00252 ipv4GetBroadcastAddr(entry->interface, &destIpAddr.ipv4Addr); 00253 00254 //A request packet is always sent to the well known port 137 00255 error = udpSendDatagramEx(entry->interface, NBNS_PORT, 00256 &destIpAddr, NBNS_PORT, buffer, offset, IPV4_DEFAULT_TTL); 00257 00258 //Free previously allocated memory 00259 netBufferFree(buffer); 00260 //Return status code 00261 return error; 00262 } 00263 00264 00265 /** 00266 * @brief Process NBNS response message 00267 * @param[in] interface Underlying network interface 00268 * @param[in] pseudoHeader UDP pseudo header 00269 * @param[in] udpHeader UDP header 00270 * @param[in] message Pointer to the NBNS response message 00271 * @param[in] length Length of the message 00272 **/ 00273 00274 void nbnsProcessResponse(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, 00275 const UdpHeader *udpHeader, const NbnsHeader *message, size_t length) 00276 { 00277 uint_t i; 00278 size_t pos; 00279 DnsCacheEntry *entry; 00280 DnsResourceRecord *record; 00281 NbnsAddrEntry *addrEntry; 00282 00283 //The NBNS response shall contain one answer 00284 if(ntohs(message->qdcount) != 0 && ntohs(message->ancount) != 1) 00285 return; 00286 00287 //Parse NetBIOS name 00288 pos = nbnsParseName(message, length, sizeof(DnsHeader), NULL); 00289 //Invalid name? 00290 if(!pos) 00291 return; 00292 00293 //Point to the associated resource record 00294 record = DNS_GET_RESOURCE_RECORD(message, pos); 00295 //Point to the resource data 00296 pos += sizeof(DnsResourceRecord); 00297 00298 //Make sure the resource record is valid 00299 if(pos > length) 00300 return; 00301 if((pos + ntohs(record->rdlength)) > length) 00302 return; 00303 00304 //Check the class and the type of the resource record 00305 if(ntohs(record->rclass) != DNS_RR_CLASS_IN) 00306 return; 00307 if(ntohs(record->rtype) != DNS_RR_TYPE_NB) 00308 return; 00309 00310 //Verify the length of the data field 00311 if(ntohs(record->rdlength) < sizeof(NbnsAddrEntry)) 00312 return; 00313 00314 //Loop through DNS cache entries 00315 for(i = 0; i < DNS_CACHE_SIZE; i++) 00316 { 00317 //Point to the current entry 00318 entry = &dnsCache[i]; 00319 00320 //NBNS name resolution in progress? 00321 if(entry->state == DNS_STATE_IN_PROGRESS && 00322 entry->protocol == HOST_NAME_RESOLVER_NBNS && 00323 entry->type == HOST_TYPE_IPV4) 00324 { 00325 //Compare identifiers 00326 if(entry->id == ntohs(message->id)) 00327 { 00328 //Compare NetBIOS names 00329 if(nbnsCompareName(message, length, sizeof(DnsHeader), entry->name)) 00330 { 00331 //Point to the address entry array 00332 addrEntry = (NbnsAddrEntry *) record->rdata; 00333 //Copy the IPv4 address 00334 entry->ipAddr.length = sizeof(Ipv4Addr); 00335 entry->ipAddr.ipv4Addr = addrEntry->addr; 00336 00337 //Save current time 00338 entry->timestamp = osGetSystemTime(); 00339 //Save TTL value 00340 entry->timeout = ntohl(record->ttl) * 1000; 00341 //Limit the lifetime of the NBNS cache entries 00342 entry->timeout = MIN(entry->timeout, NBNS_MAX_LIFETIME); 00343 00344 //Host name successfully resolved 00345 entry->state = DNS_STATE_RESOLVED; 00346 } 00347 } 00348 } 00349 } 00350 } 00351 00352 #endif 00353
Generated on Tue Jul 12 2022 17:10:15 by
