GPLization banner introduced to *.[hc] files
[sip-router] / modules / tm / uac.c
1 /*
2  * $Id$
3  *
4  * simple UAC for things such as SUBSCRIBE or SMS gateway;
5  * no authentication and other UAC features -- just send
6  * a message, retransmit and await a reply; forking is not
7  * supported during client generation, in all other places
8  * it is -- adding it should be simple
9  *
10  * Copyright (C) 2001-2003 Fhg Fokus
11  *
12  * This file is part of ser, a free SIP server.
13  *
14  * ser is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version
18  *
19  * For a license to use the ser software under conditions
20  * other than those described here, or to purchase support for this
21  * software, please contact iptel.org by e-mail at the following addresses:
22  *    info@iptel.org
23  *
24  * ser is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License 
30  * along with this program; if not, write to the Free Software 
31  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
32  */
33
34
35 #include <stdlib.h>
36 #include <sys/types.h>
37 #include <unistd.h>
38 #include <stdio.h>
39 #include <errno.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43 #include <signal.h>
44 #include "../../dprint.h"
45 #include "../../ut.h"
46 #include "../../hash_func.h"
47 #include "../../md5utils.h"
48 #include "../../mem/mem.h"
49 #include "../../fifo_server.h"
50 #include "../../error.h"
51 #include "t_funcs.h"
52 #include "config.h"
53 #include "sip_msg.h"
54 #include "ut.h"
55 #include "t_msgbuilder.h"
56 #include "uac.h"
57
58 /* Call-ID has the following form: call_id_rand-pid-seq */
59
60 char call_id[RAND_DIGITS+1+MAX_PID_LEN+1+MAX_SEQ_LEN+1];
61 static unsigned long callid_seq;
62
63 char *uac_from="\"UAC Account\" <sip:uac@dev.null:9>";
64
65 char from_tag[ MD5_LEN +1];
66
67 void uac_init() {
68         unsigned long init_nr;
69         char *c;
70         int len;
71
72         str src[3];
73
74         init_nr=random() % (1<<(RAND_DIGITS*4));
75         c=call_id;
76         len=RAND_DIGITS;
77         int2reverse_hex( &c, &len, init_nr );
78         while (len) { *c='z'; len--; c++; }
79         *c='-';
80
81         src[0].s="Long live SER server";
82         src[0].len=strlen(src[0].s);
83         src[1].s=sock_info[0].address_str.s;
84         src[1].len=strlen(src[1].s);
85         src[2].s=sock_info[0].port_no_str.s;
86         src[2].len=strlen(src[2].s);
87
88         MDStringArray( from_tag, src, 3 );
89         from_tag[MD5_LEN]=0;
90 }
91
92
93 void uac_child_init( int rank ) {
94         int pid_nr;
95         char *c;
96         int len;
97
98         pid_nr=getpid() % (1<<(MAX_PID_LEN*4));
99         c=call_id+RAND_DIGITS+1;
100         len=MAX_PID_LEN;
101         int2reverse_hex( &c, &len, pid_nr );
102         while (len) { *c='z'; len--; c++; }
103         *c='-';
104
105         callid_seq=random() % TABLE_ENTRIES;
106
107 }
108
109 void generate_callid() {
110         char *c;
111         int len;
112
113         /* HACK: not long enough */
114         callid_seq = (callid_seq+1) % TABLE_ENTRIES;
115         c=call_id+RAND_DIGITS+1+MAX_PID_LEN+1;
116         len=MAX_SEQ_LEN;
117         int2reverse_hex( &c, &len, callid_seq );
118         while (len) { *c='z'; len--; c++; }
119 }
120
121
122
123 int t_uac( str *msg_type, str *dst, 
124         str *headers, str *body, str *from, 
125         transaction_cb completion_cb, void *cbp, 
126         dlg_t dlg)
127 {
128
129         struct cell *new_cell;
130         struct proxy_l *proxy;
131         int branch;
132         int ret;
133         int req_len;
134         char *buf;
135         union sockaddr_union to;
136         struct socket_info* send_sock;
137         struct retr_buf *request;
138         str dummy_from;
139
140         proxy=uri2proxy( dst );
141         if (proxy==0) {
142                 ser_error=ret=E_BAD_ADDRESS;
143                 LOG(L_ERR, "ERROR: t_uac: can't create a dst proxy\n");
144                 goto done;
145         }
146         branch=0;
147         /* might go away -- we ignore it in send_pr_buffer anyway */
148         /* T->uac[branch].request.to_len=sizeof(union sockaddr_union); */
149         hostent2su(&to, &proxy->host, proxy->addr_idx, 
150                 (proxy->port)?htons(proxy->port):htons(SIP_PORT));
151         send_sock=get_send_socket( &to );
152         if (send_sock==0) {
153                 LOG(L_ERR, "ERROR: t_uac: no corresponding listening socket "
154                         "for af %d\n", to.s.sa_family );
155                 ret=E_NO_SOCKET;
156                 goto error00;
157         }
158         generate_callid();
159
160         new_cell = build_cell( NULL ) ; 
161         if (!new_cell) {
162                 ret=E_OUT_OF_MEM;
163                 LOG(L_ERR, "ERROR: t_uac: short of cell shmem\n");
164                 goto error00;
165         }
166         new_cell->completion_cb=completion_cb;
167         new_cell->cbp=cbp;
168         /* cbp is installed -- tell error handling bellow not to free it */
169         cbp=0;
170         new_cell->is_invite=msg_type->len==INVITE_LEN 
171                 && memcmp(msg_type->s, INVITE, INVITE_LEN)==0;
172         new_cell->local=1;
173         new_cell->kr=REQ_FWDED;
174
175
176         request=&new_cell->uac[branch].request;
177         request->to=to;
178         request->send_sock=send_sock;
179
180         /* need to put in table to calculate label which is needed for printing */
181         LOCK_HASH(new_cell->hash_index);
182         insert_into_hash_table_unsafe(  new_cell );
183         UNLOCK_HASH(new_cell->hash_index);
184
185         if (from) dummy_from=*from; else { dummy_from.s=0; dummy_from.len=0; }
186         buf=build_uac_request(  *msg_type, *dst, dummy_from, *headers, *body, branch,
187                 new_cell /* t carries hash_index, label, md5, uac[].send_sock and
188                      other pieces of information needed to print a message*/
189                 , &req_len );
190     if (!buf) {
191         ret=E_OUT_OF_MEM;
192         LOG(L_ERR, "ERROR: t_uac: short of req shmem\n");
193         goto error01;
194     }      
195         new_cell->method.s=buf;new_cell->method.len=msg_type->len;
196
197
198         request->buffer = buf;
199         request->buffer_len = req_len;
200         new_cell->nr_of_outgoings++;
201
202
203         proxy->tx++;
204         proxy->tx_bytes+=req_len;
205
206         if (SEND_BUFFER( request)==-1) {
207                 LOG(L_ERR, "ERROR: t_uac: UAC sending to %.*s failed\n",
208                         dst->len, dst->s );
209                 proxy->errors++;
210                 proxy->ok=0;
211         }
212         start_retr( request );
213
214         /* success */
215         return 1;
216
217 error01:
218         LOCK_HASH(new_cell->hash_index);
219         remove_from_hash_table_unsafe( new_cell );
220         UNLOCK_HASH(new_cell->hash_index);
221         free_cell(new_cell);
222 error00:
223         free_proxy( proxy );
224         free( proxy );
225 done: 
226         /* if we did not install cbp, release it now */
227         if (cbp) shm_free(cbp);
228         return ser_error=ret;
229 }
230
231 static void fifo_callback( struct cell *t, struct sip_msg *msg,
232         int code, void *param)
233 {
234
235         char *filename;
236         str text;
237
238         DBG("DEBUG: fifo UAC completed with status %d\n", code);
239         if (!t->cbp) {
240                 LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", code);
241                 return;
242         }
243
244         filename=(char *)(t->cbp);
245         get_reply_status(&text,msg,code);
246         if (text.s==0) {
247                 LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n");
248                 fifo_reply(filename, "ERROR: fifo_callback: get_reply_status failed\n");
249                 return;
250         }
251         fifo_reply(filename, "%.*s", text.len, text.s );
252         pkg_free(text.s);
253         DBG("DEBUG: fifo_callback sucesssfuly completed\n");
254 }       
255
256 /* to be obsoleted in favor of fifo_uac_from */
257 int fifo_uac( FILE *stream, char *response_file ) 
258 {
259         char method[MAX_METHOD];
260         char header[MAX_HEADER];
261         char body[MAX_BODY];
262         char dst[MAX_DST];
263         str sm, sh, sb, sd;
264         char *shmem_file;
265         int fn_len;
266         int ret;
267         int sip_error;
268         char err_buf[MAX_REASON_LEN];
269
270         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;
271         if (!read_line(method, MAX_METHOD, stream,&sm.len)||sm.len==0) {
272                 /* line breaking must have failed -- consume the rest
273                    and proceed to a new request
274                 */
275                 LOG(L_ERR, "ERROR: fifo_uac: method expected\n");
276                 fifo_reply(response_file, 
277                         "ERROR: fifo_uac: method expected");
278                 return -1;
279         }
280         DBG("DEBUG: fifo_uac: method: %.*s\n", sm.len, method );
281         if (!read_line(dst, MAX_DST, stream, &sd.len)||sd.len==0) {
282                 fifo_reply(response_file, 
283                         "ERROR: fifo_uac: destination expected\n");
284                 LOG(L_ERR, "ERROR: fifo_uac: destination expected\n");
285                 return -1;
286         }
287         DBG("DEBUG: fifo_uac:  dst: %.*s\n", sd.len, dst );
288         /* now read header fields line by line */
289         if (!read_line_set(header, MAX_HEADER, stream, &sh.len)) {
290                 fifo_reply(response_file, 
291                         "ERROR: fifo_uac: HFs expected\n");
292                 LOG(L_ERR, "ERROR: fifo_uac: header fields expected\n");
293                 return -1;
294         }
295         DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header );
296         /* and eventually body */
297         if (!read_body(body, MAX_BODY, stream, &sb.len)) {
298                 fifo_reply(response_file, 
299                         "ERROR: fifo_uac: body expected\n");
300                 LOG(L_ERR, "ERROR: fifo_uac: body expected\n");
301                 return -1;
302         }
303         DBG("DEBUG: fifo_uac: body: %.*s\n", sb.len, body );
304         DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
305         /* we got it all, initiate transaction now! */
306         if (response_file) {
307                 fn_len=strlen(response_file)+1;
308                 shmem_file=shm_malloc(fn_len);
309                 if (shmem_file==0) {
310                         LOG(L_ERR, "ERROR: fifo_uac: no shmem\n");
311                         return -1;
312                 }
313                 memcpy(shmem_file, response_file, fn_len );
314         } else {
315                 shmem_file=0;
316         }
317         ret=t_uac(&sm,&sd,&sh,&sb, 0 /* default from */,
318                 fifo_callback,shmem_file,0 /* no dialog */);
319         if (ret>0) {
320                 if (err2reason_phrase(ret, &sip_error, err_buf,
321                                 sizeof(err_buf), "FIFO/UAC" ) > 0 ) 
322                 {
323                         fifo_reply(response_file, "FIFO/UAC error: %d\n",
324                                 ret );
325                 } else {
326                         fifo_reply(response_file, err_buf );
327                 }
328         }
329         return 1;
330 }
331
332 /* syntax:
333
334         :t_uac_from:[file] EOL
335         method EOL
336         [from] EOL (if none, server's default from is taken)
337         dst EOL (put in r-uri and To)
338         [CR-LF separated HFs]* EOL
339         EOL
340         [body] EOL
341         EOL
342
343 */
344
345 int fifo_uac_from( FILE *stream, char *response_file ) 
346 {
347         char method[MAX_METHOD];
348         char header[MAX_HEADER];
349         char body[MAX_BODY];
350         char dst[MAX_DST];
351         char from[MAX_FROM];
352         str sm, sh, sb, sd, sf;
353         char *shmem_file;
354         int fn_len;
355         int ret;
356         int sip_error;
357         char err_buf[MAX_REASON_LEN];
358         int err_ret;
359
360         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;sf.s=from;
361
362         if (!read_line(method, MAX_METHOD, stream,&sm.len)||sm.len==0) {
363                 /* line breaking must have failed -- consume the rest
364                    and proceed to a new request
365                 */
366                 LOG(L_ERR, "ERROR: fifo_uac: method expected\n");
367                 fifo_reply(response_file, 
368                         "ERROR: fifo_uac: method expected");
369                 return -1;
370         }
371         DBG("DEBUG: fifo_uac: method: %.*s\n", sm.len, method );
372         if (!read_line(from, MAX_FROM, stream, &sf.len)) {
373                 fifo_reply(response_file, 
374                         "ERROR: fifo_uac: from expected\n");
375                 LOG(L_ERR, "ERROR: fifo_uac: from expected\n");
376                 return -1;
377         }
378         DBG("DEBUG: fifo_uac:  from: %.*s\n", sf.len, from);
379         if (!read_line(dst, MAX_DST, stream, &sd.len)||sd.len==0) {
380                 fifo_reply(response_file, 
381                         "ERROR: fifo_uac: destination expected\n");
382                 LOG(L_ERR, "ERROR: fifo_uac: destination expected\n");
383                 return -1;
384         }
385         DBG("DEBUG: fifo_uac:  dst: %.*s\n", sd.len, dst );
386         /* now read header fields line by line */
387         if (!read_line_set(header, MAX_HEADER, stream, &sh.len)) {
388                 fifo_reply(response_file, 
389                         "ERROR: fifo_uac: HFs expected\n");
390                 LOG(L_ERR, "ERROR: fifo_uac: header fields expected\n");
391                 return -1;
392         }
393         DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header );
394         /* and eventually body */
395         if (!read_body(body, MAX_BODY, stream, &sb.len)) {
396                 fifo_reply(response_file, 
397                         "ERROR: fifo_uac: body expected\n");
398                 LOG(L_ERR, "ERROR: fifo_uac: body expected\n");
399                 return -1;
400         }
401         DBG("DEBUG: fifo_uac: body: %.*s\n", sb.len, body );
402         DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
403         /* we got it all, initiate transaction now! */
404         if (response_file) {
405                 fn_len=strlen(response_file)+1;
406                 shmem_file=shm_malloc(fn_len);
407                 if (shmem_file==0) {
408                         LOG(L_ERR, "ERROR: fifo_uac: no shmem\n");
409                         return -1;
410                 }
411                 memcpy(shmem_file, response_file, fn_len );
412         } else {
413                 shmem_file=0;
414         }
415         /* HACK: there is yet a shortcoming -- if t_uac fails, callback
416            will not be triggered and no feedback will be printed
417            to shmem_file
418         */
419         ret=t_uac(&sm,&sd,&sh,&sb, sf.len==0 ? 0 : &sf /* default from */,
420                 fifo_callback,shmem_file,0 /* no dialog */);
421         if (ret<=0) {
422                 err_ret=err2reason_phrase(ret, &sip_error, err_buf,
423                                 sizeof(err_buf), "FIFO/UAC" ) ;
424                 if (err_ret > 0 )
425                 {
426                         fifo_reply(response_file, err_buf );
427                 } else {
428                         fifo_reply(response_file, "FIFO/UAC error: %d\n",
429                                 ret );
430                 }
431         }
432         return 1;
433
434 }