summaryrefslogtreecommitdiff
path: root/src/ip_target_file.c
blob: 6bb3c4cfaf434aa23cce315c8d5ee5194636b22a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * ZMapv6 Copyright 2016 Chair of Network Architectures and Services
 * Technical University of Munich
 *
 * XMap Copyright 2021 Xiang Li from Network and Information Security Lab
 * Tsinghua University
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy
 * of the License at http://www.apache.org/licenses/LICENSE-2.0
 */

#include "ip_target_file.h"

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "state.h"

#include "../lib/blocklist.h"
#include "../lib/logger.h"
#include "../lib/util.h"

#define LOGGER_NAME "ip_target_file"

static int ipv46_flag;

int64_t ip_target_file_init(char *file) {
    if (!file)
        log_fatal(LOGGER_NAME, "ip_target_file_init called with NULL filename");
    ipv46_flag = xconf.ipv46_flag;

    return get_file_lines(file);
}

int ip_target_set_thread_pos(iterator_t *it) {
    FILE *fp = fopen(xconf.list_of_ips_filename, "r");
    if (fp == NULL) {
        log_fatal(LOGGER_NAME,
                  "ip_target_set_thread_pos called with NULL filename");
    }

    char     line[64];
    long     pos;
    int      i           = 0;
    uint64_t count       = 0;
    shard_t *sd          = get_shard(it, i);
    uint8_t  num_threads = get_num_threads(it);
    do {
        if (sd->ip_target_file_params.first == count) {
            fgetpos(fp, (fpos_t *) &pos);
            rewind(sd->ip_target_file_params.fp);
            fseek(sd->ip_target_file_params.fp, pos, SEEK_SET);
            sd->ip_target_file_params.pos = pos;
            i++;
            if (i >= num_threads) return EXIT_SUCCESS;
            sd = get_shard(it, i);
        }
        count++;
    } while (fgets(line, sizeof(line), fp));
    fclose(fp);

    return EXIT_SUCCESS;
}

static int recover_thread_file_params(shard_t *shard) {
    if (shard->ip_target_file_params.port_current + 1 >=
        shard->ip_target_file_params.port_total)
        return EXIT_FAILURE;
    shard->ip_target_file_params.port_current++;
    shard->ip_target_file_params.current = shard->ip_target_file_params.first;
    rewind(shard->ip_target_file_params.fp);
    fseek(shard->ip_target_file_params.fp, shard->ip_target_file_params.pos,
          SEEK_SET);
    return EXIT_SUCCESS;
}

static int recover_thread_file_params_(shard_t *shard) {
    if (shard->ip_target_file_params.index_current + 1 >=
        shard->ip_target_file_params.index_total) {
        shard->ip_target_file_params.index_current = 0;
        if (recover_thread_file_params(shard)) return EXIT_FAILURE;
    } else {
        shard->ip_target_file_params.index_current++;
        shard->ip_target_file_params.current =
            shard->ip_target_file_params.first;
        rewind(shard->ip_target_file_params.fp);
        fseek(shard->ip_target_file_params.fp, shard->ip_target_file_params.pos,
              SEEK_SET);
    }
    return EXIT_SUCCESS;
}

int ip_target_file_get_ip(void *ip, shard_t *shard) {
    if (shard->ip_target_file_params.current >=
        shard->ip_target_file_params.last)
        if (recover_thread_file_params_(shard)) return EXIT_FAILURE;

    FILE *fp = shard->ip_target_file_params.fp;
    assert(fp);

    char  line[64];
    char *ret, *pos;

    ret = fgets(line, sizeof(line), fp);
    if (ret == NULL)
        if (recover_thread_file_params(shard)) return EXIT_FAILURE;

    shard->ip_target_file_params.current++;
    pos = strchr(line, '\n');
    if (pos != NULL) *pos = '\0';
    pos = strchr(line, '/');
    if (pos != NULL) *pos = '\0';
    if (!inet_str2in(line, ip, ipv46_flag)) {
        if (!xconf.ignore_filelist_error)
            log_fatal(LOGGER_NAME,
                      "could not parse IPv%d address from line: %s: %s",
                      ipv46_flag, line, strerror(errno));
        goto goon;
    }

    while (!blocklist_is_allowed_ip(ip)) {
    goon:
        if (shard->ip_target_file_params.current >=
            shard->ip_target_file_params.last)
            if (recover_thread_file_params(shard)) return EXIT_FAILURE;
        ret = fgets(line, sizeof(line), fp);
        if (ret == NULL)
            if (recover_thread_file_params(shard)) return EXIT_FAILURE;
        shard->ip_target_file_params.current++;
        pos = strchr(line, '\n');
        if (pos != NULL) *pos = '\0';
        pos = strchr(line, '/');
        if (pos != NULL) *pos = '\0';
        if (!inet_str2in(line, ip, ipv46_flag)) {
            if (!xconf.ignore_filelist_error)
                log_fatal(LOGGER_NAME,
                          "could not parse IPv%d address from line: %s: %s",
                          ipv46_flag, line, strerror(errno));
        }
    }

    return EXIT_SUCCESS;
}

port_h_t ip_target_file_get_port(shard_t *shard) {
    return xconf.target_port_list[shard->ip_target_file_params.port_current];
}

index_h_t ip_target_file_get_index(shard_t *shard) {
    return shard->ip_target_file_params.index_current;
}