xref: /minix3/minix/lib/liblwip/dist/src/apps/netbiosns/netbiosns.c (revision 5d5fbe79c1b60734f34c69330aec5496644e8651)
1*5d5fbe79SDavid van Moolenbroek /**
2*5d5fbe79SDavid van Moolenbroek  * @file
3*5d5fbe79SDavid van Moolenbroek  * NetBIOS name service responder
4*5d5fbe79SDavid van Moolenbroek  */
5*5d5fbe79SDavid van Moolenbroek 
6*5d5fbe79SDavid van Moolenbroek /**
7*5d5fbe79SDavid van Moolenbroek  * @defgroup netbiosns NETBIOS responder
8*5d5fbe79SDavid van Moolenbroek  * @ingroup apps
9*5d5fbe79SDavid van Moolenbroek  *
10*5d5fbe79SDavid van Moolenbroek  * This is an example implementation of a NetBIOS name server.
11*5d5fbe79SDavid van Moolenbroek  * It responds to name queries for a configurable name.
12*5d5fbe79SDavid van Moolenbroek  * Name resolving is not supported.
13*5d5fbe79SDavid van Moolenbroek  *
14*5d5fbe79SDavid van Moolenbroek  * Note that the device doesn't broadcast it's own name so can't
15*5d5fbe79SDavid van Moolenbroek  * detect duplicate names!
16*5d5fbe79SDavid van Moolenbroek  */
17*5d5fbe79SDavid van Moolenbroek 
18*5d5fbe79SDavid van Moolenbroek /*
19*5d5fbe79SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without modification,
20*5d5fbe79SDavid van Moolenbroek  * are permitted provided that the following conditions are met:
21*5d5fbe79SDavid van Moolenbroek  *
22*5d5fbe79SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright notice,
23*5d5fbe79SDavid van Moolenbroek  *    this list of conditions and the following disclaimer.
24*5d5fbe79SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright notice,
25*5d5fbe79SDavid van Moolenbroek  *    this list of conditions and the following disclaimer in the documentation
26*5d5fbe79SDavid van Moolenbroek  *    and/or other materials provided with the distribution.
27*5d5fbe79SDavid van Moolenbroek  * 3. The name of the author may not be used to endorse or promote products
28*5d5fbe79SDavid van Moolenbroek  *    derived from this software without specific prior written permission.
29*5d5fbe79SDavid van Moolenbroek  *
30*5d5fbe79SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
31*5d5fbe79SDavid van Moolenbroek  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
32*5d5fbe79SDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
33*5d5fbe79SDavid van Moolenbroek  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
34*5d5fbe79SDavid van Moolenbroek  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
35*5d5fbe79SDavid van Moolenbroek  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36*5d5fbe79SDavid van Moolenbroek  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37*5d5fbe79SDavid van Moolenbroek  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
38*5d5fbe79SDavid van Moolenbroek  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
39*5d5fbe79SDavid van Moolenbroek  * OF SUCH DAMAGE.
40*5d5fbe79SDavid van Moolenbroek  *
41*5d5fbe79SDavid van Moolenbroek  * This file is part of the lwIP TCP/IP stack.
42*5d5fbe79SDavid van Moolenbroek  *
43*5d5fbe79SDavid van Moolenbroek  */
44*5d5fbe79SDavid van Moolenbroek 
45*5d5fbe79SDavid van Moolenbroek #include "lwip/apps/netbiosns.h"
46*5d5fbe79SDavid van Moolenbroek 
47*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV4 && LWIP_UDP  /* don't build if not configured for use in lwipopts.h */
48*5d5fbe79SDavid van Moolenbroek 
49*5d5fbe79SDavid van Moolenbroek #include "lwip/def.h"
50*5d5fbe79SDavid van Moolenbroek #include "lwip/udp.h"
51*5d5fbe79SDavid van Moolenbroek #include "lwip/netif.h"
52*5d5fbe79SDavid van Moolenbroek 
53*5d5fbe79SDavid van Moolenbroek #include <string.h>
54*5d5fbe79SDavid van Moolenbroek 
55*5d5fbe79SDavid van Moolenbroek /** default port number for "NetBIOS Name service */
56*5d5fbe79SDavid van Moolenbroek #define NETBIOS_PORT     137
57*5d5fbe79SDavid van Moolenbroek 
58*5d5fbe79SDavid van Moolenbroek /** size of a NetBIOS name */
59*5d5fbe79SDavid van Moolenbroek #define NETBIOS_NAME_LEN 16
60*5d5fbe79SDavid van Moolenbroek 
61*5d5fbe79SDavid van Moolenbroek /** The Time-To-Live for NetBIOS name responds (in seconds)
62*5d5fbe79SDavid van Moolenbroek  * Default is 300000 seconds (3 days, 11 hours, 20 minutes) */
63*5d5fbe79SDavid van Moolenbroek #define NETBIOS_NAME_TTL 300000u
64*5d5fbe79SDavid van Moolenbroek 
65*5d5fbe79SDavid van Moolenbroek /** NetBIOS header flags */
66*5d5fbe79SDavid van Moolenbroek #define NETB_HFLAG_RESPONSE           0x8000U
67*5d5fbe79SDavid van Moolenbroek #define NETB_HFLAG_OPCODE             0x7800U
68*5d5fbe79SDavid van Moolenbroek #define NETB_HFLAG_OPCODE_NAME_QUERY  0x0000U
69*5d5fbe79SDavid van Moolenbroek #define NETB_HFLAG_AUTHORATIVE        0x0400U
70*5d5fbe79SDavid van Moolenbroek #define NETB_HFLAG_TRUNCATED          0x0200U
71*5d5fbe79SDavid van Moolenbroek #define NETB_HFLAG_RECURS_DESIRED     0x0100U
72*5d5fbe79SDavid van Moolenbroek #define NETB_HFLAG_RECURS_AVAILABLE   0x0080U
73*5d5fbe79SDavid van Moolenbroek #define NETB_HFLAG_BROADCAST          0x0010U
74*5d5fbe79SDavid van Moolenbroek #define NETB_HFLAG_REPLYCODE          0x0008U
75*5d5fbe79SDavid van Moolenbroek #define NETB_HFLAG_REPLYCODE_NOERROR  0x0000U
76*5d5fbe79SDavid van Moolenbroek 
77*5d5fbe79SDavid van Moolenbroek /** NetBIOS name flags */
78*5d5fbe79SDavid van Moolenbroek #define NETB_NFLAG_UNIQUE             0x8000U
79*5d5fbe79SDavid van Moolenbroek #define NETB_NFLAG_NODETYPE           0x6000U
80*5d5fbe79SDavid van Moolenbroek #define NETB_NFLAG_NODETYPE_HNODE     0x6000U
81*5d5fbe79SDavid van Moolenbroek #define NETB_NFLAG_NODETYPE_MNODE     0x4000U
82*5d5fbe79SDavid van Moolenbroek #define NETB_NFLAG_NODETYPE_PNODE     0x2000U
83*5d5fbe79SDavid van Moolenbroek #define NETB_NFLAG_NODETYPE_BNODE     0x0000U
84*5d5fbe79SDavid van Moolenbroek 
85*5d5fbe79SDavid van Moolenbroek /** NetBIOS message header */
86*5d5fbe79SDavid van Moolenbroek #ifdef PACK_STRUCT_USE_INCLUDES
87*5d5fbe79SDavid van Moolenbroek #  include "arch/bpstruct.h"
88*5d5fbe79SDavid van Moolenbroek #endif
89*5d5fbe79SDavid van Moolenbroek PACK_STRUCT_BEGIN
90*5d5fbe79SDavid van Moolenbroek struct netbios_hdr {
91*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FIELD(u16_t trans_id);
92*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FIELD(u16_t flags);
93*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FIELD(u16_t questions);
94*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FIELD(u16_t answerRRs);
95*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FIELD(u16_t authorityRRs);
96*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FIELD(u16_t additionalRRs);
97*5d5fbe79SDavid van Moolenbroek } PACK_STRUCT_STRUCT;
98*5d5fbe79SDavid van Moolenbroek PACK_STRUCT_END
99*5d5fbe79SDavid van Moolenbroek #ifdef PACK_STRUCT_USE_INCLUDES
100*5d5fbe79SDavid van Moolenbroek #  include "arch/epstruct.h"
101*5d5fbe79SDavid van Moolenbroek #endif
102*5d5fbe79SDavid van Moolenbroek 
103*5d5fbe79SDavid van Moolenbroek /** NetBIOS message name part */
104*5d5fbe79SDavid van Moolenbroek #ifdef PACK_STRUCT_USE_INCLUDES
105*5d5fbe79SDavid van Moolenbroek #  include "arch/bpstruct.h"
106*5d5fbe79SDavid van Moolenbroek #endif
107*5d5fbe79SDavid van Moolenbroek PACK_STRUCT_BEGIN
108*5d5fbe79SDavid van Moolenbroek struct netbios_name_hdr {
109*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FLD_8(u8_t  nametype);
110*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FLD_8(u8_t  encname[(NETBIOS_NAME_LEN*2)+1]);
111*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FIELD(u16_t type);
112*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FIELD(u16_t cls);
113*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FIELD(u32_t ttl);
114*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FIELD(u16_t datalen);
115*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FIELD(u16_t flags);
116*5d5fbe79SDavid van Moolenbroek   PACK_STRUCT_FLD_S(ip4_addr_p_t addr);
117*5d5fbe79SDavid van Moolenbroek } PACK_STRUCT_STRUCT;
118*5d5fbe79SDavid van Moolenbroek PACK_STRUCT_END
119*5d5fbe79SDavid van Moolenbroek #ifdef PACK_STRUCT_USE_INCLUDES
120*5d5fbe79SDavid van Moolenbroek #  include "arch/epstruct.h"
121*5d5fbe79SDavid van Moolenbroek #endif
122*5d5fbe79SDavid van Moolenbroek 
123*5d5fbe79SDavid van Moolenbroek /** NetBIOS message */
124*5d5fbe79SDavid van Moolenbroek #ifdef PACK_STRUCT_USE_INCLUDES
125*5d5fbe79SDavid van Moolenbroek #  include "arch/bpstruct.h"
126*5d5fbe79SDavid van Moolenbroek #endif
127*5d5fbe79SDavid van Moolenbroek PACK_STRUCT_BEGIN
128*5d5fbe79SDavid van Moolenbroek struct netbios_resp
129*5d5fbe79SDavid van Moolenbroek {
130*5d5fbe79SDavid van Moolenbroek   struct netbios_hdr      resp_hdr;
131*5d5fbe79SDavid van Moolenbroek   struct netbios_name_hdr resp_name;
132*5d5fbe79SDavid van Moolenbroek } PACK_STRUCT_STRUCT;
133*5d5fbe79SDavid van Moolenbroek PACK_STRUCT_END
134*5d5fbe79SDavid van Moolenbroek #ifdef PACK_STRUCT_USE_INCLUDES
135*5d5fbe79SDavid van Moolenbroek #  include "arch/epstruct.h"
136*5d5fbe79SDavid van Moolenbroek #endif
137*5d5fbe79SDavid van Moolenbroek 
138*5d5fbe79SDavid van Moolenbroek #ifdef NETBIOS_LWIP_NAME
139*5d5fbe79SDavid van Moolenbroek #define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME
140*5d5fbe79SDavid van Moolenbroek #else
141*5d5fbe79SDavid van Moolenbroek static char netbiosns_local_name[NETBIOS_NAME_LEN];
142*5d5fbe79SDavid van Moolenbroek #define NETBIOS_LOCAL_NAME netbiosns_local_name
143*5d5fbe79SDavid van Moolenbroek #endif
144*5d5fbe79SDavid van Moolenbroek 
145*5d5fbe79SDavid van Moolenbroek struct udp_pcb *netbiosns_pcb;
146*5d5fbe79SDavid van Moolenbroek 
147*5d5fbe79SDavid van Moolenbroek /** Decode a NetBIOS name (from packet to string) */
148*5d5fbe79SDavid van Moolenbroek static int
netbiosns_name_decode(char * name_enc,char * name_dec,int name_dec_len)149*5d5fbe79SDavid van Moolenbroek netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len)
150*5d5fbe79SDavid van Moolenbroek {
151*5d5fbe79SDavid van Moolenbroek   char *pname;
152*5d5fbe79SDavid van Moolenbroek   char  cname;
153*5d5fbe79SDavid van Moolenbroek   char  cnbname;
154*5d5fbe79SDavid van Moolenbroek   int   idx = 0;
155*5d5fbe79SDavid van Moolenbroek 
156*5d5fbe79SDavid van Moolenbroek   LWIP_UNUSED_ARG(name_dec_len);
157*5d5fbe79SDavid van Moolenbroek 
158*5d5fbe79SDavid van Moolenbroek   /* Start decoding netbios name. */
159*5d5fbe79SDavid van Moolenbroek   pname  = name_enc;
160*5d5fbe79SDavid van Moolenbroek   for (;;) {
161*5d5fbe79SDavid van Moolenbroek     /* Every two characters of the first level-encoded name
162*5d5fbe79SDavid van Moolenbroek      * turn into one character in the decoded name. */
163*5d5fbe79SDavid van Moolenbroek     cname = *pname;
164*5d5fbe79SDavid van Moolenbroek     if (cname == '\0')
165*5d5fbe79SDavid van Moolenbroek       break;    /* no more characters */
166*5d5fbe79SDavid van Moolenbroek     if (cname == '.')
167*5d5fbe79SDavid van Moolenbroek       break;    /* scope ID follows */
168*5d5fbe79SDavid van Moolenbroek     if (cname < 'A' || cname > 'Z') {
169*5d5fbe79SDavid van Moolenbroek       /* Not legal. */
170*5d5fbe79SDavid van Moolenbroek       return -1;
171*5d5fbe79SDavid van Moolenbroek     }
172*5d5fbe79SDavid van Moolenbroek     cname -= 'A';
173*5d5fbe79SDavid van Moolenbroek     cnbname = cname << 4;
174*5d5fbe79SDavid van Moolenbroek     pname++;
175*5d5fbe79SDavid van Moolenbroek 
176*5d5fbe79SDavid van Moolenbroek     cname = *pname;
177*5d5fbe79SDavid van Moolenbroek     if (cname == '\0' || cname == '.') {
178*5d5fbe79SDavid van Moolenbroek       /* No more characters in the name - but we're in
179*5d5fbe79SDavid van Moolenbroek        * the middle of a pair.  Not legal. */
180*5d5fbe79SDavid van Moolenbroek       return -1;
181*5d5fbe79SDavid van Moolenbroek     }
182*5d5fbe79SDavid van Moolenbroek     if (cname < 'A' || cname > 'Z') {
183*5d5fbe79SDavid van Moolenbroek       /* Not legal. */
184*5d5fbe79SDavid van Moolenbroek       return -1;
185*5d5fbe79SDavid van Moolenbroek     }
186*5d5fbe79SDavid van Moolenbroek     cname -= 'A';
187*5d5fbe79SDavid van Moolenbroek     cnbname |= cname;
188*5d5fbe79SDavid van Moolenbroek     pname++;
189*5d5fbe79SDavid van Moolenbroek 
190*5d5fbe79SDavid van Moolenbroek     /* Do we have room to store the character? */
191*5d5fbe79SDavid van Moolenbroek     if (idx < NETBIOS_NAME_LEN) {
192*5d5fbe79SDavid van Moolenbroek       /* Yes - store the character. */
193*5d5fbe79SDavid van Moolenbroek       name_dec[idx++] = (cnbname!=' '?cnbname:'\0');
194*5d5fbe79SDavid van Moolenbroek     }
195*5d5fbe79SDavid van Moolenbroek   }
196*5d5fbe79SDavid van Moolenbroek 
197*5d5fbe79SDavid van Moolenbroek   return 0;
198*5d5fbe79SDavid van Moolenbroek }
199*5d5fbe79SDavid van Moolenbroek 
200*5d5fbe79SDavid van Moolenbroek #if 0 /* function currently unused */
201*5d5fbe79SDavid van Moolenbroek /** Encode a NetBIOS name (from string to packet) - currently unused because
202*5d5fbe79SDavid van Moolenbroek     we don't ask for names. */
203*5d5fbe79SDavid van Moolenbroek static int
204*5d5fbe79SDavid van Moolenbroek netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len)
205*5d5fbe79SDavid van Moolenbroek {
206*5d5fbe79SDavid van Moolenbroek   char         *pname;
207*5d5fbe79SDavid van Moolenbroek   char          cname;
208*5d5fbe79SDavid van Moolenbroek   unsigned char ucname;
209*5d5fbe79SDavid van Moolenbroek   int           idx = 0;
210*5d5fbe79SDavid van Moolenbroek 
211*5d5fbe79SDavid van Moolenbroek   /* Start encoding netbios name. */
212*5d5fbe79SDavid van Moolenbroek   pname = name_enc;
213*5d5fbe79SDavid van Moolenbroek 
214*5d5fbe79SDavid van Moolenbroek   for (;;) {
215*5d5fbe79SDavid van Moolenbroek     /* Every two characters of the first level-encoded name
216*5d5fbe79SDavid van Moolenbroek      * turn into one character in the decoded name. */
217*5d5fbe79SDavid van Moolenbroek     cname = *pname;
218*5d5fbe79SDavid van Moolenbroek     if (cname == '\0')
219*5d5fbe79SDavid van Moolenbroek       break;    /* no more characters */
220*5d5fbe79SDavid van Moolenbroek     if (cname == '.')
221*5d5fbe79SDavid van Moolenbroek       break;    /* scope ID follows */
222*5d5fbe79SDavid van Moolenbroek     if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) {
223*5d5fbe79SDavid van Moolenbroek       /* Not legal. */
224*5d5fbe79SDavid van Moolenbroek       return -1;
225*5d5fbe79SDavid van Moolenbroek     }
226*5d5fbe79SDavid van Moolenbroek 
227*5d5fbe79SDavid van Moolenbroek     /* Do we have room to store the character? */
228*5d5fbe79SDavid van Moolenbroek     if (idx >= name_dec_len) {
229*5d5fbe79SDavid van Moolenbroek       return -1;
230*5d5fbe79SDavid van Moolenbroek     }
231*5d5fbe79SDavid van Moolenbroek 
232*5d5fbe79SDavid van Moolenbroek     /* Yes - store the character. */
233*5d5fbe79SDavid van Moolenbroek     ucname = cname;
234*5d5fbe79SDavid van Moolenbroek     name_dec[idx++] = ('A'+((ucname>>4) & 0x0F));
235*5d5fbe79SDavid van Moolenbroek     name_dec[idx++] = ('A'+( ucname     & 0x0F));
236*5d5fbe79SDavid van Moolenbroek     pname++;
237*5d5fbe79SDavid van Moolenbroek   }
238*5d5fbe79SDavid van Moolenbroek 
239*5d5fbe79SDavid van Moolenbroek   /* Fill with "space" coding */
240*5d5fbe79SDavid van Moolenbroek   for (;idx < name_dec_len - 1;) {
241*5d5fbe79SDavid van Moolenbroek     name_dec[idx++] = 'C';
242*5d5fbe79SDavid van Moolenbroek     name_dec[idx++] = 'A';
243*5d5fbe79SDavid van Moolenbroek   }
244*5d5fbe79SDavid van Moolenbroek 
245*5d5fbe79SDavid van Moolenbroek   /* Terminate string */
246*5d5fbe79SDavid van Moolenbroek   name_dec[idx] = '\0';
247*5d5fbe79SDavid van Moolenbroek 
248*5d5fbe79SDavid van Moolenbroek   return 0;
249*5d5fbe79SDavid van Moolenbroek }
250*5d5fbe79SDavid van Moolenbroek #endif /* 0 */
251*5d5fbe79SDavid van Moolenbroek 
252*5d5fbe79SDavid van Moolenbroek /** NetBIOS Name service recv callback */
253*5d5fbe79SDavid van Moolenbroek static void
netbiosns_recv(void * arg,struct udp_pcb * upcb,struct pbuf * p,const ip_addr_t * addr,u16_t port)254*5d5fbe79SDavid van Moolenbroek netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
255*5d5fbe79SDavid van Moolenbroek {
256*5d5fbe79SDavid van Moolenbroek   LWIP_UNUSED_ARG(arg);
257*5d5fbe79SDavid van Moolenbroek 
258*5d5fbe79SDavid van Moolenbroek   /* if packet is valid */
259*5d5fbe79SDavid van Moolenbroek   if (p != NULL) {
260*5d5fbe79SDavid van Moolenbroek     char   netbios_name[NETBIOS_NAME_LEN+1];
261*5d5fbe79SDavid van Moolenbroek     struct netbios_hdr*      netbios_hdr      = (struct netbios_hdr*)p->payload;
262*5d5fbe79SDavid van Moolenbroek     struct netbios_name_hdr* netbios_name_hdr = (struct netbios_name_hdr*)(netbios_hdr+1);
263*5d5fbe79SDavid van Moolenbroek 
264*5d5fbe79SDavid van Moolenbroek     /* we only answer if we got a default interface */
265*5d5fbe79SDavid van Moolenbroek     if (netif_default != NULL) {
266*5d5fbe79SDavid van Moolenbroek       /* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */
267*5d5fbe79SDavid van Moolenbroek       /* if the packet is a NetBIOS name query question */
268*5d5fbe79SDavid van Moolenbroek       if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) &&
269*5d5fbe79SDavid van Moolenbroek           ((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) &&
270*5d5fbe79SDavid van Moolenbroek            (netbios_hdr->questions == PP_NTOHS(1))) {
271*5d5fbe79SDavid van Moolenbroek         /* decode the NetBIOS name */
272*5d5fbe79SDavid van Moolenbroek         netbiosns_name_decode((char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name));
273*5d5fbe79SDavid van Moolenbroek         /* if the packet is for us */
274*5d5fbe79SDavid van Moolenbroek         if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) {
275*5d5fbe79SDavid van Moolenbroek           struct pbuf *q;
276*5d5fbe79SDavid van Moolenbroek           struct netbios_resp *resp;
277*5d5fbe79SDavid van Moolenbroek 
278*5d5fbe79SDavid van Moolenbroek           q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM);
279*5d5fbe79SDavid van Moolenbroek           if (q != NULL) {
280*5d5fbe79SDavid van Moolenbroek             resp = (struct netbios_resp*)q->payload;
281*5d5fbe79SDavid van Moolenbroek 
282*5d5fbe79SDavid van Moolenbroek             /* prepare NetBIOS header response */
283*5d5fbe79SDavid van Moolenbroek             resp->resp_hdr.trans_id      = netbios_hdr->trans_id;
284*5d5fbe79SDavid van Moolenbroek             resp->resp_hdr.flags         = PP_HTONS(NETB_HFLAG_RESPONSE |
285*5d5fbe79SDavid van Moolenbroek                                                  NETB_HFLAG_OPCODE_NAME_QUERY |
286*5d5fbe79SDavid van Moolenbroek                                                  NETB_HFLAG_AUTHORATIVE |
287*5d5fbe79SDavid van Moolenbroek                                                  NETB_HFLAG_RECURS_DESIRED);
288*5d5fbe79SDavid van Moolenbroek             resp->resp_hdr.questions     = 0;
289*5d5fbe79SDavid van Moolenbroek             resp->resp_hdr.answerRRs     = PP_HTONS(1);
290*5d5fbe79SDavid van Moolenbroek             resp->resp_hdr.authorityRRs  = 0;
291*5d5fbe79SDavid van Moolenbroek             resp->resp_hdr.additionalRRs = 0;
292*5d5fbe79SDavid van Moolenbroek 
293*5d5fbe79SDavid van Moolenbroek             /* prepare NetBIOS header datas */
294*5d5fbe79SDavid van Moolenbroek             MEMCPY( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname));
295*5d5fbe79SDavid van Moolenbroek             resp->resp_name.nametype     = netbios_name_hdr->nametype;
296*5d5fbe79SDavid van Moolenbroek             resp->resp_name.type         = netbios_name_hdr->type;
297*5d5fbe79SDavid van Moolenbroek             resp->resp_name.cls          = netbios_name_hdr->cls;
298*5d5fbe79SDavid van Moolenbroek             resp->resp_name.ttl          = PP_HTONL(NETBIOS_NAME_TTL);
299*5d5fbe79SDavid van Moolenbroek             resp->resp_name.datalen      = PP_HTONS(sizeof(resp->resp_name.flags)+sizeof(resp->resp_name.addr));
300*5d5fbe79SDavid van Moolenbroek             resp->resp_name.flags        = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE);
301*5d5fbe79SDavid van Moolenbroek             ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default));
302*5d5fbe79SDavid van Moolenbroek 
303*5d5fbe79SDavid van Moolenbroek             /* send the NetBIOS response */
304*5d5fbe79SDavid van Moolenbroek             udp_sendto(upcb, q, addr, port);
305*5d5fbe79SDavid van Moolenbroek 
306*5d5fbe79SDavid van Moolenbroek             /* free the "reference" pbuf */
307*5d5fbe79SDavid van Moolenbroek             pbuf_free(q);
308*5d5fbe79SDavid van Moolenbroek           }
309*5d5fbe79SDavid van Moolenbroek         }
310*5d5fbe79SDavid van Moolenbroek       }
311*5d5fbe79SDavid van Moolenbroek     }
312*5d5fbe79SDavid van Moolenbroek     /* free the pbuf */
313*5d5fbe79SDavid van Moolenbroek     pbuf_free(p);
314*5d5fbe79SDavid van Moolenbroek   }
315*5d5fbe79SDavid van Moolenbroek }
316*5d5fbe79SDavid van Moolenbroek 
317*5d5fbe79SDavid van Moolenbroek /**
318*5d5fbe79SDavid van Moolenbroek  * @ingroup netbiosns
319*5d5fbe79SDavid van Moolenbroek  * Init netbios responder
320*5d5fbe79SDavid van Moolenbroek  */
321*5d5fbe79SDavid van Moolenbroek void
netbiosns_init(void)322*5d5fbe79SDavid van Moolenbroek netbiosns_init(void)
323*5d5fbe79SDavid van Moolenbroek {
324*5d5fbe79SDavid van Moolenbroek #ifdef NETBIOS_LWIP_NAME
325*5d5fbe79SDavid van Moolenbroek   LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN);
326*5d5fbe79SDavid van Moolenbroek #endif
327*5d5fbe79SDavid van Moolenbroek 
328*5d5fbe79SDavid van Moolenbroek   netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
329*5d5fbe79SDavid van Moolenbroek   if (netbiosns_pcb != NULL) {
330*5d5fbe79SDavid van Moolenbroek     /* we have to be allowed to send broadcast packets! */
331*5d5fbe79SDavid van Moolenbroek     ip_set_option(netbiosns_pcb, SOF_BROADCAST);
332*5d5fbe79SDavid van Moolenbroek     udp_bind(netbiosns_pcb, IP_ANY_TYPE, NETBIOS_PORT);
333*5d5fbe79SDavid van Moolenbroek     udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb);
334*5d5fbe79SDavid van Moolenbroek   }
335*5d5fbe79SDavid van Moolenbroek }
336*5d5fbe79SDavid van Moolenbroek 
337*5d5fbe79SDavid van Moolenbroek #ifndef NETBIOS_LWIP_NAME
338*5d5fbe79SDavid van Moolenbroek /**
339*5d5fbe79SDavid van Moolenbroek  * @ingroup netbiosns
340*5d5fbe79SDavid van Moolenbroek  * Set netbios name. ATTENTION: the hostname must be less than 15 characters!
341*5d5fbe79SDavid van Moolenbroek  */
342*5d5fbe79SDavid van Moolenbroek void
netbiosns_set_name(const char * hostname)343*5d5fbe79SDavid van Moolenbroek netbiosns_set_name(const char* hostname)
344*5d5fbe79SDavid van Moolenbroek {
345*5d5fbe79SDavid van Moolenbroek   size_t copy_len = strlen(hostname);
346*5d5fbe79SDavid van Moolenbroek   LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN);
347*5d5fbe79SDavid van Moolenbroek   if (copy_len >= NETBIOS_NAME_LEN) {
348*5d5fbe79SDavid van Moolenbroek     copy_len = NETBIOS_NAME_LEN - 1;
349*5d5fbe79SDavid van Moolenbroek   }
350*5d5fbe79SDavid van Moolenbroek   MEMCPY(netbiosns_local_name, hostname, copy_len + 1);
351*5d5fbe79SDavid van Moolenbroek }
352*5d5fbe79SDavid van Moolenbroek #endif
353*5d5fbe79SDavid van Moolenbroek 
354*5d5fbe79SDavid van Moolenbroek /**
355*5d5fbe79SDavid van Moolenbroek  * @ingroup netbiosns
356*5d5fbe79SDavid van Moolenbroek  * Stop netbios responder
357*5d5fbe79SDavid van Moolenbroek  */
358*5d5fbe79SDavid van Moolenbroek void
netbiosns_stop(void)359*5d5fbe79SDavid van Moolenbroek netbiosns_stop(void)
360*5d5fbe79SDavid van Moolenbroek {
361*5d5fbe79SDavid van Moolenbroek   if (netbiosns_pcb != NULL) {
362*5d5fbe79SDavid van Moolenbroek     udp_remove(netbiosns_pcb);
363*5d5fbe79SDavid van Moolenbroek     netbiosns_pcb = NULL;
364*5d5fbe79SDavid van Moolenbroek   }
365*5d5fbe79SDavid van Moolenbroek }
366*5d5fbe79SDavid van Moolenbroek 
367*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_IPV4 && LWIP_UDP */
368