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: 5274
Committed: Thu Jan 1 20:00:33 2015 UTC (9 years, 2 months ago) by michael
Content type: text/x-csrc
Original Path: hopm/trunk/src/libopm/src/libopm.c
File size: 31850 byte(s)
Log Message:
- Renamed MyMalloc() to xcalloc()

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

Properties

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