ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/branches/1.1.x/src/libopm/src/libopm.c
Revision: 9996
Committed: Thu Jun 17 18:43:18 2021 UTC (2 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 32591 byte(s)
Log Message:
- config.c, libopm.c: remove redundant 'p->addr.ss_family = res->ai_family' assignments

File Contents

# User Rev Content
1 michael 5052 /*
2     * Copyright (C) 2002-2003 Erik Fears
3     *
4     * This program is free software; you can redistribute it and/or
5     * modify it under the terms of the GNU General Public License
6     * as published by the Free Software Foundation; either version 2
7     * of the License, or (at your option) any later version.
8     *
9     * This program is distributed in the hope that it will be useful,
10     * but WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     * GNU General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with this program; if not, write to
16     *
17     * The Free Software Foundation, Inc.
18     * 59 Temple Place - Suite 330
19     * Boston, MA 02111-1307, USA.
20     *
21 michael 5909 *
22 michael 5052 */
23    
24     #include "setup.h"
25    
26 michael 8202 #include <errno.h>
27     #include <time.h>
28     #include <unistd.h>
29     #include <fcntl.h>
30     #include <string.h>
31     #include <stdlib.h>
32 michael 9530 #include <assert.h>
33 michael 8202 #include <poll.h>
34     #ifdef HAVE_LIBCRYPTO
35     #include <openssl/ssl.h>
36     #endif
37 michael 9530 #include <sys/types.h>
38     #include <sys/socket.h>
39     #include <netdb.h>
40 michael 8202
41 michael 5052 #include "config.h"
42     #include "libopm.h"
43 michael 5947 #include "memory.h"
44 michael 5052 #include "opm_error.h"
45     #include "opm_types.h"
46     #include "opm_common.h"
47 michael 9861 #include "opm_gettime.h"
48 michael 5052 #include "list.h"
49     #include "proxy.h"
50    
51    
52     static OPM_PROTOCOL_CONFIG_T *libopm_protocol_config_create(void);
53     static void libopm_protocol_config_free(OPM_PROTOCOL_CONFIG_T *);
54    
55     static OPM_SCAN_T *libopm_scan_create(OPM_T *, OPM_REMOTE_T *);
56     static void libopm_scan_free(OPM_SCAN_T *);
57    
58     static OPM_CONNECTION_T *libopm_connection_create(void);
59     static void libopm_connection_free(OPM_CONNECTION_T *);
60    
61     static void libopm_check_establish(OPM_T *);
62     static void libopm_check_poll(OPM_T *);
63     static void libopm_check_closed(OPM_T *);
64     static void libopm_check_queue(OPM_T *);
65    
66     static void libopm_do_connect(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
67     static void libopm_do_readready(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
68 michael 6222 static int libopm_do_readready_tls(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
69 michael 5052 static void libopm_do_writeready(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
70     static void libopm_do_hup(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
71     static void libopm_do_read(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
72     static void libopm_do_openproxy(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
73     static void libopm_do_callback(OPM_T *, OPM_REMOTE_T *, int, int);
74    
75     static OPM_REMOTE_T *libopm_setup_remote(OPM_REMOTE_T *, OPM_CONNECTION_T *);
76    
77    
78     /* OPM_PROTOCOLS hash
79     *
80     * OPM_PPROTOCOLS hashes the protocol types (int) to functions
81     * which handle the protocol (sending/receiving protocol specific
82     * data).
83     *
84     */
85 michael 5325 static OPM_PROTOCOL_T OPM_PROTOCOLS[] =
86     {
87 michael 6222 { OPM_TYPE_HTTP, libopm_proxy_http_write, NULL, 0 },
88     { OPM_TYPE_SOCKS4, libopm_proxy_socks4_write, NULL, 0 },
89     { OPM_TYPE_SOCKS5, libopm_proxy_socks5_write, NULL, 0 },
90     { OPM_TYPE_ROUTER, libopm_proxy_router_write, NULL, 0 },
91     { OPM_TYPE_WINGATE, libopm_proxy_wingate_write, NULL, 0 },
92     { OPM_TYPE_HTTPPOST, libopm_proxy_httppost_write, NULL, 0 },
93     { OPM_TYPE_DREAMBOX, libopm_proxy_dreambox_write, NULL, 0 },
94     { OPM_TYPE_HTTPS, libopm_proxy_https_write, libopm_do_readready_tls, 1 },
95 michael 8565 { OPM_TYPE_HTTPSPOST, libopm_proxy_httpspost_write, libopm_do_readready_tls, 1 },
96     { OPM_TYPE_SSH, NULL, NULL, 0 }
97 michael 5052 };
98    
99     /* opm_create
100     *
101     * Initialize a new scanner and return a pointer to it.
102     *
103     * Parameters:
104     * None
105 michael 5325 *
106     * Return
107 michael 5052 * Pointer to new OPM_T (scanner)
108     */
109 michael 5325 OPM_T *
110     opm_create(void)
111 michael 5052 {
112 michael 5325 OPM_T *ret;
113 michael 5052
114 michael 8206 ret = libopm_calloc(sizeof(*ret));
115 michael 5325 ret->config = libopm_config_create();
116 michael 5052
117 michael 5325 /* Setup callbacks */
118 michael 8206 ret->callbacks = libopm_calloc(sizeof(OPM_CALLBACK_T) * CBLEN);
119 michael 5052
120 michael 5325 return ret;
121 michael 5052 }
122    
123     /* opm_remote_create
124     *
125     * Create OPM_REMOTE_T struct, fill it with neccessary
126     * default values and return it to the client.
127     *
128     * Parameters:
129     * ip: IP of remote host
130     *
131     * Return:
132     * Address of OPM_REMOTE_T created
133     *
134     */
135 michael 5325 OPM_REMOTE_T *
136     opm_remote_create(const char *ip)
137     {
138     OPM_REMOTE_T *ret;
139 michael 5052
140 michael 8206 ret = libopm_calloc(sizeof(*ret));
141     ret->ip = libopm_strdup(ip);
142 michael 5094
143 michael 5325 return ret;
144 michael 5052 }
145    
146     /* opm_remote_free
147     *
148     * Free OPM_REMOTE_T struct and cleanup
149     *
150     * Parameters:
151     * remote: Struct to free
152     *
153     * Return:
154     * None
155     */
156 michael 5325 void
157     opm_remote_free(OPM_REMOTE_T *remote)
158 michael 5052 {
159 michael 5325 OPM_NODE_T *p, *next;
160     OPM_PROTOCOL_CONFIG_T *ppc;
161 michael 5052
162 michael 8206 libopm_free(remote->ip);
163 michael 5052
164 michael 8580 LIST_FOREACH_SAFE(p, next, remote->protocols.head)
165 michael 5325 {
166     ppc = p->data;
167 michael 5052
168 michael 5325 libopm_protocol_config_free(ppc);
169 michael 8580 libopm_list_remove(&remote->protocols, p);
170 michael 5325 libopm_node_free(p);
171     }
172 michael 5052
173 michael 8206 libopm_free(remote);
174 michael 5052 }
175    
176     /* opm_callback
177     * Register scanner level callback
178     *
179     * Parameters
180     * scanner: scanner struct
181     * type: callback type
182     * Return:
183     * Error code
184     */
185    
186 michael 5325 OPM_ERR_T
187     opm_callback(OPM_T *scanner, int type, OPM_CALLBACK_FUNC *function, void *data)
188 michael 5052 {
189 michael 5673 if (type < 0 || type >= CBLEN)
190 michael 5325 return OPM_ERR_CBNOTFOUND;
191 michael 5052
192 michael 5325 scanner->callbacks[type].func = function;
193     scanner->callbacks[type].data = data;
194 michael 5052
195 michael 5325 return OPM_SUCCESS;
196 michael 5052 }
197    
198     /* opm_free
199     *
200     * Free OPM_T (scanner) and cleanup
201     *
202     * Parameters:
203     * scanner: Address of OPM_T to cleanup
204     *
205     * Return:
206     * None
207     */
208 michael 5325 void
209     opm_free(OPM_T *scanner)
210 michael 5052 {
211 michael 5325 OPM_NODE_T *p, *next;
212     OPM_PROTOCOL_CONFIG_T *ppc;
213     OPM_SCAN_T *scan;
214 michael 5052
215 michael 5325 libopm_config_free(scanner->config);
216 michael 5052
217 michael 8580 LIST_FOREACH_SAFE(p, next, scanner->protocols.head)
218 michael 5325 {
219     ppc = p->data;
220 michael 5052
221 michael 5325 libopm_protocol_config_free(ppc);
222 michael 8580 libopm_list_remove(&scanner->protocols, p);
223 michael 5325 libopm_node_free(p);
224     }
225 michael 5052
226 michael 8580 LIST_FOREACH_SAFE(p, next, scanner->scans.head)
227 michael 5325 {
228     scan = p->data;
229 michael 5052
230 michael 5325 libopm_scan_free(scan);
231 michael 8580 libopm_list_remove(&scanner->scans, p);
232 michael 5325 libopm_node_free(p);
233     }
234 michael 5052
235 michael 8580 LIST_FOREACH_SAFE(p, next, scanner->queue.head)
236 michael 5325 {
237     scan = p->data;
238 michael 5052
239 michael 5325 libopm_scan_free(scan);
240 michael 8580 libopm_list_remove(&scanner->queue, p);
241 michael 5325 libopm_node_free(p);
242     }
243 michael 5052
244 michael 8206 libopm_free(scanner->callbacks);
245     libopm_free(scanner);
246 michael 5325 }
247 michael 5052
248     /* opm_config
249     *
250     * Wrapper to config_set. Set configuration variables
251     * on the config struct.
252     *
253     * Parameters:
254     * scanner: OPM_T struct the config struct resides in
255     * key: Variable within the config struct to set
256     * value: Address of value to set variable (key) to
257     *
258     * Return:
259     * OPM_ERR_T containing error code
260     */
261 michael 5325 OPM_ERR_T
262     opm_config(OPM_T *scanner, int key, const void *value)
263 michael 5052 {
264 michael 6076 return libopm_config_set(scanner->config, key, value);
265 michael 5052 }
266    
267     /* opm_addtype
268     *
269 michael 5325 * Add a proxy type and port to the list of protocols
270 michael 5052 * a scanner will use.
271 michael 5325 *
272 michael 5052 * Parameters:
273     * scanner: pointer to scanner struct
274     * type: type of proxy to scan (used in hashing to the functions)
275     * port: port this specific type/protocol will scan on
276     * Return:
277     * OPM_SUCCESS: Successful protocol add
278     * OPM_ERR_BADPROTOCOL: Protocol is unknown
279     */
280 michael 5325 OPM_ERR_T
281     opm_addtype(OPM_T *scanner, int type, unsigned short int port)
282 michael 5052 {
283 michael 5325 OPM_NODE_T *node;
284     OPM_PROTOCOL_CONFIG_T *protocol_config;
285 michael 5052
286 michael 5671 for (unsigned int i = 0; i < sizeof(OPM_PROTOCOLS) / sizeof(OPM_PROTOCOL_T); ++i)
287 michael 5325 {
288     if (type == OPM_PROTOCOLS[i].type)
289     {
290 michael 6222 #ifndef HAVE_LIBCRYPTO
291     if (OPM_PROTOCOLS[i].use_tls)
292     return OPM_ERR_BADPROTOCOL;
293     #endif
294 michael 5325 protocol_config = libopm_protocol_config_create();
295     protocol_config->type = &OPM_PROTOCOLS[i];
296     protocol_config->port = port;
297 michael 5052
298 michael 5325 node = libopm_node_create(protocol_config);
299 michael 8580 libopm_list_add(&scanner->protocols, node);
300 michael 5052
301 michael 5325 return OPM_SUCCESS;
302     }
303     }
304 michael 5052
305 michael 5325 return OPM_ERR_BADPROTOCOL;
306 michael 5052 }
307    
308     /* opm_remote_addtype
309     *
310     * Add a proxy type and port to the list of protocols
311     * a scanner will use.
312     *
313     * Parameters:
314     * remote: pointer to scanner struct
315     * type: type of proxy to scan (used in hashing to the functions)
316     * port: port this specific type/protocol will scan on
317     * Return:
318     * OPM_SUCCESS: Successful protocol add
319     * OPM_ERR_BADPROTOCOL: Protocol is unknown
320     */
321     OPM_ERR_T opm_remote_addtype(OPM_REMOTE_T *remote, int type, unsigned short int port)
322     {
323 michael 5325 OPM_NODE_T *node;
324     OPM_PROTOCOL_CONFIG_T *protocol_config;
325 michael 5052
326 michael 5671 for (unsigned int i = 0; i < sizeof(OPM_PROTOCOLS) / sizeof(OPM_PROTOCOL_T); ++i)
327 michael 5325 {
328     if (type == OPM_PROTOCOLS[i].type)
329     {
330 michael 6222 #ifndef HAVE_LIBCRYPTO
331     if (OPM_PROTOCOLS[i].use_tls)
332     return OPM_ERR_BADPROTOCOL;
333     #endif
334 michael 5325 protocol_config = libopm_protocol_config_create();
335     protocol_config->type = &OPM_PROTOCOLS[i];
336     protocol_config->port = port;
337 michael 5052
338 michael 5325 node = libopm_node_create(protocol_config);
339 michael 8580 libopm_list_add(&remote->protocols, node);
340 michael 5052
341 michael 5325 return OPM_SUCCESS;
342     }
343     }
344 michael 5052
345 michael 5325 return OPM_ERR_BADPROTOCOL;
346 michael 5052 }
347    
348     /* libopm_protocol_config_create
349     *
350     * Allocate and return address of a new OPM_PROTOCOL_CONFIG_T
351     *
352     * Parameters:
353     * None
354     *
355     * Return:
356     * Address of new OPM_PROTOCOL_CONFIG_T
357     */
358 michael 5325 static OPM_PROTOCOL_CONFIG_T *
359     libopm_protocol_config_create(void)
360 michael 5052 {
361 michael 5325 OPM_PROTOCOL_CONFIG_T *ret;
362 michael 5671
363 michael 8206 ret = libopm_calloc(sizeof(*ret));
364 michael 5052
365 michael 5325 return ret;
366 michael 5052 }
367    
368     /* protocol_config_free
369     *
370     * Free OPM_PROTOCOL_CONFIG_T struct
371     *
372     * Parameters:
373     * protocol: struct to free
374     *
375     * Return:
376     * None
377     */
378 michael 5325 static void
379     libopm_protocol_config_free(OPM_PROTOCOL_CONFIG_T *protocol)
380 michael 5052 {
381 michael 8206 libopm_free(protocol);
382 michael 5052 }
383    
384     /* opm_scan
385     *
386     * Scan remote host. The opm_scan function takes an OPM_REMOTE_T
387     * struct, calculates the in_addr of the remote host, and creates
388     * a scan list based on protocols defined in the scanner.
389     *
390     * Parameters:
391     * scanner: Scanner to scan host on
392     * remote: OPM_REMOTE_T defining remote host
393 michael 5325 *
394 michael 5052 * Return:
395     * (to be written)
396     */
397 michael 5325 OPM_ERR_T
398     opm_scan(OPM_T *scanner, OPM_REMOTE_T *remote)
399 michael 5052 {
400 michael 5325 OPM_NODE_T *node; /* Node we'll add scan to when we link it to scans */
401 michael 9530 struct addrinfo hints, *res;
402 michael 5052
403 michael 8580 if (LIST_SIZE(&scanner->protocols) == 0 &&
404     LIST_SIZE(&remote->protocols) == 0)
405 michael 5325 return OPM_ERR_NOPROTOCOLS;
406 michael 5052
407 michael 9530 memset(&hints, 0, sizeof(hints));
408    
409     hints.ai_family = AF_UNSPEC;
410     hints.ai_socktype = SOCK_STREAM;
411     hints.ai_flags = AI_NUMERICHOST;
412    
413 michael 8127 /*
414     * XXX: libopm ideally shouldn't see an IP address in string representation.
415     * Could have been stuffed into the _OPM_REMOTE struct by the caller that
416     * already does getaddrinfo() anyway.
417     */
418 michael 9530 if (getaddrinfo(remote->ip, NULL, &hints, &res) || res->ai_family != AF_INET) /* XXX: only do v4 for now */
419     {
420 michael 9538 if (res)
421     freeaddrinfo(res);
422    
423 michael 8127 return OPM_ERR_BADADDR;
424 michael 9530 }
425 michael 8127
426 michael 9538 OPM_SCAN_T *scan = libopm_scan_create(scanner, remote);
427 michael 5052
428 michael 9538 memcpy(&scan->addr, res->ai_addr, res->ai_addrlen);
429     scan->addr_len = res->ai_addrlen;
430 michael 9530
431     freeaddrinfo(res);
432    
433 michael 5325 node = libopm_node_create(scan);
434 michael 8580 libopm_list_add(&scanner->queue, node);
435 michael 5052
436 michael 5325 return OPM_SUCCESS;
437 michael 5052 }
438    
439     /* opm_end
440     *
441     * End a scan prematurely.
442     *
443     * Parameters:
444     * scanner: Scanner to end scan on
445     * remote: Pointer to remote struct to search for and end
446     *
447 michael 5325 * Return:
448 michael 5052 * No return. OPM_CALLBACK_END will still be called as normal.
449     */
450 michael 5325 void
451     opm_end(OPM_T *scanner, OPM_REMOTE_T *remote)
452 michael 5052 {
453 michael 5325 OPM_NODE_T *node1, *node2, *next1, *next2;
454     OPM_SCAN_T *scan;
455     OPM_CONNECTION_T *conn;
456 michael 5052
457 michael 5325 /* End active scans */
458     opm_endscan(scanner, remote);
459 michael 5052
460 michael 5325 /*
461     * Secondly remove all traces of it in the queue. Once removed we have to call
462     * OPM_CALLBACK_END
463     */
464 michael 8580 LIST_FOREACH_SAFE(node1, next1, scanner->queue.head)
465 michael 5325 {
466     scan = node1->data;
467 michael 5052
468 michael 5325 if (scan->remote == remote)
469     {
470     /* Free all connections */
471 michael 8580 LIST_FOREACH_SAFE(node2, next2, scan->connections.head)
472 michael 5052 {
473 michael 5325 conn = node2->data;
474 michael 5052
475 michael 8580 libopm_list_remove(&scan->connections, node2);
476 michael 5325 libopm_connection_free(conn);
477     libopm_node_free(node2);
478     continue;
479     }
480 michael 5052
481 michael 5325 /* OPM_CALLBACK_END because check_closed normally handles this */
482     libopm_do_callback(scanner, scan->remote, OPM_CALLBACK_END, 0);
483 michael 5052
484 michael 5325 /* Free up the scan */
485 michael 8580 libopm_list_remove(&scanner->queue, node1);
486 michael 5325 libopm_scan_free(scan);
487     libopm_node_free(node1);
488     }
489     }
490 michael 5052 }
491    
492     /* opm_endscan
493     *
494     * End a scan prematurely. Only end non-queued scans. This is useful
495     * because it only checks the active scan list (saving time), where
496     * opm_end checks both the scan and the possibly large queue.
497     *
498     * Parameters:
499     * scanner: Scanner to end scan on
500     * remote: Pointer to remote struct to search for and end
501     *
502     * Return:
503     * No return. OPM_CALLBACK_END will still be called as normal.
504     */
505 michael 5325 void
506     opm_endscan(OPM_T *scanner, OPM_REMOTE_T *remote)
507 michael 5052 {
508 michael 5325 OPM_NODE_T *node1, *node2;
509     OPM_SCAN_T *scan;
510     OPM_CONNECTION_T *conn;
511 michael 5052
512 michael 5325 /*
513     * First check to see if it's in the queue, if it is set all connections closed
514     * Next cycle of libopm_check_closed will take care of the garbage and handle
515     * OPM_CALLBACK_END
516 michael 5052 */
517 michael 8580 LIST_FOREACH(node1, scanner->scans.head)
518 michael 5325 {
519     scan = node1->data;
520 michael 5052
521 michael 5325 if (scan->remote == remote)
522     {
523 michael 8580 LIST_FOREACH(node2, scan->connections.head)
524 michael 5052 {
525 michael 5912 conn = node2->data;
526 michael 5325 conn->state = OPM_STATE_CLOSED;
527 michael 5052 }
528 michael 5325 }
529     }
530 michael 5052 }
531    
532 michael 5325 /* opm_active
533 michael 5052
534     Return number of scans in a scanner left.
535    
536     Parameters:
537     scanner: Scanner to return active scans on
538    
539     Return:
540     Number of active scans, both queued and active.
541     */
542 michael 5325 size_t
543     opm_active(OPM_T *scanner)
544 michael 5052 {
545 michael 8580 return LIST_SIZE(&scanner->queue) + LIST_SIZE(&scanner->scans);
546 michael 5052 }
547    
548     /* scan_create
549     *
550     * Create new OPM_SCAN_T struct
551     *
552 michael 5325 * Parameters:
553 michael 5052 * scanner: Scanner the scan is being created for. This
554     * is needed to get information on currently set
555     * protocols/config.
556 michael 5909 *
557 michael 5052 * remote: Remote host this scan will be scanning
558 michael 5909 *
559 michael 5052 * Return
560     * Address of new struct
561     */
562 michael 5325 static OPM_SCAN_T *
563     libopm_scan_create(OPM_T *scanner, OPM_REMOTE_T *remote)
564 michael 5052 {
565 michael 5325 OPM_SCAN_T *ret;
566     OPM_CONNECTION_T *conn;
567     OPM_NODE_T *node, *p;
568 michael 6222 #ifdef HAVE_LIBCRYPTO
569     static int tls_init = 0;
570     static SSL_CTX *ctx_client;
571 michael 5052
572 michael 6222 if (!tls_init)
573     {
574     tls_init = 1;
575     SSLeay_add_ssl_algorithms();
576    
577     ctx_client = SSL_CTX_new(SSLv23_client_method());
578     if (!ctx_client)
579     exit(EXIT_FAILURE);
580     }
581     #endif
582    
583 michael 8206 ret = libopm_calloc(sizeof(*ret));
584 michael 5325 ret->remote = remote;
585 michael 5052
586 michael 5671 /* Setup list of connections, one for each protocol */
587 michael 8580 LIST_FOREACH(p, scanner->protocols.head)
588 michael 5325 {
589     conn = libopm_connection_create();
590 michael 5052
591 michael 5671 conn->protocol = ((OPM_PROTOCOL_CONFIG_T *)p->data)->type;
592     conn->port = ((OPM_PROTOCOL_CONFIG_T *)p->data)->port;
593 michael 5052
594 michael 6222 #ifdef HAVE_LIBCRYPTO
595     if (conn->protocol->use_tls)
596     /* SSL_new does only fail if OOM in which case HOPM exits anyway */
597     conn->tls_handle = SSL_new(ctx_client);
598     #endif
599    
600 michael 5325 node = libopm_node_create(conn);
601 michael 8580 libopm_list_add(&ret->connections, node);
602 michael 5325 }
603 michael 5052
604 michael 5325 /*
605     * Do the same for any specific protocols the remote struct might be configured with
606     */
607 michael 8580 LIST_FOREACH(p, remote->protocols.head)
608 michael 5325 {
609     conn = libopm_connection_create();
610 michael 5052
611 michael 5671 conn->protocol = ((OPM_PROTOCOL_CONFIG_T *)p->data)->type;
612     conn->port = ((OPM_PROTOCOL_CONFIG_T *)p->data)->port;
613 michael 5052
614 michael 6222 #ifdef HAVE_LIBCRYPTO
615     if (conn->protocol->use_tls)
616     /* SSL_new does only fail if OOM in which case HOPM exits anyway */
617     conn->tls_handle = SSL_new(ctx_client);
618     #endif
619    
620 michael 5325 node = libopm_node_create(conn);
621 michael 8580 libopm_list_add(&ret->connections, node);
622 michael 5325 }
623 michael 5052
624 michael 5325 return ret;
625 michael 5052 }
626    
627     /* scan_free
628     *
629     * Free and cleanup OPM_SCAN_T struct
630     *
631     * Parametsr:
632     * scan: Scan struct to free
633 michael 5909 *
634 michael 5052 * Return:
635     * None
636     */
637 michael 5325 static void
638     libopm_scan_free(OPM_SCAN_T *scan)
639 michael 5052 {
640 michael 5325 OPM_NODE_T *p, *next;
641     OPM_CONNECTION_T *conn;
642 michael 5052
643 michael 8580 LIST_FOREACH_SAFE(p, next, scan->connections.head)
644 michael 5325 {
645     conn = p->data;
646 michael 5052
647 michael 5325 libopm_connection_free(conn);
648 michael 8580 libopm_list_remove(&scan->connections, p);
649 michael 5325 libopm_node_free(p);
650     }
651 michael 5052
652 michael 8206 libopm_free(scan);
653 michael 5052 }
654    
655     /* connection_create
656     *
657     * Allocate new OPM_CONNECTION_T
658     *
659     * Parameters:
660     * None
661     *
662     * Return:
663     * Address of new OPM_CONNECTION_T
664     */
665 michael 5325 static OPM_CONNECTION_T *
666     libopm_connection_create(void)
667 michael 5052 {
668 michael 5325 OPM_CONNECTION_T *ret;
669 michael 5052
670 michael 8206 ret = libopm_calloc(sizeof(*ret));
671 michael 5913 ret->state = OPM_STATE_UNESTABLISHED;
672 michael 5052
673 michael 5325 return ret;
674 michael 5052 }
675    
676     /* connection_free
677     *
678     * Free OPM_CONNECTION_T struct
679     *
680     * Parameters:
681     * conn: Address of struct to free
682     *
683     * Return:
684     * None
685     */
686 michael 5325 static void
687     libopm_connection_free(OPM_CONNECTION_T *conn)
688 michael 5052 {
689 michael 8206 libopm_free(conn);
690 michael 5052 }
691    
692     /* opm_cycle
693     *
694     * Perform tasks (called by client's loop)
695     *
696     * Parameters:
697     * None
698     * Return:
699     * None
700     */
701 michael 5325 void
702     opm_cycle(OPM_T *scanner)
703 michael 5052 {
704 michael 5325 libopm_check_queue(scanner); /* Move scans from the queue to the live scan list */
705     libopm_check_establish(scanner); /* Make new connections if possible */
706     libopm_check_poll(scanner); /* Poll connections for IO and proxy test */
707     libopm_check_closed(scanner); /* Check for closed or timed out connections */
708 michael 5052 }
709    
710     /* check_queue
711     *
712     * Move scans from the queue to the live scan list as long as there is
713     * room.
714     *
715 michael 5909 * Parameters:
716 michael 5052 * scanner: Scanner to check queue on
717     *
718     * Return:
719     * None
720     */
721 michael 5325 static void
722     libopm_check_queue(OPM_T *scanner)
723 michael 5052 {
724 michael 5671 OPM_NODE_T *node;
725     OPM_SCAN_T *scan;
726     unsigned int protocols, projected, fd_limit;
727 michael 5052
728 michael 8580 if (LIST_SIZE(&scanner->queue) == 0)
729 michael 5671 return;
730 michael 5052
731 michael 5671 fd_limit = *(int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT);
732     projected = scanner->fd_use;
733 michael 5052
734 michael 5671 /*
735     * We want to keep the live scan list as small as possible, so only move
736     * queued scans to the live list if they will not push above fd_limit
737     */
738 michael 8580 while (LIST_SIZE(&scanner->queue) > 0)
739 michael 5671 {
740     /* Grab the top scan */
741 michael 8580 scan = scanner->queue.head->data;
742     protocols = LIST_SIZE(&scan->connections);
743 michael 5052
744 michael 5671 /* Check if it will fit in the live scan list */
745     if ((protocols + projected) > fd_limit)
746     break;
747 michael 5052
748 michael 5671 /*
749     * Scans on the top of the queue were added first, swap the head off the
750     * top of the queue and add it to the tail of the live scan list
751     */
752 michael 8580 node = libopm_list_remove(&scanner->queue, scanner->queue.head);
753     libopm_list_add(&scanner->scans, node);
754 michael 5671 projected += protocols;
755     }
756 michael 5052 }
757    
758     /* check_establish
759     *
760     * Make new connections if there are free file descriptors and connections
761     * to be made.
762     *
763     * Parameters:
764     * scanner: Scanner to check for establish on
765     * Return:
766     * None
767     */
768 michael 5325 static void
769     libopm_check_establish(OPM_T *scanner)
770 michael 5052 {
771 michael 5325 OPM_NODE_T *node1, *node2;
772     OPM_SCAN_T *scan;
773     OPM_CONNECTION_T *conn;
774     unsigned int fd_limit;
775 michael 5052
776 michael 8580 if (LIST_SIZE(&scanner->scans) == 0)
777 michael 5325 return;
778 michael 5052
779 michael 5325 fd_limit = *(int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT);
780 michael 5052
781 michael 5325 if (scanner->fd_use >= fd_limit)
782     return;
783 michael 5052
784 michael 8580 LIST_FOREACH(node1, scanner->scans.head)
785 michael 5325 {
786     scan = node1->data;
787 michael 5052
788 michael 8580 LIST_FOREACH(node2, scan->connections.head)
789 michael 5325 {
790     /* Only scan if we have free file descriptors */
791     if (scanner->fd_use >= fd_limit)
792     return;
793 michael 5052
794 michael 5325 conn = node2->data;
795    
796     if (conn->state == OPM_STATE_UNESTABLISHED)
797     libopm_do_connect(scanner, scan, conn);
798 michael 5671 }
799 michael 5325 }
800 michael 5052 }
801    
802     /* check_closed
803 michael 5909 *
804 michael 5052 * Check for connections which have timed out or are
805     * closed. Connections timed out still need to be closed.
806     *
807     * Remove the connection from the list of connections, free
808     * the connection struct and free the list node. Then if this is
809     * the last connection of the scan, consider the scan completed and
810     * free the scan aswell (and callback that the scan ended).
811     *
812     * Parameters:
813     * scanner: Scanner to check on
814     * Return:
815     * None
816     */
817 michael 5325 static void
818     libopm_check_closed(OPM_T *scanner)
819 michael 5052 {
820 michael 5671 time_t present;
821     int timeout;
822     OPM_NODE_T *node1, *node2, *next1, *next2;
823     OPM_SCAN_T *scan;
824     OPM_CONNECTION_T *conn;
825 michael 5052
826 michael 8580 if (LIST_SIZE(&scanner->scans) == 0)
827 michael 5671 return;
828 michael 5052
829 michael 9861 present = opm_gettime();
830 michael 5671 timeout = *(int *)libopm_config(scanner->config, OPM_CONFIG_TIMEOUT);
831 michael 5052
832 michael 8580 LIST_FOREACH_SAFE(node1, next1, scanner->scans.head)
833 michael 5671 {
834     scan = node1->data;
835 michael 5052
836 michael 8580 LIST_FOREACH_SAFE(node2, next2, scan->connections.head)
837 michael 5671 {
838     conn = node2->data;
839 michael 5052
840 michael 5671 if (conn->state == OPM_STATE_CLOSED)
841 michael 5052 {
842 michael 6222 #ifdef HAVE_LIBCRYPTO
843     if (conn->protocol->use_tls)
844     {
845     SSL_set_shutdown(conn->tls_handle, SSL_RECEIVED_SHUTDOWN);
846     if (!SSL_shutdown(conn->tls_handle))
847     SSL_shutdown(conn->tls_handle);
848     SSL_free(conn->tls_handle);
849     }
850     #endif
851 michael 6224 if (conn->fd > -1)
852 michael 5671 close(conn->fd);
853 michael 5052
854 michael 5671 scanner->fd_use--;
855 michael 5052
856 michael 8580 libopm_list_remove(&scan->connections, node2);
857 michael 5671 libopm_connection_free(conn);
858     libopm_node_free(node2);
859     continue;
860 michael 5052 }
861    
862 michael 5671 if (((present - conn->creation) >= timeout) && conn->state != OPM_STATE_UNESTABLISHED)
863 michael 5052 {
864 michael 6222 #ifdef HAVE_LIBCRYPTO
865     if (conn->protocol->use_tls)
866     {
867     SSL_set_shutdown(conn->tls_handle, SSL_RECEIVED_SHUTDOWN);
868     if (!SSL_shutdown(conn->tls_handle))
869     SSL_shutdown(conn->tls_handle);
870     SSL_free(conn->tls_handle);
871     }
872     #endif
873 michael 6224 if (conn->fd > -1)
874     close(conn->fd);
875    
876 michael 5671 scanner->fd_use--;
877 michael 5052
878 michael 5671 libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_TIMEOUT, 0);
879 michael 8580 libopm_list_remove(&scan->connections, node2);
880 michael 5671 libopm_connection_free(conn);
881     libopm_node_free(node2);
882     continue;
883 michael 5052 }
884 michael 5671 }
885    
886     /*
887     * No more connections left in this scan, let the client know the scan has
888     * ended, then remove the scan from the scanner, and free it up.
889     */
890 michael 8580 if (LIST_SIZE(&scan->connections) == 0)
891 michael 5671 {
892     libopm_do_callback(scanner, scan->remote, OPM_CALLBACK_END, 0);
893 michael 8580 libopm_list_remove(&scanner->scans, node1);
894 michael 5671 libopm_scan_free(scan);
895     libopm_node_free(node1);
896     }
897     }
898 michael 5052 }
899    
900     /* do_connect
901     *
902     * Call socket() and connect() to start a scan.
903     *
904     * Parametsr:
905     * scan: Scan struct containing the connection
906     * conn: Connection to establish
907 michael 5909 * Return:
908 michael 5052 * None
909     */
910 michael 5325 static void
911     libopm_do_connect(OPM_T * scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
912 michael 5052 {
913 michael 9530 assert(scan->addr.ss_family == AF_INET);
914 michael 5052
915 michael 9530 if (scan->addr.ss_family == AF_INET6)
916     ((struct sockaddr_in6 *)&scan->addr)->sin6_port = htons(conn->port);
917     else
918     ((struct sockaddr_in *)&scan->addr)->sin_port = htons(conn->port);
919 michael 5052
920 michael 5671 scanner->fd_use++; /* Increase file descriptor use */
921 michael 5052
922 michael 9530 conn->fd = socket(scan->addr.ss_family, SOCK_STREAM, 0);
923 michael 5671 if (conn->fd == -1)
924     {
925     libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_ERROR, OPM_ERR_NOFD);
926     conn->state = OPM_STATE_CLOSED;
927     return;
928     }
929 michael 5052
930 michael 9530 struct sockaddr_storage *bind_ip = libopm_config(scanner->config, OPM_CONFIG_BIND_IP);
931 michael 5671 if (bind_ip)
932     {
933 michael 9530 size_t addr_len;
934 michael 5052
935 michael 9530 if (bind_ip->ss_family == AF_INET6)
936     {
937     struct sockaddr_in6 *in = (struct sockaddr_in6 *)bind_ip;
938     in->sin6_port = htons(0);
939     addr_len = sizeof(*in);
940     }
941     else
942     {
943     struct sockaddr_in *in = (struct sockaddr_in *)bind_ip;
944     in->sin_port = htons(0);
945     addr_len = sizeof(*in);
946     }
947 michael 5671
948 michael 9530 if (bind(conn->fd, (const struct sockaddr *)bind_ip, addr_len) == -1)
949 michael 5671 {
950     libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_ERROR, OPM_ERR_BIND);
951 michael 5052 conn->state = OPM_STATE_CLOSED;
952     return;
953 michael 5671 }
954     }
955 michael 5052
956 michael 5671 /* Set socket non blocking */
957     fcntl(conn->fd, F_SETFL, O_NONBLOCK);
958 michael 5052
959 michael 9530 connect(conn->fd, (const struct sockaddr *)&scan->addr, scan->addr_len);
960 michael 5052
961 michael 6222 #ifdef HAVE_LIBCRYPTO
962     if (conn->protocol->use_tls)
963     SSL_set_fd(conn->tls_handle, conn->fd);
964     #endif
965    
966 michael 5671 conn->state = OPM_STATE_ESTABLISHED;
967 michael 9861 conn->creation = opm_gettime(); /* Stamp creation time, for timeout */
968 michael 5052 }
969    
970     /* check_poll
971     *
972     * Check sockets for ready read/write
973     *
974     * Parameters:
975     * scanner: Scanner to isolate check on
976     * Return:
977     * None
978     */
979 michael 5325 static void
980     libopm_check_poll(OPM_T *scanner)
981 michael 5052 {
982 michael 5671 OPM_NODE_T *node1, *node2;
983     OPM_SCAN_T *scan;
984     OPM_CONNECTION_T *conn;
985     unsigned int size = 0;
986     static unsigned int ufds_size;
987     static struct pollfd *ufds = NULL;
988 michael 5052
989 michael 5671 /* Grow pollfd array (ufds) as needed */
990     if (ufds_size < (*(unsigned int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT)))
991     {
992 michael 8206 libopm_free(ufds);
993 michael 5052
994 michael 8206 ufds = libopm_calloc((sizeof *ufds) * (*(unsigned int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT)));
995 michael 5671 ufds_size = (*(unsigned int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT));
996     }
997 michael 5052
998 michael 8580 if (LIST_SIZE(&scanner->scans) == 0)
999 michael 5671 return;
1000 michael 5052
1001 michael 8580 LIST_FOREACH(node1, scanner->scans.head)
1002 michael 5671 {
1003     scan = node1->data;
1004 michael 5052
1005 michael 8580 LIST_FOREACH(node2, scan->connections.head)
1006 michael 5671 {
1007     if (size >= ufds_size)
1008     break;
1009 michael 5052
1010 michael 5671 conn = node2->data;
1011 michael 5052
1012 michael 5671 if (conn->state < OPM_STATE_ESTABLISHED ||
1013     conn->state == OPM_STATE_CLOSED)
1014     continue;
1015 michael 5052
1016 michael 5671 ufds[size].events = 0;
1017     ufds[size].revents = 0;
1018     ufds[size].fd = conn->fd;
1019 michael 5052
1020 michael 5671 /* Check for HUNG UP. */
1021     ufds[size].events |= POLLHUP;
1022     /* Check for INVALID FD */
1023     ufds[size].events |= POLLNVAL;
1024    
1025     switch (conn->state)
1026     {
1027     case OPM_STATE_ESTABLISHED:
1028     ufds[size].events |= POLLOUT;
1029     break;
1030     case OPM_STATE_NEGSENT:
1031     ufds[size].events |= POLLIN;
1032     break;
1033 michael 5052 }
1034    
1035 michael 5671 size++;
1036     }
1037     }
1038 michael 5052
1039 michael 5671 switch (poll(ufds, size, 0))
1040     {
1041     case -1:
1042     /* error in select/poll */
1043     return;
1044     case 0:
1045     /* Nothing to do */
1046     return;
1047 michael 5052
1048 michael 5671 /* Pass pointer to connection to handler. */
1049     }
1050    
1051 michael 8580 LIST_FOREACH(node1, scanner->scans.head)
1052 michael 5671 {
1053     scan = node1->data;
1054    
1055 michael 8580 LIST_FOREACH(node2, scan->connections.head)
1056 michael 5671 {
1057     conn = node2->data;
1058    
1059     for (unsigned int i = 0; i < size; ++i)
1060 michael 5052 {
1061 michael 5671 if ((ufds[i].fd == conn->fd) && (conn->state != OPM_STATE_CLOSED))
1062     {
1063     if (ufds[i].revents & POLLIN)
1064     libopm_do_readready(scanner, scan, conn);
1065     if (ufds[i].revents & POLLOUT)
1066     libopm_do_writeready(scanner, scan, conn);
1067     if (ufds[i].revents & POLLHUP)
1068     libopm_do_hup(scanner, scan, conn);
1069     }
1070 michael 5052 }
1071 michael 5671 }
1072     }
1073 michael 5052 }
1074    
1075 michael 6222 static int
1076     libopm_do_readready_tls(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1077     {
1078     #ifdef HAVE_LIBCRYPTO
1079     int max_read, length;
1080     char readbuf[LIBOPM_TLS_RECORD_SIZE];
1081    
1082     if (!SSL_is_init_finished(conn->tls_handle))
1083     return 0;
1084    
1085     if ((length = SSL_read(conn->tls_handle, readbuf, sizeof(readbuf))) <= 0)
1086     {
1087     switch (SSL_get_error(conn->tls_handle, length))
1088     {
1089     /* TBD: possibly could recover here from some errors */
1090     default:
1091     libopm_do_hup(scanner, scan, conn);
1092     return 0;
1093     }
1094     }
1095    
1096     max_read = *(int *)libopm_config(scanner->config, OPM_CONFIG_MAX_READ);
1097    
1098     for (const char *p = readbuf, *end = readbuf + length; p < end; ++p)
1099     {
1100     conn->bytes_read++;
1101    
1102     if (conn->bytes_read >= max_read)
1103     {
1104     libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_ERROR, OPM_ERR_MAX_READ);
1105     conn->state = OPM_STATE_CLOSED;
1106     return 0;
1107     }
1108    
1109     if (*p == '\0' || *p == '\r')
1110     continue;
1111    
1112     if (*p == '\n')
1113     {
1114     conn->readbuf[conn->readlen] = '\0';
1115     conn->readlen = 0;
1116    
1117     libopm_do_read(scanner, scan, conn);
1118    
1119     if (conn->state == OPM_STATE_CLOSED)
1120     return 0;
1121    
1122     continue;
1123     }
1124    
1125     if (conn->readlen < READBUFLEN)
1126     conn->readbuf[++(conn->readlen) - 1] = *p; /* -1 to pad for null term */
1127     }
1128     #endif
1129     return 0;
1130     }
1131    
1132 michael 5052 /* do_readready
1133     *
1134 michael 5909 * Remote connection is read ready, read the data into a buffer and check it against
1135     * the target_string if neccessary
1136 michael 5052 *
1137     * Parameters:
1138     * scanner: Scanner doing the scan
1139     * scan: Specific scan
1140     * conn: Specific connection in the scan
1141     *
1142     * Return:
1143     * None
1144     */
1145 michael 5325 static void
1146     libopm_do_readready(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1147 michael 5052 {
1148 michael 5671 int max_read;
1149     char c;
1150 michael 5052
1151 michael 5671 /*
1152     * If protocol has a specific read function, call that instead of
1153     * reading data from here.
1154     */
1155     if (conn->protocol->read_function)
1156     {
1157     conn->protocol->read_function(scanner, scan, conn);
1158     return;
1159     }
1160 michael 5052
1161 michael 5671 max_read = *(int *)libopm_config(scanner->config, OPM_CONFIG_MAX_READ);
1162 michael 5052
1163 michael 5671 while (1)
1164     {
1165     switch (read(conn->fd, &c, 1))
1166     {
1167     case 0:
1168     libopm_do_hup(scanner, scan, conn);
1169     return;
1170 michael 5052
1171 michael 5671 case -1:
1172     if (errno != EAGAIN)
1173     libopm_do_hup(scanner, scan, conn);
1174     return;
1175 michael 5052
1176 michael 5671 default:
1177     conn->bytes_read++;
1178 michael 5052
1179 michael 5671 if (conn->bytes_read >= max_read)
1180     {
1181     libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_ERROR, OPM_ERR_MAX_READ);
1182     conn->state = OPM_STATE_CLOSED;
1183     return;
1184     }
1185 michael 5052
1186 michael 5671 if (c == '\0' || c == '\r')
1187     continue;
1188 michael 5052
1189 michael 5671 if (c == '\n')
1190     {
1191     conn->readbuf[conn->readlen] = '\0';
1192     conn->readlen = 0;
1193 michael 5052
1194 michael 5671 libopm_do_read(scanner, scan, conn);
1195 michael 5052
1196 michael 5671 if (conn->state == OPM_STATE_CLOSED)
1197     return;
1198 michael 5052
1199 michael 5671 continue;
1200     }
1201 michael 5052
1202 michael 5671 if (conn->readlen < READBUFLEN)
1203     conn->readbuf[++(conn->readlen) - 1] = c; /* -1 to pad for null term */
1204     }
1205     }
1206 michael 5052 }
1207    
1208     /* do_read
1209     *
1210     * A line of data has been read from the socket, check it against
1211     * target string.
1212     *
1213     *
1214 michael 5325 *
1215 michael 5052 * Parameters:
1216     * scanner: Scanner doing the scan
1217     * scan: Specific scan
1218     * conn: Specific connection in the scan
1219     *
1220     * Return:
1221     * None
1222     */
1223 michael 5325 static void
1224     libopm_do_read(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1225 michael 5052 {
1226 michael 5325 OPM_LIST_T *list;
1227     OPM_NODE_T *node;
1228 michael 5052
1229 michael 5325 /* Check readbuf against target strings */
1230     list = (OPM_LIST_T *)libopm_config(scanner->config, OPM_CONFIG_TARGET_STRING);
1231    
1232     LIST_FOREACH(node, list->head)
1233     {
1234 michael 6075 const char *target_string = node->data;
1235 michael 5325
1236     if (strstr(conn->readbuf, target_string))
1237     {
1238     libopm_do_openproxy(scanner, scan, conn);
1239     break;
1240     }
1241     }
1242 michael 5052 }
1243    
1244     /* do_openproxy
1245     *
1246 michael 5909 * An open proxy was found on connection conn. Cleanup the connection and
1247 michael 5052 * call the appropriate callback to let the client know the proxy was found.
1248     *
1249     * Parameters:
1250     * scanner: Scanner doing the scan
1251     * scan: Specific scan
1252     * conn: Specific connection in the scan
1253     *
1254     * Return:
1255     * None
1256     */
1257 michael 5325 static void
1258     libopm_do_openproxy(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1259 michael 5052 {
1260 michael 5325 /* Mark the connection for close */
1261     conn->state = OPM_STATE_CLOSED;
1262 michael 5052
1263 michael 5325 /* Call client's open proxy callback */
1264     libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_OPENPROXY, 0);
1265 michael 5052 }
1266    
1267     /* do_writeready
1268     *
1269     * Remote connection is write ready, call the specific protocol
1270     * function for writing to this socket.
1271     *
1272     * Parameters:
1273     * scanner: Scanner doing the scan
1274     * scan: Specific scan
1275     * conn: Specific connection in the scan
1276     *
1277     * Return:
1278     * None
1279     */
1280 michael 5325 static void
1281     libopm_do_writeready(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1282 michael 5052 {
1283 michael 5325 OPM_PROTOCOL_T *protocol;
1284 michael 5052
1285 michael 6222 #ifdef HAVE_LIBCRYPTO
1286     if (conn->protocol->use_tls)
1287     {
1288     if (!SSL_is_init_finished(conn->tls_handle))
1289     {
1290     SSL_connect(conn->tls_handle);
1291     return;
1292     }
1293     }
1294     #endif
1295    
1296 michael 5325 protocol = conn->protocol;
1297 michael 5052
1298 michael 5325 /* Call write function for specific protocol */
1299     if (protocol->write_function)
1300     protocol->write_function(scanner, scan, conn);
1301 michael 5052
1302 michael 5325 /* Flag as NEGSENT so we don't have to send data again*/
1303     conn->state = OPM_STATE_NEGSENT;
1304 michael 5052 }
1305    
1306     /* do_hup
1307     *
1308     * Connection ended prematurely
1309     *
1310     * Parameters:
1311     * scanner: Scanner doing the scan
1312     * scan: Specific scan
1313     * conn: Specific connection in the scan
1314     * error: OPM_ERR_T containing the error type
1315     * Return:
1316     * None
1317     */
1318 michael 5325 static void
1319     libopm_do_hup(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1320 michael 5052 {
1321     /* Mark the connection for close */
1322 michael 5325 conn->state = OPM_STATE_CLOSED;
1323 michael 5052
1324 michael 5325 libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_NEGFAIL, 0);
1325 michael 5052 }
1326    
1327     /* do_callback
1328 michael 5909 *
1329 michael 5052 * Call callback
1330     *
1331     * Parameters:
1332     * scanner: scanner remote is on
1333     * remote: remote callback is for
1334     * type: callback type
1335     * var: optional var passed back (error codes, etc )
1336     * Return:
1337     * None
1338     */
1339 michael 5325 static void
1340     libopm_do_callback(OPM_T *scanner, OPM_REMOTE_T *remote, int type, int var)
1341 michael 5052 {
1342 michael 5325 /* Callback is out of range */
1343 michael 5673 if (type < 0 || type >= CBLEN)
1344 michael 5325 return;
1345 michael 5052
1346 michael 5325 if (scanner->callbacks[type].func)
1347     (scanner->callbacks[type].func)(scanner, remote, var, scanner->callbacks[type].data);
1348 michael 5052 }
1349    
1350     /* setup_remote
1351     *
1352     * Setup an OPM_REMOTE_T with information from an OPM_CONNECTION_T
1353     * for callback
1354     *
1355     * Parameters:
1356     * remote, conn
1357 michael 5325 *
1358 michael 5052 * Return:
1359     * remote
1360     */
1361 michael 5325 static OPM_REMOTE_T *
1362     libopm_setup_remote(OPM_REMOTE_T *remote, OPM_CONNECTION_T *conn)
1363 michael 5052 {
1364 michael 5325 remote->port = conn->port;
1365     remote->bytes_read = conn->bytes_read;
1366     remote->protocol = conn->protocol->type;
1367 michael 5052
1368 michael 5325 return remote;
1369 michael 5052 }

Properties

Name Value
svn:eol-style native
svn:keywords Id