ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/branches/1.0.x/src/libopm/src/libopm.c
Revision: 6077
Committed: Mon Jun 8 20:53:10 2015 UTC (8 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 29718 byte(s)
Log Message:
- libopm/src/libopm.c:opm_config(): removed extraneous parentheses

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

Properties

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