1803155206c7002d258100e1cca84877ef25c782
[sip-router] / src / core / dset.c
1 /*
2  * destination set
3  *
4  * Copyright (C) 2001-2004 FhG FOKUS
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License 
19  * along with this program; if not, write to the Free Software 
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23 /** Kamailio core :: destination set / branches support.
24  * @file dset.c
25  * @ingroup core
26  * Module: @ref core
27  */
28
29 #include <string.h>
30 #include "dprint.h"
31 #include "config.h"
32 #include "parser/parser_f.h"
33 #include "parser/parse_uri.h"
34 #include "parser/msg_parser.h"
35 #include "globals.h"
36 #include "ut.h"
37 #include "hash_func.h"
38 #include "error.h"
39 #include "dset.h"
40 #include "mem/mem.h"
41 #include "ip_addr.h"
42 #include "strutils.h"
43
44 #define CONTACT "Contact: "
45 #define CONTACT_LEN (sizeof(CONTACT) - 1)
46
47 #define CONTACT_DELIM ", "
48 #define CONTACT_DELIM_LEN (sizeof(CONTACT_DELIM) - 1)
49
50 #define Q_PARAM ";q="
51 #define Q_PARAM_LEN (sizeof(Q_PARAM) - 1)
52
53 #define ROUTE_PARAM "?Route="
54 #define ROUTE_PARAM_LEN (sizeof(ROUTE_PARAM) - 1)
55
56 #define FLAGS_PARAM ";flags="
57 #define FLAGS_PARAM_LEN (sizeof(FLAGS_PARAM) - 1)
58
59 /* 
60  * Where we store URIs of additional transaction branches
61  * (sr_dst_max_branches - 1 : because of the default branch for r-uri, #0 in tm)
62  */
63 static struct branch *branches = NULL;
64
65 /* how many of them we have */
66 unsigned int nr_branches = 0;
67
68 /* branch iterator */
69 static int branch_iterator = 0;
70
71 /* used to mark ruris "consumed" when branching (1 new, 0 consumed) */
72 int ruri_is_new = 0;
73
74 /* The q parameter of the Request-URI */
75 static qvalue_t ruri_q = Q_UNSPECIFIED;
76
77 /* Branch flags of the Request-URI */
78 static flag_t ruri_bflags;
79
80
81 int init_dst_set(void)
82 {
83         if(sr_dst_max_branches<=0 || sr_dst_max_branches>=MAX_BRANCHES_LIMIT) {
84                 LM_ERR("invalid value for max branches parameter: %u\n",
85                                 sr_dst_max_branches);
86                 return -1;
87         }
88         /* sr_dst_max_branches - 1 : because of the default branch for r-uri, #0 in tm */
89         branches = (branch_t*)pkg_malloc((sr_dst_max_branches-1)*sizeof(branch_t));
90         if(branches==NULL) {
91                 PKG_MEM_ERROR;
92                 return -1;
93         }
94         memset(branches, 0, (sr_dst_max_branches-1)*sizeof(branch_t));
95         return 0;
96 }
97
98 /*! \brief
99  * Return pointer to branch[idx] structure
100  * @param idx - branch index
101  *
102  * @return  pointer to branch or NULL if invalid branch
103  */
104 branch_t *get_sip_branch(int idx)
105 {
106         if(nr_branches==0)
107                 return NULL;
108         if(idx<0)
109         {
110                 if((int)nr_branches + idx >= 0)
111                         return &branches[nr_branches+idx];
112                 return NULL;
113         }
114         if(idx < nr_branches)
115                 return &branches[idx];
116         return 0;
117 }
118
119 /*! \brief
120  * Drop branch[idx]
121  * @param idx - branch index
122  *
123  * @return  0 on success, -1 on error
124  */
125 int drop_sip_branch(int idx)
126 {
127         if(nr_branches==0 || idx>=nr_branches)
128                 return 0;
129         if(idx<0 && (int)nr_branches+idx<0)
130                 return 0;
131         if(idx<0)
132                 idx += nr_branches;
133         /* last branch */
134         if(idx==nr_branches-1)
135         {
136                 nr_branches--;
137                 return 0;
138         }
139         /* shift back one position */
140         for(; idx<nr_branches-1; idx++)
141                 memcpy(&branches[idx], &branches[idx+1], sizeof(branch_t));
142         nr_branches--;
143         return 0;
144 }
145
146 static inline flag_t* get_bflags_ptr(unsigned int branch)
147 {
148         if (branch == 0) return &ruri_bflags;
149         if (branch - 1 < nr_branches) return &branches[branch - 1].flags;
150         return NULL;
151 }
152
153
154 int setbflag(unsigned int branch, flag_t flag)
155 {
156         flag_t* flags;
157
158         if ((flags = get_bflags_ptr(branch)) == NULL) return -1;
159         (*flags) |= 1 << flag;
160         return 1;
161 }
162
163
164 int isbflagset(unsigned int branch, flag_t flag)
165 {
166         flag_t* flags;
167
168         if ((flags = get_bflags_ptr(branch)) == NULL) return -1;
169         return ((*flags) & (1 << flag)) ? 1 : -1;
170 }
171
172
173 int resetbflag(unsigned int branch, flag_t flag)
174 {
175         flag_t* flags;
176
177         if ((flags = get_bflags_ptr(branch)) == NULL) return -1;
178         (*flags) &= ~ (1 << flag);
179         return 1;
180 }
181
182
183 int getbflagsval(unsigned int branch, flag_t* res)
184 {
185         flag_t* flags;
186         if (res == NULL) return -1;
187         if ((flags = get_bflags_ptr(branch)) == NULL) return -1;
188         *res = *flags;
189         return 1;
190 }
191
192
193 int setbflagsval(unsigned int branch, flag_t val)
194 {
195         flag_t* flags;
196         if ((flags = get_bflags_ptr(branch)) == NULL) return -1;
197         *flags = val;
198         return 1;
199 }
200
201
202 /*
203  * Initialize the branch iterator, the next
204  * call to next_branch will return the first
205  * contact from the dset array
206  */
207 void init_branch_iterator(void)
208 {
209         branch_iterator = 0;
210 }
211
212 /**
213  * return the value of current branch iterator
214  */
215 int get_branch_iterator(void)
216 {
217         return branch_iterator;
218 }
219
220 /**
221  * set the value of current branch interator
222  */
223 void set_branch_iterator(int n)
224 {
225         branch_iterator = n;
226 }
227
228
229 /** \brief Get a branch from the destination set
230  * \return Return the 'i' branch from the dset
231  * array, 0 is returned if there are no
232  * more branches
233  */
234 char* get_branch(unsigned int i, int* len, qvalue_t* q, str* dst_uri,
235                  str* path, unsigned int *flags,
236                  struct socket_info** force_socket,
237                  str *ruid, str *instance, str *location_ua)
238 {
239         if (i < nr_branches) {
240                 *len = branches[i].len;
241                 *q = branches[i].q;
242                 if (dst_uri) {
243                         dst_uri->len = branches[i].dst_uri_len;
244                         dst_uri->s = (dst_uri->len)?branches[i].dst_uri:0;
245                 }
246                 if (path) {
247                         path->len = branches[i].path_len;
248                         path->s = (path->len)?branches[i].path:0;
249                 }
250                 if (force_socket)
251                         *force_socket = branches[i].force_send_socket;
252                 if (flags)
253                         *flags = branches[i].flags;
254                 if (ruid) {
255                         ruid->len = branches[i].ruid_len;
256                         ruid->s = (ruid->len)?branches[i].ruid:0;
257                 }
258                 if (instance) {
259                         instance->len = branches[i].instance_len;
260                         instance->s = (instance->len)?branches[i].instance:0;
261                 }
262                 if (location_ua) {
263                         location_ua->len = branches[i].location_ua_len;
264                         location_ua->s
265                                 = (location_ua->len)?branches[i].location_ua:0;
266                 }
267                 return branches[i].uri;
268         } else {
269                 *len = 0;
270                 *q = Q_UNSPECIFIED;
271                 if (dst_uri) {
272                         dst_uri->s = 0;
273                         dst_uri->len = 0;
274                 }
275                 if (path) {
276                         path->s = 0;
277                         path->len = 0;
278                 }
279                 if (force_socket)
280                         *force_socket = 0;
281                 if (flags)
282                         *flags = 0;
283                 if (ruid) {
284                         ruid->s = 0;
285                         ruid->len = 0;
286                 }
287                 if (instance) {
288                         instance->s = 0;
289                         instance->len = 0;
290                 }
291                 if (location_ua) {
292                         location_ua->s = 0;
293                         location_ua->len = 0;
294                 }
295                 return 0;
296         }
297 }
298
299
300
301 /** Return the next branch from the dset array.
302  * 0 is returned if there are no more branches
303  */
304 char* next_branch(int* len, qvalue_t* q, str* dst_uri, str* path,
305                   unsigned int* flags, struct socket_info** force_socket,
306                   str* ruid, str *instance, str *location_ua)
307 {
308         char* ret;
309         
310         ret=get_branch(branch_iterator, len, q, dst_uri, path, flags,
311                        force_socket, ruid, instance, location_ua);
312         if (likely(ret))
313                 branch_iterator++;
314         return ret;
315 }
316
317
318 /*
319  * Empty the dset array
320  */
321 void clear_branches(void)
322 {
323         nr_branches = 0;
324         ruri_q = Q_UNSPECIFIED;
325         ruri_bflags = 0;
326         ruri_mark_consumed();
327 }
328
329
330
331 /**  Add a new branch to the current transaction.
332  * @param msg sip message, used for getting the uri if not specified (0).
333  * @param uri uri, can be 0 (in which case the uri is taken from msg)
334  * @param dst_uri destination uri, can be 0.
335  * @param path path vector (passed in a string), can be 0.
336  * @param q  q value.
337  * @param flags per branch flags.
338  * @param force_socket socket that should be used when sending.
339  * @param instance sip instance contact header param value
340  * @param reg_id reg-id contact header param value
341  * @param ruid ruid value from usrloc
342  * @param location_ua location user agent
343  *
344  * @return  <0 (-1) on failure, 1 on success (script convention).
345  */
346 int append_branch(struct sip_msg* msg, str* uri, str* dst_uri, str* path,
347                   qvalue_t q, unsigned int flags,
348                   struct socket_info* force_socket,
349                   str* instance, unsigned int reg_id,
350                   str* ruid, str* location_ua)
351 {
352         str luri;
353
354         /* if we have already set up the maximum number
355          * of branches, don't try new ones 
356          */
357         if (unlikely(nr_branches == sr_dst_max_branches - 1)) {
358                 LM_ERR("max nr of branches exceeded\n");
359                 ser_error = E_TOO_MANY_BRANCHES;
360                 return -1;
361         }
362
363         /* if not parameterized, take current uri */
364         if (uri==0 || uri->len==0 || uri->s==0) {
365                 if(msg==NULL) {
366                         LM_ERR("no new uri and no msg to take r-uri\n");
367                         ser_error = E_INVALID_PARAMS;
368                         return -1;
369                 }
370                 if (msg->new_uri.s)
371                         luri = msg->new_uri;
372                 else
373                         luri = msg->first_line.u.request.uri;
374         } else {
375                 luri = *uri;
376         }
377
378         if (unlikely(luri.len > MAX_URI_SIZE - 1)) {
379                 LM_ERR("too long uri: %.*s\n", luri.len, luri.s);
380                 return -1;
381         }
382
383         /* copy the dst_uri */
384         if (dst_uri && dst_uri->len && dst_uri->s) {
385                 if (unlikely(dst_uri->len > MAX_URI_SIZE - 1)) {
386                         LM_ERR("too long dst_uri: %.*s\n", dst_uri->len, dst_uri->s);
387                         return -1;
388                 }
389                 memcpy(branches[nr_branches].dst_uri, dst_uri->s, dst_uri->len);
390                 branches[nr_branches].dst_uri[dst_uri->len] = 0;
391                 branches[nr_branches].dst_uri_len = dst_uri->len;
392         } else {
393                 branches[nr_branches].dst_uri[0] = '\0';
394                 branches[nr_branches].dst_uri_len = 0;
395         }
396
397         /* copy the path string */
398         if (unlikely(path && path->len && path->s)) {
399                 if (unlikely(path->len > MAX_PATH_SIZE - 1)) {
400                         LM_ERR("too long path: %.*s\n", path->len, path->s);
401                         return -1;
402                 }
403                 memcpy(branches[nr_branches].path, path->s, path->len);
404                 branches[nr_branches].path[path->len] = 0;
405                 branches[nr_branches].path_len = path->len;
406         } else {
407                 branches[nr_branches].path[0] = '\0';
408                 branches[nr_branches].path_len = 0;
409         }
410
411         /* copy the ruri */
412         memcpy(branches[nr_branches].uri, luri.s, luri.len);
413         branches[nr_branches].uri[luri.len] = 0;
414         branches[nr_branches].len = luri.len;
415         branches[nr_branches].q = q;
416
417         branches[nr_branches].force_send_socket = force_socket;
418         branches[nr_branches].flags = flags;
419
420         /* copy instance string */
421         if (unlikely(instance && instance->len && instance->s)) {
422                 if (unlikely(instance->len > MAX_INSTANCE_SIZE - 1)) {
423                         LM_ERR("too long instance: %.*s\n",
424                             instance->len, instance->s);
425                         return -1;
426                 }
427                 memcpy(branches[nr_branches].instance, instance->s,
428                        instance->len);
429                 branches[nr_branches].instance[instance->len] = 0;
430                 branches[nr_branches].instance_len = instance->len;
431         } else {
432                 branches[nr_branches].instance[0] = '\0';
433                 branches[nr_branches].instance_len = 0;
434         }
435
436         /* copy reg_id */
437         branches[nr_branches].reg_id = reg_id;
438
439         /* copy ruid string */
440         if (unlikely(ruid && ruid->len && ruid->s)) {
441                 if (unlikely(ruid->len > MAX_RUID_SIZE - 1)) {
442                         LM_ERR("too long ruid: %.*s\n",
443                             ruid->len, ruid->s);
444                         return -1;
445                 }
446                 memcpy(branches[nr_branches].ruid, ruid->s,
447                        ruid->len);
448                 branches[nr_branches].ruid[ruid->len] = 0;
449                 branches[nr_branches].ruid_len = ruid->len;
450         } else {
451                 branches[nr_branches].ruid[0] = '\0';
452                 branches[nr_branches].ruid_len = 0;
453         }
454
455         if (unlikely(location_ua && location_ua->len && location_ua->s)) {
456                 if (unlikely(location_ua->len > MAX_UA_SIZE)) {
457                         LM_ERR("too long location_ua: %.*s\n",
458                             location_ua->len, location_ua->s);
459                         return -1;
460                 }
461                 memcpy(branches[nr_branches].location_ua, location_ua->s,
462                        location_ua->len);
463                 branches[nr_branches].location_ua[location_ua->len] = 0;
464                 branches[nr_branches].location_ua_len = location_ua->len;
465         } else {
466                 branches[nr_branches].location_ua[0] = '\0';
467                 branches[nr_branches].location_ua_len = 0;
468         }
469         
470         nr_branches++;
471         return 1;
472 }
473
474
475 /*! \brief
476  * Combines the given elements into a Contact header field
477  * dest = target buffer, will be updated to new position after the printed contact
478  * uri, q = contact elements
479  * end = end of target buffer
480  * Returns 0 on success or -1 on error (buffer is too short)
481  */
482 static int print_contact_str(char **dest, str *uri, qvalue_t q, str *path, unsigned int flags, char *end, int options)
483 {
484         char *p = *dest;
485         str buf;
486
487         /* uri */
488         if (p + uri->len + 2 > end) {
489                 return -1;
490         }
491         *p++ = '<';
492         memcpy(p, uri->s, uri->len);
493         p += uri->len;
494
495         /* uri parameters */
496         /* path vector as route header parameter */
497         if ((options & DS_PATH) && path->len > 0) {
498                 if (p + ROUTE_PARAM_LEN + path->len > end) {
499                         return -1;
500                 }
501                 memcpy(p, ROUTE_PARAM, ROUTE_PARAM_LEN);
502                 p += ROUTE_PARAM_LEN;
503                 /* copy escaped path into dest */
504                 buf.s = p;
505                 buf.len = end - p;
506                 if (escape_param(path, &buf) < 0) {
507                         return -1;
508                 }
509                 p += buf.len;
510         }
511
512         /* end of uri parameters */
513         *p++ = '>';
514
515         /* header parameters */
516         /* q value */
517         if (q != Q_UNSPECIFIED) {
518                 buf.s = q2str(q, (unsigned int*)&buf.len);
519                 if (p + Q_PARAM_LEN + buf.len > end) {
520                         return -1;
521                 }
522                 memcpy(p, Q_PARAM, Q_PARAM_LEN);
523                 p += Q_PARAM_LEN;
524                 memcpy(p, buf.s, buf.len);
525                 p += buf.len;
526         }
527
528         /* branch flags (not SIP standard conformant) */
529         if (options & DS_FLAGS) {
530                 buf.s = int2str(flags, &buf.len);
531                 if (p + FLAGS_PARAM_LEN + buf.len > end) {
532                         return -1;
533                 }
534                 memcpy(p, FLAGS_PARAM, FLAGS_PARAM_LEN);
535                 p += FLAGS_PARAM_LEN;
536                 memcpy(p, buf.s, buf.len);
537                 p += buf.len;
538         }
539
540         *dest = p;
541         return 0;
542 }
543
544
545 /*
546  * Create a Contact header field from the dset
547  * array
548  */
549 char* print_dset(struct sip_msg* msg, int* len, int options)
550 {
551         int cnt = 0;
552         qvalue_t q;
553         str uri, path;
554         unsigned int flags;
555         char *p;
556         int crt_branch;
557         static char dset[MAX_REDIRECTION_LEN];
558         char *end = dset + MAX_REDIRECTION_LEN;
559
560         /* backup current branch index to restore it later */
561         crt_branch = get_branch_iterator();
562
563         /* contact header name */
564         if (CONTACT_LEN + CRLF_LEN + 1 > MAX_REDIRECTION_LEN) {
565                 goto memfail;
566         }
567         memcpy(dset, CONTACT, CONTACT_LEN);
568         p = dset + CONTACT_LEN;
569
570         /* current uri */
571         if (msg->new_uri.s) {
572                 if (print_contact_str(&p, &msg->new_uri, ruri_q, &msg->path_vec, ruri_bflags, end, options) < 0) {
573                         goto memfail;
574                 }
575                 cnt++;
576         }
577
578         /* branches */
579         init_branch_iterator();
580         while ((uri.s = next_branch(&uri.len, &q, 0, &path, &flags, 0, 0, 0, 0))) {
581                 if (cnt > 0) {
582                         if (p + CONTACT_DELIM_LEN > end) {
583                                 goto memfail;
584                         }
585                         memcpy(p, CONTACT_DELIM, CONTACT_DELIM_LEN);
586                         p += CONTACT_DELIM_LEN;
587                 }
588
589                 if (print_contact_str(&p, &uri, q, &path, flags, end, options) < 0) {
590                         goto memfail;
591                 }
592
593                 cnt++;
594         }
595
596         if (cnt == 0) {
597                 LM_WARN("no r-uri or branches\n");
598                 goto error;
599         }
600
601         if (p + CRLF_LEN + 1 > end) {
602                 goto memfail;
603         }
604         memcpy(p, CRLF " ", CRLF_LEN + 1);
605         *len = p - dset + CRLF_LEN;
606         set_branch_iterator(crt_branch);
607         return dset;
608
609 memfail:
610         LM_ERR("redirection buffer length exceed\n");
611 error:
612         *len = 0;
613         set_branch_iterator(crt_branch);
614         return 0;
615 }
616
617
618 /*
619  * Sets the q parameter of the Request-URI
620  */
621 void set_ruri_q(qvalue_t q)
622 {
623         ruri_q = q;
624 }
625
626
627 /*
628  * Return the q value of the Request-URI
629  */
630 qvalue_t get_ruri_q(void)
631 {
632         return ruri_q;
633 }
634
635
636
637 /*
638  * Rewrite Request-URI
639  */
640 int rewrite_uri(struct sip_msg* _m, str* _s)
641 {
642         char *buf = NULL;
643
644         if(_m->new_uri.s==NULL || _m->new_uri.len<_s->len) {
645                 buf = (char*)pkg_malloc(_s->len + 1);
646                 if (!buf) {
647                         PKG_MEM_ERROR;
648                         return -1;
649                 }
650         }
651         if(buf!=NULL) {
652                 if(_m->new_uri.s)
653                         pkg_free(_m->new_uri.s);
654         } else {
655                 buf = _m->new_uri.s;
656         }
657
658         memcpy(buf, _s->s, _s->len);
659         buf[_s->len] = '\0';
660
661         _m->parsed_uri_ok = 0;
662
663         _m->new_uri.s = buf;
664         _m->new_uri.len = _s->len;
665         /* mark ruri as new and available for forking */
666         ruri_mark_new();
667
668         return 1;
669 }
670
671 /**
672  * return src ip, port and proto as a SIP uri or proxy address
673  * - value stored in a static buffer
674  * - mode=0 return uri, mode=1 return proxy address
675  */
676 int msg_get_src_addr(sip_msg_t *msg, str *uri, int mode)
677 {
678         static char buf[80];
679         char* p;
680         str ip, port;
681         int len;
682         str proto;
683
684         if (msg==NULL || uri==NULL) {
685                 LM_ERR("invalid parameter value\n");
686                 return -1;
687         }
688
689         ip.s = ip_addr2a(&msg->rcv.src_ip);
690         ip.len = strlen(ip.s);
691
692         port.s = int2str(msg->rcv.src_port, &port.len);
693
694         switch(msg->rcv.proto) {
695                 case PROTO_NONE:
696                 case PROTO_UDP:
697                         if(mode==0) {
698                                 proto.s = 0; /* Do not add transport parameter, UDP is default */
699                                 proto.len = 0;
700                         } else {
701                                 proto.s = "udp";
702                                 proto.len = 3;
703                         }
704                 break;
705
706                 case PROTO_TCP:
707                         proto.s = "tcp";
708                         proto.len = 3;
709                 break;
710
711                 case PROTO_TLS:
712                         proto.s = "tls";
713                         proto.len = 3;
714                 break;
715
716                 case PROTO_SCTP:
717                         proto.s = "sctp";
718                         proto.len = 4;
719                 break;
720
721                 case PROTO_WS:
722                 case PROTO_WSS:
723                         proto.s = "ws";
724                         proto.len = 2;
725                 break;
726
727                 default:
728                         LM_ERR("unknown transport protocol\n");
729                 return -1;
730         }
731
732         len = ip.len + 2*(msg->rcv.src_ip.af==AF_INET6)+ 1 + port.len;
733         if (mode==0) {
734                 len += 4;
735                 if(proto.s) {
736                         len += TRANSPORT_PARAM_LEN;
737                         len += proto.len;
738                 }
739         } else {
740                 len += proto.len + 1;
741         }
742
743         if (len > 79) {
744                 LM_ERR("buffer too small\n");
745                 return -1;
746         }
747
748         p = buf;
749         if(mode==0) {
750                 memcpy(p, "sip:", 4);
751                 p += 4;
752         } else {
753                 memcpy(p, proto.s, proto.len);
754                 p += proto.len;
755                 *p++ = ':';
756         }
757
758         if (msg->rcv.src_ip.af==AF_INET6)
759                 *p++ = '[';
760         memcpy(p, ip.s, ip.len);
761         p += ip.len;
762         if (msg->rcv.src_ip.af==AF_INET6)
763                 *p++ = ']';
764
765         *p++ = ':';
766
767         memcpy(p, port.s, port.len);
768         p += port.len;
769
770         if (mode==0 && proto.s) {
771                 memcpy(p, TRANSPORT_PARAM, TRANSPORT_PARAM_LEN);
772                 p += TRANSPORT_PARAM_LEN;
773
774                 memcpy(p, proto.s, proto.len);
775                 p += proto.len;
776         }
777
778         uri->s = buf;
779         uri->len = len;
780         uri->s[uri->len] = '\0';
781
782         return 0;
783 }
784
785 /**
786  * add alias parameter with encoding of source address
787  * - nuri->s must point to a buffer of nuri->len size
788  */
789 int uri_add_rcv_alias(sip_msg_t *msg, str *uri, str *nuri)
790 {
791         char* p;
792         str ip, port;
793         int len;
794
795         if (msg==NULL || uri==NULL || nuri==NULL) {
796                 LM_ERR("invalid parameter value\n");
797                 return -1;
798         }
799
800         ip.s = ip_addr2a(&msg->rcv.src_ip);
801         ip.len = strlen(ip.s);
802
803         port.s = int2str(msg->rcv.src_port, &port.len);
804
805         /*uri;alias=[ip]~port~proto*/
806         len = uri->len+ip.len+port.len+12;
807         if(len>=nuri->len) {
808                 LM_ERR("not enough space - new uri len: %d (buf size: %d)\n",
809                                 len, nuri->len);
810                 return -1;
811         }
812         p = nuri->s;
813         memcpy(p, uri->s, uri->len);
814         p += uri->len;
815         memcpy(p, ";alias=", 7);
816         p += 7;
817         if (msg->rcv.src_ip.af == AF_INET6)
818                 *p++ = '[';
819         memcpy(p, ip.s, ip.len);
820         p += ip.len;
821         if (msg->rcv.src_ip.af == AF_INET6)
822                 *p++ = ']';
823         *p++ = '~';
824         memcpy(p, port.s, port.len);
825         p += port.len;
826         *p++ = '~';
827         *p++ = msg->rcv.proto + '0';
828         nuri->len = p - nuri->s;
829         nuri->s[nuri->len] = '\0';
830
831         LM_DBG("encoded <%.*s> => [%.*s]\n",
832                         uri->len, uri->s, nuri->len, nuri->s);
833         return 0;
834 }
835
836 /**
837  * restore from alias parameter with encoding of source address
838  * - nuri->s must point to a buffer of nuri->len size
839  * - suri->s must point to a buffer of suri->len size
840  */
841 int uri_restore_rcv_alias(str *uri, str *nuri, str *suri)
842 {
843         char* p;
844         str skip;
845         str ip, port, sproto;
846         int proto;
847
848         if (uri==NULL || nuri==NULL || suri==NULL) {
849                 LM_ERR("invalid parameter value\n");
850                 return -1;
851         }
852
853         /* sip:x;alias=1.1.1.1~0~0 */
854         if(uri->len < 23) {
855                 /* no alias possible */
856                 return -2;
857         }
858         p = uri->s + uri->len-18;
859         skip.s = 0;
860         while(p>uri->s+5) {
861                 if(strncmp(p, ";alias=", 7)==0) {
862                         skip.s = p;
863                         break;
864                 }
865                 p--;
866         }
867         if(skip.s==0) {
868                 /* alias parameter not found */
869                 return -2;
870         }
871         p += 7;
872         ip.s = p;
873         p = (char*)memchr(ip.s, '~', (size_t)(uri->s+uri->len-ip.s));
874         if(p==NULL) {
875                 /* proper alias parameter not found */
876                 return -2;
877         }
878         ip.len = p - ip.s;
879         p++;
880         if(p>=uri->s+uri->len) {
881                 /* proper alias parameter not found */
882                 return -2;
883         }
884         port.s = p;
885         p = (char*)memchr(port.s, '~', (size_t)(uri->s+uri->len-port.s));
886         if(p==NULL) {
887                 /* proper alias parameter not found */
888                 return -2;
889         }
890         port.len = p - port.s;
891         p++;
892         if(p>=uri->s+uri->len) {
893                 /* proper alias parameter not found */
894                 return -2;
895         }
896         proto = (int)(*p - '0');
897         p++;
898
899         if(p!=uri->s+uri->len && *p!=';') {
900                 /* proper alias parameter not found */
901                 return -2;
902         }
903         skip.len = (int)(p - skip.s);
904
905         if(suri->len<=4+ip.len+1+port.len+11/*;transport=*/+4) {
906                 LM_ERR("address buffer too small\n");
907                 return -1;
908         }
909         if(nuri->len<=uri->len - skip.len) {
910                 LM_ERR("uri buffer too small\n");
911                 return -1;
912         }
913
914         p = nuri->s;
915         memcpy(p, uri->s, (size_t)(skip.s-uri->s));
916         p += skip.s-uri->s;
917         memcpy(p, skip.s+skip.len, (size_t)(uri->s+uri->len - skip.s - skip.len));
918         p += uri->s+uri->len - skip.s - skip.len;
919         nuri->len = p - nuri->s;
920
921         p = suri->s;
922         memcpy(p, "sip:", 4);
923         p += 4;
924         memcpy(p, ip.s, ip.len);
925         p += ip.len;
926         *p++ = ':';
927         memcpy(p, port.s, port.len);
928         p += port.len;
929         proto_type_to_str((unsigned short)proto, &sproto);
930         if(sproto.len>0 && proto!=PROTO_UDP) {
931                 memcpy(p, ";transport=", 11);
932                 p += 11;
933                 memcpy(p, sproto.s, sproto.len);
934                 p += sproto.len;
935         }
936         suri->len = p - suri->s;
937
938         LM_DBG("decoded <%.*s> => [%.*s] [%.*s]\n",
939                         uri->len, uri->s, nuri->len, nuri->s, suri->len, suri->s);
940
941         return 0;
942 }
943
944 /* address of record (aor) management */
945
946 /* address of record considered case sensitive
947  * - 0 = no; 1 = yes */
948 static int aor_case_sensitive=0;
949
950 int set_aor_case_sensitive(int mode)
951 {
952         int r;
953         r = aor_case_sensitive;
954         aor_case_sensitive = mode;
955         return r;
956 }
957
958 int get_aor_case_sensitive(void)
959 {
960         return aor_case_sensitive;
961 }