nbns_responder.c
Go to the documentation of this file.
1 /**
2  * @file nbns_responder.c
3  * @brief NBNS responder (NetBIOS Name Service)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 1.9.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NBNS_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "netbios/nbns_responder.h"
37 #include "netbios/nbns_common.h"
38 #include "dns/dns_debug.h"
39 #include "debug.h"
40 
41 //Check TCP/IP stack configuration
42 #if (NBNS_RESPONDER_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED)
43 
44 
45 /**
46  * @brief Process NBNS query message
47  * @param[in] interface Underlying network interface
48  * @param[in] pseudoHeader UDP pseudo header
49  * @param[in] udpHeader UDP header
50  * @param[in] message Pointer to the NBNS query message
51  * @param[in] length Length of the message
52  **/
53 
54 void nbnsProcessQuery(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader,
55  const UdpHeader *udpHeader, const NbnsHeader *message, size_t length)
56 {
57  size_t pos;
58  DnsQuestion *question;
59 
60  //The NBNS query shall contain one question
61  if(ntohs(message->qdcount) != 1)
62  return;
63 
64  //Parse NetBIOS name
65  pos = nbnsParseName(message, length, sizeof(DnsHeader), NULL);
66 
67  //Invalid name?
68  if(!pos)
69  return;
70  //Malformed NBNS query message?
71  if((pos + sizeof(DnsQuestion)) > length)
72  return;
73 
74  //Point to the corresponding entry
75  question = DNS_GET_QUESTION(message, pos);
76 
77  //Check the class and the type of the request
78  if(ntohs(question->qclass) != DNS_RR_CLASS_IN)
79  return;
80  if(ntohs(question->qtype) != DNS_RR_TYPE_NB)
81  return;
82 
83  //Compare NetBIOS names
84  if(nbnsCompareName(message, length, sizeof(DnsHeader), interface->hostname))
85  {
86  uint16_t destPort;
88 
89  //A response packet is always sent to the source UDP port and
90  //source IP address of the request packet
91  destIpAddr.length = sizeof(Ipv4Addr);
92  destIpAddr.ipv4Addr = pseudoHeader->srcAddr;
93 
94  //Convert the port number to host byte order
95  destPort = ntohs(udpHeader->srcPort);
96 
97  //Send NBNS response
98  nbnsSendResponse(interface, &destIpAddr, destPort, message->id);
99  }
100 }
101 
102 
103 /**
104  * @brief Send NBNS response message
105  * @param[in] interface Underlying network interface
106  * @param[in] destIpAddr Destination IP address
107  * @param[in] destPort destination port
108  * @param[in] id 16-bit identifier to be used when sending NBNS query
109  **/
110 
112  const IpAddr *destIpAddr, uint16_t destPort, uint16_t id)
113 {
114  error_t error;
115  size_t length;
116  size_t offset;
117  NetBuffer *buffer;
119  NbnsAddrEntry *addrEntry;
120  DnsResourceRecord *record;
121 
122  //Allocate a memory buffer to hold the NBNS response message
123  buffer = udpAllocBuffer(DNS_MESSAGE_MAX_SIZE, &offset);
124  //Failed to allocate buffer?
125  if(buffer == NULL)
126  return ERROR_OUT_OF_MEMORY;
127 
128  //Point to the NBNS header
129  message = netBufferAt(buffer, offset);
130 
131  //Take the identifier from the query message
132  message->id = id;
133 
134  //Format NBNS response header
135  message->qr = 1;
136  message->opcode = DNS_OPCODE_QUERY;
137  message->aa = 1;
138  message->tc = 0;
139  message->rd = 1;
140  message->ra = 1;
141  message->z = 0;
142  message->b = 0;
143  message->rcode = DNS_RCODE_NO_ERROR;
144 
145  //The NBNS response contains 1 answer resource record
146  message->qdcount = 0;
147  message->ancount = HTONS(1);
148  message->nscount = 0;
149  message->arcount = 0;
150 
151  //NBNS response message length
152  length = sizeof(DnsHeader);
153 
154  //Encode the host name using the NBNS name notation
155  length += nbnsEncodeName(interface->hostname, (uint8_t *) message + length);
156 
157  //Point to the corresponding resource record
159 
160  //Fill in resource record
161  record->rtype = HTONS(DNS_RR_TYPE_NB);
162  record->rclass = HTONS(DNS_RR_CLASS_IN);
164  record->rdlength = HTONS(sizeof(NbnsAddrEntry));
165 
166  //Point to the address entry array
167  addrEntry = (NbnsAddrEntry *) record->rdata;
168 
169  //Fill in address entry
170  addrEntry->flags = HTONS(NBNS_G_UNIQUE | NBNS_ONT_BNODE);
171  addrEntry->addr = interface->ipv4Context.addrList[0].addr;
172 
173  //Update the length of the NBNS response message
174  length += sizeof(DnsResourceRecord) + sizeof(NbnsAddrEntry);
175 
176  //Adjust the length of the multi-part buffer
177  netBufferSetLength(buffer, offset + length);
178 
179  //Debug message
180  TRACE_INFO("Sending NBNS message (%" PRIuSIZE " bytes)...\r\n", length);
181  //Dump message
183 
184  //A response packet is always sent to the source UDP port and source IP
185  //address of the request packet
186  error = udpSendDatagramEx(interface, NULL, NBNS_PORT, destIpAddr,
187  destPort, buffer, offset, IP_FLAG_DONT_ROUTE | IPV4_DEFAULT_TTL);
188 
189  //Free previously allocated memory
190  netBufferFree(buffer);
191 
192  //Return status code
193  return error;
194 }
195 
196 #endif
error_t udpSendDatagramEx(NetInterface *interface, const IpAddr *srcIpAddr, uint16_t srcPort, const IpAddr *destIpAddr, uint16_t destPort, NetBuffer *buffer, size_t offset, uint_t flags)
Send a UDP datagram (raw interface)
Definition: udp.c:463
void nbnsProcessQuery(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, const UdpHeader *udpHeader, const NbnsHeader *message, size_t length)
Process NBNS query message.
uint8_t length
Definition: dtls_misc.h:149
size_t nbnsParseName(const NbnsHeader *message, size_t length, size_t pos, char_t *dest)
Decode a NetBIOS name.
Definition: nbns_common.c:201
IP network address.
Definition: ip.h:71
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
__start_packed struct @146 DnsHeader
DNS message header.
Internet.
Definition: dns_common.h:110
uint16_t destPort
Definition: tcp.h:303
#define NBNS_PORT
Definition: nbns_common.h:46
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:239
__start_packed struct @148 DnsResourceRecord
Resource record format.
NetBIOS name service.
Definition: dns_common.h:134
#define HTONL(value)
Definition: cpu_endian.h:391
error_t
Error codes.
Definition: error.h:42
#define DNS_GET_QUESTION(message, offset)
Definition: dns_common.h:63
#define DNS_GET_RESOURCE_RECORD(message, offset)
Definition: dns_common.h:64
Definitions common to NBNS client and NBNS responder.
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:413
#define NetInterface
Definition: net.h:36
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
__start_packed struct @122 UdpHeader
UDP header.
error_t nbnsSendResponse(NetInterface *interface, const IpAddr *destIpAddr, uint16_t destPort, uint16_t id)
Send NBNS response message.
#define Ipv4PseudoHeader
Definition: ipv4.h:39
#define TRACE_INFO(...)
Definition: debug.h:94
void dnsDumpMessage(const DnsHeader *message, size_t length)
Dump DNS message for debugging purpose.
Definition: dns_debug.c:52
NetBuffer * udpAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold a UDP packet.
Definition: udp.c:697
size_t nbnsEncodeName(const char_t *src, uint8_t *dest)
Encode a NetBIOS name.
Definition: nbns_common.c:149
#define IPV4_DEFAULT_TTL
Definition: ipv4.h:56
#define ntohs(value)
Definition: cpu_endian.h:398
#define NBNS_DEFAULT_RESOURCE_RECORD_TTL
Definition: nbns_common.h:40
#define HTONS(value)
Definition: cpu_endian.h:390
#define DNS_MESSAGE_MAX_SIZE
Definition: dns_common.h:45
error_t netBufferSetLength(NetBuffer *buffer, size_t length)
Adjust the length of a multi-part buffer.
Definition: net_mem.c:320
uint8_t message[]
Definition: chap.h:152
uint16_t id
Definition: dns_common.h:158
__start_packed struct @147 DnsQuestion
Question format.
#define PRIuSIZE
Definition: compiler_port.h:78
TCP/IP stack core.
Data logging functions for debugging purpose (DNS)
__start_packed struct @261 NbnsAddrEntry
NBNS address entry.
Debugging facilities.
NBNS responder (NetBIOS Name Service)
bool_t nbnsCompareName(const NbnsHeader *message, size_t length, size_t pos, const char_t *name)
Compare NetBIOS names.
Definition: nbns_common.c:285
__start_packed struct @260 NbnsHeader
NBNS message header.
Ipv4Addr destIpAddr
Definition: ipcp.h:78