41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
pid = fork();
if (pid > 0) {
exit(EXIT_SUCCESS);
}
if (pid < 0) {
if (conf.debug == 0) {
syslog(LOG_ERR, "Fork failed while daemonizing: %s",
strerror(errno));
} else {
fprintf(stderr, "Fork failed while daemonizing: %s",
strerror(errno));
}
exit(EXIT_FAILURE);
}
}
#ifdef USE_CACHE
/*
|
<
<
|
<
<
<
<
|
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
pid = fork();
if (pid > 0) {
exit(EXIT_SUCCESS);
}
if (pid < 0) {
DPRINT("Fork failed while damonizing: %s", strerror(errno));
exit(EXIT_FAILURE);
}
}
#ifdef USE_CACHE
/*
|
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
|
int packet_check_ip(const struct packet_info ip) {
int retval;
#ifdef USE_CACHE
uint32_t ipaddr_check;
uint32_t cache_hash = 0;
time_t currtime;
char *actionstr;
currtime = time(NULL);
ipaddr_check = packet_info_to_ip(ip);
if (packet_cache_len > 0) {
cache_hash = packet_cache_hash(ip) % packet_cache_len;
}
if (cache_hash>0 && cache_hash<packet_cache_len && packet_cache != NULL) {
if (packet_cache[cache_hash].ipaddr==ipaddr_check
&& packet_cache[cache_hash].expires>currtime) {
get_ip_string(&ip);
retval = packet_cache[cache_hash].action;
switch (retval) {
case NF_DROP:
actionstr="reject";
statistics.cachereject++;
break;
case NF_ACCEPT:
actionstr="accept";
statistics.cacheaccept++;
break;
default:
actionstr="???";
break;
}
if (!conf.quiet) {
if (conf.debug == 0) {
syslog(LOG_INFO, "[Found in cache (%s)] [%s]",
actionstr, msgbuf);
} else {
fprintf(stderr, "[Found in cache (%s)] [%s]",
actionstr, msgbuf);
}
}
return retval;
}
}
#endif
/* the get_ip_string is set AFTER the check_packet_*
* calls because of the possibility they could screw with
* msgbuf. They shouldn't, really, but better safe than
* sorry, at least for now. */
if (check_packet_list(&ip, conf.whitelist) == 1) {
get_ip_string(&ip);
if (!conf.quiet) {
if (conf.debug == 0) {
syslog(LOG_INFO,
"[accept whitelist] [%s]",
msgbuf);
} else {
fprintf(stderr,
"[accept whitelist] [%s]",
msgbuf);
}
}
statistics.whitelisthits++;
retval=NF_ACCEPT;
} else
if (check_packet_list(&ip, conf.blacklist) == 1) {
get_ip_string(&ip);
if (!conf.quiet) {
if (conf.debug == 0) {
syslog(LOG_INFO,
"[reject blacklist] [%s]\n",
msgbuf);
} else {
fprintf(stderr,
"[reject blacklist] [%s]\n",
msgbuf);
}
}
statistics.blacklisthits++;
retval=NF_DROP;
} else
if (check_packet_dnsbl(&ip, conf.whitelistbl) == 1) {
get_ip_string(&ip);
if (!conf.quiet) {
if (conf.debug == 0) {
syslog(LOG_INFO,
"[accept dnsbl] [%s]",
msgbuf);
} else {
fprintf(stderr,
"[accept dnsbl] [%s]",
msgbuf);
}
}
statistics.whitelistblhits++;
retval=NF_ACCEPT;
} else
if (check_packet_dnsbl(&ip, conf.blacklistbl) == 1) {
get_ip_string(&ip);
if (!conf.quiet) {
if (conf.debug == 0) {
syslog(LOG_INFO,
"[reject dnsbl] [%s]",
msgbuf);
} else {
fprintf(stderr,
"[reject dnsbl] [%s]",
msgbuf);
}
}
statistics.blacklistblhits++;
retval=NF_DROP;
} else {
get_ip_string(&ip);
if (conf.default_accept == 1) {
if (!conf.quiet) {
if (conf.debug == 0) {
syslog(LOG_INFO,
"[accept fallthrough] [%s]",
msgbuf);
} else {
fprintf(stderr,
"[accept fallthrough] [%s]",
msgbuf);
}
}
retval=NF_ACCEPT;
} else {
if (!conf.quiet) {
if (conf.debug == 0) {
syslog(LOG_INFO,
"[reject fallthrough] [%s]",
msgbuf);
} else {
fprintf(stderr,
"[reject fallthrough] [%s]",
msgbuf);
}
}
retval=NF_DROP;
}
statistics.fallthroughhits++;
}
#ifdef USE_CACHE
/* Put current action into the cache. */
if (packet_cache != NULL) {
packet_cache[cache_hash].ipaddr = ipaddr_check;
packet_cache[cache_hash].action = retval;
packet_cache[cache_hash].expires = currtime + packet_cache_ttl;
}
#endif
return retval;
}
static int pbl_callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
struct nfq_data *nfa, void *data) {
int ret;
|
|
|
<
<
<
|
|
<
<
|
<
<
|
>
>
<
<
<
<
<
|
|
|
<
|
<
<
<
|
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
>
|
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
|
int packet_check_ip(const struct packet_info ip) {
int retval;
#ifdef USE_CACHE
uint32_t ipaddr_check;
uint32_t cache_hash = 0;
time_t currtime;
char *actionstr = NULL, *buf = NULL;
currtime = time(NULL);
ipaddr_check = packet_info_to_ip(ip);
if (packet_cache_len > 0) {
cache_hash = packet_cache_hash(ip) % packet_cache_len;
}
buf = get_ip_string(&ip);
if (cache_hash>0 && cache_hash<packet_cache_len && packet_cache != NULL) {
if (packet_cache[cache_hash].ipaddr==ipaddr_check
&& packet_cache[cache_hash].expires>currtime) {
retval = packet_cache[cache_hash].action;
switch (retval) {
case NF_DROP:
actionstr="reject";
statistics.cachereject++;
break;
case NF_ACCEPT:
actionstr="accept";
statistics.cacheaccept++;
break;
default:
actionstr="???";
break;
}
DPRINTQ("[Found in cache (%s)] [%s]",
actionstr, buf);
free(buf);
return retval;
}
}
#else
int rv;
char *buf;
buf = get_ip_string(&ip);
#endif
if (retval = check_packet_list(&ip, conf.whitelist) > 0) {
DPRINTQ("[accept whitelist] [%s] [%d]\n", buf, retval);
statistics.whitelisthits++;
retval=NF_ACCEPT;
} else if (retval = check_packet_list(&ip, conf.blacklist) > 0) {
DPRINTQ("[reject blacklist] [%s] [%d]\n", buf, retval);
statistics.blacklisthits++;
retval=NF_DROP;
} else if (retval = check_packet_dnsbl(&ip, conf.whitelistbl) > 0) {
DPRINTQ("[accept dnsbl] [%s] [%d]", buf, retval);
statistics.whitelistblhits++;
retval=NF_ACCEPT;
} else if (retval = check_packet_dnsbl(&ip, conf.blacklistbl) > 0) {
DPRINTQ("[reject dnsbl] [%s] [%d]", buf, retval);
statistics.blacklistblhits++;
retval=NF_DROP;
} else {
if (conf.default_accept == 1) {
DPRINTQ("[accept fallthrough] [%s]", buf);
retval=NF_ACCEPT;
} else {
DPRINTQ("[reject fallthrough] [%s]", buf);
retval=NF_DROP;
}
statistics.fallthroughhits++;
}
#ifdef USE_CACHE
/* Put current action into the cache. */
if (packet_cache != NULL) {
packet_cache[cache_hash].ipaddr = ipaddr_check;
packet_cache[cache_hash].action = retval;
packet_cache[cache_hash].expires = currtime + packet_cache_ttl;
}
#endif
free(buf);
return retval;
}
static int pbl_callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
struct nfq_data *nfa, void *data) {
int ret;
|
741
742
743
744
745
746
747
748
749
750
751
752
753
754
|
ce = malloc(sizeof(struct config_entry));
if (ce == NULL) {
/* shouldn't happen... */
fprintf(stderr, "Failed to allocate memory for ce struct\n");
exit(EXIT_FAILURE);
}
ce->string = (char *)strdup(setting);
ce->next = NULL;
#ifdef HAVE_FIREDNS
blacklistlen = strlen(ce->string);
if (ce->string[blacklistlen - 1] == '.') {
ce->string[blacklistlen - 1] = '\0';
}
|
>
|
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
|
ce = malloc(sizeof(struct config_entry));
if (ce == NULL) {
/* shouldn't happen... */
fprintf(stderr, "Failed to allocate memory for ce struct\n");
exit(EXIT_FAILURE);
}
ce->index = i;
ce->string = (char *)strdup(setting);
ce->next = NULL;
#ifdef HAVE_FIREDNS
blacklistlen = strlen(ce->string);
if (ce->string[blacklistlen - 1] == '.') {
ce->string[blacklistlen - 1] = '\0';
}
|
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
|
*
* ARGUMENTS:
* struct packet_info *ip IP address data to check in supplied list.
* struct config_entry *list List that contains data to check in against,
* whitelist for example.
*
* RETURN VALUE:
* 0 is returned if the "ip" cannot be found in the given "list". 1 is
* returned on a successful match.
*
* NOTES:
* "check_packet_list" searches the given list parameter (which is a list
* CIDRs) to determine if the data passed in "ip" matches (whitelist, for
* for example).
* This function must be able to cope with NULL "ip" and "list" paramters
* without aborting.
|
|
|
|
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
|
*
* ARGUMENTS:
* struct packet_info *ip IP address data to check in supplied list.
* struct config_entry *list List that contains data to check in against,
* whitelist for example.
*
* RETURN VALUE:
* 0 is returned if the "ip" cannot be found in the given "list". The index
* of the matched list is returned on a successful match.
*
* NOTES:
* "check_packet_list" searches the given list parameter (which is a list
* CIDRs) to determine if the data passed in "ip" matches (whitelist, for
* for example).
* This function must be able to cope with NULL "ip" and "list" paramters
* without aborting.
|
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
|
while (1) {
uint32_t p = 0;
p = ip_proc;
p &= wltmp->cidr.processed;
if (p == wltmp->cidr.ip) {
rv = snprintf(msgbuf, sizeof(msgbuf),
"%hhu.%hhu.%hhu.%hhu %x/%d",
ip->b1, ip->b2, ip->b3, ip->b4,
wltmp->cidr.ip, wltmp->cidr.network);
if (rv < 0) {
syslog(LOG_ERR, "snprintf failed at line %d: %s",
__LINE__, strerror(errno));
exit (1);
}
return 1;
}
if (wltmp->next == NULL) {
break;
}
wltmp = wltmp->next;
}
return 0;
}
/*
* SYNOPSIS:
* static void get_ip_string(
* const struct packet_info *ip
* );
*
* ARGUMENTS:
* struct packet_info *ip Structure containing IP parts to construct
* the ASCII representation from.
*
* RETURN VALUE:
* (none)
*
* NOTES:
* This function takes the data in the parameter "ip" and stores an ASCII
* representation in the global variable "msgbuf."
* It must be able to cope with "ip" being NULL.
*
*/
static void get_ip_string(const struct packet_info *ip) {
int rv;
if (ip == NULL) {
rv = sprintf(msgbuf, "-");
if (rv < 0) {
syslog(LOG_ERR, "sprintf failed in line %d: %s",
__LINE__, strerror(errno));
exit(1);
}
return;
}
rv = snprintf(msgbuf, sizeof(msgbuf), "%hhu.%hhu.%hhu.%hhu:%hu.%hu",
ip->b1, ip->b2, ip->b3, ip->b4,
ip->s_port,ip->d_port);
if (rv < 0) {
syslog(LOG_ERR, "snprintf failed in line %d: %s",
__LINE__, strerror(errno));
exit(1);
}
return;
}
#ifdef USE_SOCKSTAT
/*
* SYNOPSIS:
* void *pbl_sockstat_thread(
* void *tdata
|
<
<
<
|
<
<
<
<
<
|
|
|
|
>
|
>
>
>
>
>
>
>
|
|
|
|
|
|
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
|
while (1) {
uint32_t p = 0;
p = ip_proc;
p &= wltmp->cidr.processed;
if (p == wltmp->cidr.ip) {
return wltmp->index;
return 1;
}
if (wltmp->next == NULL) {
break;
}
wltmp = wltmp->next;
}
return 0;
}
/*
* SYNOPSIS:
* char * get_ip_string(
* const struct packet_info *ip
* );
*
* ARGUMENTS:
* struct packet_info *ip Structure containing IP parts to construct
* the ASCII representation from.
*
* RETURN VALUE:
* (none)
*
* NOTES:
* This function takes the data in the parameter "ip" and returns a buffer
* containing a string representation. This buffer must be freed.
* It must be able to cope with "ip" being NULL.
*
*/
char *get_ip_string(const struct packet_info *ip) {
int rv;
char *buf = NULL;
buf = malloc(BUFFERSIZE);
if (buf == NULL) {
syslog(LOG_ERR, "could not malloc buf in get_ip_string: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
if (ip == NULL) {
rv = sprintf(buf, "-");
if (rv < 0) {
syslog(LOG_ERR, "sprintf failed in line %d: %s",
__LINE__, strerror(errno));
exit(EXIT_FAILURE);
}
return buf;
}
rv = snprintf(buf, BUFFERSIZE, "%hhu.%hhu.%hhu.%hhu:%hu.%hu",
ip->b1, ip->b2, ip->b3, ip->b4,
ip->s_port,ip->d_port);
if (rv < 0) {
syslog(LOG_ERR, "snprintf failed in line %d: %s",
__LINE__, strerror(errno));
exit(1);
}
return buf;
}
#ifdef USE_SOCKSTAT
/*
* SYNOPSIS:
* void *pbl_sockstat_thread(
* void *tdata
|