void recv_packet(void) {
	char errbuf[PCAP_ERRBUF_SIZE], pfilter[512], base_filter[256], addr_filter[64], defhost[64];
	struct bpf_program filter;
	struct sockaddr_in lsin;
	bpf_u_int32 net, mask;
	int ac_s=0, ret=0;
	uint32_t foct=0, defport=0;
	uint8_t msg_type=0, status=0, *ptr=NULL;
	size_t msg_len=0;
	xpoll_t spdf[2];
	union {
		void *ptr;
		uint8_t *cr;
		uint16_t *r_magic;
	} r_u;
	union {
		recv_udp_workunit_t *u;
		recv_tcp_workunit_t *t;
		recv_arp_workunit_t *a;
		uint8_t *cr;
		uint32_t *magic;
	} wku;
	union {
		listener_info_t *l;
		uint8_t *ptr;
	} l_u;

	r_queue=fifo_init();

	close_output_modules();
	close_report_modules();
	close_payload_modules();

	if (s->verbose > 3) MSG(M_DBG1, "Creating server socket");

	CLEAR(defhost); CLEAR(defport);

	/* heh */
	if (sscanf(DEF_LISTENER, "%63[0-9.]:%u", defhost, &defport) != 2) {
		MSG(M_ERR, "Cant parse default listener data `%s'", DEF_LISTENER);
		terminate(TERM_ERROR);
	}

	if (inet_aton(defhost, &lsin.sin_addr) < 0) {
		MSG(M_ERR, "Can't parse default host `%s'", defhost);
		terminate(TERM_ERROR);
	}
	if (defport > 0xFFFF) {
		MSG(M_ERR, "Default listening port is out of range");
		terminate(TERM_ERROR);
	}

	lsin.sin_port=htons(defport);
	lsin.sin_addr.s_addr=htonl(INADDR_ANY);

	if ((ac_s=create_server_socket((const struct sockaddr_in *)&lsin)) < 0) {
		MSG(M_ERR, "cant create listener socket");
		terminate(TERM_ERROR);
	}

	if (s->verbose > 3) MSG(M_DBG1, "Waiting for main to connect");

	lc_s=wait_for_client(ac_s);
	if (lc_s < 0) {
		MSG(M_ERR, "main didnt connect, exiting");
		terminate(TERM_ERROR);
	}
	if (s->verbose > 3) MSG(M_DBG1, "Got connection");

	if (get_singlemessage(lc_s, &msg_type, &status, &ptr, &msg_len) != 1) {
		MSG(M_ERR, "Unexpected sequence of messages from parent waiting for ident request, exiting");
		terminate(TERM_ERROR);
	}

	if (msg_type != MSG_IDENT || status != MSG_STATUS_OK) {
		MSG(M_VERB, "Got an unknown message type `%s' or bad status %d from parent, exiting", strmsgtype(msg_type), status);
	}

	if (send_message(lc_s, MSG_IDENTLISTENER, MSG_STATUS_OK, NULL, 0) < 0) {
		MSG(M_ERR, "Can't send back msgident to parent");
		terminate(TERM_ERROR);
	}

	if (get_singlemessage(lc_s, &msg_type, &status, &ptr, &msg_len) != 1) {
		MSG(M_ERR, "Can't read ident ack message from parent, exiting");
		terminate(TERM_ERROR);
	}
	if (msg_type != MSG_ACK || status != MSG_STATUS_OK) {
		MSG(M_VERB, "Got an unknown message type `%s' or bad status %d from parent, exiting", strmsgtype(msg_type), status);
	}

	if (s->verbose > 3) MSG(M_DBG1, "Sending ready message to parent");

	l_u.l=(listener_info_t *)xmalloc(sizeof(listener_info_t));
	l_u.l->myaddr=s->vi->myaddr.sin_addr.s_addr;
	memcpy(l_u.l->hwaddr, s->vi->hwaddr, THE_ONLY_SUPPORTED_HWADDR_LEN);
	l_u.l->mtu=s->vi->mtu;

	if (send_message(lc_s, MSG_READY, MSG_STATUS_OK, l_u.ptr, sizeof(listener_info_t)) < 0) {
		MSG(M_ERR, "Cant send message ready");
		terminate(TERM_ERROR);
	}

	xfree(l_u.l);

	/* XXX */
	s->_low_ip=0;
	s->_high_ip=0;
	s->repeats=0;
	s->pps=0;
	s->port_str=NULL;
	s->ss->syn_key=0;

	memset(s->ss, 0, sizeof(scan_settings_t));

	if (get_singlemessage(lc_s, &msg_type, &status, &(wku.cr), &msg_len) != 1) {
		MSG(M_ERR, "Unexpected sequence of messages from parent looking for a workunit");
		terminate(TERM_ERROR);
	}

	if (msg_type == MSG_QUIT || status != MSG_STATUS_OK) terminate(0);

	if (msg_type != MSG_WORKUNIT) {
		MSG(M_ERR, "I was expecting a work unit or quit message, i got a `%s' message", strmsgtype(msg_type));
		terminate(TERM_ERROR);
	}

	assert(wku.magic != NULL);
	if (*wku.magic == UDP_RECV_MAGIC) {
		if (s->verbose > 5) MSG(M_DBG2, "Got udp workunit");

		s->ss->mode=MODE_UDPSCAN;
		s->ss->recv_timeout=wku.u->recv_timeout;
		s->vi->mtu=wku.u->mtu;
		s->recv_opts=wku.u->recv_opts;
	}
	else if (*wku.magic == TCP_RECV_MAGIC) {
		if (s->verbose > 5) MSG(M_DBG2, "Got tcp workunit");

		s->ss->mode=MODE_TCPSCAN;
		s->ss->recv_timeout=wku.t->recv_timeout;
		s->vi->mtu=wku.t->mtu;
		s->recv_opts=wku.t->recv_opts;

		s->ss->syn_key=wku.t->syn_key;
	}
	else if (*wku.magic == ARP_RECV_MAGIC) {
		if (s->verbose > 5) MSG(M_DBG2, "Got arp workunit");

		s->ss->mode=MODE_ARPSCAN;
		s->ss->recv_timeout=wku.a->recv_timeout;
		s->vi->mtu=wku.a->mtu;
		s->recv_opts=wku.a->recv_opts;
	}
	else {
		MSG(M_ERR, "Unknown workunit type `%c'", *wku.cr);
		terminate(0);
	}

	s->mode=s->ss->mode; /* XXX */

	if (s->verbose > 3) {
		if (s->ss->mode == MODE_TCPSCAN) {
			MSG(M_DBG1, "FROM IPC: TCP scan recv_timeout %d mtu %d recv_opts %x syn_key %.08x", s->ss->recv_timeout, s->vi->mtu, s->recv_opts, s->ss->syn_key);
		}
		else if (s->ss->mode == MODE_UDPSCAN) {
			MSG(M_DBG1, "FROM IPC: UDP scan recv_timeout %d mtu %d recv_opts %x", s->ss->recv_timeout, s->vi->mtu, s->recv_opts);
		}
		else if (s->ss->mode == MODE_ARPSCAN) {
			MSG(M_DBG1, "FROM IPC: ARP scan recv_timeout %d mtu %d recv_opts %x", s->ss->recv_timeout, s->vi->mtu, s->recv_opts);
		}
	}

	if (GET_RETPACKET()) {
		if (s->verbose > 3) MSG(M_DBG2, "Setting up packet queue");
		p_queue=fifo_init();
	}
	if (s->ss->mode == MODE_TCPSCAN || s->ss->mode == MODE_UDPSCAN) {
		foct=(htonl(s->vi->myaddr.sin_addr.s_addr) >> 24);
		if (foct == 0x7f) {
			snprintf(addr_filter, sizeof(addr_filter) -1, "dst %s", s->vi->myaddr_s);
		}
		else {
			snprintf(addr_filter, sizeof(addr_filter) -1, "dst %s and ! src %s", s->vi->myaddr_s, s->vi->myaddr_s);
		}
	}
Пример #2
0
void process_packet(uint8_t *user, const struct pcap_pkthdr *phdr, const uint8_t *packet) {
	const struct myiphdr *ip_ptr=NULL;
	const struct mytcphdr *tcp_ptr=NULL;
	const uint8_t *data=NULL;
	size_t hdrlen=0;
	int j=0, j1=0;

	if (packet == NULL) return;

	hdrlen=(header_len + sizeof(struct myiphdr) + sizeof(struct mytcphdr));

	if (phdr->caplen < hdrlen) {
		ERR("Short packet at %d bytes", phdr->caplen);
		return;
	}

	ip_ptr=(const struct myiphdr *)(packet + header_len);
	tcp_ptr=(const struct mytcphdr *)(packet + header_len + sizeof(struct myiphdr));

	if (phdr->caplen > (header_len + sizeof(struct myiphdr) + (4 * tcp_ptr->doff))) {
		data=(const uint8_t *)(packet + header_len + sizeof(struct myiphdr) + (4 * tcp_ptr->doff));
	}
	else {
		data=NULL;
	}

	VRB(0, "caplen %d datalen %d "
		"sport %d dport %d doff %d"
		"seq %08x ackseq %08x "
		"window %u checksum %04x urg_ptr %d\n",
		phdr->caplen, (phdr->caplen - (header_len + sizeof(struct myiphdr) + (4 * tcp_ptr->doff))),
		ntohs(tcp_ptr->source), ntohs(tcp_ptr->dest), tcp_ptr->doff,
		tcp_ptr->seq, tcp_ptr->ack_seq, tcp_ptr->window, tcp_ptr->check,
		tcp_ptr->urg_ptr);

	for (j=0; j < MAX_CONNS ; j++) {
		if (conns[j].sport == ntohs(tcp_ptr->source) && conns[j].dport == ntohs(tcp_ptr->dest)) {
			break;
		}
		if (conns[j].sport == 0) {
			conns[j].sport=ntohs(tcp_ptr->source);
			conns[j].dport=ntohs(tcp_ptr->dest);

			if (conns[j].sport > 7999 && conns[j].sport < 8006) {
				conns[j].name=xstrdup("Master To Drone");
			}
			else if (conns[j].sport > 12320 && conns[j].sport < 12324) {
				conns[j].name=xstrdup("Drone To Master");
			}
			else {
				conns[j].name=xstrdup("Unknown");
			}
			break;
		}
	}


	if (data) {
		union {
			const ipc_msghdr_t *msg;
			const uint8_t *ptr;
		} mm_u;
		union {
			const uint8_t *ptr;
			const void *vp;
			listener_info_t *l;
		} md_u;

		mm_u.ptr=data;

		if (mm_u.msg->header != 0xf0f1f2f3) {
			ERR("BAD IPC PACKET, magic header wrong");
			return;
		}

		if (mm_u.msg->type == MSG_IDENTLISTENER) {
			if (conns[j].name) xfree(conns[j].name);
			conns[j].name=xstrdup("LISTENER To Master");
			for (j1=0 ; j1 < MAX_CONNS ; j1++) {
				if (conns[j1].dport == conns[j].sport && conns[j1].sport == conns[j].dport) {
					if (conns[j1].name) xfree(conns[j1].name);
					conns[j1].name=xstrdup("Master to LISTENER");
				}
			}
		}
		else if (mm_u.msg->type == MSG_IDENTSENDER) {
			if (conns[j].name) xfree(conns[j].name);
			conns[j].name=xstrdup("SENDER To Master");
			for (j1=0 ; j1 < MAX_CONNS ; j1++) {
				if (conns[j1].dport == conns[j].sport && conns[j1].sport == conns[j].dport) {
					if (conns[j1].name) xfree(conns[j1].name);
					conns[j1].name=xstrdup("Master to SENDER");
				}
			}
		}

		MSG(M_INFO, "{%s}\tMessagetype %s status %d len %d", (conns[j].name == NULL ? "Unknown" : conns[j].name), strmsgtype(mm_u.msg->type), mm_u.msg->status, mm_u.msg->len);

		if (mm_u.msg->len > 0) {
			struct in_addr ia1;

			if (mm_u.msg->len != (phdr->caplen - (header_len + sizeof(struct myiphdr) + (4 * tcp_ptr->doff) + sizeof(ipc_msghdr_t)))) {
				MSG(M_ERR, "BAD IPC PACKET!");
				return;
			}
			md_u.ptr=data + sizeof(ipc_msghdr_t);

			switch (mm_u.msg->type) {
				case MSG_WORKUNIT:
					MSG(M_OUT, "WORKUNIT: `%s'", strworkunit(md_u.vp, (size_t )mm_u.msg->len));
					break;
				case MSG_READY:
					if (mm_u.msg->len == sizeof(listener_info_t)) {
						ia1.s_addr=md_u.l->myaddr;
						MSG(M_OUT, "Ready with IP %s HWADDR %s MTU %u", inet_ntoa(ia1), decode_6mac(md_u.l->hwaddr), md_u.l->mtu);
					}
					else {
						MSG(M_OUT, "Unknown ready infomation");
					}
				default:
					break;
			}
		}
	}
	return;
}
Пример #3
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");
}
Пример #4
0
void recv_packet(void) {
	char errbuf[PCAP_ERRBUF_SIZE], *pfilter=NULL;
	struct bpf_program filter;
	bpf_u_int32 net, mask;
	int ac_s=0, ret=0, worktodo=1;
	uint8_t msg_type=0, status=0, *ptr=NULL;
	size_t msg_len=0;
	xpoll_t spdf[2];
	union {
		recv_workunit_t *r;
		uint8_t *cr;
		uint32_t *magic;
	} wk_u;
	union {
		listener_info_t *l;
		uint8_t *ptr;
	} l_u;
	union {
		drone_version_t *v;
		uint8_t *ptr;
	} d_u;
	drone_version_t dv;
	struct pcap_stat pcs;

	r_queue=fifo_init();

	close_output_modules();
	close_report_modules();
	close_payload_modules();

	DBG(M_IPC, "creating server socket");

	memset(s->ss, 0, sizeof(scan_settings_t));

	memset(&dv, 0, sizeof(dv));
	d_u.v=&dv;
	dv.magic=DRONE_MAGIC;
	dv.maj=DRONE_MAJ;
	dv.min=DRONE_MIN;
	recv_stats_t recv_stats;

	/* heh */
	if ((ac_s=socktrans_bind(s->ipcuri)) < 0) {
		terminate("cant create listener socket");
	}

	DBG(M_IPC, "waiting for main to connect");

	parent_sync();

	lc_s=socktrans_accept(ac_s, DEF_SOCK_TIMEOUT);
	if (lc_s < 0) {
		terminate("main didnt connect, exiting");
	}

	DBG(M_IPC, "got connection");

	if (get_singlemessage(lc_s, &msg_type, &status, &ptr, &msg_len) != 1) {
		terminate("unexpected sequence of messages from parent waiting for ident request, exiting");
	}

	if (msg_type != MSG_IDENT || status != MSG_STATUS_OK) {
		ERR("got an unknown message type `%s' or bad status %d from parent, exiting", strmsgtype(msg_type), status);
	}

	if (send_message(lc_s, MSG_IDENTLISTENER, MSG_STATUS_OK, d_u.ptr, sizeof(drone_version_t)) < 0) {
		terminate("cant send back msgident to parent");
	}

	if (get_singlemessage(lc_s, &msg_type, &status, &ptr, &msg_len) != 1) {
		terminate("cant read ident ack message from parent, exiting");
	}
	if (msg_type != MSG_ACK || status != MSG_STATUS_OK) {
		ERR("got an unknown message type `%s' or bad status %d from parent, exiting", strmsgtype(msg_type), status);
	}

	DBG(M_IPC, "sending ready message to parent");

	l_u.l=(listener_info_t *)xmalloc(sizeof(listener_info_t));

	memcpy(&l_u.l->myaddr, &s->vi[0]->myaddr, sizeof(struct sockaddr_storage));
	memcpy(&l_u.l->mymask, &s->vi[0]->mymask, sizeof(struct sockaddr_storage));
	memcpy(l_u.l->hwaddr, s->vi[0]->hwaddr, THE_ONLY_SUPPORTED_HWADDR_LEN);
	l_u.l->mtu=s->vi[0]->mtu;

	assert(s->interface_str != NULL);

	if (pcap_lookupnet(s->interface_str, &net, &mask, errbuf) < 0) {
		ERR("pcap_lookupnet fails, ignoring: %s", errbuf);
	}

	if (s->pcap_readfile == NULL) {
		pdev=pcap_open_live(s->interface_str, /* XXX haha */ s->vi[0]->mtu + 64, (GET_PROMISC() ? 1 : 0), 0, errbuf);
		if (pdev == NULL) {
			ERR("pcap open live: %s", errbuf);

			DBG(M_IPC, "sending ready error message to parent");
			if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
				terminate("cant send message ready error");
			}
			terminate("informed parent, exiting");
		}
	}
	else {
		pdev=pcap_open_offline(s->pcap_readfile, errbuf);
		if (pdev == NULL) {
			ERR("pcap open offline: %s", errbuf);

			DBG(M_IPC, "sending ready error message to parent");
			if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
				terminate("cant send message ready error");
			}
			terminate("informed parent, exiting");
		}
	}

	ret=util_getheadersize(pdev, errbuf);
	if (ret < 0 || ret > 0xffff) {
		ERR("error getting link header size: %s", errbuf);

		DBG(M_IPC, "sending ready error message to parent");
		if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
			terminate("cant send message ready error");
		}
		terminate("informed parent, exiting");
	}
	s->ss->header_len=(uint16_t)ret;

	if (s->pcap_dumpfile != NULL) {
		VRB(0, "opening `%s' for pcap log", s->pcap_dumpfile);
		pdump=pcap_dump_open(pdev, s->pcap_dumpfile);
		if (pdump == NULL) {
			ERR("cant log to pcap file `%s'", pcap_geterr(pdev));

			DBG(M_IPC, "sending ready error message to parent");
			if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
				terminate("cant send message ready error");
			}
			terminate("informed parent, exiting");
		}
	}
	else {
		DBG(M_CLD, "not logging to pcap file");
	}

	if (util_preparepcap(pdev, errbuf) < 0) {
		ERR("cant setup pcap filedesc to immediate mode: %s", errbuf);

		DBG(M_IPC, "sending ready error message to parent");
		if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
			terminate("cant send message ready error");
		}
		terminate("informed parent, exiting");
	}

	/* pcap_fd will be -1 for a pcap file */
	pcap_fd=pcap_get_selectable_fd(pdev);

	if (pcap_fd < 0 && s->pcap_readfile == NULL) {
		ERR("cant get selectable fd from pcap device, exiting");

		DBG(M_IPC, "sending ready error message to parent");
		if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
			terminate("sant send message ready error");
		}
		terminate("informed parent, exiting");
	}

#ifdef PCAP_D_IN
	if (pcap_setdirection(pdev, PCAP_D_IN) < 0) {
		ERR("cant set pcap direction to in, exiting");

		DBG(M_IPC, "sending ready error message to parent");
		if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
			terminate("sant send message ready error");
		}
		terminate("informed parent, exiting");
	}
#endif

	DBG(M_CLD, "listener dropping privs");

	if (drop_privs() < 0) {
		terminate("cant drop privs");
	}

	if (send_message(lc_s, MSG_READY, MSG_STATUS_OK, l_u.ptr, sizeof(listener_info_t)) < 0) {
		terminate("cant send message ready");
	}

	xfree(l_u.l);

	/* XXX */
	s->ss->syn_key=0;

	do {
		if (get_singlemessage(lc_s, &msg_type, &status, &wk_u.cr, &msg_len) != 1) {
			terminate("unexpected sequence of messages from parent looking for a workunit");
		}

		if (status != MSG_STATUS_OK) {
			terminate("bad message status %u", status);
		}

		if (msg_type == MSG_QUIT) {
			worktodo=0;
			break;
		}
		else if (msg_type == MSG_WORKUNIT) {
			;
		}
		else {
			terminate("unexpected message, expecting workunit or quit message");
		}

		if (msg_len < sizeof(uint32_t)) {
			terminate("bad message, too short [" STFMT "]", msg_len);
		}

		if (msg_len < sizeof(recv_workunit_t)) {
			terminate("short workunit");
		}

		worktodo=1;

		DBG(M_WRK, "workunit `%s'", strworkunit(wk_u.cr, msg_len));

		s->ss->recv_timeout=wk_u.r->recv_timeout;
		s->ss->ret_layers=wk_u.r->ret_layers;
		s->recv_opts=wk_u.r->recv_opts;
		s->ss->window_size=wk_u.r->window_size;

		s->ss->syn_key=wk_u.r->syn_key;

		if (wk_u.r->pcap_len) {
			if ((msg_len - sizeof(recv_workunit_t)) == wk_u.r->pcap_len) {
				extract_pcapfilter(wk_u.cr + sizeof(recv_workunit_t), wk_u.r->pcap_len);
			}
			else {
				terminate("pcap option length illegal");
			}
		}

		switch (*wk_u.magic) {
			case UDP_RECV_MAGIC:
				s->ss->mode=MODE_UDPSCAN;
				break;

			case TCP_RECV_MAGIC:
				s->ss->mode=MODE_TCPSCAN;
				break;

			case ARP_RECV_MAGIC:
				s->ss->mode=MODE_ARPSCAN;
				break;

			default:
				terminate("unknown recv workunit type");
				break;
		}

		DBG(M_IPC, "from ipc, got workunit: %s", strworkunit((const void *)wk_u.cr, msg_len));

		if (s->ss->mode == MODE_ARPSCAN) {
			if (s->ss->header_len != 14) {

				DBG(M_IPC, "sending msg error");
				if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
					terminate("cant send message ready");
				}
				terminate("wrong linktype for arp scan");
			}
		}

		if (s->ss->ret_layers > 0) {
			DBG(M_CLD, "setting up packet queue");
			p_queue=fifo_init();
		}

		pfilter=get_pcapfilterstr();

		VRB(1, "using pcap filter: `%s'", pfilter);

		memset(&filter, 0, sizeof(filter));
		if (pcap_compile(pdev, &filter, pfilter, 0, net) < 0) {
			ERR("error compiling filter: %s",  pcap_geterr(pdev));

			if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
				ERR("cant send message ready error");
			}
			terminate("cant compile pcap filter");
		}

		if (pcap_setfilter(pdev, &filter) < 0) {
			ERR("error setting compiled filter: %s", pcap_geterr(pdev));

			if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) {
				ERR("cant send message ready error");
			}
			terminate("cant set compiled pcap filter");
		}

		pcap_freecode(&filter);

		if (s->ss->ret_layers > 0) {
			DBG(M_IPC, "returning whole packet via ipc");
		}

		DBG(M_IPC, "sending ready message to parent");

		if (pcap_setnonblock(pdev, 1, errbuf) < 0) {
			terminate("cant set pcap non-blocking mode");
		}

		if (send_message(lc_s, MSG_READY, MSG_STATUS_OK, NULL, 0) < 0) {
			terminate("cant send message ready");
		}

		while (1) {
			spdf[0].fd=lc_s;
			spdf[1].fd=pcap_fd;

			/* if pdev is a socket  ( ! -1 ) */
			if (xpoll(&spdf[0], 2, -1) < 0) {
				ERR("xpoll fails: %s", strerror(errno));
			}

			if (spdf[1].rw & XPOLL_READABLE) {
				pcap_dispatch(pdev, 1, parse_packet, NULL);
			}

			/* no packets, better drain the queue */
			drain_pqueue();

			if (spdf[0].rw & XPOLL_READABLE) {
				if (get_singlemessage(lc_s, &msg_type, &status, &ptr, &msg_len) != 1) {
					ERR("unexpected sequence of messages from parent in main read loop, exiting");
					worktodo=0;
					break;
				}

				if (msg_type == MSG_TERMINATE) {
					DBG(M_IPC, "parent wants me to stop listening, breaking");
					break;
				}
				else if (msg_type == MSG_QUIT) {
					DBG(M_IPC, "Parent wants me to quit, breaking");
					worktodo=0;
					break;
				}
				else {
					ERR("got strange message `%s' from parent, exiting", strmsgtype(msg_type));
					worktodo=0;
					break;
				}
			}
		}

		memset(&recv_stats, 0, sizeof(recv_stats));

		if (pcap_stats(pdev, &pcs) != -1) {

			recv_stats.packets_recv=pcs.ps_recv;
			recv_stats.packets_dropped=pcs.ps_drop;
			recv_stats.packets_dropped=pcs.ps_ifdrop;
		}

		if (send_message(lc_s, MSG_WORKDONE, MSG_STATUS_OK, (void *)&recv_stats, sizeof(recv_stats)) < 0) {
			terminate("cant send workdone message to parent, exiting");
		}

	} while (worktodo);

	pcap_close(pdev);
	if (s->pcap_dumpfile) {
		pcap_dump_close(pdump);
	}


	DBG(M_CLD, "listener exiting");

	shutdown(lc_s, SHUT_RDWR);
	close(lc_s);
 
	uexit(0);
}
Пример #5
0
int main(int argc, char **argv) {
	char buf[4096];
	pid_t chld_listener=-1, chld_sender=-1;
	uint8_t status=0, msg_type=0, ecount=0;
	size_t msg_len=0;
	struct sigaction chsa;
	uint8_t *ptr=NULL;
	int lports=IPC_BINDPORT_START;
	uint8_t all_done=0;
	char verbose_level[4];
	drone_t *c=NULL;

	ident=IDENT_MASTER;
	ident_name_ptr=IDENT_MASTER_NAME;

	CLEAR(buf);

	s=(settings_t *)xmalloc(sizeof(settings_t));
	memset(s, 0, sizeof(settings_t));
	s->vi=(interface_info_t *)xmalloc(sizeof(interface_info_t));
	memset(s->vi, 0, sizeof(interface_info_t));

	s->forked=0; /* not required, for clarity */

	/* s->display=&display_builtin; */

	getconfig_argv(argc, argv);

	if (s->interface_str == NULL) {
		if (get_default_route_interface(&s->interface_str) != 1) {
			MSG(M_WARN, "Can't find default route, and matching device, using default interface `%s'", DEFAULT_NETDEV);
			s->interface_str=xstrdup(DEFAULT_NETDEV);
		}
		if (s->verbose > 1) {
			MSG(M_VERB, "Using interface %s", s->interface_str);
		}
	}

	if (!(GET_OVERRIDE())) {
		/* let the listener tell us then, the user didnt request a specific address */
		CLEAR(s->vi->myaddr_s); CLEAR(s->vi->hwaddr_s);
		sprintf(s->vi->myaddr_s, "0.0.0.0");
		sprintf(s->vi->hwaddr_s, "00:00:00:00:00:00");
		memset(&s->vi->myaddr, 0, sizeof(s->vi->myaddr));
		memset(&s->vi->hwaddr, 0, sizeof(s->vi->hwaddr));
        }
	else {
		/* complete the information we need like hwaddr, cause its impossible to specify that currently */
		if (s->verbose > 1) MSG(M_DBG2, "Spoofing from `%s [%s]'", s->vi->myaddr_s, s->vi->hwaddr_s);

		/* the ip info is already filled in, so just complete the rest */
		CLEAR(s->vi->hwaddr_s);
		sprintf(s->vi->hwaddr_s, "00:00:00:00:00:00");
		memset(&s->vi->hwaddr, 0, sizeof(s->vi->hwaddr));
	}
	s->vi->mtu=0; /* the listener HAS to tell us this, seeing as how the real limitation is there */

	time(&(s->s_time));

	if (s->forklocal) {
		if (s->verbose > 5) MSG(M_DBG2, "children will be forked, setting up signal handler for them");

		memset(&chsa, 0, sizeof(chsa));
		chsa.sa_handler=&child_dead;
		if (sigaction(SIGCHLD, &chsa, NULL) < 0) {
			MSG(M_ERR, "Cant register SIGCHLD handler");
			terminate(TERM_ERROR);
		}
	}

	arc4random_stir();

	if (init_modules() < 0) {
		MSG(M_ERR, "Can't initialize module structures, quiting");
		terminate(TERM_ERROR);
	}

	if (ipc_init() < 0) {
		MSG(M_ERR, "Cant initialize IPC, quiting");
		terminate(TERM_ERROR);
	}

	if (s->verbose > 0) {
		char low[32], high[32];
		uint32_t ips=0;

		CLEAR(low); CLEAR(high);
		ips=ntohl(s->_low_ip);
		snprintf(low, sizeof(low) -1, "%s", inet_ntoa((*(struct in_addr *)&ips)));
		ips=ntohl(s->_high_ip);
		snprintf(high, sizeof(high) -1, "%s", inet_ntoa((*(struct in_addr *)&ips)));

		MSG(M_VERB, "Scanning: %s -> %s : %s from %s [%s] at %u pps", low, high, (s->mode == MODE_ARPSCAN ? "Arp" : s->port_str), s->vi->myaddr_s, s->vi->hwaddr_s, s->pps);
	}

	if (s->verbose > 3) MSG(M_DBG1, "Main process id is %d", getpid());

	snprintf(verbose_level, sizeof(verbose_level) -1, "%d", s->verbose);

	/* initialize senders */
	if ((s->forklocal & FORK_LOCAL_SENDER) == FORK_LOCAL_SENDER) {
		if (s->drone_str == NULL) {
			s->drone_str=xstrdup(DEF_SENDER);
			if (s->verbose > 5) MSG(M_DBG2, "Added default sender to drone list `%s'", s->drone_str);
		}
		else {
			char newstr[128];

			CLEAR(newstr);
			snprintf(newstr, sizeof(newstr) -1, "%s,%s", s->drone_str, DEF_SENDER);
			xfree(s->drone_str);
			s->drone_str=xstrdup(newstr);
		}

		chld_sender=fork();
		if (chld_sender < 0) {
			MSG(M_ERR, "Can't fork sender: %s", strerror(errno));
			terminate(TERM_ERROR);
		}
		if (chld_sender == 0) {
			char *argz[5];
			char *envz[2];

			argz[0]=SENDERNAME;
			argz[1]=s->mod_dir;
			argz[2]=verbose_level;
			argz[3]=s->interface_str;
			argz[4]=NULL;

			envz[0]='\0';

			execve(SENDER_PATH, argz, envz);
			MSG(M_ERR, "execve %s fails", SENDER_PATH);
			terminate(TERM_ERROR);
		}
		child_running++;
		s->forklocal &= ~(FORK_LOCAL_SENDER);
	}
	else if (s->verbose > 5) {
		MSG(M_DBG2, "No local sender will be forked");
	}

	/* initialize listeners */
	if ((s->forklocal & FORK_LOCAL_LISTENER) == FORK_LOCAL_LISTENER) {
		if (s->drone_str == NULL) {
			s->drone_str=xstrdup(DEF_LISTENER);
			if (s->verbose > 5) MSG(M_DBG2, "Adding default listener to drone list");
		}
		else {
			char newstr[128];

			CLEAR(newstr);
			snprintf(newstr, sizeof(newstr) -1, "%s,%s", s->drone_str, DEF_LISTENER);
			xfree(s->drone_str);
			s->drone_str=xstrdup(newstr);
		}

		chld_listener=fork();
		if (chld_listener < 0) {
			MSG(M_ERR, "Can't fork listener: %s", strerror(errno));
			terminate(TERM_ERROR);
		}
		if (chld_listener == 0) {
			char *argz[7];
			char *envz[2];
			char mtu[8];

			CLEAR(mtu);
			snprintf(mtu, sizeof(mtu) -1, "%u", s->vi->mtu);

			argz[0]=LISTENERNAME;
			argz[1]=s->mod_dir;
			argz[2]=verbose_level;
			argz[3]=s->interface_str;
			argz[4]=s->vi->myaddr_s;
			argz[5]=s->vi->hwaddr_s;
			argz[6]=NULL;

			envz[0]='\0';

			execve(LISTENER_PATH, argz, envz);
			MSG(M_ERR, "execve %s fails", LISTENER_PATH);
			terminate(TERM_ERROR);
		}
		child_running++;
		s->forklocal &= ~(FORK_LOCAL_LISTENER);
	}
	else if (s->verbose > 5) {
		MSG(M_DBG2, "No local listener will be forked");
	}

	/* we need these modules cause we are hardcoded as a output conduit for now XXX */
	if (init_output_modules() < 0) {
		MSG(M_ERR, "Can't initialize output module structures, quiting");
		terminate(TERM_ERROR);
	}
	if (init_report_modules() < 0) {
		MSG(M_ERR, "Can't initialize report module structures, quiting");
		terminate(TERM_ERROR);
	}

	if (s->verbose > 2) MSG(M_DBG1, "drones: %s", s->drone_str);

	if (parse_drone_list((const char *)s->drone_str) < 0) {
		terminate(TERM_ERROR);
	}
	else if (s->verbose > 5) {
		MSG(M_DBG1, "Drone list `%s' parsed correctly", s->drone_str);
	}

	/* do stuff to figure out if there are working drones */
	if (s->verbose > 4) MSG(M_DBG1, "Drone list is %d big, connecting to them.", s->dlh->size);

	do {
		uint8_t *dummy=NULL;
		struct sockaddr_in lbind;

		c=s->dlh->head;

		if (c == NULL) {
			MSG(M_ERR, "no drones?, thats not going to work");
			terminate(TERM_ERROR);
		}

		for (c=s->dlh->head ; c != NULL ; c=c->next) {
			if (s->verbose > 6) MSG(M_DBG1, "THIS NODE -> status: %d type: %s host: %s port: %d socket: %d (%d out of %d ready)", c->status, (c->type == DRONE_TYPE_SENDER ? "Sender" : "Listener") , inet_ntoa(c->dsa.sin_addr), ntohs(c->dsa.sin_port), c->s, all_done, s->dlh->size);

			if (ecount > MAX_ERRORS) {
				MSG(M_ERR, "Too many errors, exiting now");
				terminate(TERM_ERROR);
			}

			switch (c->status) {

				/* connect to it */
				case DRONE_STATUS_UNKNOWN:
					memset(&lbind, 0, sizeof(lbind));
					lbind.sin_port=htons(lports++);

					if (c->s == -1 && create_client_socket(c, (struct sockaddr_in *)&lbind) < 0) {
						c->s=-1;
						usleep(50000);
						ecount++;
					}
					else {
						c->status=DRONE_STATUS_CONNECTED;
					}
					break;

				/* find out what it is */
				case DRONE_STATUS_CONNECTED:
					c->type=DRONE_TYPE_UNKNOWN;
					if (send_message(c->s, MSG_IDENT, MSG_STATUS_OK, dummy, 0) < 0) {
						ecount++;
						MSG(M_ERR, "Cant ident message node, marking as dead");
						if (ecount > MAX_ERRORS) {
							mark_dead(c);
							break;
						}
					}
					else {
						if (get_singlemessage(c->s, &msg_type, &status, &ptr, &msg_len) != 1) {
							MSG(M_ERR, "Unexpected message response from fd %d, marking as dead", c->s);
							mark_dead(c);
						}
						switch (msg_type) {
							case MSG_IDENTSENDER:
								c->type=DRONE_TYPE_SENDER;
								s->senders++;
								break;
							case MSG_IDENTLISTENER:
								c->type=DRONE_TYPE_LISTENER;
								s->listeners++;
								break;
							default:
								MSG(M_ERR, "Unknown drone type from message %s", strmsgtype(msg_type));
								c->type=DRONE_TYPE_UNKNOWN;
						}

						if (send_message(c->s, MSG_ACK, MSG_STATUS_OK, dummy, 0) < 0) {
							MSG(M_ERR, "Cant ack ident message from node on fd %d, marking as dead", c->s);
							mark_dead(c);
						}

						c->status=DRONE_STATUS_IDENT;
					}
					break;

				/* wait for it to say its ready */
				case DRONE_STATUS_IDENT:
					if (get_singlemessage(c->s, &msg_type, &status, &ptr, &msg_len) != 1) {
						MSG(M_ERR, "Unexpected message reply from drone on fd %d, marking as dead", c->s);
						mark_dead(c);
					}
					else if (msg_type == MSG_READY) {
						c->status=DRONE_STATUS_READY;
						if (s->verbose > 3) MSG(M_DBG1, "drone on fd %d is ready", c->s);
						if (c->type == DRONE_TYPE_LISTENER) {
							union {
								listener_info_t *l;
								uint8_t *ptr;
							} l_u;
							struct in_addr ia;

							if (msg_len != sizeof(listener_info_t)) {
								MSG(M_ERR, "Listener didnt send me the correct information, marking dead");
								mark_dead(c);
							}
							l_u.ptr=ptr;
							s->vi->myaddr.sin_addr.s_addr=l_u.l->myaddr;
							ia.s_addr=s->vi->myaddr.sin_addr.s_addr;
							s->vi->mtu=l_u.l->mtu;
							memcpy(s->vi->hwaddr, l_u.l->hwaddr, THE_ONLY_SUPPORTED_HWADDR_LEN);
							snprintf(s->vi->hwaddr_s, sizeof(s->vi->hwaddr_s) -1, "%.02x:%.02x:%.02x:%.02x:%.02x:%.02x", l_u.l->hwaddr[0], l_u.l->hwaddr[1], l_u.l->hwaddr[2], l_u.l->hwaddr[3], l_u.l->hwaddr[4], l_u.l->hwaddr[5]);
							snprintf(s->vi->myaddr_s, sizeof(s->vi->myaddr_s) -1, "%s", inet_ntoa(ia));

							if (s->verbose > 2) MSG(M_DBG1, "Listener info gave me the following address information `%s [%s]' with mtu %u", s->vi->myaddr_s, s->vi->hwaddr_s, s->vi->mtu);
						}
					}
					else {
						MSG(M_ERR, "drone isnt ready on fd %d, marking as dead", c->s);
						mark_dead(c);
					}
					break;

				case DRONE_STATUS_READY:
					all_done++;
					break;

				case DRONE_STATUS_DEAD:
					all_done++;
					MSG(M_WARN, "Dead drone in list on fd %d", c->s);
					break;

			} /* switch node status */
		} /* step though list */
	} while (all_done < s->dlh->size);

	/* XXX remove this and fix */
	if (s->senders == 0 && GET_SENDDRONE()) {
		/* XXX */
		MSG(M_ERR, "No senders for scan, giving up and rudley disconnecting from other drones without warning");
		terminate(TERM_ERROR);
	}

	if (s->listeners == 0 && GET_LISTENDRONE()) {
		/* XXX */
		MSG(M_ERR, "No listeners for scan, giving up and rudley disconnecting from other drones without warning");
		terminate(TERM_ERROR);
	}

	if (s->verbose > 5) MSG(M_DBG2, "Running scan");
	run_mode();

	time(&(s->e_time));

	if (s->verbose > 4) MSG(M_DBG2, "Main shuting down output modules");
	fini_output_modules();
	fini_report_modules();
	if (s->verbose > 4) MSG(M_DBG2, "Main exiting");

	terminate(TERM_NORMAL);
}
Пример #6
0
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();
	}
		
}