BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 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 #include "lwip/prot/iana.h"
53  
54 #include <string.h>
55  
56 /** size of a NetBIOS name */
57 #define NETBIOS_NAME_LEN 16
58  
59 /** The Time-To-Live for NetBIOS name responds (in seconds)
60 * Default is 300000 seconds (3 days, 11 hours, 20 minutes) */
61 #define NETBIOS_NAME_TTL 300000u
62  
63 /** NetBIOS header flags */
64 #define NETB_HFLAG_RESPONSE 0x8000U
65 #define NETB_HFLAG_OPCODE 0x7800U
66 #define NETB_HFLAG_OPCODE_NAME_QUERY 0x0000U
67 #define NETB_HFLAG_AUTHORATIVE 0x0400U
68 #define NETB_HFLAG_TRUNCATED 0x0200U
69 #define NETB_HFLAG_RECURS_DESIRED 0x0100U
70 #define NETB_HFLAG_RECURS_AVAILABLE 0x0080U
71 #define NETB_HFLAG_BROADCAST 0x0010U
72 #define NETB_HFLAG_REPLYCODE 0x0008U
73 #define NETB_HFLAG_REPLYCODE_NOERROR 0x0000U
74  
75 /** NetBIOS name flags */
76 #define NETB_NFLAG_UNIQUE 0x8000U
77 #define NETB_NFLAG_NODETYPE 0x6000U
78 #define NETB_NFLAG_NODETYPE_HNODE 0x6000U
79 #define NETB_NFLAG_NODETYPE_MNODE 0x4000U
80 #define NETB_NFLAG_NODETYPE_PNODE 0x2000U
81 #define NETB_NFLAG_NODETYPE_BNODE 0x0000U
82  
83 /** NetBIOS message header */
84 #ifdef PACK_STRUCT_USE_INCLUDES
85 # include "arch/bpstruct.h"
86 #endif
87 PACK_STRUCT_BEGIN
88 struct netbios_hdr {
89 PACK_STRUCT_FIELD(u16_t trans_id);
90 PACK_STRUCT_FIELD(u16_t flags);
91 PACK_STRUCT_FIELD(u16_t questions);
92 PACK_STRUCT_FIELD(u16_t answerRRs);
93 PACK_STRUCT_FIELD(u16_t authorityRRs);
94 PACK_STRUCT_FIELD(u16_t additionalRRs);
95 } PACK_STRUCT_STRUCT;
96 PACK_STRUCT_END
97 #ifdef PACK_STRUCT_USE_INCLUDES
98 # include "arch/epstruct.h"
99 #endif
100  
101 /** NetBIOS message name part */
102 #ifdef PACK_STRUCT_USE_INCLUDES
103 # include "arch/bpstruct.h"
104 #endif
105 PACK_STRUCT_BEGIN
106 struct netbios_name_hdr {
107 PACK_STRUCT_FLD_8(u8_t nametype);
108 PACK_STRUCT_FLD_8(u8_t encname[(NETBIOS_NAME_LEN * 2) + 1]);
109 PACK_STRUCT_FIELD(u16_t type);
110 PACK_STRUCT_FIELD(u16_t cls);
111 PACK_STRUCT_FIELD(u32_t ttl);
112 PACK_STRUCT_FIELD(u16_t datalen);
113 PACK_STRUCT_FIELD(u16_t flags);
114 PACK_STRUCT_FLD_S(ip4_addr_p_t addr);
115 } PACK_STRUCT_STRUCT;
116 PACK_STRUCT_END
117 #ifdef PACK_STRUCT_USE_INCLUDES
118 # include "arch/epstruct.h"
119 #endif
120  
121 /** NetBIOS message */
122 #ifdef PACK_STRUCT_USE_INCLUDES
123 # include "arch/bpstruct.h"
124 #endif
125 PACK_STRUCT_BEGIN
126 struct netbios_resp {
127 struct netbios_hdr resp_hdr;
128 struct netbios_name_hdr resp_name;
129 } PACK_STRUCT_STRUCT;
130 PACK_STRUCT_END
131 #ifdef PACK_STRUCT_USE_INCLUDES
132 # include "arch/epstruct.h"
133 #endif
134  
135 #ifdef NETBIOS_LWIP_NAME
136 #define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME
137 #else
138 static char netbiosns_local_name[NETBIOS_NAME_LEN];
139 #define NETBIOS_LOCAL_NAME netbiosns_local_name
140 #endif
141  
142 struct udp_pcb *netbiosns_pcb;
143  
144 /** Decode a NetBIOS name (from packet to string) */
145 static int
146 netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len)
147 {
148 char *pname;
149 char cname;
150 char cnbname;
151 int idx = 0;
152  
153 LWIP_UNUSED_ARG(name_dec_len);
154  
155 /* Start decoding netbios name. */
156 pname = name_enc;
157 for (;;) {
158 /* Every two characters of the first level-encoded name
159 * turn into one character in the decoded name. */
160 cname = *pname;
161 if (cname == '\0') {
162 break; /* no more characters */
163 }
164 if (cname == '.') {
165 break; /* scope ID follows */
166 }
167 if (cname < 'A' || cname > 'Z') {
168 /* Not legal. */
169 return -1;
170 }
171 cname -= 'A';
172 cnbname = cname << 4;
173 pname++;
174  
175 cname = *pname;
176 if (cname == '\0' || cname == '.') {
177 /* No more characters in the name - but we're in
178 * the middle of a pair. Not legal. */
179 return -1;
180 }
181 if (cname < 'A' || cname > 'Z') {
182 /* Not legal. */
183 return -1;
184 }
185 cname -= 'A';
186 cnbname |= cname;
187 pname++;
188  
189 /* Do we have room to store the character? */
190 if (idx < NETBIOS_NAME_LEN) {
191 /* Yes - store the character. */
192 name_dec[idx++] = (cnbname != ' ' ? cnbname : '\0');
193 }
194 }
195  
196 return 0;
197 }
198  
199 #if 0 /* function currently unused */
200 /** Encode a NetBIOS name (from string to packet) - currently unused because
201 we don't ask for names. */
202 static int
203 netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len)
204 {
205 char *pname;
206 char cname;
207 unsigned char ucname;
208 int idx = 0;
209  
210 /* Start encoding netbios name. */
211 pname = name_enc;
212  
213 for (;;) {
214 /* Every two characters of the first level-encoded name
215 * turn into one character in the decoded name. */
216 cname = *pname;
217 if (cname == '\0') {
218 break; /* no more characters */
219 }
220 if (cname == '.') {
221 break; /* scope ID follows */
222 }
223 if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) {
224 /* Not legal. */
225 return -1;
226 }
227  
228 /* Do we have room to store the character? */
229 if (idx >= name_dec_len) {
230 return -1;
231 }
232  
233 /* Yes - store the character. */
234 ucname = cname;
235 name_dec[idx++] = ('A' + ((ucname >> 4) & 0x0F));
236 name_dec[idx++] = ('A' + ( ucname & 0x0F));
237 pname++;
238 }
239  
240 /* Fill with "space" coding */
241 for (; idx < name_dec_len - 1;) {
242 name_dec[idx++] = 'C';
243 name_dec[idx++] = 'A';
244 }
245  
246 /* Terminate string */
247 name_dec[idx] = '\0';
248  
249 return 0;
250 }
251 #endif /* 0 */
252  
253 /** NetBIOS Name service recv callback */
254 static void
255 netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
256 {
257 LWIP_UNUSED_ARG(arg);
258  
259 /* if packet is valid */
260 if (p != NULL) {
261 char netbios_name[NETBIOS_NAME_LEN + 1];
262 struct netbios_hdr *netbios_hdr = (struct netbios_hdr *)p->payload;
263 struct netbios_name_hdr *netbios_name_hdr = (struct netbios_name_hdr *)(netbios_hdr + 1);
264  
265 /* we only answer if we got a default interface */
266 if (netif_default != NULL) {
267 /* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */
268 /* if the packet is a NetBIOS name query question */
269 if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) &&
270 ((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) &&
271 (netbios_hdr->questions == PP_NTOHS(1))) {
272 /* decode the NetBIOS name */
273 netbiosns_name_decode((char *)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name));
274 /* if the packet is for us */
275 if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) {
276 struct pbuf *q;
277 struct netbios_resp *resp;
278  
279 q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM);
280 if (q != NULL) {
281 resp = (struct netbios_resp *)q->payload;
282  
283 /* prepare NetBIOS header response */
284 resp->resp_hdr.trans_id = netbios_hdr->trans_id;
285 resp->resp_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE |
286 NETB_HFLAG_OPCODE_NAME_QUERY |
287 NETB_HFLAG_AUTHORATIVE |
288 NETB_HFLAG_RECURS_DESIRED);
289 resp->resp_hdr.questions = 0;
290 resp->resp_hdr.answerRRs = PP_HTONS(1);
291 resp->resp_hdr.authorityRRs = 0;
292 resp->resp_hdr.additionalRRs = 0;
293  
294 /* prepare NetBIOS header datas */
295 MEMCPY( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname));
296 resp->resp_name.nametype = netbios_name_hdr->nametype;
297 resp->resp_name.type = netbios_name_hdr->type;
298 resp->resp_name.cls = netbios_name_hdr->cls;
299 resp->resp_name.ttl = PP_HTONL(NETBIOS_NAME_TTL);
300 resp->resp_name.datalen = PP_HTONS(sizeof(resp->resp_name.flags) + sizeof(resp->resp_name.addr));
301 resp->resp_name.flags = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE);
302 ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default));
303  
304 /* send the NetBIOS response */
305 udp_sendto(upcb, q, addr, port);
306  
307 /* free the "reference" pbuf */
308 pbuf_free(q);
309 }
310 }
311 }
312 }
313 /* free the pbuf */
314 pbuf_free(p);
315 }
316 }
317  
318 /**
319 * @ingroup netbiosns
320 * Init netbios responder
321 */
322 void
323 netbiosns_init(void)
324 {
325 #ifdef NETBIOS_LWIP_NAME
326 LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN);
327 #endif
328  
329 netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
330 if (netbiosns_pcb != NULL) {
331 /* we have to be allowed to send broadcast packets! */
332 ip_set_option(netbiosns_pcb, SOF_BROADCAST);
333 udp_bind(netbiosns_pcb, IP_ANY_TYPE, LWIP_IANA_PORT_NETBIOS);
334 udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb);
335 }
336 }
337  
338 #ifndef NETBIOS_LWIP_NAME
339 /**
340 * @ingroup netbiosns
341 * Set netbios name. ATTENTION: the hostname must be less than 15 characters!
342 */
343 void
344 netbiosns_set_name(const char *hostname)
345 {
346 size_t copy_len = strlen(hostname);
347 LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN);
348 if (copy_len >= NETBIOS_NAME_LEN) {
349 copy_len = NETBIOS_NAME_LEN - 1;
350 }
351 MEMCPY(netbiosns_local_name, hostname, copy_len + 1);
352 }
353 #endif
354  
355 /**
356 * @ingroup netbiosns
357 * Stop netbios responder
358 */
359 void
360 netbiosns_stop(void)
361 {
362 if (netbiosns_pcb != NULL) {
363 udp_remove(netbiosns_pcb);
364 netbiosns_pcb = NULL;
365 }
366 }
367  
368 #endif /* LWIP_IPV4 && LWIP_UDP */