Listing 1.14
Session Retargeting


#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


void PrintL1Name( uchar *src, int max )
  /* ---------------------------------------------------- **
   * Decode and pretty-print an L1-encoded NetBIOS name.
   * ---------------------------------------------------- **
   */
  {
  int         suffix;
  static char namestr[16];

  suffix = L1_Decode( namestr, src, 1, max );
  Hex_Print( namestr, strlen( namestr ) );
  printf( "<%.2x>", suffix );
  }/* PrintL1Name */


int Get_SS_Length( uchar *hdr )
  /* ---------------------------------------------------- **
   * Read the length field from an SMB Session Service
   * header.
   * ---------------------------------------------------- **
   */
  {
  int tmp;

  tmp  = (hdr[1] & 1) << 16;
  tmp |= hdr[2] << 8;
  tmp |= hdr[3];
  return( tmp );
  } /* Get_SS_Length */


int OpenPort139( void )
  /* ---------------------------------------------------- **
   * Open port 139 for listening.
   * Note: this requires root privilege, and Samba's
   *       SMBD daemon must not be running on its
   *       default port.
   * ---------------------------------------------------- **
   */
  {
  int                result;
  int                sock;
  struct sockaddr_in sox;
  
  /* Create the socket. */  
  sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
  if( sock < 0 )
    {
    printf( "Failed to create socket(); %s.\n",
            strerror( errno ) );
    exit( EXIT_FAILURE );
    }
  
  /* Bind the socket to any interface, port TCP/139.  */
  sox.sin_addr.s_addr = INADDR_ANY;
  sox.sin_family      = AF_INET;
  sox.sin_port        = htons( 139 );
  result = bind( sock,
                 (struct sockaddr *)&sox,
                 sizeof(struct sockaddr_in) );
  if( result < 0 )
    {
    printf( "Failed to bind() socket; %s.\n",
            strerror( errno ) );
    exit( EXIT_FAILURE );
    }

  /* Post the listen request. */
  result = listen( sock, 5 );
  if( result < 0 )
    {
    printf( "Failed to listen() on socket; %s.\n",
            strerror( errno ) );
    exit( EXIT_FAILURE );
    }
    
  /* Ready... */
  return( sock );
  } /* OpenPort139 */


void Listen( struct in_addr trg_addr, int trg_port )
  /* ---------------------------------------------------- **
   * Accepts incoming connections, sends a retarget
   * message, and then disconnects.
   * ---------------------------------------------------- **
   */
  {
  int                listen_sock;
  int                reply_sock;
  int                result;
  struct sockaddr_in remote_addr;
  socklen_t          addr_len;
  uchar              recvbufr[1536];
  uchar              replymsg[10];
          
  listen_sock = OpenPort139();
          
  /* Fill in the redirect message. */
  replymsg[0] = 0x84;   /* Retarget code. */
  replymsg[1] = 0;
  replymsg[2] = 0;
  replymsg[3] = 6;      /* Remaining length. */
  (void)memcpy( &(replymsg[4]), &trg_addr.s_addr, 4 );
  trg_port = htons( trg_port );
  (void)memcpy( &(replymsg[8]), &trg_port, 2 );

  printf( "Waiting for connections...\n" );      
  for(;;)  /* Until killed. */
    {
    /* Wait for a connection. */
    addr_len = sizeof( struct sockaddr_in );
    reply_sock = accept( listen_sock,
                         (struct sockaddr *)&remote_addr,
                         &addr_len );

    /* If the accept() failed exit with an error message. */
    if( reply_sock < 0 )
      {
      printf( "Error accept()ing a connection: %s\n",
              strerror(errno) );
      exit( EXIT_FAILURE );
      }

    result = recv( reply_sock, recvbufr, 1536, 0 );
    if( result < 0 )
      {
      printf( "Error receiving packet: %s\n",
              strerror(errno) );
      }
    else
      {
      printf( "SESSION MESSAGE\n  {\n" );
      printf( "  TYPE   = 0x%.2x\n", recvbufr[0] );
      printf( "  LENGTH = %d\n", Get_SS_Length( recvbufr ) );
      if( 0x81 == recvbufr[0] )
        {
        int offset;

        printf( "  CALLED_NAME  = " );
        PrintL1Name( &recvbufr[4], result );
        offset = 5 + strlen( &(recvbufr[4]) );
        printf( "\n  CALLING_NAME = " );
        PrintL1Name( &recvbufr[offset], result );
        printf( "\n  }\nSending Retarget message.\n" );
        (void)send( reply_sock, (void *)replymsg, 10, 0 );
        }
      else
        printf( "  }\nPacket Dropped.\n" );
      }
    close( reply_sock );
    }     
  } /* Listen */


int main( int argc, char *argv[] )
  /* ---------------------------------------------------- **
   * Simple daemon that listens on port TCP/139 and
   * redirects incoming traffic to another IP and port.
   * ---------------------------------------------------- **
   */
  {
  int            target_port;
  struct in_addr target_address;
         
  if( argc != 3 )
    {
    printf( "Usage:  %s <IP> <PORT>\n", argv[0] );
    exit( EXIT_FAILURE );
    }
          
  if( 0 == inet_aton( argv[1], &target_address ) )
    {
    printf( "Invalid IP.\n" );
    printf( "Usage:  %s <IP> <PORT>\n", argv[0] );
    exit( EXIT_FAILURE );
    }
           
  target_port = atoi( argv[2] );
  if( 0 == target_port )
    {
    printf( "Invalid Port number.\n" );
    printf( "Usage:  %s <IP> <PORT>\n", argv[0] );
    exit( EXIT_FAILURE );
    }
  
  Listen( target_address, target_port );
  return( EXIT_SUCCESS );
  } /* main */


$Revision: 1.7 $
$Date: 2003/02/18 21:43:58 $
[W3C Validated] Copyright © 2002-2003 Christopher R. Hertel 
Released under the terms of the LGPL