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: 5912
Committed: Tue May 5 18:33:11 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: 30135 byte(s)
Log Message:
- config.c, proxy.c: removed useless casts

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

Properties

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