static void DestroyConnection(struct DriverConnection *conn) { api_("DestroyConnection(conn=%p {pid=%d dbus_conn=%p objpath='%s'})", conn, conn->pid, conn->dbus, conn->objpath); if (conn->dbus) { verbose_("close and unref DBus conn=%p", conn->dbus); dbus_connection_close(conn->dbus); dbus_connection_unref(conn->dbus); conn->dbus = NULL; } if (conn->pid > 0) { TerminateChild(conn->pid); conn->pid = 0; } }
/*---------------------------------------------------------------------------* * NAME: xml_parsing * DESC: Main xml parsing function *---------------------------------------------------------------------------*/ void xml_parsing(config *conf) { /* open the file using the libxml2 library */ debug(3, "xml parsing of the file: %s\n", conf->xml_filename); conf->doc = xmlParseFile(conf->xml_filename); if (conf->doc == NULL) { error_("Document not parsed successfully!\n"); return; } verbose_("[*] parsing the file: %s\n", conf->xml_filename); /* point on the root element of the tree */ conf->cur = xmlDocGetRootElement(conf->doc); if (conf->cur == NULL) { error_("Empty Document!\n"); xmlFreeDoc(conf->doc); return; } /* check if the format seems to be PDML: ie root = pdml */ debug(3,"name of the root: %s\n", conf->cur->name); if (xmlStrcmp(conf->cur->name, (const xmlChar *) "pdml")) { error_("Document NOT a PDML file!\n"); xmlFreeDoc(conf->doc); return; } /* start the autodafe's script language */ output_("/*--------------------------------------------------------------------------*\n"); output_(" * xml autodafe's parser v.%d.%d (c) Martin Vuagnoux - 2004-2006 *\n", MAJOR_VERSION, MINOR_VERSION); output_(" * auto-generated script using PDML (Packet Details Markup Language) source *\n"); output_(" *--------------------------------------------------------------------------*/\n\n"); /* the file is good, check for the packet entry (child) */ conf->cur = conf->cur->xmlChildrenNode; while (conf->cur != NULL) { if (!xmlStrcmp(conf->cur->name, (const xmlChar *) "packet")) { debug(3, "packet field found\n"); /* open the block */ output_(AD_F_BLOCK_BEGIN"(\"packet_%d\");\n", conf->packet_counter); /* parse the internal data of the packet block */ xml_parse_packet(conf); /* close the block */ output_(AD_F_BLOCK_END"(\"packet_%d\");\n", conf->packet_counter); /* client send/recv */ if ((conf->ip_pkt == conf->ip_client) && (conf->port_pkt == conf->port_client)) { debug(3, "check client\n"); if (conf->transport_type == 1) { if (conf->invert == 0) output_(AD_F_SEND"(\"packet_%d\"); /* tcp */\n\n", conf->packet_counter); else output_(AD_F_RECV"(\"packet_%d\"); /* tcp */\n\n", conf->packet_counter); } else if (conf->transport_type == 2) { if (conf->invert == 0) output_(AD_F_SEND"(\"packet_%d\"); /* udp */\n\n", conf->packet_counter); else output_(AD_F_RECV"(\"packet_%d\"); /* udp */\n\n", conf->packet_counter); } } /* server send/recv */ else if ((conf->ip_pkt == conf->ip_server) && (conf->port_pkt == conf->port_server)) { debug(3, "check server\n"); if (conf->transport_type == 1) { if (conf->invert == 1) output_(AD_F_SEND"(\"packet_%d\"); /* tcp */\n\n", conf->packet_counter); else output_(AD_F_RECV"(\"packet_%d\"); /* tcp */\n\n", conf->packet_counter); } else if (conf->transport_type == 2) { if (conf->invert == 1) output_(AD_F_SEND"(\"packet_%d\"); /* udp */\n\n", conf->packet_counter); else output_(AD_F_RECV"(\"packet_%d\"); /* udp */\n\n", conf->packet_counter); } } else { error_("too much different packets?! Check your Ethereal logs!\n"); error_("client: ip->%d, port->%d\n", conf->ip_client, conf->port_client); error_("server: ip->%d, port->%d\n", conf->ip_server, conf->port_server); error_("packet: ip->%d, port->%d\n", conf->ip_pkt, conf->port_pkt); exit(-1); } conf->packet_counter++; } conf->cur = conf->cur->next; } /* free */ xmlFreeDoc(conf->doc); }
/*---------------------------------------------------------------------------* * NAME: xml_parse_packet * DESC: Parse the content of a PDML packet *---------------------------------------------------------------------------*/ void xml_parse_packet(config *conf) { xmlChar *name; /* we keep a copy of cur */ xmlNodePtr cur = conf->cur; /* enter in packet */ cur = cur->xmlChildrenNode; /* init the protocol counter */ conf->proto_counter = 1; debug(3, "protocol counter: %d\n", conf->proto_counter); while (cur != NULL) { if (!(xmlStrcmp(cur->name, (const xmlChar *) "proto"))) { /* catch the name of the proto */ name = xmlGetProp(cur, "name"); /* geninfo type */ if (!strncmp(name, "geninfo", strlen(name))) { debug(3, "retreiving geninfo informations.\n", name); } /* frame type */ else if (!strncmp(name, "frame", strlen(name))) { debug(3, "retreiving frame informations.\n", name); } /* eth type */ else if (!strncmp(name, "eth", strlen(name))) { debug(3, "retreiving eth informations.\n", name); } /* ip type */ else if (!strncmp(name, "ip", strlen(name))) { debug(3, "retreiving ip informations.\n", name); xml_parse_ip(conf, cur); } /* tcp type */ else if (!strncmp(name, "tcp", strlen(name))) { debug(3, "retreiving tcp informations.\n", name); /* the communication seems to be in tcp */ if (!conf->transport_type) conf->transport_type = 1; /* udp and tcp in the same sniff ? huh not good! */ else if (conf->transport_type != 1) { error_("UDP *AND* TCP?! Check your Ethereal logs!\n"); exit(-1); } /* save the port (for identification, ip is not enough (think localhost)) */ xmlChar *value; unsigned short src_port; unsigned short dst_port; value = xml_parse_field(cur, 1, "tcp.srcport", "show"); src_port = (unsigned short) atoi(value); xmlFree(value); value = xml_parse_field(cur, 1, "tcp.dstport", "show"); dst_port = (unsigned short) atoi(value); xmlFree(value); /* save the pkt source port */ conf->port_pkt = src_port; /* save the port */ if ((conf->port_client == 0) && (conf->port_server == 0)) { if (conf->ip_client == conf->ip_pkt) { conf->port_client = src_port; conf->port_server = dst_port; } if (conf->ip_server == conf->ip_pkt) { conf->port_client = dst_port; conf->port_server = src_port; } } } /* udp type */ else if (!strncmp(name, "udp", strlen(name))) { debug(3, "retreiving udp informations.\n", name); /* the communication seems to be in udp */ if (!conf->transport_type) conf->transport_type = 2; /* udp and tcp in the same sniff ? huh not good! */ else if (conf->transport_type != 2) { error_("UDP *AND* TCP?! Check your Ethereal logs!\n"); exit(-1); } /* save the port (for identification, ip is not enough (think localhost)) */ xmlChar *value; unsigned short src_port; unsigned short dst_port; value = xml_parse_field(cur, 1, "udp.srcport", "show"); src_port = (unsigned short) atoi(value); xmlFree(value); value = xml_parse_field(cur, 1, "udp.dstport", "show"); dst_port = (unsigned short) atoi(value); xmlFree(value); /* save the pkt source port */ conf->port_pkt = src_port; /* save the port */ if ((conf->port_client == 0) && (conf->port_server == 0)) { if (conf->ip_client == conf->ip_pkt) { conf->port_client = src_port; conf->port_server = dst_port; } if (conf->ip_server == conf->ip_pkt) { conf->port_client = dst_port; conf->port_server = src_port; } } } /* other packet */ /* TODO XXXFIXMEXXX parse icmp, etc.. like tcp */ else if (conf->check_proto) { debug(3, "proto type: %s\n", name); /* parse the content of the packet */ verbose_("[*] packet type: %s\n", name); xml_parse_proto(conf, cur); } conf->proto_counter++; /* free the field name */ xmlFree(name); } else if (!(xmlStrcmp(cur->name, (const xmlChar *) "field"))) { if (!conf->check_proto) xml_parse_raw_data(conf, cur); } cur = cur->next; } }
/*---------------------------------------------------------------------------* * NAME: xml_parse_proto * DESC: Parse the content of a PDML protocol (not tcp,udp,ip,eth,frame,etc.) *---------------------------------------------------------------------------*/ void xml_parse_proto(config *conf, xmlNodePtr cur_orig) { xmlNodePtr cur; xmlChar *name; xmlChar *value; xmlChar *show; xmlChar *size; xmlChar *pos; xmlChar *showname; xmlChar *unmaskedvalue; int checked_string; unsigned int length; for(cur = cur_orig;cur;cur = cur->next) { if (cur->type == XML_ELEMENT_NODE) { /* take the attributes */ name = xmlGetProp(cur, "name"); value = xmlGetProp(cur, "value"); show = xmlGetProp(cur, "show"); size = xmlGetProp(cur, "size"); pos = xmlGetProp(cur, "pos"); showname = xmlGetProp(cur, "showname"); unmaskedvalue = xmlGetProp(cur, "unmaskedvalue"); debug(2, "name :%s\n", name); debug(2, "show :%s\n", show); debug(2, "value :%s\n", value); debug(2, "size :%s\n", size); debug(2, "pos :%s\n", pos); debug(2, "showname:%s\n", showname); /* has some children ? */ if (cur->children) { conf->tab++; debug(3, "children of %s detected\n", name); /* create a new block */ output_tab_(conf->tab, AD_F_BLOCK_BEGIN"(\"packet_%d.%d.%s.%s\");\n", conf->packet_counter, conf->proto_counter, pos, name); xml_parse_proto(conf,cur->children); output_tab_(conf->tab, AD_F_BLOCK_END"(\"packet_%d.%d.%s.%s\");\n", conf->packet_counter, conf->proto_counter, pos, name); conf->tab--; } /* leaf of the tree, we record the content of value */ else { /* write in the output field */ conf->tab++; /* BUG0001 */ /* detection of "unmaskedvalue" is equivalent to have bit-wise flags */ if (unmaskedvalue != 0) { verbose_("[*] FLAG (bit-wise) detected: %s\n", name); /* we check the flag position: first = writing value */ if ((atoi(pos)) > conf->previous_pos) { /* write in the .ad file that it is a flag */ output_tab_(conf->tab, "\n"); output_tab_(conf->tab, "// *** FLAG DETECTED: see below for the description\n"); /* we write the unmasked value */ if (conf->ethereal_hex_style) { output_tab_(conf->tab, AD_F_HEX"(\n"); output_tab_ether(conf->tab, unmaskedvalue); output_tab_(conf->tab, ");\n"); } else output_tab_(conf->tab, AD_F_HEX"(%s);\n", unmaskedvalue); } /* then we add comments */ output_tab_(conf->tab+1, "// *** FLAG +- name : %s\n", name); output_tab_(conf->tab+1, "// *** FLAG +- showname: %s\n", showname); goto xml_parse_proto_end; } /* if the name, showname or show contain a " * / " it's a problem.. */ output_tab_(conf->tab, "\n"); output_tab_(conf->tab, "// name : %s\n", name); output_tab_(conf->tab, "// showname: %s\n", showname); output_tab_(conf->tab, "// show : %s\n", show); output_tab_(conf->tab, "// position: %s\n", pos); if (size){ output_tab_(conf->tab, "// size: 0x%x (%d)\n", atoi(size), atoi(size)); } /* yes, it happens! */ else { output_tab_(conf->tab, "// size: 0x0 (0)\n"); goto xml_parse_proto_end; } /* yes, it happens! */ if (!value) goto xml_parse_proto_end; /* check if we can convert the hexadecimal value in lenght. */ /* you can disable this function with the check_length opt */ /* WARNING! probabilistic analysis! */ length = 0; if ((conf->check_length)) { debug(1, "check if the value can be a length field\n"); debug(1, "WARNING! not 100%% sure! you need to verify!\n"); length = recover_length(conf, name, show, value, showname); if (length) goto xml_parse_proto_end; } debug(1, "the value is not a length\n"); /* check if we can convert the hexadecimal value in a string */ /* you can disable this function with the check_string opt */ /* WARNING! probabilistic analysis! */ checked_string = 0; if ((conf->check_string)) { debug(1, "check if the value can be converted in a string\n"); checked_string = recover_string(conf, name, show, value, showname); } if (checked_string) goto xml_parse_proto_end; debug(1, "the value is not a string\n"); /* the value is considered as an hexadecimal value. However, */ /* you can write this value using the Ethereal-like style */ /* which is activated by default (more userfriendly) */ if (conf->ethereal_hex_style) { output_tab_(conf->tab, AD_F_HEX"(\n"); output_tab_ether(conf->tab, value); output_tab_(conf->tab, ");\n"); } else output_tab_(conf->tab, AD_F_HEX"(%s);\n", value); xml_parse_proto_end: /* update the position */ conf->previous_pos = atoi(pos); conf->tab--; } /* free attributes */ if (name) xmlFree(name); if (value) xmlFree(value); if (show) xmlFree(show); if (size) xmlFree(size); if (pos) xmlFree(pos); if (showname) xmlFree(showname); if (unmaskedvalue) xmlFree(unmaskedvalue); } } }
/*---------------------------------------------------------------------------* * NAME: main * DESC: Main Entry Point *---------------------------------------------------------------------------*/ int main(int argc, char **argv) { config *conf; unsigned int first_arg; /* create the configuration structure */ conf = malloc_(sizeof(config)); /* create the adc structure */ conf->adc = malloc_(sizeof(struct struct_adc)); /* initialize the configuration structure */ init_configuration(conf); /* parse the arguments */ first_arg = parsing_args(argc, argv, conf); /* check if selected mode is well defined (dirty) */ if ( /* client mode -> port AND host */ ((conf->mode == 0) && ((conf->port == 0) || (conf->host == NULL))) || /* server mode -> port */ ((conf->mode == 1) && (conf->port == 0)) || /* no file.ad defined */ (argv[first_arg] == NULL) || /* debugger and file */ ((conf->type == 2) && (conf->dbg_mode)) || /* fuzz udp or tcp or file */ ((conf->fuzz_file_dir != NULL) && ((conf->host != NULL) || (conf->port != 0) || (conf->type != 2))) ) { usage(argv, conf); } /* verbose messages */ /* autodafe's debugger */ if (conf->dbg_mode) { verbose_("[*] Autodafe's debugger mode activated.\n"); } /* file mode */ if (conf->type == 2) { verbose_("[*] mode *file* - all fuzzed files will be in %s\n", conf->fuzz_file_dir); } /* network mode */ else { if (conf->mode) { if (!conf->type) /* tcp */ verbose_("[*] mode *server* - listening on port: %d (tcp)\n", conf->port); else /* udp */ verbose_("[*] mode *server* - listening on port: %d (udp)\n", conf->port); } else { if (!conf->type) /* tcp */ verbose_("[*] mode *client* - connection to %s on port: %d (tcp)\n", conf->host, conf->port); else /* udp */ verbose_("[*] mode *client* - connection to %s on port: %d (udp)\n", conf->host, conf->port); } } /* read the file */ if(read_adc_file(conf, argv[first_arg])) goto fuzzer_end; /* ignore the SIGPIPE signal (ie. "Connection closed by foreign host") */ signal(SIGPIPE, sigpipe_handler); /* start the connection with the debugger */ if (conf->dbg_mode) if (dbg_connection(conf)) goto fuzzer_end; /* start the fuzz engine */ fuzz_engine(conf); if (conf->buf_fuzz) free(conf->buf_fuzz); /* free the fuzz buffer (in case of error) */ fuzzer_end: if (conf->adc->buffer) free(conf->adc->buffer); /* free the memory-copy of adc file */ if (conf->adc) free(conf->adc); /* free the adc structure */ if (conf) free(conf); /* free the configuration structure */ return 0; }
/*---------------------------------------------------------------------------* * NAME: fuzz_core * DESC: the heart of the fuzzing function. * * id is the id of the fuzz * filename is the file used to fuzz * weight is the default weight of the fuzz * * RETURN 0 -> don't fuzz. * RETURN struct struct_fuzz *fuzz of the fuzzed value *---------------------------------------------------------------------------*/ struct struct_fuzz *fuzz_core(config *conf, unsigned int id, unsigned char *filename, unsigned int weight) { struct struct_fuzz *fuzz; struct struct_fuzz *prev = NULL; struct struct_source *source; FILE *file; unsigned char *file_content; /* debug */ debug(1, "<-----------------------[enter]\n"); /* check if there is a fuzz structure for this id */ debug(3, "value of conf->fuzz: %p\n", conf->fuzz); for (fuzz=conf->fuzz;fuzz;fuzz=fuzz->next) { prev = fuzz; if (fuzz->id == id) break; } /* there is no entry, we add a new one */ if (!fuzz) { debug(2, "Adding a new fuzz entry\n"); /* malloc_ */ fuzz = malloc_(sizeof(struct struct_fuzz)); /* init the structure */ fuzz->next = NULL; fuzz->source = NULL; fuzz->id = id; fuzz->current = 0; fuzz->weight = weight; /* update previous entry */ if (prev) prev->next = fuzz; /* update if it's the first entry */ if (!conf->fuzz) conf->fuzz = fuzz; /* init total + parse the source files */ fuzz->total = fill_source(fuzz, filename); /* bad (memory leak, but who cares?) */ if (fuzz->total == -1) { exit(-31339); } } /* there is an entry */ else { debug(2, "fuzz[%d] found\n", fuzz->id); /* we are currently fuzzing this structure */ if (conf->fuzz_current == fuzz->id) { /* check if we use the debugger mode, if yes, check if we don't use the bruteforce mode, if yes, check if the weight is > 0, if not fuzz->current = fuzz->total i.e. we don't fuzz this entry */ if ((conf->dbg_mode) && (!conf->bruteforce) && (fuzz->weight <= 0)) { fuzz->current = fuzz->total; verbose_("[!] this fuzz is *NOT* relevant, we don't fuzz id: %d\n", fuzz->id); } /* there is something to fuzz */ if (fuzz->current < fuzz->total) { debug(1, "fuzzing: %d/%d\n", fuzz->current+1, fuzz->total); /* open the file pointed by fuzz->source->filename where id == fuzz->current */ for (source = fuzz->source; source; source = source->next) { debug(3, "source: %p source->id: %d fuzz->current: %d\n", source, source->id, fuzz->current); if (source->id == fuzz->current) { break; } } debug(3,"we catch the source->id: %d and fuzz->current: %d\n", source->id, fuzz->current); debug(3,"try to open the file: \"%s\"\n", source->filename); /* open the file */ file = fopen(source->filename, "r"); /* should never happen */ if (!file) { error_(" ??? cannot read another time this file: \"%s\" ???: ", source->filename); perror(""); error_("QUITTING!\n"); exit(-31337); } /* allocate buffer */ file_content = malloc_(source->size); /* copy the content of the file in the buffer */ if (fread(file_content, source->size, 1, file) <= 0) { error_(" ??? cannot read the content of this file: \"%s\" ???: ", source->filename); perror(""); error_("QUITTING!\n"); exit(-31338); } /* close the file */ fclose(file); /* copy the content in the fuzz buffer */ push_data(conf, file_content, source->size); /* free file_content */ free(file_content); /* update the fuzzer counter */ fuzz->current++; /* debug */ debug(1, "<-----------------------[quit]\n"); return fuzz; } /* we can fuzz the next structure */ conf->fuzz_current++; debug(2, "we have fuzzed all the data for this function...\n"); return 0; } } /* debug */ debug(1, "<-----------------------[quit]\n"); /* we are not currently fuzzing this structure */ return 0; }
static struct DriverConnection *CreateConnection(void) { struct DriverConnection *conn = &g_conn; /* Create socket for bootstrap communication with child */ int socket_fds[2] = {-1, -1}; int rc = socketpair(AF_UNIX, SOCK_STREAM, 0, socket_fds); if (rc < 0) { error_("failed to open sockets, errno=%d (%s)", errno, strerror(errno)); return NULL; } api_("CreateConnection(g_exe_fd=%d, '%s')", g_exe_fd, g_exe_file); conn->pid = fork(); if (conn->pid < 0) { error_("failed to fork, errno=%d (%s)", errno, strerror(errno)); return NULL; } if (conn->pid == 0) { /* Child process: run the driver */ close(socket_fds[0]); RunDriver(g_exe_fd, g_exe_file, socket_fds[1]); } /* Read bootstrap information back from the child */ /* First: uint32_t len, char server_add[len] */ uint32_t len; rc = read(socket_fds[0], &len, sizeof(len)); assert (rc == sizeof(len)); char *server_address = (char *)malloc(len); rc = read(socket_fds[0], server_address, len); assert (rc == len); /* Second: uint64_t nonce (used to confirm that the D-Bus connection we set up * later is indeed to the child process */ uint64_t nonce; rc = read(socket_fds[0], &nonce, sizeof(nonce)); assert (rc == sizeof(nonce)); verbose_("started child process %d, read socket name '%s', nonce %ld", conn->pid, server_address, nonce); close(socket_fds[0]); close(socket_fds[1]); snprintf(conn->objpath, 20, "/nonce/%ld", nonce); /* Initialize D-Bus private connection; use the nonce as the object address */ DBusError err; dbus_error_init(&err); conn->dbus = dbus_connection_open_private(server_address, &err); if (!conn->dbus) { error_("!!! dbus_connection_open_private failed: %s: %s\n", err.name, err.message); free(server_address); DestroyConnection(conn); return NULL; } log_("got connection %p to private bus '%s' with {pid=%d dbus_conn=%p objpath='%s'})", conn, server_address, conn->pid, conn->dbus, conn->objpath); free(server_address); /* Send a no-op message to work around a D-Bus problem (if the first message sent includes a file descriptor, it fails). */ DBusMessage *req = ConnectionNewRequest(conn, "__noop"); DBusMessage *rsp = ConnectionBlockingSendReply(conn, req, &err); if (rsp == NULL) { DestroyConnection(conn); return NULL; } dbus_message_unref(rsp); return conn; }
/*---------------------------------------------------------------------------* * NAME: send_fuzz() * DESC: send a buffer using tcp/udp or file method: * tcp/udp: use sendto * RETN: >=0 if everything is OK * -1 if there is a big error (not recoverable) * -2 connection closed by foreign host. *---------------------------------------------------------------------------*/ int send_fuzz(config *conf, struct struct_block *block) { unsigned int bytes; /* debug */ debug(1, "<-----------------------[enter]\n"); /* send using fwrite (file) */ if (conf->type == 2) { bytes = fwrite(conf->buf_fuzz + block->offset, sizeof(char), block->size, conf->fuzz_file); debug(3, "--->bytes written: %d\n", bytes); if (bytes <= 0) return -1; } /* send using sendto (compatible tcp *and* udp) */ else { bytes = sendto(conf->socket, conf->buf_fuzz + block->offset, block->size, 0, (struct sockaddr *)&(server), sizeof(server)); debug(1, "send_fuzz bytes: %d\n", bytes); if (bytes == -1) { /* this is a "Broken pipe" ie: connection closed by foreign host. We detect it and reconnect to the server with return value -2 */ if (errno == EPIPE) { /* EPIPE = 32 cf. /usr/include/asm/errno.h */ verbose_("[!] connection closed by foreign host (sendto)\n"); return -2; } error_("sendto error: "); perror(""); return -1; } /* debugger detection. We wait for at least DBG_TIMEOUT seconds an answer of the debugger. Even if the answer arrives in the next check it's ok (independant messages) */ if (conf->dbg_mode) { fd_set rfds; struct timeval tv; int retval; tv.tv_sec = DBG_TIMEOUT_SEC; tv.tv_usec = DBG_TIMEOUT_USEC; FD_ZERO(&rfds); FD_SET(conf->dbg_socket, &rfds); retval = select(conf->dbg_socket+1, &rfds, NULL, NULL, &tv); /* error */ if (retval == -1) { error_("select error: "); perror(""); return -1; } /* there is something from the dbg */ if (retval) { verbose_("[*] the debugger has something to say!\n"); if (dbg_read_msg(conf)) bytes = -1; } } } /* debug */ debug(1, "<-----------------------[quit]\n"); return bytes; }
/*---------------------------------------------------------------------------* * NAME: recv_fuzz() * DESC: recv a buffer using tcp/udp or file method: * tcp/udp: use recvfrom * RETN: > 0 if everything is OK * 0 if connection closed by foreign host * -1 if major error *---------------------------------------------------------------------------*/ int recv_fuzz(config *conf, struct struct_block *block, unsigned char *buffer) { int bytes; unsigned int len; /* recv using *nothing* (file) */ if (conf->type == 2) { bytes = 1; /* do nothing */ } /* recv using recvfrom (compatible tcp *and* udp) */ else { /* timeout for receiving an answer */ fd_set rfds; struct timeval tv; int retval; tv.tv_sec = conf->timeout; tv.tv_usec = 0; FD_ZERO(&rfds); FD_SET(conf->socket, &rfds); retval = select(conf->socket+1, &rfds, NULL, NULL, &tv); /* error */ if (retval == -1) { error_("select error: "); perror(""); return -1; } /* there is data */ if (retval) { len = sizeof(server); debug(3, "len: %d\n", len); debug(3, "block->size :%d\n", block->size); bytes = recvfrom(conf->socket, buffer, block->size, 0, (struct sockaddr *)&server, &len); debug(1, "recv_fuzz bytes: %d\n", bytes); if (bytes == -1) { error_("recvfrom error: "); perror(""); free(buffer); buffer = NULL; return 0; } if (bytes == 0) { verbose_("[!] connection closed by foreign host (recv_from)\n"); free(buffer); buffer = NULL; } return bytes; } /* nothing has been received for RECV_TIMEOUT_SEC and RECV_TIMEOUT_USEC */ else { verbose_("[!] timeout of %d [sec] expired... launch the next attack.\n", conf->timeout); free(buffer); buffer = NULL; return 0; } } /* TODOXXXFIXMEXXX: verify if OK */ return -1; }