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 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 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 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 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 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