NetBIOS Responder should respond to "*" names

See bug #53325

Signed-off-by: goldsimon <goldsimon@gmx.de>
This commit is contained in:
Ray Abram 2018-03-12 02:44:59 +01:00 committed by goldsimon
parent 82d8f08451
commit b0ae967660
2 changed files with 98 additions and 3 deletions

View File

@ -1,4 +1,4 @@
/**
/**
* @file
* NetBIOS name service responder
*/
@ -40,6 +40,10 @@
*
* This file is part of the lwIP TCP/IP stack.
*
* Modifications by Ray Abram to respond to NetBIOS name requests when Incoming name = *
* - based on code from "https://github.com/esp8266/Arduino/commit/1f7989b31d26d7df9776a08f36d685eae7ac8f99"
* - with permission to relicense to BSD from original author:
* http://www.xpablo.cz/?p=751#more-751
*/
#include "lwip/apps/netbiosns.h"
@ -80,6 +84,10 @@
#define NETB_NFLAG_NODETYPE_PNODE 0x2000U
#define NETB_NFLAG_NODETYPE_BNODE 0x0000U
#define NETB_NFLAG_NAME_IN_CONFLICT 0x0800U /* 1=Yes, 0=No */
#define NETB_NFLAG_NAME_IS_ACTIVE 0x0400U /* 1=Yes, 0=No */
#define NETB_NFLAG_NAME_IS_PERMANENT 0x0200U /* 1=Yes (Name is Permanent Node Name), 0=No */
/** NetBIOS message header */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
@ -132,6 +140,35 @@ PACK_STRUCT_END
# include "arch/epstruct.h"
#endif
/** The NBNS Structure Responds to a Name Query */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct netbios_answer {
struct netbios_hdr answer_hdr;
/** the length of the next string */
PACK_STRUCT_FIELD(u8_t name_size);
/** WARNING!!! this item may be of a different length (we use this struct for transmission) */
PACK_STRUCT_FLD_8(u8_t query_name[(NETBIOS_NAME_LEN * 2) + 1]);
PACK_STRUCT_FIELD(u16_t packet_type);
PACK_STRUCT_FIELD(u16_t cls);
PACK_STRUCT_FIELD(u32_t ttl);
PACK_STRUCT_FIELD(u16_t data_length);
/** number of names */
PACK_STRUCT_FLD_8(u8_t number_of_names);
/** node name */
PACK_STRUCT_FLD_8(u8_t answer_name[NETBIOS_NAME_LEN]);
/** node flags */
PACK_STRUCT_FIELD(u16_t answer_name_flags);
/** type name */
PACK_STRUCT_FLD_8(u8_t name_type);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#ifdef NETBIOS_LWIP_NAME
#define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME
#else
@ -307,6 +344,50 @@ netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t
/* free the "reference" pbuf */
pbuf_free(q);
}
#if LWIP_NETBIOS_RESPOND_NAME_QUERY
} else if (!lwip_strnicmp(netbios_name, "*", sizeof(NETBIOS_LOCAL_NAME))) {
/* general query - ask for our IP address */
struct pbuf *q;
struct netbios_answer *resp;
q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_answer), PBUF_RAM);
if (q != NULL) {
/* buffer to which a response is compiled */
resp = (struct netbios_answer *) q->payload;
/* copy the query to the response ID */
resp->answer_hdr.trans_id = netbios_hdr->trans_id;
/* acknowledgment of termination */
resp->answer_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE | NETB_HFLAG_OPCODE_NAME_QUERY | NETB_HFLAG_AUTHORATIVE);
resp->answer_hdr.questions = PP_HTONS(0);
/* serial number of the answer */
resp->answer_hdr.answerRRs = PP_HTONS(1);
resp->answer_hdr.authorityRRs = PP_HTONS(0);
resp->answer_hdr.additionalRRs = PP_HTONS(0);
/* we will copy the length of the station name */
resp->name_size = netbios_name_hdr->nametype;
/* we will copy the queried name */
MEMCPY(resp->query_name, netbios_name_hdr->encname, (NETBIOS_NAME_LEN * 2) + 1);
/* NBSTAT */
resp->packet_type = PP_HTONS(0x21);
/* Internet name */
resp->cls = PP_HTONS(1);
resp->ttl = PP_HTONL(0);
resp->data_length = PP_HTONS(4 + NETBIOS_NAME_LEN);
resp->number_of_names = 1;
memset(resp->answer_name, 0x20, NETBIOS_NAME_LEN);
MEMCPY(resp->answer_name, NETBIOS_LOCAL_NAME, strlen(NETBIOS_LOCAL_NAME));
/* b-node, unique, active */
resp->answer_name_flags = PP_HTONS(NETB_NFLAG_NAME_IS_ACTIVE);
/* Workstation/Redirector */
resp->name_type = 0;
udp_sendto(upcb, q, addr, port);
pbuf_free(q);
}
#endif /* LWIP_NETBIOS_RESPOND_NAME_QUERY */
}
}
}
@ -340,19 +421,26 @@ netbiosns_init(void)
/**
* @ingroup netbiosns
* Set netbios name. ATTENTION: the hostname must be less than 15 characters!
* the NetBIOS name spec says the name MUST be upper case, so incoming name is forced into uppercase :-)
*/
void
netbiosns_set_name(const char *hostname)
{
size_t i;
size_t copy_len = strlen(hostname);
LWIP_ASSERT_CORE_LOCKED();
LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN);
if (copy_len >= NETBIOS_NAME_LEN) {
copy_len = NETBIOS_NAME_LEN - 1;
}
MEMCPY(netbiosns_local_name, hostname, copy_len + 1);
/* make name into upper case */
for (i = 0; i < copy_len; i++ ) {
netbiosns_local_name[i] = (char)toupper(hostname[i]);
}
netbiosns_local_name[copy_len] = '\0';
}
#endif
#endif /* NETBIOS_LWIP_NAME */
/**
* @ingroup netbiosns

View File

@ -52,6 +52,13 @@
#define NETBIOS_LWIP_NAME "NETBIOSLWIPDEV"
#endif
/** Respond to NetBIOS name queries
* Default is disabled
*/
#if !defined LWIP_NETBIOS_RESPOND_NAME_QUERY || defined __DOXYGEN__
#define LWIP_NETBIOS_RESPOND_NAME_QUERY 0
#endif
/**
* @}
*/