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: 5913
Committed: Tue May 5 18:41:24 2015 UTC (8 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: hopm/trunk/src/libopm/src/libopm.c
File size: 29885 byte(s)
Log Message:
- config.c, libopm.c: remove a series of NULL/0 assignments not needed with calloc()

File Contents

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

Properties

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