/
encode_uri.c
454 lines (440 loc) · 14.5 KB
/
encode_uri.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
/*
* Copyright (C) 2006-2007 VozTelecom Sistemas S.L
*
* This file is part of opensips, a free SIP server.
*
* opensips is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* opensips is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* =====================================================================================
*
* Filename: xuri.c
*
* Description: first trial to implement xuri
*
* Version: 1.0
* Created: 16/11/05 18:07:24 CET
* Revision: none
* Compiler: gcc
*
* Author: Elias Baixas (EB), elias@conillera.net
* Company: VozTele.com
*
* =====================================================================================
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <netinet/in.h>
#include "../../mem/mem.h"
#include "../../parser/msg_parser.h"
#include "../../dprint.h"
#include "encode_uri.h"
#include "encode_parameters.h"
#include "encode_header.h"
#include "xaddress.h"
#define REL_PTR(a,b) ((unsigned char)(b-a))
/*The XURI is one of the most important parts in SEAS, as
* most of the SIP MESSAGE structured headers (that is,
* headers which have a well-specified body construction)
* use the URI as the body (ie. via, route, record-route,
* contact, from, to, RURI)
*
* the XURI is a codified structure of flags and pointers
* that ease the parsing of the URI string.
*
* 1: The first byte of the structure, is a
* HEADER_START-based pointer to the beginning of the URI
* (including the "sip:").
* 1: The next byte is the length of the uri, so URIMAX
* is 256 (enough...)
* 2: Flags specifying the parts that are present in the URI
*
* as follows:
* 1: first byte
* SIP_OR_TEL_F 0x01 it is SIP or TEL uri.
* SECURE_F 0x02 it is secure or not (SIPS,TELS)
* USER_F 0x04 it as a user part (user@host)
* PASSWORD_F 0x08 it has a password part
* HOST_F 0x10 it has a host part
* PORT_F 0x20 it has a port part
* PARAMETERS_F 0x40 it has a port part
* HEADERS_F 0x80 it has a port part
* 1: second byte
* TRANSPORT_F 0x01 it has other parameters
* TTL_F 0x02 it has headers
* USER_F 0x04 it has the transport parameter
* METHOD_F 0x08 it has the ttl parameter
* MADDR_F 0x10 it has the user parameter
* LR_F 0x20 it has the method parameter
*
* All the following bytes are URI_START-based pointers to
* the fields that are present in the uri, as specified by
* the flags. They must appear in the same order shown in
* the flags, and only appear if the flag was set to 1.
*
* the end of the field, will be the place where the
* following pointer points to, minus one (note that all the
* fields present in a URI are preceded by 1 character, ie
* sip[:user][:passwod][@host][:port][;param1=x][;param2=y][?hdr1=a][&hdr2=b]$p
* it will be necessary to have a pointer at the end,
* pointing two past the end of the uri, so that the length
* of the last header can be computed.
*
* The reason to have the OTHER and HEADERS flags at the
* beginning(just after the strictly-uri stuff), is that it
* will be necessary to know the length of the parameters
* section and the headers section.
*
* The parameters can
* appear in an arbitrary order, so they won't be following
* the convention of transport-ttl-user-method-maddr-lr, so
* we can't rely on the next pointer to compute the length
* of the previous pointer field, as the ttl param can
* appear before the transport param. so the parameter
* pointers must have 2 bytes: pointer+length.
*
*/
int encode_uri2(char *hdr,int hdrlen,str uri_str, struct sip_uri *uri_parsed,unsigned char *payload)
{
int i=4,j;/* 1*pointer+1*len+2*flags*/
unsigned int scheme;
unsigned char flags1=0,flags2=0,uriptr;
uriptr=REL_PTR(hdr,uri_str.s);
if(uri_str.len>255 || uriptr>hdrlen){
LM_ERR("uri too long, or out of the sip_msg bounds\n");
return -1;
}
payload[0]=uriptr;
payload[1]=(unsigned char)uri_str.len;
if(uri_parsed->user.s && uri_parsed->user.len){
flags1 |= USER_F;
payload[i++]=REL_PTR(uri_str.s,uri_parsed->user.s);
}
if(uri_parsed->passwd.s && uri_parsed->passwd.len){
flags1 |= PASSWORD_F;
payload[i++]=REL_PTR(uri_str.s,uri_parsed->passwd.s);
}
if(uri_parsed->host.s && uri_parsed->host.len){
flags1 |= HOST_F;
payload[i++]=REL_PTR(uri_str.s,uri_parsed->host.s);
}
if(uri_parsed->port.s && uri_parsed->port.len){
flags1 |= PORT_F;
payload[i++]=REL_PTR(uri_str.s,uri_parsed->port.s);
}
if(uri_parsed->params.s && uri_parsed->params.len){
flags1 |= PARAMETERS_F;
payload[i++]=REL_PTR(uri_str.s,uri_parsed->params.s);
}
if(uri_parsed->headers.s && uri_parsed->headers.len){
flags1 |= HEADERS_F;
payload[i++]=REL_PTR(uri_str.s,uri_parsed->headers.s);
}
payload[i]=(unsigned char)(uri_str.len+1);
i++;
if(uri_parsed->transport.s && uri_parsed->transport.len){
flags2 |= TRANSPORT_F;
payload[i]=REL_PTR(uri_str.s,uri_parsed->transport.s);
payload[i+1]=(unsigned char)(uri_parsed->transport.len);
i+=2;
}
if(uri_parsed->ttl.s && uri_parsed->ttl.len){
flags2 |= TTL_F;
payload[i]=REL_PTR(uri_str.s,uri_parsed->ttl.s);
payload[i+1]=(unsigned char)uri_parsed->ttl.len;
i+=2;
}
if(uri_parsed->user_param.s && uri_parsed->user_param.len){
flags2 |= USER_F;
payload[i]=REL_PTR(uri_str.s,uri_parsed->user_param.s);
payload[i+1]=(unsigned char)uri_parsed->user_param.len;
i+=2;
}
if(uri_parsed->method.s && uri_parsed->method.len){
flags2 |= METHOD_F;
payload[i]=REL_PTR(uri_str.s,uri_parsed->method.s);
payload[i+1]=(unsigned char)uri_parsed->method.len;
i+=2;
}
if(uri_parsed->maddr.s && uri_parsed->maddr.len){
flags2 |= MADDR_F;
payload[i]=REL_PTR(uri_str.s,uri_parsed->maddr.s);
payload[i+1]=(unsigned char)uri_parsed->maddr.len;
i+=2;
}
if(uri_parsed->lr.s && uri_parsed->lr.len){
flags2 |= LR_F;
payload[i]=REL_PTR(uri_str.s,uri_parsed->lr.s);
payload[i+1]=(unsigned char)uri_parsed->lr.len;
i+=2;
}
/*in parse_uri, when there's a user=phone, the type
* is set to TEL_URI_T, even if there's a sip: in the beginning
* so lets check it by ourselves:
switch(uri_parsed->type){
case SIP_URI_T:
flags1 |= SIP_OR_TEL_F;
break;
case SIPS_URI_T:
flags1 |= (SIP_OR_TEL_F|SECURE_F);
break;
case TEL_URI_T:
break;
case TELS_URI_T:
flags1 |= SECURE_F;
break;
default:
return -1;
}*/
#define SIP_SCH 0x3a706973
#define SIPS_SCH 0x73706973
#define TEL_SCH 0x3a6c6574
#define TELS_SCH 0x736c6574
scheme=uri_str.s[0]+(uri_str.s[1]<<8)+(uri_str.s[2]<<16)+(uri_str.s[3]<<24);
scheme|=0x20202020;
if (scheme==SIP_SCH){
flags1 |= SIP_OR_TEL_F;
}else if(scheme==SIPS_SCH){
if(uri_str.s[4]==':'){
flags1 |= (SIP_OR_TEL_F|SECURE_F);
}else goto error;
}else if (scheme==TEL_SCH){
/*nothing*/
}else if (scheme==TELS_SCH){
if(uri_str.s[4]==':'){
flags1 |= SECURE_F;
}
}else goto error;
payload[2]=flags1;
payload[3]=flags2;
j=i;
i+=encode_parameters(&payload[i],uri_parsed->params.s,uri_str.s,&uri_parsed->params.len,'u');
if(i<j)
goto error;
return i;
error:
return -1;
}
int print_encoded_uri(FILE *fp,unsigned char *payload,int paylen,char *hdrstart,int hdrlen,char *prefix)
{
int i=4,j=0;/*1*pointer+1*len+2*flags*/
unsigned char uriidx=0,flags1=0,flags2=0,urilen;
char *ch_uriptr,*uritype=NULL,*secure=NULL;
uriidx=payload[0];
fprintf(fp,"%s",prefix);
for(j=0;j<paylen;j++)
fprintf(fp,"%s%d%s",j==0?"ENCODED-URI:[":":",payload[j],j==paylen-1?"]\n":"");
if(uriidx>hdrlen){
fprintf(fp,"bad index for start of uri: hdrlen=%d uri_index=%d\n",hdrlen,uriidx);
return -1;
}
ch_uriptr = hdrstart+uriidx;
urilen=payload[1];
flags1=payload[2];
flags2=payload[3];
fprintf(fp,"%sURI:[%.*s]\n",prefix,urilen,ch_uriptr);
uritype=flags1&SIP_OR_TEL_F?"SIP":"TEL";
secure=flags1&SECURE_F?"S":"";
fprintf(fp,"%s TYPE:[%s%s]\n",prefix,uritype,secure);
if(flags1 & USER_F){
fprintf(fp,"%s USER:[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
++i;
}
if(flags1 & PASSWORD_F){
fprintf(fp,"%s PASSWORD=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
++i;
}
if(flags1 & HOST_F){
fprintf(fp,"%s HOST=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
++i;
}
if(flags1 & PORT_F){
fprintf(fp,"%s PORT=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
++i;
}
if(flags1 & PARAMETERS_F){
fprintf(fp,"%s PARAMETERS=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
++i;
}
if(flags1 & HEADERS_F){
fprintf(fp,"%s HEADERS=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
++i;
}
++i;
if(flags2 & TRANSPORT_F){
fprintf(fp,"%s TRANSPORT=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]);
i+=2;
}
if(flags2 & TTL_F){
fprintf(fp,"%s TTL_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]);
i+=2;
}
if(flags2 & USER_F){
fprintf(fp,"%s USER_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]);
i+=2;
}
if(flags2 & METHOD_F){
fprintf(fp,"%s METHOD_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]);
i+=2;
}
if(flags2 & MADDR_F){
fprintf(fp,"%s MADDR_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]);
i+=2;
}
if(flags2 & LR_F){
fprintf(fp,"%s LR_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]);
i+=2;
}
print_encoded_parameters(fp,&payload[i],ch_uriptr,paylen-i,prefix);
return 0;
}
int print_uri_junit_tests(char *hdrstart,int hdrlen,unsigned char *payload,int paylen,int fd,char also_hdr,char *prefix)
{
int i=4,k=0,m=0;/*1*pointer+1*len+2*flags*/
unsigned char uriidx=0,flags1=0,flags2=0,urilen;
char *ch_uriptr,*aux,*aux2,*aux3,*uritype=NULL,*secure=NULL;
FILE *fp;
if ( (fp = fdopen(fd, "w*")) == NULL)
return -1;
uriidx=payload[0];
if(uriidx>hdrlen){
fprintf(fp,"bad index for start of uri: hdrlen=%d uri_index=%d\n",hdrlen,uriidx);
return -1;
}
if(also_hdr)
dump_standard_hdr_test(hdrstart,hdrlen,payload,paylen,fd);
ch_uriptr = hdrstart+uriidx;
urilen=payload[1];
flags1=payload[2];
flags2=payload[3];
fprintf(fp,"%stoString=(S)%.*s\n",prefix,urilen,ch_uriptr);
uritype=flags1&SIP_OR_TEL_F?"sip":"tel";
secure=flags1&SECURE_F?"s":"";
fprintf(fp,"%sgetScheme=(S)%s%s\n",prefix,uritype,secure);
fprintf(fp,"%sisSecure=(B)%s\n",prefix,flags1&SECURE_F?"true":"false");
fprintf(fp,"%sisSipURI=(B)%s\n",prefix,"true");
fprintf(fp,"%sgetUser=(S)",prefix);
if(flags1 & USER_F){
fprintf(fp,"%.*s\n",(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
++i;
}else
fprintf(fp,"(null)\n");
fprintf(fp,"%sgetUserPassword=(S)",prefix);
if(flags1 & PASSWORD_F){
fprintf(fp,"%.*s\n",(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
++i;
}else
fprintf(fp,"(null)\n");
fprintf(fp,"%sgetHost=(S)",prefix);
if(flags1 & HOST_F){
fprintf(fp,"%.*s\n",(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
++i;
}else
fprintf(fp,"(null)\n");/*can't happen*/
fprintf(fp,"%sgetPort=(I)",prefix);
if(flags1 & PORT_F){
fprintf(fp,"%.*s\n",(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
++i;
}else
fprintf(fp,"(null)\n");
/*user=phone;transport=udp*/
if(flags1 & PARAMETERS_F){
aux=&ch_uriptr[payload[i]];
aux2=NULL;
aux3=aux;
m=(payload[i+1]-1-payload[i]);
fprintf(fp,"%sgetParameter=(SAVP)",prefix);/*SVP = Attribute Value Pair*/
for(k=0;k<=m;k++){
if((aux3[k]==';'||(k==m)) && aux2==NULL){/*no parameterValue was found*/
fprintf(fp,"%.*s=;",(int)(aux3-aux+k),aux);
aux2=NULL;/*resets the parameterValue-start pointer*/
aux=aux3+1+k;/*points to the next parameter*/
}else
if((aux3[k]==';'||(k==m)) && aux2!=NULL){
fprintf(fp,"%.*s=%.*s;",(int)(aux2-aux),aux,(int)(aux3-aux2-1+k),aux2+1);
aux2=NULL;
aux=aux3+1+k;
} else
if(aux3[k]=='='){
aux2=aux3+k;
}
}
fprintf(fp,"\n");
++i;
}
if(flags1 & HEADERS_F){
aux=&ch_uriptr[payload[i]];
aux2=NULL;
aux3=aux;
m=(payload[i+1]-1-payload[i]);
fprintf(fp,"%sgetHeader=(SAVP)",prefix);
for(k=0;k<=m;k++){
if((aux3[k]==';'||(k==m)) && aux2==NULL){/*no parameterValue was found*/
fprintf(fp,"%.*s=;",(int)(aux3-aux+k),aux);
aux2=NULL;/*resets the parameterValue-start pointer*/
aux=aux3+1+k;/*points to the next parameter*/
}else
if((aux3[k]==';'||(k==m)) && aux2!=NULL){
fprintf(fp,"%.*s=%.*s;",(int)(aux2-aux),aux,(int)(aux3-aux2-1+k),aux2+1);
aux2=NULL;
aux=aux3+1+k;
} else
if(aux3[k]=='='){
aux2=aux3+k;
}
}
fprintf(fp,"\n");
++i;
}
++i;
fprintf(fp,"%sgetTransportParam=(S)",prefix);
if(flags2 & TRANSPORT_F){
fprintf(fp,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]);
i+=2;
}else
fprintf(fp,"(null)\n");
fprintf(fp,"%sgetTTLparam=(I)",prefix);
if(flags2 & TTL_F){
fprintf(fp,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]);
i+=2;
}else
fprintf(fp,"(null)\n");
fprintf(fp,"%sgetUserParam=(S)",prefix);
if(flags2 & USER_F){
fprintf(fp,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]);
i+=2;
}else
fprintf(fp,"(null)\n");
fprintf(fp,"%sgetMethodParam=(S)",prefix);
if(flags2 & METHOD_F){
fprintf(fp,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]);
i+=2;
}else
fprintf(fp,"(null)\n");
fprintf(fp,"%sgetMAddrParam=(S)",prefix);
if(flags2 & MADDR_F){
fprintf(fp,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]);
i+=2;
}else
fprintf(fp,"(null)\n");
if(flags2 & LR_F){
i+=2;
}
fprintf(fp,"\n");
fclose(fp);
return 0;
}