![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
lwip_netbiosns.c
Go to the documentation of this file.
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 Sun Jul 17 2022 08:25:24 by
![doxygen](doxygen.png)