void indicator_play(struct ausrv *ausrv, int type, uint32_t vol, int dur) { struct stream *stream = stream_find(ausrv, ind_stream); uint32_t timeout = dur ? dur : MAX_TONE_LENGTH; if (stream != NULL) { dtmf_stop(ausrv); indicator_stop(ausrv, PRESERVE_STREAM); } else { stream = stream_create(ausrv, ind_stream, NULL, 0, tone_write_callback, tone_destroy_callback, ind_props, NULL); if (stream == NULL) { LOG_ERROR("%s(): Can't create stream", __FUNCTION__); return; } } vol = (vol_scale * vol) / 100; switch (type) { case TONE_DIAL: switch (standard) { case STD_CEPT: tone_create(stream, type, 425, vol, 1000000, 1000000, 0,0); break; case STD_ANSI: case STD_ATNT: tone_create(stream, type, 350, (vol*7)/10, 1000000, 1000000, 0,0); tone_create(stream, type, 440, (vol*7)/10, 1000000, 1000000, 0,0); break; case STD_JAPAN: tone_create(stream, type, 400, vol, 1000000, 1000000, 0,0); break; } timeout = MAX_TONE_LENGTH; break; case TONE_BUSY: switch (standard) { case STD_CEPT: tone_create(stream, type, 425, vol, 1000000, 500000, 0,dur); break; case STD_ANSI: case STD_ATNT: tone_create(stream, type, 480, (vol*7)/10, 1000000, 500000, 0,dur); tone_create(stream, type, 620, (vol*7)/10, 1000000, 500000, 0,dur); break; case STD_JAPAN: tone_create(stream, type, 400, vol, 1000000, 500000, 0,dur); break; } break; case TONE_CONGEST: switch (standard) { case STD_CEPT: tone_create(stream, type, 425, vol, 400000, 200000, 0,dur); break; case STD_ANSI: case STD_ATNT: tone_create(stream, type, 480, (vol*7)/10, 500000, 250000, 0,dur); tone_create(stream, type, 620, (vol*7)/10, 500000, 250000, 0,dur); break; case STD_JAPAN: /* * this is non-standard, but * we play busy tone instead of being silent */ tone_create(stream, type, 400, vol, 1000000, 500000, 0,dur); break; } break; case TONE_RADIO_ACK: switch (standard) { case STD_CEPT: case STD_ANSI: case STD_ATNT: tone_create(stream, type, 425, vol, 200000, 200000, 0,200000); timeout = MAX_SHORT_TONE_LENGTH; break; case STD_JAPAN: tone_create(stream, type, 400, vol, 3000000, 1000000, 0,0); /* The Japan standard tone is repeating, so I guess we need to wait 60s anyway. */ timeout = MAX_TONE_LENGTH; break; } break; case TONE_RADIO_NA: switch (standard) { case STD_CEPT: case STD_ANSI: case STD_ATNT: tone_create(stream, type, 425, vol, 400000, 200000, 0,1200000); break; case STD_JAPAN: break; } timeout = MAX_SHORT_TONE_LENGTH; break; case TONE_ERROR: switch (standard) { case STD_CEPT: case STD_ANSI: case STD_ATNT: tone_create(stream, type, 900, vol, 2000000, 333333, 0,dur); tone_create(stream, type, 1400, vol, 2000000, 332857, 333333,dur); tone_create(stream, type, 1800, vol, 2000000, 300000, 666190,dur); break; case STD_JAPAN: /* * this is non-standard, but * we play busy tone instead of being silent */ tone_create(stream, type, 400, vol, 1000000, 500000, 0,dur); break; } break; case TONE_WAIT: switch (standard) { case STD_CEPT: tone_create(stream,type, 425, vol, 800000,200000, 0,1000000); tone_create(stream,type, 425, vol, 800000,200000, 4000000,1000000); break; case STD_ANSI: tone_create(stream,type, 440, vol, 300000,300000, 0,300000); tone_create(stream,type, 440, vol, 10000000,100000, 10000000,0); tone_create(stream,type, 440, vol, 10000000,100000, 10200000,0); break; case STD_ATNT: tone_create(stream, type, 440, vol, 4000000, 200000, 0, 0); tone_create(stream, type, 440, vol, 4000000, 200000, 500000, 0); break; case STD_JAPAN: break; } timeout = MAX_TONE_LENGTH; break; case TONE_RING: switch (standard) { case STD_CEPT: tone_create(stream, type, 425, vol, 5000000, 1000000, 0,0); break; case STD_ANSI: case STD_ATNT: tone_create(stream, type, 440, (vol*7)/10, 6000000, 2000000, 0,0); tone_create(stream, type, 480, (vol*7)/10, 6000000, 2000000, 0,0); break; case STD_JAPAN: break; } timeout = MAX_TONE_LENGTH; break; default: LOG_ERROR("%s(): invalid type %d", __FUNCTION__, type); break; } stream_set_timeout(stream, timeout); }
tree_cell * nasl_recv(lex_ctxt * lexic) { char * data; int len = get_int_local_var_by_name(lexic, "length", -1); int min_len = get_int_local_var_by_name(lexic, "min", -1); int soc = get_int_local_var_by_name(lexic, "socket", 0); int to = get_int_local_var_by_name(lexic, "timeout", lexic->recv_timeout); fd_set rd; struct timeval tv; int new_len = 0; tree_cell * retc; int type = -1, opt_len = sizeof(type); int e; if(len <= 0 || soc <= 0) return NULL; if (to <= 0) to = 5; tv.tv_sec = to; tv.tv_usec = 0; data = emalloc(len); if ( !fd_is_stream(soc) ) e = getsockopt(soc, SOL_SOCKET, SO_TYPE, &type, &opt_len); else e = -1; if(e == 0 && type == SOCK_DGRAM) { /* * As UDP packets may be lost, we retry up to 5 times */ int retries = 5; int i; tv.tv_sec = to / retries; tv.tv_usec = (to % retries) * 100000; for(i=0;i<retries;i++) { FD_ZERO(&rd); FD_SET(soc, &rd); if(!to || select(soc+1, &rd, NULL, NULL, &tv)>0) { int e; e = recv(soc, data+new_len, len-new_len, 0); if(e <= 0) { if(!new_len) { efree(&data); return NULL; } else break; } else new_len+=e; if(new_len >= len)break; break; /* UDP data is never fragmented */ } else { /* * The packet may have been lost en route - we resend it */ char * data; int len; data = get_udp_data(lexic->script_infos, soc, &len); if(data != NULL)send(soc, data, len, 0); tv.tv_sec = to / retries; tv.tv_usec = ( to % retries) * 100000; } } } else { int old = stream_set_timeout(soc, tv.tv_sec); new_len = read_stream_connection_min(soc, data, min_len, len); stream_set_timeout(soc, old); } if(new_len > 0) { retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; retc->x.str_val = nasl_strndup(data, new_len); retc->size = new_len; efree(&data); return retc; } else { efree(&data); return NULL; } }
static int proto_tftp_process(void *proto_priv, struct packet *p, struct proto_process_stack *stack, unsigned int stack_index) { struct proto_process_stack *s = &stack[stack_index]; struct proto_process_stack *s_prev = &stack[stack_index - 1]; struct proto_process_stack *s_next = &stack[stack_index + 1]; if (conntrack_get_unique_from_parent(stack, stack_index) != POM_OK) { pomlog(POMLOG_ERR "Could not get a conntrack entry"); return PROTO_ERR; } struct proto_tftp_conntrack_priv *priv = s->ce->priv; if (!priv) { priv = malloc(sizeof(struct proto_tftp_conntrack_priv)); if (!priv) { pom_oom(sizeof(struct proto_tftp_conntrack_priv)); conntrack_unlock(s->ce); return POM_ERR; } memset(priv, 0, sizeof(struct proto_tftp_conntrack_priv)); s->ce->priv = priv; } if (priv->flags & PROTO_TFTP_CONN_INVALID) { conntrack_unlock(s->ce); return PROTO_INVALID; } void *pload = s->pload; uint32_t plen = s->plen; // proto_tftp only process up to the opcode field // afterwards, it's up to the analyzer to parse the rest uint16_t opcode = ntohs(*((uint16_t*)pload)); PTYPE_UINT16_SETVAL(s->pkt_info->fields_value[proto_tftp_field_opcode], opcode); pload += sizeof(uint16_t); plen -= sizeof(uint16_t); s_next->pload = pload; s_next->plen = plen; switch (opcode) { case tftp_rrq: case tftp_wrq: { // Find the filename char *filename = pload; char *mode = memchr(filename, 0, plen - 1); if (!mode) { priv->flags |= PROTO_TFTP_CONN_INVALID; conntrack_unlock(s->ce); debug_tftp("End of filename not found in read/write request"); return PROTO_INVALID; } mode++; ssize_t filename_len = mode - filename; char *end = memchr(mode, 0, plen - filename_len); if (!end) { priv->flags |= PROTO_TFTP_CONN_INVALID; conntrack_unlock(s->ce); debug_tftp("End of mode not found in read/write request"); return PROTO_INVALID; } debug_tftp("Got read/write request for filename \"%s\" with mode \"%s\"", filename, mode); struct conntrack_session *session = conntrack_session_get(s->ce); if (!session) { conntrack_unlock(s->ce); return POM_ERR; } // We don't need to do anything with the session conntrack_session_unlock(session); struct proto_expectation *expt = proto_expectation_alloc_from_conntrack(s_prev->ce, proto_tftp, NULL); if (!expt) { conntrack_unlock(s->ce); return PROTO_ERR; } proto_expectation_set_field(expt, -1, NULL, POM_DIR_REV); if (proto_expectation_add(expt, session, PROTO_TFTP_EXPT_TIMER, p->ts) != POM_OK) { conntrack_unlock(s->ce); proto_expectation_cleanup(expt); return PROTO_ERR; } break; } case tftp_data: { if (plen < 2) { priv->flags |= PROTO_TFTP_CONN_INVALID; conntrack_unlock(s->ce); return PROTO_INVALID; } uint16_t block_id = ntohs(*((uint16_t*)(pload))); int set_start_seq = 0; if (!priv->stream) { priv->stream = stream_alloc(PROTO_TFTP_STREAM_BUFF, s->ce, 0, proto_tftp_process_payload); if (!priv->stream) { conntrack_unlock(s->ce); return PROTO_ERR; } stream_set_timeout(priv->stream, PROTO_TFTP_PKT_TIMER); set_start_seq = 1; } conntrack_unlock(s->ce); if (set_start_seq) stream_set_start_seq(priv->stream, s->direction, PROTO_TFTP_BLK_SIZE + 2); int res = stream_process_packet(priv->stream, p, stack, stack_index + 1, block_id * (PROTO_TFTP_BLK_SIZE + 2), 0); return (res == PROTO_OK ? PROTO_STOP : res); } case tftp_ack: // Nothing to do break; case tftp_error: // An error occured, cleanup this conntrack soon conntrack_delayed_cleanup(s->ce, 1, p->ts); break; default: priv->flags |= PROTO_TFTP_CONN_INVALID; conntrack_unlock(s->ce); return PROTO_INVALID; } conntrack_delayed_cleanup(s->ce, PROTO_TFTP_PKT_TIMER, p->ts); conntrack_unlock(s->ce); return PROTO_OK; }