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  * 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 "core/net.h"
34 #include "netbios/nbns_responder.h"
35 #include "netbios/nbns_common.h"
36 #include "dns/dns_debug.h"
37 #include "debug.h"
38 
39 //Check TCP/IP stack configuration
40 #if (NBNS_RESPONDER_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED)
41 
42 
43 /**
44  * @brief Process NBNS query message
45  * @param[in] interface Underlying network interface
46  * @param[in] pseudoHeader UDP pseudo header
47  * @param[in] udpHeader UDP header
48  * @param[in] message Pointer to the NBNS query message
49  * @param[in] length Length of the message
50  **/
51 
52 void nbnsProcessQuery(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader,
53  const UdpHeader *udpHeader, const NbnsHeader *message, size_t length)
54 {
55  size_t pos;
56  DnsQuestion *question;
57 
58  //The NBNS query shall contain one question
59  if(ntohs(message->qdcount) != 1)
60  return;
61 
62  //Parse NetBIOS name
63  pos = nbnsParseName(message, length, sizeof(DnsHeader), NULL);
64 
65  //Invalid name?
66  if(!pos)
67  return;
68  //Malformed NBNS query message?
69  if((pos + sizeof(DnsQuestion)) > length)
70  return;
71 
72  //Point to the corresponding entry
73  question = DNS_GET_QUESTION(message, pos);
74 
75  //Check the class and the type of the request
76  if(ntohs(question->qclass) != DNS_RR_CLASS_IN)
77  return;
78  if(ntohs(question->qtype) != DNS_RR_TYPE_NB)
79  return;
80 
81  //Compare NetBIOS names
82  if(nbnsCompareName(message, length, sizeof(DnsHeader), interface->hostname))
83  {
84  uint16_t destPort;
86 
87  //A response packet is always sent to the source UDP port and
88  //source IP address of the request packet
89  destIpAddr.length = sizeof(Ipv4Addr);
90  destIpAddr.ipv4Addr = pseudoHeader->srcAddr;
91 
92  //Convert the port number to host byte order
93  destPort = ntohs(udpHeader->srcPort);
94 
95  //Send NBNS response
96  nbnsSendResponse(interface, &destIpAddr, destPort, message->id);
97  }
98 }
99 
100 
101 /**
102  * @brief Send NBNS response message
103  * @param[in] interface Underlying network interface
104  * @param[in] destIpAddr Destination IP address
105  * @param[in] destPort destination port
106  * @param[in] id 16-bit identifier to be used when sending NBNS query
107  **/
108 
110  const IpAddr *destIpAddr, uint16_t destPort, uint16_t id)
111 {
112  error_t error;
113  size_t length;
114  size_t offset;
115  NetBuffer *buffer;
117  NbnsAddrEntry *addrEntry;
118  DnsResourceRecord *record;
119 
120  //Allocate a memory buffer to hold the NBNS response message
121  buffer = udpAllocBuffer(DNS_MESSAGE_MAX_SIZE, &offset);
122  //Failed to allocate buffer?
123  if(buffer == NULL)
124  return ERROR_OUT_OF_MEMORY;
125 
126  //Point to the NBNS header
127  message = netBufferAt(buffer, offset);
128 
129  //Take the identifier from the query message
130  message->id = id;
131 
132  //Format NBNS response header
133  message->qr = 1;
134  message->opcode = DNS_OPCODE_QUERY;
135  message->aa = 1;
136  message->tc = 0;
137  message->rd = 1;
138  message->ra = 1;
139  message->z = 0;
140  message->b = 0;
141  message->rcode = DNS_RCODE_NO_ERROR;
142 
143  //The NBNS response contains 1 answer resource record
144  message->qdcount = 0;
145  message->ancount = HTONS(1);
146  message->nscount = 0;
147  message->arcount = 0;
148 
149  //NBNS response message length
150  length = sizeof(DnsHeader);
151 
152  //Encode the host name using the NBNS name notation
153  length += nbnsEncodeName(interface->hostname, (uint8_t *) message + length);
154 
155  //Point to the corresponding resource record
157  //Fill in resource record
158  record->rtype = HTONS(DNS_RR_TYPE_NB);
159  record->rclass = HTONS(DNS_RR_CLASS_IN);
161  record->rdlength = HTONS(sizeof(NbnsAddrEntry));
162 
163  //Point to the address entry array
164  addrEntry = (NbnsAddrEntry *) record->rdata;
165  //Fill in address entry
166  addrEntry->flags = HTONS(NBNS_G_UNIQUE | NBNS_ONT_BNODE);
167  addrEntry->addr = interface->ipv4Context.addr;
168 
169  //Update the length of the NBNS response message
170  length += sizeof(DnsResourceRecord) + sizeof(NbnsAddrEntry);
171 
172  //Adjust the length of the multi-part buffer
173  netBufferSetLength(buffer, offset + length);
174 
175  //Debug message
176  TRACE_INFO("Sending NBNS message (%" PRIuSIZE " bytes)...\r\n", length);
177  //Dump message
179 
180  //A response packet is always sent to the source UDP port and
181  //source IP address of the request packet
182  error = udpSendDatagramEx(interface, NBNS_PORT, destIpAddr,
183  destPort, buffer, offset, IPV4_DEFAULT_TTL);
184 
185  //Free previously allocated memory
186  netBufferFree(buffer);
187  //Return status code
188  return error;
189 }
190 
191 #endif
#define DNS_GET_QUESTION(message, offset)
Definition: dns_common.h:61
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:232
__start_packed struct @151 DnsQuestion
Question format.
#define DNS_GET_RESOURCE_RECORD(message, offset)
Definition: dns_common.h:62
NBNS responder (NetBIOS Name Service)
uint16_t destPort
Definition: tcp.h:301
NetBIOS name service.
Definition: dns_common.h:132
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 netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:280
Debugging facilities.
Internet.
Definition: dns_common.h:108
uint8_t message[]
Definition: chap.h:150
error_t netBufferSetLength(NetBuffer *buffer, size_t length)
Adjust the length of a multi-part buffer.
Definition: net_mem.c:318
#define NBNS_PORT
Definition: nbns_common.h:44
IP network address.
Definition: ip.h:57
#define HTONL(value)
Definition: cpu_endian.h:389
#define Ipv4PseudoHeader
Definition: ipv4.h:37
#define HTONS(value)
Definition: cpu_endian.h:388
error_t nbnsSendResponse(NetInterface *interface, const IpAddr *destIpAddr, uint16_t destPort, uint16_t id)
Send NBNS response message.
#define IPV4_DEFAULT_TTL
Definition: ipv4.h:54
Data logging functions for debugging purpose (DNS)
__start_packed struct @150 DnsHeader
DNS message header.
#define ntohs(value)
Definition: cpu_endian.h:396
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:411
__start_packed struct @263 NbnsHeader
NBNS message header.
__start_packed struct @126 UdpHeader
UDP header.
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
uint16_t id
Definition: dns_common.h:156
void dnsDumpMessage(const DnsHeader *message, size_t length)
Dump DNS message for debugging purpose.
Definition: dns_debug.c:50
NetBuffer * udpAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold a UDP packet.
Definition: udp.c:656
#define TRACE_INFO(...)
Definition: debug.h:86
#define NBNS_DEFAULT_RESOURCE_RECORD_TTL
Definition: nbns_common.h:38
bool_t nbnsCompareName(const NbnsHeader *message, size_t length, size_t pos, const char_t *name)
Compare NetBIOS names.
Definition: nbns_common.c:280
#define DNS_MESSAGE_MAX_SIZE
Definition: dns_common.h:43
error_t
Error codes.
Definition: error.h:40
Ipv4Addr destIpAddr
Definition: ipcp.h:76
#define PRIuSIZE
Definition: compiler_port.h:72
error_t udpSendDatagramEx(NetInterface *interface, uint16_t srcPort, const IpAddr *destIpAddr, uint16_t destPort, NetBuffer *buffer, size_t offset, uint8_t ttl)
Send a UDP datagram (raw interface)
Definition: udp.c:448
#define NetInterface
Definition: net.h:34
__start_packed struct @264 NbnsAddrEntry
NBNS address entry.
void nbnsProcessQuery(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, const UdpHeader *udpHeader, const NbnsHeader *message, size_t length)
Process NBNS query message.
__start_packed struct @152 DnsResourceRecord
Resource record format.
size_t nbnsEncodeName(const char_t *src, uint8_t *dest)
Encode a NetBIOS name.
Definition: nbns_common.c:144
uint8_t length
Definition: dtls_misc.h:140
Definitions common to NBNS client and NBNS responder.