1f69847ea32fae2c51fe896d0f58c3987c5d49a9
[sip-router] / modules / corex / corex_lib.c
1 /**
2  * $Id$
3  *
4  * Copyright (C) 2011 Daniel-Constantin Mierla (asipto.com)
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  *
20  */
21
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "../../dprint.h"
28 #include "../../dset.h"
29 #include "../../forward.h"
30
31 #include "corex_lib.h"
32
33 /**
34  * append new branches with generic parameters
35  */
36 int corex_append_branch(sip_msg_t *msg, gparam_t *pu, gparam_t *pq)
37 {
38         str uri = {0};
39         str qv = {0};
40         int ret = 0;
41
42         qvalue_t q = Q_UNSPECIFIED;
43         flag_t branch_flags = 0;
44
45         if (pu!=NULL)
46         {
47                 if(fixup_get_svalue(msg, pu, &uri)!=0)
48                 {
49                         LM_ERR("cannot get the URI parameter\n");
50                         return -1;
51                 }
52         }
53
54         if (pq!=NULL)
55         {
56                 if(fixup_get_svalue(msg, pq, &qv)!=0)
57                 {
58                         LM_ERR("cannot get the Q parameter\n");
59                         return -1;
60                 }
61                 if(qv.len>0 && str2q(&q, qv.s, qv.len)<0)
62                 {
63                         LM_ERR("cannot parse the Q parameter\n");
64                         return -1;
65                 }
66         }
67
68
69         getbflagsval(0, &branch_flags);
70         ret = append_branch(msg, (uri.len>0)?&uri:0, &msg->dst_uri,
71                         &msg->path_vec, q, branch_flags,
72                         msg->force_send_socket);
73
74
75         if(uri.len<=0)
76         {
77                 /* reset all branch attributes if r-uri was shifted to branch */
78                 reset_force_socket(msg);
79                 setbflagsval(0, 0);
80                 if(msg->dst_uri.s!=0)
81                         pkg_free(msg->dst_uri.s);
82                 msg->dst_uri.s = 0;
83                 msg->dst_uri.len = 0;
84                 if(msg->path_vec.s!=0)
85                         pkg_free(msg->path_vec.s);
86                 msg->path_vec.s = 0;
87                 msg->path_vec.len = 0;
88         }
89
90         return ret;
91 }
92
93 typedef struct corex_alias {
94         str alias;
95         unsigned short port;
96         unsigned short proto;
97         int flags;
98         struct corex_alias* next;
99 } corex_alias_t;
100
101 static corex_alias_t *_corex_alias_list = NULL;
102
103 int corex_add_alias_subdomains(char* aliasval)
104 {
105         char *p = NULL;
106         corex_alias_t ta;
107         corex_alias_t *na;
108
109         memset(&ta, 0, sizeof(corex_alias_t));
110
111         p = strchr(aliasval, ':');
112         if(p==NULL) {
113                 /* only hostname */
114                 ta.alias.s = aliasval;
115                 ta.alias.len = strlen(aliasval);
116                 goto done;
117         }
118         if((p-aliasval)==3 || (p-aliasval)==4) {
119                 /* check if it is protocol */
120                 if((p-aliasval)==3 && strncasecmp(aliasval, "udp", 3)==0) {
121                         ta.proto = PROTO_UDP;
122                 } else if((p-aliasval)==3 && strncasecmp(aliasval, "tcp", 3)==0) {
123                         ta.proto = PROTO_TCP;
124                 } else if((p-aliasval)==3 && strncasecmp(aliasval, "tls", 3)==0) {
125                         ta.proto = PROTO_TLS;
126                 } else if((p-aliasval)==4 && strncasecmp(aliasval, "sctp", 4)==0) {
127                         ta.proto = PROTO_SCTP;
128                 } else {
129                         /* use hostname */
130                         ta.alias.s = aliasval;
131                         ta.alias.len = p - aliasval;
132                 }
133         }
134         if(ta.alias.len==0) {
135                 p++;
136                 if(p>=aliasval+strlen(aliasval))
137                         goto error;
138                 ta.alias.s = p;
139                 p = strchr(ta.alias.s, ':');
140                 if(p==NULL) {
141                         ta.alias.len = strlen(ta.alias.s);
142                         goto done;
143                 }
144         }
145         /* port */
146         p++;
147         if(p>=aliasval+strlen(aliasval))
148                 goto error;
149         ta.port = str2s(p, strlen(p), NULL);
150
151 done:
152         if(ta.alias.len==0)
153                 goto error;
154
155         na = (corex_alias_t*)pkg_malloc(sizeof(corex_alias_t));
156         if(na==NULL) {
157                 LM_ERR("no memory for adding alias subdomains: %s\n", aliasval);
158                 return -1;
159         }
160         memcpy(na, &ta, sizeof(corex_alias_t));
161         na->next = _corex_alias_list;
162         _corex_alias_list = na;
163
164         return 0;
165
166 error:
167         LM_ERR("error adding alias subdomains: %s\n", aliasval);
168         return -1;
169 }
170
171
172 int corex_check_self(str* host, unsigned short port, unsigned short proto)
173 {
174         corex_alias_t *ta;
175
176         for(ta=_corex_alias_list; ta; ta=ta->next) {
177                 if(host->len<ta->alias.len)
178                         continue;
179                 if(ta->port!=0 && port!=0 && ta->port!=port)
180                         continue;
181                 if(ta->proto!=0 && proto!=0 && ta->proto!=proto)
182                         continue;
183                 if(host->len==ta->alias.len
184                                 && strncasecmp(host->s, ta->alias.s, host->len)==0) {
185                         /* match domain */
186                         LM_DBG("check self domain match: %d:%.*s:%d\n", (int)ta->port,
187                                         ta->alias.len, ta->alias.s, (int)ta->proto);
188                         return 1;
189                 }
190                 if(strncasecmp(ta->alias.s, host->s + host->len - ta->alias.len,
191                                         ta->alias.len)==0) {
192                         if(host->s[host->len - ta->alias.len - 1]=='.') {
193                                 /* match sub-domain */
194                                 LM_DBG("check self sub-domain match: %d:%.*s:%d\n", (int)ta->port,
195                                         ta->alias.len, ta->alias.s, (int)ta->proto);
196                                 return 1;
197                         }
198                 }
199         }
200
201         return 0; /* no match */
202 }
203
204 int corex_register_check_self(void)
205 {
206         if(_corex_alias_list==NULL)
207                 return 0;
208         if (register_check_self_func(corex_check_self) <0 ) {
209             LM_ERR("failed to register check self function\n");
210             return -1;
211         }
212         return 0;
213 }