Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
nbns_common.c
Go to the documentation of this file.
00001 /** 00002 * @file nbns_common.c 00003 * @brief Functions common to NBNS client and NBNS responder 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 <stdlib.h> 00034 #include <string.h> 00035 #include <ctype.h> 00036 #include "core/net.h" 00037 #include "netbios/nbns_client.h" 00038 #include "netbios/nbns_responder.h" 00039 #include "netbios/nbns_common.h" 00040 #include "dns/dns_debug.h" 00041 #include "debug.h" 00042 00043 //Check TCP/IP stack configuration 00044 #if (NBNS_CLIENT_SUPPORT == ENABLED || NBNS_RESPONDER_SUPPORT == ENABLED) 00045 #if (IPV4_SUPPORT == ENABLED) 00046 00047 00048 /** 00049 * @brief NBNS related initialization 00050 * @param[in] interface Underlying network interface 00051 * @return Error code 00052 **/ 00053 00054 error_t nbnsInit(NetInterface *interface) 00055 { 00056 error_t error; 00057 00058 //Callback function to be called when a NBNS message is received 00059 error = udpAttachRxCallback(interface, NBNS_PORT, nbnsProcessMessage, NULL); 00060 //Any error to report? 00061 if(error) 00062 return error; 00063 00064 //Successful initialization 00065 return NO_ERROR; 00066 } 00067 00068 00069 /** 00070 * @brief Process incoming NBNS message 00071 * @param[in] interface Underlying network interface 00072 * @param[in] pseudoHeader UDP pseudo header 00073 * @param[in] udpHeader UDP header 00074 * @param[in] buffer Multi-part buffer containing the incoming NBNS message 00075 * @param[in] offset Offset to the first byte of the NBNS message 00076 * @param[in] params Callback function parameter (not used) 00077 **/ 00078 00079 void nbnsProcessMessage(NetInterface *interface, const IpPseudoHeader *pseudoHeader, 00080 const UdpHeader *udpHeader, const NetBuffer *buffer, size_t offset, void *params) 00081 { 00082 size_t length; 00083 NbnsHeader *message; 00084 00085 //Make sure the NBNS message was received from an IPv4 peer 00086 if(pseudoHeader->length != sizeof(Ipv4PseudoHeader)) 00087 return; 00088 00089 //Retrieve the length of the NBNS message 00090 length = netBufferGetLength(buffer) - offset; 00091 00092 //Ensure the NBNS message is valid 00093 if(length < sizeof(NbnsHeader)) 00094 return; 00095 if(length > DNS_MESSAGE_MAX_SIZE) 00096 return; 00097 00098 //Point to the NBNS message header 00099 message = netBufferAt(buffer, offset); 00100 //Sanity check 00101 if(message == NULL) 00102 return; 00103 00104 //Debug message 00105 TRACE_INFO("NBNS message received (%" PRIuSIZE " bytes)...\r\n", length); 00106 //Dump message 00107 dnsDumpMessage((DnsHeader *) message, length); 00108 00109 //NBNS messages received with an opcode other than zero must be silently ignored 00110 if(message->opcode != DNS_OPCODE_QUERY) 00111 return; 00112 //NBNS messages received with non-zero response codes must be silently ignored 00113 if(message->rcode != DNS_RCODE_NO_ERROR) 00114 return; 00115 00116 //NBNS query received? 00117 if(!message->qr) 00118 { 00119 #if (NBNS_RESPONDER_SUPPORT == ENABLED) 00120 //Process incoming NBNS query message 00121 nbnsProcessQuery(interface, &pseudoHeader->ipv4Data, 00122 udpHeader, message, length); 00123 #endif 00124 } 00125 //NBNS response received? 00126 else 00127 { 00128 #if (NBNS_CLIENT_SUPPORT == ENABLED) 00129 //Process incoming NBNS response message 00130 nbnsProcessResponse(interface, &pseudoHeader->ipv4Data, 00131 udpHeader, message, length); 00132 #endif 00133 } 00134 } 00135 00136 00137 /** 00138 * @brief Encode a NetBIOS name 00139 * @param[in] src Pointer to the name to encode 00140 * @param[out] dest Pointer to the encoded NetBIOS name 00141 * @return Length of the encoded NetBIOS name 00142 **/ 00143 00144 size_t nbnsEncodeName(const char_t *src, uint8_t *dest) 00145 { 00146 size_t i; 00147 size_t j; 00148 char_t c; 00149 00150 //Point to first byte of the output buffer 00151 j = 0; 00152 00153 //NetBIOS names are 32-byte long 00154 dest[j++] = 32; 00155 00156 //Parse input name 00157 for(i = 0; i < 15 && src[i] != '\0'; i++) 00158 { 00159 //Convert current character to uppercase 00160 c = toupper((uint8_t) src[i]); 00161 00162 //Encode character 00163 dest[j++] = NBNS_ENCODE_H(c); 00164 dest[j++] = NBNS_ENCODE_L(c); 00165 } 00166 00167 //Pad NetBIOS name with space characters 00168 for(; i < 15; i++) 00169 { 00170 //Encoded space character 00171 dest[j++] = NBNS_ENCODE_H(' '); 00172 dest[j++] = NBNS_ENCODE_L(' '); 00173 } 00174 00175 //The 16th character is the NetBIOS suffix 00176 dest[j++] = NBNS_ENCODE_H(0); 00177 dest[j++] = NBNS_ENCODE_L(0); 00178 00179 //Terminate the NetBIOS name with a zero length count 00180 dest[j++] = 0; 00181 00182 //Return the length of the encoded NetBIOS name 00183 return j; 00184 } 00185 00186 00187 /** 00188 * @brief Decode a NetBIOS name 00189 * @param[in] message Pointer to the NBNS message 00190 * @param[in] length Length of the NBNS message 00191 * @param[in] pos Offset of the name to decode 00192 * @param[out] dest Pointer to the decoded name (optional) 00193 * @return The position of the resource record that immediately follows the NetBIOS name 00194 **/ 00195 00196 size_t nbnsParseName(const NbnsHeader *message, 00197 size_t length, size_t pos, char_t *dest) 00198 { 00199 size_t i; 00200 size_t n; 00201 char_t c; 00202 00203 //Cast the input NBNS message to byte array 00204 uint8_t *src = (uint8_t *) message; 00205 00206 //Malformed NBNS message? 00207 if((pos + 34) >= length) 00208 return 0; 00209 00210 //Retrieve the length of the first label 00211 n = src[pos++]; 00212 00213 //NetBIOS names must be 32-byte long 00214 if(n != 32) 00215 return 0; 00216 00217 //Parse the NetBIOS name 00218 for(i = 0; i < 15; i++) 00219 { 00220 //Make sure the characters of the sequence are valid 00221 if(src[pos] < 'A' || src[pos] > 'P') 00222 return 0; 00223 if(src[pos + 1] < 'A' || src[pos + 1] > 'P') 00224 return 0; 00225 00226 //Combine nibbles to restore the original ASCII character 00227 c = ((src[pos] - 'A') << 4) | (src[pos + 1] - 'A'); 00228 00229 //Padding character found? 00230 if(c == ' ') 00231 break; 00232 00233 //Save current ASCII character 00234 if(dest != NULL) 00235 *(dest++) = c; 00236 00237 //Advance data pointer 00238 pos += 2; 00239 } 00240 00241 //Skip padding characters 00242 for(; i < 16; i++) 00243 { 00244 //Make sure the nibbles are valid 00245 if(src[pos] < 'A' || src[pos] > 'P') 00246 return 0; 00247 if(src[pos + 1] < 'A' || src[pos + 1] > 'P') 00248 return 0; 00249 00250 //Advance data pointer 00251 pos += 2; 00252 } 00253 00254 //Retrieve the length of the next label 00255 n = src[pos++]; 00256 00257 //NetBIOS names are terminated with a zero length count 00258 if(n != 0) 00259 return 0; 00260 00261 //Properly terminate the string 00262 if(dest != NULL) 00263 *(dest++) = '\0'; 00264 00265 //Return the position of the resource record that 00266 //is immediately following the NetBIOS name 00267 return pos; 00268 } 00269 00270 00271 /** 00272 * @brief Compare NetBIOS names 00273 * @param[in] message Pointer to the NBNS message 00274 * @param[in] length Length of the NBNS message 00275 * @param[in] pos Offset of the encoded domain name 00276 * @param[in] name NULL-terminated string that holds a domain name 00277 * @return TRUE if the NetBIOS names match, else FALSE 00278 **/ 00279 00280 bool_t nbnsCompareName(const NbnsHeader *message, 00281 size_t length, size_t pos, const char_t *name) 00282 { 00283 size_t i; 00284 size_t n; 00285 char_t c; 00286 00287 //Cast the input NBNS message to byte array 00288 uint8_t *src = (uint8_t *) message; 00289 00290 //Malformed NBNS message? 00291 if((pos + 34) >= length) 00292 return FALSE; 00293 00294 //Retrieve the length of the first label 00295 n = src[pos++]; 00296 00297 //NetBIOS names must be 32-byte long 00298 if(n != 32) 00299 return FALSE; 00300 00301 //Parse the NetBIOS name 00302 for(i = 0; i < 15; i++) 00303 { 00304 //Make sure the characters of the sequence are valid 00305 if(src[pos] < 'A' || src[pos] > 'P') 00306 return FALSE; 00307 if(src[pos + 1] < 'A' || src[pos + 1] > 'P') 00308 return FALSE; 00309 00310 //Combine nibbles to restore the original ASCII character 00311 c = ((src[pos] - 'A') << 4) | (src[pos + 1] - 'A'); 00312 00313 //Padding character found? 00314 if(c == ' ' && *name == '\0') 00315 break; 00316 00317 //Perform case insensitive comparison 00318 if(toupper((uint8_t) c) != toupper((uint8_t) *name)) 00319 return FALSE; 00320 00321 //Advance data pointer 00322 pos += 2; 00323 name++; 00324 } 00325 00326 //Skip padding characters 00327 for(; i < 16; i++) 00328 { 00329 //Make sure the nibbles are valid 00330 if(src[pos] < 'A' || src[pos] > 'P') 00331 return FALSE; 00332 if(src[pos + 1] < 'A' || src[pos + 1] > 'P') 00333 return FALSE; 00334 00335 //Advance data pointer 00336 pos += 2; 00337 } 00338 00339 //Retrieve the length of the next label 00340 n = src[pos]; 00341 00342 //NetBIOS names are terminated with a zero length count 00343 if(n != 0) 00344 return FALSE; 00345 00346 //The NetBIOS names match 00347 return TRUE; 00348 } 00349 00350 #endif 00351 #endif 00352
Generated on Tue Jul 12 2022 17:10:15 by
