1 /**
2 * @file
3 * NetBIOS name service responder
4 */
5
6 /**
7 * @defgroup netbiosns NETBIOS responder
8 * @ingroup apps
9 *
10 * This is an example implementation of a NetBIOS name server.
11 * It responds to name queries for a configurable name.
12 * Name resolving is not supported.
13 *
14 * Note that the device doesn't broadcast it's own name so can't
15 * detect duplicate names!
16 */
17
18 /*
19 * Redistribution and use in source and binary forms, with or without modification,
20 * are permitted provided that the following conditions are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright notice,
23 * this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright notice,
25 * this list of conditions and the following disclaimer in the documentation
26 * and/or other materials provided with the distribution.
27 * 3. The name of the author may not be used to endorse or promote products
28 * derived from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
31 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
32 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
33 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
34 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
35 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
38 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
39 * OF SUCH DAMAGE.
40 *
41 * This file is part of the lwIP TCP/IP stack.
42 *
43 */
44
45 #include "lwip/apps/netbiosns.h"
46
47 #if LWIP_IPV4 && LWIP_UDP /* don't build if not configured for use in lwipopts.h */
48
49 #include "lwip/def.h"
50 #include "lwip/udp.h"
51 #include "lwip/netif.h"
52
53 #include <string.h>
54
55 /** default port number for "NetBIOS Name service */
56 #define NETBIOS_PORT 137
57
58 /** size of a NetBIOS name */
59 #define NETBIOS_NAME_LEN 16
60
61 /** The Time-To-Live for NetBIOS name responds (in seconds)
62 * Default is 300000 seconds (3 days, 11 hours, 20 minutes) */
63 #define NETBIOS_NAME_TTL 300000u
64
65 /** NetBIOS header flags */
66 #define NETB_HFLAG_RESPONSE 0x8000U
67 #define NETB_HFLAG_OPCODE 0x7800U
68 #define NETB_HFLAG_OPCODE_NAME_QUERY 0x0000U
69 #define NETB_HFLAG_AUTHORATIVE 0x0400U
70 #define NETB_HFLAG_TRUNCATED 0x0200U
71 #define NETB_HFLAG_RECURS_DESIRED 0x0100U
72 #define NETB_HFLAG_RECURS_AVAILABLE 0x0080U
73 #define NETB_HFLAG_BROADCAST 0x0010U
74 #define NETB_HFLAG_REPLYCODE 0x0008U
75 #define NETB_HFLAG_REPLYCODE_NOERROR 0x0000U
76
77 /** NetBIOS name flags */
78 #define NETB_NFLAG_UNIQUE 0x8000U
79 #define NETB_NFLAG_NODETYPE 0x6000U
80 #define NETB_NFLAG_NODETYPE_HNODE 0x6000U
81 #define NETB_NFLAG_NODETYPE_MNODE 0x4000U
82 #define NETB_NFLAG_NODETYPE_PNODE 0x2000U
83 #define NETB_NFLAG_NODETYPE_BNODE 0x0000U
84
85 /** NetBIOS message header */
86 #ifdef PACK_STRUCT_USE_INCLUDES
87 # include "arch/bpstruct.h"
88 #endif
89 PACK_STRUCT_BEGIN
90 struct netbios_hdr {
91 PACK_STRUCT_FIELD(u16_t trans_id);
92 PACK_STRUCT_FIELD(u16_t flags);
93 PACK_STRUCT_FIELD(u16_t questions);
94 PACK_STRUCT_FIELD(u16_t answerRRs);
95 PACK_STRUCT_FIELD(u16_t authorityRRs);
96 PACK_STRUCT_FIELD(u16_t additionalRRs);
97 } PACK_STRUCT_STRUCT;
98 PACK_STRUCT_END
99 #ifdef PACK_STRUCT_USE_INCLUDES
100 # include "arch/epstruct.h"
101 #endif
102
103 /** NetBIOS message name part */
104 #ifdef PACK_STRUCT_USE_INCLUDES
105 # include "arch/bpstruct.h"
106 #endif
107 PACK_STRUCT_BEGIN
108 struct netbios_name_hdr {
109 PACK_STRUCT_FLD_8(u8_t nametype);
110 PACK_STRUCT_FLD_8(u8_t encname[(NETBIOS_NAME_LEN*2)+1]);
111 PACK_STRUCT_FIELD(u16_t type);
112 PACK_STRUCT_FIELD(u16_t cls);
113 PACK_STRUCT_FIELD(u32_t ttl);
114 PACK_STRUCT_FIELD(u16_t datalen);
115 PACK_STRUCT_FIELD(u16_t flags);
116 PACK_STRUCT_FLD_S(ip4_addr_p_t addr);
117 } PACK_STRUCT_STRUCT;
118 PACK_STRUCT_END
119 #ifdef PACK_STRUCT_USE_INCLUDES
120 # include "arch/epstruct.h"
121 #endif
122
123 /** NetBIOS message */
124 #ifdef PACK_STRUCT_USE_INCLUDES
125 # include "arch/bpstruct.h"
126 #endif
127 PACK_STRUCT_BEGIN
128 struct netbios_resp
129 {
130 struct netbios_hdr resp_hdr;
131 struct netbios_name_hdr resp_name;
132 } PACK_STRUCT_STRUCT;
133 PACK_STRUCT_END
134 #ifdef PACK_STRUCT_USE_INCLUDES
135 # include "arch/epstruct.h"
136 #endif
137
138 #ifdef NETBIOS_LWIP_NAME
139 #define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME
140 #else
141 static char netbiosns_local_name[NETBIOS_NAME_LEN];
142 #define NETBIOS_LOCAL_NAME netbiosns_local_name
143 #endif
144
145 struct udp_pcb *netbiosns_pcb;
146
147 /** Decode a NetBIOS name (from packet to string) */
148 static int
netbiosns_name_decode(char * name_enc,char * name_dec,int name_dec_len)149 netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len)
150 {
151 char *pname;
152 char cname;
153 char cnbname;
154 int idx = 0;
155
156 LWIP_UNUSED_ARG(name_dec_len);
157
158 /* Start decoding netbios name. */
159 pname = name_enc;
160 for (;;) {
161 /* Every two characters of the first level-encoded name
162 * turn into one character in the decoded name. */
163 cname = *pname;
164 if (cname == '\0')
165 break; /* no more characters */
166 if (cname == '.')
167 break; /* scope ID follows */
168 if (cname < 'A' || cname > 'Z') {
169 /* Not legal. */
170 return -1;
171 }
172 cname -= 'A';
173 cnbname = cname << 4;
174 pname++;
175
176 cname = *pname;
177 if (cname == '\0' || cname == '.') {
178 /* No more characters in the name - but we're in
179 * the middle of a pair. Not legal. */
180 return -1;
181 }
182 if (cname < 'A' || cname > 'Z') {
183 /* Not legal. */
184 return -1;
185 }
186 cname -= 'A';
187 cnbname |= cname;
188 pname++;
189
190 /* Do we have room to store the character? */
191 if (idx < NETBIOS_NAME_LEN) {
192 /* Yes - store the character. */
193 name_dec[idx++] = (cnbname!=' '?cnbname:'\0');
194 }
195 }
196
197 return 0;
198 }
199
200 #if 0 /* function currently unused */
201 /** Encode a NetBIOS name (from string to packet) - currently unused because
202 we don't ask for names. */
203 static int
204 netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len)
205 {
206 char *pname;
207 char cname;
208 unsigned char ucname;
209 int idx = 0;
210
211 /* Start encoding netbios name. */
212 pname = name_enc;
213
214 for (;;) {
215 /* Every two characters of the first level-encoded name
216 * turn into one character in the decoded name. */
217 cname = *pname;
218 if (cname == '\0')
219 break; /* no more characters */
220 if (cname == '.')
221 break; /* scope ID follows */
222 if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) {
223 /* Not legal. */
224 return -1;
225 }
226
227 /* Do we have room to store the character? */
228 if (idx >= name_dec_len) {
229 return -1;
230 }
231
232 /* Yes - store the character. */
233 ucname = cname;
234 name_dec[idx++] = ('A'+((ucname>>4) & 0x0F));
235 name_dec[idx++] = ('A'+( ucname & 0x0F));
236 pname++;
237 }
238
239 /* Fill with "space" coding */
240 for (;idx < name_dec_len - 1;) {
241 name_dec[idx++] = 'C';
242 name_dec[idx++] = 'A';
243 }
244
245 /* Terminate string */
246 name_dec[idx] = '\0';
247
248 return 0;
249 }
250 #endif /* 0 */
251
252 /** NetBIOS Name service recv callback */
253 static void
netbiosns_recv(void * arg,struct udp_pcb * upcb,struct pbuf * p,const ip_addr_t * addr,u16_t port)254 netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
255 {
256 LWIP_UNUSED_ARG(arg);
257
258 /* if packet is valid */
259 if (p != NULL) {
260 char netbios_name[NETBIOS_NAME_LEN+1];
261 struct netbios_hdr* netbios_hdr = (struct netbios_hdr*)p->payload;
262 struct netbios_name_hdr* netbios_name_hdr = (struct netbios_name_hdr*)(netbios_hdr+1);
263
264 /* we only answer if we got a default interface */
265 if (netif_default != NULL) {
266 /* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */
267 /* if the packet is a NetBIOS name query question */
268 if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) &&
269 ((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) &&
270 (netbios_hdr->questions == PP_NTOHS(1))) {
271 /* decode the NetBIOS name */
272 netbiosns_name_decode((char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name));
273 /* if the packet is for us */
274 if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) {
275 struct pbuf *q;
276 struct netbios_resp *resp;
277
278 q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM);
279 if (q != NULL) {
280 resp = (struct netbios_resp*)q->payload;
281
282 /* prepare NetBIOS header response */
283 resp->resp_hdr.trans_id = netbios_hdr->trans_id;
284 resp->resp_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE |
285 NETB_HFLAG_OPCODE_NAME_QUERY |
286 NETB_HFLAG_AUTHORATIVE |
287 NETB_HFLAG_RECURS_DESIRED);
288 resp->resp_hdr.questions = 0;
289 resp->resp_hdr.answerRRs = PP_HTONS(1);
290 resp->resp_hdr.authorityRRs = 0;
291 resp->resp_hdr.additionalRRs = 0;
292
293 /* prepare NetBIOS header datas */
294 MEMCPY( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname));
295 resp->resp_name.nametype = netbios_name_hdr->nametype;
296 resp->resp_name.type = netbios_name_hdr->type;
297 resp->resp_name.cls = netbios_name_hdr->cls;
298 resp->resp_name.ttl = PP_HTONL(NETBIOS_NAME_TTL);
299 resp->resp_name.datalen = PP_HTONS(sizeof(resp->resp_name.flags)+sizeof(resp->resp_name.addr));
300 resp->resp_name.flags = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE);
301 ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default));
302
303 /* send the NetBIOS response */
304 udp_sendto(upcb, q, addr, port);
305
306 /* free the "reference" pbuf */
307 pbuf_free(q);
308 }
309 }
310 }
311 }
312 /* free the pbuf */
313 pbuf_free(p);
314 }
315 }
316
317 /**
318 * @ingroup netbiosns
319 * Init netbios responder
320 */
321 void
netbiosns_init(void)322 netbiosns_init(void)
323 {
324 #ifdef NETBIOS_LWIP_NAME
325 LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN);
326 #endif
327
328 netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
329 if (netbiosns_pcb != NULL) {
330 /* we have to be allowed to send broadcast packets! */
331 ip_set_option(netbiosns_pcb, SOF_BROADCAST);
332 udp_bind(netbiosns_pcb, IP_ANY_TYPE, NETBIOS_PORT);
333 udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb);
334 }
335 }
336
337 #ifndef NETBIOS_LWIP_NAME
338 /**
339 * @ingroup netbiosns
340 * Set netbios name. ATTENTION: the hostname must be less than 15 characters!
341 */
342 void
netbiosns_set_name(const char * hostname)343 netbiosns_set_name(const char* hostname)
344 {
345 size_t copy_len = strlen(hostname);
346 LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN);
347 if (copy_len >= NETBIOS_NAME_LEN) {
348 copy_len = NETBIOS_NAME_LEN - 1;
349 }
350 MEMCPY(netbiosns_local_name, hostname, copy_len + 1);
351 }
352 #endif
353
354 /**
355 * @ingroup netbiosns
356 * Stop netbios responder
357 */
358 void
netbiosns_stop(void)359 netbiosns_stop(void)
360 {
361 if (netbiosns_pcb != NULL) {
362 udp_remove(netbiosns_pcb);
363 netbiosns_pcb = NULL;
364 }
365 }
366
367 #endif /* LWIP_IPV4 && LWIP_UDP */
368