ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/branches/1.0.x/src/libopm/src/libopm.c
Revision: 5326
Committed: Tue Jan 6 21:05:44 2015 UTC (9 years, 2 months ago) by michael
Content type: text/x-csrc
File size: 31187 byte(s)
Log Message:
- Cleaned up style in several places

File Contents

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

Properties

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