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: 5216
Committed: Tue Dec 30 16:42:02 2014 UTC (9 years, 2 months ago) by michael
Content type: text/x-csrc
Original Path: hopm/trunk/src/libopm/src/libopm.c
File size: 31965 byte(s)
Log Message:
- Removed all instances of #ifdef HAVE_STRING_H

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

Properties

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