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(); } }