Check-in [371d474ebc]
Overview
Comment:some bugs related to use_cache, etc. also a lot of cleanup.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 371d474ebc7f4ae2e14f7b6ee92151dde19a4aee
User & Date: rmiller on 2011-03-06 23:20:20
Other Links: manifest | tags
Context
2011-03-06
23:30
remove pbl_set_verdict. It was a waste of code lines. check-in: 49947c3157 user: rmiller tags: trunk
23:20
some bugs related to use_cache, etc. also a lot of cleanup. check-in: 371d474ebc user: rmiller tags: trunk
17:47
update readme check-in: d59c5b24a3 user: rmiller tags: trunk
Changes

Modified packetbl.c from [c4e4dc8395] to [ac69747424].

1
2
3
4
5
6
7
8
9

/* Copyright 2004 Russell Miller
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of

|







1
2
3
4
5
6
7
8
9

/* Copyright 2004-2011 Russell Miller
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
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

Modified packetbl.h from [04dd1a732b] to [0899b0d159].

67
68
69
70
71
72
73







74
75
76
77
78
79
80
# define PBL_SET_MODE nfq_set_mode
# define PBL_COPY_PACKET NFQNL_COPY_PACKET
# define PBL_ID_T u_int32_t
# define PBL_ERRSTR ""

#define DEBUG(x, y) if (conf.debug >= x) { printf(y "\n"); }
#define INVALID_OCTET(x) x < 0 || x > 255








struct packet_info {

	uint8_t b1;
	uint8_t b2;
	uint8_t b3;
	uint8_t b4;







>
>
>
>
>
>
>







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# define PBL_SET_MODE nfq_set_mode
# define PBL_COPY_PACKET NFQNL_COPY_PACKET
# define PBL_ID_T u_int32_t
# define PBL_ERRSTR ""

#define DEBUG(x, y) if (conf.debug >= x) { printf(y "\n"); }
#define INVALID_OCTET(x) x < 0 || x > 255
#define DPRINT(format, args...) if (conf.debug == 0) { \
	syslog(LOG_INFO, format , ## args); \
} else { \
	fprintf(stderr, format , ## args); \
}

#define DPRINTQ(format, args...) if (!conf.quiet) { DPRINT(format, ## args) };

struct packet_info {

	uint8_t b1;
	uint8_t b2;
	uint8_t b3;
	uint8_t b4;
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109
110
111
112
113

struct config_entry {

	char *string;
	struct config_entry *next;
	struct packet_info ip;
	struct cidr	cidr;


};

char msgbuf[BUFFERSIZE];

struct config {
	int	allow_non25;
	int	allow_nonsyn;
	int	default_accept;
	int	dryrun;
	int 	log_facility;
	int	queueno;







>



<
<







102
103
104
105
106
107
108
109
110
111
112


113
114
115
116
117
118
119

struct config_entry {

	char *string;
	struct config_entry *next;
	struct packet_info ip;
	struct cidr	cidr;
	int index;

};



struct config {
	int	allow_non25;
	int	allow_nonsyn;
	int	default_accept;
	int	dryrun;
	int 	log_facility;
	int	queueno;
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
struct packet_cache_t {
	uint32_t ipaddr;
	time_t	expires;
	int	action;
};
struct packet_cache_t *packet_cache = NULL;
uint32_t packet_cache_len = USE_CACHE_DEF_LEN;
uint16_t packet_cache_ttl = USE_CACHE_DEF_TTL;
#endif

struct config_entry *hostlistcache = NULL;

int get_packet_info(char *payload, struct packet_info *ip);

int check_packet_list(const struct packet_info *ip, struct config_entry *list);
int check_packet_dnsbl(const struct packet_info *ip, struct config_entry *list);
int parse_cidr(struct config_entry *ce);
/* int validate_blacklist(char *); */
void parse_config(void);
void parse_arguments(int argc, char **argv);
void pbl_init_sockstat(void);
static void get_ip_string(const struct packet_info *ip);
static void pbl_set_verdict(struct PBL_HANDLE *h, PBL_ID_T id,
        unsigned int verdict);

static int pbl_callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
	struct nfq_data *nfa, void *data);
	
typedef struct facility {







|













|







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
struct packet_cache_t {
	uint32_t ipaddr;
	time_t	expires;
	int	action;
};
struct packet_cache_t *packet_cache = NULL;
uint32_t packet_cache_len = USE_CACHE_DEF_LEN;
uint32_t packet_cache_ttl = USE_CACHE_DEF_TTL;
#endif

struct config_entry *hostlistcache = NULL;

int get_packet_info(char *payload, struct packet_info *ip);

int check_packet_list(const struct packet_info *ip, struct config_entry *list);
int check_packet_dnsbl(const struct packet_info *ip, struct config_entry *list);
int parse_cidr(struct config_entry *ce);
/* int validate_blacklist(char *); */
void parse_config(void);
void parse_arguments(int argc, char **argv);
void pbl_init_sockstat(void);
char * get_ip_string(const struct packet_info *ip);
static void pbl_set_verdict(struct PBL_HANDLE *h, PBL_ID_T id,
        unsigned int verdict);

static int pbl_callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
	struct nfq_data *nfa, void *data);
	
typedef struct facility {