/*
* Program: Synonym
* File: scan.c
* Author: Cristian Draghici
* Date: 17 Nov 2003
*
* $Id: scan.c,v 1.2 2004/01/19 09:24:31 diciu Exp $
*
* Licensed under the Modulo Consulting Software License
* (see file license.txt)
*
*/
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <syslog.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <stdio.h>
#define SCAN_FAILURE 1
#define SCAN_SUCCESS 0
#define print_debug syslog
/* request scan from clamd */
int request_scan(char *scan_data, long scan_size)
{
int data_sock, command_sock, retval = 0;
struct timeval tv;
fd_set data_wfds, command_wfds;
struct sockaddr_in data_serv_addr, command_serv_addr;
char buffer[1024];
int bytes_read;
struct hostent *temp_hostent;
unsigned long clamd_hostaddr;
int scan_port;
if ((command_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
syslog(LOG_ERR, "Failed to create the command socket for communicating with clamd - err code: %d", errno);
return SCAN_FAILURE;
}
if((temp_hostent = gethostbyname("127.0.0.1"))==NULL)
{
print_debug(LOG_ERR, "Unable to resolve the notification host address %s\n", optarg);
return SCAN_FAILURE;
}
clamd_hostaddr = *((unsigned long*)temp_hostent->h_addr);
command_serv_addr.sin_family = AF_INET;
command_serv_addr.sin_addr.s_addr = clamd_hostaddr;
command_serv_addr.sin_port = htons(3773);
if (connect(command_sock, (struct sockaddr *)&command_serv_addr, sizeof(command_serv_addr)) != 0)
{
syslog(LOG_ERR, "Failed to connect to the notification engine command channel");
close(command_sock);
return SCAN_FAILURE;
}
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&command_wfds);
FD_SET(command_sock, &command_wfds);
if ((retval = select((command_sock)+1, NULL, &command_wfds, NULL,&tv)) > 0)
{
write(command_sock, "STREAM", strlen("STREAM"));
}
/* now read the answer */
if ((retval = select((command_sock)+1, NULL, &command_wfds, NULL,&tv)) > 0)
{
bytes_read = read(command_sock, buffer, 1024);
}
buffer[bytes_read] = '\0';
print_debug(LOG_DEBUG, "Read %d bytes, %s", bytes_read, buffer);
/* get the port from the answer */
if(sscanf(buffer, "PORT %d\n", &scan_port) != 1)
print_debug(LOG_DEBUG, "Reading scan port failed.");
print_debug(LOG_DEBUG, "Scan port is %d", scan_port);
if ((data_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
syslog(LOG_ERR, "Failed to create the data socket for communicating with clamd - err code: %d", errno);
return SCAN_FAILURE;
}
data_serv_addr.sin_family = AF_INET;
data_serv_addr.sin_addr.s_addr = clamd_hostaddr;
data_serv_addr.sin_port = htons(scan_port);
sleep(1);
/* open a new connection */
if (connect(data_sock, (struct sockaddr *)&data_serv_addr, sizeof(data_serv_addr)) != 0)
{
syslog(LOG_ERR, "Failed to connect to the notification engine data channel");
close(data_sock);
close(command_sock);
return SCAN_FAILURE;
}
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&data_wfds);
FD_SET(data_sock, &data_wfds);
if ((retval = select((data_sock)+1, NULL, &data_wfds, NULL,&tv)) > 0)
{
write(data_sock, scan_data, scan_size);
}
close(data_sock);
print_debug(LOG_DEBUG, "Sent data for scan, reading answer on command socket");
/* now read the answer */
if ((retval = select((command_sock)+1, NULL, &command_wfds, NULL,&tv)) > 0)
{
bytes_read = read(command_sock, buffer, 1024);
}
buffer[bytes_read] = '\0';
print_debug(LOG_DEBUG, "Read %d bytes, %s", bytes_read, buffer);
close(command_sock);
return SCAN_SUCCESS;
}
syntax highlighted by Code2HTML, v. 0.9.1