core/corex: move send()/send_tcp() to corex module
[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 #include "../../parser/parse_uri.h"
31 #include "../../resolve.h"
32
33 #include "corex_lib.h"
34
35 /**
36  * append new branches with generic parameters
37  */
38 int corex_append_branch(sip_msg_t *msg, gparam_t *pu, gparam_t *pq)
39 {
40         str uri = {0};
41         str qv = {0};
42         int ret = 0;
43
44         qvalue_t q = Q_UNSPECIFIED;
45         flag_t branch_flags = 0;
46
47         if (pu!=NULL)
48         {
49                 if(fixup_get_svalue(msg, pu, &uri)!=0)
50                 {
51                         LM_ERR("cannot get the URI parameter\n");
52                         return -1;
53                 }
54         }
55
56         if (pq!=NULL)
57         {
58                 if(fixup_get_svalue(msg, pq, &qv)!=0)
59                 {
60                         LM_ERR("cannot get the Q parameter\n");
61                         return -1;
62                 }
63                 if(qv.len>0 && str2q(&q, qv.s, qv.len)<0)
64                 {
65                         LM_ERR("cannot parse the Q parameter\n");
66                         return -1;
67                 }
68         }
69
70
71         getbflagsval(0, &branch_flags);
72         ret = append_branch(msg, (uri.len>0)?&uri:0, &msg->dst_uri,
73                         &msg->path_vec, q, branch_flags,
74                         msg->force_send_socket);
75
76
77         if(uri.len<=0)
78         {
79                 /* reset all branch attributes if r-uri was shifted to branch */
80                 reset_force_socket(msg);
81                 setbflagsval(0, 0);
82                 if(msg->dst_uri.s!=0)
83                         pkg_free(msg->dst_uri.s);
84                 msg->dst_uri.s = 0;
85                 msg->dst_uri.len = 0;
86                 if(msg->path_vec.s!=0)
87                         pkg_free(msg->path_vec.s);
88                 msg->path_vec.s = 0;
89                 msg->path_vec.len = 0;
90         }
91
92         return ret;
93 }
94
95 typedef struct corex_alias {
96         str alias;
97         unsigned short port;
98         unsigned short proto;
99         int flags;
100         struct corex_alias* next;
101 } corex_alias_t;
102
103 static corex_alias_t *_corex_alias_list = NULL;
104
105 int corex_add_alias_subdomains(char* aliasval)
106 {
107         char *p = NULL;
108         corex_alias_t ta;
109         corex_alias_t *na;
110
111         memset(&ta, 0, sizeof(corex_alias_t));
112
113         p = strchr(aliasval, ':');
114         if(p==NULL) {
115                 /* only hostname */
116                 ta.alias.s = aliasval;
117                 ta.alias.len = strlen(aliasval);
118                 goto done;
119         }
120         if((p-aliasval)==3 || (p-aliasval)==4) {
121                 /* check if it is protocol */
122                 if((p-aliasval)==3 && strncasecmp(aliasval, "udp", 3)==0) {
123                         ta.proto = PROTO_UDP;
124                 } else if((p-aliasval)==3 && strncasecmp(aliasval, "tcp", 3)==0) {
125                         ta.proto = PROTO_TCP;
126                 } else if((p-aliasval)==3 && strncasecmp(aliasval, "tls", 3)==0) {
127                         ta.proto = PROTO_TLS;
128                 } else if((p-aliasval)==4 && strncasecmp(aliasval, "sctp", 4)==0) {
129                         ta.proto = PROTO_SCTP;
130                 } else {
131                         /* use hostname */
132                         ta.alias.s = aliasval;
133                         ta.alias.len = p - aliasval;
134                 }
135         }
136         if(ta.alias.len==0) {
137                 p++;
138                 if(p>=aliasval+strlen(aliasval))
139                         goto error;
140                 ta.alias.s = p;
141                 p = strchr(ta.alias.s, ':');
142                 if(p==NULL) {
143                         ta.alias.len = strlen(ta.alias.s);
144                         goto done;
145                 }
146         }
147         /* port */
148         p++;
149         if(p>=aliasval+strlen(aliasval))
150                 goto error;
151         ta.port = str2s(p, strlen(p), NULL);
152
153 done:
154         if(ta.alias.len==0)
155                 goto error;
156
157         na = (corex_alias_t*)pkg_malloc(sizeof(corex_alias_t));
158         if(na==NULL) {
159                 LM_ERR("no memory for adding alias subdomains: %s\n", aliasval);
160                 return -1;
161         }
162         memcpy(na, &ta, sizeof(corex_alias_t));
163         na->next = _corex_alias_list;
164         _corex_alias_list = na;
165
166         return 0;
167
168 error:
169         LM_ERR("error adding alias subdomains: %s\n", aliasval);
170         return -1;
171 }
172
173
174 int corex_check_self(str* host, unsigned short port, unsigned short proto)
175 {
176         corex_alias_t *ta;
177
178         for(ta=_corex_alias_list; ta; ta=ta->next) {
179                 if(host->len<ta->alias.len)
180                         continue;
181                 if(ta->port!=0 && port!=0 && ta->port!=port)
182                         continue;
183                 if(ta->proto!=0 && proto!=0 && ta->proto!=proto)
184                         continue;
185                 if(host->len==ta->alias.len
186                                 && strncasecmp(host->s, ta->alias.s, host->len)==0) {
187                         /* match domain */
188                         LM_DBG("check self domain match: %d:%.*s:%d\n", (int)ta->port,
189                                         ta->alias.len, ta->alias.s, (int)ta->proto);
190                         return 1;
191                 }
192                 if(strncasecmp(ta->alias.s, host->s + host->len - ta->alias.len,
193                                         ta->alias.len)==0) {
194                         if(host->s[host->len - ta->alias.len - 1]=='.') {
195                                 /* match sub-domain */
196                                 LM_DBG("check self sub-domain match: %d:%.*s:%d\n", (int)ta->port,
197                                         ta->alias.len, ta->alias.s, (int)ta->proto);
198                                 return 1;
199                         }
200                 }
201         }
202
203         return 0; /* no match */
204 }
205
206 int corex_register_check_self(void)
207 {
208         if(_corex_alias_list==NULL)
209                 return 0;
210         if (register_check_self_func(corex_check_self) <0 ) {
211             LM_ERR("failed to register check self function\n");
212             return -1;
213         }
214         return 0;
215 }
216
217 int corex_send(sip_msg_t *msg, gparam_t *pu, enum sip_protos proto)
218 {
219         str dest = {0};
220         int ret = 0;
221         struct sip_uri next_hop, *u;
222         struct dest_info dst;
223         char *p;
224
225         if (pu)
226         {
227                 if (fixup_get_svalue(msg, pu, &dest))
228                 {
229                         LM_ERR("cannot get the destination parameter\n");
230                         return -1;
231                 }
232         }
233
234         init_dest_info(&dst);
235
236         if (dest.len <= 0)
237         {
238                 /*get next hop uri uri*/
239                 if (msg->dst_uri.len) {
240                         ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len,
241                                                         &next_hop);
242                         u = &next_hop;
243                 } else {
244                         ret = parse_sip_msg_uri(msg);
245                         u = &msg->parsed_uri;
246                 }
247
248                 if (ret<0) {
249                         LM_ERR("send() - bad_uri dropping packet\n");
250                         ret=E_BUG;
251                         goto error;
252                 }
253         }
254         else
255         {
256                 u = &next_hop;
257                 u->port_no = 5060;
258                 u->host = dest;
259                 p = memchr(dest.s, ':', dest.len);
260                 if (p)
261                 {
262                         u->host.len = p - dest.s;
263                         p++;
264                         u->port_no = str2s(p, dest.len - (p - dest.s), NULL);
265                 }
266         }
267
268         ret = sip_hostport2su(&dst.to, &u->host, u->port_no,
269                                 &dst.proto);
270         if(ret!=0) {
271                 LM_ERR("failed to resolve [%.*s]\n", u->host.len,
272                         ZSW(u->host.s));
273                 ret=E_BUG;
274                 goto error;
275         }
276
277         dst.proto = proto;
278         if (proto == PROTO_UDP)
279         {
280                 dst.send_sock=get_send_socket(msg, &dst.to, PROTO_UDP);
281                 if (dst.send_sock!=0){
282                         ret=udp_send(&dst, msg->buf, msg->len);
283                 }else{
284                         ret=-1;
285                 }
286         }
287 #ifdef USE_TCP
288         else{
289                 /*tcp*/
290                 dst.id=0;
291                 ret=tcp_send(&dst, 0, msg->buf, msg->len);
292         }
293 #endif
294
295         if (ret>=0) ret=1;
296
297
298 error:
299         return ret;
300 }