/[svn]/hopm/trunk/src/libopm/src/libopm.c
ViewVC logotype

Contents of /hopm/trunk/src/libopm/src/libopm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5135 - (show annotations)
Thu Dec 25 18:51:51 2014 UTC (5 years, 5 months ago) by michael
File MIME type: text/x-chdr
File size: 31995 byte(s)
- propset svn:eol-style native

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

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28