1542 lines
34 KiB
C
1542 lines
34 KiB
C
/*
|
|
* Copyright (C) 2002-2003 Erik Fears
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to
|
|
*
|
|
* The Free Software Foundation, Inc.
|
|
* 59 Temple Place - Suite 330
|
|
* Boston, MA 02111-1307, USA.
|
|
*
|
|
*
|
|
*/
|
|
|
|
#include "modconfig.h"
|
|
|
|
#include "config.h"
|
|
#include "libopm.h"
|
|
#include "malloc.h"
|
|
#include "opm_error.h"
|
|
#include "opm_types.h"
|
|
#include "opm_common.h"
|
|
#include "list.h"
|
|
#include "inet.h"
|
|
#include "proxy.h"
|
|
|
|
#include <errno.h>
|
|
#ifdef TIME_WITH_SYS_TIME
|
|
# include <sys/time.h>
|
|
# include <time.h>
|
|
#else
|
|
# ifdef HAVE_SYS_TIME_H
|
|
# include <sys/time.h>
|
|
# else
|
|
# include <time.h>
|
|
# endif
|
|
#endif
|
|
|
|
#include <unistd.h>
|
|
|
|
#ifdef HAVE_STRING_H
|
|
# include <string.h>
|
|
#endif
|
|
|
|
RCSID("$Id$");
|
|
|
|
static OPM_PROTOCOL_CONFIG_T *libopm_protocol_config_create(void);
|
|
static void libopm_protocol_config_free(OPM_PROTOCOL_CONFIG_T *);
|
|
|
|
/*
|
|
* XXX - does not appear to be used anywhere?
|
|
* -grifferz
|
|
*/
|
|
#if 0
|
|
static OPM_PROTOCOL_T *libopm_protocol_create(void);
|
|
static void libopm_protocol_free(OPM_PROTOCOL_T *);
|
|
#endif
|
|
|
|
static OPM_SCAN_T *libopm_scan_create(OPM_T *, OPM_REMOTE_T *);
|
|
static void libopm_scan_free(OPM_SCAN_T *);
|
|
|
|
static OPM_CONNECTION_T *libopm_connection_create(void);
|
|
static void libopm_connection_free(OPM_CONNECTION_T *);
|
|
|
|
static void libopm_check_establish(OPM_T *);
|
|
static void libopm_check_poll(OPM_T *);
|
|
static void libopm_check_closed(OPM_T *);
|
|
static void libopm_check_queue(OPM_T *);
|
|
|
|
static void libopm_do_connect(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
|
|
static void libopm_do_readready(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
|
|
static void libopm_do_writeready(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
|
|
static void libopm_do_hup(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
|
|
static void libopm_do_read(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
|
|
static void libopm_do_openproxy(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
|
|
|
|
static void libopm_do_callback(OPM_T *, OPM_REMOTE_T *, int, int);
|
|
|
|
static OPM_REMOTE_T *libopm_setup_remote(OPM_REMOTE_T *, OPM_CONNECTION_T *);
|
|
|
|
|
|
/* OPM_PROTOCOLS hash
|
|
*
|
|
* OPM_PPROTOCOLS hashes the protocol types (int) to functions
|
|
* which handle the protocol (sending/receiving protocol specific
|
|
* data).
|
|
*
|
|
*/
|
|
|
|
static OPM_PROTOCOL_T OPM_PROTOCOLS[] = {
|
|
{OPM_TYPE_HTTP, libopm_proxy_http_write, NULL},
|
|
{OPM_TYPE_SOCKS4, libopm_proxy_socks4_write, NULL},
|
|
{OPM_TYPE_SOCKS5, libopm_proxy_socks5_write, NULL},
|
|
{OPM_TYPE_ROUTER, libopm_proxy_router_write, NULL},
|
|
{OPM_TYPE_WINGATE, libopm_proxy_wingate_write, NULL},
|
|
{OPM_TYPE_HTTPPOST, libopm_proxy_httppost_write, NULL}
|
|
};
|
|
|
|
|
|
|
|
|
|
/* opm_create
|
|
*
|
|
* Initialize a new scanner and return a pointer to it.
|
|
*
|
|
* Parameters:
|
|
* None
|
|
*
|
|
* Return
|
|
* Pointer to new OPM_T (scanner)
|
|
*/
|
|
|
|
OPM_T *opm_create()
|
|
{
|
|
int i;
|
|
OPM_T *ret;
|
|
|
|
ret = MyMalloc(sizeof *ret);
|
|
|
|
ret->config = libopm_config_create();
|
|
ret->scans = libopm_list_create();
|
|
ret->queue = libopm_list_create();
|
|
ret->protocols = libopm_list_create();
|
|
ret->fd_use = 0;
|
|
|
|
/* Setup callbacks */
|
|
ret->callbacks = MyMalloc(sizeof(OPM_CALLBACK_T) * CBLEN);
|
|
for(i = 0; i < CBLEN; i++)
|
|
{
|
|
ret->callbacks[i].func = NULL;
|
|
ret->callbacks[i].data = NULL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* opm_remote_create
|
|
*
|
|
* Create OPM_REMOTE_T struct, fill it with neccessary
|
|
* default values and return it to the client.
|
|
*
|
|
* Parameters:
|
|
* ip: IP of remote host
|
|
*
|
|
* Return:
|
|
* Address of OPM_REMOTE_T created
|
|
*
|
|
*/
|
|
|
|
OPM_REMOTE_T *opm_remote_create(const char *ip)
|
|
{
|
|
OPM_REMOTE_T *ret;
|
|
|
|
|
|
ret = MyMalloc(sizeof *ret);
|
|
|
|
/* Do initializations */
|
|
if(ip == NULL)
|
|
return NULL;
|
|
|
|
ret->ip = (char*) strdup(ip); /* replace with custom strdup function */
|
|
|
|
ret->port = 0;
|
|
ret->protocol = 0;
|
|
ret->bytes_read = 0;
|
|
|
|
ret->data = NULL;
|
|
|
|
ret->protocols = libopm_list_create(); /* setup protocol list */
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
/* opm_remote_free
|
|
*
|
|
* Free OPM_REMOTE_T struct and cleanup
|
|
*
|
|
* Parameters:
|
|
* remote: Struct to free
|
|
*
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
void opm_remote_free(OPM_REMOTE_T *remote)
|
|
{
|
|
|
|
OPM_NODE_T *p, *next;
|
|
OPM_PROTOCOL_CONFIG_T *ppc;
|
|
|
|
MyFree(remote->ip);
|
|
|
|
LIST_FOREACH_SAFE(p, next, remote->protocols->head)
|
|
{
|
|
ppc = (OPM_PROTOCOL_CONFIG_T *) p->data;
|
|
|
|
libopm_protocol_config_free(ppc);
|
|
libopm_list_remove(remote->protocols, p);
|
|
libopm_node_free(p);
|
|
}
|
|
|
|
libopm_list_free(remote->protocols);
|
|
|
|
MyFree(remote);
|
|
}
|
|
|
|
|
|
|
|
|
|
/* opm_callback
|
|
* Register scanner level callback
|
|
*
|
|
* Parameters
|
|
* scanner: scanner struct
|
|
* type: callback type
|
|
* Return:
|
|
* Error code
|
|
*/
|
|
|
|
OPM_ERR_T opm_callback(OPM_T *scanner, int type, OPM_CALLBACK_FUNC *function, void *data)
|
|
{
|
|
if(type < 0 || type >= (CBLEN + 1))
|
|
return OPM_ERR_CBNOTFOUND;
|
|
|
|
scanner->callbacks[type].func = function;
|
|
scanner->callbacks[type].data = data;
|
|
|
|
return OPM_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* opm_free
|
|
*
|
|
* Free OPM_T (scanner) and cleanup
|
|
*
|
|
* Parameters:
|
|
* scanner: Address of OPM_T to cleanup
|
|
*
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
void opm_free(OPM_T *scanner)
|
|
{
|
|
OPM_NODE_T *p, *next;
|
|
OPM_PROTOCOL_CONFIG_T *ppc;
|
|
OPM_SCAN_T *scan;
|
|
|
|
libopm_config_free(scanner->config);
|
|
|
|
LIST_FOREACH_SAFE(p, next, scanner->protocols->head)
|
|
{
|
|
ppc = (OPM_PROTOCOL_CONFIG_T *) p->data;
|
|
|
|
libopm_protocol_config_free(ppc);
|
|
libopm_list_remove(scanner->protocols, p);
|
|
libopm_node_free(p);
|
|
}
|
|
|
|
LIST_FOREACH_SAFE(p, next, scanner->scans->head)
|
|
{
|
|
scan = (OPM_SCAN_T *) p->data;
|
|
libopm_scan_free(scan);
|
|
libopm_list_remove(scanner->scans, p);
|
|
libopm_node_free(p);
|
|
}
|
|
|
|
LIST_FOREACH_SAFE(p, next, scanner->queue->head)
|
|
{
|
|
scan = (OPM_SCAN_T *) p->data;
|
|
libopm_scan_free(scan);
|
|
libopm_list_remove(scanner->queue, p);
|
|
libopm_node_free(p);
|
|
}
|
|
|
|
libopm_list_free(scanner->protocols);
|
|
libopm_list_free(scanner->scans);
|
|
libopm_list_free(scanner->queue);
|
|
|
|
MyFree(scanner->callbacks);
|
|
MyFree(scanner);
|
|
}
|
|
|
|
|
|
|
|
|
|
/* opm_config
|
|
*
|
|
* Wrapper to config_set. Set configuration variables
|
|
* on the config struct.
|
|
*
|
|
* Parameters:
|
|
* scanner: OPM_T struct the config struct resides in
|
|
* key: Variable within the config struct to set
|
|
* value: Address of value to set variable (key) to
|
|
*
|
|
* Return:
|
|
* OPM_ERR_T containing error code
|
|
*/
|
|
|
|
OPM_ERR_T opm_config(OPM_T *scanner, int key, void *value)
|
|
{
|
|
return libopm_config_set((scanner->config), key, value);
|
|
}
|
|
|
|
|
|
|
|
|
|
/* opm_addtype
|
|
*
|
|
* Add a proxy type and port to the list of protocols
|
|
* a scanner will use.
|
|
*
|
|
* Parameters:
|
|
* scanner: pointer to scanner struct
|
|
* type: type of proxy to scan (used in hashing to the functions)
|
|
* port: port this specific type/protocol will scan on
|
|
* Return:
|
|
* OPM_SUCCESS: Successful protocol add
|
|
* OPM_ERR_BADPROTOCOL: Protocol is unknown
|
|
*/
|
|
|
|
OPM_ERR_T opm_addtype(OPM_T *scanner, int type, unsigned short int port)
|
|
{
|
|
unsigned int i;
|
|
|
|
OPM_NODE_T *node;
|
|
OPM_PROTOCOL_CONFIG_T *protocol_config;
|
|
|
|
for(i = 0; i < sizeof(OPM_PROTOCOLS) / sizeof(OPM_PROTOCOL_T); i++)
|
|
{
|
|
if(type == OPM_PROTOCOLS[i].type)
|
|
{
|
|
protocol_config = libopm_protocol_config_create();
|
|
|
|
protocol_config->type = &OPM_PROTOCOLS[i];
|
|
protocol_config->port = port;
|
|
|
|
node = libopm_node_create(protocol_config);
|
|
libopm_list_add(scanner->protocols, node);
|
|
|
|
return OPM_SUCCESS;
|
|
|
|
}
|
|
}
|
|
return OPM_ERR_BADPROTOCOL;
|
|
}
|
|
|
|
|
|
|
|
/* opm_remote_addtype
|
|
*
|
|
* Add a proxy type and port to the list of protocols
|
|
* a scanner will use.
|
|
*
|
|
* Parameters:
|
|
* remote: pointer to scanner struct
|
|
* type: type of proxy to scan (used in hashing to the functions)
|
|
* port: port this specific type/protocol will scan on
|
|
* Return:
|
|
* OPM_SUCCESS: Successful protocol add
|
|
* OPM_ERR_BADPROTOCOL: Protocol is unknown
|
|
*/
|
|
|
|
OPM_ERR_T opm_remote_addtype(OPM_REMOTE_T *remote, int type, unsigned short int port)
|
|
{
|
|
unsigned int i;
|
|
|
|
OPM_NODE_T *node;
|
|
OPM_PROTOCOL_CONFIG_T *protocol_config;
|
|
|
|
for(i = 0; i < sizeof(OPM_PROTOCOLS) / sizeof(OPM_PROTOCOL_T); i++)
|
|
{
|
|
if(type == OPM_PROTOCOLS[i].type)
|
|
{
|
|
protocol_config = libopm_protocol_config_create();
|
|
|
|
protocol_config->type = &OPM_PROTOCOLS[i];
|
|
protocol_config->port = port;
|
|
|
|
node = libopm_node_create(protocol_config);
|
|
libopm_list_add(remote->protocols, node);
|
|
|
|
return OPM_SUCCESS;
|
|
}
|
|
}
|
|
return OPM_ERR_BADPROTOCOL;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* libopm_protocol_create
|
|
*
|
|
* Create OPM_PROTOCOL_T struct.
|
|
*
|
|
* Parameters:
|
|
* None
|
|
* Return:
|
|
* Pointer to new struct
|
|
*
|
|
* XXX - does not appear to be used anywhere?
|
|
* -grifferz
|
|
*/
|
|
|
|
#if 0
|
|
static OPM_PROTOCOL_T *libopm_protocol_create(void)
|
|
{
|
|
OPM_PROTOCOL_T *ret;
|
|
ret = MyMalloc(sizeof(OPM_PROTOCOL_T));
|
|
|
|
ret->type = 0;
|
|
ret->write_function = NULL;
|
|
ret->read_function = NULL;
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
|
|
/* libopm_protocol_free
|
|
*
|
|
* Free an OPM_PROTOCOL_T struct. Assume that if
|
|
* format is not NULL, it is pointed to dynamically
|
|
* allocated memory and free it.
|
|
*
|
|
* Parameters:
|
|
* protocol: struct to free
|
|
*
|
|
* Return:
|
|
* None
|
|
*
|
|
* XXX - apparently no longer used?
|
|
* -grifferz
|
|
*/
|
|
|
|
#if 0
|
|
static void libopm_protocol_free(OPM_PROTOCOL_T *protocol)
|
|
{
|
|
MyFree(protocol);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
/* libopm_protocol_config_create
|
|
*
|
|
* Allocate and return address of a new OPM_PROTOCOL_CONFIG_T
|
|
*
|
|
* Parameters:
|
|
* None
|
|
*
|
|
* Return:
|
|
* Address of new OPM_PROTOCOL_CONFIG_T
|
|
*/
|
|
|
|
static OPM_PROTOCOL_CONFIG_T *libopm_protocol_config_create(void)
|
|
{
|
|
OPM_PROTOCOL_CONFIG_T *ret;
|
|
ret = MyMalloc(sizeof *ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* protocol_config_free
|
|
*
|
|
* Free OPM_PROTOCOL_CONFIG_T struct
|
|
*
|
|
* Parameters:
|
|
* protocol: struct to free
|
|
*
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_protocol_config_free(OPM_PROTOCOL_CONFIG_T *protocol)
|
|
{
|
|
MyFree(protocol);
|
|
}
|
|
|
|
|
|
|
|
|
|
/* opm_scan
|
|
*
|
|
* Scan remote host. The opm_scan function takes an OPM_REMOTE_T
|
|
* struct, calculates the in_addr of the remote host, and creates
|
|
* a scan list based on protocols defined in the scanner.
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner to scan host on
|
|
* remote: OPM_REMOTE_T defining remote host
|
|
*
|
|
* Return:
|
|
* (to be written)
|
|
*/
|
|
|
|
OPM_ERR_T opm_scan(OPM_T *scanner, OPM_REMOTE_T *remote)
|
|
{
|
|
OPM_SCAN_T *scan; /* New scan for OPM_T */
|
|
OPM_NODE_T *node; /* Node we'll add scan to
|
|
when we link it to scans */
|
|
unsigned int fd_limit;
|
|
|
|
fd_limit = *(int *) libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT);
|
|
|
|
if(LIST_SIZE(scanner->protocols) == 0 &&
|
|
LIST_SIZE(remote->protocols) == 0)
|
|
{
|
|
return OPM_ERR_NOPROTOCOLS;
|
|
}
|
|
|
|
scan = libopm_scan_create(scanner, remote);
|
|
|
|
if(inet_pton(AF_INET, remote->ip, &(scan->addr.sa4.sin_addr) ) <= 0)
|
|
{
|
|
libopm_scan_free(scan);
|
|
return OPM_ERR_BADADDR;
|
|
}
|
|
|
|
node = libopm_node_create(scan);
|
|
libopm_list_add(scanner->queue, node);
|
|
|
|
return OPM_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* opm_end
|
|
*
|
|
* End a scan prematurely.
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner to end scan on
|
|
* remote: Pointer to remote struct to search for and end
|
|
*
|
|
* Return:
|
|
* No return. OPM_CALLBACK_END will still be called as normal.
|
|
*/
|
|
|
|
void opm_end(OPM_T *scanner, OPM_REMOTE_T *remote)
|
|
{
|
|
OPM_NODE_T *node1, *node2, *next1, *next2;
|
|
|
|
OPM_SCAN_T *scan;
|
|
OPM_CONNECTION_T *conn;
|
|
|
|
/* End active scans */
|
|
opm_endscan(scanner, remote);
|
|
|
|
/* Secondly remove all traces of it in the queue. Once removed we have to call
|
|
OPM_CALLBACK_END */
|
|
|
|
LIST_FOREACH_SAFE(node1, next1, scanner->queue->head)
|
|
{
|
|
scan = (OPM_SCAN_T *) node1->data;
|
|
if(scan->remote == remote)
|
|
{
|
|
/* Free all connections */
|
|
LIST_FOREACH_SAFE(node2, next2, scan->connections->head)
|
|
{
|
|
|
|
conn = (OPM_CONNECTION_T *) node2->data;
|
|
|
|
libopm_list_remove(scan->connections, node2);
|
|
libopm_connection_free(conn);
|
|
libopm_node_free(node2);
|
|
continue;
|
|
}
|
|
|
|
/* OPM_CALLBACK_END because check_closed normally handles this */
|
|
libopm_do_callback(scanner, scan->remote, OPM_CALLBACK_END, 0);
|
|
|
|
/* Free up the scan */
|
|
libopm_list_remove(scanner->queue, node1);
|
|
libopm_scan_free(scan);
|
|
libopm_node_free(node1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/* opm_endscan
|
|
*
|
|
* End a scan prematurely. Only end non-queued scans. This is useful
|
|
* because it only checks the active scan list (saving time), where
|
|
* opm_end checks both the scan and the possibly large queue.
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner to end scan on
|
|
* remote: Pointer to remote struct to search for and end
|
|
*
|
|
* Return:
|
|
* No return. OPM_CALLBACK_END will still be called as normal.
|
|
*/
|
|
|
|
void opm_endscan(OPM_T *scanner, OPM_REMOTE_T *remote)
|
|
{
|
|
OPM_NODE_T *node1, *node2;
|
|
|
|
OPM_SCAN_T *scan;
|
|
OPM_CONNECTION_T *conn;
|
|
|
|
/*
|
|
First check to see if it's in the queue, if it is set all connections closed
|
|
Next cycle of libopm_check_closed will take care of the garbage and handle
|
|
OPM_CALLBACK_END
|
|
*/
|
|
LIST_FOREACH(node1, scanner->scans->head)
|
|
{
|
|
scan = (OPM_SCAN_T *) node1->data;
|
|
|
|
if(scan->remote == remote)
|
|
{
|
|
LIST_FOREACH(node2, scan->connections->head)
|
|
{
|
|
conn = (OPM_CONNECTION_T *) node2->data;
|
|
conn->state = OPM_STATE_CLOSED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/* opm_active
|
|
|
|
Return number of scans in a scanner left.
|
|
|
|
Parameters:
|
|
scanner: Scanner to return active scans on
|
|
|
|
Return:
|
|
Number of active scans, both queued and active.
|
|
*/
|
|
|
|
size_t opm_active(OPM_T *scanner)
|
|
{
|
|
return LIST_SIZE(scanner->queue) + LIST_SIZE(scanner->scans);
|
|
}
|
|
|
|
|
|
|
|
/* scan_create
|
|
*
|
|
* Create new OPM_SCAN_T struct
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner the scan is being created for. This
|
|
* is needed to get information on currently set
|
|
* protocols/config.
|
|
*
|
|
* remote: Remote host this scan will be scanning
|
|
*
|
|
* Return
|
|
* Address of new struct
|
|
*/
|
|
static OPM_SCAN_T *libopm_scan_create(OPM_T *scanner, OPM_REMOTE_T *remote)
|
|
{
|
|
OPM_SCAN_T *ret;
|
|
OPM_CONNECTION_T *conn;
|
|
OPM_NODE_T *node, *p;
|
|
|
|
ret = MyMalloc(sizeof *ret);
|
|
|
|
ret->remote = remote;
|
|
ret->connections = libopm_list_create();
|
|
|
|
/* Setup list of connections, one for each protocol */
|
|
LIST_FOREACH(p, scanner->protocols->head)
|
|
{
|
|
conn = libopm_connection_create();
|
|
|
|
conn->protocol = ((OPM_PROTOCOL_CONFIG_T *) p->data)->type;
|
|
conn->port = ((OPM_PROTOCOL_CONFIG_T *) p->data)->port;
|
|
|
|
node = libopm_node_create(conn);
|
|
|
|
libopm_list_add(ret->connections, node);
|
|
}
|
|
|
|
/* Do the same for any specific protocols the remote struct might be configured
|
|
with */
|
|
|
|
LIST_FOREACH(p, remote->protocols->head)
|
|
{
|
|
conn = libopm_connection_create();
|
|
|
|
conn->protocol = ((OPM_PROTOCOL_CONFIG_T *) p->data)->type;
|
|
conn->port = ((OPM_PROTOCOL_CONFIG_T *) p->data)->port;
|
|
|
|
node = libopm_node_create(conn);
|
|
|
|
libopm_list_add(ret->connections, node);
|
|
}
|
|
|
|
memset(&(ret->addr), 0, sizeof(opm_sockaddr));
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* scan_free
|
|
*
|
|
* Free and cleanup OPM_SCAN_T struct
|
|
*
|
|
* Parametsr:
|
|
* scan: Scan struct to free
|
|
*
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_scan_free(OPM_SCAN_T *scan)
|
|
{
|
|
OPM_NODE_T *p, *next;
|
|
OPM_CONNECTION_T *conn;
|
|
|
|
LIST_FOREACH_SAFE(p, next, scan->connections->head)
|
|
{
|
|
conn = (OPM_CONNECTION_T *) p->data;
|
|
libopm_connection_free(conn);
|
|
|
|
libopm_list_remove(scan->connections, p);
|
|
libopm_node_free(p);
|
|
}
|
|
libopm_list_free(scan->connections);
|
|
|
|
MyFree(scan);
|
|
}
|
|
|
|
|
|
|
|
|
|
/* connection_create
|
|
*
|
|
* Allocate new OPM_CONNECTION_T
|
|
*
|
|
* Parameters:
|
|
* None
|
|
*
|
|
* Return:
|
|
* Address of new OPM_CONNECTION_T
|
|
*/
|
|
|
|
static OPM_CONNECTION_T *libopm_connection_create(void)
|
|
{
|
|
OPM_CONNECTION_T *ret;
|
|
ret = MyMalloc(sizeof *ret);
|
|
|
|
ret->fd = 0;
|
|
ret->bytes_read = 0;
|
|
ret->readlen = 0;
|
|
ret->protocol = 0;
|
|
ret->port = 0;
|
|
|
|
ret->state = OPM_STATE_UNESTABLISHED;
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* connection_free
|
|
*
|
|
* Free OPM_CONNECTION_T struct
|
|
*
|
|
* Parameters:
|
|
* conn: Address of struct to free
|
|
*
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_connection_free(OPM_CONNECTION_T *conn)
|
|
{
|
|
MyFree(conn);
|
|
}
|
|
|
|
|
|
/* opm_cycle
|
|
*
|
|
* Perform tasks (called by client's loop)
|
|
*
|
|
* Parameters:
|
|
* None
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
void opm_cycle(OPM_T *scanner)
|
|
{
|
|
libopm_check_queue(scanner); /* Move scans from the queue to the live scan list */
|
|
libopm_check_establish(scanner); /* Make new connections if possible */
|
|
libopm_check_poll(scanner); /* Poll connections for IO and proxy test */
|
|
libopm_check_closed(scanner); /* Check for closed or timed out connections */
|
|
}
|
|
|
|
|
|
|
|
|
|
/* check_queue
|
|
*
|
|
* Move scans from the queue to the live scan list as long as there is
|
|
* room.
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner to check queue on
|
|
*
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_check_queue(OPM_T *scanner)
|
|
{
|
|
OPM_NODE_T *node;
|
|
OPM_SCAN_T *scan;
|
|
|
|
unsigned int protocols, projected, fd_limit;
|
|
|
|
if(LIST_SIZE(scanner->queue) == 0)
|
|
return;
|
|
|
|
fd_limit = *(int *) libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT);
|
|
|
|
projected = scanner->fd_use;
|
|
|
|
/* We want to keep the live scan list as small as possible, so only
|
|
move queued scans to the live list if they will not push above fd_limit */
|
|
while(LIST_SIZE(scanner->queue) > 0)
|
|
{
|
|
|
|
/* Grab the top scan */
|
|
scan = (OPM_SCAN_T *) scanner->queue->head->data;
|
|
protocols = LIST_SIZE(scan->connections);
|
|
|
|
/* Check if it will fit in the live scan list */
|
|
if((protocols + projected) > fd_limit)
|
|
break;
|
|
|
|
/* Scans on the top of the queue were added first, swap the head off the
|
|
top of the queue and add it to the tail of the live scan list */
|
|
node = libopm_list_remove(scanner->queue, scanner->queue->head);
|
|
libopm_list_add(scanner->scans, node);
|
|
projected += protocols;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* check_establish
|
|
*
|
|
* Make new connections if there are free file descriptors and connections
|
|
* to be made.
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner to check for establish on
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_check_establish(OPM_T *scanner)
|
|
{
|
|
OPM_NODE_T *node1, *node2;
|
|
OPM_SCAN_T *scan;
|
|
OPM_CONNECTION_T *conn;
|
|
|
|
unsigned int fd_limit;
|
|
|
|
if(LIST_SIZE(scanner->scans) == 0)
|
|
return;
|
|
|
|
fd_limit = *(int *) libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT);
|
|
|
|
if(scanner->fd_use >= fd_limit)
|
|
return;
|
|
|
|
LIST_FOREACH(node1, scanner->scans->head)
|
|
{
|
|
scan = (OPM_SCAN_T *) node1->data;
|
|
LIST_FOREACH(node2, scan->connections->head)
|
|
{
|
|
/* Only scan if we have free file descriptors */
|
|
if(scanner->fd_use >= fd_limit)
|
|
return;
|
|
|
|
conn = (OPM_CONNECTION_T *) node2->data;
|
|
if(conn->state == OPM_STATE_UNESTABLISHED)
|
|
libopm_do_connect(scanner, scan, conn);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/* check_closed
|
|
*
|
|
* Check for connections which have timed out or are
|
|
* closed. Connections timed out still need to be closed.
|
|
*
|
|
* Remove the connection from the list of connections, free
|
|
* the connection struct and free the list node. Then if this is
|
|
* the last connection of the scan, consider the scan completed and
|
|
* free the scan aswell (and callback that the scan ended).
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner to check on
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_check_closed(OPM_T *scanner)
|
|
{
|
|
|
|
time_t present;
|
|
OPM_NODE_T *node1, *node2, *next1, *next2;
|
|
int timeout;
|
|
|
|
OPM_SCAN_T *scan;
|
|
OPM_CONNECTION_T *conn;
|
|
|
|
if(LIST_SIZE(scanner->scans) == 0)
|
|
return;
|
|
|
|
time(&present);
|
|
|
|
timeout = *(int *) libopm_config(scanner->config, OPM_CONFIG_TIMEOUT);
|
|
|
|
LIST_FOREACH_SAFE(node1, next1, scanner->scans->head)
|
|
{
|
|
scan = (OPM_SCAN_T *) node1->data;
|
|
LIST_FOREACH_SAFE(node2, next2, scan->connections->head)
|
|
{
|
|
|
|
conn = (OPM_CONNECTION_T *) node2->data;
|
|
|
|
if(conn->state == OPM_STATE_CLOSED)
|
|
{
|
|
if(conn->fd > 0)
|
|
close(conn->fd);
|
|
|
|
scanner->fd_use--;
|
|
|
|
libopm_list_remove(scan->connections, node2);
|
|
libopm_connection_free(conn);
|
|
libopm_node_free(node2);
|
|
continue;
|
|
}
|
|
|
|
if(((present - conn->creation) >= timeout) &&
|
|
conn->state != OPM_STATE_UNESTABLISHED)
|
|
{
|
|
|
|
close(conn->fd);
|
|
scanner->fd_use--;
|
|
|
|
libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_TIMEOUT, 0);
|
|
|
|
libopm_list_remove(scan->connections, node2);
|
|
libopm_connection_free(conn);
|
|
libopm_node_free(node2);
|
|
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* No more connections left in this scan, let the
|
|
client know the scan has ended, then remove the
|
|
scan from the scanner, and free it up */
|
|
if(LIST_SIZE(scan->connections) == 0)
|
|
{
|
|
libopm_do_callback(scanner, scan->remote, OPM_CALLBACK_END, 0);
|
|
|
|
libopm_list_remove(scanner->scans, node1);
|
|
libopm_scan_free(scan);
|
|
libopm_node_free(node1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/* do_connect
|
|
*
|
|
* Call socket() and connect() to start a scan.
|
|
*
|
|
* Parametsr:
|
|
* scan: Scan struct containing the connection
|
|
* conn: Connection to establish
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_do_connect(OPM_T * scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
|
|
{
|
|
opm_sockaddr *bind_ip;
|
|
|
|
struct sockaddr_in *addr; /* Outgoing host */
|
|
struct sockaddr_in local_addr; /* For binding */
|
|
|
|
addr = (struct sockaddr_in *) &(scan->addr.sa4); /* Already have the IP in byte format from opm_scan */
|
|
|
|
addr->sin_family = AF_INET;
|
|
addr->sin_port = htons(conn->port);
|
|
|
|
|
|
bind_ip = (opm_sockaddr *) libopm_config(scanner->config, OPM_CONFIG_BIND_IP);
|
|
|
|
conn->fd = socket(PF_INET, SOCK_STREAM, 0);
|
|
scanner->fd_use++; /* Increase file descriptor use */
|
|
|
|
if(conn->fd == -1)
|
|
{
|
|
libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_ERROR, OPM_ERR_NOFD);
|
|
conn->state = OPM_STATE_CLOSED;
|
|
return;
|
|
}
|
|
|
|
if(bind_ip != NULL)
|
|
{
|
|
memset(&local_addr, 0, sizeof(local_addr));
|
|
local_addr.sin_addr.s_addr = bind_ip->sa4.sin_addr.s_addr;
|
|
local_addr.sin_family = AF_INET;
|
|
local_addr.sin_port = htons(0);
|
|
|
|
if(bind(conn->fd, (struct sockaddr *) &(local_addr), sizeof(local_addr)) == -1)
|
|
{
|
|
libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_ERROR, OPM_ERR_BIND);
|
|
conn->state = OPM_STATE_CLOSED;
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Set socket non blocking */
|
|
fcntl(conn->fd, F_SETFL, O_NONBLOCK);
|
|
|
|
connect(conn->fd, (struct sockaddr *) addr, sizeof(*addr));
|
|
|
|
conn->state = OPM_STATE_ESTABLISHED;
|
|
time(&(conn->creation)); /* Stamp creation time, for timeout */
|
|
}
|
|
|
|
|
|
/* check_poll
|
|
*
|
|
* Check sockets for ready read/write
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner to isolate check on
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_check_poll(OPM_T *scanner)
|
|
{
|
|
OPM_NODE_T *node1, *node2;
|
|
OPM_SCAN_T *scan;
|
|
OPM_CONNECTION_T *conn;
|
|
|
|
static unsigned int ufds_size;
|
|
static struct pollfd *ufds = NULL;
|
|
|
|
unsigned int size, i;
|
|
size = 0;
|
|
|
|
/* Grow pollfd array (ufds) as needed */
|
|
if(ufds_size < (*(unsigned int *) libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT)))
|
|
{
|
|
MyFree(ufds);
|
|
ufds = MyMalloc((sizeof *ufds) * (*(unsigned int *) libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT)));
|
|
ufds_size = (*(unsigned int *) libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT));
|
|
}
|
|
|
|
if(LIST_SIZE(scanner->scans) == 0)
|
|
return;
|
|
|
|
LIST_FOREACH(node1, scanner->scans->head)
|
|
{
|
|
scan = (OPM_SCAN_T *) node1->data;
|
|
LIST_FOREACH(node2, scan->connections->head)
|
|
{
|
|
if(size >= ufds_size)
|
|
break;
|
|
|
|
conn = (OPM_CONNECTION_T *) node2->data;
|
|
|
|
if(conn->state < OPM_STATE_ESTABLISHED ||
|
|
conn->state == OPM_STATE_CLOSED)
|
|
continue;
|
|
|
|
ufds[size].events = 0;
|
|
ufds[size].revents = 0;
|
|
ufds[size].fd = conn->fd;
|
|
|
|
/* Check for HUNG UP. */
|
|
ufds[size].events |= POLLHUP;
|
|
/* Check for INVALID FD */
|
|
ufds[size].events |= POLLNVAL;
|
|
|
|
switch(conn->state)
|
|
{
|
|
case OPM_STATE_ESTABLISHED:
|
|
ufds[size].events |= POLLOUT;
|
|
break;
|
|
case OPM_STATE_NEGSENT:
|
|
ufds[size].events |= POLLIN;
|
|
break;
|
|
}
|
|
size++;
|
|
}
|
|
|
|
}
|
|
|
|
switch (poll(ufds, size, 0))
|
|
{
|
|
case -1:
|
|
/* error in select/poll */
|
|
return;
|
|
case 0:
|
|
/* Nothing to do */
|
|
return;
|
|
/* Pass pointer to connection to handler. */
|
|
}
|
|
|
|
LIST_FOREACH(node1, scanner->scans->head)
|
|
{
|
|
scan = (OPM_SCAN_T *) node1->data;
|
|
|
|
LIST_FOREACH(node2, scan->connections->head)
|
|
{
|
|
conn = (OPM_CONNECTION_T *) node2->data;
|
|
|
|
for(i = 0; i < size; i++)
|
|
{
|
|
if((ufds[i].fd == conn->fd) && (conn->state != OPM_STATE_CLOSED))
|
|
{
|
|
if(ufds[i].revents & POLLIN)
|
|
libopm_do_readready(scanner, scan, conn);
|
|
if(ufds[i].revents & POLLOUT)
|
|
libopm_do_writeready(scanner, scan, conn);
|
|
if(ufds[i].revents & POLLHUP)
|
|
libopm_do_hup(scanner, scan, conn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* before_poll
|
|
*
|
|
* external select/poll routine to setup our fd checks
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner to isolate check on
|
|
* Return:
|
|
* pollfds struct.
|
|
*/
|
|
|
|
int libopm_before_poll(OPM_T *scanner, pollfd *ufds)
|
|
{
|
|
OPM_NODE_T *node1, *node2;
|
|
OPM_SCAN_T *scan;
|
|
OPM_CONNECTION_T *conn;
|
|
unsigned int maxsize, size;
|
|
|
|
size = 0;
|
|
libopm_check_closed(scanner); /* Check for closed or timed out connections */
|
|
libopm_check_queue(scanner); /* Move scans from the queue to the live scan list */
|
|
libopm_check_establish(scanner); /* Make new connections if possible */
|
|
|
|
|
|
/* ufds = MyMalloc((sizeof *ufds) * (*(unsigned int *) libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT))); */
|
|
maxsize = (*(unsigned int *) libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT));
|
|
|
|
if(LIST_SIZE(scanner->scans) == 0)
|
|
return -1;
|
|
|
|
LIST_FOREACH(node1, scanner->scans->head)
|
|
{
|
|
scan = (OPM_SCAN_T *) node1->data;
|
|
LIST_FOREACH(node2, scan->connections->head)
|
|
{
|
|
if(size >= maxsize)
|
|
break;
|
|
|
|
conn = (OPM_CONNECTION_T *) node2->data;
|
|
|
|
if(conn->state < OPM_STATE_ESTABLISHED ||
|
|
conn->state == OPM_STATE_CLOSED)
|
|
continue;
|
|
|
|
ufds[size].events = 0;
|
|
ufds[size].revents = 0;
|
|
ufds[size].fd = conn->fd;
|
|
|
|
/* Check for HUNG UP. */
|
|
ufds[size].events |= POLLHUP;
|
|
/* Check for INVALID FD */
|
|
ufds[size].events |= POLLNVAL;
|
|
|
|
switch(conn->state)
|
|
{
|
|
case OPM_STATE_ESTABLISHED:
|
|
ufds[size].events |= POLLOUT;
|
|
break;
|
|
case OPM_STATE_NEGSENT:
|
|
ufds[size].events |= POLLIN;
|
|
break;
|
|
}
|
|
size++;
|
|
}
|
|
|
|
}
|
|
return size;
|
|
}
|
|
/* after_poll
|
|
*
|
|
* external select/poll routine to check what our fd check
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner to isolate check on
|
|
* Return:
|
|
* pollfds struct.
|
|
*/
|
|
|
|
void libopm_after_poll(OPM_T *scanner, pollfd *ufds, unsigned int ufdssize)
|
|
{
|
|
OPM_NODE_T *node1, *node2;
|
|
OPM_SCAN_T *scan;
|
|
OPM_CONNECTION_T *conn;
|
|
|
|
int i;
|
|
if (opm_active(scanner) < 1) {
|
|
return;
|
|
}
|
|
LIST_FOREACH(node1, scanner->scans->head)
|
|
{
|
|
scan = (OPM_SCAN_T *) node1->data;
|
|
|
|
LIST_FOREACH(node2, scan->connections->head)
|
|
{
|
|
conn = (OPM_CONNECTION_T *) node2->data;
|
|
|
|
for(i = 0; i < (int)ufdssize; i++)
|
|
{
|
|
if((ufds[i].fd == conn->fd) && (conn->state != OPM_STATE_CLOSED))
|
|
{
|
|
if(ufds[i].revents & POLLIN)
|
|
libopm_do_readready(scanner, scan, conn);
|
|
if(ufds[i].revents & POLLOUT)
|
|
libopm_do_writeready(scanner, scan, conn);
|
|
if(ufds[i].revents & POLLHUP)
|
|
libopm_do_hup(scanner, scan, conn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do_readready
|
|
*
|
|
* Remote connection is read ready, read the data into a buffer and check it against
|
|
* the target_string if neccessary
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner doing the scan
|
|
* scan: Specific scan
|
|
* conn: Specific connection in the scan
|
|
*
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_do_readready(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
|
|
{
|
|
|
|
int max_read;
|
|
char c;
|
|
|
|
/* If protocol has a specific read function, call that instead of
|
|
reading data from here. */
|
|
if(conn->protocol->read_function)
|
|
{
|
|
conn->protocol->read_function(scanner, scan, conn);
|
|
return;
|
|
}
|
|
|
|
max_read = *(int *) libopm_config(scanner->config, OPM_CONFIG_MAX_READ);
|
|
|
|
while(1)
|
|
{
|
|
switch (read(conn->fd, &c, 1))
|
|
{
|
|
case 0:
|
|
libopm_do_hup(scanner, scan, conn);
|
|
return;
|
|
|
|
case -1:
|
|
if(errno != EAGAIN)
|
|
libopm_do_hup(scanner, scan, conn);
|
|
return;
|
|
|
|
default:
|
|
|
|
conn->bytes_read++;
|
|
|
|
if(conn->bytes_read >= max_read)
|
|
{
|
|
libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_ERROR, OPM_ERR_MAX_READ);
|
|
conn->state = OPM_STATE_CLOSED;
|
|
return;
|
|
}
|
|
|
|
if(c == '\0' || c == '\r')
|
|
continue;
|
|
|
|
if(c == '\n')
|
|
{
|
|
conn->readbuf[conn->readlen] = '\0';
|
|
conn->readlen = 0;
|
|
libopm_do_read(scanner, scan, conn);
|
|
|
|
if(conn->state == OPM_STATE_CLOSED)
|
|
return;
|
|
|
|
continue;
|
|
}
|
|
|
|
if(conn->readlen < READBUFLEN)
|
|
{ /* -1 to pad for null term */
|
|
conn->readbuf[++(conn->readlen) - 1] = c;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/* do_read
|
|
*
|
|
* A line of data has been read from the socket, check it against
|
|
* target string.
|
|
*
|
|
*
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner doing the scan
|
|
* scan: Specific scan
|
|
* conn: Specific connection in the scan
|
|
*
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_do_read(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
|
|
{
|
|
OPM_LIST_T *list;
|
|
OPM_NODE_T *node;
|
|
char *target_string;
|
|
|
|
/* Check readbuf against target strings */
|
|
list = (OPM_LIST_T *) libopm_config(scanner->config, OPM_CONFIG_TARGET_STRING);
|
|
LIST_FOREACH(node, list->head)
|
|
{
|
|
target_string = (char *) node->data;
|
|
if(strstr(conn->readbuf, target_string))
|
|
{
|
|
libopm_do_openproxy(scanner, scan, conn);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* do_openproxy
|
|
*
|
|
* An open proxy was found on connection conn. Cleanup the connection and
|
|
* call the appropriate callback to let the client know the proxy was found.
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner doing the scan
|
|
* scan: Specific scan
|
|
* conn: Specific connection in the scan
|
|
*
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_do_openproxy(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
|
|
{
|
|
OPM_REMOTE_T *remote;
|
|
|
|
remote = scan->remote;
|
|
|
|
/* Mark the connection for close */
|
|
conn->state = OPM_STATE_CLOSED;
|
|
|
|
/* Call client's open proxy callback */
|
|
libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_OPENPROXY, 0);
|
|
}
|
|
|
|
|
|
|
|
|
|
/* do_writeready
|
|
*
|
|
* Remote connection is write ready, call the specific protocol
|
|
* function for writing to this socket.
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner doing the scan
|
|
* scan: Specific scan
|
|
* conn: Specific connection in the scan
|
|
*
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_do_writeready(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
|
|
{
|
|
OPM_PROTOCOL_T *protocol;
|
|
|
|
protocol = conn->protocol;
|
|
|
|
/* Call write function for specific protocol */
|
|
if(protocol->write_function)
|
|
protocol->write_function(scanner, scan, conn);
|
|
|
|
/* Flag as NEGSENT so we don't have to send data again*/
|
|
conn->state = OPM_STATE_NEGSENT;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* do_hup
|
|
*
|
|
* Connection ended prematurely
|
|
*
|
|
* Parameters:
|
|
* scanner: Scanner doing the scan
|
|
* scan: Specific scan
|
|
* conn: Specific connection in the scan
|
|
* error: OPM_ERR_T containing the error type
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_do_hup(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
|
|
{
|
|
OPM_REMOTE_T *remote;
|
|
|
|
remote = scan->remote;
|
|
|
|
/* Mark the connection for close */
|
|
conn->state = OPM_STATE_CLOSED;
|
|
|
|
libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_NEGFAIL, 0);
|
|
}
|
|
|
|
|
|
|
|
|
|
/* do_callback
|
|
*
|
|
* Call callback
|
|
*
|
|
* Parameters:
|
|
* scanner: scanner remote is on
|
|
* remote: remote callback is for
|
|
* type: callback type
|
|
* var: optional var passed back (error codes, etc )
|
|
* Return:
|
|
* None
|
|
*/
|
|
|
|
static void libopm_do_callback(OPM_T *scanner, OPM_REMOTE_T *remote, int type, int var)
|
|
{
|
|
/* Callback is out of range */
|
|
if(type < 0 || type >= (CBLEN + 1))
|
|
return;
|
|
|
|
if(scanner->callbacks[type].func)
|
|
(scanner->callbacks[type].func) (scanner, remote, var, scanner->callbacks[type].data);
|
|
}
|
|
|
|
|
|
|
|
|
|
/* setup_remote
|
|
*
|
|
* Setup an OPM_REMOTE_T with information from an OPM_CONNECTION_T
|
|
* for callback
|
|
*
|
|
* Parameters:
|
|
* remote, conn
|
|
*
|
|
* Return:
|
|
* remote
|
|
*/
|
|
|
|
static OPM_REMOTE_T *libopm_setup_remote(OPM_REMOTE_T *remote, OPM_CONNECTION_T *conn)
|
|
{
|
|
remote->port = conn->port;
|
|
remote->bytes_read = conn->bytes_read;
|
|
remote->protocol = conn->protocol->type;
|
|
|
|
return remote;
|
|
}
|