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: 5927
Committed: Wed May 6 17:41:36 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: 29673 byte(s)
Log Message:
- libopm.c:opm_scan(): removed another dead store

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

Properties

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