Exemple #1
0
void connect_wait(void *pri_work) {
	drone_t *d=NULL;
	xpoll_t spdf[8];
	unsigned int spdf_off=0;
	int pret=0, getret=0;
	uint8_t msg_type=0, status=0;
	size_t msg_len=0;
	uint8_t *ptr=NULL;
	time_t s_time=0, e_time=0;

	VRB(1, "waiting for connections to finish");

	if (s->dlh == NULL || s->dlh->head == NULL) {
		PANIC("waiting for connections with no drones?");
	}

	for (s_time=time(NULL);;) {
		int livesocks=0;

		for (d=s->dlh->head, spdf_off=0; d != NULL; d=d->next, spdf_off++) {
			if (d->s) livesocks++;
			spdf[spdf_off].fd=d->s;
		}

		DBG(M_CON, "polling %d sockets......", livesocks);

		if ((pret=xpoll(&spdf[0], s->dlh->size, 5000)) < 0) {
			ERR("poll drone fd's fail: %s", strerror(errno));
		}

		time(&e_time);

		if ((e_time - s_time) > s->ss->recv_timeout) {
			break;
		}

		for (d=s->dlh->head, spdf_off=0; d != NULL; d=d->next, spdf_off++) {
                        d->s_rw=0;
                        if (d->status != DRONE_STATUS_DEAD && d->status != DRONE_STATUS_DONE) {
                                d->s_rw=spdf[spdf_off].rw;
                        }
                        if (spdf[spdf_off].rw & XPOLL_READABLE) {
                                DBG(M_CON, "socket type %s is readable", strdronetype(d->type));
                        }
                }

		for (d=s->dlh->head; d != NULL; d=d->next) {
			DBG(M_CON, "drone type %s drone status %s", strdronetype(d->type), strdronestatus(d->status));
			if (d->type == DRONE_TYPE_LISTENER && (d->status == DRONE_STATUS_READY || d->status == DRONE_STATUS_WORKING)) {
				/* i just moved this here cause the line above was ugly */
				if ((d->s_rw & XPOLL_READABLE) == XPOLL_READABLE) {
					if (recv_messages(d->s) < 1) {
						ERR("cant recv_messages from ready listener");
						drone_updatestate(d, DRONE_STATUS_DEAD);
						continue;
					}

					while (1) {
						getret=get_message(d->s, &msg_type, &status, &ptr, &msg_len);
						if (getret < 1) {
							break;
						}
						if (msg_type == MSG_ERROR || status != MSG_STATUS_OK) {
							ERR("drone on fd %d is dead, closing socket and marking dead", d->s);
							drone_updatestate(d, DRONE_STATUS_DEAD);
							break;
						}
						else if (msg_type == MSG_OUTPUT) {
							deal_with_output(ptr, msg_len);
						}
						else {
							ERR("unhandled message from Listener drone message type `%s' with status %d", strmsgtype(msg_type), status);
						}
					}
				}
			}
			else if (d->type == DRONE_TYPE_SENDER && d->status == DRONE_STATUS_READY) {
				union {
					uint8_t *pw_ptr;
					void *ptr;
					send_pri_workunit_t *p;
				} pw_u;

				while ((pw_u.ptr=fifo_pop(pri_work)) != NULL) {

					DBG(M_CON, "sending pri work to sender in wait connections");
					if (send_message(
							d->s,
							MSG_WORKUNIT,
							MSG_STATUS_OK,
							pw_u.pw_ptr,
							sizeof(send_pri_workunit_t) + pw_u.p->doff
						) < 0) {
						ERR("cant send priority workunit to sender on fd %d, marking dead", d->s);
						drone_updatestate(d, DRONE_STATUS_DEAD);
						fifo_push(pri_work, pw_u.ptr);
						continue;
					}
					xfree(pw_u.ptr);
				}
			}

			if (s->senders == 0 || s->listeners == 0) {
				PANIC(s->senders == 0 ? "no senders" : "no listeners");
			}
		}

	}

	VRB(1, "connections timeout");
}
void run_scan(void) {
	uint8_t msg_type=0, status=0, *ptr=NULL;
	size_t wk_len=0, msg_len=0;
	xpoll_t spdf[4]; /* XXX dynamic */
	union {
		uint8_t *cr;
		void *ptr;
	} w_k;
	drone_t *c=NULL;

	rfifo=fifo_init();

	if (GET_DOCONNECT()) {
		pri_work=fifo_init();
		state_tbl=TBLINIT(111);
	}

	if (s->ss->mode == MODE_TCPSCAN) s->ss->syn_key=arc4random();

	for (c=s->dlh->head  ; c != NULL ; c=c->next) {
		if (c->type == DRONE_TYPE_LISTENER && c->status == DRONE_STATUS_READY) {
			if ((w_k.ptr=get_lp_workunit(&wk_len)) != NULL) {
				if (s->verbose > 2) {
					if (s->verbose > 5) {
						MSG(M_DBG2, "Got listener workunit of size %d :]", wk_len);
					}
					MSG(M_DBG1, "sending workunit to listener");
				}

				if (send_message(c->s, MSG_WORKUNIT, MSG_STATUS_OK, w_k.cr, wk_len) < 0) {
					MSG(M_ERR, "Cant Send Workunit to listener on fd %d", c->s);
					mark_dead(c, DRONE_STATUS_DEAD);
				}

				if (c->s == -1) PANIC("WOW!!!!");

				if (get_singlemessage(c->s, &msg_type, &status, &ptr, &msg_len) != 1) {
					MSG(M_ERR, "Unexpected sequence of messages from listener on fd %d, marking dead", c->s);
					mark_dead(c, DRONE_STATUS_DEAD);
				}

				if (status != MSG_STATUS_OK) {
					MSG(M_ERR, "bad status `%d' from listener on fd %d, marking as dead", status, c->s);
					mark_dead(c, DRONE_STATUS_DEAD);
				}

				if (msg_type != MSG_READY) {
					MSG(M_ERR, "bad message `%s' from listener on fd %d, marking as dead", strmsgtype(msg_type), c->s);
					mark_dead(c, DRONE_STATUS_DEAD);
				}

				else if (s->verbose > 3) {
					MSG(M_DBG1, "Sent workunits to listener on fd %d", c->s);
				}
			}
		}
	}

	if (s->listeners == 0) {
		MSG(M_ERR, "Not enough listeners to run scan, bailing out");
		return;
	}

	while (1) {
		int readorwrite=0, breakout=0, pret=0;
		uint32_t d_offset=0;

		c=s->dlh->head;
		assert(s->dlh->size <= sizeof(spdf)); /* XXX */

		/* write loop */
		for (c=s->dlh->head, d_offset=0 ; c != NULL ; c=c->next, d_offset++) {
			if (c->type == DRONE_TYPE_SENDER) {
				void *pw_ptr=NULL;

				if (GET_DOCONNECT()) {
					while ((pw_ptr=fifo_pop(pri_work)) != NULL) {
						if (send_message(c->s, MSG_WORKUNIT, MSG_STATUS_OK, pw_ptr, sizeof(send_pri_workunit_t)) < 0) {
							MSG(M_ERR, "Cant send priority workunit to sender on fd %d, marking dead", c->s);
							mark_dead(c, DRONE_STATUS_DEAD);
						}
					}
				}

				if (c->status == DRONE_STATUS_READY) {
					/* get to work! */
					w_k.cr=NULL;
					if ((w_k.ptr=get_sp_workunit(&wk_len)) != NULL) {
						if (s->verbose > 2) {
							if (s->verbose > 5) {
								MSG(M_DBG2, "Got workunit of size %d :]", wk_len);
							}
							MSG(M_DBG1, "sending workunit to sender");
						}

						if (send_message(c->s, MSG_WORKUNIT, MSG_STATUS_OK, w_k.cr, wk_len) < 0) {
							MSG(M_ERR, "Cant Send Workunit to sender on fd %d", c->s);
							mark_dead(c, DRONE_STATUS_DEAD);
						}
						else if (s->verbose > 3) {
							MSG(M_DBG1, "Sent workunits to senders");
						}
						c->status=DRONE_STATUS_WORKING;
						readorwrite=1;
					}
					else {
						if (s->verbose > 3) MSG(M_DBG1, "Marking sender on fd %d as done, no more workunits to send", c->s);
						send_message(c->s, MSG_QUIT, MSG_STATUS_OK, ptr, 0);
						mark_dead(c, DRONE_STATUS_DONE);
					}
				}
			}
			spdf[d_offset].fd=c->s;
		}
		if (!(s->senders)) {
			breakout++;
			break;
		}

		if ((pret=xpoll(&spdf[0], s->dlh->size, -1)) < 0) {
			MSG(M_ERR, "Poll drone fd's fail: %s", strerror(errno));
		}

		for (c=s->dlh->head, d_offset=0 ; c != NULL ; c=c->next, d_offset++) {
			c->s_rw=0;
			if (c->status != DRONE_STATUS_DEAD && c->status != DRONE_STATUS_DONE) {
				c->s_rw=spdf[d_offset].rw;
			}
			if (spdf[d_offset].rw & XPOLL_READABLE) {
				if (s->verbose > 4) MSG(M_DBG1, "Socket type %s is readable", (c->type == DRONE_TYPE_LISTENER) ? "Listener" : "Sender");
			}
		}

		/* read loop */
		for (c=s->dlh->head, d_offset=0 ; c != NULL ; c=c->next, d_offset++) {
			if (c->status != DRONE_STATUS_DEAD && c->status != DRONE_STATUS_DONE && c->s_rw & XPOLL_READABLE) {
				int getret=0;
				if (s->verbose > 5) MSG(M_DBG2, "Reading file descriptor %d type %s and %d senders left", c->s, (c->type == DRONE_TYPE_SENDER ? "Sender" : "Listener"), s->senders);

				if (recv_messages(c->s) < 0) {
					MSG(M_ERR, "Cant recieve messages from fd %d, marking as dead", c->s);
					mark_dead(c, DRONE_STATUS_DEAD);
					continue;
				}

				while (1) {
					if (c->status == DRONE_STATUS_DONE || c->status == DRONE_STATUS_DEAD) break;
					getret=get_message(c->s, &msg_type, &status, &ptr, &msg_len);
					if (getret < 1) break;
					if (msg_type == MSG_ERROR || status != MSG_STATUS_OK) {
						MSG(M_ERR, "Drone on fd %d is dead, closing socket and marking dead", c->s);
						mark_dead(c, DRONE_STATUS_DEAD);
						break;
					}
					else if (msg_type == MSG_WORKDONE && c->type == DRONE_TYPE_SENDER) {
						if (s->verbose > 5) MSG(M_DBG2, "Setting sender back to ready state after workdone message");
						c->status=DRONE_STATUS_READY;
					}
					else if (msg_type == MSG_OUTPUT && c->type == DRONE_TYPE_LISTENER) {
						if (s->ss->mode == MODE_TCPSCAN || s->ss->mode == MODE_UDPSCAN) {
							if (msg_len < sizeof(ip_report_t)) {
								MSG(M_ERR, "Unknown report format from listener");
							}
							else {
								handle_ipoutput(ptr);
							}
						}
						else if (s->ss->mode == MODE_ARPSCAN) {
							handle_arpoutput(ptr);
						}

					}
					else {
						MSG(M_ERR, "Unhandled message from `%s' drone message type `%s' with status %d", (c->type == DRONE_TYPE_SENDER ? "Sender" : "Listener"), strmsgtype(msg_type), status);
					}
					if (getret == 0) break;
				} /* multiple message read loop */
			} /* readable fd */
		}
		if (breakout) break;
	}

	if (s->verbose > 3) MSG(M_DBG1, "###### Waiting for listener packet timeout %d seconds", s->ss->recv_timeout);

	if (1) {
		unsigned int remain=s->ss->recv_timeout;

		while (1) {
			remain=sleep(remain);
			if (remain == 0) {
				break;
			}
		}
	}

	while (1) {
		uint32_t d_offset=0;
		int pret=0;

		for (c=s->dlh->head ; c != NULL ; c=c->next) {
			if (c->type != DRONE_TYPE_LISTENER) {
				if (s->verbose > 7) MSG(M_DBG2, "skipping drone type %d", c->type);
				continue;
			}
			if (c->status == DRONE_STATUS_DEAD) {
				if (s->verbose > 5) MSG(M_DBG2, "skipping dead drone type %d", c->type);
				continue;
			}

			if (c->status == DRONE_STATUS_READY && !(GET_LISTENDRONE())) {
				if (send_message(c->s, MSG_TERMINATE, MSG_STATUS_OK, NULL, 0) < 0) {
					MSG(M_ERR, "Can't tell listener to quit, this scan is useless");
					mark_dead(c, DRONE_STATUS_DEAD);
					continue;
				}
				if (s->verbose > 6) MSG(M_DBG2, "Told listener on fd %d to go into reporting mode", c->s);
				c->status=DRONE_STATUS_WORKING;
			}
		}

		for (c=s->dlh->head, d_offset=0 ; c != NULL ; c=c->next, d_offset++) {
			spdf[d_offset].fd=c->s;
		}

		if (s->listeners && (pret=xpoll(&spdf[0], s->dlh->size, -1)) < 0) {
			MSG(M_ERR, "Poll drone fd's fail: %s", strerror(errno));
		}

		for (c=s->dlh->head, d_offset=0 ; c != NULL ; c=c->next, d_offset++) {
			c->s_rw=0;
			if (c->status != DRONE_STATUS_DEAD) c->s_rw=spdf[d_offset].rw;
			if (spdf[d_offset].rw & XPOLL_READABLE) {
				if (s->verbose > 7) MSG(M_DBG1, "Socket type %s is readable", (c->type == DRONE_TYPE_LISTENER) ? "Listener" : "Sender");
			}
		}

		for (c=s->dlh->head ; c != NULL ; c=c->next) {
			if (c->status != DRONE_STATUS_DEAD && c->status != DRONE_STATUS_DONE && c->s_rw & XPOLL_READABLE) {
				int getret=0;

				if (recv_messages(c->s) < 0) {
					MSG(M_ERR, "read fd %d fails, marking as dead", c->s);
					mark_dead(c, DRONE_STATUS_DEAD);
					continue;
				}

				while (1) {
					if (c->status == DRONE_STATUS_DONE || c->status == DRONE_STATUS_DEAD) break;
					getret=get_message(c->s, &msg_type, &status, &ptr, &msg_len);
					if (getret < 1) break;
					if (s->verbose > 5) MSG(M_DBG2, "Got message type `%s [%d]' from a Listener Drone with status %d and %p data", strmsgtype(msg_type), msg_type, status, ptr);
					if (msg_type == MSG_ERROR || status != MSG_STATUS_OK) {
						MSG(M_ERR, "Got bad message from listener on fd %d, marking as dead", c->s);
						mark_dead(c, DRONE_STATUS_DEAD);
						continue;
					}
					else if (msg_type == MSG_OUTPUT) {
						if (s->ss->mode == MODE_TCPSCAN || s->ss->mode == MODE_UDPSCAN) {
							if (msg_len < sizeof(ip_report_t)) {
								MSG(M_ERR, "Unknown report format from listener on fd %d", c->s);
							}
							else {
								handle_ipoutput(ptr);
							}
						}
						else if (s->ss->mode == MODE_ARPSCAN) {
							handle_arpoutput(ptr);
						}
					}
					else if (msg_type == MSG_QUIT) {
						mark_dead(c, DRONE_STATUS_DONE);
					}
					else {
						MSG(M_ERR, "Unknown message from listener %d on fd %d, marking as dead", msg_type, c->s);
						/* hrmm, welp i dont get this drone, lets stop talking to him */
						mark_dead(c, DRONE_STATUS_DEAD);
					}
					if (getret == 0) break;
				} /* while messages are read */
			}
		} /* for reading listeners */
		if (s->listeners == 0) break;
	}

	if (s->ss->mode == MODE_UDPSCAN || s->ss->mode == MODE_TCPSCAN) {
		do_report();
	}
	else if (s->ss->mode == MODE_ARPSCAN) {
		do_arpreport();
	}
		
}