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