t_uac_from introduced (good for faking From via FIFO)
[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
11 #include <stdlib.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14 #include <stdio.h>
15 #include <errno.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <signal.h>
20 #include "../../dprint.h"
21 #include "../../ut.h"
22 #include "../../hash_func.h"
23 #include "../../md5utils.h"
24 #include "../../mem/mem.h"
25 #include "../../fifo_server.h"
26 #include "../../error.h"
27 #include "t_funcs.h"
28 #include "config.h"
29 #include "sip_msg.h"
30 #include "ut.h"
31 #include "t_msgbuilder.h"
32 #include "uac.h"
33
34 /* Call-ID has the following form: call_id_rand-pid-seq */
35
36 char call_id[RAND_DIGITS+1+MAX_PID_LEN+1+MAX_SEQ_LEN+1];
37 static unsigned long callid_seq;
38
39 char *uac_from="\"UAC Account\" <sip:uac@dev.null:9>";
40
41 char from_tag[ MD5_LEN +1];
42
43 void uac_init() {
44         unsigned long init_nr;
45         char *c;
46         int len;
47
48         str src[3];
49
50         init_nr=random() % (1<<(RAND_DIGITS*4));
51         c=call_id;
52         len=RAND_DIGITS;
53         int2reverse_hex( &c, &len, init_nr );
54         while (len) { *c='z'; len--; c++; }
55         *c='-';
56
57         src[0].s="Long live SER server";
58         src[0].len=strlen(src[0].s);
59         src[1].s=sock_info[0].address_str.s;
60         src[1].len=strlen(src[1].s);
61         src[2].s=sock_info[0].port_no_str.s;
62         src[2].len=strlen(src[2].s);
63
64         MDStringArray( from_tag, src, 3 );
65         from_tag[MD5_LEN]=0;
66 }
67
68
69 void uac_child_init( int rank ) {
70         int pid_nr;
71         char *c;
72         int len;
73
74         pid_nr=getpid() % (1<<(MAX_PID_LEN*4));
75         c=call_id+RAND_DIGITS+1;
76         len=MAX_PID_LEN;
77         int2reverse_hex( &c, &len, pid_nr );
78         while (len) { *c='z'; len--; c++; }
79         *c='-';
80
81         callid_seq=random() % TABLE_ENTRIES;
82
83 }
84
85 void generate_callid() {
86         char *c;
87         int len;
88
89         /* HACK: not long enough */
90         callid_seq = (callid_seq+1) % TABLE_ENTRIES;
91         c=call_id+RAND_DIGITS+1+MAX_PID_LEN+1;
92         len=MAX_SEQ_LEN;
93         int2reverse_hex( &c, &len, callid_seq );
94         while (len) { *c='z'; len--; c++; }
95 }
96
97
98
99 int t_uac( str *msg_type, str *dst, 
100         str *headers, str *body, str *from, 
101         transaction_cb completion_cb, void *cbp, 
102         dlg_t dlg)
103 {
104
105         struct cell *new_cell;
106         struct proxy_l *proxy;
107         int branch;
108         int ret;
109         int req_len;
110         char *buf;
111         union sockaddr_union to;
112         struct socket_info* send_sock;
113         struct retr_buf *request;
114         str dummy_from;
115
116         /* be optimist -- assume success for return value */
117         ret=1;
118
119         proxy=uri2proxy( dst );
120         if (proxy==0) {
121                 ser_error=ret=E_BAD_ADDRESS;
122                 LOG(L_ERR, "ERROR: t_uac: can't create a dst proxy\n");
123                 goto done;
124         }
125         branch=0;
126         /* might go away -- we ignore it in send_pr_buffer anyway */
127         /* T->uac[branch].request.to_len=sizeof(union sockaddr_union); */
128         hostent2su(&to, &proxy->host, proxy->addr_idx, 
129                 (proxy->port)?htons(proxy->port):htons(SIP_PORT));
130         send_sock=get_send_socket( &to );
131         if (send_sock==0) {
132                 LOG(L_ERR, "ERROR: t_uac: no corresponding listening socket "
133                         "for af %d\n", to.s.sa_family );
134                 ret=E_NO_SOCKET;
135                 goto error00;
136         }
137         generate_callid();
138
139         new_cell = build_cell( NULL ) ; 
140         if (!new_cell) {
141                 ret=E_OUT_OF_MEM;
142                 LOG(L_ERR, "ERROR: t_uac: short of cell shmem\n");
143                 goto error00;
144         }
145         new_cell->completion_cb=completion_cb;
146         new_cell->cbp=cbp;
147         /* cbp is installed -- tell error handling bellow not to free it */
148         cbp=0;
149         new_cell->is_invite=msg_type->len==INVITE_LEN 
150                 && memcmp(msg_type->s, INVITE, INVITE_LEN)==0;
151         new_cell->local=1;
152         LOCK_HASH(new_cell->hash_index);
153         insert_into_hash_table_unsafe(  new_cell );
154         UNLOCK_HASH(new_cell->hash_index);
155
156         request=&new_cell->uac[branch].request;
157         request->to=to;
158         request->send_sock=send_sock;
159
160         if (from) dummy_from=*from; else { dummy_from.s=0; dummy_from.len=0; }
161         buf=build_uac_request(  *msg_type, *dst, dummy_from, *headers, *body, branch,
162                 new_cell /* t carries hash_index, label, md5, uac[].send_sock and
163                      other pieces of information needed to print a message*/
164                 , &req_len );
165     if (!buf) {
166         ret=E_OUT_OF_MEM;
167         LOG(L_ERR, "ERROR: t_uac: short of req shmem\n");
168         goto error01;
169     }      
170         new_cell->method.s=buf;new_cell->method.len=msg_type->len;
171
172         request->buffer = buf;
173         request->buffer_len = req_len;
174         new_cell->nr_of_outgoings++;
175
176         proxy->tx++;
177         proxy->tx_bytes+=req_len;
178
179         if (SEND_BUFFER( request)==-1) {
180                 LOG(L_ERR, "ERROR: t_uac: UAC sending to %.*s failed\n",
181                         dst->len, dst->s );
182                 proxy->errors++;
183                 proxy->ok=0;
184                 ser_error=ret=E_SEND;
185                 goto error01;
186         }
187         start_retr( request );
188
189         /* success */
190         goto done;
191
192 error01: 
193         /* this is the safest way (though not the cheapest) to
194            make a transaction disappear; we may appreciate the
195            safety later when we add more complexity
196         */
197         cleanup_uac_timers(new_cell);
198         put_on_wait(new_cell);
199 error00:
200         free_proxy( proxy );
201         free( proxy );
202 done: 
203         /* if we did not install cbp, release it now */
204         if (cbp) shm_free(cbp);
205         return ser_error=ret;
206 }
207
208 static void fifo_callback( struct cell *t, struct sip_msg *msg,
209         int code, void *param)
210 {
211
212         char *filename;
213         int file;
214         int r;
215         str text;
216
217         DBG("DEBUG: fifo UAC completed with status %d\n", code);
218         if (t->cbp) {
219                 filename=(char *)(t->cbp);
220                 file=open(filename, O_WRONLY);
221                 if (file<0) {
222                         LOG(L_ERR, "ERROR: fifo_callback: can't open file %s: %s\n",
223                                 filename, strerror(errno));
224                         return;
225                 }
226                 get_reply_status(&text,msg,code);
227                 if (text.s==0) {
228                         LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n");
229                         return;
230                 }
231                 r=write(file, text.s , text.len );
232                 close(file);
233                 pkg_free(text.s);
234                 if (r<0) {
235                         LOG(L_ERR, "ERROR: fifo_callback: write error: %s\n",
236                                 strerror(errno));
237                         return; 
238                 }
239         } else {
240                 LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", code);
241         }
242 }       
243
244 /* to be obsoleted in favor of fifo_uac_from */
245 int fifo_uac( FILE *stream, char *response_file ) 
246 {
247         char method[MAX_METHOD];
248         char header[MAX_HEADER];
249         char body[MAX_BODY];
250         char dst[MAX_DST];
251         str sm, sh, sb, sd;
252         char *shmem_file;
253         int fn_len;
254
255         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;
256         while(1) {
257                 if (!read_line(method, MAX_METHOD, stream,&sm.len)||sm.len==0) {
258                         /* line breaking must have failed -- consume the rest
259                            and proceed to a new request
260                         */
261                         LOG(L_ERR, "ERROR: fifo_uac: method expected\n");
262                         fifo_reply(response_file, 
263                                 "ERROR: fifo_uac: method expected");
264                         return -1;
265                 }
266                 DBG("DEBUG: fifo_uac: method: %.*s\n", sm.len, method );
267                 if (!read_line(dst, MAX_DST, stream, &sd.len)||sd.len==0) {
268                         fifo_reply(response_file, 
269                                 "ERROR: fifo_uac: destination expected\n");
270                         LOG(L_ERR, "ERROR: fifo_uac: destination expected\n");
271                         return -1;
272                 }
273                 DBG("DEBUG: fifo_uac:  dst: %.*s\n", sd.len, dst );
274                 /* now read header fields line by line */
275                 if (!read_line_set(header, MAX_HEADER, stream, &sh.len)) {
276                         fifo_reply(response_file, 
277                                 "ERROR: fifo_uac: HFs expected\n");
278                         LOG(L_ERR, "ERROR: fifo_uac: header fields expected\n");
279                         return -1;
280                 }
281                 DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header );
282                 /* and eventually body */
283                 if (!read_body(body, MAX_BODY, stream, &sb.len)) {
284                         fifo_reply(response_file, 
285                                 "ERROR: fifo_uac: body expected\n");
286                         LOG(L_ERR, "ERROR: fifo_uac: body expected\n");
287                         return -1;
288                 }
289                 DBG("DEBUG: fifo_uac: body: %.*s\n", sb.len, body );
290                 DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
291                 /* we got it all, initiate transaction now! */
292                 if (response_file) {
293                         fn_len=strlen(response_file)+1;
294                         shmem_file=shm_malloc(fn_len);
295                         if (shmem_file==0) {
296                                 LOG(L_ERR, "ERROR: fifo_uac: no shmem\n");
297                                 return -1;
298                         }
299                         memcpy(shmem_file, response_file, fn_len );
300                 } else {
301                         shmem_file=0;
302                 }
303                 /* HACK: there is yet a shortcoming -- if t_uac fails, callback
304                    will not be triggered and no feedback will be printed
305                    to shmem_file
306                 */
307                 t_uac(&sm,&sd,&sh,&sb, 0 /* default from */,
308                         fifo_callback,shmem_file,0 /* no dialog */);
309                 return 1;
310
311         }
312 }
313
314 /* syntax:
315
316         :t_uac_from:[file] EOL
317         method EOL
318         [from] EOL (if none, server's default from is taken)
319         dst EOL (put in r-uri and To)
320         [CR-LF separated HFs]* EOL
321         EOL
322         [body] EOL
323         EOL
324
325 */
326
327 int fifo_uac_from( FILE *stream, char *response_file ) 
328 {
329         char method[MAX_METHOD];
330         char header[MAX_HEADER];
331         char body[MAX_BODY];
332         char dst[MAX_DST];
333         char from[MAX_FROM];
334         str sm, sh, sb, sd, sf;
335         char *shmem_file;
336         int fn_len;
337
338         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;sf.s=from;
339         while(1) {
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                                 "ERROR: fifo_uac: method expected");
347                         return -1;
348                 }
349                 DBG("DEBUG: fifo_uac: method: %.*s\n", sm.len, method );
350                 if (!read_line(from, MAX_FROM, stream, &sf.len)) {
351                         fifo_reply(response_file, 
352                                 "ERROR: fifo_uac: from expected\n");
353                         LOG(L_ERR, "ERROR: fifo_uac: from expected\n");
354                         return -1;
355                 }
356                 DBG("DEBUG: fifo_uac:  from: %.*s\n", sf.len, from);
357                 if (!read_line(dst, MAX_DST, stream, &sd.len)||sd.len==0) {
358                         fifo_reply(response_file, 
359                                 "ERROR: fifo_uac: destination expected\n");
360                         LOG(L_ERR, "ERROR: fifo_uac: destination expected\n");
361                         return -1;
362                 }
363                 DBG("DEBUG: fifo_uac:  dst: %.*s\n", sd.len, dst );
364                 /* now read header fields line by line */
365                 if (!read_line_set(header, MAX_HEADER, stream, &sh.len)) {
366                         fifo_reply(response_file, 
367                                 "ERROR: fifo_uac: HFs expected\n");
368                         LOG(L_ERR, "ERROR: fifo_uac: header fields expected\n");
369                         return -1;
370                 }
371                 DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header );
372                 /* and eventually body */
373                 if (!read_body(body, MAX_BODY, stream, &sb.len)) {
374                         fifo_reply(response_file, 
375                                 "ERROR: fifo_uac: body expected\n");
376                         LOG(L_ERR, "ERROR: fifo_uac: body expected\n");
377                         return -1;
378                 }
379                 DBG("DEBUG: fifo_uac: body: %.*s\n", sb.len, body );
380                 DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
381                 /* we got it all, initiate transaction now! */
382                 if (response_file) {
383                         fn_len=strlen(response_file)+1;
384                         shmem_file=shm_malloc(fn_len);
385                         if (shmem_file==0) {
386                                 LOG(L_ERR, "ERROR: fifo_uac: no shmem\n");
387                                 return -1;
388                         }
389                         memcpy(shmem_file, response_file, fn_len );
390                 } else {
391                         shmem_file=0;
392                 }
393                 /* HACK: there is yet a shortcoming -- if t_uac fails, callback
394                    will not be triggered and no feedback will be printed
395                    to shmem_file
396                 */
397                 t_uac(&sm,&sd,&sh,&sb, sf.len==0 ? 0 : &sf /* default from */,
398                         fifo_callback,shmem_file,0 /* no dialog */);
399                 return 1;
400
401         }
402 }