ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/branches/1.1.x/src/libopm/src/libopm.c
Revision: 5913
Committed: Tue May 5 18:41:24 2015 UTC (8 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: hopm/trunk/src/libopm/src/libopm.c
File size: 29885 byte(s)
Log Message:
- config.c, libopm.c: remove a series of NULL/0 assignments not needed with calloc()

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

Properties

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