forked from firehol/iprange
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ipset.h
136 lines (99 loc) · 3.84 KB
/
ipset.h
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
#ifndef IPRANGE_IPSET_H
#define IPRANGE_IPSET_H
#define MAX_LINE 1024
#define IPSET_FLAG_OPTIMIZED 0x00000001
typedef struct ipset {
char filename[FILENAME_MAX+1];
/* char name[FILENAME_MAX+1]; */
size_t lines;
size_t entries;
size_t entries_max;
size_t unique_ips; /* this is updated only after calling ipset_optimize() */
uint32_t flags;
struct ipset *next;
struct ipset *prev;
network_addr_t *netaddrs;
} ipset;
extern ipset *ipset_create(const char *filename, size_t entries);
extern void ipset_free(ipset *ips);
extern void ipset_free_all(ipset *ips);
extern size_t prefix_counters[33];
extern size_t ipset_unique_ips(ipset *ips);
/* ----------------------------------------------------------------------------
* ipset_grow()
*
* exprand the ipset so that it will have at least the given number of free
* entries in its internal array
*
*/
extern void ipset_grow_internal(ipset *ips, size_t free_entries_needed);
static inline void ipset_grow(ipset *ips, size_t free_entries_needed) {
if(unlikely(!ips)) return;
if(unlikely(!free_entries_needed))
free_entries_needed = 1;
if(unlikely((ips->entries_max - ips->entries) < free_entries_needed))
ipset_grow_internal(ips, free_entries_needed);
}
/* ----------------------------------------------------------------------------
* ipset_added_entry()
*
* validate and check the ipset, after appending one more entry
*
*/
static inline void ipset_added_entry(ipset *ips) {
size_t entries = ips->entries;
ips->lines++;
ips->unique_ips += ips->netaddrs[entries].broadcast - ips->netaddrs[entries].addr + 1;
if(likely(ips->flags & IPSET_FLAG_OPTIMIZED && entries > 0)) {
// the new is just next to the last
if(unlikely(ips->netaddrs[entries].addr == (ips->netaddrs[entries - 1].broadcast + 1))) {
ips->netaddrs[entries - 1].broadcast = ips->netaddrs[entries].broadcast;
return;
}
// the new is after the end of the last
if(likely(ips->netaddrs[entries].addr > ips->netaddrs[entries - 1].broadcast)) {
ips->entries++;
return;
}
// the new is before the beginning of the last
ips->flags &= ~IPSET_FLAG_OPTIMIZED;
if(unlikely(debug)) {
in_addr_t new_from = ips->netaddrs[ips->entries].addr;
in_addr_t new_to = ips->netaddrs[ips->entries].broadcast;
in_addr_t last_from = ips->netaddrs[ips->entries - 1].addr;
in_addr_t last_to = ips->netaddrs[ips->entries - 1].broadcast;
char buf[IP2STR_MAX_LEN + 1];
fprintf(stderr, "%s: NON-OPTIMIZED %s at line %zu, entry %zu, last was %s (%u) - ", PROG, ips->filename, ips->lines, ips->entries, ip2str_r(buf, last_from), last_from);
fprintf(stderr, "%s (%u), new is ", ip2str_r(buf, last_to), last_to);
fprintf(stderr, "%s (%u) - ", ip2str_r(buf, new_from), new_from);
fprintf(stderr, "%s (%u)\n", ip2str_r(buf, new_to), new_to);
}
}
ips->entries++;
}
/* ----------------------------------------------------------------------------
* ipset_add_ip_range()
*
* add an IP entry (from - to) to the ipset given
*
*/
static inline void ipset_add_ip_range(ipset *ips, in_addr_t from, in_addr_t to) {
ipset_grow(ips, 1);
ips->netaddrs[ips->entries].addr = from;
ips->netaddrs[ips->entries].broadcast = to;
ipset_added_entry(ips);
}
/* ----------------------------------------------------------------------------
* ipset_add_ipstr()
*
* add a single IP entry to an ipset, by parsing the given IP string
*
*/
static inline int ipset_add_ipstr(ipset *ips, char *ipstr) {
int err = 0;
ipset_grow(ips, 1);
ips->netaddrs[ips->entries] = str2netaddr(ipstr, &err);
if(!err) ipset_added_entry(ips);
return !err;
}
#endif //IPRANGE_IPSET_H