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: 5671
Committed: Wed Mar 11 17:41:19 2015 UTC (9 years, 1 month ago) by michael
Content type: text/x-csrc
Original Path: hopm/trunk/src/libopm/src/libopm.c
File size: 30261 byte(s)
Log Message:
- libopm.c: style corrections

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 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 5325 if (type < 0 || type >= (CBLEN + 1))
201     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 5325 conn = (OPM_CONNECTION_T *) node2->data;
567     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     *
598     * remote: Remote host this scan will be scanning
599     *
600     * 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 michael 5052
612 michael 5325 ret->remote = remote;
613     ret->connections = libopm_list_create();
614 michael 5052
615 michael 5671 /* Setup list of connections, one for each protocol */
616 michael 5325 LIST_FOREACH(p, scanner->protocols->head)
617     {
618     conn = libopm_connection_create();
619 michael 5052
620 michael 5671 conn->protocol = ((OPM_PROTOCOL_CONFIG_T *)p->data)->type;
621     conn->port = ((OPM_PROTOCOL_CONFIG_T *)p->data)->port;
622 michael 5052
623 michael 5325 node = libopm_node_create(conn);
624     libopm_list_add(ret->connections, node);
625     }
626 michael 5052
627 michael 5325 /*
628     * Do the same for any specific protocols the remote struct might be configured with
629     */
630     LIST_FOREACH(p, remote->protocols->head)
631     {
632     conn = libopm_connection_create();
633 michael 5052
634 michael 5671 conn->protocol = ((OPM_PROTOCOL_CONFIG_T *)p->data)->type;
635     conn->port = ((OPM_PROTOCOL_CONFIG_T *)p->data)->port;
636 michael 5052
637 michael 5325 node = libopm_node_create(conn);
638     libopm_list_add(ret->connections, node);
639     }
640 michael 5052
641 michael 5325 memset(&(ret->addr), 0, sizeof(opm_sockaddr));
642     return ret;
643 michael 5052 }
644    
645     /* scan_free
646     *
647     * Free and cleanup OPM_SCAN_T struct
648     *
649     * Parametsr:
650     * scan: Scan struct to free
651     *
652     * Return:
653     * None
654     */
655 michael 5325 static void
656     libopm_scan_free(OPM_SCAN_T *scan)
657 michael 5052 {
658 michael 5325 OPM_NODE_T *p, *next;
659     OPM_CONNECTION_T *conn;
660 michael 5052
661 michael 5325 LIST_FOREACH_SAFE(p, next, scan->connections->head)
662     {
663     conn = p->data;
664 michael 5052
665 michael 5325 libopm_connection_free(conn);
666     libopm_list_remove(scan->connections, p);
667     libopm_node_free(p);
668     }
669 michael 5052
670 michael 5325 libopm_list_free(scan->connections);
671    
672     MyFree(scan);
673 michael 5052 }
674    
675     /* connection_create
676     *
677     * Allocate new OPM_CONNECTION_T
678     *
679     * Parameters:
680     * None
681     *
682     * Return:
683     * Address of new OPM_CONNECTION_T
684     */
685 michael 5325 static OPM_CONNECTION_T *
686     libopm_connection_create(void)
687 michael 5052 {
688 michael 5325 OPM_CONNECTION_T *ret;
689 michael 5052
690 michael 5325 ret = xcalloc(sizeof *ret);
691 michael 5052
692 michael 5325 ret->fd = 0;
693     ret->bytes_read = 0;
694     ret->readlen = 0;
695     ret->protocol = 0;
696     ret->port = 0;
697 michael 5052
698 michael 5325 ret->state = OPM_STATE_UNESTABLISHED;
699    
700     return ret;
701 michael 5052 }
702    
703     /* connection_free
704     *
705     * Free OPM_CONNECTION_T struct
706     *
707     * Parameters:
708     * conn: Address of struct to free
709     *
710     * Return:
711     * None
712     */
713 michael 5325 static void
714     libopm_connection_free(OPM_CONNECTION_T *conn)
715 michael 5052 {
716 michael 5325 MyFree(conn);
717 michael 5052 }
718    
719     /* opm_cycle
720     *
721     * Perform tasks (called by client's loop)
722     *
723     * Parameters:
724     * None
725     * Return:
726     * None
727     */
728 michael 5325 void
729     opm_cycle(OPM_T *scanner)
730 michael 5052 {
731 michael 5325 libopm_check_queue(scanner); /* Move scans from the queue to the live scan list */
732     libopm_check_establish(scanner); /* Make new connections if possible */
733     libopm_check_poll(scanner); /* Poll connections for IO and proxy test */
734     libopm_check_closed(scanner); /* Check for closed or timed out connections */
735 michael 5052 }
736    
737     /* check_queue
738     *
739     * Move scans from the queue to the live scan list as long as there is
740     * room.
741     *
742     * Parameters:
743     * scanner: Scanner to check queue on
744     *
745     * Return:
746     * None
747     */
748 michael 5325 static void
749     libopm_check_queue(OPM_T *scanner)
750 michael 5052 {
751 michael 5671 OPM_NODE_T *node;
752     OPM_SCAN_T *scan;
753     unsigned int protocols, projected, fd_limit;
754 michael 5052
755 michael 5671 if (LIST_SIZE(scanner->queue) == 0)
756     return;
757 michael 5052
758 michael 5671 fd_limit = *(int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT);
759     projected = scanner->fd_use;
760 michael 5052
761 michael 5671 /*
762     * We want to keep the live scan list as small as possible, so only move
763     * queued scans to the live list if they will not push above fd_limit
764     */
765     while (LIST_SIZE(scanner->queue) > 0)
766     {
767     /* Grab the top scan */
768     scan = scanner->queue->head->data;
769     protocols = LIST_SIZE(scan->connections);
770 michael 5052
771 michael 5671 /* Check if it will fit in the live scan list */
772     if ((protocols + projected) > fd_limit)
773     break;
774 michael 5052
775 michael 5671 /*
776     * Scans on the top of the queue were added first, swap the head off the
777     * top of the queue and add it to the tail of the live scan list
778     */
779     node = libopm_list_remove(scanner->queue, scanner->queue->head);
780     libopm_list_add(scanner->scans, node);
781     projected += protocols;
782     }
783 michael 5052 }
784    
785     /* check_establish
786     *
787     * Make new connections if there are free file descriptors and connections
788     * to be made.
789     *
790     * Parameters:
791     * scanner: Scanner to check for establish on
792     * Return:
793     * None
794     */
795 michael 5325 static void
796     libopm_check_establish(OPM_T *scanner)
797 michael 5052 {
798 michael 5325 OPM_NODE_T *node1, *node2;
799     OPM_SCAN_T *scan;
800     OPM_CONNECTION_T *conn;
801     unsigned int fd_limit;
802 michael 5052
803 michael 5325 if (LIST_SIZE(scanner->scans) == 0)
804     return;
805 michael 5052
806 michael 5325 fd_limit = *(int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT);
807 michael 5052
808 michael 5325 if (scanner->fd_use >= fd_limit)
809     return;
810 michael 5052
811 michael 5325 LIST_FOREACH(node1, scanner->scans->head)
812     {
813     scan = node1->data;
814 michael 5052
815 michael 5325 LIST_FOREACH(node2, scan->connections->head)
816     {
817     /* Only scan if we have free file descriptors */
818     if (scanner->fd_use >= fd_limit)
819     return;
820 michael 5052
821 michael 5325 conn = node2->data;
822    
823     if (conn->state == OPM_STATE_UNESTABLISHED)
824     libopm_do_connect(scanner, scan, conn);
825 michael 5671 }
826 michael 5325 }
827 michael 5052 }
828    
829     /* check_closed
830     *
831     * Check for connections which have timed out or are
832     * closed. Connections timed out still need to be closed.
833     *
834     * Remove the connection from the list of connections, free
835     * the connection struct and free the list node. Then if this is
836     * the last connection of the scan, consider the scan completed and
837     * free the scan aswell (and callback that the scan ended).
838     *
839     * Parameters:
840     * scanner: Scanner to check on
841     * Return:
842     * None
843     */
844 michael 5325 static void
845     libopm_check_closed(OPM_T *scanner)
846 michael 5052 {
847 michael 5671 time_t present;
848     int timeout;
849     OPM_NODE_T *node1, *node2, *next1, *next2;
850     OPM_SCAN_T *scan;
851     OPM_CONNECTION_T *conn;
852 michael 5052
853 michael 5671 if (LIST_SIZE(scanner->scans) == 0)
854     return;
855 michael 5052
856 michael 5671 time(&present);
857     timeout = *(int *)libopm_config(scanner->config, OPM_CONFIG_TIMEOUT);
858 michael 5052
859 michael 5671 LIST_FOREACH_SAFE(node1, next1, scanner->scans->head)
860     {
861     scan = node1->data;
862 michael 5052
863 michael 5671 LIST_FOREACH_SAFE(node2, next2, scan->connections->head)
864     {
865     conn = node2->data;
866 michael 5052
867 michael 5671 if (conn->state == OPM_STATE_CLOSED)
868 michael 5052 {
869 michael 5671 if (conn->fd > 0)
870     close(conn->fd);
871 michael 5052
872 michael 5671 scanner->fd_use--;
873 michael 5052
874 michael 5671 libopm_list_remove(scan->connections, node2);
875     libopm_connection_free(conn);
876     libopm_node_free(node2);
877     continue;
878 michael 5052 }
879    
880 michael 5671 if (((present - conn->creation) >= timeout) && conn->state != OPM_STATE_UNESTABLISHED)
881 michael 5052 {
882 michael 5671 close(conn->fd);
883     scanner->fd_use--;
884 michael 5052
885 michael 5671 libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_TIMEOUT, 0);
886     libopm_list_remove(scan->connections, node2);
887     libopm_connection_free(conn);
888     libopm_node_free(node2);
889     continue;
890 michael 5052 }
891 michael 5671 }
892    
893     /*
894     * No more connections left in this scan, let the client know the scan has
895     * ended, then remove the scan from the scanner, and free it up.
896     */
897     if (LIST_SIZE(scan->connections) == 0)
898     {
899     libopm_do_callback(scanner, scan->remote, OPM_CALLBACK_END, 0);
900     libopm_list_remove(scanner->scans, node1);
901     libopm_scan_free(scan);
902     libopm_node_free(node1);
903     }
904     }
905 michael 5052 }
906    
907     /* do_connect
908     *
909     * Call socket() and connect() to start a scan.
910     *
911     * Parametsr:
912     * scan: Scan struct containing the connection
913     * conn: Connection to establish
914     * Return:
915     * None
916     */
917 michael 5325 static void
918     libopm_do_connect(OPM_T * scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
919 michael 5052 {
920 michael 5671 opm_sockaddr *bind_ip;
921     struct sockaddr_in *addr; /* Outgoing host */
922     struct sockaddr_in local_addr; /* For binding */
923 michael 5052
924 michael 5671 addr = (struct sockaddr_in *)&(scan->addr.sa4); /* Already have the IP in byte format from opm_scan */
925     addr->sin_family = AF_INET;
926     addr->sin_port = htons(conn->port);
927 michael 5052
928 michael 5671 bind_ip = (opm_sockaddr *)libopm_config(scanner->config, OPM_CONFIG_BIND_IP);
929 michael 5052
930 michael 5671 conn->fd = socket(PF_INET, SOCK_STREAM, 0);
931     scanner->fd_use++; /* Increase file descriptor use */
932 michael 5052
933 michael 5671 if (conn->fd == -1)
934     {
935     libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_ERROR, OPM_ERR_NOFD);
936     conn->state = OPM_STATE_CLOSED;
937     return;
938     }
939 michael 5052
940 michael 5671 if (bind_ip)
941     {
942     memset(&local_addr, 0, sizeof(local_addr));
943 michael 5052
944 michael 5671 local_addr.sin_addr.s_addr = bind_ip->sa4.sin_addr.s_addr;
945     local_addr.sin_family = AF_INET;
946     local_addr.sin_port = htons(0);
947    
948     if (bind(conn->fd, (struct sockaddr *)&(local_addr), sizeof(local_addr)) == -1)
949     {
950     libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_ERROR, OPM_ERR_BIND);
951 michael 5052 conn->state = OPM_STATE_CLOSED;
952     return;
953 michael 5671 }
954     }
955 michael 5052
956 michael 5671 /* Set socket non blocking */
957     fcntl(conn->fd, F_SETFL, O_NONBLOCK);
958 michael 5052
959 michael 5671 connect(conn->fd, (struct sockaddr *)addr, sizeof(*addr));
960 michael 5052
961 michael 5671 conn->state = OPM_STATE_ESTABLISHED;
962     time(&conn->creation); /* Stamp creation time, for timeout */
963 michael 5052 }
964    
965     /* check_poll
966     *
967     * Check sockets for ready read/write
968     *
969     * Parameters:
970     * scanner: Scanner to isolate check on
971     * Return:
972     * None
973     */
974 michael 5325 static void
975     libopm_check_poll(OPM_T *scanner)
976 michael 5052 {
977 michael 5671 OPM_NODE_T *node1, *node2;
978     OPM_SCAN_T *scan;
979     OPM_CONNECTION_T *conn;
980     unsigned int size = 0;
981     static unsigned int ufds_size;
982     static struct pollfd *ufds = NULL;
983 michael 5052
984 michael 5671 /* Grow pollfd array (ufds) as needed */
985     if (ufds_size < (*(unsigned int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT)))
986     {
987     MyFree(ufds);
988 michael 5052
989 michael 5671 ufds = xcalloc((sizeof *ufds) * (*(unsigned int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT)));
990     ufds_size = (*(unsigned int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT));
991     }
992 michael 5052
993 michael 5671 if (LIST_SIZE(scanner->scans) == 0)
994     return;
995 michael 5052
996 michael 5671 LIST_FOREACH(node1, scanner->scans->head)
997     {
998     scan = node1->data;
999 michael 5052
1000 michael 5671 LIST_FOREACH(node2, scan->connections->head)
1001     {
1002     if (size >= ufds_size)
1003     break;
1004 michael 5052
1005 michael 5671 conn = node2->data;
1006 michael 5052
1007 michael 5671 if (conn->state < OPM_STATE_ESTABLISHED ||
1008     conn->state == OPM_STATE_CLOSED)
1009     continue;
1010 michael 5052
1011 michael 5671 ufds[size].events = 0;
1012     ufds[size].revents = 0;
1013     ufds[size].fd = conn->fd;
1014 michael 5052
1015 michael 5671 /* Check for HUNG UP. */
1016     ufds[size].events |= POLLHUP;
1017     /* Check for INVALID FD */
1018     ufds[size].events |= POLLNVAL;
1019    
1020     switch (conn->state)
1021     {
1022     case OPM_STATE_ESTABLISHED:
1023     ufds[size].events |= POLLOUT;
1024     break;
1025     case OPM_STATE_NEGSENT:
1026     ufds[size].events |= POLLIN;
1027     break;
1028 michael 5052 }
1029    
1030 michael 5671 size++;
1031     }
1032     }
1033 michael 5052
1034 michael 5671 switch (poll(ufds, size, 0))
1035     {
1036     case -1:
1037     /* error in select/poll */
1038     return;
1039     case 0:
1040     /* Nothing to do */
1041     return;
1042 michael 5052
1043 michael 5671 /* Pass pointer to connection to handler. */
1044     }
1045    
1046     LIST_FOREACH(node1, scanner->scans->head)
1047     {
1048     scan = node1->data;
1049    
1050     LIST_FOREACH(node2, scan->connections->head)
1051     {
1052     conn = node2->data;
1053    
1054     for (unsigned int i = 0; i < size; ++i)
1055 michael 5052 {
1056 michael 5671 if ((ufds[i].fd == conn->fd) && (conn->state != OPM_STATE_CLOSED))
1057     {
1058     if (ufds[i].revents & POLLIN)
1059     libopm_do_readready(scanner, scan, conn);
1060     if (ufds[i].revents & POLLOUT)
1061     libopm_do_writeready(scanner, scan, conn);
1062     if (ufds[i].revents & POLLHUP)
1063     libopm_do_hup(scanner, scan, conn);
1064     }
1065 michael 5052 }
1066 michael 5671 }
1067     }
1068 michael 5052 }
1069    
1070     /* do_readready
1071     *
1072     * Remote connection is read ready, read the data into a buffer and check it against
1073     * the target_string if neccessary
1074     *
1075     * Parameters:
1076     * scanner: Scanner doing the scan
1077     * scan: Specific scan
1078     * conn: Specific connection in the scan
1079     *
1080     * Return:
1081     * None
1082     */
1083 michael 5325 static void
1084     libopm_do_readready(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1085 michael 5052 {
1086 michael 5671 int max_read;
1087     char c;
1088 michael 5052
1089 michael 5671 /*
1090     * If protocol has a specific read function, call that instead of
1091     * reading data from here.
1092     */
1093     if (conn->protocol->read_function)
1094     {
1095     conn->protocol->read_function(scanner, scan, conn);
1096     return;
1097     }
1098 michael 5052
1099 michael 5671 max_read = *(int *)libopm_config(scanner->config, OPM_CONFIG_MAX_READ);
1100 michael 5052
1101 michael 5671 while (1)
1102     {
1103     switch (read(conn->fd, &c, 1))
1104     {
1105     case 0:
1106     libopm_do_hup(scanner, scan, conn);
1107     return;
1108 michael 5052
1109 michael 5671 case -1:
1110     if (errno != EAGAIN)
1111     libopm_do_hup(scanner, scan, conn);
1112     return;
1113 michael 5052
1114 michael 5671 default:
1115     conn->bytes_read++;
1116 michael 5052
1117 michael 5671 if (conn->bytes_read >= max_read)
1118     {
1119     libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_ERROR, OPM_ERR_MAX_READ);
1120     conn->state = OPM_STATE_CLOSED;
1121     return;
1122     }
1123 michael 5052
1124 michael 5671 if (c == '\0' || c == '\r')
1125     continue;
1126 michael 5052
1127 michael 5671 if (c == '\n')
1128     {
1129     conn->readbuf[conn->readlen] = '\0';
1130     conn->readlen = 0;
1131 michael 5052
1132 michael 5671 libopm_do_read(scanner, scan, conn);
1133 michael 5052
1134 michael 5671 if (conn->state == OPM_STATE_CLOSED)
1135     return;
1136 michael 5052
1137 michael 5671 continue;
1138     }
1139 michael 5052
1140 michael 5671 if (conn->readlen < READBUFLEN)
1141     conn->readbuf[++(conn->readlen) - 1] = c; /* -1 to pad for null term */
1142     }
1143     }
1144 michael 5052 }
1145    
1146     /* do_read
1147     *
1148     * A line of data has been read from the socket, check it against
1149     * target string.
1150     *
1151     *
1152 michael 5325 *
1153 michael 5052 * Parameters:
1154     * scanner: Scanner doing the scan
1155     * scan: Specific scan
1156     * conn: Specific connection in the scan
1157     *
1158     * Return:
1159     * None
1160     */
1161 michael 5325 static void
1162     libopm_do_read(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1163 michael 5052 {
1164 michael 5325 OPM_LIST_T *list;
1165     OPM_NODE_T *node;
1166     char *target_string;
1167 michael 5052
1168 michael 5325 /* Check readbuf against target strings */
1169     list = (OPM_LIST_T *)libopm_config(scanner->config, OPM_CONFIG_TARGET_STRING);
1170    
1171     LIST_FOREACH(node, list->head)
1172     {
1173     target_string = node->data;
1174    
1175     if (strstr(conn->readbuf, target_string))
1176     {
1177     libopm_do_openproxy(scanner, scan, conn);
1178     break;
1179     }
1180     }
1181 michael 5052 }
1182    
1183     /* do_openproxy
1184     *
1185     * An open proxy was found on connection conn. Cleanup the connection and
1186     * call the appropriate callback to let the client know the proxy was found.
1187     *
1188     * Parameters:
1189     * scanner: Scanner doing the scan
1190     * scan: Specific scan
1191     * conn: Specific connection in the scan
1192     *
1193     * Return:
1194     * None
1195     */
1196 michael 5325 static void
1197     libopm_do_openproxy(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1198 michael 5052 {
1199 michael 5325 OPM_REMOTE_T *remote;
1200 michael 5052
1201 michael 5325 remote = scan->remote;
1202 michael 5052
1203 michael 5325 /* Mark the connection for close */
1204     conn->state = OPM_STATE_CLOSED;
1205 michael 5052
1206 michael 5325 /* Call client's open proxy callback */
1207     libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_OPENPROXY, 0);
1208 michael 5052 }
1209    
1210     /* do_writeready
1211     *
1212     * Remote connection is write ready, call the specific protocol
1213     * function for writing to this socket.
1214     *
1215     * Parameters:
1216     * scanner: Scanner doing the scan
1217     * scan: Specific scan
1218     * conn: Specific connection in the scan
1219     *
1220     * Return:
1221     * None
1222     */
1223 michael 5325 static void
1224     libopm_do_writeready(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1225 michael 5052 {
1226 michael 5325 OPM_PROTOCOL_T *protocol;
1227 michael 5052
1228 michael 5325 protocol = conn->protocol;
1229 michael 5052
1230 michael 5325 /* Call write function for specific protocol */
1231     if (protocol->write_function)
1232     protocol->write_function(scanner, scan, conn);
1233 michael 5052
1234 michael 5325 /* Flag as NEGSENT so we don't have to send data again*/
1235     conn->state = OPM_STATE_NEGSENT;
1236 michael 5052 }
1237    
1238     /* do_hup
1239     *
1240     * Connection ended prematurely
1241     *
1242     * Parameters:
1243     * scanner: Scanner doing the scan
1244     * scan: Specific scan
1245     * conn: Specific connection in the scan
1246     * error: OPM_ERR_T containing the error type
1247     * Return:
1248     * None
1249     */
1250 michael 5325 static void
1251     libopm_do_hup(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1252 michael 5052 {
1253 michael 5325 OPM_REMOTE_T *remote;
1254 michael 5052
1255 michael 5325 remote = scan->remote;
1256 michael 5052
1257     /* Mark the connection for close */
1258 michael 5325 conn->state = OPM_STATE_CLOSED;
1259 michael 5052
1260 michael 5325 libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_NEGFAIL, 0);
1261 michael 5052 }
1262    
1263     /* do_callback
1264     *
1265     * Call callback
1266     *
1267     * Parameters:
1268     * scanner: scanner remote is on
1269     * remote: remote callback is for
1270     * type: callback type
1271     * var: optional var passed back (error codes, etc )
1272     * Return:
1273     * None
1274     */
1275 michael 5325 static void
1276     libopm_do_callback(OPM_T *scanner, OPM_REMOTE_T *remote, int type, int var)
1277 michael 5052 {
1278 michael 5325 /* Callback is out of range */
1279     if (type < 0 || type >= (CBLEN + 1))
1280     return;
1281 michael 5052
1282 michael 5325 if (scanner->callbacks[type].func)
1283     (scanner->callbacks[type].func)(scanner, remote, var, scanner->callbacks[type].data);
1284 michael 5052 }
1285    
1286     /* setup_remote
1287     *
1288     * Setup an OPM_REMOTE_T with information from an OPM_CONNECTION_T
1289     * for callback
1290     *
1291     * Parameters:
1292     * remote, conn
1293 michael 5325 *
1294 michael 5052 * Return:
1295     * remote
1296     */
1297 michael 5325 static OPM_REMOTE_T *
1298     libopm_setup_remote(OPM_REMOTE_T *remote, OPM_CONNECTION_T *conn)
1299 michael 5052 {
1300 michael 5325 remote->port = conn->port;
1301     remote->bytes_read = conn->bytes_read;
1302     remote->protocol = conn->protocol->type;
1303 michael 5052
1304 michael 5325 return remote;
1305 michael 5052 }

Properties

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