c48e5ac9ccbe6a2f13b7e4bbc36744db6971f577
[sip-router] / modules_k / registrar / save.c
1 /*
2  * $Id$
3  *
4  * Process REGISTER request and send reply
5  *
6  * Copyright (C) 2001-2003 FhG Fokus
7  * Copyright (C) 2006 Voice Sistem SRL
8  *
9  * This file is part of Kamailio, a free SIP server.
10  *
11  * Kamailio is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version
15  *
16  * Kamailio is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License 
22  * along with this program; if not, write to the Free Software 
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  *
25  * History:
26  * ----------
27  * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
28  * 2003-02-28 scrathcpad compatibility abandoned (jiri)
29  * 2003-03-21 save_noreply added, patch provided by Maxim Sobolev 
30  *            <sobomax@portaone.com> (janakj)
31  * 2005-07-11 added sip_natping_flag for nat pinging with SIP method
32  *            instead of UDP package (bogdan)
33  * 2006-04-13 added tcp_persistent_flag for keeping the TCP connection as long
34  *            as a TCP contact is registered (bogdan)
35  * 2006-11-22 save_noreply and save_memory merged into save() (bogdan)
36  * 2006-11-28 Added statistic support for the number of accepted/rejected 
37  *            registrations. (Jeffrey Magder - SOMA Networks) 
38  * 2007-02-24  sip_natping_flag moved into branch flags, so migrated to 
39  *             nathelper module (bogdan)
40  */
41 /*!
42  * \file
43  * \brief SIP registrar module - Process REGISTER request and send reply
44  * \ingroup registrar   
45  */  
46
47
48 #include "../../str.h"
49 #include "../../socket_info.h"
50 #include "../../parser/parse_allow.h"
51 #include "../../parser/parse_methods.h"
52 #include "../../parser/msg_parser.h"
53 #include "../../parser/parse_to.h"
54 #include "../../parser/parse_uri.h"
55 #include "../../dprint.h"
56 #include "../../trim.h"
57 #include "../../ut.h"
58 #include "../../qvalue.h"
59 #include "../../dset.h"
60 #include "../../mod_fix.h"
61 #include "../../lib/kcore/cmpapi.h"
62 #ifdef USE_TCP
63 #include "../../tcp_server.h"
64 #endif
65 #include "../usrloc/usrloc.h"
66 #include "common.h"
67 #include "sip_msg.h"
68 #include "rerrno.h"
69 #include "reply.h"
70 #include "reg_mod.h"
71 #include "regtime.h"
72 #include "path.h"
73 #include "save.h"
74
75 static int mem_only = 0;
76
77 /*! \brief
78  * Process request that contained a star, in that case, 
79  * we will remove all bindings with the given username 
80  * from the usrloc and return 200 OK response
81  */
82 static inline int star(udomain_t* _d, str* _a)
83 {
84         urecord_t* r;
85         ucontact_t* c;
86         
87         ul.lock_udomain(_d, _a);
88
89         if (!ul.get_urecord(_d, _a, &r)) {
90                 c = r->contacts;
91                 while(c) {
92                         if (mem_only) {
93                                 c->flags |= FL_MEM;
94                         } else {
95                                 c->flags &= ~FL_MEM;
96                         }
97                         c = c->next;
98                 }
99         } else {
100                 r = NULL;
101         }
102
103         if (ul.delete_urecord(_d, _a, r) < 0) {
104                 LM_ERR("failed to remove record from usrloc\n");
105                 
106                      /* Delete failed, try to get corresponding
107                       * record structure and send back all existing
108                       * contacts
109                       */
110                 rerrno = R_UL_DEL_R;
111                 if (!ul.get_urecord(_d, _a, &r)) {
112                         build_contact(r->contacts);
113                         ul.release_urecord(r);
114                 }
115                 ul.unlock_udomain(_d, _a);
116                 return -1;
117         }
118         ul.unlock_udomain(_d, _a);
119         return 0;
120 }
121
122
123 /*! \brief
124  */
125 static struct socket_info *get_sock_hdr(struct sip_msg *msg)
126 {
127         struct socket_info *sock;
128         struct hdr_field *hf;
129         str socks;
130         str hosts;
131         int port;
132         int proto;
133         char c;
134
135         if (parse_headers( msg, HDR_EOH_F, 0) == -1) {
136                 LM_ERR("failed to parse message\n");
137                 return 0;
138         }
139
140         for (hf=msg->headers; hf; hf=hf->next) {
141                 if (cmp_hdrname_str(&hf->name, &sock_hdr_name)==0)
142                         break;
143         }
144
145         /* hdr found? */
146         if (hf==0)
147                 return 0;
148
149         trim_len( socks.len, socks.s, hf->body );
150         if (socks.len==0)
151                 return 0;
152
153         /*FIXME: This is a hack */
154         c = socks.s[socks.len];
155         socks.s[socks.len] = '\0';
156         if (parse_phostport( socks.s, &hosts.s, &hosts.len,
157         &port, &proto)!=0) {
158                 socks.s[socks.len] = c;
159                 LM_ERR("bad socket <%.*s> in \n",
160                         socks.len, socks.s);
161                 return 0;
162         }
163         socks.s[socks.len] = c;
164         sock = grep_sock_info(&hosts,(unsigned short)port,(unsigned short)proto);
165         if (sock==0) {
166                 LM_ERR("non-local socket <%.*s>\n",     socks.len, socks.s);
167                 return 0;
168         }
169
170         LM_DBG("%d:<%.*s>:%d -> p=%p\n", proto,socks.len,socks.s,port_no,sock );
171
172         return sock;
173 }
174
175
176
177 /*! \brief
178  * Process request that contained no contact header
179  * field, it means that we have to send back a response
180  * containing a list of all existing bindings for the
181  * given username (in To HF)
182  */
183 static inline int no_contacts(udomain_t* _d, str* _a)
184 {
185         urecord_t* r;
186         int res;
187         
188         ul.lock_udomain(_d, _a);
189         res = ul.get_urecord(_d, _a, &r);
190         if (res < 0) {
191                 rerrno = R_UL_GET_R;
192                 LM_ERR("failed to retrieve record from usrloc\n");
193                 ul.unlock_udomain(_d, _a);
194                 return -1;
195         }
196         
197         if (res == 0) {  /* Contacts found */
198                 build_contact(r->contacts);
199                 ul.release_urecord(r);
200         }
201         ul.unlock_udomain(_d, _a);
202         return 0;
203 }
204
205
206
207 /*! \brief
208  * Fills the common part (for all contacts) of the info structure
209  */
210 static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c,
211                                                                                         unsigned int _e, unsigned int _f)
212 {
213         static ucontact_info_t ci;
214         static str no_ua = str_init("n/a");
215         static str callid;
216         static str path_received = {0,0};
217         static str path;
218         static str received = {0,0};
219         static int received_found;
220         static unsigned int allowed, allow_parsed;
221         static struct sip_msg *m = 0;
222         int_str val;
223
224         if (_m!=0) {
225                 memset( &ci, 0, sizeof(ucontact_info_t));
226
227                 /* Get callid of the message */
228                 callid = _m->callid->body;
229                 trim_trailing(&callid);
230                 if (callid.len > CALLID_MAX_SIZE) {
231                         rerrno = R_CALLID_LEN;
232                         LM_ERR("callid too long\n");
233                         goto error;
234                 }
235                 ci.callid = &callid;
236
237                 /* Get CSeq number of the message */
238                 if (str2int(&get_cseq(_m)->number, (unsigned int*)&ci.cseq) < 0) {
239                         rerrno = R_INV_CSEQ;
240                         LM_ERR("failed to convert cseq number\n");
241                         goto error;
242                 }
243
244                 /* set received socket */
245                 if (_m->flags&sock_flag) {
246                         ci.sock = get_sock_hdr(_m);
247                         if (ci.sock==0)
248                                 ci.sock = _m->rcv.bind_address;
249                 } else {
250                         ci.sock = _m->rcv.bind_address;
251                 }
252
253                 /* additional info from message */
254                 if (parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent &&
255                 _m->user_agent->body.len>0 && _m->user_agent->body.len<UA_MAX_SIZE) {
256                         ci.user_agent = &_m->user_agent->body;
257                 } else {
258                         ci.user_agent = &no_ua;
259                 }
260
261                 /* extract Path headers */
262                 if (path_enabled) {
263                         if (build_path_vector(_m, &path, &path_received) < 0) {
264                                 rerrno = R_PARSE_PATH;
265                                 goto error;
266                         }
267                         if (path.len && path.s) {
268                                 ci.path = &path;
269                                 /* save in msg too for reply */
270                                 if (set_path_vector(_m, &path) < 0) {
271                                         rerrno = R_PARSE_PATH;
272                                         goto error;
273                                 }
274                         }
275                 }
276
277                 ci.last_modified = act_time;
278
279                 /* set flags */
280                 ci.flags  = _f;
281                 getbflagsval(0, &ci.flags);
282
283                 /* get received */
284                 if (path_received.len && path_received.s) {
285                         ci.cflags |= ul.nat_flag;
286                         ci.received = path_received;
287                 }
288
289                 allow_parsed = 0; /* not parsed yet */
290                 received_found = 0; /* not found yet */
291                 m = _m; /* remember the message */
292         }
293
294         if(_c!=0) {
295                 /* Calculate q value of the contact */
296                 if (calc_contact_q(_c->q, &ci.q) < 0) {
297                         rerrno = R_INV_Q;
298                         LM_ERR("failed to calculate q\n");
299                         goto error;
300                 }
301
302                 /* set expire time */
303                 ci.expires = _e;
304
305                 /* Get methods of contact */
306                 if (_c->methods) {
307                         if (parse_methods(&(_c->methods->body), &ci.methods) < 0) {
308                                 rerrno = R_PARSE;
309                                 LM_ERR("failed to parse contact methods\n");
310                                 goto error;
311                         }
312                 } else {
313                         /* check on Allow hdr */
314                         if (allow_parsed == 0) {
315                                 if (m && parse_allow( m ) != -1) {
316                                         allowed = get_allow_methods(m);
317                                 } else {
318                                         allowed = ALL_METHODS;
319                                 }
320                                 allow_parsed = 1;
321                         }
322                         ci.methods = allowed;
323                 }
324
325                 /* get received */
326                 if (ci.received.len==0) {
327                         if (_c->received) {
328                                 ci.received = _c->received->body;
329                         } else {
330                                 if (received_found==0) {
331                                         memset(&val, 0, sizeof(int_str));
332                                         if (rcv_avp_name.n!=0
333                                                                 && search_first_avp(rcv_avp_type, rcv_avp_name, &val, 0)
334                                                                 && val.s.len > 0) {
335                                                 if (val.s.len>RECEIVED_MAX_SIZE) {
336                                                         rerrno = R_CONTACT_LEN;
337                                                         LM_ERR("received too long\n");
338                                                         goto error;
339                                                 }
340                                                 received = val.s;
341                                         } else {
342                                                 received.s = 0;
343                                                 received.len = 0;
344                                         }
345                                         received_found = 1;
346                                 }
347                                 ci.received = received;
348                         }
349                 }
350
351         }
352
353         return &ci;
354 error:
355         return 0;
356 }
357
358
359
360 /*! \brief
361  * Message contained some contacts, but record with same address
362  * of record was not found so we have to create a new record
363  * and insert all contacts from the message that have expires
364  * > 0
365  */
366 static inline int insert_contacts(struct sip_msg* _m, contact_t* _c,
367                                                                                                         udomain_t* _d, str* _a)
368 {
369         ucontact_info_t* ci;
370         urecord_t* r;
371         ucontact_t* c;
372         unsigned int flags;
373         int num, expires;
374 #ifdef USE_TCP
375         int e_max, tcp_check;
376         struct sip_uri uri;
377 #endif
378
379         flags = mem_only;
380 #ifdef USE_TCP
381         if ( (_m->flags&tcp_persistent_flag) &&
382         (_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS)) {
383                 e_max = 0;
384                 tcp_check = 1;
385         } else {
386                 e_max = tcp_check = 0;
387         }
388 #endif
389
390         for( num=0,r=0,ci=0 ; _c ; _c = get_next_contact(_c) ) {
391                 /* calculate expires */
392                 calc_contact_expires(_m, _c->expires, &expires);
393                 /* Skip contacts with zero expires */
394                 if (expires == 0)
395                         continue;
396
397                 if (max_contacts && (num >= max_contacts)) {
398                         LM_INFO("too many contacts (%d) for AOR <%.*s>\n", 
399                                         num, _a->len, _a->s);
400                         rerrno = R_TOO_MANY;
401                         goto error;
402                 }
403                 num++;
404
405                 if (r==0) {
406                         if (ul.insert_urecord(_d, _a, &r) < 0) {
407                                 rerrno = R_UL_NEW_R;
408                                 LM_ERR("failed to insert new record structure\n");
409                                 goto error;
410                         }
411                 }
412
413                 /* pack the contact_info */
414                 if ( (ci=pack_ci( (ci==0)?_m:0, _c, expires, flags))==0 ) {
415                         LM_ERR("failed to extract contact info\n");
416                         goto error;
417                 }
418
419                 if ( r->contacts==0 ||
420                 ul.get_ucontact(r, &_c->uri, ci->callid, ci->cseq+1, &c)!=0 ) {
421                         if (ul.insert_ucontact( r, &_c->uri, ci, &c) < 0) {
422                                 rerrno = R_UL_INS_C;
423                                 LM_ERR("failed to insert contact\n");
424                                 goto error;
425                         }
426                 } else {
427                         if (ul.update_ucontact( r, c, ci) < 0) {
428                                 rerrno = R_UL_UPD_C;
429                                 LM_ERR("failed to update contact\n");
430                                 goto error;
431                         }
432                 }
433 #ifdef USE_TCP
434                 if (tcp_check) {
435                         /* parse contact uri to see if transport is TCP */
436                         if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) {
437                                 LM_ERR("failed to parse contact <%.*s>\n", 
438                                                 _c->uri.len, _c->uri.s);
439                         } else if (uri.proto==PROTO_TCP || uri.proto==PROTO_TLS) {
440                                 if (e_max) {
441                                         LM_WARN("multiple TCP contacts on single REGISTER\n");
442                                         if (expires>e_max) e_max = expires;
443                                 } else {
444                                         e_max = expires;
445                                 }
446                         }
447                 }
448 #endif
449         }
450
451         if (r) {
452                 if (r->contacts)
453                         build_contact(r->contacts);
454                 ul.release_urecord(r);
455         }
456
457 #ifdef USE_TCP
458         if ( tcp_check && e_max>0 ) {
459                 e_max -= act_time;
460                 /*FIXME: Do we want this in the sr core?*/
461                 /*force_tcp_conn_lifetime( &_m->rcv , e_max + 10 );*/
462         }
463 #endif
464
465         return 0;
466 error:
467         if (r)
468                 ul.delete_urecord(_d, _a, r);
469         return -1;
470 }
471
472
473 static int test_max_contacts(struct sip_msg* _m, urecord_t* _r, contact_t* _c,
474                                                                                                                 ucontact_info_t *ci)
475 {
476         int num;
477         int e;
478         ucontact_t* ptr, *cont;
479         int ret;
480         
481         num = 0;
482         ptr = _r->contacts;
483         while(ptr) {
484                 if (VALID_CONTACT(ptr, act_time)) {
485                         num++;
486                 }
487                 ptr = ptr->next;
488         }
489         LM_DBG("%d valid contacts\n", num);
490         
491         for( ; _c ; _c = get_next_contact(_c) ) {
492                 /* calculate expires */
493                 calc_contact_expires(_m, _c->expires, &e);
494                 
495                 ret = ul.get_ucontact( _r, &_c->uri, ci->callid, ci->cseq, &cont);
496                 if (ret==-1) {
497                         LM_ERR("invalid cseq for aor <%.*s>\n",_r->aor.len,_r->aor.s);
498                         rerrno = R_INV_CSEQ;
499                         return -1;
500                 } else if (ret==-2) {
501                         continue;
502                 }
503                 if (ret > 0) {
504                         /* Contact not found */
505                         if (e != 0) num++;
506                 } else {
507                         if (e == 0) num--;
508                 }
509         }
510         
511         LM_DBG("%d contacts after commit\n", num);
512         if (num > max_contacts) {
513                 LM_INFO("too many contacts for AOR <%.*s>\n", _r->aor.len, _r->aor.s);
514                 rerrno = R_TOO_MANY;
515                 return -1;
516         }
517
518         return 0;
519 }
520
521
522 /*! \brief
523  * Message contained some contacts and appropriate
524  * record was found, so we have to walk through
525  * all contacts and do the following:
526  * 1) If contact in usrloc doesn't exists and
527  *    expires > 0, insert new contact
528  * 2) If contact in usrloc exists and expires
529  *    > 0, update the contact
530  * 3) If contact in usrloc exists and expires
531  *    == 0, delete contact
532  */
533 static inline int update_contacts(struct sip_msg* _m, urecord_t* _r,
534                                                                                 contact_t* _c, int _mode)
535 {
536         ucontact_info_t *ci;
537         ucontact_t *c, *ptr, *ptr0;
538         int expires, ret, updated;
539         unsigned int flags;
540 #ifdef USE_TCP
541         int e_max, tcp_check;
542         struct sip_uri uri;
543 #endif
544         int rc;
545
546         /* mem flag */
547         flags = mem_only;
548
549         rc = 0;
550         /* pack the contact_info */
551         if ( (ci=pack_ci( _m, 0, 0, flags))==0 ) {
552                 LM_ERR("failed to initial pack contact info\n");
553                 goto error;
554         }
555
556         if (max_contacts && test_max_contacts(_m, _r, _c, ci) != 0 )
557                 goto error;
558
559 #ifdef USE_TCP
560         if ( (_m->flags&tcp_persistent_flag) &&
561         (_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS)) {
562                 e_max = -1;
563                 tcp_check = 1;
564         } else {
565                 e_max = tcp_check = 0;
566         }
567 #endif
568
569         updated=0;
570         for( ; _c ; _c = get_next_contact(_c) ) {
571                 /* calculate expires */
572                 calc_contact_expires(_m, _c->expires, &expires);
573
574                 /* search for the contact*/
575                 ret = ul.get_ucontact( _r, &_c->uri, ci->callid, ci->cseq, &c);
576                 if (ret==-1) {
577                         LM_ERR("invalid cseq for aor <%.*s>\n",_r->aor.len,_r->aor.s);
578                         rerrno = R_INV_CSEQ;
579                         goto error;
580                 } else if (ret==-2) {
581                         if(expires!=0 && _mode)
582                                 break;
583                         continue;
584                 }
585
586                 if ( ret > 0 ) {
587                         /* Contact not found -> expired? */
588                         if (expires==0)
589                                 continue;
590
591                         /* pack the contact_info */
592                         if ( (ci=pack_ci( 0, _c, expires, 0))==0 ) {
593                                 LM_ERR("failed to extract contact info\n");
594                                 goto error;
595                         }
596
597                         if (ul.insert_ucontact( _r, &_c->uri, ci, &c) < 0) {
598                                 rerrno = R_UL_INS_C;
599                                 LM_ERR("failed to insert contact\n");
600                                 goto error;
601                         }
602                         rc = 1;
603                         if(_mode)
604                         {
605                                 ptr=_r->contacts;
606                                 while(ptr)
607                                 {
608                                         ptr0 = ptr;
609                                         if(ptr!=c)
610                                                 ul.delete_ucontact(_r, ptr);
611                                         ptr=ptr0->next;
612                                 }
613                                 updated=1;
614                         }
615                 } else {
616                         /* Contact found */
617                         if (expires == 0) {
618                                 /* it's expired */
619                                 if (mem_only) {
620                                         c->flags |= FL_MEM;
621                                 } else {
622                                         c->flags &= ~FL_MEM;
623                                 }
624
625                                 if (ul.delete_ucontact(_r, c) < 0) {
626                                         rerrno = R_UL_DEL_C;
627                                         LM_ERR("failed to delete contact\n");
628                                         goto error;
629                                 }
630                                 rc = 3;
631                         } else {
632                                 /* do update */
633                                 /* pack the contact specific info */
634                                 if ( (ci=pack_ci( 0, _c, expires, 0))==0 ) {
635                                         LM_ERR("failed to pack contact specific info\n");
636                                         goto error;
637                                 }
638
639                                 if(_mode)
640                                 {
641                                         ptr=_r->contacts;
642                                         while(ptr)
643                                         {
644                                                 ptr0 = ptr;
645                                                 if(ptr!=c)
646                                                         ul.delete_ucontact(_r, ptr);
647                                                 ptr=ptr0->next;
648                                         }
649                                         updated=1;
650                                 }
651                                 if (ul.update_ucontact(_r, c, ci) < 0) {
652                                         rerrno = R_UL_UPD_C;
653                                         LM_ERR("failed to update contact\n");
654                                         goto error;
655                                 }
656                                 rc = 2;
657                         }
658                 }
659 #ifdef USE_TCP
660                 if (tcp_check) {
661                         /* parse contact uri to see if transport is TCP */
662                         if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) {
663                                 LM_ERR("failed to parse contact <%.*s>\n", 
664                                                 _c->uri.len, _c->uri.s);
665                         } else if (uri.proto==PROTO_TCP || uri.proto==PROTO_TLS) {
666                                 if (e_max>0) {
667                                         LM_WARN("multiple TCP contacts on single REGISTER\n");
668                                 }
669                                 if (expires>e_max) e_max = expires;
670                         }
671                 }
672 #endif
673                 /* have one contact only -- break */
674                 if(updated)
675                         break;
676         }
677
678 #ifdef USE_TCP
679         if ( tcp_check && e_max>-1 ) {
680                 if (e_max) e_max -= act_time;
681                 /*FIXME: Do we want this in the sr core? */
682                 /*force_tcp_conn_lifetime( &_m->rcv , e_max + 10 );*/
683         }
684 #endif
685
686         return rc;
687 error:
688         return -1;
689 }
690
691
692 /*! \brief
693  * This function will process request that
694  * contained some contact header fields
695  */
696 static inline int add_contacts(struct sip_msg* _m, contact_t* _c,
697                                                                 udomain_t* _d, str* _a, int _mode)
698 {
699         int res;
700         int ret;
701         urecord_t* r;
702
703         ret = 0;
704         ul.lock_udomain(_d, _a);
705         res = ul.get_urecord(_d, _a, &r);
706         if (res < 0) {
707                 rerrno = R_UL_GET_R;
708                 LM_ERR("failed to retrieve record from usrloc\n");
709                 ul.unlock_udomain(_d, _a);
710                 return -2;
711         }
712
713         if (res == 0) { /* Contacts found */
714                 if ((ret=update_contacts(_m, r, _c, _mode)) < 0) {
715                         build_contact(r->contacts);
716                         ul.release_urecord(r);
717                         ul.unlock_udomain(_d, _a);
718                         return -3;
719                 }
720                 build_contact(r->contacts);
721                 ul.release_urecord(r);
722         } else {
723                 if (insert_contacts(_m, _c, _d, _a) < 0) {
724                         ul.unlock_udomain(_d, _a);
725                         return -4;
726                 }
727                 ret = 1;
728         }
729         ul.unlock_udomain(_d, _a);
730         return ret;
731 }
732
733
734 /*!\brief
735  * Process REGISTER request and save it's contacts
736  */
737 #define is_cflag_set(_name) (((unsigned int)(unsigned long)_cflags)&(_name))
738 int save(struct sip_msg* _m, char* _d, char* _cflags)
739 {
740         contact_t* c;
741         int st, mode;
742         str aor;
743         int ret;
744
745         rerrno = R_FINE;
746         ret = 1;
747
748         if (parse_message(_m) < 0) {
749                 goto error;
750         }
751
752         if (check_contacts(_m, &st) > 0) {
753                 goto error;
754         }
755         
756         get_act_time();
757         c = get_first_contact(_m);
758
759         if (extract_aor(&get_to(_m)->uri, &aor) < 0) {
760                 LM_ERR("failed to extract Address Of Record\n");
761                 goto error;
762         }
763
764         mem_only = is_cflag_set(REG_SAVE_MEM_FL)?FL_MEM:FL_NONE;
765
766         if (c == 0) {
767                 if (st) {
768                         if (star((udomain_t*)_d, &aor) < 0) goto error;
769                         else ret=3;
770                 } else {
771                         if (no_contacts((udomain_t*)_d, &aor) < 0) goto error;
772                         else ret=4;
773                 }
774         } else {
775                 mode = is_cflag_set(REG_SAVE_REPL_FL)?1:0;
776                 if ((ret=add_contacts(_m, c, (udomain_t*)_d, &aor, mode)) < 0)
777                         goto error;
778                 ret = (ret==0)?1:ret;
779         }
780
781         update_stat(accepted_registrations, 1);
782         /* Only send reply upon request, not upon reply */
783         if ((route_type == REQUEST_ROUTE) && !is_cflag_set(REG_SAVE_NORPL_FL) && (send_reply(_m) < 0))
784                 return -1;
785
786         return ret;
787 error:
788         update_stat(rejected_registrations, 1);
789
790         if ((route_type == REQUEST_ROUTE) && !is_cflag_set(REG_SAVE_NORPL_FL) )
791                 send_reply(_m);
792
793         return 0;
794 }
795
796 int unregister(struct sip_msg* _m, char* _d, char* _uri)
797 {
798         str aor = {0, 0};
799         str uri = {0, 0};
800
801         if(fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0)
802         {
803                 LM_ERR("invalid uri parameter\n");
804                 return -1;
805         }
806
807         if (extract_aor(&uri, &aor) < 0) {
808                 LM_ERR("failed to extract Address Of Record\n");
809                 return -1;
810         }
811
812         if (star((udomain_t*)_d, &aor) < 0)
813         {
814                 LM_ERR("error unregistering user [%.*s]\n", aor.len, aor.s);
815                 return -1;
816         }
817         return 1;
818 }
819