/* Nessuslib -- the Nessus Library
 * Copyright (C) 1998 Renaud Deraison
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Network Functions
 */ 

#define EXPORTING
#include <includes.h>
#include <stdarg.h>
#include "network.h"
#include "resolve.h"


#define TIMEOUT 10
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif


ExtFunc
int open_sock_opt_hn(hostname, port, type, protocol)
 const char * hostname; 
 unsigned int port; 
 int type;
 int protocol;
{
 struct sockaddr_in addr;
 int soc;
  
  bzero((void*)&addr, sizeof(addr));
  addr.sin_family=AF_INET;
  addr.sin_port=htons((unsigned short)port);
  addr.sin_addr = nn_resolve(hostname);
  if (addr.sin_addr.s_addr == INADDR_NONE || addr.sin_addr.s_addr == 0)
    return(-1);
    
  if ((soc = socket(AF_INET, type, protocol)) < 0)
    return -1;   
  alarm(TIMEOUT); 
  if (connect(soc, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
      close(soc);
      alarm(0);
      return  -1;
    }
  alarm(0); 
  return soc;
}


ExtFunc
int open_sock_tcp_hn(hostname, port)
 const char * hostname;
 unsigned int port;
{
  return(open_sock_opt_hn(hostname, port, SOCK_STREAM, IPPROTO_TCP));
}


ExtFunc
int open_sock_tcp(args, port)
 struct arglist * args; 
 unsigned int port;
{
	return(open_sock_option(args, port, SOCK_STREAM,IPPROTO_TCP));
}


ExtFunc
int open_sock_udp(args, port)
 struct arglist * args;
 unsigned int port;
{
	return(open_sock_option(args, port, SOCK_DGRAM, IPPROTO_UDP));
}


ExtFunc
int open_sock_option(args, port, type, protocol)
 struct arglist * args;
 unsigned int port;
 int type;
 int protocol;
{
  struct sockaddr_in addr;
  struct in_addr * t;
  int soc;
  
  if(host_get_port_state(args, port)<=0)return(-1);
  bzero((void*)&addr, sizeof(addr));
  addr.sin_family=AF_INET;
  addr.sin_port=htons((unsigned short)port);
  t = plug_get_host_ip(args);
  if(!t)
  {
   fprintf(stderr, "ERROR ! NO ADDRESS ASSOCIATED WITH NAME\n");
   arg_dump(args, 0);
   return(-1);
  }
  addr.sin_addr = *t;
  if (addr.sin_addr.s_addr == INADDR_NONE)
    return(-1);
    
  if ((soc = socket(AF_INET, type, protocol)) < 0)
    return -1;  
  alarm(TIMEOUT);
  if (connect(soc, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
      close(soc);
      alarm(0);
      return  -1;
    }
  alarm(0); 
  return soc;
}


ExtFunc
short is_cgi_installed(data, cgi_name)
 struct arglist * data;
 const char * cgi_name;
{
  char * command = emalloc(200);
  short soc=-1;
  short i=0;
  char * buff = emalloc(256);
  
  sprintf(command, "GET /cgi-bin/%s HTTP/1.0\nhostname: %s\n\n",
	  cgi_name,  plug_get_hostname(data));
	  
  soc = open_sock_tcp(data, 80);
  if(soc <0)return(0); /* couldn't open a connection */
  send(soc, command, strlen(command), 0);
  recv(soc, buff, 255,0);
  efree(&command);
  close(soc);
 
  if(strstr(buff, "HTTP/1.0 200 ") || strstr(buff, "HTTP/1.1 200 "))i=1; /* No error */
  else i=0; /* Error */
  
  efree(&buff);
  return(i);
}


ExtFunc
void recv_line(soc, buf, bufsiz)
 int soc;
 char * buf;
 size_t bufsiz;
{
 size_t i = 0;
 char c[2];
 int ok = 0;
 
 bzero(buf, bufsiz);
 bzero(c, 2);
 while(!ok)
 {
  recv(soc, c, 1, 0);
  buf[i++] = c[0];
  if((!strlen(c)) || (!c[0]) || (c[0]=='\n') || (i>=bufsiz))ok=1;
 }
} 


ExtFunc void
socket_close(soc)
int soc;
{
 close(soc);
}

/*
 * auth_printf()
 *
 * Writes data to the global socket of the thread
 */
ExtFunc void 
auth_printf(struct arglist * globals, const char * data, ...)
{
  va_list param;
  int soc = (int)arg_get_value(globals, "global_socket");
  char * buffer;
  
#ifndef NESSUSNT
  signal(SIGPIPE, exit);
#endif
  buffer = emalloc(4096);
  va_start(param, data);
#ifdef HAVE_VSNPRINTF
  vsnprintf(buffer, 4095, data, param);
#else
  vsprintf(buffer, data,param);
#endif
  send(soc, buffer, strlen(buffer), 0);
  efree(&buffer);
#ifndef NESSUSNT
  signal(SIGPIPE, SIG_IGN);
#endif
  va_end(param);
}                    


/*
 * auth_gets()
 *
 * Reads data from the global socket of the thread
 */
ExtFunc char * 
auth_gets(globals, buf, bufsiz)
     struct arglist * globals;
     char * buf;
     size_t bufsiz;
{
  int soc = (int)arg_get_value(globals, "global_socket");

  bzero(buf, bufsiz);
  recv_line(soc, buf, bufsiz);
  if(!strlen(buf)){
    EXIT(0);
  }
  /* we will have to decypher some stuff here !*/
  return(buf);
}
