/
http.c
196 lines (166 loc) · 5.01 KB
/
http.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
/*
* Copyright (C) 2005 iptelorg GmbH
* Written by Jan Janak <jan@iptel.org>
*
* This file is part of Kamailio, a free SIP server.
*
* Kamailio 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
*
* Kamailio 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., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/** @addtogroup xmlrpc
* @{
*/
/** @file
* XML-RPC requests are carried in the body of HTTP requests, but HTTP
* requests does not contain some mandatory SIP headers and thus cannot
* be processed by SER directly. This file contains functions that can
* turn HTTP requests into SIP request by inserting fake mandatory SIP
* headers, such as Via. This allows SER to process such HTTP requests
* and extract the body of the request, which contains the XML-RPC
* document.
*/
#include "http.h"
#include "../../core/mem/mem.h"
#include "../../core/dprint.h"
#include "../../core/parser/parse_via.h"
#include "../../core/data_lump.h"
#include "../../core/ip_addr.h"
#include "../../core/msg_translator.h"
#include "../../core/ut.h"
#include <string.h>
/** Insert fake Via header field into SIP message.
*
* This function takes a SIP message and a Via header field
* as text and inserts the Via header field into the SIP
* message, modifying the data structures within the SIP
* message to make it look that the Via header field was
* received with the message.
*
* @param msg a pointer to the currently processed SIP message
* @param via the Via header field text to be inserted
* @param via_len size of the Via header field being inserted
* @return 0 on succes, a negative number on error.
*/
static int insert_fake_via(sip_msg_t* msg, char* via, int via_len)
{
struct via_body* vb = 0;
via_cnt++;
vb = pkg_malloc(sizeof(struct via_body));
if (vb == 0){
LM_ERR("out of pkg memory\n");
goto error;
}
memset(vb, 0, sizeof(struct via_body));
msg->h_via1 = pkg_malloc(sizeof(hdr_field_t));
if (!msg->h_via1) {
ERR("No memory left\n");
goto error;
}
memset(msg->h_via1, 0, sizeof(hdr_field_t));
/* FIXME: The code below would break if the VIA prefix
* gets changed in config.h
*/
msg->h_via1->name.s = via;
msg->h_via1->name.len = 3;
msg->h_via1->body.s = via + 5;
msg->h_via1->body.len = via_len - 5 - CRLF_LEN;
msg->h_via1->type = HDR_VIA_T;
msg->h_via1->parsed = vb;
/* This field is used by the msg translator to add a new
* via when forwarding the request. It must point to an existing
* header field because otherwise call to anchor_lump, which does
* hdr.s - buf, would crash
*/
vb->hdr.s = msg->headers->name.s;
vb->hdr.len = 0;
msg->via1 = vb;
/* We have to replace the zero terminating character right behind
* CRLF because otherwise the parser will return an error.
* It expects that there is either a next header field or another
* CRLF delimiter
*/
via[via_len] = 'a';
parse_via(via + 5, via + via_len + 1, vb);
if (vb->error == PARSE_ERROR){
ERR("Bad via\n");
goto error;
}
if (msg->last_header == 0) {
msg->headers = msg->h_via1;
msg->last_header = msg->h_via1;
} else {
msg->last_header->next = msg->h_via1;
msg->last_header = msg->h_via1;
}
return 0;
error:
if (vb) {
free_via_list(vb);
}
if (msg->h_via1) {
pkg_free(msg->h_via1);
msg->h_via1 = 0;
}
return -1;
}
static int insert_via_lump(sip_msg_t* msg, char* via, int via_len)
{
struct lump* anchor;
anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, HDR_VIA_T);
if (anchor == 0) {
ERR("Unable to create anchor\n");
return -1;
}
if (insert_new_lump_after(anchor, via, via_len, HDR_VIA_T) == 0) {
ERR("Unable to insert via lump\n");
return -1;
}
return 0;
}
/** Create a fake Via header field.
*
* This function creates a fake Via header field and inserts
* the fake header field into the header of the HTTP request.
* The fake Via header field contains the source IP address
* and port of the TCP/IP connection.
*/
int create_via(sip_msg_t* msg, char* s1, char* s2)
{
char* via;
unsigned int via_len;
str ip, port;
struct hostport hp;
struct dest_info dst;
ip.s = ip_addr2a(&msg->rcv.src_ip);
ip.len = strlen(ip.s);
port.s = int2str(msg->rcv.src_port, &port.len);
hp.host = &ip;
hp.port = &port;
init_dst_from_rcv(&dst, &msg->rcv);
via = via_builder(&via_len, NULL, &dst, 0, 0, &hp);
if (!via) {
ERR("Unable to build Via header field\n");
return -1;
}
if (insert_fake_via(msg, via, via_len) < 0) {
pkg_free(via);
return -1;
}
if (insert_via_lump(msg, via, via_len - CRLF_LEN) < 0) {
pkg_free(via);
return -1;
}
return 1;
}
/** @} */