Registrar Fix various typos
[sip-router] / modules / registrar / registrar.c
1 /*
2  * Registrar module interface
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 /*!
25  * \defgroup registrar Registrar :: SIP Registrar support
26  * The module contains REGISTER processing logic.
27  */
28
29 /*!
30  * \file
31  * \brief SIP registrar module - interface
32  * \ingroup registrar
33  *
34  * - Module: \ref registrar
35  */
36
37 #include <stdio.h>
38 #include "../../sr_module.h"
39 #include "../../timer.h"
40 #include "../../dprint.h"
41 #include "../../error.h"
42 #include "../../socket_info.h"
43 #include "../../pvar.h"
44 #include "../../dset.h"
45 #include "../../modules/usrloc/usrloc.h"
46 #include "../../lib/kcore/statistics.h"
47 #include "../../lib/srutils/sruid.h"
48 #include "../../modules/sl/sl.h"
49 #include "../../mod_fix.h"
50 #include "../../kemi.h"
51
52 #include "save.h"
53 #include "api.h"
54 #include "lookup.h"
55 #include "regpv.h"
56 #include "reply.h"
57 #include "registrar.h"
58 #include "config.h"
59
60 MODULE_VERSION
61
62 usrloc_api_t ul;/*!< Structure containing pointers to usrloc functions*/
63
64 /*! \brief Module init & destroy function */
65 static int  mod_init(void);
66 static int  child_init(int);
67 static void mod_destroy(void);
68 static int w_save2(struct sip_msg* _m, char* _d, char* _cflags);
69 static int w_save3(struct sip_msg* _m, char* _d, char* _cflags, char* _uri);
70 static int w_lookup(struct sip_msg* _m, char* _d, char* _p2);
71 static int w_lookup_to_dset(struct sip_msg* _m, char* _d, char* _p2);
72 static int w_lookup_branches(struct sip_msg* _m, char* _d, char* _p2);
73 static int w_registered(struct sip_msg* _m, char* _d, char* _uri);
74 static int w_unregister(struct sip_msg* _m, char* _d, char* _uri);
75 static int w_unregister2(struct sip_msg* _m, char* _d, char* _uri, char *_ruid);
76 static int w_registered3(struct sip_msg* _m, char* _d, char* _uri, char* _flags);
77 static int w_registered4(struct sip_msg* _m, char* _d, char* _uri, char* _flags, char* _actionflags);
78
79 /*! \brief Fixup functions */
80 static int domain_fixup(void** param, int param_no);
81 static int domain_uri_fixup(void** param, int param_no);
82 static int save_fixup(void** param, int param_no);
83 static int unreg_fixup(void** param, int param_no);
84 static int fetchc_fixup(void** param, int param_no);
85 static int registered_fixup(void** param, int param_no);
86 /*! \brief Functions */
87 static int add_sock_hdr(struct sip_msg* msg, char *str, char *foo);
88
89 int tcp_persistent_flag = -1;                   /*!< if the TCP connection should be kept open */
90 int method_filtering = 0;                       /*!< if the looked up contacts should be filtered based on supported methods */
91 int path_enabled = 0;                           /*!< if the Path HF should be handled */
92 int path_mode = PATH_MODE_STRICT;               /*!< if the Path HF should be inserted in the reply.
93                         *   - STRICT (2): always insert, error if no support indicated in request
94                         *   - LAZY   (1): insert only if support indicated in request
95                         *   - OFF    (0): never insert */
96
97 int path_use_params = 0;                        /*!< if the received- and nat-parameters of last Path uri should be used
98                                                  * to determine if UAC is nat'ed */
99 int path_check_local = 0;
100
101 /* sruid to get internal uid */
102 sruid_t _reg_sruid;
103
104 int reg_gruu_enabled = 1;
105 int reg_outbound_mode = 0;
106 int reg_regid_mode = 0;
107 int reg_flow_timer = 0;
108
109 str match_callid_name = str_init("match_callid");
110 str match_received_name = str_init("match_received");
111 str match_contact_name = str_init("match_contact");
112
113 char* rcv_avp_param = 0;
114 unsigned short rcv_avp_type = 0;
115 int_str rcv_avp_name;
116
117 str reg_xavp_cfg = {0};
118 str reg_xavp_rcd = {0};
119
120 int reg_use_domain = 0;
121
122 int sock_flag = -1;
123 str sock_hdr_name = {0,0};
124
125 /* where to go for event route ("usrloc:contact-expired") */
126 int reg_expire_event_rt = -1; /* default disabled */
127
128 #define RCV_NAME "received"
129 str rcv_param = str_init(RCV_NAME);
130
131 stat_var *accepted_registrations;
132 stat_var *rejected_registrations;
133 stat_var *max_expires_stat;
134 stat_var *max_contacts_stat;
135 stat_var *default_expire_stat;
136 stat_var *default_expire_range_stat;
137 stat_var *expire_range_stat;
138 /** SL API structure */
139 sl_api_t slb;
140
141 /*! \brief
142  * Exported PV
143  */
144 static pv_export_t mod_pvs[] = {
145         { {"ulc", sizeof("ulc")-1}, PVT_OTHER, pv_get_ulc, pv_set_ulc,
146                 pv_parse_ulc_name, pv_parse_index, 0, 0 },
147         { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
148 };
149
150
151 /*! \brief
152  * Exported functions
153  */
154 static cmd_export_t cmds[] = {
155         {"save",         (cmd_function)w_save2,       1,  save_fixup, 0,
156                         REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
157         {"save",         (cmd_function)w_save2,       2,  save_fixup, 0,
158                         REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
159         {"save",         (cmd_function)w_save3,       3,  save_fixup, 0,
160                         REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
161         {"lookup",       (cmd_function)w_lookup,      1,  domain_uri_fixup, 0,
162                         REQUEST_ROUTE | FAILURE_ROUTE },
163         {"lookup",       (cmd_function)w_lookup,      2,  domain_uri_fixup, 0,
164                         REQUEST_ROUTE | FAILURE_ROUTE },
165         {"lookup_to_dset",  (cmd_function)w_lookup_to_dset,  1,  domain_uri_fixup, 0,
166                         REQUEST_ROUTE | FAILURE_ROUTE },
167         {"lookup_to_dset",  (cmd_function)w_lookup_to_dset,  2,  domain_uri_fixup, 0,
168                         REQUEST_ROUTE | FAILURE_ROUTE },
169         {"registered",   (cmd_function)w_registered,  1,  domain_uri_fixup, 0,
170                         ANY_ROUTE },
171         {"registered",   (cmd_function)w_registered,  2,  domain_uri_fixup, 0,
172                         ANY_ROUTE },
173         {"registered",   (cmd_function)w_registered3, 3,  registered_fixup, 0,
174                         ANY_ROUTE },
175         {"registered",   (cmd_function)w_registered4, 4,  registered_fixup, 0,
176                         ANY_ROUTE },
177         {"add_sock_hdr", (cmd_function)add_sock_hdr,  1,  fixup_str_null, 0,
178                         REQUEST_ROUTE },
179         {"unregister",   (cmd_function)w_unregister,  2,  unreg_fixup, 0,
180                         REQUEST_ROUTE| FAILURE_ROUTE },
181         {"unregister",   (cmd_function)w_unregister2, 3, unreg_fixup, 0,
182                         REQUEST_ROUTE| FAILURE_ROUTE },
183         {"reg_fetch_contacts", (cmd_function)pv_fetch_contacts, 3,
184                         fetchc_fixup, 0,
185                         REQUEST_ROUTE| FAILURE_ROUTE },
186         {"reg_free_contacts", (cmd_function)pv_free_contacts,   1,
187                         fixup_str_null, 0,
188                         REQUEST_ROUTE| FAILURE_ROUTE },
189         {"lookup_branches",  (cmd_function)w_lookup_branches, 1,  domain_uri_fixup, 0,
190                         REQUEST_ROUTE | FAILURE_ROUTE },
191         {"bind_registrar",  (cmd_function)bind_registrar,  0,
192                 0, 0, 0},
193         {0, 0, 0, 0, 0, 0}
194 };
195
196
197 /*! \brief
198  * Exported parameters
199  */
200 static param_export_t params[] = {
201         {"default_expires",    INT_PARAM, &default_registrar_cfg.default_expires                },
202         {"default_expires_range", INT_PARAM, &default_registrar_cfg.default_expires_range       },
203         {"expires_range",      INT_PARAM, &default_registrar_cfg.expires_range  },
204         {"default_q",          INT_PARAM, &default_registrar_cfg.default_q                      },
205         {"append_branches",    INT_PARAM, &default_registrar_cfg.append_branches                },
206         {"case_sensitive",     INT_PARAM, &default_registrar_cfg.case_sensitive                 },
207         /*      {"tcp_persistent_flag",INT_PARAM, &tcp_persistent_flag }, */
208         {"realm_prefix",       PARAM_STR, &default_registrar_cfg.realm_pref                     },
209         {"min_expires",        INT_PARAM, &default_registrar_cfg.min_expires                    },
210         {"max_expires",        INT_PARAM, &default_registrar_cfg.max_expires                    },
211         {"received_param",     PARAM_STR, &rcv_param                                            },
212         {"received_avp",       PARAM_STRING, &rcv_avp_param                                             },
213         {"max_contacts",       INT_PARAM, &default_registrar_cfg.max_contacts                   },
214         {"retry_after",        INT_PARAM, &default_registrar_cfg.retry_after                    },
215         {"sock_flag",          INT_PARAM, &sock_flag                                            },
216         {"sock_hdr_name",      PARAM_STR, &sock_hdr_name                                        },
217         {"method_filtering",   INT_PARAM, &method_filtering                                     },
218         {"use_path",           INT_PARAM, &path_enabled                                         },
219         {"path_mode",          INT_PARAM, &path_mode                                            },
220         {"path_use_received",  INT_PARAM, &path_use_params                                      },
221         {"path_check_local",   INT_PARAM, &path_check_local                                     },
222         {"xavp_cfg",           PARAM_STR, &reg_xavp_cfg                                         },
223         {"xavp_rcd",           PARAM_STR, &reg_xavp_rcd                                         },
224         {"gruu_enabled",       INT_PARAM, &reg_gruu_enabled                                     },
225         {"outbound_mode",      INT_PARAM, &reg_outbound_mode                                    },
226         {"regid_mode",         INT_PARAM, &reg_regid_mode                                       },
227         {"flow_timer",         INT_PARAM, &reg_flow_timer                                       },
228         {0, 0, 0}
229 };
230
231
232 /*! \brief We expose internal variables via the statistic framework below.*/
233 stat_export_t mod_stats[] = {
234         {"max_expires",       STAT_NO_RESET, &max_expires_stat        },
235         {"max_contacts",      STAT_NO_RESET, &max_contacts_stat       },
236         {"default_expire",    STAT_NO_RESET, &default_expire_stat     },
237         {"default_expires_range", STAT_NO_RESET, &default_expire_range_stat },
238         {"expires_range",     STAT_NO_RESET, &expire_range_stat },
239         {"accepted_regs",                 0, &accepted_registrations  },
240         {"rejected_regs",                 0, &rejected_registrations  },
241         {0, 0, 0}
242 };
243
244
245
246 /*! \brief
247  * Module exports structure
248  */
249 struct module_exports exports = {
250         "registrar",
251         DEFAULT_DLFLAGS, /* dlopen flags */
252         cmds,        /* Exported functions */
253         params,      /* Exported parameters */
254         mod_stats,   /* exported statistics */
255         0,           /* exported MI functions */
256         mod_pvs,     /* exported pseudo-variables */
257         0,           /* extra processes */
258         mod_init,    /* module initialization function */
259         0,
260         mod_destroy, /* destroy function */
261         child_init,  /* Per-child init function */
262 };
263
264
265 /*! \brief
266  * Initialize parent
267  */
268 static int mod_init(void)
269 {
270         pv_spec_t avp_spec;
271         str s;
272         bind_usrloc_t bind_usrloc;
273         qvalue_t dq;
274
275         if(sruid_init(&_reg_sruid, '-', "uloc", SRUID_INC) < 0) {
276                 return -1;
277         }
278
279 #ifdef STATISTICS
280         /* register statistics */
281         if (register_module_stats( exports.name, mod_stats)!=0 ) {
282                 LM_ERR("Failed to register core statistics\n");
283                 return -1;
284         }
285 #endif
286
287         /* bind the SL API */
288         if (sl_load_api(&slb)!=0) {
289                 LM_ERR("Cannot bind to SL API. Please load the SL module before loading this module.\n");
290                 return -1;
291         }
292
293         if(cfg_declare("registrar", registrar_cfg_def, &default_registrar_cfg, cfg_sizeof(registrar), &registrar_cfg)){
294                 LM_ERR("Failed to declare the configuration parameters.\n");
295                 return -1;
296         }
297
298         if (rcv_avp_param && *rcv_avp_param) {
299                 s.s = rcv_avp_param; s.len = strlen(s.s);
300                 if (pv_parse_spec(&s, &avp_spec)==0
301                                 || avp_spec.type!=PVT_AVP) {
302                         LM_ERR("malformed or non AVP %s AVP definition\n", rcv_avp_param);
303                         return -1;
304                 }
305
306                 if(pv_get_avp_name(0, &avp_spec.pvp, &rcv_avp_name, &rcv_avp_type)!=0)
307                 {
308                         LM_ERR("[%s]- invalid AVP definition\n", rcv_avp_param);
309                         return -1;
310                 }
311         } else {
312                 rcv_avp_name.n = 0;
313                 rcv_avp_type = 0;
314         }
315
316         bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);
317         if (!bind_usrloc) {
318                 LM_ERR("Can't bind to the usrloc module. Please load it before this module.\n");
319                 return -1;
320         }
321
322         /* Normalize default_q parameter */
323         dq = cfg_get(registrar, registrar_cfg, default_q);
324         if ( dq!= Q_UNSPECIFIED) {
325                 if (dq > MAX_Q) {
326                         LM_DBG("default_q = %d, lowering to MAX_Q: %d\n", dq, MAX_Q);
327                         dq = MAX_Q;
328                 } else if (dq < MIN_Q) {
329                         LM_DBG("default_q = %d, raising to MIN_Q: %d\n", dq, MIN_Q);
330                         dq = MIN_Q;
331                 }
332         }
333         cfg_get(registrar, registrar_cfg, default_q) = dq;
334
335         if (bind_usrloc(&ul) < 0) {
336                 return -1;
337         }
338
339         if(ul.register_ulcb != NULL)
340         {
341                 reg_expire_event_rt = route_lookup(&event_rt, "usrloc:contact-expired");
342                 if (reg_expire_event_rt>=0 && event_rt.rlist[reg_expire_event_rt]==0)
343                         reg_expire_event_rt=-1; /* disable */
344                 if (reg_expire_event_rt>=0) {
345                         set_child_rpc_sip_mode();
346                         if(ul.register_ulcb(UL_CONTACT_EXPIRE, reg_ul_expired_contact, 0)< 0)
347                         {
348                                 LM_ERR("Can not register callback for expired contacts (usrloc module)\n");
349                                 return -1;
350                         }
351                 }
352         }
353         /*
354          * Import use_domain parameter from usrloc
355          */
356         reg_use_domain = ul.use_domain;
357
358         if (sock_hdr_name.s) {
359                 if (sock_hdr_name.len==0 || sock_flag==-1) {
360                         LM_WARN("empty sock_hdr_name or sock_flag not set -> resetting\n");
361                         sock_hdr_name.len = 0;
362                         sock_flag = -1;
363                 }
364         } else if (reg_xavp_cfg.s) {
365                 if (reg_xavp_cfg.len == 0 || sock_flag == -1) {
366                         LM_WARN("empty reg_xavp_cfg or sock_flag not set -> resetting\n");
367                         sock_flag = -1;
368                 }
369         } else if (sock_flag!=-1) {
370                 LM_WARN("sock_flag defined but no sock_hdr_name or no reg_xavp_cfg -> resetting flag\n");
371                 sock_flag = -1;
372         }
373
374         if (reg_outbound_mode < 0 || reg_outbound_mode > 2) {
375                 LM_ERR("outbound_mode modparam must be 0 (not supported), 1 (supported), or 2 (supported and required)\n");
376                 return -1;
377         }
378
379         if (reg_regid_mode < 0 || reg_regid_mode > 1) {
380                 LM_ERR("regid_mode modparam must be 0 (use with outbound), 1 (use always)\n");
381                 return -1;
382         }
383
384         if (reg_flow_timer < 0 || reg_flow_timer > REG_FLOW_TIMER_MAX
385                         || (reg_flow_timer > 0 && reg_outbound_mode == REG_OUTBOUND_NONE)) {
386                 LM_ERR("bad value for flow_timer\n");
387                 return -1;
388         }
389
390         /* fix the flags */
391         sock_flag = (sock_flag!=-1)?(1<<sock_flag):0;
392         tcp_persistent_flag = (tcp_persistent_flag!=-1)?(1<<tcp_persistent_flag):0;
393
394         set_aor_case_sensitive(cfg_get(registrar, registrar_cfg, case_sensitive));
395
396         return 0;
397 }
398
399
400 static int child_init(int rank)
401 {
402         if(sruid_init(&_reg_sruid, '-', "uloc", SRUID_INC)<0)
403                 return -1;
404         if (rank==1) {
405                 /* init stats */
406                 //TODO if parameters are modified via cfg framework do i change them?
407                 update_stat( max_expires_stat, default_registrar_cfg.max_expires );
408                 update_stat( max_contacts_stat, default_registrar_cfg.max_contacts );
409                 update_stat( default_expire_stat, default_registrar_cfg.default_expires );
410         }
411
412         return 0;
413 }
414
415 /*! \brief
416  * Wrapper to save(location)
417  */
418 static int w_save2(struct sip_msg* _m, char* _d, char* _cflags)
419 {
420         return save(_m, (udomain_t*)_d, ((int)(unsigned long)_cflags), NULL);
421 }
422
423 /*! \brief
424  * Wrapper to save(location)
425  */
426 static int w_save3(struct sip_msg* _m, char* _d, char* _cflags, char* _uri)
427 {
428         str uri;
429         if(fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0)
430         {
431                 LM_ERR("invalid uri parameter\n");
432                 return -1;
433         }
434
435         return save(_m, (udomain_t*)_d, ((int)(unsigned long)_cflags), &uri);
436 }
437
438 /*! \brief
439  * Wrapper to lookup(location)
440  */
441 static int w_lookup(struct sip_msg* _m, char* _d, char* _uri)
442 {
443         str uri = {0};
444         if(_uri!=NULL && (fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0))
445         {
446                 LM_ERR("invalid uri parameter\n");
447                 return -1;
448         }
449
450         return lookup(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL);
451 }
452
453 /*! \brief
454  * Wrapper to lookup_to_dset(location)
455  */
456 static int w_lookup_to_dset(struct sip_msg* _m, char* _d, char* _uri)
457 {
458         str uri = {0};
459         if(_uri!=NULL && (fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0))
460         {
461                 LM_ERR("invalid uri parameter\n");
462                 return -1;
463         }
464
465         return lookup_to_dset(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL);
466 }
467
468 /*! \brief
469  * Wrapper to lookup_branches(location)
470  */
471 static int w_lookup_branches(sip_msg_t* _m, char* _d, char* _p2)
472 {
473         return lookup_branches(_m, (udomain_t*)_d);
474 }
475
476
477 static int w_registered(struct sip_msg* _m, char* _d, char* _uri)
478 {
479         str uri = {0};
480         if(_uri!=NULL && (fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0))
481         {
482                 LM_ERR("invalid uri parameter\n");
483                 return -1;
484         }
485         return registered(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL);
486 }
487
488 static int w_registered3(struct sip_msg* _m, char* _d, char* _uri, char* _flags)
489 {
490         str uri = {0};
491         int flags = 0;
492         if(_uri!=NULL && (fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0))
493         {
494                 LM_ERR("invalid uri parameter\n");
495                 return -1;
496         }
497         if(_flags!=NULL && (fixup_get_ivalue(_m, (fparam_t*)_flags, &flags)) < 0)
498         {
499                 LM_ERR("invalid flags parameter\n");
500                 return -1;
501         }
502         return registered3(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL, flags);
503 }
504
505 static int w_registered4(struct sip_msg* _m, char* _d, char* _uri, char* _flags, char* _actionflags)
506 {
507         str uri = {0};
508         int flags = 0;
509         int actionflags = 0;
510         if(_uri!=NULL && (fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0))
511         {
512                 LM_ERR("invalid uri parameter\n");
513                 return -1;
514         }
515         if(_flags!=NULL && (fixup_get_ivalue(_m, (fparam_t*)_flags, &flags)) < 0)
516         {
517                 LM_ERR("invalid flags parameter\n");
518                 return -1;
519         }
520         if(_actionflags!=NULL && (fixup_get_ivalue(_m, (fparam_t*)_actionflags, &actionflags)) < 0)
521         {
522                 LM_ERR("invalid action flag parameter\n");
523                 return -1;
524         }
525         return registered4(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL, flags, actionflags);
526 }
527
528 static int w_unregister(struct sip_msg* _m, char* _d, char* _uri)
529 {
530         str uri = {0};
531         if(fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0)
532         {
533                 LM_ERR("invalid uri parameter\n");
534                 return -1;
535         }
536
537         return unregister(_m, (udomain_t*)_d, &uri, NULL);
538 }
539
540 static int w_unregister2(struct sip_msg* _m, char* _d, char* _uri, char *_ruid)
541 {
542         str uri = {0, 0};
543         str ruid = {0};
544         if(fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0)
545         {
546                 LM_ERR("invalid uri parameter\n");
547                 return -1;
548         }
549         if(fixup_get_svalue(_m, (gparam_p)_ruid, &ruid)!=0 || ruid.len<=0)
550         {
551                 LM_ERR("invalid ruid parameter\n");
552                 return -1;
553         }
554
555
556         return unregister(_m, (udomain_t*)_d, &uri, &ruid);
557 }
558
559 /*! \brief
560  * Convert char* parameter to udomain_t* pointer
561  */
562 static int domain_fixup(void** param, int param_no)
563 {
564         udomain_t* d;
565
566         if (param_no == 1) {
567                 if (ul.register_udomain((char*)*param, &d) < 0) {
568                         LM_ERR("failed to register domain\n");
569                         return E_UNSPEC;
570                 }
571
572                 *param = (void*)d;
573         }
574         return 0;
575 }
576
577 /*! \brief
578  * Convert char* parameter to udomain_t* pointer
579  */
580 static int domain_uri_fixup(void** param, int param_no)
581 {
582         if (param_no == 1) {
583                 return domain_fixup(param, 1);
584         } else if (param_no == 2) {
585                 return fixup_spve_null(param, 1);
586         }
587         return 0;
588 }
589
590 static int registered_fixup(void** param, int param_no)
591 {
592         if (param_no == 1) {
593                 return domain_fixup(param, 1);
594         } else if (param_no == 2) {
595                 return fixup_spve_null(param, 1);
596         } else if (param_no == 3) {
597                 return fixup_igp_null(param, 1);
598         } else if (param_no == 4) {
599                 return fixup_igp_null(param, 1);
600         }
601         return 0;
602 }
603
604 /*! \brief
605  * Convert char* parameter to udomain_t* pointer
606  * Convert char* parameter to pv_elem_t* pointer
607  */
608 static int unreg_fixup(void** param, int param_no)
609 {
610         if (param_no == 1) {
611                 return domain_fixup(param, 1);
612         } else if (param_no == 2) {
613                 return fixup_spve_null(param, 1);
614         } else if (param_no == 3) {
615                 return fixup_spve_null(param, 1);
616         }
617         return 0;
618 }
619
620
621
622 /*! \brief
623  * Fixup for "save" function - both domain and flags
624  */
625 static int save_fixup(void** param, int param_no)
626 {
627         unsigned int flags;
628         str s;
629
630         if (param_no == 1) {
631                 return domain_fixup(param,param_no);
632         } else if (param_no == 2) {
633                 s.s = (char*)*param;
634                 s.len = strlen(s.s);
635                 flags = 0;
636                 if ( (strno2int(&s, &flags )<0) || (flags>REG_SAVE_ALL_FL) ) {
637                         LM_ERR("bad flags <%s>\n", (char *)(*param));
638                         return E_CFG;
639                 }
640                 if (ul.db_mode==DB_ONLY && flags&REG_SAVE_MEM_FL) {
641                         LM_ERR("MEM flag set while using the DB_ONLY mode in USRLOC\n");
642                         return E_CFG;
643                 }
644                 pkg_free(*param);
645                 *param = (void*)(unsigned long int)flags;
646         } else if (param_no == 3) {
647                 return fixup_spve_null(param, 1);
648         }
649         return 0;
650 }
651
652 /*! \brief
653  * Convert char* parameter to udomain_t* pointer
654  * Convert char* parameter to pv_elem_t* pointer
655  * Convert char* parameter to str* pointer
656  */
657 static int fetchc_fixup(void** param, int param_no)
658 {
659         if (param_no == 1) {
660                 return domain_fixup(param, 1);
661         } else if (param_no == 2) {
662                 return fixup_spve_null(param, 1);
663         } else if (param_no == 3) {
664                 return fixup_str_null(param, 1);
665         }
666         return 0;
667 }
668
669
670 static void mod_destroy(void)
671 {
672         free_contact_buf();
673 }
674
675
676 #include "../../data_lump.h"
677 #include "../../ip_addr.h"
678 #include "../../ut.h"
679
680 static int add_sock_hdr(struct sip_msg* msg, char *name, char *foo)
681 {
682         struct socket_info* si;
683         struct lump* anchor;
684         str *hdr_name;
685         str hdr;
686         char *p;
687
688         hdr_name = (str*)name;
689         si = msg->rcv.bind_address;
690
691         if (parse_headers( msg, HDR_EOH_F, 0) == -1) {
692                 LM_ERR("failed to parse message\n");
693                 goto error;
694         }
695
696         anchor = anchor_lump( msg, msg->unparsed-msg->buf, 0, 0);
697         if (anchor==0) {
698                 LM_ERR("can't get anchor\n");
699                 goto error;
700         }
701
702         hdr.len = hdr_name->len + 2 + si->sock_str.len + CRLF_LEN;
703         if ( (hdr.s=(char*)pkg_malloc(hdr.len))==0 ) {
704                 LM_ERR("no more pkg mem\n");
705                 goto error;
706         }
707
708         p = hdr.s;
709         memcpy( p, hdr_name->s, hdr_name->len);
710         p += hdr_name->len;
711         *(p++) = ':';
712         *(p++) = ' ';
713
714         memcpy( p, si->sock_str.s, si->sock_str.len);
715         p += si->sock_str.len;
716
717         memcpy( p, CRLF, CRLF_LEN);
718         p += CRLF_LEN;
719
720         if ( p-hdr.s!=hdr.len ) {
721                 LM_CRIT("buffer overflow (%d!=%d)\n", (int)(long)(p-hdr.s),hdr.len);
722                 goto error1;
723         }
724
725         if (insert_new_lump_before( anchor, hdr.s, hdr.len, 0) == 0) {
726                 LM_ERR("can't insert lump\n");
727                 goto error1;
728         }
729
730         return 1;
731 error1:
732         pkg_free(hdr.s);
733 error:
734         return -1;
735 }
736
737 void default_expires_stats_update(str* gname, str* name){
738         update_stat(default_expire_stat, cfg_get(registrar, registrar_cfg, default_expires));
739 }
740
741 void max_expires_stats_update(str* gname, str* name){
742         update_stat(max_expires_stat, cfg_get(registrar, registrar_cfg, max_expires));
743 }
744
745 void default_expires_range_update(str* gname, str* name){
746         update_stat(default_expire_range_stat, cfg_get(registrar, registrar_cfg, default_expires_range));
747 }
748
749 void expires_range_update(str* gname, str* name){
750         update_stat(expire_range_stat, cfg_get(registrar, registrar_cfg, expires_range));
751 }
752
753 /**
754  *
755  */
756 static sr_kemi_t sr_kemi_registrar_exports[] = {
757         { str_init("registrar"), str_init("save"),
758                 SR_KEMIP_INT, regapi_save,
759                 { SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_NONE,
760                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
761         },
762         { str_init("registrar"), str_init("save_uri"),
763                 SR_KEMIP_INT, regapi_save_uri,
764                 { SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_STR,
765                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
766         },
767         { str_init("registrar"), str_init("lookup"),
768                 SR_KEMIP_INT, regapi_lookup,
769                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
770                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
771         },
772         { str_init("registrar"), str_init("lookup_uri"),
773                 SR_KEMIP_INT, regapi_lookup_uri,
774                 { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
775                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
776         },
777         { str_init("registrar"), str_init("lookup_to_dset"),
778                 SR_KEMIP_INT, regapi_lookup_to_dset,
779                 { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
780                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
781         },
782         { str_init("registrar"), str_init("registered"),
783                 SR_KEMIP_INT, regapi_registered,
784                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
785                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
786         },
787
788         { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
789 };
790
791 /**
792  *
793  */
794 int mod_register(char *path, int *dlflags, void *p1, void *p2)
795 {
796         sr_kemi_modules_add(sr_kemi_registrar_exports);
797         return 0;
798 }