/[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 6077 - (show annotations)
Mon Jun 8 20:53:10 2015 UTC (5 years, 1 month ago) by michael
File MIME type: text/x-chdr
File size: 29718 byte(s)
- libopm/src/libopm.c:opm_config(): removed extraneous parentheses

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

Properties

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

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