keepalive: early start of OPTIONS checking
[sip-router] / src / modules / rr / record.c
1 /*
2  * Copyright (C) 2001-2003 FhG Fokus
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21 /*!
22  * \file
23  * \brief Route & Record-Route module, loose routing support
24  * \ingroup rr
25  */
26
27 /*!
28  * \defgroup rr RR :: Route & Record-Route Module
29  * This module contains record routing logic, as described in RFC 3261
30  * (see chapter 16.12 and 12.1.1 - UAS behavior).
31  */
32
33 #include <string.h>
34 #include "../../core/mem/mem.h"
35 #include "../../core/dprint.h"
36 #include "../../core/parser/parse_uri.h"
37 #include "../../core/parser/parse_from.h"
38 #include "../../core/parser/parse_rr.h"
39 #include "../../core/str.h"
40 #include "../../core/data_lump.h"
41 #include "record.h"
42 #include "rr_mod.h"
43 #include "loose.h"
44
45
46 #define RR_PREFIX_SIP "Record-Route: <sip:"
47 #define RR_PREFIX_SIP_LEN (sizeof(RR_PREFIX_SIP)-1)
48
49 #define RR_PREFIX_SIPS "Record-Route: <sips:"
50 #define RR_PREFIX_SIPS_LEN (sizeof(RR_PREFIX_SIPS)-1)
51
52 #define RR_LR ";lr"
53 #define RR_LR_LEN (sizeof(RR_LR)-1)
54
55 #define RR_LR_FULL ";lr=on"
56 #define RR_LR_FULL_LEN (sizeof(RR_LR_FULL)-1)
57
58 #define RR_FROMTAG ";ftag="
59 #define RR_FROMTAG_LEN (sizeof(RR_FROMTAG)-1)
60
61 #define RR_R2 ";r2=on"
62 #define RR_R2_LEN (sizeof(RR_R2)-1)
63
64 #define RR_TERM ">"CRLF
65 #define RR_TERM_LEN (sizeof(RR_TERM)-1)
66
67 #define INBOUND  1      /*!< Insert inbound Record-Route */
68 #define OUTBOUND 0      /*!< Insert outbound Record-Route */
69
70 #define RR_PARAM_BUF_SIZE 512 /*!< buffer for RR parameter */
71
72 extern int rr_ignore_sips;
73 extern int rr_sockname_mode;
74
75 /*!
76  * \brief RR param buffer
77  * \note used for storing RR param which are added before RR insertion
78  */
79 static char rr_param_buf_ptr[RR_PARAM_BUF_SIZE];
80 static str rr_param_buf = {rr_param_buf_ptr,0};
81 static unsigned int rr_param_msg;
82
83 static pv_spec_t *custom_user_avp;              /*!< AVP for custom_user setting */
84
85
86 inline static int rr_is_sips(sip_msg_t *_m)
87 {
88         if(parse_sip_msg_uri(_m)<0)
89                 return 0;
90         if(_m->parsed_uri.type==SIPS_URI_T)
91                 return 1;
92         return 0;
93 }
94
95 void init_custom_user(pv_spec_t *custom_user_avp_p)
96 {
97     custom_user_avp = custom_user_avp_p;
98 }
99
100 /*!
101  * \brief Return the custom_user for a record route
102  * \param req SIP message
103  * \param custom_user to be returned
104  * \return <0 for failure
105  */
106 inline static int get_custom_user(struct sip_msg *req, str *custom_user) {
107         pv_value_t pv_val;
108
109         if (custom_user_avp) {
110                 if ((pv_get_spec_value(req, custom_user_avp, &pv_val) == 0)
111                                 && (pv_val.flags & PV_VAL_STR) && (pv_val.rs.len > 0)) {
112                         custom_user->s = pv_val.rs.s;
113                         custom_user->len = pv_val.rs.len;
114                         return 0;
115                 }
116                 LM_DBG("invalid AVP value, using default user from RURI\n");
117         }
118
119         return -1;
120 }
121
122 /*!
123  * \brief Extract username from the Request URI
124  *
125  * Extract username from the Request URI. First try to look at the original
126  * Request URI and if there is no username use the new Request URI.
127  * \param _m SIP message
128  * \param _user username
129  * \return 0 on success, negative on errors
130  */
131 static inline int get_username(struct sip_msg* _m, str* _user)
132 {
133         struct sip_uri puri;
134
135         /* first try to look at r-uri for a username */
136         if (parse_uri(_m->first_line.u.request.uri.s, _m->first_line.u.request.uri.len, &puri) < 0) {
137                 LM_ERR("failed to parse R-URI\n");
138                 return -1;
139         }
140
141         /* no username in original uri -- hmm; maybe it is a uri
142          * with just host address and username is in a preloaded route,
143          * which is now no rewritten r-uri (assumed rewriteFromRoute
144          * was called somewhere in script's beginning)
145          */
146         if (!puri.user.len && _m->new_uri.s) {
147                 if (parse_uri(_m->new_uri.s, _m->new_uri.len, &puri) < 0) {
148                         LM_ERR("failed to parse new_uri\n");
149                         return -2;
150                 }
151         }
152
153         _user->s = puri.user.s;
154         _user->len = puri.user.len;
155         return 0;
156 }
157
158
159 /*!
160  * \brief Insert RR parameter lump in new allocated private memory
161  * \param before lump list
162  * \param s parameter string
163  * \param l parameter string length
164  * \return pointer to new lump on success, NULL on failure
165  */
166 static inline struct lump *insert_rr_param_lump(struct lump *before,
167                                                 char *s, int l)
168 {
169         struct lump *rrp_l;
170         char *s1;
171
172         /* duplicate data in pkg mem */
173         s1 = (char*)pkg_malloc(l);
174         if (s1==0) {
175                 LM_ERR("no more pkg mem (%d)\n",l);
176                 return 0;
177         }
178         memcpy( s1, s, l);
179
180         /* add lump */
181         rrp_l = insert_new_lump_before( before, s1, l, HDR_RECORDROUTE_T);
182         if (rrp_l==0) {
183                 LM_ERR("failed to add before lump\n");
184                 pkg_free(s1);
185                 return 0;
186         }
187         return rrp_l;
188 }
189
190
191 /*!
192  * \brief Build a Record-Route header field
193  *
194 * Build a Record-Route header field, allocates new private memory for this.
195  * \param _l first lump
196  * \param _l2 second lump
197  * \param user user parameter
198  * \param tag tag parameter
199  * \param params parameter
200  * \param _inbound inbound request
201  * \return 0 on success, negative on failure
202  */
203 static inline int build_rr(struct lump* _l, struct lump* _l2, str* user,
204                                 str *tag, str *params, int _inbound, int _sips)
205 {
206         char* prefix, *suffix, *term, *r2;
207         int suffix_len, prefix_len;
208         char *p;
209         char *rr_prefix;
210         int rr_prefix_len;
211         int rr_lump_type;
212
213         if(_sips==0) {
214                 rr_prefix = RR_PREFIX_SIP;
215                 rr_prefix_len = RR_PREFIX_SIP_LEN;
216         } else {
217                 rr_prefix = RR_PREFIX_SIPS;
218                 rr_prefix_len = RR_PREFIX_SIPS_LEN;
219         }
220
221         prefix_len = rr_prefix_len + (user->len ? (user->len + 1) : 0);
222         if (enable_full_lr) {
223                 suffix_len = RR_LR_FULL_LEN + (params?params->len:0) +
224                                 ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0);
225         } else {
226                 suffix_len = RR_LR_LEN + (params?params->len:0) +
227                                 ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0);
228         }
229
230         prefix = pkg_malloc(prefix_len);
231         suffix = pkg_malloc(suffix_len);
232         term = pkg_malloc(RR_TERM_LEN);
233         r2 = pkg_malloc(RR_R2_LEN);
234
235         if (!prefix || !suffix || !term || !r2) {
236                 LM_ERR("No more pkg memory\n");
237                 if (suffix) pkg_free(suffix);
238                 if (prefix) pkg_free(prefix);
239                 if (term) pkg_free(term);
240                 if (r2) pkg_free(r2);
241                 return -3;
242         }
243
244         memcpy(prefix, rr_prefix, rr_prefix_len);
245         if (user->len) {
246                 memcpy(prefix + rr_prefix_len, user->s, user->len);
247 #ifdef ENABLE_USER_CHECK
248                 /* don't add the ignored user into a RR */
249                 if(i_user.len && i_user.len == user->len &&
250                                 !strncmp(i_user.s, user->s, i_user.len))
251                 {
252                         if(prefix[rr_prefix_len]=='x')
253                                 prefix[rr_prefix_len]='y';
254                         else
255                                 prefix[rr_prefix_len]='x';
256                 }
257 #endif
258                 prefix[rr_prefix_len + user->len] = '@';
259         }
260
261         p = suffix;
262         if (enable_full_lr) {
263                 memcpy( p, RR_LR_FULL, RR_LR_FULL_LEN);
264                 p += RR_LR_FULL_LEN;
265         } else {
266                 memcpy( p, RR_LR, RR_LR_LEN);
267                 p += RR_LR_LEN;
268         }
269         if (tag && tag->len) {
270                 memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN);
271                 p += RR_FROMTAG_LEN;
272                 memcpy(p, tag->s, tag->len);
273                 p += tag->len;
274         }
275         if (params && params->len) {
276                 memcpy(p, params->s, params->len);
277                 p += params->len;
278         }
279
280         memcpy(term, RR_TERM, RR_TERM_LEN);
281         memcpy(r2, RR_R2, RR_R2_LEN);
282
283         if (!(_l = insert_new_lump_after(_l, prefix, prefix_len, 0)))
284                 goto lump_err;
285         prefix = 0;
286         rr_lump_type = (_inbound)?
287                                         (rr_sockname_mode?SUBST_RCV_ALL_EX:SUBST_RCV_ALL)
288                                         :(rr_sockname_mode?SUBST_SND_ALL_EX:SUBST_SND_ALL);
289         _l = insert_subst_lump_after(_l, rr_lump_type, 0);
290         if (_l ==0 )
291                 goto lump_err;
292         if (enable_double_rr) {
293                 if (!(_l = insert_cond_lump_after(_l,
294                                 (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_REALMS, 0)))
295                         goto lump_err;
296                 if (!(_l = insert_new_lump_after(_l, r2, RR_R2_LEN, 0)))
297                         goto lump_err;
298                 r2 = 0;
299         } else {
300                 pkg_free(r2);
301                 r2 = 0;
302         }
303         _l2 = insert_new_lump_before(_l2, suffix, suffix_len, HDR_RECORDROUTE_T);
304         if (_l2 == 0)
305                 goto lump_err;
306         if (rr_param_buf.len) {
307                 _l2 = insert_rr_param_lump(_l2, rr_param_buf.s, rr_param_buf.len);
308                 if (_l2 == 0)
309                         goto lump_err;
310         }
311         suffix = 0;
312         if (!(_l2 = insert_new_lump_before(_l2, term, RR_TERM_LEN, 0)))
313                 goto lump_err;
314         term = 0;
315         return 0;
316
317 lump_err:
318         LM_ERR("failed to insert lumps\n");
319         if (prefix) pkg_free(prefix);
320         if (suffix) pkg_free(suffix);
321         if (r2) pkg_free(r2);
322         if (term) pkg_free(term);
323         return -4;
324 }
325
326 /*!
327  * \brief Copy flow-token from top-Route: to a string
328  *
329  * Copy the user part of the top-Route: to a string (allocating private memory
330  * for this).
331  * \param token where the user-part of the top-Route: will be copied to
332  * \param _m the SIP message to extract the top-Route: from
333  * \return 0 on success, negative on failure
334  */
335 static int copy_flow_token(str *token, struct sip_msg *_m)
336 {
337         rr_t *rt;
338         struct sip_uri puri;
339
340         if (_m->route
341             || (parse_headers(_m, HDR_ROUTE_F, 0) != -1 && _m->route)) {
342                 if (parse_rr(_m->route) < 0) {
343                         LM_ERR("parsing Route: header body\n");
344                         return -1;
345                 }
346                 rt = (rr_t *) _m->route->parsed;
347                 if (!rt) {
348                         LM_ERR("empty Route:\n");
349                         return -1;
350                 }
351                 if (parse_uri(rt->nameaddr.uri.s, rt->nameaddr.uri.len,
352                                 &puri) < 0) {
353                         LM_ERR("parsing Route-URI\n");
354                         return -1;
355                 }
356
357                 token->s = pkg_malloc(puri.user.len * sizeof(char));
358                 if (token->s == NULL) {
359                         LM_ERR("allocating memory\n");
360                         return -1;
361                 }
362                 memcpy(token->s, puri.user.s, puri.user.len);
363                 token->len = puri.user.len;
364                 return 0;
365         }
366
367         LM_ERR("no Route: headers found\n");
368         return -1;
369 }
370
371
372 /*!
373  * \brief Insert a new Record-Route header field with lr parameter
374  *
375  * Insert a new Record-Route header field and also 2nd one if it is enabled
376  * and the realm changed so the 2nd record-route header will be necessary.
377  * \param _m SIP message
378  * \param params RR parameter
379  * \return 0 on success, negative on failure
380  */
381 int record_route(struct sip_msg* _m, str *params)
382 {
383         struct lump* l, *l2;
384         str user = {NULL, 0};
385         str* tag;
386         int use_ob = rr_obb.use_outbound ? rr_obb.use_outbound(_m) : 0;
387         int sips = 0;
388         int ret = 0;
389
390         user.len = 0;
391
392         if (add_username) {
393                 /* check if there is a custom user set */
394                 if (get_custom_user(_m, &user) < 0) {
395                         if (get_username(_m, &user) < 0) {
396                                 LM_ERR("failed to extract username\n");
397                                 return -1;
398                         }
399                 }
400         } else if (use_ob == 1) {
401                 if (rr_obb.encode_flow_token(&user, _m->rcv) != 0) {
402                         LM_ERR("encoding outbound flow-token\n");
403                         return -1;
404                 }
405         } else if (use_ob == 2) {
406                 if (copy_flow_token(&user, _m) != 0) {
407                         LM_ERR("copying outbound flow-token\n");
408                         return -1;
409                 }
410         }
411
412         if (append_fromtag) {
413                 if (is_direction(_m, RR_FLOW_UPSTREAM) == 0) {
414                         if (parse_to_header(_m) < 0) {
415                                 LM_ERR("To parsing failed\n");
416                                 ret = -2;
417                                 goto error;
418                         }
419                         tag = &((struct to_body*)_m->to->parsed)->tag_value;
420                 } else {
421                         if (parse_from_header(_m) < 0) {
422                                 LM_ERR("From parsing failed\n");
423                                 ret = -2;
424                                 goto error;
425                         }
426                         tag = &((struct to_body*)_m->from->parsed)->tag_value;
427                 }
428         } else {
429                 tag = 0;
430         }
431
432         if (rr_param_buf.len && rr_param_msg!=_m->id) {
433                 /* rr_params were set for a different message -> reset buffer */
434                 rr_param_buf.len = 0;
435         }
436
437         if(rr_ignore_sips==0) {
438                 sips = rr_is_sips(_m);
439         }
440
441         if (enable_double_rr) {
442                 l = anchor_lump(_m, _m->headers->name.s - _m->buf,0,HDR_RECORDROUTE_T);
443                 l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
444                 if (!l || !l2) {
445                         LM_ERR("failed to create an anchor\n");
446                         ret = -5;
447                         goto error;
448                 }
449                 l = insert_cond_lump_after(l,
450                                 (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_REALMS, 0);
451                 l2 = insert_cond_lump_before(l2,
452                                 (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_REALMS, 0);
453                 if (!l || !l2) {
454                         LM_ERR("failed to insert conditional lump\n");
455                         ret = -6;
456                         goto error;
457                 }
458                 if (build_rr(l, l2, &user, tag, params, OUTBOUND, sips) < 0) {
459                         LM_ERR("failed to insert outbound Record-Route\n");
460                         ret = -7;
461                         goto error;
462                 }
463         }
464
465         l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
466         l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
467         if (!l || !l2) {
468                 LM_ERR("failed to create an anchor\n");
469                 ret = -3;
470                 goto error;
471         }
472
473         if (build_rr(l, l2, &user, tag, params, INBOUND, sips) < 0) {
474                 LM_ERR("failed to insert inbound Record-Route\n");
475                 ret = -4;
476                 goto error;
477         }
478
479         LM_DBG("inserted record route (r2: %d - plen: %d)\n", enable_double_rr,
480                         (params)?params->len:0);
481         /* reset the rr_param buffer */
482         rr_param_buf.len = 0;
483         ret = 0;
484 error:
485         if ((use_ob == 1) || (use_ob == 2))
486                 if (user.s != NULL)
487                         pkg_free(user.s);
488         return ret;
489 }
490
491
492 /*!
493  * \brief Insert manually created Record-Route header
494  *
495  * Insert manually created Record-Route header, no checks, no restrictions,
496  * always adds lr parameter, only fromtag is added automatically when requested.
497  * Allocates new private memory for this.
498  * \param _m SIP message
499  * \param _data manually created RR header
500  * \return 1 on success, negative on failure
501  */
502 int record_route_preset(struct sip_msg* _m, str* _data)
503 {
504         str user = {NULL, 0};
505         struct to_body* from = NULL;
506         struct lump* l;
507         char* hdr, *p;
508         int hdr_len;
509         int use_ob = rr_obb.use_outbound ? rr_obb.use_outbound(_m) : 0;
510         char *rr_prefix;
511         int rr_prefix_len;
512         int sips = 0;
513         int ret = 0;
514
515         if(rr_ignore_sips==0) {
516                 sips = rr_is_sips(_m);
517         }
518         if(sips==0) {
519                 rr_prefix = RR_PREFIX_SIP;
520                 rr_prefix_len = RR_PREFIX_SIP_LEN;
521         } else {
522                 rr_prefix = RR_PREFIX_SIPS;
523                 rr_prefix_len = RR_PREFIX_SIPS_LEN;
524         }
525
526         if (add_username) {
527                 if (get_username(_m, &user) < 0) {
528                         LM_ERR("failed to extract username\n");
529                         return -1;
530                 }
531         } else if (use_ob == 1) {
532                 if (rr_obb.encode_flow_token(&user, _m->rcv) != 0) {
533                         LM_ERR("encoding outbound flow-token\n");
534                         return -1;
535                 }
536         } else if (use_ob == 2) {
537                 if (copy_flow_token(&user, _m) != 0) {
538                         LM_ERR("copying outbound flow-token\n");
539                         return -1;
540                 }
541         }
542
543         if (append_fromtag) {
544                 if (parse_from_header(_m) < 0 || get_from(_m)==NULL) {
545                         LM_ERR("From parsing failed\n");
546                         ret = -2;
547                         goto error;
548                 }
549                 from = get_from(_m);
550         }
551
552         l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
553         if (!l) {
554                 LM_ERR("failed to create lump anchor\n");
555                 ret = -3;
556                 goto error;
557         }
558
559         hdr_len = rr_prefix_len;
560         if (user.len)
561                 hdr_len += user.len + 1; /* @ */
562         hdr_len += _data->len;
563
564         if (append_fromtag && from->tag_value.len) {
565                 hdr_len += RR_FROMTAG_LEN + from->tag_value.len;
566         }
567
568         if (enable_full_lr) {
569                 hdr_len += RR_LR_FULL_LEN;
570         } else {
571                 hdr_len += RR_LR_LEN;
572         }
573
574         hdr_len += RR_TERM_LEN;
575
576         hdr = pkg_malloc(hdr_len);
577         if (!hdr) {
578                 LM_ERR("no pkg memory left\n");
579                 ret = -4;
580                 goto error;
581         }
582
583         p = hdr;
584         memcpy(p, rr_prefix, rr_prefix_len);
585         p += rr_prefix_len;
586
587         if (user.len) {
588                 memcpy(p, user.s, user.len);
589                 p += user.len;
590                 *p = '@';
591                 p++;
592         }
593
594         memcpy(p, _data->s, _data->len);
595         p += _data->len;
596
597         if (append_fromtag && from->tag_value.len) {
598                 memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN);
599                 p += RR_FROMTAG_LEN;
600                 memcpy(p, from->tag_value.s, from->tag_value.len);
601                 p += from->tag_value.len;
602         }
603
604         if (enable_full_lr) {
605                 memcpy(p, RR_LR_FULL, RR_LR_FULL_LEN);
606                 p += RR_LR_FULL_LEN;
607         } else {
608                 memcpy(p, RR_LR, RR_LR_LEN);
609                 p += RR_LR_LEN;
610         }
611
612         memcpy(p, RR_TERM, RR_TERM_LEN);
613
614         if (!insert_new_lump_after(l, hdr, hdr_len, 0)) {
615                 LM_ERR("failed to insert new lump\n");
616                 pkg_free(hdr);
617                 ret = -5;
618                 goto error;
619         }
620         LM_DBG("inserted preset record route\n");
621         ret = 1;
622 error:
623         if ((use_ob == 1) || (use_ob == 2))
624                 if (user.s != NULL)
625                         pkg_free(user.s);
626         return ret;
627 }
628
629 /*!
630  * \brief Insert manually created Record-Route header
631  *
632  * Insert manually created Record-Route header, no checks, no restrictions,
633  * always adds lr parameter, only fromtag is added automatically when requested.
634  * Allocates new private memory for this.
635  * \param _m SIP message
636  * \param _data manually created RR header
637  * \return 1 on success, negative on failure
638  */
639
640 #define RR_TRANS_LEN 11
641 #define RR_TRANS ";transport="
642 static inline int build_advertised_rr(struct lump* _l, struct lump* _l2, str *_data,
643                                 str* user, str *tag, int _inbound, int _sips)
644 {
645         char *p;
646         char *hdr, *trans, *r2, *suffix, *term;
647         int hdr_len, suffix_len;
648         char *rr_prefix;
649         int rr_prefix_len;
650
651         if(_sips==0) {
652                 rr_prefix = RR_PREFIX_SIP;
653                 rr_prefix_len = RR_PREFIX_SIP_LEN;
654         } else {
655                 rr_prefix = RR_PREFIX_SIPS;
656                 rr_prefix_len = RR_PREFIX_SIPS_LEN;
657         }
658
659         hdr_len = rr_prefix_len;
660         if (user && user->len)
661                 hdr_len += user->len + 1; /* @ */
662         hdr_len += _data->len;
663
664         suffix_len = 0;
665         if (tag && tag->len) {
666                 suffix_len += RR_FROMTAG_LEN + tag->len;
667         }
668
669         if (enable_full_lr) {
670                 suffix_len += RR_LR_FULL_LEN;
671         } else {
672                 suffix_len += RR_LR_LEN;
673         }
674
675         hdr = pkg_malloc(hdr_len);
676         trans = pkg_malloc(RR_TRANS_LEN);
677         suffix = pkg_malloc(suffix_len);
678         r2 = pkg_malloc(RR_R2_LEN);
679         term = pkg_malloc(RR_TERM_LEN);
680         if (!hdr || !trans || !suffix || !term || !r2) {
681                 LM_ERR("no pkg memory left\n");
682                 if (hdr) pkg_free(hdr);
683                 if (trans) pkg_free(trans);
684                 if (suffix) pkg_free(suffix);
685                 if (r2) pkg_free(r2);
686                 if (term) pkg_free(term);
687                 return -1;
688         }
689
690         p = hdr;
691         memcpy(p, rr_prefix, rr_prefix_len);
692         p += rr_prefix_len;
693
694         if (user && user->len) {
695                 memcpy(p, user->s, user->len);
696                 p += user->len;
697                 *p = '@';
698                 p++;
699         }
700
701         memcpy(p, _data->s, _data->len);
702
703         p = suffix;
704         if (tag && tag->len) {
705                 memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN);
706                 p += RR_FROMTAG_LEN;
707                 memcpy(p, tag->s, tag->len);
708                 p += tag->len;
709         }
710
711         if (enable_full_lr) {
712                 memcpy(p, RR_LR_FULL, RR_LR_FULL_LEN);
713                 p += RR_LR_FULL_LEN;
714         } else {
715                 memcpy(p, RR_LR, RR_LR_LEN);
716                 p += RR_LR_LEN;
717         }
718
719         memcpy(trans, RR_TRANS, RR_TRANS_LEN);
720         memcpy(term, RR_TERM, RR_TERM_LEN);
721         memcpy(r2, RR_R2, RR_R2_LEN);
722
723         if (!(_l = insert_new_lump_after(_l, hdr, hdr_len, 0))) {
724                 LM_ERR("failed to insert new lump\n");
725                 goto lump_err;
726         }
727         hdr = NULL;
728         if (!(_l = insert_cond_lump_after(_l,
729                                 (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_PROTO, 0)))
730                 goto lump_err;
731         if (!(_l = insert_new_lump_after(_l, trans, RR_TRANS_LEN, 0)))
732                 goto lump_err;
733         if (!(_l = insert_subst_lump_after(_l, _inbound?SUBST_RCV_PROTO:SUBST_SND_PROTO, 0)))
734                 goto lump_err;
735         if (enable_double_rr) {
736                 if (!(_l = insert_cond_lump_after(_l,
737                                         (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_REALMS, 0)))
738                         goto lump_err;
739                 if (!(_l = insert_new_lump_after(_l, r2, RR_R2_LEN, 0)))
740                         goto lump_err;
741                 r2 = 0;
742         } else {
743                 pkg_free(r2);
744                 r2 = 0;
745         }
746         if (!(_l2 = insert_new_lump_before(_l2, suffix, suffix_len, HDR_RECORDROUTE_T)))
747                 goto lump_err;
748         suffix = NULL;
749         if (rr_param_buf.len) {
750                 if (!(_l2 = insert_rr_param_lump(_l2, rr_param_buf.s, rr_param_buf.len)))
751                         goto lump_err;
752         }
753         if (!(_l2 = insert_new_lump_before(_l2, term, RR_TERM_LEN, 0)))
754                 goto lump_err;
755         return 1;
756 lump_err:
757         if (hdr) pkg_free(hdr);
758         if (trans) pkg_free(trans);
759         if (suffix) pkg_free(suffix);
760         if (term) pkg_free(term);
761         if (r2) pkg_free(r2);
762         return -7;
763 }
764
765 int record_route_advertised_address(struct sip_msg* _m, str* _data)
766 {
767         str user = {NULL, 0};
768         str *tag = NULL;
769         struct lump* l;
770         struct lump* l2;
771         int use_ob = rr_obb.use_outbound ? rr_obb.use_outbound(_m) : 0;
772         int sips = 0;
773         int ret = 0;
774
775         user.len = 0;
776         user.s = 0;
777
778         if (add_username) {
779                 if (get_username(_m, &user) < 0) {
780                         LM_ERR("failed to extract username\n");
781                         return -1;
782                 }
783         } else if (use_ob == 1) {
784                 if (rr_obb.encode_flow_token(&user, _m->rcv) != 0) {
785                         LM_ERR("encoding outbound flow-token\n");
786                         return -1;
787                 }
788         } else if (use_ob == 2) {
789                 if (copy_flow_token(&user, _m) != 0) {
790                         LM_ERR("copying outbound flow-token\n");
791                         return -1;
792                 }
793         }
794
795         if (append_fromtag) {
796                 if (is_direction(_m, RR_FLOW_UPSTREAM) == 0) {
797                         if (parse_to_header(_m) < 0) {
798                                 LM_ERR("To parsing failed\n");
799                                 ret = -2;
800                                 goto error;
801                         }
802                         tag = &((struct to_body*)_m->to->parsed)->tag_value;
803                 } else {
804                         if (parse_from_header(_m) < 0) {
805                                 LM_ERR("From parsing failed\n");
806                                 ret = -2;
807                                 goto error;
808                         }
809                         tag = &((struct to_body*)_m->from->parsed)->tag_value;
810                 }
811         } else {
812                 tag = 0;
813         }
814
815         if(rr_ignore_sips==0) {
816                 sips = rr_is_sips(_m);
817         }
818
819         if (enable_double_rr) {
820                 l = anchor_lump(_m, _m->headers->name.s - _m->buf,0,HDR_RECORDROUTE_T);
821                 l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
822                 if (!l || !l2) {
823                         LM_ERR("failed to create an anchor\n");
824                         ret = -3;
825                         goto error;
826                 }
827                 l = insert_cond_lump_after(l,
828                                 (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_PROTO, 0);
829                 l2 = insert_cond_lump_before(l2,
830                                 (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_PROTO, 0);
831                 if (!l || !l2) {
832                         LM_ERR("failed to insert conditional lump\n");
833                         ret = -4;
834                         goto error;
835                 }
836                 if (build_advertised_rr(l, l2, _data, &user, tag, OUTBOUND,
837                                         sips) < 0) {
838                         LM_ERR("failed to insert outbound Record-Route\n");
839                         ret = -5;
840                         goto error;
841                 }
842         }
843
844         l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
845         l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
846         if (!l || !l2) {
847                 LM_ERR("failed to create an anchor\n");
848                 ret = -6;
849                 goto error;
850         }
851
852         if (build_advertised_rr(l, l2, _data, &user, tag, INBOUND, sips) < 0) {
853                 LM_ERR("failed to insert outbound Record-Route\n");
854                 ret = -7;
855                 goto error;
856         }
857         LM_DBG("inserted advertised address record route\n");
858         ret = 1;
859 error:
860         if ((use_ob == 1) || (use_ob == 2))
861                 if (user.s != NULL)
862                         pkg_free(user.s);
863         return ret;
864 }
865
866
867 /*!
868  * \brief Get the RR parameter lump
869  * \param root root of the lump list
870  * \return pointer to the RR parameter lump, or NULL if not found
871  */
872 static struct lump *get_rr_param_lump( struct lump** root)
873 {
874         struct lump *r, *crt, *last;
875         /* look on the "before" branch for the last added lump */
876
877         last = 0;
878         for( crt=*root ; crt && !last ; crt=crt->next,(*root)=crt ) {
879                 /* check on before list */
880                 for( r=crt->before ; r ; r=r->before ) {
881                         /* we are looking for the lump that adds the
882                          * suffix of the RR header */
883                         if ( r->type==HDR_RECORDROUTE_T && r->op==LUMP_ADD)
884                                 last = r;
885                 }
886         }
887         return last;
888 }
889
890
891 /*!
892  * \brief Appends a new Record-Route parameter
893  * \param msg SIP message
894  * \param rr_param RR parameter
895  * \return 0 on success, -1 on failure
896  */
897 int add_rr_param(struct sip_msg* msg, str* rr_param)
898 {
899         struct lump *last_param;
900         struct lump *root;
901
902         root = msg->add_rm;
903         last_param = get_rr_param_lump( &root );
904         if (last_param) {
905                 /* RR was already done -> have to add a new lump before this one */
906                 if (insert_rr_param_lump( last_param, rr_param->s, rr_param->len)==0) {
907                         LM_ERR("failed to add lump\n");
908                         goto error;
909                 }
910                 /* double routing enabled? */
911                 if (enable_double_rr) {
912                         if (root==0 || (last_param=get_rr_param_lump(&root))==0) {
913                                 LM_CRIT("failed to locate double RR lump\n");
914                                 goto error;
915                         }
916                         if (insert_rr_param_lump(last_param,rr_param->s,rr_param->len)==0){
917                                 LM_ERR("failed to add 2nd lump\n");
918                                 goto error;
919                         }
920                 }
921         } else {
922                 /* RR not done yet -> store the param in the static buffer */
923                 if (rr_param_msg!=msg->id) {
924                         /* it's about a different message -> reset buffer */
925                         rr_param_buf.len = 0;
926                         rr_param_msg = msg->id;
927                 }
928                 if (rr_param_buf.len+rr_param->len>RR_PARAM_BUF_SIZE) {
929                         LM_ERR("maximum size of rr_param_buf exceeded\n");
930                         goto error;
931                 }
932                 memcpy( rr_param_buf.s+rr_param_buf.len, rr_param->s, rr_param->len);
933                 rr_param_buf.len += rr_param->len;
934                 LM_DBG("rr_param_buf=<%.*s>\n",rr_param_buf.len, rr_param_buf.s);
935         }
936         return 0;
937
938 error:
939         return -1;
940 }