- fixed cfg.y for icc (hack)
[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 <limits.h>
45 #include "../../dprint.h"
46 #include "../../ut.h"
47 #include "../../hash_func.h"
48 #include "../../md5utils.h"
49 #include "../../mem/mem.h"
50 #include "../../fifo_server.h"
51 #include "../../error.h"
52 #include "../../pt.h"
53 #include "../../crc.h"
54 #include "t_funcs.h"
55 #include "config.h"
56 #include "sip_msg.h"
57 #include "ut.h"
58 #include "t_msgbuilder.h"
59 #include "uac.h"
60
61 /* Call-ID has the following form: <callid_nr>-<pid>@<ip>
62  * callid_nr is initialized as a random number and continually
63  * increases; -<pid>@<ip> is kept in callid_suffix
64  */
65
66 #define CALLID_SUFFIX_LEN (1 /* - */ + 5 /* pid */ \
67         + 42 /* embedded v4inv6 address can be looong '128.' */ \
68         + 2 /* parenthessis [] */ + 1 /* ZT 0 */ \
69         + 16 /* one never knows ;-) */ )
70 #define CALLID_NR_LEN 20
71
72 /* the character which separates random from constant part */
73 #define CID_SEP '-'
74
75 /* length of FROM tags */
76 #define FROM_TAG_LEN (MD5_LEN +1 /* - */ + CRC16_LEN)
77
78 static unsigned long callid_nr;
79 static char *callid_suffix;
80 static int callid_suffix_len;
81 static int rand_len;    /* number of chars to display max rand */
82 static char callid[CALLID_NR_LEN+CALLID_SUFFIX_LEN];
83
84 char *uac_from="\"UAC Account\" <sip:uac@dev.null:9>";
85
86 static char from_tag[ FROM_TAG_LEN+1 ];
87
88
89
90 int uac_init() {
91
92         int i; 
93         unsigned long uli;
94         int rand_len_bits;
95         int rand_cnt; /* number of rands() to be long enough */
96         int rand_bits; /* length of rands() in bits */
97         str src[3];
98
99         if (RAND_MAX<TABLE_ENTRIES) {
100                 LOG(L_WARN, "Warning: uac does not spread "
101                         "accross the whole hash table\n");
102         }
103
104         /* calculate the initial call-id */
105
106         /* how many bits and chars do we need to display the 
107          * whole ULONG number */
108         for (rand_len_bits=0,uli=ULONG_MAX;uli;
109                         uli>>=1, rand_len_bits++ );
110         rand_len=rand_len_bits/4;
111         if (rand_len>CALLID_NR_LEN) {
112                 LOG(L_ERR, "ERROR: Too small callid buffer\n");
113                 return -1;
114         }
115
116         /* how long are the rand()s ? */
117         for (rand_bits=0,i=RAND_MAX;i;i>>=1,rand_bits++);
118         /* how many rands() fit in the ULONG ? */
119         rand_cnt=rand_len_bits / rand_bits;
120
121         /* now fill in the callid with as many random
122          * numbers as you can + 1 */
123         callid_nr=rand(); /* this is the + 1 */
124         while(rand_cnt) {
125                 rand_cnt--;
126                 callid_nr<<=rand_bits;
127                 callid_nr|=rand();
128         }
129         callid_suffix=callid+rand_len;
130         DBG("CALLID initialization: %lx (len=%d)\n", 
131                         callid_nr, rand_len );
132         DBG("CALLID0=%0*lx\n", rand_len, callid_nr );
133
134
135         /* calculate the initial From tag */
136
137         src[0].s="Long live SER server";
138         src[0].len=strlen(src[0].s);
139         src[1].s=sock_info[bind_idx].address_str.s;
140         src[1].len=strlen(src[1].s);
141         src[2].s=sock_info[bind_idx].port_no_str.s;
142         src[2].len=strlen(src[2].s);
143
144         MDStringArray( from_tag, src, 3 );
145         from_tag[MD5_LEN]=CID_SEP;
146
147         return 1;
148 }
149
150
151 int uac_child_init( int rank ) 
152 {
153         callid_suffix_len=snprintf(callid_suffix,CALLID_SUFFIX_LEN,
154                         "%c%d@%.*s", CID_SEP, my_pid(), 
155                         sock_info[bind_idx].address_str.len,
156                         sock_info[bind_idx].address_str.s );
157         if (callid_suffix_len==-1) {
158                 LOG(L_ERR, "ERROR: uac_child_init: buffer too small\n");
159                 return -1;
160         }
161         DBG("DEBUG: callid_suffix: %s\n", callid_suffix );
162         return 1;
163 }
164
165 int t_uac( str *msg_type, str *dst, 
166         str *headers, str *body, str *from, 
167         transaction_cb completion_cb, void *cbp, 
168         dlg_t dlg)
169 {
170
171         int r;
172         struct cell *new_cell;
173         struct proxy_l *proxy;
174         int branch;
175         int ret;
176         unsigned int req_len;
177         char *buf;
178         union sockaddr_union to;
179         struct socket_info* send_sock;
180         struct retr_buf *request;
181         str dummy_from;
182         str callid_s;
183         str fromtag;
184
185         /* make -Wall shut up */
186         ret=0;
187
188         proxy=uri2proxy( dst );
189         if (proxy==0) {
190                 ser_error=ret=E_BAD_ADDRESS;
191                 LOG(L_ERR, "ERROR: t_uac: can't create a dst proxy\n");
192                 goto done;
193         }
194         branch=0;
195         /* might go away -- we ignore it in send_pr_buffer anyway */
196         /* T->uac[branch].request.to_len=sizeof(union sockaddr_union); */
197         hostent2su(&to, &proxy->host, proxy->addr_idx, 
198                 (proxy->port)?htons(proxy->port):htons(SIP_PORT));
199         send_sock=get_send_socket( &to );
200         if (send_sock==0) {
201                 LOG(L_ERR, "ERROR: t_uac: no corresponding listening socket "
202                         "for af %d\n", to.s.sa_family );
203                 ret=E_NO_SOCKET;
204                 goto error00;
205         }
206
207         /* update callid */
208         /* generate_callid(); */
209         callid_nr++;
210         r=snprintf(callid, rand_len+1, "%0*lx", rand_len, callid_nr );
211         if (r==-1) {
212                 LOG(L_CRIT, "BUG: SORRY, callid calculation failed\n");
213                 goto error00;
214         }
215         /* fix the ZT 0 */
216         callid[rand_len]=CID_SEP;
217         callid_s.s=callid;
218         callid_s.len=rand_len+callid_suffix_len;
219         DBG("DEBUG: sufix_len = %d\n",callid_suffix_len);
220         DBG("DEBUG: NEW CALLID:%.*s[%d]:\n", callid_s.len, callid_s.s 
221                 , callid_s.len);
222         new_cell = build_cell( NULL ) ; 
223         if (!new_cell) {
224                 ret=E_OUT_OF_MEM;
225                 LOG(L_ERR, "ERROR: t_uac: short of cell shmem\n");
226                 goto error00;
227         }
228         new_cell->completion_cb=completion_cb;
229         new_cell->cbp=cbp;
230         /* cbp is installed -- tell error handling bellow not to free it */
231         cbp=0;
232         new_cell->is_invite=msg_type->len==INVITE_LEN 
233                 && memcmp(msg_type->s, INVITE, INVITE_LEN)==0;
234         new_cell->local=1;
235         new_cell->kr=REQ_FWDED;
236
237
238         request=&new_cell->uac[branch].request;
239         request->to=to;
240         request->send_sock=send_sock;
241
242         /* need to put in table to calculate label which is needed for printing */
243         LOCK_HASH(new_cell->hash_index);
244         insert_into_hash_table_unsafe(  new_cell );
245         UNLOCK_HASH(new_cell->hash_index);
246
247         if (from) dummy_from=*from; else { dummy_from.s=0; dummy_from.len=0; }
248         /* calculate from tag from callid */
249         crcitt_string_array(&from_tag[MD5_LEN+1], &callid_s, 1 );
250         fromtag.s=from_tag; fromtag.len=FROM_TAG_LEN;
251         buf=build_uac_request(  *msg_type, *dst, 
252                         dummy_from, fromtag,
253                         DEFAULT_CSEQ, callid_s, 
254                         *headers, *body, branch,
255                         new_cell, /* t carries hash_index, label, md5,
256                                 uac[].send_sock and other pieces of
257                                 information needed to print a message*/
258                 &req_len );
259         if (!buf) {
260                 ret=E_OUT_OF_MEM;
261                 LOG(L_ERR, "ERROR: t_uac: short of req shmem\n");
262                 goto error01;
263         }      
264         new_cell->method.s=buf;new_cell->method.len=msg_type->len;
265
266
267         request->buffer = buf;
268         request->buffer_len = req_len;
269         new_cell->nr_of_outgoings++;
270
271
272         proxy->tx++;
273         proxy->tx_bytes+=req_len;
274
275         if (SEND_BUFFER( request)==-1) {
276                 LOG(L_ERR, "ERROR: t_uac: UAC sending to %.*s failed\n",
277                         dst->len, dst->s );
278                 proxy->errors++;
279                 proxy->ok=0;
280         }
281         start_retr( request );
282
283         /* success */
284         return 1;
285
286 error01:
287         LOCK_HASH(new_cell->hash_index);
288         remove_from_hash_table_unsafe( new_cell );
289         UNLOCK_HASH(new_cell->hash_index);
290         free_cell(new_cell);
291 error00:
292         free_proxy( proxy );
293         free( proxy );
294 done: 
295         /* if we did not install cbp, release it now */
296         if (cbp) shm_free(cbp);
297         return ser_error=ret;
298 }
299
300 static void fifo_callback( struct cell *t, struct sip_msg *msg,
301         int code, void *param)
302 {
303
304         char *filename;
305         str text;
306
307         DBG("DEBUG: fifo UAC completed with status %d\n", code);
308         if (!t->cbp) {
309                 LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", code);
310                 return;
311         }
312
313         filename=(char *)(t->cbp);
314         get_reply_status(&text,msg,code);
315         if (text.s==0) {
316                 LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n");
317                 fifo_reply(filename, "500 fifo_callback: get_reply_status failed\n");
318                 return;
319         }
320         fifo_reply(filename, "%.*s", text.len, text.s );
321         pkg_free(text.s);
322         DBG("DEBUG: fifo_callback sucesssfuly completed\n");
323 }       
324
325 /* to be obsoleted in favor of fifo_uac_from */
326 int fifo_uac( FILE *stream, char *response_file ) 
327 {
328         char method[MAX_METHOD];
329         char header[MAX_HEADER];
330         char body[MAX_BODY];
331         char dst[MAX_DST];
332         str sm, sh, sb, sd;
333         char *shmem_file;
334         int fn_len;
335         int ret;
336         int sip_error;
337         char err_buf[MAX_REASON_LEN];
338
339         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;
340         if (!read_line(method, MAX_METHOD, stream,&sm.len)||sm.len==0) {
341                 /* line breaking must have failed -- consume the rest
342                    and proceed to a new request
343                 */
344                 LOG(L_ERR, "ERROR: fifo_uac: method expected\n");
345                 fifo_reply(response_file, 
346                         "400 fifo_uac: method expected");
347                 return 1;
348         }
349         DBG("DEBUG: fifo_uac: method: %.*s\n", sm.len, method );
350         if (!read_line(dst, MAX_DST, stream, &sd.len)||sd.len==0) {
351                 fifo_reply(response_file, 
352                         "400 fifo_uac: destination expected\n");
353                 LOG(L_ERR, "ERROR: fifo_uac: destination expected\n");
354                 return 1;
355         }
356         DBG("DEBUG: fifo_uac:  dst: %.*s\n", sd.len, dst );
357         /* now read header fields line by line */
358         if (!read_line_set(header, MAX_HEADER, stream, &sh.len)) {
359                 fifo_reply(response_file, 
360                         "400 fifo_uac: HFs expected\n");
361                 LOG(L_ERR, "ERROR: fifo_uac: header fields expected\n");
362                 return 1;
363         }
364         DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header );
365         /* and eventually body */
366         if (!read_body(body, MAX_BODY, stream, &sb.len)) {
367                 fifo_reply(response_file, 
368                         "400 fifo_uac: body expected\n");
369                 LOG(L_ERR, "ERROR: fifo_uac: body expected\n");
370                 return 1;
371         }
372         DBG("DEBUG: fifo_uac: body: %.*s\n", sb.len, body );
373         DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
374         /* we got it all, initiate transaction now! */
375         if (response_file) {
376                 fn_len=strlen(response_file)+1;
377                 shmem_file=shm_malloc(fn_len);
378                 if (shmem_file==0) {
379                         LOG(L_ERR, "ERROR: fifo_uac: no shmem\n");
380                         fifo_reply(response_file, 
381                                 "500 fifo_uac: no shmem for shmem_file\n");
382                         return 1;
383                 }
384                 memcpy(shmem_file, response_file, fn_len );
385         } else {
386                 shmem_file=0;
387         }
388         ret=t_uac(&sm,&sd,&sh,&sb, 0 /* default from */,
389                 fifo_callback,shmem_file,0 /* no dialog */);
390         if (ret>0) {
391                 if (err2reason_phrase(ret, &sip_error, err_buf,
392                                 sizeof(err_buf), "FIFO/UAC" ) > 0 ) 
393                 {
394                         fifo_reply(response_file, "500 FIFO/UAC error: %d\n",
395                                 ret );
396                 } else {
397                         fifo_reply(response_file, err_buf );
398                 }
399         }
400         return 1;
401 }
402
403 /* syntax:
404
405         :t_uac_from:[file] EOL
406         method EOL
407         [from] EOL (if none, server's default from is taken)
408         dst EOL (put in r-uri and To)
409         [CR-LF separated HFs]* EOL
410         EOL
411         [body] EOL
412         EOL
413
414 */
415
416 int fifo_uac_from( FILE *stream, char *response_file ) 
417 {
418         char method[MAX_METHOD];
419         char header[MAX_HEADER];
420         char body[MAX_BODY];
421         char dst[MAX_DST];
422         char from[MAX_FROM];
423         str sm, sh, sb, sd, sf;
424         char *shmem_file;
425         int fn_len;
426         int ret;
427         int sip_error;
428         char err_buf[MAX_REASON_LEN];
429         int err_ret;
430
431         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;sf.s=from;
432
433         if (!read_line(method, MAX_METHOD, stream,&sm.len)||sm.len==0) {
434                 /* line breaking must have failed -- consume the rest
435                    and proceed to a new request
436                 */
437                 LOG(L_ERR, "ERROR: fifo_uac: method expected\n");
438                 fifo_reply(response_file, 
439                         "400 fifo_uac: method expected");
440                 return 1;
441         }
442         DBG("DEBUG: fifo_uac: method: %.*s\n", sm.len, method );
443         if (!read_line(from, MAX_FROM, stream, &sf.len)) {
444                 fifo_reply(response_file, 
445                         "400 fifo_uac: from expected\n");
446                 LOG(L_ERR, "ERROR: fifo_uac: from expected\n");
447                 return 1;
448         }
449         DBG("DEBUG: fifo_uac:  from: %.*s\n", sf.len, from);
450         if (!read_line(dst, MAX_DST, stream, &sd.len)||sd.len==0) {
451                 fifo_reply(response_file, 
452                         "400 fifo_uac: destination expected\n");
453                 LOG(L_ERR, "ERROR: fifo_uac: destination expected\n");
454                 return 1;
455         }
456         DBG("DEBUG: fifo_uac:  dst: %.*s\n", sd.len, dst );
457         /* now read header fields line by line */
458         if (!read_line_set(header, MAX_HEADER, stream, &sh.len)) {
459                 fifo_reply(response_file, 
460                         "400 fifo_uac: HFs expected\n");
461                 LOG(L_ERR, "ERROR: fifo_uac: header fields expected\n");
462                 return 1;
463         }
464         DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header );
465         /* and eventually body */
466         if (!read_body(body, MAX_BODY, stream, &sb.len)) {
467                 fifo_reply(response_file, 
468                         "400 fifo_uac: body expected\n");
469                 LOG(L_ERR, "ERROR: fifo_uac: body expected\n");
470                 return 1;
471         }
472         DBG("DEBUG: fifo_uac: body: %.*s\n", sb.len, body );
473         DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
474         /* we got it all, initiate transaction now! */
475         if (response_file) {
476                 fn_len=strlen(response_file)+1;
477                 shmem_file=shm_malloc(fn_len);
478                 if (shmem_file==0) {
479                         LOG(L_ERR, "ERROR: fifo_uac: no shmem\n");
480                         fifo_reply(response_file, 
481                                 "500 fifo_uac: no memory for shmem_file\n");
482                         return 1;
483                 }
484                 memcpy(shmem_file, response_file, fn_len );
485         } else {
486                 shmem_file=0;
487         }
488         /* HACK: there is yet a shortcoming -- if t_uac fails, callback
489            will not be triggered and no feedback will be printed
490            to shmem_file
491         */
492         ret=t_uac(&sm,&sd,&sh,&sb, sf.len==0 ? 0 : &sf /* default from */,
493                 fifo_callback,shmem_file,0 /* no dialog */);
494         if (ret<=0) {
495                 err_ret=err2reason_phrase(ret, &sip_error, err_buf,
496                                 sizeof(err_buf), "FIFO/UAC" ) ;
497                 if (err_ret > 0 )
498                 {
499                         fifo_reply(response_file, "%d %s", sip_error, err_buf );
500                 } else {
501                         fifo_reply(response_file, "500 FIFO/UAC error: %d\n",
502                                 ret );
503                 }
504         }
505         return 1;
506
507 }