/[svn]/hopm/branches/1.0.x/src/libopm/src/libopm.c
ViewVC logotype

Contents of /hopm/branches/1.0.x/src/libopm/src/libopm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5911 - (show annotations)
Tue May 5 18:32:36 2015 UTC (7 years, 3 months ago) by michael
File MIME type: text/x-chdr
File size: 30135 byte(s)
- config.c, proxy.c: removed useless casts

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

Properties

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

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