/[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 5927 - (show annotations)
Wed May 6 17:41:36 2015 UTC (7 years, 3 months ago) by michael
File MIME type: text/x-chdr
File size: 29673 byte(s)
- libopm.c:opm_scan(): removed another dead store

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