Browse code

Merge remote branch 'origin/andrei/blst_send_flags'

Support for blacklist ignore flags, both global and on a per
message basis.
E.g.:
per message:
if (method=~"MESSAGE")
blst_set_ignore(6);

global:
sercmd cfg.set_now_int core dst_blacklist_tcp_imask 16

* origin/andrei/blst_send_flags:
NEWS: minor blacklist flag number correction
tm: blacklist on 503 reply fixed for send flags
NEWS: mentioned blacklist ignore masks
core: cfg script support for blacklist ignore masks
blst: global config variables for ignoring blacklist events
blst: docs for blst_{set,clear}_ignore script functions
blst: functions for ignoring blacklist events
blst: use dst_blacklist_force_add
tm: simplified blacklist add code
blacklist: ignore mask support
tm: updated to the new snd_flags_t structure
core: send_flags preliminary blacklist support

Conflicts:
NEWS
cfg.lex
cfg.y
dst_blacklist.h

Andrei Pelinescu-Onciul authored on 19/02/2010 15:37:51
Showing 24 changed files
... ...
@@ -3,7 +3,43 @@ Release notes for SIP Router (sr)
3 3
 
4 4
 $Id$
5 5
 
6
-sip-router changes
6
+sip-router 3.1 chages
7
+
8
+core:
9
+  - global, per protocol blacklist ignore masks (via extended send_flags).
10
+    See dst_blacklist_udp_imask a.s.o (dst_blacklist_*_imask).
11
+  - per message blacklist ignore masks
12
+
13
+new config variables:
14
+  - dst_blacklist_udp_imask - global blacklist events ignore mask for udp
15
+    (a blacklist event/reason set in this variable will be ignored when 
16
+    deciding whether or not to blacklist an udp destination). Can be set
17
+    at runtime. Default: 0 (no blacklist reason is ignored).
18
+    Possible values:  0 -disabled, 2 - send error; 4 - connect error,
19
+                      8 - icmp (reserverd), 16 - transaction timeout,
20
+                     32 - 503 received, 64 - administratively prohibited
21
+                     (manually set).
22
+   - dst_blacklist_tcp_imask - like dst_blacklist_udp_imask, but for tcp.
23
+   - dst_blacklist_tls_imask - like dst_blacklist_tls_imask, but for tcp.
24
+   - dst_blacklist_sctp_imask -like dst_blacklist_sctp_imask, but for tcp.
25
+
26
+modules:
27
+   - blst: functions for ignoring blacklist events per message:
28
+           blst_set_ignore(mask):  set the events in mask in the per
29
+            per message blacklist ignore mask for a request
30
+            (see dst_blacklist_udp_imask for possible values).
31
+            The basic operation is: msg_blst_ignore_mask|=mask.
32
+           blst_clear_ignore(mask): like blst_set_ignore(mask), but instead
33
+            of setting some events, it clears them
34
+            (msg_blst_ignore_mask&=~mask).
35
+           blst_rpl_set_ignore(mask): like blst_set_ignore(mask), but sets
36
+            the mask for possible local replies to the current message.
37
+           blst_rpl_clear_ignore(mask): like blst_rpl_ignore(mask), but
38
+            clears instead of setting.
39
+
40
+
41
+
42
+sip-router 3.0 changes
7 43
 
8 44
 core:
9 45
   - type casts operators: (int), (str).
... ...
@@ -66,6 +102,8 @@ config script changes:
66 102
   - event route support: event_route[module_name:eventid]
67 103
   - user and shm_force_alloc must now appear prior to any modparam() or route
68 104
      block.
105
+  - per message send_flags support (see set_forward_no_connect(),
106
+     set_forward_reply_no_connect(), set_forward_close() & set_reply_close())
69 107
 
70 108
 build system:
71 109
   - multiple modules directories are now supported (defined in Makefile.dirs)
... ...
@@ -1235,19 +1235,19 @@ match_cleanup:
1235 1235
 				ret=v;
1236 1236
 			break;
1237 1237
 		case SET_FWD_NO_CONNECT_T:
1238
-			msg->fwd_send_flags|= SND_F_FORCE_CON_REUSE;
1238
+			msg->fwd_send_flags.f|= SND_F_FORCE_CON_REUSE;
1239 1239
 			ret=1; /* continue processing */
1240 1240
 			break;
1241 1241
 		case SET_RPL_NO_CONNECT_T:
1242
-			msg->rpl_send_flags|= SND_F_FORCE_CON_REUSE;
1242
+			msg->rpl_send_flags.f|= SND_F_FORCE_CON_REUSE;
1243 1243
 			ret=1; /* continue processing */
1244 1244
 			break;
1245 1245
 		case SET_FWD_CLOSE_T:
1246
-			msg->fwd_send_flags|= SND_F_CON_CLOSE;
1246
+			msg->fwd_send_flags.f|= SND_F_CON_CLOSE;
1247 1247
 			ret=1; /* continue processing */
1248 1248
 			break;
1249 1249
 		case SET_RPL_CLOSE_T:
1250
-			msg->rpl_send_flags|= SND_F_CON_CLOSE;
1250
+			msg->rpl_send_flags.f|= SND_F_CON_CLOSE;
1251 1251
 			ret=1; /* continue processing */
1252 1252
 			break;
1253 1253
 /*
... ...
@@ -81,6 +81,7 @@
81 81
  *  2009-04-24  add strlen, strempty and defined operators (andrei)
82 82
  *  2009-03-07  RETCODE, it's now  a core pvar (andrei)
83 83
  *  2010-01-10  added SHM_MEM_SZ (andrei)
84
+ *  2010-02-17 added DST_BLST_{UDP,TCP,TLS,SCTP}_IMASK (andrei)
84 85
 */
85 86
 
86 87
 
... ...
@@ -358,6 +359,10 @@ USE_DST_BLST		use_dst_blacklist
358 359
 DST_BLST_MEM		dst_blacklist_mem
359 360
 DST_BLST_TTL		dst_blacklist_expire|dst_blacklist_ttl
360 361
 DST_BLST_GC_INT		dst_blacklist_gc_interval
362
+DST_BLST_UDP_IMASK	dst_blacklist_udp_imask
363
+DST_BLST_TCP_IMASK	dst_blacklist_tcp_imask
364
+DST_BLST_TLS_IMASK	dst_blacklist_tls_imask
365
+DST_BLST_SCTP_IMASK	dst_blacklist_sctp_imask
361 366
 
362 367
 
363 368
 PORT	port
... ...
@@ -703,6 +708,14 @@ EAT_ABLE	[\ \t\b\r]
703 708
 								return DST_BLST_TTL; }
704 709
 <INITIAL>{DST_BLST_GC_INT}	{ count(); yylval.strval=yytext;
705 710
 								return DST_BLST_GC_INT; }
711
+<INITIAL>{DST_BLST_UDP_IMASK}	{ count(); yylval.strval=yytext;
712
+								return DST_BLST_UDP_IMASK; }
713
+<INITIAL>{DST_BLST_TCP_IMASK}	{ count(); yylval.strval=yytext;
714
+								return DST_BLST_TCP_IMASK; }
715
+<INITIAL>{DST_BLST_TLS_IMASK}	{ count(); yylval.strval=yytext;
716
+								return DST_BLST_TLS_IMASK; }
717
+<INITIAL>{DST_BLST_SCTP_IMASK}	{ count(); yylval.strval=yytext;
718
+								return DST_BLST_SCTP_IMASK; }
706 719
 <INITIAL>{PORT}	{ count(); yylval.strval=yytext; return PORT; }
707 720
 <INITIAL>{STAT}	{ count(); yylval.strval=yytext; return STAT; }
708 721
 <INITIAL>{MAXBUFFER}	{ count(); yylval.strval=yytext; return MAXBUFFER; }
... ...
@@ -98,6 +98,7 @@
98 98
  * 2009-05-04  switched if to rval_expr (andrei)
99 99
  * 2010-01-10  init shm on first mod_param or route block;
100 100
  *             added SHM_MEM_SZ (andrei)
101
+ * 2010-02-17  added blacklist imask (DST_BLST_*_IMASK) support (andrei)
101 102
 */
102 103
 
103 104
 %{
... ...
@@ -403,6 +404,10 @@ extern char *finame;
403 404
 %token DST_BLST_MEM
404 405
 %token DST_BLST_TTL
405 406
 %token DST_BLST_GC_INT
407
+%token DST_BLST_UDP_IMASK
408
+%token DST_BLST_TCP_IMASK
409
+%token DST_BLST_TLS_IMASK
410
+%token DST_BLST_SCTP_IMASK
406 411
 
407 412
 %token PORT
408 413
 %token STAT
... ...
@@ -840,14 +845,36 @@ assign_stm:
840 845
 	| DNS_CACHE_DEL_NONEXP error { yyerror("boolean value expected"); }
841 846
 	| DST_BLST_INIT EQUAL NUMBER   { IF_DST_BLACKLIST(dst_blacklist_init=$3); }
842 847
 	| DST_BLST_INIT error { yyerror("boolean value expected"); }
843
-	| USE_DST_BLST EQUAL NUMBER   { IF_DST_BLACKLIST(default_core_cfg.use_dst_blacklist=$3); }
848
+	| USE_DST_BLST EQUAL NUMBER {
849
+		IF_DST_BLACKLIST(default_core_cfg.use_dst_blacklist=$3);
850
+	}
844 851
 	| USE_DST_BLST error { yyerror("boolean value expected"); }
845
-	| DST_BLST_MEM EQUAL NUMBER   { IF_DST_BLACKLIST(default_core_cfg.blst_max_mem=$3); }
852
+	| DST_BLST_MEM EQUAL NUMBER {
853
+		IF_DST_BLACKLIST(default_core_cfg.blst_max_mem=$3); 
854
+	}
846 855
 	| DST_BLST_MEM error { yyerror("boolean value expected"); }
847
-	| DST_BLST_TTL EQUAL NUMBER   { IF_DST_BLACKLIST(default_core_cfg.blst_timeout=$3); }
856
+	| DST_BLST_TTL EQUAL NUMBER {
857
+		IF_DST_BLACKLIST(default_core_cfg.blst_timeout=$3);
858
+	}
848 859
 	| DST_BLST_TTL error { yyerror("boolean value expected"); }
849 860
 	| DST_BLST_GC_INT EQUAL NUMBER { IF_DST_BLACKLIST(blst_timer_interval=$3);}
850 861
 	| DST_BLST_GC_INT error { yyerror("boolean value expected"); }
862
+	| DST_BLST_UDP_IMASK EQUAL NUMBER {
863
+		IF_DST_BLACKLIST(default_core_cfg.blst_udp_imask=$3);
864
+	}
865
+	| DST_BLST_UDP_IMASK error { yyerror("number(flags) expected"); }
866
+	| DST_BLST_TCP_IMASK EQUAL NUMBER {
867
+		IF_DST_BLACKLIST(default_core_cfg.blst_tcp_imask=$3);
868
+	}
869
+	| DST_BLST_TCP_IMASK error { yyerror("number(flags) expected"); }
870
+	| DST_BLST_TLS_IMASK EQUAL NUMBER {
871
+		IF_DST_BLACKLIST(default_core_cfg.blst_tls_imask=$3);
872
+	}
873
+	| DST_BLST_TLS_IMASK error { yyerror("number(flags) expected"); }
874
+	| DST_BLST_SCTP_IMASK EQUAL NUMBER {
875
+		IF_DST_BLACKLIST(default_core_cfg.blst_sctp_imask=$3);
876
+	}
877
+	| DST_BLST_SCTP_IMASK error { yyerror("number(flags) expected"); }
851 878
 	| PORT EQUAL NUMBER   { port_no=$3; }
852 879
 	| STAT EQUAL STRING {
853 880
 		#ifdef STATS
... ...
@@ -69,6 +69,10 @@ struct cfg_group_core default_core_cfg = {
69 69
 	0, /*!< dst blacklist is disabled by default */
70 70
 	DEFAULT_BLST_TIMEOUT,
71 71
 	DEFAULT_BLST_MAX_MEM,
72
+	0, /* blst_udp_imask */
73
+	0, /* blst_tcp_imask */
74
+	0, /* blst_tls_imask */
75
+	0, /* blst_sctp_imask */
72 76
 #endif
73 77
 	/* resolver */
74 78
 #ifdef USE_IPV6
... ...
@@ -129,7 +133,16 @@ cfg_def_t core_cfg_def[] = {
129 133
 	{"dst_blacklist_expire",	CFG_VAR_INT,	0, 0, 0, 0,
130 134
 		"how much time (in s) a blacklisted destination is kept in the list"},
131 135
 	{"dst_blacklist_mem",	CFG_VAR_INT,	0, 0, blst_max_mem_fixup, 0,
132
-		"maximum shared memory amount (in KB) used for keeping the blacklisted destinations"},
136
+		"maximum shared memory amount (in KB) used for keeping the blacklisted"
137
+			" destinations"},
138
+	{"dst_blacklist_udp_imask", CFG_VAR_INT, 0, 0, 0, blst_reinit_ign_masks,
139
+		"blacklist event ignore mask for UDP"},
140
+	{"dst_blacklist_tcp_imask", CFG_VAR_INT, 0, 0, 0, blst_reinit_ign_masks,
141
+		"blacklist event ignore mask for TCP"},
142
+	{"dst_blacklist_tls_imask", CFG_VAR_INT, 0, 0, 0, blst_reinit_ign_masks,
143
+		"blacklist event ignore mask for TLS"},
144
+	{"dst_blacklist_sctp_imask", CFG_VAR_INT, 0, 0, 0, blst_reinit_ign_masks,
145
+		"blacklist event ignore mask for SCTP"},
133 146
 #endif
134 147
 	/* resolver */
135 148
 #ifdef USE_DNS_CACHE
... ...
@@ -63,6 +63,10 @@ struct cfg_group_core {
63 63
 	unsigned int	blst_timeout; /*!< blacklist entry ttl */
64 64
 	unsigned int	blst_max_mem; /*!< maximum memory used for the
65 65
 					blacklist entries */
66
+	unsigned int	blst_udp_imask;  /* ignore mask for udp */
67
+	unsigned int	blst_tcp_imask;  /* ignore mask for tcp */
68
+	unsigned int	blst_tls_imask;  /* ignore mask for tls */
69
+	unsigned int	blst_sctp_imask; /* ignore mask for sctp */
66 70
 #endif
67 71
 	/* resolver */
68 72
 	int dns_try_ipv6;
... ...
@@ -143,6 +143,9 @@ struct dst_blst_lst_head* dst_blst_hash=0;
143 143
 struct t_dst_blacklist_stats* dst_blacklist_stats=0;
144 144
 #endif
145 145
 
146
+/* blacklist per protocol event ignore mask array */
147
+unsigned blst_proto_imask[PROTO_LAST+1];
148
+
146 149
 #ifdef DST_BLACKLIST_HOOKS
147 150
 
148 151
 /* there 2 types of callbacks supported: on add new entry to the blacklist
... ...
@@ -303,6 +306,26 @@ inline static int blacklist_run_hooks(struct blst_callbacks_lst *cb_lst,
303 306
 #endif /* DST_BLACKLIST_HOOKS */
304 307
 
305 308
 
309
+/** init per protocol blacklist event ignore masks.
310
+ * @return 0 on success, < 0 on error.
311
+ */
312
+int blst_init_ign_masks()
313
+{
314
+	if ((PROTO_UDP > PROTO_LAST) || (PROTO_TCP > PROTO_LAST) ||
315
+		(PROTO_TLS > PROTO_LAST) || (PROTO_SCTP > PROTO_LAST)){
316
+		BUG("protocol array too small\n");
317
+		return -1;
318
+	}
319
+	blst_proto_imask[PROTO_UDP]=cfg_get(core, core_cfg, blst_udp_imask);
320
+	blst_proto_imask[PROTO_TCP]=cfg_get(core, core_cfg, blst_tcp_imask);
321
+	blst_proto_imask[PROTO_TLS]=cfg_get(core, core_cfg, blst_tls_imask);
322
+	blst_proto_imask[PROTO_SCTP]=cfg_get(core, core_cfg, blst_sctp_imask);
323
+	blst_proto_imask[PROTO_NONE]=blst_proto_imask[PROTO_UDP];
324
+	return 0;
325
+}
326
+
327
+
328
+
306 329
 inline static void blst_destroy_entry(struct dst_blst_entry* e)
307 330
 {
308 331
 	shm_free(e);
... ...
@@ -485,6 +508,10 @@ int init_dst_blacklist()
485 508
 			goto error;
486 509
 		}
487 510
 	}
511
+	if (blst_init_ign_masks() < 0){
512
+		ret=E_BUG;
513
+		goto error;
514
+	}
488 515
 	return 0;
489 516
 error:
490 517
 	destroy_dst_blacklist();
... ...
@@ -801,8 +828,8 @@ inline static int dst_is_blacklisted_ip(unsigned char proto,
801 828
  * @param timeout - timeout in ticks
802 829
  * @return 0 on success, -1 on error
803 830
  */
804
-int dst_blacklist_add_to(unsigned char err_flags,  struct dest_info* si,
805
-						struct sip_msg* msg, ticks_t timeout)
831
+int dst_blacklist_force_add_to(unsigned char err_flags,  struct dest_info* si,
832
+								struct sip_msg* msg, ticks_t timeout)
806 833
 {
807 834
 	struct ip_addr ip;
808 835
 
... ...
@@ -819,12 +846,12 @@ int dst_blacklist_add_to(unsigned char err_flags,  struct dest_info* si,
819 846
 
820 847
 
821 848
 /** add dst to the blacklist, specifying the timeout.
822
- * (like @function dst_blacklist_add_to)= above, but uses 
849
+ * (like @function dst_blacklist_force_add_to)= above, but uses 
823 850
  * (proto, sockaddr_union) instead of struct dest_info)
824 851
  */
825
-int dst_blacklist_su_to(unsigned char err_flags, unsigned char proto,
826
-							union sockaddr_union* dst,
827
-							struct sip_msg* msg, ticks_t timeout)
852
+int dst_blacklist_force_su_to(unsigned char err_flags, unsigned char proto,
853
+								union sockaddr_union* dst,
854
+								struct sip_msg* msg, ticks_t timeout)
828 855
 {
829 856
 	struct ip_addr ip;
830 857
 #ifdef DST_BLACKLIST_HOOKS
... ...
@@ -1204,5 +1231,14 @@ int blst_max_mem_fixup(void *handle, str *gname, str *name, void **val)
1204 1231
 	return 0;
1205 1232
 }
1206 1233
 
1234
+
1235
+
1236
+/** re-inint per child blst_proto_ign_mask array. */
1237
+void blst_reinit_ign_masks(str* gname, str* name)
1238
+{
1239
+	blst_init_ign_masks();
1240
+}
1241
+
1242
+
1207 1243
 #endif /* USE_DST_BLACKLIST */
1208 1244
 
... ...
@@ -20,9 +20,8 @@
20 20
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 21
  */
22 22
 
23
-/**
23
+/** SIP-router core :: Destination blacklists.
24 24
  * @file
25
- * @brief SIP-router core :: Destination blacklists
26 25
  * @ingroup core
27 26
  * Module: @ref core
28 27
  */
... ...
@@ -31,6 +30,8 @@
31 30
  * --------
32 31
  *  2006-07-29  created by andrei
33 32
  *  2007-07-30  dst blacklist measurements added (Gergo)
33
+ *  2009-12-22  blacklist ignore mask support and dst_blacklist_{add,su}
34
+ *               switched to macros (andrei)
34 35
  */
35 36
 
36 37
 #ifndef dst_black_list_h
... ...
@@ -67,6 +68,9 @@
67 68
 #define DST_BLACKLIST_ADD_CB 1
68 69
 #define DST_BLACKLIST_SEARCH_CB 2
69 70
 
71
+
72
+extern unsigned blst_proto_imask[PROTO_LAST+1];
73
+
70 74
 #ifdef DST_BLACKLIST_HOOKS
71 75
 struct blacklist_hook{
72 76
 	/* WARNING: msg might be NULL, and it might point to shared memory
... ...
@@ -89,41 +93,127 @@ int init_dst_blacklist_stats(int iproc_num);
89 93
 void destroy_dst_blacklist();
90 94
 
91 95
 
92
-/** @brief like dst_blacklist_add, but the timeout can be also set */
93
-int dst_blacklist_add_to(unsigned char err_flags, struct dest_info* si,
94
-						struct sip_msg* msg, ticks_t timeout);
95
-/** @brief like above, but using a differnt way of passing the target */
96
-int dst_blacklist_su_to(unsigned char err_flags, unsigned char proto,
97
-							union sockaddr_union* dst,
98
-							struct sip_msg* msg, ticks_t timeout);
96
+/** force add to the blacklist.
97
+ * like @function dst_blacklist_add_to, but no ignore mask or
98
+ * blacklist enabled checks are made.
99
+ * @see dst_blacklist_add_to for the parameters and return value.
100
+ */
101
+int dst_blacklist_force_add_to(unsigned char err_flags, struct dest_info* si,
102
+								struct sip_msg* msg, ticks_t timeout);
99 103
 
100
-/** @brief adds a dst to the blacklist with default timeout.
101
- * @see dst_blacklist_add_to for more details.
104
+/** force add to the blacklist, long version.
105
+ * like @function dst_blacklist_su_to, but no ignore mask or
106
+ * blacklist enabled checks are made.
107
+ * @see dst_blacklist_su_to for the parameters and return value.
102 108
  */
103
-#define dst_blacklist_add(err_flags, si, msg) \
104
-	dst_blacklist_add_to((err_flags), (si), (msg), \
105
-		S_TO_TICKS(cfg_get(core, core_cfg, blst_timeout)))
109
+int dst_blacklist_force_su_to(	unsigned char err_flags,
110
+								unsigned char proto,
111
+								union sockaddr_union* dst,
112
+								struct sip_msg* msg,
113
+								ticks_t timeout);
114
+
115
+
116
+/** checks if blacklist should be used.
117
+  * @param  err_flags - blacklist reason
118
+  * @param si - filled dest_info structure pointer.
119
+  * @return 1 if blacklist is enabled (core_cfg) and the event/error
120
+  *           is not in the ignore list.
121
+  *         0 otherwise
122
+  */
123
+#define should_blacklist(err_flags, si) \
124
+	(cfg_get(core, core_cfg, use_dst_blacklist) && \
125
+		((err_flags) & ~blst_proto_imask[(unsigned)((si)->proto)] & \
126
+		 			   ~(si)->send_flags.blst_imask ))
127
+
128
+
129
+/** checks if blacklist should be used, long version.
130
+  * @param  err_flags - blacklist reason
131
+  * @param snd_flags - snd_flags pointer, can be 0.
132
+  * @param proto - protocol, can be 0 (PROTO_NONE).
133
+  * @param si  - sockaddr_union pointer, can be 0.
134
+  * @return 1 if blacklist is enabled (core_cfg) and the event/error
135
+  *           is not in the ignore list.
136
+  *         0 otherwise
137
+  */
138
+#define should_blacklist_su(err_flags, snd_flags, proto, su) \
139
+	(cfg_get(core, core_cfg, use_dst_blacklist) && \
140
+		((err_flags) & ~blst_proto_imask[(unsigned)(proto)] & \
141
+		 			~((snd_flags)?((snd_flags_t*)(snd_flags))->blst_imask:0)))
142
+
143
+
144
+/** adds a dst to the blacklist.
145
+ *
146
+ * @param  err_flags - blacklist reason
147
+ * @param si  - dest_info structure (dst).
148
+ * @param msg - sip msg struct. pointer if known, 0 otherwise.
149
+ * @param timeout - timeout in ticks.
150
+ * @return >=0 on success, -1 on error.
151
+ */
152
+#define dst_blacklist_add_to(err_flags, si, msg, timeout) \
153
+	(should_blacklist(err_flags, si)? \
154
+		dst_blacklist_force_add_to((err_flags), (si), (msg), (timeout))\
155
+		: 0)
156
+
157
+
158
+/** adds a dst to the blacklist, long version.
159
+ * Similar to dst_blacklist_add_to, but uses "unpacked" parameters.
160
+ * @param  err_flags - blacklist reason
161
+ * @param proto - protocol.
162
+ * @param dst  - sockaddr_union pointer.
163
+ * @param snd_flags - snd_flags pointer, can be 0.
164
+ * @param msg - sip msg struct. pointer if known, 0 otherwise.
165
+ * @param timeout - timeout in ticks.
166
+ * @return >=0 on success, -1 on error.
167
+ */
168
+#define dst_blacklist_su_to(err_flags, proto, dst, snd_flags, msg, timeout) \
169
+	(should_blacklist_su(err_flags, snd_flags, proto, dst) ? \
170
+		dst_blacklist_force_su_to((err_flags), (proto), (dst), (msg), \
171
+									(timeout))\
172
+		: 0)
173
+
106 174
 
107
-/** @brief adds a dst to the blacklist with default timeout.
108
- * @see dst_blacklist_su_to for more details.
175
+/** adds a dst to the blacklist with default timeout.
176
+ *
177
+ * @param  err_flags - blacklist reason
178
+ * @param si  - dest_info structure (dst).
179
+ * @param msg - sip msg struct. pointer if known, 0 otherwise.
180
+ * @return >=0 on success, -1 on error.
181
+ * @see dst_blacklist_add_to.
109 182
  */
110
-#define dst_blacklist_su(err_flags, proto, dst, msg) \
111
-	dst_blacklist_su_to((err_flags), (proto), (dst), (msg), \
112
-		S_TO_TICKS(cfg_get(core, core_cfg, blst_timeout)))
183
+#define dst_blacklist_add(err_flags, si, msg) \
184
+	dst_blacklist_add_to(err_flags, si, msg, \
185
+							S_TO_TICKS(cfg_get(core, core_cfg, blst_timeout)))
186
+
187
+
188
+/** adds a dst to the blacklist with default timeout, long version.
189
+ * Similar to dst_blacklist_add_to, but uses "unpacked" parameters.
190
+ * @param  err_flags - blacklist reason
191
+ * @param proto - protocol.
192
+ * @param dst  - sockaddr_union pointer.
193
+ * @param snd_flags - snd_flags pointer, can be 0.
194
+ * @param msg - sip msg struct. pointer if known, 0 otherwise.
195
+ * @return >=0 on success, -1 on error.
196
+ * @see dst_blacklist_su_to.
197
+ */
198
+#define dst_blacklist_su(err_flags, proto, dst, snd_flags, msg) \
199
+	dst_blacklist_su_to(err_flags, proto, dst, snd_flags, msg, \
200
+							S_TO_TICKS(cfg_get(core, core_cfg, blst_timeout)))
113 201
 
114 202
 int dst_is_blacklisted(struct dest_info* si, struct sip_msg* msg);
115 203
 
116
-/** @brief  delete an entry from the blacklist */
204
+/** delete an entry from the blacklist. */
117 205
 int dst_blacklist_del(struct dest_info* si, struct sip_msg* msg);
118 206
 
119
-/** @brief deletes all the entries from the blacklist except the permanent ones
207
+/** deletes all the entries from the blacklist except the permanent ones.
120 208
  * (which are marked with BLST_PERMANENT)
121 209
  */
122 210
 void dst_blst_flush(void);
123 211
 
124 212
 int use_dst_blacklist_fixup(void *handle, str *gname, str *name, void **val);
125 213
 
126
-/** @brief KByte to Byte conversion */
214
+/** KByte to Byte conversion. */
127 215
 int blst_max_mem_fixup(void *handle, str *gname, str *name, void **val);
128 216
 
217
+void blst_reinit_ign_masks(str* gname, str* name);
218
+
129 219
 #endif
... ...
@@ -603,8 +603,7 @@ int forward_request(struct sip_msg* msg, str* dst, unsigned short port,
603 603
 		if (msg_send(send_info, buf, len)<0){
604 604
 			ret=ser_error=E_SEND;
605 605
 #ifdef USE_DST_BLACKLIST
606
-			if (cfg_get(core, core_cfg, use_dst_blacklist))
607
-				dst_blacklist_add(BLST_ERR_SEND, send_info, msg);
606
+			dst_blacklist_add(BLST_ERR_SEND, send_info, msg);
608 607
 #endif
609 608
 #ifdef USE_DNS_FAILOVER
610 609
 			continue; /* try another ip */
... ...
@@ -766,7 +765,7 @@ int forward_reply(struct sip_msg* msg)
766 765
 	}
767 766
 
768 767
 	dst.proto=msg->via2->proto;
769
-	dst.send_flags=msg->fwd_send_flags | msg->rpl_send_flags;
768
+	SND_FLAGS_OR(&dst.send_flags, &msg->fwd_send_flags, &msg->rpl_send_flags);
770 769
 	if (update_sock_struct_from_via( &dst.to, msg, msg->via2 )==-1) goto error;
771 770
 #ifdef USE_COMP
772 771
 	dst.comp=msg->via2->comp_no;
... ...
@@ -158,7 +158,7 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
158 158
 			goto error;
159 159
 		}else{
160 160
 			from=0;
161
-			if (unlikely((dst->send_flags & SND_F_FORCE_SOCKET) &&
161
+			if (unlikely((dst->send_flags.f & SND_F_FORCE_SOCKET) &&
162 162
 						dst->send_sock)) {
163 163
 				local_addr=dst->send_sock->su;
164 164
 				su_setport(&local_addr, 0); /* any local port will do */
... ...
@@ -180,7 +180,7 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
180 180
 			goto error;
181 181
 		}else{
182 182
 			from=0;
183
-			if (unlikely((dst->send_flags & SND_F_FORCE_SOCKET) &&
183
+			if (unlikely((dst->send_flags.f & SND_F_FORCE_SOCKET) &&
184 184
 						dst->send_sock)) {
185 185
 				local_addr=dst->send_sock->su;
186 186
 				su_setport(&local_addr, 0); /* any local port will do */
... ...
@@ -142,7 +142,31 @@ struct receive_info{
142 142
 #define SND_F_CON_CLOSE			2 /* close the connection after sending */
143 143
 #define SND_F_FORCE_SOCKET		4 /* send socket in dst is forced */
144 144
 
145
-typedef unsigned char  snd_flags_t;
145
+struct snd_flags {
146
+	unsigned char f;          /* snd flags */
147
+	unsigned char blst_imask; /* blacklist ignore mask */
148
+};
149
+
150
+
151
+typedef struct snd_flags  snd_flags_t;
152
+
153
+#define SND_FLAGS_INIT(sflags) \
154
+	do{ \
155
+		(sflags)->f=0; \
156
+		(sflags)->blst_imask=0; \
157
+	}while(0)
158
+
159
+#define SND_FLAGS_OR(dst, src1, src2) \
160
+	do{ \
161
+		(dst)->f = (src1)->f | (src2)->f; \
162
+		(dst)->blst_imask = (src1)->blst_imask | (src2)->blst_imask; \
163
+	}while(0)
164
+
165
+#define SND_FLAGS_AND(dst, src1, src2) \
166
+	do{ \
167
+		(dst)->f = (src1)->f & (src2)->f; \
168
+		(dst)->blst_imask = (src1)->blst_imask & (src2)->blst_imask; \
169
+	}while(0)
146 170
 
147 171
 struct dest_info{
148 172
 	struct socket_info* send_sock;
... ...
@@ -757,7 +781,8 @@ inline static void init_dst_from_rcv(struct dest_info* dst,
757 781
 		dst->to=rcv->src_su;
758 782
 		dst->id=rcv->proto_reserved1;
759 783
 		dst->proto=rcv->proto;
760
-		dst->send_flags=0;
784
+		dst->send_flags.f=0;
785
+		dst->send_flags.blst_imask=0;
761 786
 #ifdef USE_COMP
762 787
 		dst->comp=rcv->comp;
763 788
 #endif
... ...
@@ -659,8 +659,10 @@ static int add_uac( struct cell *t, struct sip_msg *request, str *uri,
659 659
 		t->uac[branch].request.dst.send_sock =
660 660
 		get_send_socket( request, &t->uac[branch].request.dst.to,
661 661
 								t->uac[branch].request.dst.proto);
662
-		t->uac[branch].request.dst.send_flags=request?
663
-												request->fwd_send_flags:0;
662
+		if (request)
663
+			t->uac[branch].request.dst.send_flags=request->fwd_send_flags;
664
+		else
665
+			SND_FLAGS_INIT(&t->uac[branch].request.dst.send_flags);
664 666
 		next_hop=0;
665 667
 	}else {
666 668
 		next_hop= next_hop?next_hop:uri;
... ...
@@ -845,7 +847,7 @@ int add_uac_dns_fallback(struct cell *t, struct sip_msg* msg,
845 847
 				 * in the rest of the message, only in the VIA HF (Miklos) */
846 848
 				ret=add_uac_from_buf(t,  msg, &old_uac->uri,
847 849
 							&old_uac->path,
848
-							 (old_uac->request.dst.send_flags &
850
+							 (old_uac->request.dst.send_flags.f &
849 851
 								SND_F_FORCE_SOCKET)?
850 852
 									old_uac->request.dst.send_sock:0,
851 853
 							old_uac->request.dst.send_flags,
... ...
@@ -858,7 +860,7 @@ int add_uac_dns_fallback(struct cell *t, struct sip_msg* msg,
858 860
 				 *  must be changed and the send_socket might be different =>
859 861
 				 *  re-create the whole uac */
860 862
 				ret=add_uac(t,  msg, &old_uac->uri, 0, &old_uac->path, 0,
861
-							 (old_uac->request.dst.send_flags &
863
+							 (old_uac->request.dst.send_flags.f &
862 864
 								SND_F_FORCE_SOCKET)?
863 865
 									old_uac->request.dst.send_sock:0,
864 866
 							old_uac->request.dst.send_flags,
... ...
@@ -883,6 +885,7 @@ int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel,
883 885
 	int ret;
884 886
 	char *shbuf;
885 887
 	unsigned int len;
888
+	snd_flags_t snd_flags;
886 889
 
887 890
 	ret=-1;
888 891
 	if (t_cancel->uac[branch].request.buffer) {
... ...
@@ -928,12 +931,13 @@ int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel,
928 931
 			cancel_msg->first_line.u.request.method.len+1;
929 932
 		t_cancel->uac[branch].uri.len=t_invite->uac[branch].uri.len;
930 933
 	} else {
934
+		SND_FLAGS_INIT(&snd_flags);
931 935
 		/* buffer is constructed from the received CANCEL with lumps applied */
932 936
 		/*  t_cancel...request.dst is already filled (see above) */
933 937
 		if (unlikely((ret=prepare_new_uac( t_cancel, cancel_msg, branch,
934 938
 									&t_invite->uac[branch].uri,
935 939
 									&t_invite->uac[branch].path,
936
-									0, 0, 0, PROTO_NONE, 0)) <0)){
940
+									0, 0, snd_flags, PROTO_NONE, 0)) <0)){
937 941
 			ser_error=ret;
938 942
 			goto error;
939 943
 		}
... ...
@@ -1215,8 +1219,7 @@ int t_send_branch( struct cell *t, int branch, struct sip_msg* p_msg ,
1215 1219
 							ip_addr2a(&ip), su_getport(&uac->request.dst.to),
1216 1220
 							uac->request.dst.proto);
1217 1221
 #ifdef USE_DST_BLACKLIST
1218
-		if (cfg_get(core, core_cfg, use_dst_blacklist))
1219
-			dst_blacklist_add(BLST_ERR_SEND, &uac->request.dst, p_msg);
1222
+		dst_blacklist_add(BLST_ERR_SEND, &uac->request.dst, p_msg);
1220 1223
 #endif
1221 1224
 #ifdef USE_DNS_FAILOVER
1222 1225
 		/* if the destination resolves to more ips, add another
... ...
@@ -1651,7 +1651,8 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
1651 1651
 				}
1652 1652
 				/* update send_flags with possible additions from the
1653 1653
 				   reply route */
1654
-				uas_rb->dst.send_flags|=relayed_msg->rpl_send_flags;
1654
+				SND_FLAGS_OR(&uas_rb->dst.send_flags, &uas_rb->dst.send_flags,
1655
+								&relayed_msg->rpl_send_flags);
1655 1656
 			}
1656 1657
 		}
1657 1658
 		update_reply_stats( relayed_code );
... ...
@@ -1885,7 +1886,6 @@ int reply_received( struct sip_msg  *p_msg )
1885 1886
 #endif
1886 1887
 #ifdef USE_DST_BLACKLIST
1887 1888
 	int blst_503_timeout;
1888
-	struct dest_info src;
1889 1889
 	struct hdr_field* hf;
1890 1890
 #endif
1891 1891
 #ifdef TMCB_ONSEND
... ...
@@ -2014,6 +2014,10 @@ int reply_received( struct sip_msg  *p_msg )
2014 2014
 			switch_rb_retr_to_t2(&uac->request);
2015 2015
 		}
2016 2016
 	}
2017
+	/* pre-set the ignore BLST_503 flag in the message, if the
2018
+	   corresponding branch had it set on send */
2019
+	p_msg->fwd_send_flags.blst_imask|=
2020
+		uac->request.dst.send_flags.blst_imask & BLST_503;
2017 2021
 	/* processing of on_reply block */
2018 2022
 	if (t->on_reply) {
2019 2023
 		set_route_type(ONREPLY_ROUTE);
... ...
@@ -2062,10 +2066,13 @@ int reply_received( struct sip_msg  *p_msg )
2062 2066
 	}
2063 2067
 #ifdef USE_DST_BLACKLIST
2064 2068
 		/* add temporary to the blacklist the source of a 503 reply */
2065
-		if (cfg_get(tm, tm_cfg, tm_blst_503)
2066
-			&& cfg_get(core, core_cfg, use_dst_blacklist)
2067
-			&& (msg_status==503)
2068
-		){
2069
+		if (	(msg_status==503) &&
2070
+				cfg_get(tm, tm_cfg, tm_blst_503) &&
2071
+				/* check if the request sent on the branch had the the
2072
+				   blst 503 ignore flags set or it was set in the onreply_r*/
2073
+				should_blacklist_su(BLST_503, &p_msg->fwd_send_flags,
2074
+										p_msg->rcv.proto, &p_msg->rcv.src_su)
2075
+			){
2069 2076
 			blst_503_timeout=cfg_get(tm, tm_cfg, tm_blst_503_default);
2070 2077
 			if ((parse_headers(p_msg, HDR_RETRY_AFTER_F, 0)==0) && 
2071 2078
 				(p_msg->parsed_flag & HDR_RETRY_AFTER_F)){
... ...
@@ -2081,12 +2088,9 @@ int reply_received( struct sip_msg  *p_msg )
2081 2088
 					}
2082 2089
 			}
2083 2090
 			if (blst_503_timeout){
2084
-				src.send_sock=0;
2085
-				src.to=p_msg->rcv.src_su;
2086
-				src.id=p_msg->rcv.proto_reserved1;
2087
-				src.proto=p_msg->rcv.proto;
2088
-				dst_blacklist_add_to(BLST_503, &src,  p_msg, 
2089
-									S_TO_TICKS(blst_503_timeout));
2091
+				dst_blacklist_force_su_to(BLST_503, p_msg->rcv.proto,
2092
+											&p_msg->rcv.src_su, p_msg,
2093
+											S_TO_TICKS(blst_503_timeout));
2090 2094
 			}
2091 2095
 		}
2092 2096
 #endif /* USE_DST_BLACKLIST */
... ...
@@ -478,13 +478,13 @@ inline static void final_response_handler(	struct retr_buf* r_buf,
478 478
 	){
479 479
 		/* no reply received */
480 480
 #ifdef USE_DST_BLACKLIST
481
-		if (cfg_get(core, core_cfg, use_dst_blacklist)
482
-        		&& r_buf->my_T
481
+		if (r_buf->my_T
483 482
 			&& r_buf->my_T->uas.request
484
-			&& (r_buf->my_T->uas.request->REQ_METHOD & cfg_get(tm, tm_cfg, tm_blst_methods_add))
483
+			&& (r_buf->my_T->uas.request->REQ_METHOD &
484
+					cfg_get(tm, tm_cfg, tm_blst_methods_add))
485 485
 		)
486 486
 			dst_blacklist_add( BLST_ERR_TIMEOUT, &r_buf->dst,
487
-						r_buf->my_T->uas.request);
487
+								r_buf->my_T->uas.request);
488 488
 #endif
489 489
 #ifdef USE_DNS_FAILOVER
490 490
 		/* if this is an invite, the destination resolves to more ips, and
... ...
@@ -215,6 +215,7 @@ static inline int t_uac_prepare(uac_req_t *uac_r,
215 215
 	int sflag_bk;
216 216
 	int backup_route_type;
217 217
 #endif
218
+	snd_flags_t snd_flags;
218 219
 
219 220
 	ret=-1;
220 221
 	hi=0; /* make gcc happy */
... ...
@@ -239,10 +240,11 @@ static inline int t_uac_prepare(uac_req_t *uac_r,
239 240
 			uac_r->dialog->hooks.next_hop->s);
240 241
 	/* new message => take the dialog send_socket if set, or the default
241 242
 	  send_socket if not*/
243
+	SND_FLAGS_INIT(&snd_flags);
242 244
 #ifdef USE_DNS_FAILOVER
243 245
 	if (cfg_get(core, core_cfg, use_dns_failover)){
244 246
 		dns_srv_handle_init(&dns_h);
245
-		if ((uri2dst2(&dns_h, &dst, uac_r->dialog->send_sock, 0,
247
+		if ((uri2dst2(&dns_h, &dst, uac_r->dialog->send_sock, snd_flags,
246 248
 							uac_r->dialog->hooks.next_hop, PROTO_NONE)==0)
247 249
 				|| (dst.send_sock==0)){
248 250
 			dns_srv_handle_put(&dns_h);
... ...
@@ -253,7 +255,7 @@ static inline int t_uac_prepare(uac_req_t *uac_r,
253 255
 		}
254 256
 		dns_srv_handle_put(&dns_h); /* not needed anymore */
255 257
 	}else{
256
-		if ((uri2dst2(0, &dst, uac_r->dialog->send_sock, 0,
258
+		if ((uri2dst2(0, &dst, uac_r->dialog->send_sock, snd_flags,
257 259
 						uac_r->dialog->hooks.next_hop, PROTO_NONE)==0) ||
258 260
 				(dst.send_sock==0)){
259 261
 			ser_error = E_NO_SOCKET;
... ...
@@ -263,7 +265,7 @@ static inline int t_uac_prepare(uac_req_t *uac_r,
263 265
 		}
264 266
 	}
265 267
 #else /* USE_DNS_FAILOVER */
266
-	if ((uri2dst2(&dst, uac_r->dialog->send_sock, 0,
268
+	if ((uri2dst2(&dst, uac_r->dialog->send_sock, snd_flags,
267 269
 					uac_r->dialog->hooks.next_hop, PROTO_NONE)==0) ||
268 270
 			(dst.send_sock==0)){
269 271
 		ser_error = E_NO_SOCKET;
... ...
@@ -356,16 +356,24 @@ inline static struct dest_info *uri2dst(struct dns_srv_handle* dns_h,
356 356
 										struct sip_msg *msg, str *uri, 
357 357
 											int proto )
358 358
 {
359
-	return uri2dst2(dns_h, dst, msg?msg->force_send_socket:0,
360
-						msg?msg->fwd_send_flags:0, uri, proto);
359
+	snd_flags_t sflags;
360
+	if (msg)
361
+		return uri2dst2(dns_h, dst, msg->force_send_socket,
362
+							msg->fwd_send_flags, uri, proto);
363
+	SND_FLAGS_INIT(&sflags);
364
+	return uri2dst2(dns_h, dst, 0, sflags, uri, proto);
361 365
 }
362 366
 #else
363 367
 inline static struct dest_info *uri2dst(struct dest_info* dst,
364 368
 										struct sip_msg *msg, str *uri, 
365 369
 											int proto )
366 370
 {
367
-	return uri2dst2(dst, msg?msg->force_send_socket:0,
368
-						msg?msg->fwd_send_flags:0, uri, proto);
371
+	snd_flags_t sflags;
372
+	if (msg)
373
+		return uri2dst2(dst, msg->force_send_socket, msg->fwd_send_flags,
374
+						uri, proto);
375
+	SND_FLAGS_INIT(&sflags);
376
+	return uri2dst2(dst, 0, sflags, uri, proto);
369 377
 }
370 378
 #endif /* USE_DNS_FAILOVER */
371 379
 
... ...
@@ -16,6 +16,11 @@ Andrei Pelinescu-Onciul
16 16
         1.2.2. blst_add_retry_after(min, max)
17 17
         1.2.3. blst_del()
18 18
         1.2.4. blst_is_blacklisted()
19
+        1.2.5. blst_set_ignore() blst_set_ignore(flags)
20
+                blst_rpl_set_ignore() blst_rpl_set_ignore(flags)
21
+
22
+        1.2.6. blst_clear_ignore() blst_clear_ignore(flags)
23
+                blst_rpl_clear_ignore() blst_rpl_clear_ignore(flags)
19 24
 
20 25
 1.1. Overview
21 26
 
... ...
@@ -80,3 +85,45 @@ if (msg_status==503){ # blacklist 503 source for Retry-After seconds
80 85
         drop;
81 86
    }
82 87
 ...
88
+
89
+1.2.5.  blst_set_ignore() blst_set_ignore(flags) blst_rpl_set_ignore()
90
+blst_rpl_set_ignore(flags)
91
+
92
+   Set errors that will not be taken into account when deciding whether or
93
+   not to blacklist a destination for the current message or a local reply
94
+   to the current message.
95
+
96
+   blst_set_ignore(..) works for forwarding the current message and
97
+   blst_rpl_set_ignore(...) works for local replies to the current
98
+   message.
99
+
100
+   The variants with no parameters will ignore everything (equivalent with
101
+   passing 0xff).
102
+
103
+   The following flags are defined:
104
+     * 0x02 - generic send error (send denied/ failed).
105
+     * 0x04 - connect failed (TCP, TLS or SCTP).
106
+     * 0x08 - ICMP error (not currently used).
107
+     * 0x10 - SIP transaction timeout.
108
+     * 0x20 - 503 reply (statefull mode only). For more details see
109
+       tmblst_503.
110
+
111
+Note
112
+
113
+   TCP and TLS send and connect errors are handled per connection and not
114
+   per message. The connection blacklist ignore flags are inherithed from
115
+   the message that caused the connection establishment.
116
+
117
+   Example 5. blst_set_ignore usage
118
+    blst_set_ignore(6); # ignore send and connect errors
119
+
120
+1.2.6.  blst_clear_ignore() blst_clear_ignore(flags) blst_rpl_clear_ignore()
121
+blst_rpl_clear_ignore(flags)
122
+
123
+   Clears blacklist ignore flags previously set by the corresponding
124
+   blst_set_ignore(...) or blst_rpl_set_ignore(...) functions.
125
+
126
+   See also blst_set_ignore.
127
+
128
+   Example 6. blst_clear_ignore usage
129
+    blst_clear_ignore(4); # ignore connect errors
... ...
@@ -45,6 +45,10 @@ static int blst_add_f(struct sip_msg*, char*, char*);
45 45
 static int blst_add_retry_after_f(struct sip_msg*, char*, char*);
46 46
 static int blst_del_f(struct sip_msg*, char*, char*);
47 47
 static int blst_is_blacklisted_f(struct sip_msg*, char*, char*);
48
+static int blst_set_ignore_f(struct sip_msg*, char*, char*);
49
+static int blst_clear_ignore_f(struct sip_msg*, char*, char*);
50
+static int blst_rpl_set_ignore_f(struct sip_msg*, char*, char*);
51
+static int blst_rpl_clear_ignore_f(struct sip_msg*, char*, char*);
48 52
 
49 53
 
50 54
 
... ...
@@ -59,6 +63,22 @@ static cmd_export_t cmds[]={
59 63
 			REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|ONSEND_ROUTE},
60 64
 	{"blst_is_blacklisted",   blst_is_blacklisted_f, 0, 0,
61 65
 			REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|ONSEND_ROUTE},
66
+	{"blst_set_ignore",         blst_set_ignore_f,   0,  0,
67
+		REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONSEND_ROUTE},
68
+	{"blst_set_ignore",         blst_set_ignore_f,   1,  fixup_var_int_1,
69
+		REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONSEND_ROUTE},
70
+	{"blst_clear_ignore",         blst_clear_ignore_f,   0,  0,
71
+		REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONSEND_ROUTE},
72
+	{"blst_clear_ignore",         blst_clear_ignore_f,   1,  fixup_var_int_1,
73
+		REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONSEND_ROUTE},
74
+	{"blst_rpl_set_ignore",       blst_rpl_set_ignore_f, 0,  0,
75
+		REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
76
+	{"blst_rpl_set_ignore",      blst_rpl_set_ignore_f,  1,  fixup_var_int_1,
77
+		REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
78
+	{"blst_rpl_clear_ignore",   blst_rpl_clear_ignore_f, 0,  0,
79
+		REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
80
+	{"blst_rpl_clear_ignore",   blst_rpl_clear_ignore_f, 1,  fixup_var_int_1,
81
+		REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
62 82
 	{0,0,0,0,0}
63 83
 };
64 84
 
... ...
@@ -90,16 +110,15 @@ static int blst_add_f(struct sip_msg* msg, char* to, char* foo)
90 110
 		t=0;
91 111
 		if (unlikely( to && (get_int_fparam(&t, msg, (fparam_t*)to)<0)))
92 112
 			return -1;
93
-	
113
+		if (t==0)
114
+			t=cfg_get(core, core_cfg, blst_timeout);
115
+		init_dest_info(&src);
94 116
 		src.send_sock=0;
95 117
 		src.to=msg->rcv.src_su;
96 118
 		src.id=msg->rcv.proto_reserved1;
97 119
 		src.proto=msg->rcv.proto;
98
-		if (t)
99
-			dst_blacklist_add_to(BLST_ADM_PROHIBITED, &src, msg,
120
+		dst_blacklist_force_add_to(BLST_ADM_PROHIBITED, &src, msg,
100 121
 									S_TO_TICKS(t));
101
-		else
102
-			dst_blacklist_add(BLST_ADM_PROHIBITED, &src, msg);
103 122
 		return 1;
104 123
 	}else{
105 124
 		LOG(L_WARN, "WARNING: blst: blst_add: blacklist support disabled\n");
... ...
@@ -130,6 +149,7 @@ static int blst_add_retry_after_f(struct sip_msg* msg, char* min, char* max)
130 149
 			t_max=0;
131 150
 		}
132 151
 	
152
+		init_dest_info(&src);
133 153
 		src.send_sock=0;
134 154
 		src.to=msg->rcv.src_su;
135 155
 		src.id=msg->rcv.proto_reserved1;
... ...
@@ -150,8 +170,8 @@ static int blst_add_retry_after_f(struct sip_msg* msg, char* min, char* max)
150 170
 		t=MAX_unsigned(t, t_min);
151 171
 		t=MIN_unsigned(t, t_max);
152 172
 		if (likely(t))
153
-			dst_blacklist_add_to(BLST_ADM_PROHIBITED, &src, msg,
154
-									S_TO_TICKS(t));
173
+			dst_blacklist_force_add_to(BLST_ADM_PROHIBITED, &src, msg,
174
+										S_TO_TICKS(t));
155 175
 		return 1;
156 176
 	}else{
157 177
 		LOG(L_WARN, "WARNING: blst: blst_add_retry_after:"
... ...
@@ -173,6 +193,7 @@ static int blst_del_f(struct sip_msg* msg, char* foo, char* bar)
173 193
 	
174 194
 	if (likely(cfg_get(core, core_cfg, use_dst_blacklist))){
175 195
 	
196
+		init_dest_info(&src);
176 197
 		src.send_sock=0;
177 198
 		src.to=msg->rcv.src_su;
178 199
 		src.id=msg->rcv.proto_reserved1;
... ...
@@ -197,6 +218,7 @@ static int blst_is_blacklisted_f(struct sip_msg* msg, char* foo, char* bar)
197 218
 	struct dest_info src;
198 219
 	
199 220
 	if (likely(cfg_get(core, core_cfg, use_dst_blacklist))){
221
+		init_dest_info(&src);
200 222
 		src.send_sock=0;
201 223
 		src.to=msg->rcv.src_su;
202 224
 		src.id=msg->rcv.proto_reserved1;
... ...
@@ -213,3 +235,83 @@ static int blst_is_blacklisted_f(struct sip_msg* msg, char* foo, char* bar)
213 235
 #endif /* USE_DST_BLACKLIST */
214 236
 	return -1;
215 237
 }
238
+
239
+
240
+
241
+static int blst_set_ignore_f(struct sip_msg* msg, char* flags, char* foo)
242
+{
243
+#ifdef USE_DST_BLACKLIST
244
+	unsigned char blst_imask;
245
+	int mask;
246
+	
247
+	if (unlikely(flags && (get_int_fparam(&mask, msg, (fparam_t*)flags)<0)))
248
+		return -1;
249
+	blst_imask=flags?mask:0xff;
250
+	msg->fwd_send_flags.blst_imask|=blst_imask;
251
+	return 1;
252
+#else /* USE_DST_BLACKLIST */
253
+	LOG(L_WARN, "WARNING: blst: blst_ignore_req: blacklist support"
254
+				" not compiled-in - no effect -\n");
255
+#endif /* USE_DST_BLACKLIST */
256
+	return 1;
257
+}
258
+
259
+
260
+
261
+static int blst_clear_ignore_f(struct sip_msg* msg, char* flags, char* foo)
262
+{
263
+#ifdef USE_DST_BLACKLIST
264
+	unsigned char blst_imask;
265
+	int mask;
266
+	
267
+	if (unlikely(flags && (get_int_fparam(&mask, msg, (fparam_t*)flags)<0)))
268
+		return -1;
269
+	blst_imask=flags?mask:0xff;
270
+	msg->fwd_send_flags.blst_imask&=~blst_imask;
271
+	return 1;
272
+#else /* USE_DST_BLACKLIST */
273
+	LOG(L_WARN, "WARNING: blst: blst_ignore_req: blacklist support"
274
+				" not compiled-in - no effect -\n");
275
+#endif /* USE_DST_BLACKLIST */
276
+	return 1;
277
+}
278
+
279
+
280
+
281
+static int blst_rpl_set_ignore_f(struct sip_msg* msg, char* flags, char* foo)
282
+{
283
+#ifdef USE_DST_BLACKLIST
284
+	unsigned char blst_imask;
285
+	int mask;
286
+	
287
+	if (unlikely(flags && (get_int_fparam(&mask, msg, (fparam_t*)flags)<0)))
288
+		return -1;
289
+	blst_imask=flags?mask:0xff;
290
+	msg->rpl_send_flags.blst_imask|=blst_imask;
291
+	return 1;
292
+#else /* USE_DST_BLACKLIST */
293
+	LOG(L_WARN, "WARNING: blst: blst_ignore_req: blacklist support"
294
+				" not compiled-in - no effect -\n");
295
+#endif /* USE_DST_BLACKLIST */
296
+	return 1;
297
+}
298
+
299
+
300
+
301
+static int blst_rpl_clear_ignore_f(struct sip_msg* msg, char* flags, char* foo)
302
+{
303
+#ifdef USE_DST_BLACKLIST
304
+	unsigned char blst_imask;
305
+	int mask;
306
+	
307
+	if (unlikely(flags && (get_int_fparam(&mask, msg, (fparam_t*)flags)<0)))
308
+		return -1;
309
+	blst_imask=flags?mask:0xff;
310
+	msg->rpl_send_flags.blst_imask&=~blst_imask;
311
+	return 1;
312
+#else /* USE_DST_BLACKLIST */
313
+	LOG(L_WARN, "WARNING: blst: blst_ignore_req: blacklist support"
314
+				" not compiled-in - no effect -\n");
315
+#endif /* USE_DST_BLACKLIST */
316
+	return 1;
317
+}
... ...
@@ -108,4 +108,84 @@ if (msg_status==503){ # blacklist 503 source for Retry-After seconds
108 108
 	</example>
109 109
     </section>
110 110
 
111
+	<section id="blst_set_ignore">
112
+	<title>
113
+		<function>blst_set_ignore()</function>
114
+		<function>blst_set_ignore(flags)</function>
115
+		<function>blst_rpl_set_ignore()</function>
116
+		<function>blst_rpl_set_ignore(flags)</function>
117
+	</title>
118
+	<para>
119
+		Set errors that will not be taken into account when deciding
120
+		whether or not to blacklist a destination for the current message
121
+		or a local reply to the current message.
122
+	</para>
123
+	<para>
124
+		<function>blst_set_ignore(..)</function> works for forwarding the
125
+		current message and <function>blst_rpl_set_ignore(...)</function>
126
+		works for local replies to the current message.
127
+	</para>
128
+	<para>
129
+		The variants with no parameters will ignore everything (equivalent
130
+		with passing 0xff).
131
+	</para>
132
+	<para>
133
+		The following flags are defined:
134
+		<itemizedlist>
135
+			<listitem>
136
+				<emphasis>0x02</emphasis> - generic send error (send denied/
137
+				 failed).
138
+			</listitem>
139
+			<listitem>
140
+				<emphasis>0x04</emphasis> - connect failed (TCP, TLS or SCTP).
141
+			</listitem>
142
+			<listitem>
143
+				<emphasis>0x08</emphasis> - ICMP error (not currently used).
144
+			</listitem>
145
+			<listitem>
146
+				<emphasis>0x10</emphasis> - SIP transaction timeout.
147
+			</listitem>
148
+			<listitem>
149
+				<emphasis>0x20</emphasis> - 503 reply (statefull mode only).
150
+				For more details see <emphasis>tm</emphasis>
151
+				<varname>blst_503</varname>.
152
+			</listitem>
153
+		</itemizedlist>
154
+	</para>
155
+	<note>
156
+		TCP and TLS send and connect errors are handled per connection and
157
+		not per message. The connection blacklist ignore flags are inherithed
158
+		from the message that caused the connection establishment.
159
+	</note>
160
+	<example>
161
+		<title><function>blst_set_ignore</function> usage</title>
162
+		<programlisting>
163
+    blst_set_ignore(6); # ignore send and connect errors
164
+		</programlisting>
165
+	</example>
166
+	</section>
167
+
168
+	<section id="blst_clear_ignore">
169
+	<title>
170
+		<function>blst_clear_ignore()</function>
171
+		<function>blst_clear_ignore(flags)</function>
172
+		<function>blst_rpl_clear_ignore()</function>
173
+		<function>blst_rpl_clear_ignore(flags)</function>
174
+	</title>
175
+	<para>
176
+		Clears blacklist ignore flags previously set by the corresponding
177
+		<function>blst_set_ignore(...)</function> or
178
+		<function>blst_rpl_set_ignore(...)</function> functions.
179
+	</para>
180
+	<para>
181
+		See also <function>blst_set_ignore</function>.
182
+	</para>
183
+	<example>
184
+		<title><function>blst_clear_ignore</function> usage</title>
185
+	    <programlisting>
186
+    blst_clear_ignore(4); # ignore connect errors
187
+		</programlisting>
188
+	</example>
189
+	</section>
190
+
111 191
 </section>
... ...
@@ -448,9 +448,9 @@ void reset_path_vector(struct sip_msg* msg);
448 448
 	do { \
449 449
 		(msg)->force_send_socket=(fsocket); \
450 450
 		if ((msg)->force_send_socket) \
451
-			(msg)->fwd_send_flags |= SND_F_FORCE_SOCKET; \
451
+			(msg)->fwd_send_flags.f |= SND_F_FORCE_SOCKET; \
452 452
 		else \
453
-			(msg)->fwd_send_flags &= ~SND_F_FORCE_SOCKET; \
453
+			(msg)->fwd_send_flags.f &= ~SND_F_FORCE_SOCKET; \
454 454
 	} while (0)
455 455
 
456 456
 /** reset a previously forced send socket. */
... ...
@@ -2133,13 +2133,12 @@ static int sctp_handle_send_failed(struct socket_info* si,
2133 2133
 		ret=sctp_msg_send_ext(&dst, data, data_len, &sinfo);
2134 2134
 	}
2135 2135
 #ifdef USE_DST_BLACKLIST
2136
-	 else if (cfg_get(core, core_cfg, use_dst_blacklist) &&
2137
-					cfg_get(sctp, sctp_cfg, send_retries)) {
2136
+	 else if (cfg_get(sctp, sctp_cfg, send_retries)) {
2138 2137
 		/* blacklist only if send_retries is on, if off we blacklist
2139 2138
 		   from SCTP_ASSOC_CHANGE: SCTP_COMM_LOST/SCTP_CANT_STR_ASSOC
2140 2139
 		   which is better (because we can tell connect errors from send
2141 2140
 		   errors and we blacklist a failed dst only once) */
2142
-		dst_blacklist_su(BLST_ERR_SEND, PROTO_SCTP, su, 0);
2141
+		dst_blacklist_su(BLST_ERR_SEND, PROTO_SCTP, su, 0, 0);
2143 2142
 	}
2144 2143
 #endif /* USE_DST_BLACKLIST */
2145 2144
 	
... ...
@@ -2220,9 +2219,8 @@ again:
2220 2219
 #ifdef USE_DST_BLACKLIST
2221 2220
 			/* blacklist only if send_retries is turned off (if on we don't
2222 2221
 			   know here if we did retry or we are at the first error) */
2223
-			if (cfg_get(core, core_cfg, use_dst_blacklist) &&
2224
-					(cfg_get(sctp, sctp_cfg, send_retries)==0))
2225
-						dst_blacklist_su(BLST_ERR_SEND, PROTO_SCTP, su, 0);
2222
+			if (cfg_get(sctp, sctp_cfg, send_retries)==0)
2223
+						dst_blacklist_su(BLST_ERR_SEND, PROTO_SCTP, su, 0, 0);
2226 2224
 #endif /* USE_DST_BLACKLIST */
2227 2225
 			/* no break */
2228 2226
 			goto comm_lost_cont;	/* do not increment counters for
... ...
@@ -2254,9 +2252,8 @@ comm_lost_cont:
2254 2252
 #ifdef USE_DST_BLACKLIST
2255 2253
 			/* blacklist only if send_retries is turned off (if on we don't 
2256 2254
 			   know here if we did retry or we are at the first error) */
2257
-			if (cfg_get(core, core_cfg, use_dst_blacklist) &&
2258
-					(cfg_get(sctp, sctp_cfg, send_retries)==0))
2259
-						dst_blacklist_su(BLST_ERR_CONNECT, PROTO_SCTP, su, 0);
2255
+			if (cfg_get(sctp, sctp_cfg, send_retries)==0)
2256
+					dst_blacklist_su(BLST_ERR_CONNECT, PROTO_SCTP, su, 0, 0);
2260 2257
 #endif /* USE_DST_BLACKLIST */
2261 2258
 			break;
2262 2259
 		default:
... ...
@@ -172,7 +172,7 @@ struct tcp_connection{
172 172
 	atomic_t refcnt;
173 173
 	enum sip_protos type; /* PROTO_TCP or a protocol over it, e.g. TLS */
174 174
 	unsigned short flags; /* connection related flags */
175
-	unsigned short send_flags; /* special send flags */
175
+	snd_flags_t send_flags; /* special send flags */
176 176
 	enum tcp_conn_states state; /* connection state */
177 177
 	void* extra_data; /* extra data associated to the connection, 0 for tcp*/
178 178
 	struct timer_ln timer;
... ...
@@ -192,9 +192,10 @@ struct tcp_connection{
192 192
 
193 193
 /* helper macros */
194 194
 
195
-#define tcpconn_set_send_flags(c, snd_flags) ((c)->send_flags|=(snd_flags))
195
+#define tcpconn_set_send_flags(c, snd_flags) \
196
+	SND_FLAGS_OR(&(c)->send_flags, &(c)->send_flags, &(snd_flags))
196 197
 
197
-#define tcpconn_close_after_send(c)	((c)->send_flags & SND_F_CON_CLOSE)
198
+#define tcpconn_close_after_send(c)	((c)->send_flags.f & SND_F_CON_CLOSE)
198 199
 
199 200
 #define TCP_RCV_INFO(c) (&(c)->rcv)
200 201
 
... ...
@@ -484,7 +484,7 @@ error:
484 484
  * if BLOCKING_USE_SELECT and HAVE_SELECT are defined it will internally
485 485
  * use select() instead of poll (bad if fd > FD_SET_SIZE, poll is preferred)
486 486
  */
487
-static int tcp_blocking_connect(int fd, int type,
487
+static int tcp_blocking_connect(int fd, int type, snd_flags_t* send_flags,
488 488
 								const struct sockaddr *servaddr,
489 489
 								socklen_t addrlen)
490 490
 {
... ...
@@ -577,18 +577,16 @@ error_errno:
577 577
 		case ENETUNREACH:
578 578
 		case EHOSTUNREACH:
579 579
 #ifdef USE_DST_BLACKLIST
580
-			if (cfg_get(core, core_cfg, use_dst_blacklist))
581
-				dst_blacklist_su(BLST_ERR_CONNECT, type,
582
-							 (union sockaddr_union*)servaddr, 0);
580
+			dst_blacklist_su(BLST_ERR_CONNECT, type,
581
+							 (union sockaddr_union*)servaddr, send_flags, 0);
583 582
 #endif /* USE_DST_BLACKLIST */
584 583
 			TCP_EV_CONNECT_UNREACHABLE(errno, 0, 0,
585 584
 							(union sockaddr_union*)servaddr, type);
586 585
 			break;
587 586
 		case ETIMEDOUT:
588 587
 #ifdef USE_DST_BLACKLIST
589
-			if (cfg_get(core, core_cfg, use_dst_blacklist))
590
-				dst_blacklist_su(BLST_ERR_CONNECT, type,
591
-								 (union sockaddr_union*)servaddr, 0);
588
+			dst_blacklist_su(BLST_ERR_CONNECT, type,
589
+							 (union sockaddr_union*)servaddr, send_flags, 0);
592 590
 #endif /* USE_DST_BLACKLIST */
593 591
 			TCP_EV_CONNECT_TIMEOUT(errno, 0, 0,
594 592
 							(union sockaddr_union*)servaddr, type);
... ...
@@ -596,9 +594,8 @@ error_errno:
596 594
 		case ECONNREFUSED:
597 595
 		case ECONNRESET:
598 596
 #ifdef USE_DST_BLACKLIST
599
-			if (cfg_get(core, core_cfg, use_dst_blacklist))
600
-				dst_blacklist_su(BLST_ERR_CONNECT, type,
601
-								 (union sockaddr_union*)servaddr, 0);
597
+			dst_blacklist_su(BLST_ERR_CONNECT, type,
598
+							 (union sockaddr_union*)servaddr, send_flags, 0);
602 599
 #endif /* USE_DST_BLACKLIST */
603 600
 			TCP_EV_CONNECT_RST(errno, 0, 0,
604 601
 							(union sockaddr_union*)servaddr, type);
... ...
@@ -618,9 +615,8 @@ error_errno:
618 615
 error_timeout:
619 616
 	/* timeout */
620 617
 #ifdef USE_DST_BLACKLIST
621
-	if (cfg_get(core, core_cfg, use_dst_blacklist))
622
-		dst_blacklist_su(BLST_ERR_CONNECT, type,
623
-							(union sockaddr_union*)servaddr, 0);
618
+	dst_blacklist_su(BLST_ERR_CONNECT, type,
619
+						(union sockaddr_union*)servaddr, send_flags, 0);
624 620
 #endif /* USE_DST_BLACKLIST */
625 621
 	TCP_EV_CONNECT_TIMEOUT(0, 0, 0, (union sockaddr_union*)servaddr, type);
626 622
 	LOG(L_ERR, "ERROR: tcp_blocking_connect %s: timeout %d s elapsed "
... ...
@@ -673,22 +669,16 @@ inline static int _wbufq_add(struct  tcp_connection* c, char* data,
673 669
 		if (q->first && TICKS_LT(q->wr_timeout, t)){
674 670
 			if (unlikely(c->state==S_CONN_CONNECT)){
675 671
 #ifdef USE_DST_BLACKLIST
676
-				if (likely(cfg_get(core, core_cfg, use_dst_blacklist))){
677
-					DBG("blacklisting, state=%d\n", c->state);
678
-					dst_blacklist_su( BLST_ERR_CONNECT, c->rcv.proto,
679
-										&c->rcv.src_su, 0);
680
-				}
672
+				dst_blacklist_su( BLST_ERR_CONNECT, c->rcv.proto,
673
+										&c->rcv.src_su, &c->send_flags, 0);
681 674
 #endif /* USE_DST_BLACKLIST */
682 675
 				TCP_EV_CONNECT_TIMEOUT(0, TCP_LADDR(c), TCP_LPORT(c),
683 676
 											TCP_PSU(c), TCP_PROTO(c));
684 677
 				TCP_STATS_CONNECT_FAILED();
685 678
 			}else{
686 679
 #ifdef USE_DST_BLACKLIST
687
-				if (likely(cfg_get(core, core_cfg, use_dst_blacklist))){
688
-					DBG("blacklisting, state=%d\n", c->state);
689
-					dst_blacklist_su( BLST_ERR_SEND, c->rcv.proto,
690
-										&c->rcv.src_su, 0);
691
-				}
680
+				dst_blacklist_su( BLST_ERR_SEND, c->rcv.proto,
681
+									&c->rcv.src_su, &c->send_flags, 0);
692 682
 #endif /* USE_DST_BLACKLIST */
693 683
 				TCP_EV_SEND_TIMEOUT(0, &c->rcv);
694 684
 				TCP_STATS_SEND_TIMEOUT();
... ...
@@ -872,10 +862,10 @@ inline static int wbufq_run(int fd, struct tcp_connection* c, int* empty)
872 862
 							case ENETUNREACH:
873 863
 							case EHOSTUNREACH: /* not posix for send() */
874 864
 #ifdef USE_DST_BLACKLIST
875
-								if (cfg_get(core, core_cfg, use_dst_blacklist))
876
-									dst_blacklist_su(BLST_ERR_CONNECT,
877
-															c->rcv.proto,
878
-															&c->rcv.src_su, 0);
865
+								dst_blacklist_su(BLST_ERR_CONNECT,
866
+													c->rcv.proto,
867
+													&c->rcv.src_su,
868
+													&c->send_flags, 0);
879 869
 #endif /* USE_DST_BLACKLIST */
880 870
 								TCP_EV_CONNECT_UNREACHABLE(errno, TCP_LADDR(c),
881 871
 													TCP_LPORT(c), TCP_PSU(c),
... ...
@@ -884,10 +874,10 @@ inline static int wbufq_run(int fd, struct tcp_connection* c, int* empty)
884 874
 							case ECONNREFUSED:
885 875
 							case ECONNRESET:
886 876
 #ifdef USE_DST_BLACKLIST
887
-								if (cfg_get(core, core_cfg, use_dst_blacklist))
888
-									dst_blacklist_su(BLST_ERR_CONNECT,
889
-															c->rcv.proto,
890
-															&c->rcv.src_su, 0);
877
+								dst_blacklist_su(BLST_ERR_CONNECT,
878
+													c->rcv.proto,
879
+													&c->rcv.src_su,
880
+													&c->send_flags, 0);
891 881
 #endif /* USE_DST_BLACKLIST */
892 882
 								TCP_EV_CONNECT_RST(0, TCP_LADDR(c),
893 883
 													TCP_LPORT(c), TCP_PSU(c),
... ...
@@ -908,10 +898,10 @@ inline static int wbufq_run(int fd, struct tcp_connection* c, int* empty)
908 898
 							case ENETUNREACH:
909 899
 							case EHOSTUNREACH: /* not posix for send() */
910 900
 #ifdef USE_DST_BLACKLIST
911
-								if (cfg_get(core, core_cfg, use_dst_blacklist))
912
-									dst_blacklist_su(BLST_ERR_SEND,
913
-														c->rcv.proto,
914
-														&c->rcv.src_su, 0);
901
+								dst_blacklist_su(BLST_ERR_SEND,
902
+													c->rcv.proto,
903
+													&c->rcv.src_su,
904
+													&c->send_flags, 0);
915 905
 #endif /* USE_DST_BLACKLIST */
916 906
 								break;
917 907
 						}
... ...
@@ -1090,6 +1080,7 @@ error:
1090 1080
 inline static int tcp_do_connect(	union sockaddr_union* server,
1091 1081
 									union sockaddr_union* from,
1092 1082
 									int type,
1083
+									snd_flags_t* send_flags,
1093 1084
 									union sockaddr_union* res_local_addr,
1094 1085
 									struct socket_info** res_si,
1095 1086
 									enum tcp_conn_states *state
... ...
@@ -1134,23 +1125,23 @@ again:
1134 1125
 					case ENETUNREACH:
1135 1126
 					case EHOSTUNREACH:
1136 1127
 #ifdef USE_DST_BLACKLIST
1137
-						if (cfg_get(core, core_cfg, use_dst_blacklist))
1138
-							dst_blacklist_su(BLST_ERR_CONNECT, type, server,0);
1128
+						dst_blacklist_su(BLST_ERR_CONNECT, type, server,
1129
+											send_flags, 0);
1139 1130
 #endif /* USE_DST_BLACKLIST */
1140 1131
 						TCP_EV_CONNECT_UNREACHABLE(errno, 0, 0, server, type);
1141 1132
 						break;
1142 1133
 					case ETIMEDOUT:
1143 1134
 #ifdef USE_DST_BLACKLIST
1144
-						if (cfg_get(core, core_cfg, use_dst_blacklist))
1145
-							dst_blacklist_su(BLST_ERR_CONNECT, type, server,0);
1135
+						dst_blacklist_su(BLST_ERR_CONNECT, type, server,
1136
+											send_flags, 0);
1146 1137
 #endif /* USE_DST_BLACKLIST */
1147 1138
 						TCP_EV_CONNECT_TIMEOUT(errno, 0, 0, server, type);
1148 1139
 						break;
1149 1140
 					case ECONNREFUSED:
1150 1141
 					case ECONNRESET:
1151 1142
 #ifdef USE_DST_BLACKLIST
1152
-						if (cfg_get(core, core_cfg, use_dst_blacklist))
1153
-							dst_blacklist_su(BLST_ERR_CONNECT, type, server,0);
1143
+						dst_blacklist_su(BLST_ERR_CONNECT, type, server,
1144
+											send_flags, 0);
1154 1145
 #endif /* USE_DST_BLACKLIST */
1155 1146
 						TCP_EV_CONNECT_RST(errno, 0, 0, server, type);
1156 1147
 						break;
... ...
@@ -1169,7 +1160,7 @@ again:
1169 1160
 		}
1170 1161
 	}else{
1171 1162
 #endif /* TCP_ASYNC */
1172
-		if (tcp_blocking_connect(s, type, &server->s,
1163
+		if (tcp_blocking_connect(s, type,  send_flags, &server->s,
1173 1164
 									sockaddru_len(*server))<0){
1174 1165
 			LOG(L_ERR, "ERROR: tcp_do_connect: tcp_blocking_connect %s"
1175 1166
 						" failed\n", su2a(server, sizeof(*server)));
... ...
@@ -1219,9 +1210,9 @@ error:
1219 1210
 
1220 1211
 
1221 1212
 
1222
-struct tcp_connection* tcpconn_connect( union sockaddr_union* server, 
1213
+struct tcp_connection* tcpconn_connect( union sockaddr_union* server,
1223 1214
 										union sockaddr_union* from,
1224
-										int type)
1215
+										int type, snd_flags_t* send_flags)
1225 1216
 {
1226 1217
 	int s;
1227 1218
 	struct socket_info* si;
... ...
@@ -1238,7 +1229,7 @@ struct tcp_connection* tcpconn_connect( union sockaddr_union* server,
1238 1229
 					cfg_get(tcp, tcp_cfg, max_connections));
1239 1230
 		goto error;
1240 1231
 	}
1241
-	s=tcp_do_connect(server, from, type, &my_name, &si, &state);
1232
+	s=tcp_do_connect(server, from, type,  send_flags, &my_name, &si, &state);
1242 1233
 	if (s==-1){
1243 1234
 		LOG(L_ERR, "ERROR: tcp_do_connect %s: failed (%d) %s\n",
1244 1235
 				su2a(server, sizeof(*server)), errno, strerror(errno));
... ...
@@ -1250,6 +1241,7 @@ struct tcp_connection* tcpconn_connect( union sockaddr_union* server,
1250 1241
 				 " socket\n", su2a(server, sizeof(*server)));
1251 1242
 		goto error;
1252 1243
 	}
1244
+	tcpconn_set_send_flags(con, *send_flags);
1253 1245
 	return con;
1254 1246
 	/*FIXME: set sock idx! */
1255 1247
 error:
... ...
@@ -1271,7 +1263,8 @@ int tcpconn_finish_connect( struct tcp_connection* c,
1271 1263
 	struct tcp_conn_alias* a;
1272 1264
 	int new_conn_alias_flags;
1273 1265
 	
1274
-	s=tcp_do_connect(&c->rcv.src_su, from, c->type, &local_addr, &si, &state);
1266
+	s=tcp_do_connect(&c->rcv.src_su, from, c->type, &c->send_flags,
1267
+						&local_addr, &si, &state);
1275 1268
 	if (unlikely(s==-1)){
1276 1269
 		LOG(L_ERR, "ERROR: tcpconn_finish_connect %s: tcp_do_connect for %p"
1277 1270
 					" failed\n", su2a(&c->rcv.src_su, sizeof(c->rcv.src_su)),
... ...
@@ -1787,7 +1780,7 @@ int tcp_send(struct dest_info* dst, union sockaddr_union* from,
1787 1780
 				c=0;
1788 1781
 			}
1789 1782
 			/* check if connect() is disabled */
1790
-			if (unlikely((dst->send_flags & SND_F_FORCE_CON_REUSE) ||
1783
+			if (unlikely((dst->send_flags.f & SND_F_FORCE_CON_REUSE) ||
1791 1784
 							cfg_get(tcp, tcp_cfg, no_connect)))
1792 1785
 				return -1;
1793 1786
 			DBG("tcp_send: no open tcp connection found, opening new one\n");
... ...
@@ -1905,8 +1898,7 @@ int tcp_send(struct dest_info* dst, union sockaddr_union* from,
1905 1898
 						case ENETUNREACH:
1906 1899
 						case EHOSTUNREACH:  /* not posix for send() */
1907 1900
 #ifdef USE_DST_BLACKLIST
1908
-							if (cfg_get(core, core_cfg, use_dst_blacklist))
1909
-								dst_blacklist_add( BLST_ERR_CONNECT, dst, 0);
1901
+							dst_blacklist_add( BLST_ERR_CONNECT, dst, 0);
1910 1902
 #endif /* USE_DST_BLACKLIST */
1911 1903
 							TCP_EV_CONNECT_UNREACHABLE(errno, TCP_LADDR(c),
1912 1904
 									TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
... ...
@@ -1914,8 +1906,7 @@ int tcp_send(struct dest_info* dst, union sockaddr_union* from,
1914 1906
 						case ECONNREFUSED:
1915 1907
 						case ECONNRESET:
1916 1908
 #ifdef USE_DST_BLACKLIST
1917
-							if (cfg_get(core, core_cfg, use_dst_blacklist))
1918
-								dst_blacklist_add( BLST_ERR_CONNECT, dst, 0);
1909
+							dst_blacklist_add( BLST_ERR_CONNECT, dst, 0);
1919 1910
 #endif /* USE_DST_BLACKLIST */
1920 1911
 							TCP_EV_CONNECT_RST(errno, TCP_LADDR(c),
1921 1912
 									TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
... ...
@@ -1934,7 +1925,7 @@ int tcp_send(struct dest_info* dst, union sockaddr_union* from,
1934 1925
 				}
1935 1926
 				LOG(L_INFO, "tcp_send: quick connect for %p\n", c);
1936 1927
 				TCP_STATS_ESTABLISHED(S_CONN_CONNECT);
1937
-				if (unlikely(dst->send_flags & SND_F_CON_CLOSE)){