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: 5094
Committed: Tue Dec 23 20:26:04 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: 31989 byte(s)
Log Message:
- Add our own strdup() and make use of it

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