Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of OmniWheels by
lwip_netbiosns.c
00001 /** 00002 * @file 00003 * NetBIOS name service responder 00004 */ 00005 00006 /** 00007 * @defgroup netbiosns NETBIOS responder 00008 * @ingroup apps 00009 * 00010 * This is an example implementation of a NetBIOS name server. 00011 * It responds to name queries for a configurable name. 00012 * Name resolving is not supported. 00013 * 00014 * Note that the device doesn't broadcast it's own name so can't 00015 * detect duplicate names! 00016 */ 00017 00018 /* 00019 * Redistribution and use in source and binary forms, with or without modification, 00020 * are permitted provided that the following conditions are met: 00021 * 00022 * 1. Redistributions of source code must retain the above copyright notice, 00023 * this list of conditions and the following disclaimer. 00024 * 2. Redistributions in binary form must reproduce the above copyright notice, 00025 * this list of conditions and the following disclaimer in the documentation 00026 * and/or other materials provided with the distribution. 00027 * 3. The name of the author may not be used to endorse or promote products 00028 * derived from this software without specific prior written permission. 00029 * 00030 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00031 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00032 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00033 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00034 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00035 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00036 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00037 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00038 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00039 * OF SUCH DAMAGE. 00040 * 00041 * This file is part of the lwIP TCP/IP stack. 00042 * 00043 */ 00044 00045 #include "lwip/apps/netbiosns.h" 00046 00047 #if LWIP_IPV4 && LWIP_UDP /* don't build if not configured for use in lwipopts.h */ 00048 00049 #include "lwip/def.h" 00050 #include "lwip/udp.h" 00051 #include "lwip/netif.h" 00052 00053 #include <string.h> 00054 00055 /** default port number for "NetBIOS Name service */ 00056 #define NETBIOS_PORT 137 00057 00058 /** size of a NetBIOS name */ 00059 #define NETBIOS_NAME_LEN 16 00060 00061 /** The Time-To-Live for NetBIOS name responds (in seconds) 00062 * Default is 300000 seconds (3 days, 11 hours, 20 minutes) */ 00063 #define NETBIOS_NAME_TTL 300000u 00064 00065 /** NetBIOS header flags */ 00066 #define NETB_HFLAG_RESPONSE 0x8000U 00067 #define NETB_HFLAG_OPCODE 0x7800U 00068 #define NETB_HFLAG_OPCODE_NAME_QUERY 0x0000U 00069 #define NETB_HFLAG_AUTHORATIVE 0x0400U 00070 #define NETB_HFLAG_TRUNCATED 0x0200U 00071 #define NETB_HFLAG_RECURS_DESIRED 0x0100U 00072 #define NETB_HFLAG_RECURS_AVAILABLE 0x0080U 00073 #define NETB_HFLAG_BROADCAST 0x0010U 00074 #define NETB_HFLAG_REPLYCODE 0x0008U 00075 #define NETB_HFLAG_REPLYCODE_NOERROR 0x0000U 00076 00077 /** NetBIOS name flags */ 00078 #define NETB_NFLAG_UNIQUE 0x8000U 00079 #define NETB_NFLAG_NODETYPE 0x6000U 00080 #define NETB_NFLAG_NODETYPE_HNODE 0x6000U 00081 #define NETB_NFLAG_NODETYPE_MNODE 0x4000U 00082 #define NETB_NFLAG_NODETYPE_PNODE 0x2000U 00083 #define NETB_NFLAG_NODETYPE_BNODE 0x0000U 00084 00085 /** NetBIOS message header */ 00086 #ifdef PACK_STRUCT_USE_INCLUDES 00087 # include "arch/bpstruct.h" 00088 #endif 00089 PACK_STRUCT_BEGIN 00090 struct netbios_hdr { 00091 PACK_STRUCT_FIELD(u16_t trans_id); 00092 PACK_STRUCT_FIELD(u16_t flags); 00093 PACK_STRUCT_FIELD(u16_t questions); 00094 PACK_STRUCT_FIELD(u16_t answerRRs); 00095 PACK_STRUCT_FIELD(u16_t authorityRRs); 00096 PACK_STRUCT_FIELD(u16_t additionalRRs); 00097 } PACK_STRUCT_STRUCT; 00098 PACK_STRUCT_END 00099 #ifdef PACK_STRUCT_USE_INCLUDES 00100 # include "arch/epstruct.h" 00101 #endif 00102 00103 /** NetBIOS message name part */ 00104 #ifdef PACK_STRUCT_USE_INCLUDES 00105 # include "arch/bpstruct.h" 00106 #endif 00107 PACK_STRUCT_BEGIN 00108 struct netbios_name_hdr { 00109 PACK_STRUCT_FLD_8(u8_t nametype); 00110 PACK_STRUCT_FLD_8(u8_t encname[(NETBIOS_NAME_LEN*2)+1]); 00111 PACK_STRUCT_FIELD(u16_t type); 00112 PACK_STRUCT_FIELD(u16_t cls); 00113 PACK_STRUCT_FIELD(u32_t ttl); 00114 PACK_STRUCT_FIELD(u16_t datalen); 00115 PACK_STRUCT_FIELD(u16_t flags); 00116 PACK_STRUCT_FLD_S(ip4_addr_p_t addr); 00117 } PACK_STRUCT_STRUCT; 00118 PACK_STRUCT_END 00119 #ifdef PACK_STRUCT_USE_INCLUDES 00120 # include "arch/epstruct.h" 00121 #endif 00122 00123 /** NetBIOS message */ 00124 #ifdef PACK_STRUCT_USE_INCLUDES 00125 # include "arch/bpstruct.h" 00126 #endif 00127 PACK_STRUCT_BEGIN 00128 struct netbios_resp 00129 { 00130 struct netbios_hdr resp_hdr; 00131 struct netbios_name_hdr resp_name; 00132 } PACK_STRUCT_STRUCT; 00133 PACK_STRUCT_END 00134 #ifdef PACK_STRUCT_USE_INCLUDES 00135 # include "arch/epstruct.h" 00136 #endif 00137 00138 #ifdef NETBIOS_LWIP_NAME 00139 #define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME 00140 #else 00141 static char netbiosns_local_name[NETBIOS_NAME_LEN]; 00142 #define NETBIOS_LOCAL_NAME netbiosns_local_name 00143 #endif 00144 00145 struct udp_pcb *netbiosns_pcb; 00146 00147 /** Decode a NetBIOS name (from packet to string) */ 00148 static int 00149 netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len) 00150 { 00151 char *pname; 00152 char cname; 00153 char cnbname; 00154 int idx = 0; 00155 00156 LWIP_UNUSED_ARG(name_dec_len); 00157 00158 /* Start decoding netbios name. */ 00159 pname = name_enc; 00160 for (;;) { 00161 /* Every two characters of the first level-encoded name 00162 * turn into one character in the decoded name. */ 00163 cname = *pname; 00164 if (cname == '\0') 00165 break; /* no more characters */ 00166 if (cname == '.') 00167 break; /* scope ID follows */ 00168 if (cname < 'A' || cname > 'Z') { 00169 /* Not legal. */ 00170 return -1; 00171 } 00172 cname -= 'A'; 00173 cnbname = cname << 4; 00174 pname++; 00175 00176 cname = *pname; 00177 if (cname == '\0' || cname == '.') { 00178 /* No more characters in the name - but we're in 00179 * the middle of a pair. Not legal. */ 00180 return -1; 00181 } 00182 if (cname < 'A' || cname > 'Z') { 00183 /* Not legal. */ 00184 return -1; 00185 } 00186 cname -= 'A'; 00187 cnbname |= cname; 00188 pname++; 00189 00190 /* Do we have room to store the character? */ 00191 if (idx < NETBIOS_NAME_LEN) { 00192 /* Yes - store the character. */ 00193 name_dec[idx++] = (cnbname!=' '?cnbname:'\0'); 00194 } 00195 } 00196 00197 return 0; 00198 } 00199 00200 #if 0 /* function currently unused */ 00201 /** Encode a NetBIOS name (from string to packet) - currently unused because 00202 we don't ask for names. */ 00203 static int 00204 netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len) 00205 { 00206 char *pname; 00207 char cname; 00208 unsigned char ucname; 00209 int idx = 0; 00210 00211 /* Start encoding netbios name. */ 00212 pname = name_enc; 00213 00214 for (;;) { 00215 /* Every two characters of the first level-encoded name 00216 * turn into one character in the decoded name. */ 00217 cname = *pname; 00218 if (cname == '\0') 00219 break; /* no more characters */ 00220 if (cname == '.') 00221 break; /* scope ID follows */ 00222 if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) { 00223 /* Not legal. */ 00224 return -1; 00225 } 00226 00227 /* Do we have room to store the character? */ 00228 if (idx >= name_dec_len) { 00229 return -1; 00230 } 00231 00232 /* Yes - store the character. */ 00233 ucname = cname; 00234 name_dec[idx++] = ('A'+((ucname>>4) & 0x0F)); 00235 name_dec[idx++] = ('A'+( ucname & 0x0F)); 00236 pname++; 00237 } 00238 00239 /* Fill with "space" coding */ 00240 for (;idx < name_dec_len - 1;) { 00241 name_dec[idx++] = 'C'; 00242 name_dec[idx++] = 'A'; 00243 } 00244 00245 /* Terminate string */ 00246 name_dec[idx] = '\0'; 00247 00248 return 0; 00249 } 00250 #endif /* 0 */ 00251 00252 /** NetBIOS Name service recv callback */ 00253 static void 00254 netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) 00255 { 00256 LWIP_UNUSED_ARG(arg); 00257 00258 /* if packet is valid */ 00259 if (p != NULL) { 00260 char netbios_name[NETBIOS_NAME_LEN+1]; 00261 struct netbios_hdr* netbios_hdr = (struct netbios_hdr*)p->payload; 00262 struct netbios_name_hdr* netbios_name_hdr = (struct netbios_name_hdr*)(netbios_hdr+1); 00263 00264 /* we only answer if we got a default interface */ 00265 if (netif_default != NULL) { 00266 /* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */ 00267 /* if the packet is a NetBIOS name query question */ 00268 if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) && 00269 ((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) && 00270 (netbios_hdr->questions == PP_NTOHS(1))) { 00271 /* decode the NetBIOS name */ 00272 netbiosns_name_decode((char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name)); 00273 /* if the packet is for us */ 00274 if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) { 00275 struct pbuf *q; 00276 struct netbios_resp *resp; 00277 00278 q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM); 00279 if (q != NULL) { 00280 resp = (struct netbios_resp*)q->payload; 00281 00282 /* prepare NetBIOS header response */ 00283 resp->resp_hdr.trans_id = netbios_hdr->trans_id; 00284 resp->resp_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE | 00285 NETB_HFLAG_OPCODE_NAME_QUERY | 00286 NETB_HFLAG_AUTHORATIVE | 00287 NETB_HFLAG_RECURS_DESIRED); 00288 resp->resp_hdr.questions = 0; 00289 resp->resp_hdr.answerRRs = PP_HTONS(1); 00290 resp->resp_hdr.authorityRRs = 0; 00291 resp->resp_hdr.additionalRRs = 0; 00292 00293 /* prepare NetBIOS header datas */ 00294 MEMCPY( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname)); 00295 resp->resp_name.nametype = netbios_name_hdr->nametype; 00296 resp->resp_name.type = netbios_name_hdr->type; 00297 resp->resp_name.cls = netbios_name_hdr->cls; 00298 resp->resp_name.ttl = PP_HTONL(NETBIOS_NAME_TTL); 00299 resp->resp_name.datalen = PP_HTONS(sizeof(resp->resp_name.flags)+sizeof(resp->resp_name.addr)); 00300 resp->resp_name.flags = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE); 00301 ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default)); 00302 00303 /* send the NetBIOS response */ 00304 udp_sendto(upcb, q, addr, port); 00305 00306 /* free the "reference" pbuf */ 00307 pbuf_free(q); 00308 } 00309 } 00310 } 00311 } 00312 /* free the pbuf */ 00313 pbuf_free(p); 00314 } 00315 } 00316 00317 /** 00318 * @ingroup netbiosns 00319 * Init netbios responder 00320 */ 00321 void 00322 netbiosns_init(void) 00323 { 00324 #ifdef NETBIOS_LWIP_NAME 00325 LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN); 00326 #endif 00327 00328 netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); 00329 if (netbiosns_pcb != NULL) { 00330 /* we have to be allowed to send broadcast packets! */ 00331 ip_set_option(netbiosns_pcb, SOF_BROADCAST); 00332 udp_bind(netbiosns_pcb, IP_ANY_TYPE, NETBIOS_PORT); 00333 udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb); 00334 } 00335 } 00336 00337 #ifndef NETBIOS_LWIP_NAME 00338 /** 00339 * @ingroup netbiosns 00340 * Set netbios name. ATTENTION: the hostname must be less than 15 characters! 00341 */ 00342 void 00343 netbiosns_set_name(const char* hostname) 00344 { 00345 size_t copy_len = strlen(hostname); 00346 LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN); 00347 if (copy_len >= NETBIOS_NAME_LEN) { 00348 copy_len = NETBIOS_NAME_LEN - 1; 00349 } 00350 MEMCPY(netbiosns_local_name, hostname, copy_len + 1); 00351 } 00352 #endif 00353 00354 /** 00355 * @ingroup netbiosns 00356 * Stop netbios responder 00357 */ 00358 void 00359 netbiosns_stop(void) 00360 { 00361 if (netbiosns_pcb != NULL) { 00362 udp_remove(netbiosns_pcb); 00363 netbiosns_pcb = NULL; 00364 } 00365 } 00366 00367 #endif /* LWIP_IPV4 && LWIP_UDP */
Generated on Fri Jul 22 2022 04:53:52 by
 1.7.2
 1.7.2 
    