/* * 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 #include #include #include #include #include #include #include #include #include #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; }