Пример #1
0
void
capture_packet_time_sorter(vector_t *vector, void *item)
{
    capture_packet_t *prev, *cur;
    int count = vector_count(vector);
    int i;

    // Get current item
    cur = (capture_packet_t *) item;
    prev = vector_item(vector, count - 2);

    // Check if the item is already sorted
    if (prev && timeval_is_older(cur->header->ts, prev->header->ts)) {
        return;
    }

    for (i = count - 2 ; i >= 0; i--) {
        // Get previous packet
        prev = vector_item(vector, i);
        // Check if the item is already in a sorted position
        if (timeval_is_older(cur->header->ts, prev->header->ts)) {
            vector_insert(vector, item, i + 1);
            return;
        }
    }

    // Put this item at the begining of the vector
    vector_insert(vector, item, 0);
}
Пример #2
0
void
sip_list_sorter(vector_t *vector, void *item)
{
    sip_call_t *prev, *cur = (sip_call_t *)item;
    int count = vector_count(vector);
    int i;

    // First item is alway sorted
    if (vector_count(vector) == 1)
        return;

    prev = vector_item(vector, vector_count(vector) - 2);

    // Check if the item is already sorted
    if (call_attr_compare(cur, prev, calls.sort.by) == 0) {
        return;
    }

    for (i = count - 2 ; i >= 0; i--) {
        // Get previous item
        prev = vector_item(vector, i);
        // Check if the item is already in a sorted position
        int cmp = call_attr_compare(cur, prev, calls.sort.by);
        if ((calls.sort.asc && cmp > 0) || (!calls.sort.asc && cmp < 0)) {
            vector_insert(vector, item, i + 1);
            return;
        }
    }

    // Put this item at the begining of the vector
    vector_insert(vector, item, 0);
}
Пример #3
0
rtp_stream_t *
call_group_get_next_stream(sip_call_group_t *group, rtp_stream_t *stream)
{
    rtp_stream_t *next = NULL;
    rtp_stream_t *cand;
    sip_call_t *call;
    vector_iter_t streams;
    int i;

    for (i = 0; i < vector_count(group->calls); i++) {
        call = vector_item(group->calls, i);
        streams = vector_iterator(call->streams);
        while ( (cand = vector_iterator_next(&streams))) {
            if (!stream_get_count(cand))
                continue;

            // candidate must be between msg and next
            if (stream_is_older(cand, stream) && (!next || stream_is_older(next, cand))) {
                next = cand;
            }
        }
    }

    return next;
}
Пример #4
0
sip_msg_t *
call_group_get_next_msg(sip_call_group_t *group, sip_msg_t *msg)
{
    sip_msg_t *next = NULL;
    sip_msg_t *cand;
    vector_iter_t msgs;
    sip_call_t *call;
    int i;

    for (i = 0; i < vector_count(group->calls); i++) {

        call = vector_item(group->calls, i);
        msgs = vector_iterator(call->msgs);

        if (msg && call == msg_get_call(msg))
            vector_iterator_set_current(&msgs, msg->index);

        if (group->sdp_only)
            vector_iterator_set_filter(&msgs, msg_has_sdp);

        cand = NULL;
        while ((cand = vector_iterator_next(&msgs))) {
            // candidate must be between msg and next
            if (msg_is_older(cand, msg) && (!next || !msg_is_older(cand, next))) {
                next = cand;
                break;
            }
        }
    }

    return sip_parse_msg(next);
}
Пример #5
0
void
capture_packet_time_sorter(vector_t *vector, void *item)
{
    struct timeval curts, prevts;
    int count = vector_count(vector);
    int i;

    // TODO Implement multiframe packets
    curts = packet_time(item);
    prevts = packet_time(vector_last(vector));

    // Check if the item is already sorted
    if (timeval_is_older(curts, prevts)) {
        return;
    }

    for (i = count - 2 ; i >= 0; i--) {
        // Get previous packet
        prevts = packet_time(vector_item(vector, i));
        // Check if the item is already in a sorted position
        if (timeval_is_older(curts, prevts)) {
            vector_insert(vector, item, i + 1);
            return;
        }
    }

    // Put this item at the begining of the vector
    vector_insert(vector, item, 0);
}
Пример #6
0
char* xyzsh_job_title(int n)
{
    if(n < vector_count(gJobs) && n >= 0) {
        sObject* job = vector_item(gJobs, n);
        return SJOB(job).mName;
    }
    else {
        return NULL;
    }
}
Пример #7
0
int
call_group_msg_count(sip_call_group_t *group)
{
    sip_call_t *call;
    vector_iter_t msgs;
    int msgcnt = 0, i;

    for (i = 0; i < vector_count(group->calls); i++) {
        call = vector_item(group->calls, i);
        msgs = vector_iterator(call->msgs);
        if (group->sdp_only) {
            vector_iterator_set_filter(&msgs, msg_has_sdp);
        }
        msgcnt += vector_iterator_count(&msgs);
    }
    return msgcnt;
}
Пример #8
0
void *
vector_iterator_prev(vector_iter_t *it)
{
    void *item;

    if (it->current == -1)
        return NULL;

    while ((item = vector_item(it->vector, --it->current))) {
        if (it->filter) {
            if (it->filter(item)) {
                return item;
            }
        } else {
            return item;
        }
    }
    return NULL;
}
Пример #9
0
void *
vector_iterator_next(vector_iter_t *it)
{
    void *item;

    if (!it || it->current >= vector_count(it->vector))
        return NULL;

    while ((item = vector_item(it->vector, ++it->current))) {
        if (it->filter) {
            if (it->filter(item)) {
                return item;
            }
        } else {
            return item;
        }
    }
    return NULL;
}
Пример #10
0
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;
}
Пример #11
0
/**
 * @brief Main function logic
 *
 * Parse command line options and start running threads
 */
int
main(int argc, char* argv[])
{
    int opt, idx, limit, only_calls, no_incomplete, i;
    const char *device, *outfile;
    char bpf[512];
    const char *keyfile;
    const char *match_expr;
    int match_insensitive = 0, match_invert = 0;
    int no_interface = 0, quiet = 0, rtp_capture = 0;
    vector_t *infiles = vector_create(0, 1);

    // Program otptions
    static struct option long_options[] = {
        { "help", no_argument, 0, 'h' },
        { "version", no_argument, 0, 'V' },
        { "device", required_argument, 0, 'd' },
        { "input", required_argument, 0, 'I' },
        { "output", required_argument, 0, 'O' },
#if defined(WITH_GNUTLS) || defined(WITH_OPENSSL)
        { "keyfile", required_argument, 0, 'k' },
#endif
        { "calls", no_argument, 0, 'c' },
        { "rtp", no_argument, 0, 'r' },
        { "limit", no_argument, 0, 'l' },
        { "icase", no_argument, 0, 'i' },
        { "invert", no_argument, 0, 'v' },
        { "no-interface", no_argument, 0, 'N' },
        { "dump-config", no_argument, 0, 'D' },
#ifdef USE_EEP
        { "eep-listen", required_argument, 0, 'L' },
        { "eep-send", required_argument, 0, 'H' },
#endif
        { "quiet", no_argument, 0, 'q' },
    };

    // Initialize configuration options
    init_options();

    // Get initial values for configurable arguments
    device = setting_get_value(SETTING_CAPTURE_DEVICE);
    outfile = setting_get_value(SETTING_CAPTURE_OUTFILE);
    keyfile = setting_get_value(SETTING_CAPTURE_KEYFILE);
    limit = setting_get_intvalue(SETTING_CAPTURE_LIMIT);
    only_calls = setting_enabled(SETTING_SIP_CALLS);
    no_incomplete = setting_enabled(SETTING_SIP_NOINCOMPLETE);
    rtp_capture = setting_enabled(SETTING_CAPTURE_RTP);

    // Parse command line arguments
    opterr = 0;
    char *options = "hVd:I:O:pqtW:k:crl:ivNqDL:H:";
    while ((opt = getopt_long(argc, argv, options, long_options, &idx)) != -1) {
        switch (opt) {
        case 'h':
            usage();
            return 0;
        case 'V':
            version();
            return 0;
        case 'd':
            device = optarg;
            break;
        case 'I':
            vector_append(infiles, optarg);
            break;
        case 'O':
            outfile = optarg;
            break;
        case 'l':
            if(!(limit = atoi(optarg))) {
                fprintf(stderr, "Invalid limit value.\n");
                return 0;
            }
            break;
#if defined(WITH_GNUTLS) || defined(WITH_OPENSSL)
        case 'k':
            keyfile = optarg;
            break;
#endif
        case 'c':
            only_calls = 1;
            setting_set_value(SETTING_SIP_CALLS, SETTING_ON);
            break;
        case 'r':
            rtp_capture = 1;
            setting_set_value(SETTING_CAPTURE_RTP, SETTING_ON);
            break;
        case 'i':
            match_insensitive++;
            break;
        case 'v':
            match_invert++;
            break;
        case 'N':
            no_interface = 1;
            setting_set_value(SETTING_CAPTURE_STORAGE, "none");
            break;
        case 'q':
            quiet = 1;
            break;
        case 'D':
            key_bindings_dump();
            settings_dump();
            return 0;
        // Dark options for dummy ones
        case 'p':
        case 't':
        case 'W':
            break;
#ifdef USE_EEP
        case 'L':
            capture_eep_set_server_url(optarg);
            break;
        case 'H':
            capture_eep_set_client_url(optarg);
            break;
#endif
        case '?':
            if (strchr(options, optopt)) {
                fprintf(stderr, "-%c option requires an argument.\n", optopt);
            } else if (isprint(optopt)) {
                fprintf(stderr, "Unknown option -%c.\n", optopt);
            } else {
                fprintf(stderr, "Unknown option character '\\x%x'.\n", optopt);
            }
            return 1;
        default:
            break;
        }
    }

#if defined(WITH_GNUTLS) || defined(WITH_OPENSSL)
    // Set capture decrypt key file
    capture_set_keyfile(keyfile);
    // Check if we have a keyfile and is valid
    if (keyfile && !tls_check_keyfile(keyfile)) {
        fprintf(stderr, "%s does not contain a valid RSA private key.\n", keyfile);
        return 1;
    }
#endif

    // Check if given argument is a file
    if (argc == 2 && (access(argv[1], F_OK) == 0)) {
        // Old legacy option to open pcaps without other arguments
        printf("%s seems to be a file: You forgot -I flag?\n", argv[1]);
        return 0;
    }

    // Initialize SIP Messages Storage
    sip_init(limit, only_calls, no_incomplete);

    // Set capture options
    capture_init(limit, rtp_capture);

#ifdef USE_EEP
    // Initialize EEP if enabled
    capture_eep_init();
#endif

    // If we have an input file, load it
    if (vector_count(infiles)) {
        for (i = 0; i < vector_count(infiles); i++) {
            // Try to load file
            if (capture_offline(vector_item(infiles, i), outfile) != 0)
                return 1;
        }
    } else {
        // Check if all capture data is valid
        if (capture_online(device, outfile) != 0)
            return 1;
    }

    // Remove Input files vector
    vector_destroy(infiles);

    // More arguments pending!
    if (argv[optind]) {
        // Assume first pending argument is  match expression
        match_expr = argv[optind++];

        // Try to build the bpf filter string with the rest
        memset(bpf, 0, sizeof(bpf));
        for (i = optind; i < argc; i++)
            sprintf(bpf + strlen(bpf), "%s ", argv[i]);

        // Check if this BPF filter is valid
        if (capture_set_bpf_filter(bpf) != 0) {
            // BPF Filter invalid, check incluiding match_expr
            match_expr = 0;    // There is no need to parse all payload at this point


            // Build the bpf filter string
            memset(bpf, 0, sizeof(bpf));
            for (i = optind - 1; i < argc; i++)
                sprintf(bpf + strlen(bpf), "%s ", argv[i]);

            // Check bpf filter is valid again
            if (capture_set_bpf_filter(bpf) != 0) {
                fprintf(stderr, "Couldn't install filter %s: %s\n", bpf, capture_last_error());
                return 1;
            }
        }

        // Set the capture filter
        if (match_expr)
            if (sip_set_match_expression(match_expr, match_insensitive, match_invert)) {
                fprintf(stderr, "Unable to parse expression %s\n", match_expr);
                return 1;
            }
    }

    // Start a capture thread
    if (capture_launch_thread() != 0) {
        ncurses_deinit();
        fprintf(stderr, "Failed to launch capture thread.\n");
        return 1;
    }

    if (!no_interface) {
        // Initialize interface
        ncurses_init();
        // This is a blocking call.
        // Create the first panel and wait for user input
        ui_create_panel(PANEL_CALL_LIST);
        wait_for_input();
    } else {
        setbuf(stdout, NULL);
        while(capture_get_status() != CAPTURE_OFFLINE) {
            if (!quiet)
                printf("\rDialog count: %d", sip_calls_count());
            usleep(500 * 1000);
        }
        if (!quiet)
            printf("\rDialog count: %d\n", sip_calls_count());
    }

    // Capture deinit
    capture_deinit();

    // Deinitialize interface
    ncurses_deinit();

    // Deinitialize configuration options
    deinit_options();

    // Deallocate sip stored messages
    sip_deinit();

    // Leaving!
    return 0;
}
Пример #12
0
sip_call_t *
sip_find_by_index(int index)
{
    return vector_item(calls.list, index);
}
Пример #13
0
int
call_list_handle_key(PANEL *panel, int key)
{
    int i, height, width, rnpag_steps = setting_get_intvalue(SETTING_CL_SCROLLSTEP);
    call_list_info_t *info;
    ui_t *next_panel;
    sip_call_group_t *group;
    int action = -1;
    sip_call_t *call;

    // Sanity check, this should not happen
    if (!(info  = call_list_info(panel)))
        return -1;

    // Handle form key
    if (info->form_active)
        return call_list_handle_form_key(panel, key);

    // Get window of call list panel
    WINDOW *win = info->list_win;
    getmaxyx(win, height, width);

    // Reset iterator position to current call
    vector_iterator_set_current(&info->calls, info->cur_call);

    // Check actions for this key
    while ((action = key_find_action(key, action)) != ERR) {
        // Check if we handle this action
        switch (action) {
            case ACTION_DOWN:
                // Check if there is a call below us
                if (!vector_iterator_next(&info->calls))
                    break;
                info->cur_call = vector_iterator_current(&info->calls);
                info->cur_line++;
                // If we are out of the bottom of the displayed list
                // refresh it starting in the next call
                if (info->cur_line > height) {
                    vector_iterator_set_current(&info->calls, info->first_call);
                    vector_iterator_next(&info->calls);
                    info->first_call = vector_iterator_current(&info->calls);
                    info->first_line++;
                    info->cur_line = height;
                }
                // Disable Autoscroll
                info->autoscroll = 0;
                break;
            case ACTION_UP:
                // Check if there is a call above us
                if (!vector_iterator_prev(&info->calls))
                    break;
                info->cur_call = vector_iterator_current(&info->calls);
                info->cur_line--;
                // If we are out of the top of the displayed list
                // refresh it starting in the previous (in fact current) call
                if (info->cur_line <= 0) {
                    info->first_call = info->cur_call;
                    info->first_line--;
                    info->cur_line = 1;
                }
                // Disable Autoscroll
                info->autoscroll = 0;
                break;
            case ACTION_HNPAGE:
                rnpag_steps = rnpag_steps / 2;
                /* no break */
            case ACTION_NPAGE:
                // Next page => N key down strokes
                for (i = 0; i < rnpag_steps; i++)
                    call_list_handle_key(panel, KEY_DOWN);
                // Disable Autoscroll
                info->autoscroll = 0;
                break;
            case ACTION_HPPAGE:
                rnpag_steps = rnpag_steps / 2;
                /* no break */
            case ACTION_PPAGE:
                // Prev page => N key up strokes
                for (i = 0; i < rnpag_steps; i++)
                    call_list_handle_key(panel, KEY_UP);
                // Disable Autoscroll
                info->autoscroll = 0;
                break;
            case ACTION_BEGIN:
                // Initialize structures
                info->first_call = info->cur_call = -1;
                info->first_line = info->cur_line = 0;
                // Disable Autoscroll
                info->autoscroll = 0;
                break;
            case ACTION_END:
                // Check if there is a call below us
                while (vector_iterator_next(&info->calls)) {
                    info->cur_call = vector_iterator_current(&info->calls);
                    info->cur_line++;
                    // If we are out of the bottom of the displayed list
                    // refresh it starting in the next call
                    if (info->cur_line > height) {
                        vector_iterator_set_current(&info->calls, info->first_call);
                        vector_iterator_next(&info->calls);
                        info->first_call = vector_iterator_current(&info->calls);
                        info->first_line++;
                        info->cur_line = height;
                        vector_iterator_set_current(&info->calls, info->cur_call);
                    }
                }
                break;
            case ACTION_DISP_FILTER:
                // Activate Form
                call_list_form_activate(panel, 1);
                // Disable Autoscroll
                info->autoscroll = 0;
                break;
            case ACTION_SHOW_FLOW:
            case ACTION_SHOW_FLOW_EX:
            case ACTION_SHOW_RAW:
                // Check we have calls in the list
                if (info->cur_call == -1)
                    break;
                // Create a new group of calls
                group = call_group_clone(info->group);
                // If not selected call, show current call flow
                if (call_group_count(info->group) == 0)
                    call_group_add(group, sip_find_by_index(info->cur_call));

                // Add xcall to the group
                if (action == ACTION_SHOW_FLOW_EX)
                    call_group_add(group, call_get_xcall(sip_find_by_index(info->cur_call)));

                if (action == ACTION_SHOW_RAW) {
                    // Create a Call Flow panel
                    ui_create_panel(PANEL_CALL_RAW);
                    call_raw_set_group(group);
                } else {
                    // Display current call flow (normal or extended)
                    ui_create_panel(PANEL_CALL_FLOW);
                    call_flow_set_group(group);
                }
                break;
            case ACTION_SHOW_FILTERS:
                ui_create_panel(PANEL_FILTER);
                break;
            case ACTION_SHOW_COLUMNS:
                ui_create_panel(PANEL_COLUMN_SELECT);
                break;
            case ACTION_SHOW_STATS:
                ui_create_panel(PANEL_STATS);
                break;
            case ACTION_SAVE:
                next_panel = ui_create_panel(PANEL_SAVE);
                save_set_group(ui_get_panel(next_panel), info->group);
                break;
            case ACTION_CLEAR:
                // Clear group calls
                vector_clear(info->group->calls);
                break;
            case ACTION_CLEAR_CALLS:
                // Remove all stored calls
                sip_calls_clear();
                // Clear List
                call_list_clear(panel);
                break;
            case ACTION_AUTOSCROLL:
                info->autoscroll = (info->autoscroll) ? 0 : 1;
                break;
            case ACTION_SHOW_SETTINGS:
                ui_create_panel(PANEL_SETTINGS);
                break;
            case ACTION_SELECT:
                call = vector_item(vector_iterator_vector(&info->calls), info->cur_call);
                if (call_group_exists(info->group, call)) {
                    call_group_del(info->group, call);
                } else {
                    call_group_add(info->group, call);
                }
                break;
            case ACTION_PREV_SCREEN:
                // Handle quit from this screen unless requested
                if (setting_enabled(SETTING_EXITPROMPT)) {
                    if (dialog_confirm("Confirm exit", "Are you sure you want to quit?", "Yes,No") == 0) {
                        return KEY_ESC;
                    } else {
                        return 0;
                    }
                } else {
                    return KEY_ESC;
                }
                break;
            default:
                // Parse next action
                continue;
        }

        // This panel has handled the key successfully
        break;
    }

    // Return if this panel has handled or not the key
    return (action == ERR) ? key : 0;
}
Пример #14
0
void *
vector_last(vector_t *vector)
{
    return vector_item(vector, vector_count(vector) - 1);
}
Пример #15
0
void *
vector_first(vector_t *vector)
{
    return vector_item(vector, 0);
}