Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_netbiosns.c Source File

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  * Modifications by Ray Abram to respond to NetBIOS name requests when Incoming name = *
00044  * - based on code from "https://github.com/esp8266/Arduino/commit/1f7989b31d26d7df9776a08f36d685eae7ac8f99"
00045  * - with permission to relicense to BSD from original author:
00046  *   http://www.xpablo.cz/?p=751#more-751
00047  */
00048 
00049 #include "lwip/apps/netbiosns.h"
00050 
00051 #if LWIP_IPV4 && LWIP_UDP  /* don't build if not configured for use in lwipopts.h */
00052 
00053 #include "lwip/def.h"
00054 #include "lwip/udp.h"
00055 #include "lwip/ip.h"
00056 #include "lwip/netif.h"
00057 #include "lwip/prot/iana.h"
00058 
00059 #include <string.h>
00060 
00061 /** size of a NetBIOS name */
00062 #define NETBIOS_NAME_LEN 16
00063 
00064 /** The Time-To-Live for NetBIOS name responds (in seconds)
00065  * Default is 300000 seconds (3 days, 11 hours, 20 minutes) */
00066 #define NETBIOS_NAME_TTL 300000u
00067 
00068 /** NetBIOS header flags */
00069 #define NETB_HFLAG_RESPONSE           0x8000U
00070 #define NETB_HFLAG_OPCODE             0x7800U
00071 #define NETB_HFLAG_OPCODE_NAME_QUERY  0x0000U
00072 #define NETB_HFLAG_AUTHORATIVE        0x0400U
00073 #define NETB_HFLAG_TRUNCATED          0x0200U
00074 #define NETB_HFLAG_RECURS_DESIRED     0x0100U
00075 #define NETB_HFLAG_RECURS_AVAILABLE   0x0080U
00076 #define NETB_HFLAG_BROADCAST          0x0010U
00077 #define NETB_HFLAG_REPLYCODE          0x0008U
00078 #define NETB_HFLAG_REPLYCODE_NOERROR  0x0000U
00079 
00080 /* NetBIOS question types */
00081 #define NETB_QTYPE_NB                 0x0020U
00082 #define NETB_QTYPE_NBSTAT             0x0021U
00083 
00084 /** NetBIOS name flags */
00085 #define NETB_NFLAG_UNIQUE             0x8000U
00086 #define NETB_NFLAG_NODETYPE           0x6000U
00087 #define NETB_NFLAG_NODETYPE_HNODE     0x6000U
00088 #define NETB_NFLAG_NODETYPE_MNODE     0x4000U
00089 #define NETB_NFLAG_NODETYPE_PNODE     0x2000U
00090 #define NETB_NFLAG_NODETYPE_BNODE     0x0000U
00091 
00092 #define NETB_NFLAG_NAME_IN_CONFLICT   0x0800U /* 1=Yes, 0=No */
00093 #define NETB_NFLAG_NAME_IS_ACTIVE     0x0400U /* 1=Yes, 0=No */
00094 #define NETB_NFLAG_NAME_IS_PERMANENT  0x0200U /* 1=Yes (Name is Permanent Node Name), 0=No */
00095 
00096 /** NetBIOS message header */
00097 #ifdef PACK_STRUCT_USE_INCLUDES
00098 #  include "arch/bpstruct.h"
00099 #endif
00100 PACK_STRUCT_BEGIN
00101 struct netbios_hdr {
00102   PACK_STRUCT_FIELD(u16_t trans_id);
00103   PACK_STRUCT_FIELD(u16_t flags);
00104   PACK_STRUCT_FIELD(u16_t questions);
00105   PACK_STRUCT_FIELD(u16_t answerRRs);
00106   PACK_STRUCT_FIELD(u16_t authorityRRs);
00107   PACK_STRUCT_FIELD(u16_t additionalRRs);
00108 } PACK_STRUCT_STRUCT;
00109 PACK_STRUCT_END
00110 #ifdef PACK_STRUCT_USE_INCLUDES
00111 #  include "arch/epstruct.h"
00112 #endif
00113 
00114 /** NetBIOS message question part */
00115 #ifdef PACK_STRUCT_USE_INCLUDES
00116 #  include "arch/bpstruct.h"
00117 #endif
00118 PACK_STRUCT_BEGIN
00119 struct netbios_question_hdr {
00120   PACK_STRUCT_FLD_8(u8_t  nametype);
00121   PACK_STRUCT_FLD_8(u8_t  encname[(NETBIOS_NAME_LEN * 2) + 1]);
00122   PACK_STRUCT_FIELD(u16_t type);
00123   PACK_STRUCT_FIELD(u16_t cls);
00124 } PACK_STRUCT_STRUCT;
00125 PACK_STRUCT_END
00126 #ifdef PACK_STRUCT_USE_INCLUDES
00127 #  include "arch/epstruct.h"
00128 #endif
00129 
00130 /** NetBIOS message name part */
00131 #ifdef PACK_STRUCT_USE_INCLUDES
00132 #  include "arch/bpstruct.h"
00133 #endif
00134 PACK_STRUCT_BEGIN
00135 struct netbios_name_hdr {
00136   PACK_STRUCT_FLD_8(u8_t  nametype);
00137   PACK_STRUCT_FLD_8(u8_t  encname[(NETBIOS_NAME_LEN * 2) + 1]);
00138   PACK_STRUCT_FIELD(u16_t type);
00139   PACK_STRUCT_FIELD(u16_t cls);
00140   PACK_STRUCT_FIELD(u32_t ttl);
00141   PACK_STRUCT_FIELD(u16_t datalen);
00142   PACK_STRUCT_FIELD(u16_t flags);
00143   PACK_STRUCT_FLD_S(ip4_addr_p_t addr);
00144 } PACK_STRUCT_STRUCT;
00145 PACK_STRUCT_END
00146 #ifdef PACK_STRUCT_USE_INCLUDES
00147 #  include "arch/epstruct.h"
00148 #endif
00149 
00150 /** NetBIOS message */
00151 #ifdef PACK_STRUCT_USE_INCLUDES
00152 #  include "arch/bpstruct.h"
00153 #endif
00154 PACK_STRUCT_BEGIN
00155 struct netbios_resp {
00156   struct netbios_hdr      resp_hdr;
00157   struct netbios_name_hdr resp_name;
00158 } PACK_STRUCT_STRUCT;
00159 PACK_STRUCT_END
00160 #ifdef PACK_STRUCT_USE_INCLUDES
00161 #  include "arch/epstruct.h"
00162 #endif
00163 
00164 /** The NBNS Structure Responds to a Name Query */
00165 #ifdef PACK_STRUCT_USE_INCLUDES
00166 #  include "arch/bpstruct.h"
00167 #endif
00168 PACK_STRUCT_BEGIN
00169 struct netbios_answer {
00170   struct netbios_hdr      answer_hdr;
00171   /** the length of the next string */
00172   PACK_STRUCT_FIELD(u8_t  name_size);
00173   /** WARNING!!! this item may be of a different length (we use this struct for transmission) */
00174   PACK_STRUCT_FLD_8(u8_t  query_name[(NETBIOS_NAME_LEN * 2) + 1]);
00175   PACK_STRUCT_FIELD(u16_t packet_type);
00176   PACK_STRUCT_FIELD(u16_t cls);
00177   PACK_STRUCT_FIELD(u32_t ttl);
00178   PACK_STRUCT_FIELD(u16_t data_length);
00179 #define OFFSETOF_STRUCT_NETBIOS_ANSWER_NUMBER_OF_NAMES 56
00180   /** number of names */
00181   PACK_STRUCT_FLD_8(u8_t  number_of_names);
00182   /** node name */
00183   PACK_STRUCT_FLD_8(u8_t  answer_name[NETBIOS_NAME_LEN]);
00184   /** node flags */
00185   PACK_STRUCT_FIELD(u16_t answer_name_flags);
00186   /** Unit ID */
00187   PACK_STRUCT_FLD_8(u8_t  unit_id[6]);
00188   /** Jumpers */
00189   PACK_STRUCT_FLD_8(u8_t  jumpers);
00190   /** Test result */
00191   PACK_STRUCT_FLD_8(u8_t  test_result);
00192   /** Version number */
00193   PACK_STRUCT_FIELD(u16_t version_number);
00194   /** Period of statistics */
00195   PACK_STRUCT_FIELD(u16_t period_of_statistics);
00196   /** Statistics */
00197   PACK_STRUCT_FIELD(u16_t number_of_crcs);
00198   /** Statistics */
00199   PACK_STRUCT_FIELD(u16_t number_of_alignment_errors);
00200   /** Statistics */
00201   PACK_STRUCT_FIELD(u16_t number_of_collisions);
00202   /** Statistics */
00203   PACK_STRUCT_FIELD(u16_t number_of_send_aborts);
00204   /** Statistics */
00205   PACK_STRUCT_FIELD(u32_t number_of_good_sends);
00206   /** Statistics */
00207   PACK_STRUCT_FIELD(u32_t number_of_good_receives);
00208   /** Statistics */
00209   PACK_STRUCT_FIELD(u16_t number_of_retransmits);
00210   /** Statistics */
00211   PACK_STRUCT_FIELD(u16_t number_of_no_resource_condition);
00212   /** Statistics */
00213   PACK_STRUCT_FIELD(u16_t number_of_free_command_blocks);
00214   /** Statistics */
00215   PACK_STRUCT_FIELD(u16_t total_number_of_command_blocks);
00216   /** Statistics */
00217   PACK_STRUCT_FIELD(u16_t max_total_number_of_command_blocks);
00218   /** Statistics */
00219   PACK_STRUCT_FIELD(u16_t number_of_pending_sessions);
00220   /** Statistics */
00221   PACK_STRUCT_FIELD(u16_t max_number_of_pending_sessions);
00222   /** Statistics */
00223   PACK_STRUCT_FIELD(u16_t max_total_sessions_possible);
00224   /** Statistics */
00225   PACK_STRUCT_FIELD(u16_t session_data_packet_size);
00226 } PACK_STRUCT_STRUCT;
00227 PACK_STRUCT_END
00228 #ifdef PACK_STRUCT_USE_INCLUDES
00229 #  include "arch/epstruct.h"
00230 #endif
00231 
00232 #ifdef NETBIOS_LWIP_NAME
00233 #define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME
00234 #else
00235 static char netbiosns_local_name[NETBIOS_NAME_LEN];
00236 #define NETBIOS_LOCAL_NAME netbiosns_local_name
00237 #endif
00238 
00239 static struct udp_pcb *netbiosns_pcb;
00240 
00241 /** Decode a NetBIOS name (from packet to string) */
00242 static int
00243 netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len)
00244 {
00245   char *pname;
00246   char  cname;
00247   char  cnbname;
00248   int   idx = 0;
00249 
00250   LWIP_UNUSED_ARG(name_dec_len);
00251 
00252   /* Start decoding netbios name. */
00253   pname  = name_enc;
00254   for (;;) {
00255     /* Every two characters of the first level-encoded name
00256      * turn into one character in the decoded name. */
00257     cname = *pname;
00258     if (cname == '\0') {
00259       break;  /* no more characters */
00260     }
00261     if (cname == '.') {
00262       break;  /* scope ID follows */
00263     }
00264     if (!lwip_isupper(cname)) {
00265       /* Not legal. */
00266       return -1;
00267     }
00268     cname -= 'A';
00269     cnbname = cname << 4;
00270     pname++;
00271 
00272     cname = *pname;
00273     if (!lwip_isupper(cname)) {
00274       /* Not legal. */
00275       return -1;
00276     }
00277     cname -= 'A';
00278     cnbname |= cname;
00279     pname++;
00280 
00281     /* Do we have room to store the character? */
00282     if (idx < NETBIOS_NAME_LEN) {
00283       /* Yes - store the character. */
00284       name_dec[idx++] = (cnbname != ' ' ? cnbname : '\0');
00285     }
00286   }
00287 
00288   return 0;
00289 }
00290 
00291 #if 0 /* function currently unused */
00292 /** Encode a NetBIOS name (from string to packet) - currently unused because
00293     we don't ask for names. */
00294 static int
00295 netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len)
00296 {
00297   char         *pname;
00298   char          cname;
00299   unsigned char ucname;
00300   int           idx = 0;
00301 
00302   /* Start encoding netbios name. */
00303   pname = name_enc;
00304 
00305   for (;;) {
00306     /* Every two characters of the first level-encoded name
00307      * turn into one character in the decoded name. */
00308     cname = *pname;
00309     if (cname == '\0') {
00310       break;  /* no more characters */
00311     }
00312     if (cname == '.') {
00313       break;  /* scope ID follows */
00314     }
00315     if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) {
00316       /* Not legal. */
00317       return -1;
00318     }
00319 
00320     /* Do we have room to store the character? */
00321     if (idx >= name_dec_len) {
00322       return -1;
00323     }
00324 
00325     /* Yes - store the character. */
00326     ucname = cname;
00327     name_dec[idx++] = ('A' + ((ucname >> 4) & 0x0F));
00328     name_dec[idx++] = ('A' + ( ucname     & 0x0F));
00329     pname++;
00330   }
00331 
00332   /* Fill with "space" coding */
00333   for (; idx < name_dec_len - 1;) {
00334     name_dec[idx++] = 'C';
00335     name_dec[idx++] = 'A';
00336   }
00337 
00338   /* Terminate string */
00339   name_dec[idx] = '\0';
00340 
00341   return 0;
00342 }
00343 #endif /* 0 */
00344 
00345 /** NetBIOS Name service recv callback */
00346 static void
00347 netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
00348 {
00349   LWIP_UNUSED_ARG(arg);
00350 
00351   /* if packet is valid */
00352   if (p != NULL) {
00353     char   netbios_name[NETBIOS_NAME_LEN + 1];
00354     struct netbios_hdr          *netbios_hdr          = (struct netbios_hdr *)p->payload;
00355     struct netbios_question_hdr *netbios_question_hdr = (struct netbios_question_hdr *)(netbios_hdr + 1);
00356 
00357     /* is the packet long enough (we need the header in one piece) */
00358     if (p->len < (sizeof(struct netbios_hdr) + sizeof(struct netbios_question_hdr))) {
00359       /* packet too short */
00360       pbuf_free(p);
00361       return;
00362     }
00363     /* we only answer if we got a default interface */
00364     if (netif_default != NULL) {
00365       /* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */
00366       /* if the packet is a NetBIOS name query question */
00367       if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) &&
00368           ((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) &&
00369           (netbios_hdr->questions == PP_NTOHS(1))) {
00370         /* decode the NetBIOS name */
00371         netbiosns_name_decode((char *)(netbios_question_hdr->encname), netbios_name, sizeof(netbios_name));
00372         /* check the request type */
00373         if (netbios_question_hdr->type == PP_HTONS(NETB_QTYPE_NB)) {
00374           /* if the packet is for us */
00375           if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) {
00376             struct pbuf *q;
00377             struct netbios_resp *resp;
00378 
00379             q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM);
00380             if (q != NULL) {
00381               resp = (struct netbios_resp *)q->payload;
00382 
00383               /* prepare NetBIOS header response */
00384               resp->resp_hdr.trans_id      = netbios_hdr->trans_id;
00385               resp->resp_hdr.flags         = PP_HTONS(NETB_HFLAG_RESPONSE |
00386                                                       NETB_HFLAG_OPCODE_NAME_QUERY |
00387                                                       NETB_HFLAG_AUTHORATIVE |
00388                                                       NETB_HFLAG_RECURS_DESIRED);
00389               resp->resp_hdr.questions     = 0;
00390               resp->resp_hdr.answerRRs     = PP_HTONS(1);
00391               resp->resp_hdr.authorityRRs  = 0;
00392               resp->resp_hdr.additionalRRs = 0;
00393 
00394               /* prepare NetBIOS header datas */
00395               MEMCPY( resp->resp_name.encname, netbios_question_hdr->encname, sizeof(netbios_question_hdr->encname));
00396               resp->resp_name.nametype     = netbios_question_hdr->nametype;
00397               resp->resp_name.type         = netbios_question_hdr->type;
00398               resp->resp_name.cls          = netbios_question_hdr->cls;
00399               resp->resp_name.ttl          = PP_HTONL(NETBIOS_NAME_TTL);
00400               resp->resp_name.datalen      = PP_HTONS(sizeof(resp->resp_name.flags) + sizeof(resp->resp_name.addr));
00401               resp->resp_name.flags        = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE);
00402               ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default));
00403 
00404               /* send the NetBIOS response */
00405               udp_sendto(upcb, q, addr, port);
00406 
00407               /* free the "reference" pbuf */
00408               pbuf_free(q);
00409             }
00410           }
00411 #if LWIP_NETBIOS_RESPOND_NAME_QUERY
00412         } else if (netbios_question_hdr->type == PP_HTONS(NETB_QTYPE_NBSTAT)) {
00413           /* if the packet is for us or general query */
00414           if (!lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) ||
00415               !lwip_strnicmp(netbios_name, "*", sizeof(NETBIOS_LOCAL_NAME))) {
00416             /* general query - ask for our IP address */
00417             struct pbuf *q;
00418             struct netbios_answer *resp;
00419 
00420             q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_answer), PBUF_RAM);
00421             if (q != NULL) {
00422               /* buffer to which a response is compiled */
00423               resp = (struct netbios_answer *) q->payload;
00424 
00425               /* Init response to zero, especially the statistics fields */
00426               memset(resp, 0, sizeof(*resp));
00427 
00428               /* copy the query to the response ID */
00429               resp->answer_hdr.trans_id        = netbios_hdr->trans_id;
00430               /* acknowledgment of termination */
00431               resp->answer_hdr.flags           = PP_HTONS(NETB_HFLAG_RESPONSE | NETB_HFLAG_OPCODE_NAME_QUERY | NETB_HFLAG_AUTHORATIVE);
00432               /* resp->answer_hdr.questions       = PP_HTONS(0); done by memset() */
00433               /* serial number of the answer */
00434               resp->answer_hdr.answerRRs       = PP_HTONS(1);
00435               /* resp->answer_hdr.authorityRRs    = PP_HTONS(0); done by memset() */
00436               /* resp->answer_hdr.additionalRRs   = PP_HTONS(0); done by memset() */
00437               /* we will copy the length of the station name */
00438               resp->name_size                  = netbios_question_hdr->nametype;
00439               /* we will copy the queried name */
00440               MEMCPY(resp->query_name, netbios_question_hdr->encname, (NETBIOS_NAME_LEN * 2) + 1);
00441               /* NBSTAT */
00442               resp->packet_type                = PP_HTONS(0x21);
00443               /* Internet name */
00444               resp->cls                        = PP_HTONS(1);
00445               /* resp->ttl                        = PP_HTONL(0); done by memset() */
00446               resp->data_length                = PP_HTONS(sizeof(struct netbios_answer) - offsetof(struct netbios_answer, number_of_names));
00447               resp->number_of_names            = 1;
00448 
00449               /* make windows see us as workstation, not as a server */
00450               memset(resp->answer_name, 0x20, NETBIOS_NAME_LEN - 1);
00451               /* strlen is checked to be < NETBIOS_NAME_LEN during initialization */
00452               MEMCPY(resp->answer_name, NETBIOS_LOCAL_NAME, strlen(NETBIOS_LOCAL_NAME));
00453 
00454               /* b-node, unique, active */
00455               resp->answer_name_flags          = PP_HTONS(NETB_NFLAG_NAME_IS_ACTIVE);
00456 
00457               /* Set responder netif MAC address */
00458               SMEMCPY(resp->unit_id, ip_current_input_netif()->hwaddr, sizeof(resp->unit_id));
00459 
00460               udp_sendto(upcb, q, addr, port);
00461               pbuf_free(q);
00462             }
00463           }
00464 #endif /* LWIP_NETBIOS_RESPOND_NAME_QUERY */
00465         }
00466       }
00467     }
00468     /* free the pbuf */
00469     pbuf_free(p);
00470   }
00471 }
00472 
00473 /**
00474  * @ingroup netbiosns
00475  * Init netbios responder
00476  */
00477 void
00478 netbiosns_init(void)
00479 {
00480   /* LWIP_ASSERT_CORE_LOCKED(); is checked by udp_new() */
00481 #ifdef NETBIOS_LWIP_NAME
00482   LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN);
00483 #endif
00484 
00485   netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
00486   if (netbiosns_pcb != NULL) {
00487     /* we have to be allowed to send broadcast packets! */
00488     ip_set_option(netbiosns_pcb, SOF_BROADCAST);
00489     udp_bind(netbiosns_pcb, IP_ANY_TYPE, LWIP_IANA_PORT_NETBIOS);
00490     udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb);
00491   }
00492 }
00493 
00494 #ifndef NETBIOS_LWIP_NAME
00495 /**
00496  * @ingroup netbiosns
00497  * Set netbios name. ATTENTION: the hostname must be less than 15 characters!
00498  *                              the NetBIOS name spec says the name MUST be upper case, so incoming name is forced into uppercase :-)
00499  */
00500 void
00501 netbiosns_set_name(const char *hostname)
00502 {
00503   size_t i;
00504   size_t copy_len = strlen(hostname);
00505   LWIP_ASSERT_CORE_LOCKED();
00506   LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN);
00507   if (copy_len >= NETBIOS_NAME_LEN) {
00508     copy_len = NETBIOS_NAME_LEN - 1;
00509   }
00510 
00511   /* make name into upper case */
00512   for (i = 0; i < copy_len; i++ ) {
00513     netbiosns_local_name[i] = (char)lwip_toupper(hostname[i]);
00514   }
00515   netbiosns_local_name[copy_len] = '\0';
00516 }
00517 #endif /* NETBIOS_LWIP_NAME */
00518 
00519 /**
00520  * @ingroup netbiosns
00521  * Stop netbios responder
00522  */
00523 void
00524 netbiosns_stop(void)
00525 {
00526   LWIP_ASSERT_CORE_LOCKED();
00527   if (netbiosns_pcb != NULL) {
00528     udp_remove(netbiosns_pcb);
00529     netbiosns_pcb = NULL;
00530   }
00531 }
00532 
00533 #endif /* LWIP_IPV4 && LWIP_UDP */