nbns_common.c
Go to the documentation of this file.
1 /**
2  * @file nbns_common.c
3  * @brief Definitions common to NBNS client and NBNS responder
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL NBNS_TRACE_LEVEL
31 
32 //Dependencies
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "core/net.h"
37 #include "netbios/nbns_client.h"
38 #include "netbios/nbns_responder.h"
39 #include "netbios/nbns_common.h"
40 #include "dns/dns_debug.h"
41 #include "debug.h"
42 
43 //Check TCP/IP stack configuration
44 #if (NBNS_CLIENT_SUPPORT == ENABLED || NBNS_RESPONDER_SUPPORT == ENABLED)
45 #if (IPV4_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief NBNS related initialization
50  * @param[in] interface Underlying network interface
51  * @return Error code
52  **/
53 
55 {
56  error_t error;
57 
58  //Callback function to be called when a NBNS message is received
59  error = udpAttachRxCallback(interface, NBNS_PORT, nbnsProcessMessage, NULL);
60  //Any error to report?
61  if(error)
62  return error;
63 
64  //Successful initialization
65  return NO_ERROR;
66 }
67 
68 
69 /**
70  * @brief Process incoming NBNS message
71  * @param[in] interface Underlying network interface
72  * @param[in] pseudoHeader UDP pseudo header
73  * @param[in] udpHeader UDP header
74  * @param[in] buffer Multi-part buffer containing the incoming NBNS message
75  * @param[in] offset Offset to the first byte of the NBNS message
76  * @param[in] param Callback function parameter (not used)
77  **/
78 
79 void nbnsProcessMessage(NetInterface *interface, const IpPseudoHeader *pseudoHeader,
80  const UdpHeader *udpHeader, const NetBuffer *buffer, size_t offset, void *param)
81 {
82  size_t length;
84 
85  //Make sure the NBNS message was received from an IPv4 peer
86  if(pseudoHeader->length != sizeof(Ipv4PseudoHeader))
87  return;
88 
89  //Retrieve the length of the NBNS message
90  length = netBufferGetLength(buffer) - offset;
91 
92  //Ensure the NBNS message is valid
93  if(length < sizeof(NbnsHeader))
94  return;
96  return;
97 
98  //Point to the NBNS message header
99  message = netBufferAt(buffer, offset);
100  //Sanity check
101  if(message == NULL)
102  return;
103 
104  //Debug message
105  TRACE_INFO("NBNS message received (%" PRIuSIZE " bytes)...\r\n", length);
106  //Dump message
108 
109  //NBNS messages received with an opcode other than zero must be silently ignored
110  if(message->opcode != DNS_OPCODE_QUERY)
111  return;
112  //NBNS messages received with non-zero response codes must be silently ignored
113  if(message->rcode != DNS_RCODE_NO_ERROR)
114  return;
115 
116  //NBNS query received?
117  if(!message->qr)
118  {
119 #if (NBNS_RESPONDER_SUPPORT == ENABLED)
120  //Process incoming NBNS query message
121  nbnsProcessQuery(interface, &pseudoHeader->ipv4Data,
122  udpHeader, message, length);
123 #endif
124  }
125  //NBNS response received?
126  else
127  {
128 #if (NBNS_CLIENT_SUPPORT == ENABLED)
129  //Process incoming NBNS response message
130  nbnsProcessResponse(interface, &pseudoHeader->ipv4Data,
131  udpHeader, message, length);
132 #endif
133  }
134 }
135 
136 
137 /**
138  * @brief Encode a NetBIOS name
139  * @param[in] src Pointer to the name to encode
140  * @param[out] dest Pointer to the encoded NetBIOS name
141  * @return Length of the encoded NetBIOS name
142  **/
143 
144 size_t nbnsEncodeName(const char_t *src, uint8_t *dest)
145 {
146  size_t i;
147  size_t j;
148  char_t c;
149 
150  //Point to first byte of the output buffer
151  j = 0;
152 
153  //NetBIOS names are 32-byte long
154  dest[j++] = 32;
155 
156  //Parse input name
157  for(i = 0; i < 15 && src[i] != '\0'; i++)
158  {
159  //Convert current character to uppercase
160  c = toupper((uint8_t) src[i]);
161 
162  //Encode character
163  dest[j++] = NBNS_ENCODE_H(c);
164  dest[j++] = NBNS_ENCODE_L(c);
165  }
166 
167  //Pad NetBIOS name with space characters
168  for(; i < 15; i++)
169  {
170  //Encoded space character
171  dest[j++] = NBNS_ENCODE_H(' ');
172  dest[j++] = NBNS_ENCODE_L(' ');
173  }
174 
175  //The 16th character is the NetBIOS suffix
176  dest[j++] = NBNS_ENCODE_H(0);
177  dest[j++] = NBNS_ENCODE_L(0);
178 
179  //Terminate the NetBIOS name with a zero length count
180  dest[j++] = 0;
181 
182  //Return the length of the encoded NetBIOS name
183  return j;
184 }
185 
186 
187 /**
188  * @brief Decode a NetBIOS name
189  * @param[in] message Pointer to the NBNS message
190  * @param[in] length Length of the NBNS message
191  * @param[in] pos Offset of the name to decode
192  * @param[out] dest Pointer to the decoded name (optional)
193  * @return The position of the resource record that immediately follows the NetBIOS name
194  **/
195 
197  size_t length, size_t pos, char_t *dest)
198 {
199  size_t i;
200  size_t n;
201  char_t c;
202 
203  //Cast the input NBNS message to byte array
204  uint8_t *src = (uint8_t *) message;
205 
206  //Malformed NBNS message?
207  if((pos + 34) >= length)
208  return 0;
209 
210  //Retrieve the length of the first label
211  n = src[pos++];
212 
213  //NetBIOS names must be 32-byte long
214  if(n != 32)
215  return 0;
216 
217  //Parse the NetBIOS name
218  for(i = 0; i < 15; i++)
219  {
220  //Make sure the characters of the sequence are valid
221  if(src[pos] < 'A' || src[pos] > 'P')
222  return 0;
223  if(src[pos + 1] < 'A' || src[pos + 1] > 'P')
224  return 0;
225 
226  //Combine nibbles to restore the original ASCII character
227  c = ((src[pos] - 'A') << 4) | (src[pos + 1] - 'A');
228 
229  //Padding character found?
230  if(c == ' ')
231  break;
232 
233  //Save current ASCII character
234  if(dest != NULL)
235  *(dest++) = c;
236 
237  //Advance data pointer
238  pos += 2;
239  }
240 
241  //Skip padding characters
242  for(; i < 16; i++)
243  {
244  //Make sure the nibbles are valid
245  if(src[pos] < 'A' || src[pos] > 'P')
246  return 0;
247  if(src[pos + 1] < 'A' || src[pos + 1] > 'P')
248  return 0;
249 
250  //Advance data pointer
251  pos += 2;
252  }
253 
254  //Retrieve the length of the next label
255  n = src[pos++];
256 
257  //NetBIOS names are terminated with a zero length count
258  if(n != 0)
259  return 0;
260 
261  //Properly terminate the string
262  if(dest != NULL)
263  *(dest++) = '\0';
264 
265  //Return the position of the resource record that
266  //is immediately following the NetBIOS name
267  return pos;
268 }
269 
270 
271 /**
272  * @brief Compare NetBIOS names
273  * @param[in] message Pointer to the NBNS message
274  * @param[in] length Length of the NBNS message
275  * @param[in] pos Offset of the encoded domain name
276  * @param[in] name NULL-terminated string that holds a domain name
277  * @return TRUE if the NetBIOS names match, else FALSE
278  **/
279 
281  size_t length, size_t pos, const char_t *name)
282 {
283  size_t i;
284  size_t n;
285  char_t c;
286 
287  //Cast the input NBNS message to byte array
288  uint8_t *src = (uint8_t *) message;
289 
290  //Malformed NBNS message?
291  if((pos + 34) >= length)
292  return FALSE;
293 
294  //Retrieve the length of the first label
295  n = src[pos++];
296 
297  //NetBIOS names must be 32-byte long
298  if(n != 32)
299  return FALSE;
300 
301  //Parse the NetBIOS name
302  for(i = 0; i < 15; i++)
303  {
304  //Make sure the characters of the sequence are valid
305  if(src[pos] < 'A' || src[pos] > 'P')
306  return FALSE;
307  if(src[pos + 1] < 'A' || src[pos + 1] > 'P')
308  return FALSE;
309 
310  //Combine nibbles to restore the original ASCII character
311  c = ((src[pos] - 'A') << 4) | (src[pos + 1] - 'A');
312 
313  //Padding character found?
314  if(c == ' ' && *name == '\0')
315  break;
316 
317  //Perform case insensitive comparison
318  if(toupper((uint8_t) c) != toupper((uint8_t) *name))
319  return FALSE;
320 
321  //Advance data pointer
322  pos += 2;
323  name++;
324  }
325 
326  //Skip padding characters
327  for(; i < 16; i++)
328  {
329  //Make sure the nibbles are valid
330  if(src[pos] < 'A' || src[pos] > 'P')
331  return FALSE;
332  if(src[pos + 1] < 'A' || src[pos + 1] > 'P')
333  return FALSE;
334 
335  //Advance data pointer
336  pos += 2;
337  }
338 
339  //Retrieve the length of the next label
340  n = src[pos];
341 
342  //NetBIOS names are terminated with a zero length count
343  if(n != 0)
344  return FALSE;
345 
346  //The NetBIOS names match
347  return TRUE;
348 }
349 
350 #endif
351 #endif
NBNS responder (NetBIOS Name Service)
char char_t
Definition: compiler_port.h:41
uint8_t c
Definition: ndp.h:510
TCP/IP stack core.
size_t nbnsParseName(const NbnsHeader *message, size_t length, size_t pos, char_t *dest)
Decode a NetBIOS name.
Definition: nbns_common.c:196
void nbnsProcessMessage(NetInterface *interface, const IpPseudoHeader *pseudoHeader, const UdpHeader *udpHeader, const NetBuffer *buffer, size_t offset, void *param)
Process incoming NBNS message.
Definition: nbns_common.c:79
Debugging facilities.
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:295
error_t nbnsInit(NetInterface *interface)
NBNS related initialization.
Definition: nbns_common.c:54
uint8_t message[]
Definition: chap.h:150
#define NBNS_PORT
Definition: nbns_common.h:44
void nbnsProcessResponse(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, const UdpHeader *udpHeader, const NbnsHeader *message, size_t length)
Process NBNS response message.
Definition: nbns_client.c:274
#define Ipv4PseudoHeader
Definition: ipv4.h:37
#define TRUE
Definition: os_port.h:48
Data logging functions for debugging purpose (DNS)
#define NBNS_ENCODE_H(c)
Definition: nbns_common.h:47
__start_packed struct @150 DnsHeader
DNS message header.
size_t length
Definition: ip.h:78
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:411
char_t name[]
__start_packed struct @263 NbnsHeader
NBNS message header.
__start_packed struct @126 UdpHeader
UDP header.
error_t udpAttachRxCallback(NetInterface *interface, uint16_t port, UdpRxCallback callback, void *param)
Register user callback.
Definition: udp.c:723
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
void dnsDumpMessage(const DnsHeader *message, size_t length)
Dump DNS message for debugging purpose.
Definition: dns_debug.c:50
#define TRACE_INFO(...)
Definition: debug.h:86
bool_t nbnsCompareName(const NbnsHeader *message, size_t length, size_t pos, const char_t *name)
Compare NetBIOS names.
Definition: nbns_common.c:280
Success.
Definition: error.h:42
NBNS client (NetBIOS Name Service)
#define DNS_MESSAGE_MAX_SIZE
Definition: dns_common.h:43
error_t
Error codes.
Definition: error.h:40
#define PRIuSIZE
Definition: compiler_port.h:72
#define NetInterface
Definition: net.h:34
IP pseudo header.
Definition: ip.h:76
void nbnsProcessQuery(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, const UdpHeader *udpHeader, const NbnsHeader *message, size_t length)
Process NBNS query message.
#define NBNS_ENCODE_L(c)
Definition: nbns_common.h:48
size_t nbnsEncodeName(const char_t *src, uint8_t *dest)
Encode a NetBIOS name.
Definition: nbns_common.c:144
Ipv4PseudoHeader ipv4Data
Definition: ip.h:82
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
#define FALSE
Definition: os_port.h:44
Definitions common to NBNS client and NBNS responder.
int bool_t
Definition: compiler_port.h:47