Listing 1.3
Simple Broadcast Name Query


#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>

#define NBT_BCAST_ADDR "255.255.255.255"

#ifndef uchar
#define uchar unsigned char
#endif /* uchar */

uchar header[] =
  {
  0x07, 0xAC,  /* 1964 == 0x07AC.   */
  0x01, 0x10,  /* Binary 0 0000 0010001 0000 */
  0x00, 0x01,  /* One name query.   */
  0x00, 0x00,  /* Zero answers.     */
  0x00, 0x00,  /* Zero authorities. */
  0x00, 0x00   /* Zero additional.  */
  };

uchar query_tail[] =
  {
  0x00, 0x20,
  0x00, 0x01
  };

uchar *L1_Encode( uchar       *dst,
                  const uchar *name,
                  const uchar  pad,
                  const uchar  sfx )
  {
  int i = 0;
  int j = 0;
  int k = 0;

  while( ('\0' != name[i]) && (i < 15) )
    {
    k = toupper( name[i++] );
    dst[j++] = 'A' + ((k & 0xF0) >> 4);
    dst[j++] = 'A' +  (k & 0x0F);
    }

  i = 'A' + ((pad & 0xF0) >> 4);
  k = 'A' +  (pad & 0x0F);
  while( j < 30 )
    {
    dst[j++] = i;
    dst[j++] = k;
    }

  dst[30] = 'A' + ((sfx & 0xF0) >> 4);
  dst[31] = 'A' +  (sfx & 0x0F);
  dst[32] = '\0';

  return( dst );
  } /* L1_Encode */

int L2_Encode( uchar       *dst,
               const uchar *name,
               const uchar  pad,
               const uchar  sfx,
               const uchar *scope )
  {
  int lenpos;
  int i;
  int j;

  if( NULL == L1_Encode( &dst[1], name, pad, sfx ) )
    return( -1 );
  dst[0] = 0x20;
  lenpos = 33;

  if( '\0' != *scope )
    {
    do
      {
      for( i = 0, j = (lenpos + 1);
           ('.' != scope[i]) && ('\0' != scope[i]);
           i++, j++)
        dst[j] = toupper( scope[i] );

      dst[lenpos] = (uchar)i;
      lenpos     += i + 1;
      scope      += i;
      } while( '.' == *(scope++) );
    dst[lenpos] = '\0';
    }

  return( lenpos + 1 );
  } /* L2_Encode */

void Send_Nbtn_Bcast( uchar *msg, int msglen )
  {
  int                s;
  int                true = 1;
  struct sockaddr_in sox;

  s = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
  if( s < 0 )
    {
    perror( "Socket()" );
    exit( 0 );
    }

  if( setsockopt( s, SOL_SOCKET, SO_BROADCAST,
                  &true, sizeof(int) ) < 0 )
    {
    perror( "Setsockopt()" );
    exit( 0 );
    }

  if( 0 == inet_aton( NBT_BCAST_ADDR, &(sox.sin_addr) ) )
    {
    printf( "Invalid IP address.\n" );
    exit( 0 );
    }
  sox.sin_family = AF_INET;
  sox.sin_port   = htons( 137 );

  if( sendto( s,
              (void *)msg,
              msglen, 
              0,
              (struct sockaddr *)&sox,
              sizeof(struct sockaddr_in) ) < 0 )
    {
    perror( "Sendto()" );
    exit( 0 );
    }

  close( s );
  } /* Send_Nbtn_Bcast */

int main( int argc, char *argv[] )
  {
  uchar  bufr[512];
  int    len;
  int    total_len;
  uchar *name;
  uchar *scope;

  if( argc > 1 )
    name = (uchar *)argv[1];
  else
    exit( EXIT_FAILURE );

  if( argc > 2 )
    scope = (uchar *)argv[2];
  else
    scope = "";

  (void)memcpy( bufr, header, (total_len = sizeof(header)) );

  len = L2_Encode( &bufr[total_len], name, ' ', '\0', scope );
  if( len < 0 )
    return( EXIT_FAILURE );
  total_len += len;

  (void)memcpy( &bufr[total_len], query_tail, sizeof( query_tail ) );
  total_len += sizeof( query_tail );

  Send_Nbtn_Bcast( bufr, total_len );

  return( EXIT_SUCCESS );
  } /* main */


$Revision: 1.24 $
$Date: 2007/10/14 18:21:27 $
[W3C Validated] Copyright © 1999-2003 Christopher R. Hertel 
Released under the terms of the LGPL