tm: fix possible uninit. use of cancel_reason
[sip-router] / modules / tm / t_cancel.c
1 /*
2  * $Id$
3  *
4  *
5  * Copyright (C) 2001-2003 FhG Fokus
6  *
7  * This file is part of ser, a free SIP server.
8  *
9  * ser is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version
13  *
14  * For a license to use the ser software under conditions
15  * other than those described here, or to purchase support for this
16  * software, please contact iptel.org by e-mail at the following addresses:
17  *    info@iptel.org
18  *
19  * ser is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License 
25  * along with this program; if not, write to the Free Software 
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27  *
28  * History:
29  * ----------
30  * 2003-04-14  checking if a reply sent before cancel is initiated
31  *             moved here (jiri)
32  * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
33  * 2004-02-13  timer_link.payload removed (bogdan)
34  * 2006-10-10  cancel_uacs  & cancel_branch take more options now (andrei)
35  * 2007-03-15  TMCB_ONSEND hooks added (andrei)
36  * 2007-05-28: cancel_branch() constructs the CANCEL from the
37  *             outgoing INVITE instead of the incomming one.
38  *             (it can be disabled with reparse_invite=0) (Miklos)
39  * 2007-06-04  cancel_branch() can operate in lockless mode (with a lockless
40  *              should_cancel()) (andrei)
41  * 2008-03-07  cancel_branch() takes a new flag: F_CANCEL_B_FORCE_RETR (andrei)
42  * 2008-03-08  e2e_cancel handles non replied branches in 3 different ways,
43  *              selectable by the tm cancel_b_method parameter: fake reply,
44  *              retransmit request and send cancel on branch (andrei)
45  * 2009-07-14  renamed which_cancel() to prepare_to_cancel() for better
46  *              reflecting its purpose
47  *             prepare_to_cancel() takes now an additional skip_branches
48  *              bitmap parameter (andrei)
49  * 2010-02-26  cancel reason (rfc3326) basic support (andrei)
50  */
51
52 #include <stdio.h> /* for FILE* in fifo_uac_cancel */
53 #ifdef EXTRA_DEBUG
54 #include <assert.h>
55 #endif /* EXTRA_DEBUG */
56
57 #include "defs.h"
58 #include "config.h"
59
60 #include "t_funcs.h"
61 #include "../../dprint.h"
62 #include "../../ut.h"
63 #include "t_reply.h"
64 #include "t_cancel.h"
65 #include "t_msgbuilder.h"
66 #include "t_lookup.h" /* for t_lookup_callid in fifo_uac_cancel */
67 #include "t_hooks.h"
68
69
70 /** Prepare to cancel a transaction.
71  * Determine which branches should be canceled and prepare them (internally
72  * mark them as "cancel in progress", see prepare_cancel_branch()).
73  * Can be called without REPLY_LOCK, since prepare_cancel_branch() is atomic 
74  *  now *  -- andrei
75  * WARNING: - has side effects, see prepare_cancel_branch()
76  *          - one _must_ call cancel_uacs(cancel_bm) if *cancel_bm!=0 or
77  *             you'll have some un-cancelable branches (because they remain
78  *             "marked" internally)
79  * @param t - transaction whose branches will be canceled
80  * @param cancel_bm - pointer to a branch bitmap that will be filled with
81 *    the branches that must be canceled (must be passed to cancel_uacs() if
82 *    !=0).
83 *  @param skip - branch bitmap of branches that should not be canceled
84 */
85 void prepare_to_cancel(struct cell *t, branch_bm_t *cancel_bm,
86                                                 branch_bm_t skip_branches)
87 {
88         int i;
89         int branches_no;
90         branch_bm_t mask;
91         
92         *cancel_bm=0;
93         branches_no=t->nr_of_outgoings;
94         mask=~skip_branches;
95         membar_depends(); 
96         for( i=0 ; i<branches_no ; i++ ) {
97                 *cancel_bm |= ((mask & (1<<i)) &&  prepare_cancel_branch(t, i, 1))<<i;
98         }
99 }
100
101
102
103
104 /* cancel branches scheduled for deletion
105  * params: t          - transaction
106  *          cancel_data - structure filled with the cancel bitmap (bitmap with
107  *                       the branches that are supposed to be canceled) and
108  *                       the cancel reason.
109  *          flags     - how_to_cancel flags, see cancel_branch()
110  * returns: bitmap with the still active branches (on fr timer)
111  * WARNING: always fill cancel_data->cancel_bitmap using prepare_to_cancel(),
112  *          supplying values in any other way is a bug*/
113 int cancel_uacs( struct cell *t, struct cancel_info* cancel_data, int flags)
114 {
115         int i;
116         int ret;
117         int r;
118
119         ret=0;
120         /* cancel pending client transactions, if any */
121         for( i=0 ; i<t->nr_of_outgoings ; i++ ) 
122                 if (cancel_data->cancel_bitmap & (1<<i)){
123                         r=cancel_branch(
124                                 t,
125                                 i,
126 #ifdef CANCEL_REASON_SUPPORT
127                                 &cancel_data->reason,
128 #endif /* CANCEL_REASON_SUPPORT */
129                                 flags | ((t->uac[i].request.buffer==NULL)?
130                                         F_CANCEL_B_FAKE_REPLY:0) /* blind UAC? */
131                         );
132                         ret|=(r!=0)<<i;
133                 }
134         return ret;
135 }
136
137 int cancel_all_uacs(struct cell *trans, int how)
138 {
139         struct cancel_info cancel_data;
140         int i,j;
141
142 #ifdef EXTRA_DEBUG
143         assert(trans);
144 #endif
145         DBG("Canceling T@%p [%u:%u]\n", trans, trans->hash_index, trans->label);
146         
147         init_cancel_info(&cancel_data);
148         prepare_to_cancel(trans, &cancel_data.cancel_bitmap, 0);
149          /* tell tm to cancel the call */
150         i=cancel_uacs(trans, &cancel_data, how);
151         
152         if (how & F_CANCEL_UNREF)
153 #ifndef TM_DEL_UNREF
154         /* in case of 'too many' _buggy_ invocations, the ref count (a uint) might 
155          * actually wrap around, possibly leaving the T leaking. */
156 #warning "use of F_CANCEL_UNREF flag is unsafe without defining TM_DEL_UNREF"
157 #endif
158                 UNREF(trans);
159
160         /* count the still active branches */
161         if (! how) {
162                 j=0;
163                 while(i){
164                         j++;
165                         i&=i-1;
166                 }
167                 return j;
168         }
169         return 0;
170 }
171
172
173 /* should be called directly only if one of the condition bellow is true:
174  *  - prepare_cancel_branch or prepare_to_cancel returned true for this branch
175  *  - buffer value was 0 and then set to BUSY in an atomic op.:
176  *     if (atomic_cmpxchg_long(&buffer, 0, BUSY_BUFFER)==0).
177  *
178  * params:  t - transaction
179  *          branch - branch number to be canceled
180  *          reason - cancel reason structure
181  *          flags - howto cancel: 
182  *                   F_CANCEL_B_KILL - will completely stop the 
183  *                     branch (stops the timers), use with care
184  *                   F_CANCEL_B_FAKE_REPLY - will send a fake 487
185  *                      to all branches that haven't received any response
186  *                      (>=100). It assumes the REPLY_LOCK is not held
187  *                      (if it is => deadlock)
188  *                  F_CANCEL_B_FORCE_C - will send a cancel (and create the 
189  *                       corresp. local cancel rb) even if no reply was 
190  *                       received; F_CANCEL_B_FAKE_REPLY will be ignored.
191  *                  F_CANCEL_B_FORCE_RETR - don't stop retransmission if no 
192  *                       reply was received on the branch; incompatible
193  *                       with F_CANCEL_B_FAKE_REPLY, F_CANCEL_B_FORCE_C and
194  *                       F_CANCEL_B_KILL (all of them take precedence) a
195  *                  default: stop only the retransmissions for the branch
196  *                      and leave it to timeout if it doesn't receive any
197  *                      response to the CANCEL
198  * returns: 0 - branch inactive after running cancel_branch() 
199  *          1 - branch still active  (fr_timer)
200  *         -1 - error
201  * WARNING:
202  *          - F_CANCEL_B_KILL should be used only if the transaction is killed
203  *            explicitly afterwards (since it might kill all the timers
204  *            the transaction won't be able to "kill" itself => if not
205  *            explicitly "put_on_wait" it might live forever)
206  *          - F_CANCEL_B_FAKE_REPLY must be used only if the REPLY_LOCK is not
207  *            held
208  *          - checking for buffer==0 under REPLY_LOCK is no enough, an 
209  *           atomic_cmpxhcg or atomic_get_and_set _must_ be used.
210  */
211 int cancel_branch( struct cell *t, int branch,
212         #ifdef CANCEL_REASON_SUPPORT
213                                         struct cancel_reason* reason,
214         #endif /* CANCEL_REASON_SUPPORT */
215                                         int flags )
216 {
217         char *cancel;
218         unsigned int len;
219         struct retr_buf *crb, *irb;
220         int ret;
221         struct cancel_info tmp_cd;
222         void* pcbuf;
223
224         crb=&t->uac[branch].local_cancel;
225         irb=&t->uac[branch].request;
226         irb->flags|=F_RB_CANCELED;
227         ret=1;
228         init_cancel_info(&tmp_cd);
229
230 #       ifdef EXTRA_DEBUG
231         if (crb->buffer!=BUSY_BUFFER) {
232                 LOG(L_CRIT, "ERROR: attempt to rewrite cancel buffer: %p\n",
233                                 crb->buffer);
234                 abort();
235         }
236 #       endif
237
238         if (flags & F_CANCEL_B_KILL){
239                 stop_rb_timers( irb );
240                 ret=0;
241                 if ((t->uac[branch].last_received < 100) &&
242                                 !(flags & F_CANCEL_B_FORCE_C)) {
243                         DBG("DEBUG: cancel_branch: no response ever received: "
244                             "giving up on cancel\n");
245                         /* remove BUSY_BUFFER -- mark cancel buffer as not used */
246                         pcbuf=&crb->buffer; /* workaround for type punning warnings */
247                         atomic_set_long(pcbuf, 0);
248                         if (flags & F_CANCEL_B_FAKE_REPLY){
249                                 LOCK_REPLIES(t);
250                                 if (relay_reply(t, FAKED_REPLY, branch, 487, &tmp_cd, 1) == 
251                                                                                 RPS_ERROR){
252                                         return -1;
253                                 }
254                         }
255                         /* do nothing, hope that the caller will clean up */
256                         return ret;
257                 }
258         }else{
259                 if (t->uac[branch].last_received < 100){
260                         if (!(flags & F_CANCEL_B_FORCE_C)) {
261                                 /* no response received => don't send a cancel on this branch,
262                                  *  just drop it */
263                                 if (!(flags & F_CANCEL_B_FORCE_RETR))
264                                         stop_rb_retr(irb); /* stop retransmissions */
265                                 /* remove BUSY_BUFFER -- mark cancel buffer as not used */
266                                 pcbuf=&crb->buffer; /* workaround for type punning warnings */
267                                 atomic_set_long(pcbuf, 0);
268                                 if (flags & F_CANCEL_B_FAKE_REPLY){
269                                         stop_rb_timers( irb ); /* stop even the fr timer */
270                                         LOCK_REPLIES(t);
271                                         if (relay_reply(t, FAKED_REPLY, branch, 487, &tmp_cd, 1)== 
272                                                                                         RPS_ERROR){
273                                                 return -1;
274                                         }
275                                         return 0; /* should be inactive after the 487 */
276                                 }
277                                 /* do nothing, just wait for the final timeout */
278                                 return 1;
279                         }
280                 }
281                 stop_rb_retr(irb); /* stop retransmissions */
282         }
283
284         if (cfg_get(tm, tm_cfg, reparse_invite)) {
285                 /* build the CANCEL from the INVITE which was sent out */
286                 cancel = build_local_reparse(t, branch, &len, CANCEL, CANCEL_LEN,
287                                                                          &t->to
288         #ifdef CANCEL_REASON_SUPPORT
289                                                                          , reason
290         #endif /* CANCEL_REASON_SUPPORT */
291                                                                          );
292         } else {
293                 /* build the CANCEL from the received INVITE */
294                 cancel = build_local(t, branch, &len, CANCEL, CANCEL_LEN, &t->to
295         #ifdef CANCEL_REASON_SUPPORT
296                                                                 , reason
297         #endif /* CANCEL_REASON_SUPPORT */
298                                                                 );
299         }
300         if (!cancel) {
301                 LOG(L_ERR, "ERROR: attempt to build a CANCEL failed\n");
302                 /* remove BUSY_BUFFER -- mark cancel buffer as not used */
303                 pcbuf=&crb->buffer; /* workaround for type punning warnings */
304                 atomic_set_long(pcbuf, 0);
305                 return -1;
306         }
307         /* install cancel now */
308         crb->dst = irb->dst;
309         crb->branch = branch;
310         /* label it as cancel so that FR timer can better know how to
311            deal with it */
312         crb->activ_type = TYPE_LOCAL_CANCEL;
313         /* be extra carefully and check for bugs (the below if could be replaced
314          *  by an atomic_set((void*)&crb->buffer, cancel) */
315         if (unlikely(atomic_cmpxchg_long((void*)&crb->buffer, (long)BUSY_BUFFER,
316                                                         (long)cancel)!= (long)BUSY_BUFFER)){
317                 BUG("tm: cancel_branch: local_cancel buffer=%p != BUSY_BUFFER"
318                                 " (trying to continue)\n", crb->buffer);
319                 shm_free(cancel);
320                 return -1;
321         }
322         membar_write_atomic_op(); /* cancel retr. can be called from 
323                                                                  reply_received w/o the reply lock held => 
324                                                                  they check for buffer_len to 
325                                                                  see if a valid reply exists */
326         crb->buffer_len = len;
327
328         DBG("DEBUG: cancel_branch: sending cancel...\n");
329 #ifdef TMCB_ONSEND
330         if (SEND_BUFFER( crb )>=0){
331                 if (unlikely (has_tran_tmcbs(t, TMCB_REQUEST_SENT)))
332                         run_onsend_callbacks(TMCB_REQUEST_SENT, crb, 0, 0, TMCB_LOCAL_F);
333         }
334 #else
335         SEND_BUFFER( crb );
336 #endif
337         /*sets and starts the FINAL RESPONSE timer */
338         if (start_retr( crb )!=0)
339                 LOG(L_CRIT, "BUG: cancel_branch: failed to start retransmission"
340                                         " for %p\n", crb);
341         return ret;
342 }
343
344
345 /* fifo command to cancel a pending call (Uli)
346  * Syntax:
347  *
348  * ":uac_cancel:[response file]\n
349  * callid\n
350  * cseq\n
351  */
352 void rpc_cancel(rpc_t* rpc, void* c)
353 {
354         struct cell *trans;
355         static char cseq[128], callid[128];
356         struct cancel_info cancel_data;
357         int i,j;
358
359         str cseq_s;   /* cseq */
360         str callid_s; /* callid */
361
362         cseq_s.s=cseq;
363         callid_s.s=callid;
364         init_cancel_info(&cancel_data);
365
366         if (rpc->scan(c, "SS", &callid_s, &cseq_s) < 2) {
367                 rpc->fault(c, 400, "Callid and CSeq expected as parameters");
368                 return;
369         }
370
371         if( t_lookup_callid(&trans, callid_s, cseq_s) < 0 ) {
372                 DBG("Lookup failed\n");
373                 rpc->fault(c, 400, "Transaction not found");
374                 return;
375         }
376         /*  find the branches that need cancel-ing */
377         prepare_to_cancel(trans, &cancel_data.cancel_bitmap, 0);
378          /* tell tm to cancel the call */
379         DBG("Now calling cancel_uacs\n");
380         i=cancel_uacs(trans, &cancel_data, 0); /* don't fake 487s, 
381                                                                                  just wait for timeout */
382         
383         /* t_lookup_callid REF`d the transaction for us, we must UNREF here! */
384         UNREF(trans);
385         j=0;
386         while(i){
387                 j++;
388                 i&=i-1;
389         }
390         rpc->add(c, "ds", j, "branches remaining (waiting for timeout)");
391 }
392
393
394
395 /* returns <0 on error */
396 int cancel_b_flags_get(unsigned int* f, int m)
397 {
398         int ret;
399         
400         ret=0;
401         switch(m){
402                 case 1:
403                         *f=F_CANCEL_B_FORCE_RETR;
404                         break;
405                 case 0:
406                         *f=F_CANCEL_B_FAKE_REPLY;
407                         break;
408                 case 2:
409                         *f=F_CANCEL_B_FORCE_C;
410                         break;
411                 default:
412                         *f=F_CANCEL_B_FAKE_REPLY;
413                         ret=-1;
414         }
415         return ret;
416 }
417
418
419
420 /* fixup function for the default cancel branch method/flags
421  * (called by the configuration framework) */
422 int cancel_b_flags_fixup(void* handle, str* gname, str* name, void** val)
423 {
424         unsigned int m,f;
425         int ret;
426         
427         m=(unsigned int)(long)(*val);
428         ret=cancel_b_flags_get(&f, m);
429         if (ret<0)
430                 ERR("cancel_b_flags_fixup: invalid value for %.*s; %d\n",
431                                 name->len, name->s, m);
432         *val=(void*)(long)f;
433         return ret;
434 }
435
436
437 /**
438  * This function cancels a previously created local invite
439  * transaction. The cancel parameter should NOT have any via (CANCEL is
440  * hop by hop). returns 0 if error return >0 if OK (returns the LABEL of
441  * the cancel).*/
442 unsigned int t_uac_cancel( str *headers, str *body,
443                 unsigned int cancelled_hashIdx, unsigned int cancelled_label,
444                 transaction_cb cb, void* cbp)
445 {
446         struct cell *t_invite,*cancel_cell;
447         struct retr_buf *cancel,*invite;
448         unsigned int len,ret;
449         char *buf;
450
451         ret=0;
452         if(t_lookup_ident(&t_invite,cancelled_hashIdx,cancelled_label)<0){
453                 LM_ERR("failed to t_lookup_ident hash_idx=%d,"
454                                 "label=%d\n", cancelled_hashIdx,cancelled_label);
455                 return 0;
456         }
457         /* <sanity_checks> */
458         if(! is_local(t_invite))
459         {
460                 LM_ERR("tried to cancel a non-local transaction\n");
461                 goto error3;
462         }
463         if(t_invite->uac[0].last_received < 100)
464         {
465                 LM_WARN("trying to cancel a transaction not in "
466                                         "Proceeding state !\n");
467                 goto error3;
468         }
469         if(t_invite->uac[0].last_received > 200)
470         {
471                 LM_WARN("trying to cancel a completed transaction !\n");
472                 goto error3;
473         }
474         /* </sanity_checks*/
475         /* <build_cell> */
476         if(!(cancel_cell = build_cell(0))){
477                 ret=0;
478                 LM_ERR("no more shm memory!\n");
479                 goto error3;
480         }
481         reset_avps();
482         if(cb && insert_tmcb(&(cancel_cell->tmcb_hl),
483                         TMCB_RESPONSE_IN|TMCB_LOCAL_COMPLETED,cb,cbp,0)!=1){
484                 ret=0;
485                 LM_ERR("short of tmcb shmem !\n");
486                 goto error2;
487         }
488         /* </build_cell> */
489
490         /* <insert_into_hashtable> */
491         cancel_cell->flags |= T_IS_LOCAL_FLAG;
492         cancel_cell->hash_index=t_invite->hash_index;
493
494         LOCK_HASH(cancel_cell->hash_index);
495         insert_into_hash_table_unsafe(cancel_cell,cancel_cell->hash_index);
496         ret=cancel_cell->label;
497         cancel_cell->label=t_invite->label;
498         UNLOCK_HASH(cancel_cell->hash_index);
499         /* </insert_into_hashtable> */
500
501         /* <prepare_cancel> */
502
503         cancel=&cancel_cell->uac[0].request;
504         invite=&t_invite->uac[0].request;
505
506         cancel->dst.to              = invite->dst.to;
507         cancel->dst.send_sock       = invite->dst.send_sock;
508         cancel->dst.proto           = invite->dst.proto;
509         //cancel->dst.proto_reserved1 = invite->dst.proto_reserved1;
510
511         if(!(buf = build_uac_cancel(headers,body,t_invite,0,&len,
512                                         &(cancel->dst)))){
513                 ret=0;
514                 LM_ERR("attempt to build a CANCEL failed\n");
515                 goto error1;
516         }
517         cancel->buffer=buf;
518         cancel->buffer_len=len;
519         cancel_cell->method.s = buf;
520         cancel_cell->method.len = 6 /*c-a-n-c-e-l*/;
521         /* </prepare_cancel> */
522
523         /* <strart_sending> */
524         cancel_cell->nr_of_outgoings++;
525         if (SEND_BUFFER(cancel)==-1) {
526                 ret=0;
527                 LM_ERR("send failed\n");
528                 goto error1;
529         }
530         start_retr(cancel);
531         /* </start_sending> */
532
533         return ret;
534
535 error1:
536         LOCK_HASH(cancel_cell->hash_index);
537         remove_from_hash_table_unsafe(cancel_cell);
538         UNLOCK_HASH(cancel_cell->hash_index);
539 error2:
540         free_cell(cancel_cell);
541 error3:
542         return ret;
543 }
544
545