void vector_clear(vector_t *vector) { // Remove all items in the vector while (vector_first(vector)) vector_remove(vector, vector_first(vector)); }
const char * msg_get_attribute(sip_msg_t *msg, int id, char *value) { sdp_media_t *media; char *ar; switch (id) { case SIP_ATTR_SRC: sprintf(value, "%s:%u", msg->packet->ip_src, msg->packet->sport); break; case SIP_ATTR_DST: sprintf(value, "%s:%u", msg->packet->ip_dst, msg->packet->dport); break; case SIP_ATTR_METHOD: if (sip_method_str(msg->reqresp)) { sprintf(value, "%s", sip_method_str(msg->reqresp)); } else { sip_get_response_str(msg, value); } break; case SIP_ATTR_SIPFROM: sprintf(value, "%s", msg->sip_from); break; case SIP_ATTR_SIPTO: sprintf(value, "%s", msg->sip_to); break; case SIP_ATTR_SIPFROMUSER: sprintf(value, "%s", msg->sip_from); if ((ar = strchr(value, '@'))) *ar = '\0'; break; case SIP_ATTR_SIPTOUSER: sprintf(value, "%s", msg->sip_to); if ((ar = strchr(value, '@'))) *ar = '\0'; break; case SIP_ATTR_DATE: timeval_to_date(msg_get_time(msg), value); break; case SIP_ATTR_TIME: timeval_to_time(msg_get_time(msg), value); break; case SIP_ATTR_SDP_ADDRESS: if ((media = vector_first(msg->medias))) sprintf(value, "%s", media_get_address(media)); break; case SIP_ATTR_SDP_PORT: if ((media = vector_first(msg->medias))) sprintf(value, "%d", media_get_port(media)); break; default: fprintf(stderr, "Unhandled attribute %s (%d)\n", sip_attr_get_name(id), id); abort(); break; } return strlen(value) ? value : NULL; }
struct timeval msg_get_time(sip_msg_t *msg) { struct timeval t = { }; capture_frame_t *frame; if (msg && (frame = vector_first(msg->packet->frames))) return frame->header->ts; return t; }
int call_is_invite(sip_call_t *call) { sip_msg_t *first; if ((first = vector_first(call->msgs))) return (first->reqresp == SIP_METHOD_INVITE); return 0; }
const char * call_get_attribute(sip_call_t *call, enum sip_attr_id id, char *value) { sip_msg_t *first, *last; if (!call) return NULL; switch (id) { case SIP_ATTR_CALLINDEX: sprintf(value, "%d", call->index); break; case SIP_ATTR_CALLID: sprintf(value, "%s", call->callid); break; case SIP_ATTR_XCALLID: sprintf(value, "%s", call->xcallid); break; case SIP_ATTR_MSGCNT: sprintf(value, "%d", vector_count(call->msgs)); break; case SIP_ATTR_CALLSTATE: sprintf(value, "%s", call_state_to_str(call->state)); break; case SIP_ATTR_TRANSPORT: first = vector_first(call->msgs); sprintf(value, "%s", sip_transport_str(first->packet->type)); break; case SIP_ATTR_CONVDUR: timeval_to_duration(msg_get_time(call->cstart_msg), msg_get_time(call->cend_msg), value); break; case SIP_ATTR_TOTALDUR: first = vector_first(call->msgs); last = vector_last(call->msgs); timeval_to_duration(msg_get_time(first), msg_get_time(last), value); break; default: return msg_get_attribute(vector_first(call->msgs), id, value); break; } return strlen(value) ? value : NULL; }
pcap_dumper_t * dump_open(const char *dumpfile) { capture_info_t *capinfo; if (vector_count(capture_cfg.sources) == 1) { capinfo = vector_first(capture_cfg.sources); return pcap_dump_open(capinfo->handle, dumpfile); } return NULL; }
const char * capture_device() { capture_info_t *capinfo; if (vector_count(capture_cfg.sources) == 1) { capinfo = vector_first(capture_cfg.sources); return capinfo->device; } return NULL; }
char * capture_last_error() { capture_info_t *capinfo; if (vector_count(capture_cfg.sources) == 1) { capinfo = vector_first(capture_cfg.sources); return pcap_geterr(capinfo->handle); } return NULL; }
void sip_calls_rotate() { sip_call_t *call = vector_first(calls.list); // Remove from callids hash htable_remove(calls.callids, call->callid); // Remove first call from active and call lists vector_remove(calls.active, call); vector_remove(calls.list, call); }
VALUE thread_s_main() { VALUE thr; return (VALUE)vector_first(thr_stk); for (thr = cur_thr; TEST(thr); thr = THREAD(thr)->up) if (! TEST(THREAD(thr)->up) ) return thr; return thr; }
sip_call_t * call_group_get_next(sip_call_group_t *group, sip_call_t *call) { sip_msg_t *next, *first; sip_call_t *c; int i; if (!group) return NULL; // Get call of the first message in group if (!call) { if ((next = call_group_get_next_msg(group, NULL))) { return next->call; } return NULL; } // Initialize candidate next = NULL; // Get the call with the next chronological message for (i = 0; i < vector_count(group->calls); i++) { if ((c = vector_item(group->calls, i)) == call) continue; // Get first message first = vector_first(c->msgs); // Is first message of this call older? if (msg_is_older(first, vector_first(call->msgs)) && (!next || !msg_is_older(first, next))) { next = first; break; } } return (next) ? next->call : NULL; }
void call_update_state(sip_call_t *call, sip_msg_t *msg) { int reqresp; sip_msg_t *first; if (!call_is_invite(call)) return; // Get the first message in the call first = vector_first(call->msgs); // Get current message Method / Response Code reqresp = msg->reqresp; // If this message is actually a call, get its current state if (call->state) { if (call->state == SIP_CALLSTATE_CALLSETUP) { if (reqresp == SIP_METHOD_ACK && call->invitecseq == msg->cseq) { // Alice and Bob are talking call->state = SIP_CALLSTATE_INCALL; call->cstart_msg = msg; } else if (reqresp == SIP_METHOD_CANCEL) { // Alice is not in the mood call->state = SIP_CALLSTATE_CANCELLED; } else if (reqresp > 400 && call->invitecseq == msg->cseq) { // Bob is not in the mood call->state = SIP_CALLSTATE_REJECTED; } } else if (call->state == SIP_CALLSTATE_INCALL) { if (reqresp == SIP_METHOD_BYE) { // Thanks for all the fish! call->state = SIP_CALLSTATE_COMPLETED; call->cend_msg = msg; } } else if (reqresp == SIP_METHOD_INVITE && call->state != SIP_CALLSTATE_INCALL) { // Call is being setup (after proper authentication) call->invitecseq = msg->cseq; call->state = SIP_CALLSTATE_CALLSETUP; } } else { // This is actually a call if (reqresp == SIP_METHOD_INVITE) { call->invitecseq = msg->cseq; call->state = SIP_CALLSTATE_CALLSETUP; } } }
const char* capture_input_file() { capture_info_t *capinfo; if (vector_count(capture_cfg.sources) == 1) { capinfo = vector_first(capture_cfg.sources); if (capinfo->infile) { return sng_basename(capinfo->infile); } else { return NULL; } } else { return "Multiple files"; } }
const char * call_get_attribute(sip_call_t *call, enum sip_attr_id id) { if (!call) return NULL; switch (id) { case SIP_ATTR_CALLINDEX: case SIP_ATTR_CALLID: case SIP_ATTR_MSGCNT: case SIP_ATTR_CALLSTATE: case SIP_ATTR_CONVDUR: case SIP_ATTR_TOTALDUR: return sip_attr_get_value(call->attrs, id); default: return msg_get_attribute(vector_first(call->msgs), id); } return NULL; }
ch8 * fixed_gap_arena_text(FixedGapArena *arena, memi offset, memi size, ch8 *out) { hale_assert(offset <= arena->size); hale_assert(size <= arena->size); hale_assert(offset + size <= arena->size); if (size == 0) { return out; } Buf *it = &vector_first(&arena->buffers); Buf *end = it + vector_count(arena->buffers); it = find_buf_GT(arena, &offset, it, end); #if HALE_DEBUG ch8 *out_end = out + size; #endif // Protected by asserts above. hale_assert_requirement(it != end); memi s = buf_length(it); s = hale_minimum(size, s - offset); out = buf_text(it, offset, s, out); hale_assert_debug(out <= out_end); size -= s; while (size) { ++it; s = hale_minimum(size, buf_length(it)); out = buf_text(it, 0, s, out); hale_assert_debug(out <= out_end); size -= s; } return out; }
void call_update_state(sip_call_t *call, sip_msg_t *msg) { const char *callstate; char dur[20]; int reqresp; sip_msg_t *first; if (!call_is_invite(call)) return; // Get the first message in the call first = vector_first(call->msgs); // Get current message Method / Response Code reqresp = msg->reqresp; // If this message is actually a call, get its current state if ((callstate = call_get_attribute(call, SIP_ATTR_CALLSTATE))) { if (!strcmp(callstate, SIP_CALLSTATE_CALLSETUP)) { if (reqresp == 200) { // Alice and Bob are talking call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_INCALL); // Store the timestap where call has started call->active = 1; call->cstart_msg = msg; } else if (reqresp == SIP_METHOD_CANCEL) { // Alice is not in the mood call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_CANCELLED); // Store total call duration call_set_attribute(call, SIP_ATTR_TOTALDUR, timeval_to_duration(msg_get_time(first), msg_get_time(msg), dur)); call->active = 0; } else if (reqresp > 400) { // Bob is not in the mood call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_REJECTED); // Store total call duration call_set_attribute(call, SIP_ATTR_TOTALDUR, timeval_to_duration(msg_get_time(first), msg_get_time(msg), dur)); call->active = 0; } } else if (!strcmp(callstate, SIP_CALLSTATE_INCALL)) { if (reqresp == SIP_METHOD_BYE) { // Thanks for all the fish! call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_COMPLETED); // Store Conversation duration call_set_attribute(call, SIP_ATTR_CONVDUR, timeval_to_duration(msg_get_time(call->cstart_msg), msg_get_time(msg), dur)); call->active = 0; } } else if (reqresp == SIP_METHOD_INVITE && strcmp(callstate, SIP_CALLSTATE_INCALL)) { // Call is being setup (after proper authentication) call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_CALLSETUP); call->active = 1; } else { // Store total call duration call_set_attribute(call, SIP_ATTR_TOTALDUR, timeval_to_duration(msg_get_time(first), msg_get_time(msg), dur)); } } else { // This is actually a call if (reqresp == SIP_METHOD_INVITE) { call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_CALLSETUP); call->active = 1; } } }
int capture_eep_send_v3(capture_packet_t *pkt) { struct hep_generic *hg = NULL; void* buffer; unsigned int buflen = 0, iplen = 0, tlen = 0; hep_chunk_ip4_t src_ip4, dst_ip4; #ifdef USE_IPV6 hep_chunk_ip6_t src_ip6, dst_ip6; #endif hep_chunk_t payload_chunk; hep_chunk_t authkey_chunk; capture_frame_t *frame = vector_first(pkt->frames); unsigned char *data = capture_packet_get_payload(pkt); unsigned int len = capture_packet_get_payload_len(pkt); hg = sng_malloc(sizeof(struct hep_generic)); /* header set "HEP3" */ memcpy(hg->header.id, "\x48\x45\x50\x33", 4); /* IP proto */ hg->ip_family.chunk.vendor_id = htons(0x0000); hg->ip_family.chunk.type_id = htons(0x0001); hg->ip_family.data = pkt->ip_version == 4 ? AF_INET : AF_INET6; hg->ip_family.chunk.length = htons(sizeof(hg->ip_family)); /* Proto ID */ hg->ip_proto.chunk.vendor_id = htons(0x0000); hg->ip_proto.chunk.type_id = htons(0x0002); hg->ip_proto.data = pkt->proto; hg->ip_proto.chunk.length = htons(sizeof(hg->ip_proto)); /* IPv4 */ if (pkt->ip_version == 4) { /* SRC IP */ src_ip4.chunk.vendor_id = htons(0x0000); src_ip4.chunk.type_id = htons(0x0003); inet_pton(AF_INET, pkt->ip_src, &src_ip4.data); src_ip4.chunk.length = htons(sizeof(src_ip4)); /* DST IP */ dst_ip4.chunk.vendor_id = htons(0x0000); dst_ip4.chunk.type_id = htons(0x0004); inet_pton(AF_INET, pkt->ip_dst, &dst_ip4.data); dst_ip4.chunk.length = htons(sizeof(dst_ip4)); iplen = sizeof(dst_ip4) + sizeof(src_ip4); } #ifdef USE_IPV6 /* IPv6 */ else if(pkt->ip_version == 6) { /* SRC IPv6 */ src_ip6.chunk.vendor_id = htons(0x0000); src_ip6.chunk.type_id = htons(0x0005); inet_pton(AF_INET6, pkt->ip_src, &src_ip6.data); src_ip6.chunk.length = htonl(sizeof(src_ip6)); /* DST IPv6 */ dst_ip6.chunk.vendor_id = htons(0x0000); dst_ip6.chunk.type_id = htons(0x0006); inet_pton(AF_INET6, pkt->ip_dst, &dst_ip6.data); dst_ip6.chunk.length = htonl(sizeof(dst_ip6)); iplen = sizeof(dst_ip6) + sizeof(src_ip6); } #endif /* SRC PORT */ hg->src_port.chunk.vendor_id = htons(0x0000); hg->src_port.chunk.type_id = htons(0x0007); hg->src_port.data = htons(pkt->sport); hg->src_port.chunk.length = htons(sizeof(hg->src_port)); /* DST PORT */ hg->dst_port.chunk.vendor_id = htons(0x0000); hg->dst_port.chunk.type_id = htons(0x0008); hg->dst_port.data = htons(pkt->dport); hg->dst_port.chunk.length = htons(sizeof(hg->dst_port)); /* TIMESTAMP SEC */ hg->time_sec.chunk.vendor_id = htons(0x0000); hg->time_sec.chunk.type_id = htons(0x0009); hg->time_sec.data = htonl(frame->header->ts.tv_sec); hg->time_sec.chunk.length = htons(sizeof(hg->time_sec)); /* TIMESTAMP USEC */ hg->time_usec.chunk.vendor_id = htons(0x0000); hg->time_usec.chunk.type_id = htons(0x000a); hg->time_usec.data = htonl(frame->header->ts.tv_usec); hg->time_usec.chunk.length = htons(sizeof(hg->time_usec)); /* Protocol TYPE */ hg->proto_t.chunk.vendor_id = htons(0x0000); hg->proto_t.chunk.type_id = htons(0x000b); hg->proto_t.data = 1; hg->proto_t.chunk.length = htons(sizeof(hg->proto_t)); /* Capture ID */ hg->capt_id.chunk.vendor_id = htons(0x0000); hg->capt_id.chunk.type_id = htons(0x000c); hg->capt_id.data = htons(eep_cfg.capt_id); hg->capt_id.chunk.length = htons(sizeof(hg->capt_id)); /* Payload */ payload_chunk.vendor_id = htons(0x0000); payload_chunk.type_id = htons(0x000f); payload_chunk.length = htons(sizeof(payload_chunk) + len); tlen = sizeof(struct hep_generic) + len + iplen + sizeof(hep_chunk_t); /* auth key */ if (eep_cfg.capt_password != NULL) { tlen += sizeof(hep_chunk_t); /* Auth key */ authkey_chunk.vendor_id = htons(0x0000); authkey_chunk.type_id = htons(0x000e); authkey_chunk.length = htons(sizeof(authkey_chunk) + strlen(eep_cfg.capt_password)); tlen += strlen(eep_cfg.capt_password); } /* total */ hg->header.length = htons(tlen); if (!(buffer = sng_malloc(tlen))) { sng_free(hg); return 1; } memcpy((void*) buffer, hg, sizeof(struct hep_generic)); buflen = sizeof(struct hep_generic); /* IPv4 */ if (pkt->ip_version == 4) { /* SRC IP */ memcpy((void*) buffer + buflen, &src_ip4, sizeof(struct hep_chunk_ip4)); buflen += sizeof(struct hep_chunk_ip4); memcpy((void*) buffer + buflen, &dst_ip4, sizeof(struct hep_chunk_ip4)); buflen += sizeof(struct hep_chunk_ip4); } #ifdef USE_IPV6 /* IPv6 */ else if(pkt->ip_version == 6) { /* SRC IPv6 */ memcpy((void*) buffer+buflen, &src_ip4, sizeof(struct hep_chunk_ip6)); buflen += sizeof(struct hep_chunk_ip6); memcpy((void*) buffer+buflen, &dst_ip6, sizeof(struct hep_chunk_ip6)); buflen += sizeof(struct hep_chunk_ip6); } #endif /* AUTH KEY CHUNK */ if (eep_cfg.capt_password != NULL) { memcpy((void*) buffer + buflen, &authkey_chunk, sizeof(struct hep_chunk)); buflen += sizeof(struct hep_chunk); /* Now copying payload self */ memcpy((void*) buffer + buflen, eep_cfg.capt_password, strlen(eep_cfg.capt_password)); buflen += strlen(eep_cfg.capt_password); } /* PAYLOAD CHUNK */ memcpy((void*) buffer + buflen, &payload_chunk, sizeof(struct hep_chunk)); buflen += sizeof(struct hep_chunk); /* Now copying payload itself */ memcpy((void*) buffer + buflen, data, len); buflen += len; if (send(eep_cfg.client_sock, buffer, buflen, 0) == -1) { return 1; } /* FREE */ sng_free(buffer); sng_free(hg); return 0; }
int capture_eep_send_v2(capture_packet_t *pkt) { void* buffer; unsigned int buflen = 0, tlen = 0; struct hep_hdr hdr; struct hep_timehdr hep_time; struct hep_iphdr hep_ipheader; #ifdef USE_IPV6 struct hep_ip6hdr hep_ip6header; #endif unsigned char *data = capture_packet_get_payload(pkt); unsigned int len = capture_packet_get_payload_len(pkt); capture_frame_t *frame = vector_first(pkt->frames); /* Version && proto */ hdr.hp_v = 2; hdr.hp_f = pkt->ip_version == 4 ? AF_INET : AF_INET6; hdr.hp_p = pkt->proto; hdr.hp_sport = htons(pkt->sport); hdr.hp_dport = htons(pkt->dport); /* Timestamp */ hep_time.tv_sec = frame->header->ts.tv_sec; hep_time.tv_usec = frame->header->ts.tv_usec; hep_time.captid = eep_cfg.capt_id; /* Calculate initial HEP packet size */ tlen = sizeof(struct hep_hdr) + sizeof(struct hep_timehdr); /* IPv4 */ if (pkt->ip_version == 4) { inet_pton(AF_INET, pkt->ip_src, &hep_ipheader.hp_src); inet_pton(AF_INET, pkt->ip_dst, &hep_ipheader.hp_dst); tlen += sizeof(struct hep_iphdr); hdr.hp_l += sizeof(struct hep_iphdr); } #ifdef USE_IPV6 /* IPv6 */ else if(pkt->ip_version == 6) { inet_pton(AF_INET6, pkt->ip_src, &hep_ip6header.hp6_src); inet_pton(AF_INET6, pkt->ip_dst, &hep_ip6header.hp6_dst); tlen += sizeof(struct hep_ip6hdr); hdr.hp_l += sizeof(struct hep_ip6hdr); } #endif // Add payload size to the final size of HEP packet tlen += len; hdr.hp_l = htons(tlen); // Allocate memory for HEPv2 packet if (!(buffer = sng_malloc(tlen))) return 1; // Copy basic headers buflen = 0; memcpy((void*) buffer + buflen, &hdr, sizeof(struct hep_hdr)); buflen += sizeof(struct hep_hdr); // Copy IP header if (pkt->ip_version == 4) { memcpy((void*) buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr)); buflen += sizeof(struct hep_iphdr); } #ifdef USE_IPV6 else if(pkt->ip_version == 6) { memcpy((void*) buffer + buflen, &hep_ip6header, sizeof(struct hep_ip6hdr)); buflen += sizeof(struct hep_ip6hdr); } #endif // Copy TImestamp header memcpy((void*) buffer + buflen, &hep_time, sizeof(struct hep_timehdr)); buflen += sizeof(struct hep_timehdr); // Now copy payload itself memcpy((void*) buffer + buflen, data, len); buflen += len; if (send(eep_cfg.client_sock, buffer, buflen, 0) == -1) { return 1; } /* FREE */ sng_free(buffer); return 1; }
/* Parse the line. */ enum cparse_result cparse(char *line, struct cnode *top, struct cparam *param, int exec) { uint32_t i; uint32_t j; char *arg; struct cnode *cnode; enum match_type current; struct vector *args; struct vector *matched; struct vector *candidate; struct vector *argv; /* Arguments, matched and candidate. */ args = param->args; matched = param->matched; candidate = param->candidate; argv = param->argv; /* Lexical analysis. */ clex(line, args); /* Set top candidate. */ vector_reset(candidate); vector_append(candidate, top->v); /* Empty line. */ if (vector_max(args) == 0) { return CPARSE_EMPTY_LINE; } /* Parse user input arguments. */ for (i = 0; i < vector_max(args); i++) { /* Set current word to arg. */ arg = vector_slot(args, i); /* Empty tail space. */ if (strcmp(arg, "") == 0) { if (param->index > 0) { param->index--; } if (args->max > 0) { args->max--; } param->tail = 1; break; } /* Remember index. */ param->index = i; /* Starting from no match. */ current = NONE_MATCH; /* Rest matched vector. */ vector_reset(matched); /* Match with schema. */ for (j = 0; j < vector_max(candidate); j++) { enum match_type match = NONE_MATCH; cnode = vector_slot(candidate, j); if (exec == CPARSE_EXEC_MODE || exec == CPARSE_CONFIG_EXEC_MODE) { cnode_schema_match(cnode, arg, &match); } if (exec == CPARSE_CONFIG_MODE || (exec == CPARSE_CONFIG_EXEC_MODE && match == NONE_MATCH)) { if (strcmp(arg, cnode->name) == 0) { match = KEYWORD_MATCH; } } if (match == NONE_MATCH) { continue; } if (match > current) { vector_reset(matched); current = match; vector_set(matched, cnode); } else if (match == current) { vector_set(matched, cnode); } if (CHECK_FLAG(cnode->flags, CNODE_FLAG_SET_NODE)) { SET32_FLAG(param->flags, CNODE_FLAG_SET_NODE); } if (CHECK_FLAG(cnode->flags, CNODE_FLAG_DELETE_NODE)) { SET32_FLAG(param->flags, CNODE_FLAG_DELETE_NODE); } } /* There is no match. */ if (vector_max(matched) == 0) { break; } /* Update next level schema. */ vector_reset(candidate); for (j = 0; j < vector_max(matched); j++) { cnode = vector_slot(matched, j); vector_append(candidate, cnode->v); } } /* Match result check. */ if (vector_max(matched) == 0) { return CPARSE_NO_MATCH; } else if (vector_max(matched) > 1) { return CPARSE_AMBIGUOUS; } /* Parse success, set matched node. */ param->exec = vector_first(matched); /* Return incomplete if the node is not leaf. */ if (!cnode_is_leaf(param->exec)) { return CPARSE_INCOMPLETE; } /* Here we can build argc/argv. This is only possible at this stage * since during parsing, we can't determine which node is actually * matched. We allow user to abbreviate input so there could be * multiple candidate node during parsing. */ if (exec) { build_argv(param->exec, args, vector_max(args) - 1, argv); } /* Success. */ return CPARSE_SUCCESS; }