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: 5233
Committed: Wed Dec 31 15:08:00 2014 UTC (9 years, 3 months ago) by michael
Content type: text/x-csrc
Original Path: hopm/trunk/src/libopm/src/libopm.c
File size: 31982 byte(s)
Log Message:
- match.c, match.h: removed collapse()
- inet.h: moved poll.h header include to libopm.c

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

Properties

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