e785ee9990a3cde0b74ce5f229a73eb888fc4be2
[sip-router] / parser / parse_uri.c
1 /*
2  * $Id$
3  */
4
5 #include "parse_uri.h"
6 #include "../mem/mem.h"
7 #include <string.h>
8 #include "../dprint.h"
9 #include "../ut.h"    /* q_memchr */
10 #include "../error.h"
11
12 /* buf= pointer to begining of uri (sip:x@foo.bar:5060;a=b?h=i)
13  * len= len of uri
14  * returns: fills uri & returns <0 on error or 0 if ok 
15  */
16 int parse_uri(char *buf, int len, struct sip_uri* uri)
17 {
18         char* next, *end;
19         char *user, *passwd, *host, *port, *params, *headers, *ipv6;
20         int host_len, port_len, params_len, headers_len;
21         int ret;
22         
23         
24         ret=0;
25         host_len=0;
26         end=buf+len;
27         memset(uri, 0, sizeof(struct sip_uri)); /* zero it all, just to be sure */
28         /* look for "sip:"*/;
29         next=q_memchr(buf, ':',  len);
30         if ((next==0)||(strncmp(buf,"sip",next-buf)!=0)){
31                 LOG(L_DBG, "ERROR: parse_uri: bad sip uri\n");
32                 ser_error=ret=E_BAD_URI;
33                 goto error;
34         }
35         buf=next+1; /* next char after ':' */
36         if (buf>end){
37                 LOG(L_DBG, "ERROR: parse_uri: uri too short\n");
38                 ser_error=ret=E_BAD_URI;
39                 goto error;
40         }
41         /*look for '@' */
42         next=q_memchr(buf,'@', end-buf);
43         if (next==0){
44                 /* no '@' found, => no userinfo */
45                 uri->user.s=0;
46                 uri->passwd.s=0;
47                 host=buf;
48         }else{
49                 /* found it */
50                 user=buf;
51                 /* try to find passwd */
52                 passwd=q_memchr(user,':', next-user);
53                 if (passwd==0){
54                         /* no ':' found => no password */
55                         uri->passwd.s=0;
56                         uri->user.s=(char*)pkg_malloc(next-user+1);
57                         if (uri->user.s==0){
58                                 LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
59                                 ser_error=ret=E_OUT_OF_MEM;
60                                 goto error;
61                         }
62                         memcpy(uri->user.s, user, next-user);
63                         uri->user.len=next-user;
64                         uri->user.s[next-user]=0; /* null terminate it, 
65                                                                            usefull for easy printing*/
66                 }else{
67                         uri->user.s=(char*)pkg_malloc(passwd-user+1);
68                         if (uri->user.s==0){
69                                 LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
70                                 ser_error=ret=E_OUT_OF_MEM;
71                                 goto error;
72                         }
73                         memcpy(uri->user.s, user, passwd-user);
74                         uri->user.len=passwd-user;
75                         uri->user.s[passwd-user]=0;
76                         passwd++; /*skip ':' */
77                         uri->passwd.s=(char*)pkg_malloc(next-passwd+1);
78                         if (uri->passwd.s==0){
79                                 LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
80                                 ser_error=ret=E_OUT_OF_MEM;
81                                 goto error;
82                         }
83                         memcpy(uri->passwd.s, passwd, next-passwd);
84                         uri->passwd.len=next-passwd;
85                         uri->passwd.s[next-passwd]=0;
86                 }
87                 host=next+1; /* skip '@' */
88         }
89         /* try to find the rest */
90         if(host>=end){
91                 LOG(L_DBG, "ERROR: parse_uri: missing hostport\n");
92                 ser_error=ret=E_UNSPEC;
93                 goto error;
94         }
95         next=host;
96         ipv6=q_memchr(host, '[', end-host);
97         if (ipv6){
98                 host=ipv6+1; /* skip '[' in "[3ffe::abbcd]" */
99                 if (host>=end){
100                         LOG(L_DBG, "ERROR: parse_uri: bad ipv6 uri\n");
101                         ret=E_UNSPEC;
102                         goto error;
103                 }
104                 ipv6=q_memchr(host, ']', end-host);
105                 if ((ipv6==0)||(ipv6==host)){
106                         LOG(L_DBG, "ERROR: parse_uri: bad ipv6 uri - null address"
107                                         " or missing ']'\n");
108                         ret=E_UNSPEC;
109                         goto error;
110                 }
111                 host_len=ipv6-host;
112                 next=ipv6;
113         }
114
115                 
116         headers=q_memchr(next,'?',end-next);
117         params=q_memchr(next,';',end-next);
118         port=q_memchr(next,':',end-next);
119         if (host_len==0){ /* host not ipv6 addr */
120                 host_len=(port)?port-host:(params)?params-host:(headers)?headers-host:
121                                 end-host;
122         }
123         /* get host */
124         uri->host.s=pkg_malloc(host_len+1);
125         if (uri->host.s==0){
126                 LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
127                 ret=E_OUT_OF_MEM;
128                 goto error;
129         }
130         memcpy(uri->host.s, host, host_len);
131         uri->host.len=host_len;
132         uri->host.s[host_len]=0;
133         /* get port*/
134         if ((port)&&(port+1<end)){
135                 port++;
136                 if ( ((params) &&(params<port))||((headers) &&(headers<port)) ){
137                         /* error -> invalid uri we found ';' or '?' before ':' */
138                         LOG(L_DBG, "ERROR: parse_uri: malformed sip uri\n");
139                         ser_error=ret=E_BAD_URI;
140                         goto error;
141                 }
142                 port_len=(params)?params-port:(headers)?headers-port:end-port;
143                 uri->port.s=pkg_malloc(port_len+1);
144                 if (uri->port.s==0){
145                         LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
146                         ser_error=ret=E_OUT_OF_MEM;
147                         goto error;
148                 }
149                 memcpy(uri->port.s, port, port_len);
150                 uri->port.len=port_len;
151                 uri->port.s[port_len]=0;
152         }else uri->port.s=0;
153         /* get params */
154         if ((params)&&(params+1<end)){
155                 params++;
156                 if ((headers) && (headers<params)){
157                         /* error -> invalid uri we found '?' or '?' before ';' */
158                         LOG(L_DBG, "ERROR: parse_uri: malformed sip uri\n");
159                         ser_error=ret=E_BAD_URI;
160                         goto error;
161                 }
162                 params_len=(headers)?headers-params:end-params;
163                 uri->params.s=pkg_malloc(params_len+1);
164                 if (uri->params.s==0){
165                         LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
166                         ser_error=ret=E_OUT_OF_MEM;
167                         goto error;
168                 }
169                 memcpy(uri->params.s, params, params_len);
170                 uri->params.len=params_len;
171                 uri->params.s[params_len]=0;
172         }else uri->params.s=0;
173         /*get headers */
174         if ((headers)&&(headers+1<end)){
175                 headers++;
176                 headers_len=end-headers;
177                 uri->headers.s=pkg_malloc(headers_len+1);
178                 if(uri->headers.s==0){
179                         LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
180                         ser_error=ret=E_OUT_OF_MEM;
181                         goto error;
182                 }
183                 memcpy(uri->headers.s, headers, headers_len);
184                 uri->headers.len=headers_len;
185                 uri->headers.s[headers_len]=0;
186         }else uri->headers.s=0;
187         
188         return ret;
189 error:
190         free_uri(uri);
191         return ret;
192 }
193
194
195
196 int parse_sip_msg_uri(struct sip_msg* msg)
197 {
198         char* tmp;
199         int tmp_len;
200         if (msg->parsed_uri_ok) return 1;
201         else{
202                 if (msg->new_uri.s){
203                         tmp=msg->new_uri.s;
204                         tmp_len=msg->new_uri.len;
205                 }else{
206                         tmp=msg->first_line.u.request.uri.s;
207                         tmp_len=msg->first_line.u.request.uri.len;
208                 }
209                 if (parse_uri(tmp, tmp_len, &msg->parsed_uri)<0){
210                         LOG(L_ERR, "ERROR: parse_sip_msg_uri: bad uri <%.*s>\n",
211                                                 tmp_len, tmp);
212                         msg->parsed_uri_ok=0;
213                         return -1;
214                 }
215                 msg->parsed_uri_ok=1;
216                 return 1;
217         }
218 }
219
220
221
222 void free_uri(struct sip_uri* u)
223 {
224         if (u) {
225                 if (u->user.s)    pkg_free(u->user.s);
226                 if (u->passwd.s)  pkg_free(u->passwd.s);
227                 if (u->host.s)    pkg_free(u->host.s);
228                 if (u->port.s)    pkg_free(u->port.s);
229                 if (u->params.s)  pkg_free(u->params.s);
230                 if (u->headers.s) pkg_free(u->headers.s);
231         }
232 }