... | ... |
@@ -30,6 +30,7 @@ |
30 | 30 |
* -------- |
31 | 31 |
* 2006-07-29 created by andrei |
32 | 32 |
* 2007-05-39 added hooks for add; more locks to reduce contention (andrei) |
33 |
+ * 2007-06-26 added hooks for search (andrei) |
|
33 | 34 |
*/ |
34 | 35 |
|
35 | 36 |
|
... | ... |
@@ -129,84 +130,149 @@ struct dst_blst_lst_head* dst_blst_hash=0; |
129 | 130 |
|
130 | 131 |
#ifdef DST_BLACKLIST_HOOKS |
131 | 132 |
|
133 |
+/* there 2 types of callbacks supported: on add new entry to the blacklist |
|
134 |
+ * (DST_BLACKLIST_ADD_CB) and on blacklist search (DST_BLACKLIST_SEARCH_CB). |
|
135 |
+ * Both of them take a struct dest_info* and a flags pointer as parameters |
|
136 |
+ * (unsigned char*). The flags can be changed. |
|
137 |
+ * A callback should return one of: |
|
138 |
+ * DST_BLACKLIST_CONTINUE - do nothing, let other callbacks run |
|
139 |
+ * DST_BLACKLIST_ACCEPT - for blacklist add: force accept immediately, |
|
140 |
+ * for blacklist search: force match and use |
|
141 |
+ * the flags as the blacklist search return. |
|
142 |
+ * ( so the flags should be set to some valid |
|
143 |
+ * non zero BLST flags value ) |
|
144 |
+ * DST_BLACKLIST_DENY - for blacklist add: don't allow adding the |
|
145 |
+ * destination to the blacklist. |
|
146 |
+ * for blacklist search: force return not found |
|
147 |
+ */ |
|
148 |
+ |
|
132 | 149 |
#define MAX_BLST_HOOKS 1 |
133 | 150 |
|
134 |
-static struct blacklist_hook* blacklist_hooks; |
|
135 |
-static unsigned int blacklist_max_hooks=MAX_BLST_HOOKS; |
|
136 |
-static int last_blacklist_hook_idx=0; |
|
151 |
+struct blst_callbacks_lst{ |
|
152 |
+ struct blacklist_hook* hooks; |
|
153 |
+ unsigned int max_hooks; |
|
154 |
+ int last_idx; |
|
155 |
+}; |
|
156 |
+ |
|
157 |
+static struct blst_callbacks_lst blst_add_cb; |
|
158 |
+static struct blst_callbacks_lst blst_search_cb; |
|
137 | 159 |
|
138 |
-static int init_blacklist_hooks() |
|
160 |
+static int init_blst_callback_lst(struct blst_callbacks_lst* cb_lst, int max) |
|
139 | 161 |
{ |
140 |
- blacklist_hooks=pkg_malloc(blacklist_max_hooks* |
|
141 |
- sizeof(struct blacklist_hook)); |
|
142 |
- if (blacklist_hooks==0) |
|
162 |
+ |
|
163 |
+ cb_lst->max_hooks=MAX_BLST_HOOKS; |
|
164 |
+ cb_lst->last_idx=0; |
|
165 |
+ cb_lst->hooks=pkg_malloc(cb_lst->max_hooks*sizeof(struct blacklist_hook)); |
|
166 |
+ if (cb_lst->hooks==0) |
|
143 | 167 |
goto error; |
144 |
- memset(blacklist_hooks, 0, |
|
145 |
- blacklist_max_hooks*sizeof(struct blacklist_hook)); |
|
168 |
+ memset(cb_lst->hooks, 0, cb_lst->max_hooks*sizeof(struct blacklist_hook)); |
|
146 | 169 |
return 0; |
147 | 170 |
error: |
148 |
- LOG(L_ERR, "blacklist_hooks: memory allocation failure\n"); |
|
149 | 171 |
return -1; |
150 | 172 |
} |
151 | 173 |
|
152 | 174 |
|
153 |
-static void destroy_blacklist_hooks() |
|
175 |
+static void destroy_blst_callback_lst(struct blst_callbacks_lst* cb_lst) |
|
154 | 176 |
{ |
155 | 177 |
int r; |
156 |
- |
|
157 |
- if (blacklist_hooks){ |
|
158 |
- for (r=0; r<last_blacklist_hook_idx; r++){ |
|
159 |
- if (blacklist_hooks[r].destroy) |
|
160 |
- blacklist_hooks[r].destroy(); |
|
178 |
+ if (cb_lst && cb_lst->hooks){ |
|
179 |
+ for (r=0; r<cb_lst->last_idx; r++){ |
|
180 |
+ if (cb_lst->hooks[r].destroy) |
|
181 |
+ cb_lst->hooks[r].destroy(); |
|
161 | 182 |
} |
162 |
- pkg_free(blacklist_hooks); |
|
163 |
- blacklist_hooks=0; |
|
183 |
+ pkg_free(cb_lst->hooks); |
|
184 |
+ cb_lst->hooks=0; |
|
185 |
+ cb_lst->last_idx=0; |
|
186 |
+ cb_lst->max_hooks=0; |
|
164 | 187 |
} |
165 | 188 |
} |
166 | 189 |
|
167 | 190 |
|
191 |
+static void destroy_blacklist_hooks() |
|
192 |
+{ |
|
193 |
+ destroy_blst_callback_lst(&blst_add_cb); |
|
194 |
+ destroy_blst_callback_lst(&blst_search_cb); |
|
195 |
+} |
|
196 |
+ |
|
197 |
+ |
|
198 |
+static int init_blacklist_hooks() |
|
199 |
+{ |
|
200 |
+ |
|
201 |
+ if (init_blst_callback_lst(&blst_add_cb, MAX_BLST_HOOKS)!=0) |
|
202 |
+ goto error; |
|
203 |
+ if (init_blst_callback_lst(&blst_search_cb, MAX_BLST_HOOKS)!=0) |
|
204 |
+ goto error; |
|
205 |
+ return 0; |
|
206 |
+error: |
|
207 |
+ LOG(L_ERR, "blacklist_hooks: failure initializing internal lists\n"); |
|
208 |
+ destroy_blacklist_hooks(); |
|
209 |
+ return -1; |
|
210 |
+} |
|
211 |
+ |
|
212 |
+ |
|
213 |
+ |
|
214 |
+ |
|
168 | 215 |
/* allocates a new hook |
169 | 216 |
* returns 0 on success and -1 on error |
170 | 217 |
* must be called from mod init (from the main process, before forking)*/ |
171 |
-int register_blacklist_hook(struct blacklist_hook *h) |
|
218 |
+int register_blacklist_hook(struct blacklist_hook *h, int type) |
|
172 | 219 |
{ |
220 |
+ struct blst_callbacks_lst* cb_lst; |
|
173 | 221 |
struct blacklist_hook* tmp; |
174 | 222 |
int new_max_hooks; |
175 | 223 |
|
176 |
- if (blacklist_max_hooks==0) |
|
224 |
+ switch(type){ |
|
225 |
+ case DST_BLACKLIST_ADD_CB: |
|
226 |
+ cb_lst=&blst_add_cb; |
|
227 |
+ break; |
|
228 |
+ case DST_BLACKLIST_SEARCH_CB: |
|
229 |
+ cb_lst=&blst_search_cb; |
|
230 |
+ break; |
|
231 |
+ default: |
|
232 |
+ BUG("register_blacklist_hook: invalid type %d\n", type); |
|
233 |
+ goto error; |
|
234 |
+ } |
|
235 |
+ if (cb_lst==0 || cb_lst->hooks==0 || cb_lst->max_hooks==0){ |
|
236 |
+ BUG("register_blacklist_hook: intialization error\n"); |
|
177 | 237 |
goto error; |
178 |
- if (last_blacklist_hook_idx >= blacklist_max_hooks){ |
|
179 |
- new_max_hooks=2*blacklist_max_hooks; |
|
180 |
- tmp=pkg_realloc(blacklist_hooks, |
|
238 |
+ } |
|
239 |
+ |
|
240 |
+ if (cb_lst->last_idx >= cb_lst->max_hooks){ |
|
241 |
+ new_max_hooks=2*cb_lst->max_hooks; |
|
242 |
+ tmp=pkg_realloc(cb_lst->hooks, |
|
181 | 243 |
new_max_hooks*sizeof(struct blacklist_hook)); |
182 | 244 |
if (tmp==0){ |
183 | 245 |
goto error; |
184 | 246 |
} |
185 |
- blacklist_hooks=tmp; |
|
186 |
- /* init the new chunk */ |
|
187 |
- memset(&blacklist_hooks[last_blacklist_hook_idx+1], 0, |
|
188 |
- (new_max_hooks-blacklist_max_hooks-1)* |
|
247 |
+ cb_lst->hooks=tmp; |
|
248 |
+ /* init the new chunk (but not the current entry which is |
|
249 |
+ * overwritten anyway) */ |
|
250 |
+ memset(&cb_lst->hooks[cb_lst->max_hooks+1], 0, |
|
251 |
+ (new_max_hooks-cb_lst->max_hooks-1)* |
|
189 | 252 |
sizeof(struct blacklist_hook)); |
190 |
- blacklist_max_hooks=new_max_hooks; |
|
253 |
+ cb_lst->max_hooks=new_max_hooks; |
|
191 | 254 |
} |
192 |
- blacklist_hooks[last_blacklist_hook_idx]=*h; |
|
193 |
- last_blacklist_hook_idx++; |
|
255 |
+ cb_lst->hooks[cb_lst->last_idx]=*h; |
|
256 |
+ cb_lst->last_idx++; |
|
194 | 257 |
return 0; |
195 | 258 |
error: |
196 | 259 |
return -1; |
197 | 260 |
} |
198 | 261 |
|
199 | 262 |
|
200 |
-int blacklist_run_hooks(struct dest_info* si, unsigned char* flags) |
|
263 |
+inline static int blacklist_run_hooks(struct blst_callbacks_lst *cb_lst, |
|
264 |
+ struct dest_info* si, unsigned char* flags) |
|
201 | 265 |
{ |
202 | 266 |
int r; |
203 | 267 |
int ret; |
204 | 268 |
|
205 |
- ret=DST_BLACKLIST_ACCEPT; /* default, if no hook installed accept |
|
269 |
+ ret=DST_BLACKLIST_CONTINUE; /* default, if no hook installed accept |
|
206 | 270 |
blacklist operation */ |
207 |
- for (r=0; r<last_blacklist_hook_idx; r++){ |
|
208 |
- ret=blacklist_hooks[r].on_blst_add(si, flags); |
|
209 |
- if (ret!=DST_BLACKLIST_ACCEPT) break; |
|
271 |
+ if (likely(cb_lst->last_idx==0)) |
|
272 |
+ return ret; |
|
273 |
+ for (r=0; r<cb_lst->last_idx; r++){ |
|
274 |
+ ret=cb_lst->hooks[r].on_blst_add(si, flags); |
|
275 |
+ if (ret!=DST_BLACKLIST_CONTINUE) break; |
|
210 | 276 |
} |
211 | 277 |
return ret; |
212 | 278 |
} |
... | ... |
@@ -593,13 +659,15 @@ inline static int dst_is_blacklisted_ip(unsigned char proto, |
593 | 659 |
ret=0; |
594 | 660 |
now=get_ticks_raw(); |
595 | 661 |
hash=dst_blst_hash_no(proto, ip, port); |
596 |
- LOCK_BLST(hash); |
|
597 |
- e=_dst_blacklist_lst_find(&dst_blst_hash[hash].first, ip, proto, |
|
598 |
- port, now); |
|
599 |
- if (e){ |
|
600 |
- ret=e->flags; |
|
601 |
- } |
|
602 |
- UNLOCK_BLST(hash); |
|
662 |
+ if (unlikely(dst_blst_hash[hash].first)){ |
|
663 |
+ LOCK_BLST(hash); |
|
664 |
+ e=_dst_blacklist_lst_find(&dst_blst_hash[hash].first, ip, proto, |
|
665 |
+ port, now); |
|
666 |
+ if (e){ |
|
667 |
+ ret=e->flags; |
|
668 |
+ } |
|
669 |
+ UNLOCK_BLST(hash); |
|
670 |
+ } |
|
603 | 671 |
return ret; |
604 | 672 |
} |
605 | 673 |
|
... | ... |
@@ -610,7 +678,8 @@ int dst_blacklist_add(unsigned char err_flags, struct dest_info* si) |
610 | 678 |
struct ip_addr ip; |
611 | 679 |
|
612 | 680 |
#ifdef DST_BLACKLIST_HOOKS |
613 |
- if (blacklist_run_hooks(si, &err_flags)!=DST_BLACKLIST_ACCEPT) |
|
681 |
+ if (unlikely (blacklist_run_hooks(&blst_add_cb, si, &err_flags) == |
|
682 |
+ DST_BLACKLIST_DENY)) |
|
614 | 683 |
return 0; |
615 | 684 |
#endif |
616 | 685 |
su2ip_addr(&ip, &si->to); |
... | ... |
@@ -623,7 +692,22 @@ int dst_blacklist_add(unsigned char err_flags, struct dest_info* si) |
623 | 692 |
int dst_is_blacklisted(struct dest_info* si) |
624 | 693 |
{ |
625 | 694 |
struct ip_addr ip; |
695 |
+#ifdef DST_BLACKLIST_HOOKS |
|
696 |
+ unsigned char err_flags; |
|
697 |
+ int action; |
|
698 |
+#endif |
|
626 | 699 |
su2ip_addr(&ip, &si->to); |
700 |
+ |
|
701 |
+#ifdef DST_BLACKLIST_HOOKS |
|
702 |
+ err_flags=0; |
|
703 |
+ if (unlikely((action=(blacklist_run_hooks(&blst_search_cb, si, &err_flags)) |
|
704 |
+ ) != DST_BLACKLIST_CONTINUE)){ |
|
705 |
+ if (action==DST_BLACKLIST_DENY) |
|
706 |
+ return 0; |
|
707 |
+ else /* if (action==DST_BLACKLIST_ACCEPT) */ |
|
708 |
+ return err_flags; |
|
709 |
+ } |
|
710 |
+#endif |
|
627 | 711 |
return dst_is_blacklisted_ip(si->proto, &ip, su_getport(&si->to)); |
628 | 712 |
} |
629 | 713 |
|
... | ... |
@@ -46,11 +46,15 @@ |
46 | 46 |
#define BLST_ADM_PROHIBITED (1<<6) /* administratively prohibited */ |
47 | 47 |
#define BLST_PERMANENT (1<<7) /* never deleted, never expires */ |
48 | 48 |
|
49 |
- |
|
49 |
+/* uncomment the define above to enable blacklist callbacks support */ |
|
50 | 50 |
/*#define DST_BLACKLIST_HOOKS*/ |
51 | 51 |
|
52 |
-#define DST_BLACKLIST_ACCEPT 0 |
|
53 |
-#define DST_BLACKLIST_DENY -1 |
|
52 |
+#define DST_BLACKLIST_CONTINUE 0 /* add: do nothing/ignore, search: ignore */ |
|
53 |
+#define DST_BLACKLIST_ACCEPT 1 /* add: force accept, search: force match */ |
|
54 |
+#define DST_BLACKLIST_DENY -1 /* add: deny, search: force no match */ |
|
55 |
+ |
|
56 |
+#define DST_BLACKLIST_ADD_CB 1 |
|
57 |
+#define DST_BLACKLIST_SEARCH_CB 2 |
|
54 | 58 |
|
55 | 59 |
#ifdef DST_BLACKLIST_HOOKS |
56 | 60 |
struct blacklist_hook{ |
... | ... |
@@ -59,7 +63,7 @@ struct blacklist_hook{ |
59 | 63 |
void (*destroy)(void); |
60 | 64 |
}; |
61 | 65 |
|
62 |
-int register_blacklist_hook(struct blacklist_hook *h); |
|
66 |
+int register_blacklist_hook(struct blacklist_hook *h, int type); |
|
63 | 67 |
#endif /* DST_BLACKLIST_HOOKS */ |
64 | 68 |
|
65 | 69 |
int init_dst_blacklist(); |