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 * Modifications by Ray Abram to respond to NetBIOS name requests when Incoming name = * 44 * - based on code from "https://github.com/esp8266/Arduino/commit/1f7989b31d26d7df9776a08f36d685eae7ac8f99" 45 * - with permission to relicense to BSD from original author: 46 * http://www.xpablo.cz/?p=751#more-751 47 */ 48 49 #include "lwip/apps/netbiosns.h" 50 51 #if LWIP_IPV4 && LWIP_UDP /* don't build if not configured for use in lwipopts.h */ 52 53 #include "lwip/def.h" 54 #include "lwip/udp.h" 55 #include "lwip/ip.h" 56 #include "lwip/netif.h" 57 #include "lwip/prot/iana.h" 58 59 #include <string.h> 60 61 /** size of a NetBIOS name */ 62 #define NETBIOS_NAME_LEN 16 63 64 /** The Time-To-Live for NetBIOS name responds (in seconds) 65 * Default is 300000 seconds (3 days, 11 hours, 20 minutes) */ 66 #define NETBIOS_NAME_TTL 300000u 67 68 /** NetBIOS header flags */ 69 #define NETB_HFLAG_RESPONSE 0x8000U 70 #define NETB_HFLAG_OPCODE 0x7800U 71 #define NETB_HFLAG_OPCODE_NAME_QUERY 0x0000U 72 #define NETB_HFLAG_AUTHORATIVE 0x0400U 73 #define NETB_HFLAG_TRUNCATED 0x0200U 74 #define NETB_HFLAG_RECURS_DESIRED 0x0100U 75 #define NETB_HFLAG_RECURS_AVAILABLE 0x0080U 76 #define NETB_HFLAG_BROADCAST 0x0010U 77 #define NETB_HFLAG_REPLYCODE 0x0008U 78 #define NETB_HFLAG_REPLYCODE_NOERROR 0x0000U 79 80 /* NetBIOS question types */ 81 #define NETB_QTYPE_NB 0x0020U 82 #define NETB_QTYPE_NBSTAT 0x0021U 83 84 /** NetBIOS name flags */ 85 #define NETB_NFLAG_UNIQUE 0x8000U 86 #define NETB_NFLAG_NODETYPE 0x6000U 87 #define NETB_NFLAG_NODETYPE_HNODE 0x6000U 88 #define NETB_NFLAG_NODETYPE_MNODE 0x4000U 89 #define NETB_NFLAG_NODETYPE_PNODE 0x2000U 90 #define NETB_NFLAG_NODETYPE_BNODE 0x0000U 91 92 #define NETB_NFLAG_NAME_IN_CONFLICT 0x0800U /* 1=Yes, 0=No */ 93 #define NETB_NFLAG_NAME_IS_ACTIVE 0x0400U /* 1=Yes, 0=No */ 94 #define NETB_NFLAG_NAME_IS_PERMANENT 0x0200U /* 1=Yes (Name is Permanent Node Name), 0=No */ 95 96 /** NetBIOS message header */ 97 #ifdef PACK_STRUCT_USE_INCLUDES 98 # include "arch/bpstruct.h" 99 #endif 100 PACK_STRUCT_BEGIN 101 struct netbios_hdr { 102 PACK_STRUCT_FIELD(u16_t trans_id); 103 PACK_STRUCT_FIELD(u16_t flags); 104 PACK_STRUCT_FIELD(u16_t questions); 105 PACK_STRUCT_FIELD(u16_t answerRRs); 106 PACK_STRUCT_FIELD(u16_t authorityRRs); 107 PACK_STRUCT_FIELD(u16_t additionalRRs); 108 } PACK_STRUCT_STRUCT; 109 PACK_STRUCT_END 110 #ifdef PACK_STRUCT_USE_INCLUDES 111 # include "arch/epstruct.h" 112 #endif 113 114 /** NetBIOS message name part */ 115 #ifdef PACK_STRUCT_USE_INCLUDES 116 # include "arch/bpstruct.h" 117 #endif 118 PACK_STRUCT_BEGIN 119 struct netbios_name_hdr { 120 PACK_STRUCT_FLD_8(u8_t nametype); 121 PACK_STRUCT_FLD_8(u8_t encname[(NETBIOS_NAME_LEN * 2) + 1]); 122 PACK_STRUCT_FIELD(u16_t type); 123 PACK_STRUCT_FIELD(u16_t cls); 124 PACK_STRUCT_FIELD(u32_t ttl); 125 PACK_STRUCT_FIELD(u16_t datalen); 126 PACK_STRUCT_FIELD(u16_t flags); 127 PACK_STRUCT_FLD_S(ip4_addr_p_t addr); 128 } PACK_STRUCT_STRUCT; 129 PACK_STRUCT_END 130 #ifdef PACK_STRUCT_USE_INCLUDES 131 # include "arch/epstruct.h" 132 #endif 133 134 /** NetBIOS message */ 135 #ifdef PACK_STRUCT_USE_INCLUDES 136 # include "arch/bpstruct.h" 137 #endif 138 PACK_STRUCT_BEGIN 139 struct netbios_resp { 140 struct netbios_hdr resp_hdr; 141 struct netbios_name_hdr resp_name; 142 } PACK_STRUCT_STRUCT; 143 PACK_STRUCT_END 144 #ifdef PACK_STRUCT_USE_INCLUDES 145 # include "arch/epstruct.h" 146 #endif 147 148 /** The NBNS Structure Responds to a Name Query */ 149 #ifdef PACK_STRUCT_USE_INCLUDES 150 # include "arch/bpstruct.h" 151 #endif 152 PACK_STRUCT_BEGIN 153 struct netbios_answer { 154 struct netbios_hdr answer_hdr; 155 /** the length of the next string */ 156 PACK_STRUCT_FIELD(u8_t name_size); 157 /** WARNING!!! this item may be of a different length (we use this struct for transmission) */ 158 PACK_STRUCT_FLD_8(u8_t query_name[(NETBIOS_NAME_LEN * 2) + 1]); 159 PACK_STRUCT_FIELD(u16_t packet_type); 160 PACK_STRUCT_FIELD(u16_t cls); 161 PACK_STRUCT_FIELD(u32_t ttl); 162 PACK_STRUCT_FIELD(u16_t data_length); 163 #define OFFSETOF_STRUCT_NETBIOS_ANSWER_NUMBER_OF_NAMES 56 164 /** number of names */ 165 PACK_STRUCT_FLD_8(u8_t number_of_names); 166 /** node name */ 167 PACK_STRUCT_FLD_8(u8_t answer_name[NETBIOS_NAME_LEN]); 168 /** node flags */ 169 PACK_STRUCT_FIELD(u16_t answer_name_flags); 170 /** Unit ID */ 171 PACK_STRUCT_FLD_8(u8_t unit_id[6]); 172 /** Jumpers */ 173 PACK_STRUCT_FLD_8(u8_t jumpers); 174 /** Test result */ 175 PACK_STRUCT_FLD_8(u8_t test_result); 176 /** Version number */ 177 PACK_STRUCT_FIELD(u16_t version_number); 178 /** Period of statistics */ 179 PACK_STRUCT_FIELD(u16_t period_of_statistics); 180 /** Statistics */ 181 PACK_STRUCT_FIELD(u16_t number_of_crcs); 182 /** Statistics */ 183 PACK_STRUCT_FIELD(u16_t number_of_alignment_errors); 184 /** Statistics */ 185 PACK_STRUCT_FIELD(u16_t number_of_collisions); 186 /** Statistics */ 187 PACK_STRUCT_FIELD(u16_t number_of_send_aborts); 188 /** Statistics */ 189 PACK_STRUCT_FIELD(u32_t number_of_good_sends); 190 /** Statistics */ 191 PACK_STRUCT_FIELD(u32_t number_of_good_receives); 192 /** Statistics */ 193 PACK_STRUCT_FIELD(u16_t number_of_retransmits); 194 /** Statistics */ 195 PACK_STRUCT_FIELD(u16_t number_of_no_resource_condition); 196 /** Statistics */ 197 PACK_STRUCT_FIELD(u16_t number_of_free_command_blocks); 198 /** Statistics */ 199 PACK_STRUCT_FIELD(u16_t total_number_of_command_blocks); 200 /** Statistics */ 201 PACK_STRUCT_FIELD(u16_t max_total_number_of_command_blocks); 202 /** Statistics */ 203 PACK_STRUCT_FIELD(u16_t number_of_pending_sessions); 204 /** Statistics */ 205 PACK_STRUCT_FIELD(u16_t max_number_of_pending_sessions); 206 /** Statistics */ 207 PACK_STRUCT_FIELD(u16_t max_total_sessions_possible); 208 /** Statistics */ 209 PACK_STRUCT_FIELD(u16_t session_data_packet_size); 210 } PACK_STRUCT_STRUCT; 211 PACK_STRUCT_END 212 #ifdef PACK_STRUCT_USE_INCLUDES 213 # include "arch/epstruct.h" 214 #endif 215 216 #ifdef NETBIOS_LWIP_NAME 217 #define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME 218 #else 219 static char netbiosns_local_name[NETBIOS_NAME_LEN]; 220 #define NETBIOS_LOCAL_NAME netbiosns_local_name 221 #endif 222 223 static struct udp_pcb *netbiosns_pcb; 224 225 /** Decode a NetBIOS name (from packet to string) */ 226 static int 227 netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len) 228 { 229 char *pname; 230 char cname; 231 char cnbname; 232 int idx = 0; 233 234 LWIP_UNUSED_ARG(name_dec_len); 235 236 /* Start decoding netbios name. */ 237 pname = name_enc; 238 for (;;) { 239 /* Every two characters of the first level-encoded name 240 * turn into one character in the decoded name. */ 241 cname = *pname; 242 if (cname == '\0') { 243 break; /* no more characters */ 244 } 245 if (cname == '.') { 246 break; /* scope ID follows */ 247 } 248 if (!lwip_isupper(cname)) { 249 /* Not legal. */ 250 return -1; 251 } 252 cname -= 'A'; 253 cnbname = cname << 4; 254 pname++; 255 256 cname = *pname; 257 if (!lwip_isupper(cname)) { 258 /* Not legal. */ 259 return -1; 260 } 261 cname -= 'A'; 262 cnbname |= cname; 263 pname++; 264 265 /* Do we have room to store the character? */ 266 if (idx < NETBIOS_NAME_LEN) { 267 /* Yes - store the character. */ 268 name_dec[idx++] = (cnbname != ' ' ? cnbname : '\0'); 269 } 270 } 271 272 return 0; 273 } 274 275 #if 0 /* function currently unused */ 276 /** Encode a NetBIOS name (from string to packet) - currently unused because 277 we don't ask for names. */ 278 static int 279 netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len) 280 { 281 char *pname; 282 char cname; 283 unsigned char ucname; 284 int idx = 0; 285 286 /* Start encoding netbios name. */ 287 pname = name_enc; 288 289 for (;;) { 290 /* Every two characters of the first level-encoded name 291 * turn into one character in the decoded name. */ 292 cname = *pname; 293 if (cname == '\0') { 294 break; /* no more characters */ 295 } 296 if (cname == '.') { 297 break; /* scope ID follows */ 298 } 299 if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) { 300 /* Not legal. */ 301 return -1; 302 } 303 304 /* Do we have room to store the character? */ 305 if (idx >= name_dec_len) { 306 return -1; 307 } 308 309 /* Yes - store the character. */ 310 ucname = cname; 311 name_dec[idx++] = ('A' + ((ucname >> 4) & 0x0F)); 312 name_dec[idx++] = ('A' + ( ucname & 0x0F)); 313 pname++; 314 } 315 316 /* Fill with "space" coding */ 317 for (; idx < name_dec_len - 1;) { 318 name_dec[idx++] = 'C'; 319 name_dec[idx++] = 'A'; 320 } 321 322 /* Terminate string */ 323 name_dec[idx] = '\0'; 324 325 return 0; 326 } 327 #endif /* 0 */ 328 329 /** NetBIOS Name service recv callback */ 330 static void 331 netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) 332 { 333 LWIP_UNUSED_ARG(arg); 334 335 /* if packet is valid */ 336 if (p != NULL) { 337 char netbios_name[NETBIOS_NAME_LEN + 1]; 338 struct netbios_hdr *netbios_hdr = (struct netbios_hdr *)p->payload; 339 struct netbios_name_hdr *netbios_name_hdr = (struct netbios_name_hdr *)(netbios_hdr + 1); 340 341 /* is the packet long enough (we need the header in one piece) */ 342 if (p->len < (sizeof(struct netbios_hdr) + sizeof(struct netbios_name_hdr))) { 343 /* packet too short */ 344 pbuf_free(p); 345 return; 346 } 347 /* we only answer if we got a default interface */ 348 if (netif_default != NULL) { 349 /* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */ 350 /* if the packet is a NetBIOS name query question */ 351 if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) && 352 ((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) && 353 (netbios_hdr->questions == PP_NTOHS(1))) { 354 /* decode the NetBIOS name */ 355 netbiosns_name_decode((char *)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name)); 356 /* check the request type */ 357 if (netbios_name_hdr->type == PP_HTONS(NETB_QTYPE_NB)) { 358 /* if the packet is for us */ 359 if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) { 360 struct pbuf *q; 361 struct netbios_resp *resp; 362 363 q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM); 364 if (q != NULL) { 365 resp = (struct netbios_resp *)q->payload; 366 367 /* prepare NetBIOS header response */ 368 resp->resp_hdr.trans_id = netbios_hdr->trans_id; 369 resp->resp_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE | 370 NETB_HFLAG_OPCODE_NAME_QUERY | 371 NETB_HFLAG_AUTHORATIVE | 372 NETB_HFLAG_RECURS_DESIRED); 373 resp->resp_hdr.questions = 0; 374 resp->resp_hdr.answerRRs = PP_HTONS(1); 375 resp->resp_hdr.authorityRRs = 0; 376 resp->resp_hdr.additionalRRs = 0; 377 378 /* prepare NetBIOS header datas */ 379 MEMCPY( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname)); 380 resp->resp_name.nametype = netbios_name_hdr->nametype; 381 resp->resp_name.type = netbios_name_hdr->type; 382 resp->resp_name.cls = netbios_name_hdr->cls; 383 resp->resp_name.ttl = PP_HTONL(NETBIOS_NAME_TTL); 384 resp->resp_name.datalen = PP_HTONS(sizeof(resp->resp_name.flags) + sizeof(resp->resp_name.addr)); 385 resp->resp_name.flags = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE); 386 ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default)); 387 388 /* send the NetBIOS response */ 389 udp_sendto(upcb, q, addr, port); 390 391 /* free the "reference" pbuf */ 392 pbuf_free(q); 393 } 394 } 395 #if LWIP_NETBIOS_RESPOND_NAME_QUERY 396 } else if (netbios_name_hdr->type == PP_HTONS(NETB_QTYPE_NBSTAT)) { 397 /* if the packet is for us or general query */ 398 if (!lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) || 399 !lwip_strnicmp(netbios_name, "*", sizeof(NETBIOS_LOCAL_NAME))) { 400 /* general query - ask for our IP address */ 401 struct pbuf *q; 402 struct netbios_answer *resp; 403 404 q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_answer), PBUF_RAM); 405 if (q != NULL) { 406 /* buffer to which a response is compiled */ 407 resp = (struct netbios_answer *) q->payload; 408 409 /* Init response to zero, especially the statistics fields */ 410 memset(resp, 0, sizeof(*resp)); 411 412 /* copy the query to the response ID */ 413 resp->answer_hdr.trans_id = netbios_hdr->trans_id; 414 /* acknowledgment of termination */ 415 resp->answer_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE | NETB_HFLAG_OPCODE_NAME_QUERY | NETB_HFLAG_AUTHORATIVE); 416 /* resp->answer_hdr.questions = PP_HTONS(0); done by memset() */ 417 /* serial number of the answer */ 418 resp->answer_hdr.answerRRs = PP_HTONS(1); 419 /* resp->answer_hdr.authorityRRs = PP_HTONS(0); done by memset() */ 420 /* resp->answer_hdr.additionalRRs = PP_HTONS(0); done by memset() */ 421 /* we will copy the length of the station name */ 422 resp->name_size = netbios_name_hdr->nametype; 423 /* we will copy the queried name */ 424 MEMCPY(resp->query_name, netbios_name_hdr->encname, (NETBIOS_NAME_LEN * 2) + 1); 425 /* NBSTAT */ 426 resp->packet_type = PP_HTONS(0x21); 427 /* Internet name */ 428 resp->cls = PP_HTONS(1); 429 /* resp->ttl = PP_HTONL(0); done by memset() */ 430 resp->data_length = PP_HTONS(sizeof(struct netbios_answer) - offsetof(struct netbios_answer, number_of_names)); 431 resp->number_of_names = 1; 432 433 /* make windows see us as workstation, not as a server */ 434 memset(resp->answer_name, 0x20, NETBIOS_NAME_LEN - 1); 435 /* strlen is checked to be < NETBIOS_NAME_LEN during initialization */ 436 MEMCPY(resp->answer_name, NETBIOS_LOCAL_NAME, strlen(NETBIOS_LOCAL_NAME)); 437 438 /* b-node, unique, active */ 439 resp->answer_name_flags = PP_HTONS(NETB_NFLAG_NAME_IS_ACTIVE); 440 441 /* Set responder netif MAC address */ 442 SMEMCPY(resp->unit_id, ip_current_input_netif()->hwaddr, sizeof(resp->unit_id)); 443 444 udp_sendto(upcb, q, addr, port); 445 pbuf_free(q); 446 } 447 } 448 #endif /* LWIP_NETBIOS_RESPOND_NAME_QUERY */ 449 } 450 } 451 } 452 /* free the pbuf */ 453 pbuf_free(p); 454 } 455 } 456 457 /** 458 * @ingroup netbiosns 459 * Init netbios responder 460 */ 461 void 462 netbiosns_init(void) 463 { 464 /* LWIP_ASSERT_CORE_LOCKED(); is checked by udp_new() */ 465 #ifdef NETBIOS_LWIP_NAME 466 LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN); 467 #endif 468 469 netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); 470 if (netbiosns_pcb != NULL) { 471 /* we have to be allowed to send broadcast packets! */ 472 ip_set_option(netbiosns_pcb, SOF_BROADCAST); 473 udp_bind(netbiosns_pcb, IP_ANY_TYPE, LWIP_IANA_PORT_NETBIOS); 474 udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb); 475 } 476 } 477 478 #ifndef NETBIOS_LWIP_NAME 479 /** 480 * @ingroup netbiosns 481 * Set netbios name. ATTENTION: the hostname must be less than 15 characters! 482 * the NetBIOS name spec says the name MUST be upper case, so incoming name is forced into uppercase :-) 483 */ 484 void 485 netbiosns_set_name(const char *hostname) 486 { 487 size_t i; 488 size_t copy_len = strlen(hostname); 489 LWIP_ASSERT_CORE_LOCKED(); 490 LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN); 491 if (copy_len >= NETBIOS_NAME_LEN) { 492 copy_len = NETBIOS_NAME_LEN - 1; 493 } 494 495 /* make name into upper case */ 496 for (i = 0; i < copy_len; i++ ) { 497 netbiosns_local_name[i] = (char)lwip_toupper(hostname[i]); 498 } 499 netbiosns_local_name[copy_len] = '\0'; 500 } 501 #endif /* NETBIOS_LWIP_NAME */ 502 503 /** 504 * @ingroup netbiosns 505 * Stop netbios responder 506 */ 507 void 508 netbiosns_stop(void) 509 { 510 LWIP_ASSERT_CORE_LOCKED(); 511 if (netbiosns_pcb != NULL) { 512 udp_remove(netbiosns_pcb); 513 netbiosns_pcb = NULL; 514 } 515 } 516 517 #endif /* LWIP_IPV4 && LWIP_UDP */ 518