

/******************************************************************************
 *
 * RCS ID
 * $Id: netbios,v 1.3 1999/11/07 15:11:53 david Exp $
 *
 * HISTORY
 * $Log: netbios,v $
 * Revision 1.3  1999/11/07 15:11:53  david
 * version:updated!
 * wimp:no longer used -> now using toolbox lib instead
 *
 * Revision 1.2  1999/06/20 13:40:44  david
 * Changed to call costruct_reply instead of samba_message
 *
 * Revision 1.1  1999/05/16 12:00:07  david
 * Initial revision
 *
 *
 *****************************************************************************/
/*
#include <time.h>

#include <stdio.h>
#include <string.h>

#include "socklib.h"
#include "unixlib.h"
#include "inetlib.h"

#include "mytypes.h"

#include "local.h"

#include "byteorder.h"

#include "smb.h"      

#include "smbserver.h"
*/

#include "includes.h"

#define SESSION_MESSAGE           0x00
#define SESSION_REQUEST           0x81
#define POSITIVE_SESSION_RESPONSE 0x82
#define NEGATIVE_SESSION_RESPONSE 0x83
#define RETARGET_SESSION_RESPONSE 0x84
#define SESSION_KEEP_ALIVE        0x85
#define OLD_SESSION_KEEP_ALIVE    0x89


/****************************************************************************
interpret the weird netbios "name". Return the name type
****************************************************************************/
static int name_interpret(char *in,char *out)
{
  int ret;
  int len = (*in++) / 2;

  *out=0;

  if (len > 30 || len<1) return(0);

  while (len--)
    {
      if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
    *out = 0;
    return(0);
      }
      *out = ((in[0]-'A')<<4) + (in[1]-'A');
      in += 2;
      out++;
    }
  *out = 0;
  ret = out[-1];

#ifdef NETBIOS_SCOPE
  /* Handle any scope names */
  while(*in) 
    {
      *out++ = '.'; /* Scope names are separated by periods */
      len = *(unsigned char *)in++;
      StrnCpy(out, in, len);
      out += len;
      *out=0;
      in += len;
    }
#endif
  return(ret);
}

/****************************************************************************
find a pointer to a netbios name
****************************************************************************/
static char *name_ptr(char *buf,int ofs)
{
  unsigned char c = *(unsigned char *)(buf+ofs);

  if ((c & 0xC0) == 0xC0)
    {
      uint16 l;
      char p[2];
      memcpy(p,buf+ofs,2);
      p[0] &= ~0xC0;
      l = RSVAL(p,0);
      DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
      return(buf + l);
    }
  else
    return(buf+ofs);
}  

/****************************************************************************
extract a netbios name from a buf
****************************************************************************/
int name_extract(char *buf,int ofs,char *name)
{
  char *p = name_ptr(buf,ofs);
  int d = PTR_DIFF(p,buf+ofs);
  pstrcpy(name,"");
  if (d < -50 || d > 50) return(0);
  return(name_interpret(p,name));
}


int process_session_message(tpClients aclient, char *inbuf, char *outbuf,
                            int size, int bufsize)
{
   int length;

   char logs[100];

   sprintf(logs,"process_session_message %d, %s, %s\n",aclient->clientFd,
           aclient->remote_machine,aclient->local_machine);
   writeLog(logs,0,NULL,0);

   length = construct_reply(aclient, inbuf, outbuf, size, bufsize);

   if (length>0)
   {
      CVAL(outbuf,0)=SESSION_MESSAGE;
      smb_setlen(outbuf,length-4);
   /*   length+=4; */
   }          

   return length;
}

int process_session_request(tpClients aclient, char *inbuf, char *outbuf)
{        
    pstring name1,name2;
    char name_type = 0;
    int len;

    *name1 = *name2 = 0;

    CVAL(outbuf,0) = POSITIVE_SESSION_RESPONSE;
    CVAL(outbuf,3) = 0;
    if (name_len(inbuf+4) > 50 || 
        name_len(inbuf+4 + name_len(inbuf + 4)) > 50) 
    {
        DEBUG(0,("Invalid name length in session request\n"));
        return(0);
    } 

    name_extract(inbuf,4,name1);
    name_extract(inbuf,4 + name_len(inbuf + 4),name2);
    DEBUG(2,("netbios connect: name1=%s name2=%s\n",
             name1,name2));      

    fstrcpy(aclient->remote_machine,name2);
    aclient->remote_machine[15] = 0;
    trim_string(aclient->remote_machine," "," ");
    strlower(aclient->remote_machine);

    fstrcpy(aclient->local_machine,name1);
    len = strlen(aclient->local_machine);
    if (len == 16) 
    {
        name_type = aclient->local_machine[15];
        aclient->local_machine[15] = 0;
    }

    trim_string(aclient->local_machine," "," ");
    strlower(aclient->local_machine); 
        
    if (name_type == 'R') 
    {
        /* We are being asked for a pathworks session --- 
           no thanks! */
        CVAL(outbuf, 0) = NEGATIVE_SESSION_RESPONSE;
    }       

    return (4);

}


int netbios_in(tpClients aclient, char *inbuf, char *outbuf,
               int size,         
               int bufsize)
{
    int outsize = 4;
    int msg_type = CVAL(inbuf,0);
    int msg_flags = CVAL(inbuf,1);

    
    memset(outbuf,'\0',smb_size);

    smb_setlen(outbuf,0);

    switch (msg_type) 
    {                 
        case SESSION_MESSAGE:
            outsize=process_session_message(aclient,inbuf,outbuf,
                                            size, bufsize);
            break;
            
        case SESSION_REQUEST:
            outsize=process_session_request(aclient,inbuf,outbuf);
            break;

        case OLD_SESSION_KEEP_ALIVE:  
            /* (some old clients produce this?) */
            CVAL(outbuf,0) = 0x85;
            CVAL(outbuf,3) = 0;
            break;
        
        case POSITIVE_SESSION_RESPONSE: 
        case NEGATIVE_SESSION_RESPONSE: 
        case RETARGET_SESSION_RESPONSE:
            DEBUG(0,("Unexpected session response\n"));
            break;
        
        case SESSION_KEEP_ALIVE: 
        default:
            outsize=0;
            break;
    }
    
    DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
            msg_type, msg_flags));
    
    return(outsize);
}
   




