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