ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/branches/1.0.x/src/libopm/src/libopm.c
Revision: 5669
Committed: Wed Mar 11 16:42:33 2015 UTC (9 years ago) by michael
Content type: text/x-csrc
File size: 31014 byte(s)
Log Message:
- libopm.c:opm_remote_create(): removed useless cruft

File Contents

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

Properties

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