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: 6222
Committed: Wed Jul 1 18:09:27 2015 UTC (8 years, 8 months ago) by michael
Content type: text/x-csrc
Original Path: hopm/trunk/src/libopm/src/libopm.c
File size: 33083 byte(s)
Log Message:
- Added HTTPS support for SSL/TLS-enabled HTTP proxies

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

Properties

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