lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lwip-users] Netbios nameresolving for lwip


From: Frédéric BERNON
Subject: Re: [lwip-users] Netbios nameresolving for lwip
Date: Sun, 7 Dec 2008 08:46:14 +0100


There is already something like this in lwIP\contrib\apps\netbios based on raw api. But it's a simple implementation, so, perhaps yours is more useful.

----- Original Message ----- From: "Oliver Schindler" <address@hidden>
To: "Mailing list for lwIP users" <address@hidden>
Sent: Saturday, December 06, 2008 10:34 PM
Subject: [lwip-users] Netbios nameresolving for lwip


Hi there,
i'm quite new in this list, so didn't know, if this topic was handled
before ...
.. anyway, I'm using the lwip on an Arm9 together with FreeRtos and it's
working
smooth  like anything. There was only one little naggi thing for me,
because the counterpart of my
SW is hosted in the windows-world, and this speaks only netbios for
nameresolving.
I'm in the need of using DHCP, so there is no chance to contact my
Arm-board through a
static IP. To keep long terms short, i wrote a little piece of SW which
does the name-resolving
for a netbios-name request and sends back the current IP-Adress.
Maybe it's of any use for someone ... If the maintainer of the lwip find it
somehow usefull, it can also be a part of the lwip.  It consists of a
c- and h -file and a part for  the
lwip-opts.
The init is quite simple, jut give a pointer of your host-name, and
pointer for the namelength and a
pointer for your networkinterface. The last one is needed to get the
IP-adress for the interface, so
this will work also in cooperation with DHCP. The maximumlength for the
hostname is 32 chars, this
is the restriction from netbios.

Thanks for your great work and c.u. soon,
Oliver






--------------------------------------------------------------------------------


/*
  ----------------------------------
  ---------- NBNS options -----------
  ----------------------------------
*/
/**
* LWIP_NBNS==1: Turn on NetBiosNameService module. UDP must be available for NBNS
* transport.
*/
#ifndef LWIP_NBNS
#define LWIP_NBNS                        0
#endif

/** NBNS use a local buffer if NBNS_USES_STATIC_BUF=0, a static one if
   NBNS_USES_STATIC_BUF=1, or a dynamic one if NBNS_USES_STATIC_BUF=2.
   The buffer will be of size NBNS_MSG_SIZE */
#ifndef NBNS_USES_STATIC_BUF
#define NBNS_USES_STATIC_BUF             1
#endif

/** NBNS message max. size. Default value is RFC compliant. */
#ifndef NBNS_MSG_SIZE
#define NBNS_MSG_SIZE                    512
#endif

/** NBNS client port address */
#ifndef NBNS_CLIENT_PORT
#define NBNS_CLIENT_PORT           137
#endif




--------------------------------------------------------------------------------


/**
* @file
* NBNS - host name to NetBios resolver.
*
*/

/**

* This file implements a simple NetBios Server for the HostName.
* All other NetBios querys are ignored

* by Oliver Schindler November 2008

* uIP version Copyright (c) 2002-2003, Adam Dunkels.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
*    products derived from this software without specific prior
*    written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* NBNS.H
*
* The NetbiosNameService waiting on UDP-Port 137 for a NBNS-Query.
* If this Query matches with the HostName, a respond is send.
* All other NetBios Telegramms are ignored. ( like Samba, PrinterServices , etc. )
*/

/*-----------------------------------------------------------------------------
* RFC 1001 - Protocol Standard for a NetBIOS Service on a TCP/UDP Transport: Concepts and methods * RFC 1002 - Protocol standard for a NetBIOS service on a TCP/UDP transport: Detailed specifications
*----------------------------------------------------------------------------*/

#ifndef __LWIP_NBNS_H__
#define __LWIP_NBNS_H__

#include "lwip/opt.h"

#if LWIP_NBNS /* don't build if not configured for use in lwipopts.h */



void nbns_init(u8_t* Hostname,u8_t* Hostname_Len, struct netif *netif);

/* Values of the opcode field */

#define OPCODE_R 0x8000

/*OPCODE        1-4   Operation specifier:
                        0 = query
                        5 = registration
                        6 = release
                        7 = WACK
                        8 = refresh */

#define OPCODE_MASK 0x7800
#define OPCODE_QUERY 0x0000
#define OPCODE_REGISTRATION 0x2800
#define OPCODE_RELEASE 0x3000
#define OPCODE_WACK 0x3800
#define OPCODE_REFRESH 0x4000


/* NM_FLAGS subfield bits */
#define NM_AA_BIT         0x0400  /* Authoritative Answer */
#define NM_TR_BIT         0x0200  /* TRuncation flag      */
#define NM_RD_BIT         0x0100  /* Recursion Desired    */
#define NM_RA_BIT         0x0080  /* Recursion Available  */
#define NM_B_BIT          0x0010  /* Broadcast flag       */

/* Return Codes */
#define RCODE_POS_RSP     0x0000  /* Positive Response    */
#define RCODE_FMT_ERR     0x0001  /* Format Error         */
#define RCODE_SRV_ERR     0x0002  /* Server failure       */
#define RCODE_NAM_ERR     0x0003  /* Name Not Found       */
#define RCODE_IMP_ERR     0x0004  /* Unsupported request  */
#define RCODE_RFS_ERR     0x0005  /* Refused              */
#define RCODE_ACT_ERR     0x0006  /* Active error         */
#define RCODE_CFT_ERR     0x0007  /* Name in conflict     */
#define RCODE_MASK        0x0007  /* Mask                 */

/* Used to set the record count fields. */
#define QUERYREC          0x1000  /* Query Record         */
#define ANSREC            0x0100  /* Answer Record        */
#define NSREC             0x0010  /* NS Rec (never used)  */
#define ADDREC            0x0001  /* Additional Record    */


/* RDATA NB_FLAGS. */
#define GROUP_BIT     0x8000  /* Group indicator      */
#define ONT_B         0x0000  /* Broadcast node       */
#define ONT_P         0x2000  /* Point-to-point node  */
#define ONT_M         0x4000  /* Mixed mode node      */
#define ONT_H         0x6000  /* MS Hybrid mode node  */
#define ONT_MASK      0x6000  /* Mask                 */

/* RDATA NAME_FLAGS. */
#define DRG           0x0100  /* Deregister.          */
#define CNF           0x0800  /* Conflict.            */
#define ACT           0x0400  /* Active.              */
#define PRM           0x0200  /* Permanent.           */




#endif /* LWIP_DNS */

#endif /* __LWIP_DNS_H__ */



--------------------------------------------------------------------------------


/**
* @file
* NBNS - host name to NetBios resolver.
*
*/

/**

* This file implements a simple NetBios Server for the HostName.
* All other NetBios querys are ignored

* by Oliver Schindler November 2008

* uIP version Copyright (c) 2002-2003, Adam Dunkels.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
*    products derived from this software without specific prior
*    written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* NBNS.C
*
* The NetbiosNameService waiting on UDP-Port 137 for a NBNS-Query.
* If this Query matches with the HostName, a resond is send.
* All other NetBios Telegramms are ignored. ( like Samba, PrinterServices , etc. )
*/

/*-----------------------------------------------------------------------------
* RFC 1001 - Protocol Standard for a NetBIOS Service on a TCP/UDP Transport: Concepts and methods * RFC 1002 - Protocol standard for a NetBIOS service on a TCP/UDP transport: Detailed specifications
*----------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------
* Includes
*----------------------------------------------------------------------------*/

#include "lwip/opt.h"

#if LWIP_NBNS /* don't build if not configured for use in lwipopts.h */
#if LWIP_UDP

#include "lwip/udp.h"
#include "lwip/mem.h"
#include "lwip/nbns.h"


#include <string.h>
#include <stdlib.h>


/** NBNS server port address */
#ifndef NBNS_CLIENT_PORT
#define NBNS_CLIENT_PORT           137
#endif

#define NETBIOS_NAME_LEN    32

#if (NBNS_USES_STATIC_BUF == 1)
static u8_t pHostname[NETBIOS_NAME_LEN];
#endif /* (NBNS_USES_STATIC_BUF == 1) */



/** NBNS message header */
#ifdef PACK_STRUCT_USE_INCLUDES
#  include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN

struct nbns_hdr {
 u16_t id;
 u16_t flags;
 u16_t numquestions;
 u16_t numanswers;
 u16_t numauthrr;
 u16_t numextrarr;
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
#  include "arch/epstruct.h"
#endif


/** NBNS rdata field */
#ifdef PACK_STRUCT_USE_INCLUDES
#  include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN

struct nbns_rdata {
 u16_t len;
 u16_t nbflags;
 struct ip_addr addr;
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
#  include "arch/epstruct.h"
#endif


/* forward declarations */
static void nbns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);

/*-----------------------------------------------------------------------------
* Globales
*----------------------------------------------------------------------------*/

/* NBNS variables */
static struct udp_pcb        *nbns_pcb;
struct netif *pnetif=NULL;
static u8_t* pnbns_hostname=NULL;
u8_t* pnbns_hostname_len=NULL;

/**
* Initialize the resolver: set up the UDP pcb
*/
void
nbns_init(u8_t* Hostname,u8_t* Hostname_Len, struct netif *netif)
{


 LWIP_DEBUGF(NBNS_DEBUG, ("nbns_init: initializing\n"));
 pnbns_hostname_len=Hostname_Len;
 if (*pnbns_hostname_len>NETBIOS_NAME_LEN) {
LWIP_DEBUGF(NBNS_DEBUG, ("nbns_init:ERROR Hostname should be max 32 chars \n"));
  return;
 }
 pnbns_hostname=Hostname;
 pnetif= netif;

 /* if nbns client not yet initialized... */
 if (nbns_pcb == NULL) {
   nbns_pcb = udp_new();

   if (nbns_pcb != NULL) {

     /* initialize NBNS client */
     udp_bind(nbns_pcb, IP_ADDR_ANY, NBNS_CLIENT_PORT);
     udp_recv(nbns_pcb, nbns_recv, NULL);


   }
 }
}

static u8_t
nbns_compare_name(u8_t *query, u8_t *response,u8_t len)
{
 u8_t i;

 for (i=0;i<len;i++) {
   if (*response==0){
return 1;
}
if (*query==0){
return 1;
}
if (tolower(query[i])!=tolower(response[i])) {
return 1;
}
 }

 return 0;
}





#define NBNS_TTL_POS sizeof(struct nbns_hdr)+1+NETBIOS_NAME_LEN+1+2+2
#define NBNS_RDATA_POS NBNS_TTL_POS + 4

#define NBNS_MSGLEN_QUERY_RESPONSE 70 // NBNS_RDATA_POS+sizeof(struct nbns_rdata)


/**
* Receive input function for NBNS query packets arriving for the NameService UDP pcb.
*
* @params see udp.h
*/
static void
nbns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
{
 err_t err;
 u16_t unique_id,i;
 char c1,c2;
 char *pNamefield;
 struct nbns_hdr *hdr;
 struct nbns_rdata* rdata ;
 u16_t* ttl1,*ttl2;
 struct pbuf *prep;
 u16_t nquestions, nanswers,opcode,nm_flags,rcode,name_len;
#if (NBNS_USES_STATIC_BUF == 0)
 u8_t pHostname[NETBIOS_NAME_LEN];
#endif /* (NBNS_USES_STATIC_BUF == 0) */
#if (NBNS_USES_STATIC_BUF == 2)
 u8_t* pHostname;
#endif /* (NBNS_USES_STATIC_BUF == 2) */

 LWIP_UNUSED_ARG(arg);
 LWIP_UNUSED_ARG(pcb);


 /* is the nbns message too big ? */
 if (p->tot_len > NBNS_MSG_SIZE) {
   LWIP_DEBUGF(NBNS_DEBUG, ("nbns_recv: pbuf too big\n"));
   /* free pbuf and return */
   goto memerr1;
 }

 /* is the nbns message big enough ? */
 if (p->tot_len < (1+NETBIOS_NAME_LEN+1+2+2+sizeof(struct nbns_hdr))) {
   LWIP_DEBUGF(NBNS_DEBUG, ("nbns_recv: pbuf too small\n"));
   /* free pbuf and return */
   goto memerr1;
 }

#if (NBNS_USES_STATIC_BUF == 2)
 pHostname = mem_malloc(NETBIOS_NAME_LEN);
 if (pHostname == NULL) {
LWIP_DEBUGF(NBNS_DEBUG, ("nbns_recv: mem_malloc error\n"));
/* free pbuf and return */
goto memerr2;
 }

#endif /* (NBNS_USES_STATIC_BUF == 2) */

 /* The content of the Telegramm is only decoded for information purpses.
    Later we use a copy of the orignal message */

  hdr = (struct nbns_hdr*)p->payload;
unique_id = htons(hdr->id); /* this is a unique ID , which has to be sent back */

  /* We only care about the question(s) and the answers. The authrr
 and the extrarr are simply discarded. */
  nquestions = htons(hdr->numquestions);
  nanswers   = htons(hdr->numanswers);

  /* Decode what the client wants from us */
  opcode =  htons(hdr->flags) & 0xf800;
  nm_flags =  htons(hdr->flags) & 0x03f0;
  rcode =  htons(hdr->flags) & 0x000f;

if (opcode & OPCODE_R ) { /* This is a response packet, so don't care about */
   /* deallocate memory and return */
   goto memerr2;
  }

  switch (opcode & OPCODE_MASK) {
    case OPCODE_QUERY:
   /* There is someone looking for a host with a certain name ... */
   break;

    case OPCODE_REGISTRATION:
    case OPCODE_RELEASE:
    case OPCODE_WACK:
    case OPCODE_REFRESH:
    default:
   /* Nothing of interest for us */
   /* deallocate memory and return */
   goto memerr2;
   break; /* just for the compiler .... */
  }

  pNamefield=((u8_t*)p->payload)+sizeof(struct nbns_hdr);
  name_len=pNamefield[0];
  if (name_len!=NETBIOS_NAME_LEN) {
   /* Hmm , this is not a netbios name ... */
    goto memerr2;

  }
  memset (pHostname,0,NETBIOS_NAME_LEN);
  pNamefield++;
  /* Decode the hostname */
  for (i=0;i<name_len;i+=2) {
   c1=(pNamefield[i]&0x3f)-1;
   c2=(pNamefield[i+1]&0x3f)-1;
      pHostname[i/2]=(c1<<4)+(c2);
  }

  if (!nbns_compare_name(pHostname,pnbns_hostname,*pnbns_hostname_len)) {
   /* Hey , this is ours .. we have to send a reply */

   LWIP_DEBUGF(NBNS_DEBUG, ("nbns_recv: Got a query for our hostname\n"));

   /* reallocate of pbuf isn't implemented to grow, so we have allocate a
      new buffer ,to have space for our IP-Adress */

prep = pbuf_alloc(PBUF_TRANSPORT, NBNS_MSGLEN_QUERY_RESPONSE, PBUF_RAM);

/* clone the original message, for the transport_id,hostname and flags*/
   pbuf_copy_partial(p, prep->payload, p->tot_len, 0);


   /* set pointers for the different parts in the message */
   hdr = (struct nbns_hdr*)prep->payload;

/* ttl is 32-bit, but we can't guarantee that is aligned on a 32 bit boundary,
      so split it up into two halves */
   ttl1 = (u16_t*)(((u8_t*)prep->payload)+NBNS_TTL_POS);
   ttl2 = (u16_t*)(((u8_t*)prep->payload)+NBNS_TTL_POS+2);

   /* This is were our IP-Adress goes to */
   rdata = (struct nbns_rdata*) (((u8_t*)prep->payload)+NBNS_RDATA_POS);

   /* Set the response Flag, and the number of answers  */

   opcode=OPCODE_R+OPCODE_QUERY;
   nm_flags=NM_AA_BIT+NM_RD_BIT;
   rcode=RCODE_POS_RSP; /* Positive respones */

   hdr->flags =ntohs(opcode+nm_flags+rcode);
   hdr->numquestions=ntohs(0);
   hdr->numanswers  =ntohs(1);

   *ttl1=ntohs(0);
   *ttl2=ntohs(0); /* Infinite time to live */
   rdata->len=ntohs(2+sizeof(struct ip_addr));
   rdata->nbflags=ntohs(ONT_B); /* Broadcast Node */

memcpy((unsigned char*)&rdata->addr,(unsigned char*)&pnetif->ip_addr,sizeof(struct ip_addr));


/* It's better to answer on the port , we got the query, maybe some strange
      port-translation is in between */
   err = udp_sendto(nbns_pcb, prep, addr,port/* NBNS_CLIENT_PORT*/);

   /* cleaning up */
   pbuf_free(prep);
  }





 /* deallocate memory and return */
 //goto memerr2;



memerr2:
#if (NBNS_USES_STATIC_BUF == 2)
 /* free Hostname buffer */
if(pHostname!=NULL){
 mem_free(pHostname);
}
#endif /* (NBNS_USES_STATIC_BUF == 2) */

memerr1:
 /* free pbuf */
 pbuf_free(p);
 return;
}


#else
#error "UDP is needed !"
#endif
#endif /* LWIP_NBNS */



--------------------------------------------------------------------------------


_______________________________________________
lwip-users mailing list
address@hidden
http://lists.nongnu.org/mailman/listinfo/lwip-users






reply via email to

[Prev in Thread] Current Thread [Next in Thread]