ims_ipsec_pcscf: fix code formatting after merge commit 57961c9f
[kamailio] / src / modules / ims_ipsec_pcscf / ims_ipsec_pcscf_mod.c
1 /*
2  * IMS IPSEC PCSCF module
3  *
4  * Copyright (C) 2018 Tsvetomir Dimitrov
5  * Copyright (C) 2019 Aleksandar Yosifov
6  *
7  * This file is part of Kamailio, a free SIP server.
8  *
9  * Kamailio is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version
13  *
14  * Kamailio is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #include "../../core/sr_module.h"
26 #include "../../modules/tm/tm_load.h"
27 #include "../ims_usrloc_pcscf/usrloc.h"
28
29 #include "cmd.h"
30 #include "spi_gen.h"
31 #include "port_gen.h"
32
33
34 MODULE_VERSION
35
36 usrloc_api_t ul;                                                /**!< Structure containing pointers to usrloc functions*/
37 struct tm_binds tmb;                                    /**!< TM API structure */
38
39
40 str ipsec_listen_addr = STR_NULL;
41 str ipsec_listen_addr6 = STR_NULL;
42 int ipsec_client_port =  5062;
43 int ipsec_server_port =  5063;
44 int ipsec_max_connections = 2;
45 int spi_id_start = 100;
46 int spi_id_range = 1000;
47 int xfrm_user_selector = 143956232;
48
49 /*! \brief Module init & destroy function */
50 static int  mod_init(void);
51 static int  child_init(int);
52 static void mod_destroy(void);
53 static int w_create(struct sip_msg* _m, char* _d, char* _cflags);
54 static int w_forward(struct sip_msg* _m, char* _d, char* _cflags);
55 static int w_destroy(struct sip_msg* _m, char* _d, char* _cflags);
56
57 /*! \brief Fixup functions */
58 static int domain_fixup(void** param, int param_no);
59 static int save_fixup2(void** param, int param_no);
60
61 extern int bind_ipsec_pcscf(usrloc_api_t* api);
62
63 int init_flag = 0;
64
65 /*! \brief
66  * Exported functions
67  */
68 static cmd_export_t cmds[] = {
69         {"ipsec_create",  (cmd_function)w_create,  1, save_fixup2, 0, ONREPLY_ROUTE },
70         {"ipsec_forward", (cmd_function)w_forward, 1, save_fixup2, 0, REQUEST_ROUTE | ONREPLY_ROUTE },
71         {"ipsec_destroy", (cmd_function)w_destroy, 1, save_fixup2, 0, REQUEST_ROUTE | ONREPLY_ROUTE },
72     {"bind_ims_ipsec_pcscf", (cmd_function)bind_ipsec_pcscf, 1, 0, 0, 0},
73         {0, 0, 0, 0, 0, 0}
74 };
75
76 /*! \brief
77  * Exported parameters
78  */
79 static param_export_t params[] = {
80         {"ipsec_listen_addr",           PARAM_STR, &ipsec_listen_addr           },
81         {"ipsec_listen_addr6",          PARAM_STR, &ipsec_listen_addr6          },
82         {"ipsec_client_port",           INT_PARAM, &ipsec_client_port           },
83         {"ipsec_server_port",           INT_PARAM, &ipsec_server_port           },
84         {"ipsec_max_connections",       INT_PARAM, &ipsec_max_connections       },
85         {"ipsec_spi_id_start",          INT_PARAM, &spi_id_start                        },
86         {"ipsec_spi_id_range",          INT_PARAM, &spi_id_range                        },
87         {0, 0, 0}
88 };
89
90 /*! \brief
91  * Module exports structure
92  */
93 struct module_exports exports = {
94         "ims_ipsec_pcscf",
95         DEFAULT_DLFLAGS,/* dlopen flags */
96         cmds,                   /* exported functions */
97         params,                 /* exported params */
98         0,                              /*·exported·RPC·methods·*/
99         0,                              /* exported pseudo-variables */
100         0,                              /*·response·function·*/
101         mod_init,               /* module initialization function */
102         child_init,             /* Per-child init function */
103         mod_destroy,    /* destroy function */
104 };
105
106
107 static void ipsec_print_all_socket_lists()
108 {
109         struct socket_info *si;
110         struct socket_info** list;
111         struct addr_info* ai;
112         unsigned short proto;
113
114         LM_INFO("Listening on:\n");
115
116         proto=PROTO_UDP;
117         do{
118                 list=get_sock_info_list(proto);
119                 for(si=list?*list:0; si; si=si->next){
120                         char buf[1024];
121                         int cnt=0;
122
123                         memset(buf, 0, sizeof(buf));
124
125                         if(si->addr_info_lst){
126                                 sprintf(buf, "%s: (%s", get_valid_proto_name(proto), si->address_str.s);
127                                 cnt = strlen(buf);
128
129                                 for(ai=si->addr_info_lst; ai; ai=ai->next){
130                                         sprintf(buf + cnt, ", %s", ai->address_str.s);
131                                         cnt = strlen(buf);
132                                 }
133
134                                 if(si->port_no_str.s){
135                                         sprintf(buf + cnt, "):%s%s%s", si->port_no_str.s, si->flags & SI_IS_MCAST ? " mcast" : "", si->flags & SI_IS_MHOMED? " mhomed" : "");
136                                 }else{
137                                         sprintf(buf + cnt, "):%u%s%s", si->port_no, si->flags & SI_IS_MCAST ? " mcast" : "", si->flags & SI_IS_MHOMED? " mhomed" : "");
138                                 }
139                                 cnt = strlen(buf);
140                         }else{
141                                 sprintf(buf, "%s: %s", get_valid_proto_name(proto), si->name.s);
142                                 cnt = strlen(buf);
143
144                                 if(!(si->flags & SI_IS_IP)){
145                                         if(si->address_str.s){
146                                                 sprintf(buf + cnt, " [%s]", si->address_str.s);
147                                                 cnt = strlen(buf);
148                                         }
149                                 }
150
151                                 if(si->port_no_str.s){
152                                         sprintf(buf + cnt, ":%s%s%s", si->port_no_str.s, si->flags & SI_IS_MCAST ? " mcast" : "", si->flags & SI_IS_MHOMED? " mhomed" : "");
153                                 }else{
154                                         sprintf(buf + cnt, ":%u%s%s", si->port_no, si->flags & SI_IS_MCAST ? " mcast" : "", si->flags & SI_IS_MHOMED? " mhomed" : "");
155                                 }
156                                 cnt = strlen(buf);
157
158                                 if(si->useinfo.name.s){
159                                         printf(buf + cnt, " advertise %s:%d", si->useinfo.name.s, si->useinfo.port_no);
160                                         cnt = strlen(buf);
161                                 }
162                         }
163
164                         LM_INFO("%s\n", buf);
165                 }
166         }while((proto=next_proto(proto)));
167 }
168
169 static int ipsec_add_listen_ifaces()
170 {
171         char addr4[128];
172         char addr6[128];
173         int i;
174
175         for(i = 0; i < ipsec_max_connections; ++i){
176                 if(ipsec_listen_addr.len) {
177                         if(ipsec_listen_addr.len > sizeof(addr4)-1) {
178                                 LM_ERR("Bad value for ipsec listen address IPv4: %.*s\n", ipsec_listen_addr.len, ipsec_listen_addr.s);
179                                 return -1;
180                         }
181
182                         memset(addr4, 0, sizeof(addr4));
183                         memcpy(addr4, ipsec_listen_addr.s, ipsec_listen_addr.len);
184
185                         //add listen interfaces for IPv4
186                         if(add_listen_iface(addr4, NULL, ipsec_client_port + i, PROTO_TCP, 0) != 0) {
187                                 LM_ERR("Error adding listen ipsec client TCP interface for IPv4\n");
188                                 return -1;
189                         }
190
191                         if(add_listen_iface(addr4, NULL, ipsec_server_port + i, PROTO_TCP, 0) != 0) {
192                                 LM_ERR("Error adding listen ipsec server TCP interface for IPv4\n");
193                                 return -1;
194                         }
195
196                         if(add_listen_iface(addr4, NULL, ipsec_client_port + i, PROTO_UDP, 0) != 0) {
197                                 LM_ERR("Error adding listen ipsec client UDP interface for IPv4\n");
198                                 return -1;
199                         }
200
201                         if(add_listen_iface(addr4, NULL, ipsec_server_port + i, PROTO_UDP, 0) != 0) {
202                                 LM_ERR("Error adding listen ipsec server UDP interface for IPv4\n");
203                                 return -1;
204                         }
205                 }
206
207                 if(ipsec_listen_addr6.len) {
208                         if(ipsec_listen_addr6.len > sizeof(addr6)-1) {
209                                 LM_ERR("Bad value for ipsec listen address IPv6: %.*s\n", ipsec_listen_addr6.len, ipsec_listen_addr6.s);
210                                 return -1;
211                         }
212
213                         memset(addr6, 0, sizeof(addr6));
214                         memcpy(addr6, ipsec_listen_addr6.s, ipsec_listen_addr6.len);
215
216                         //add listen interfaces for IPv6
217                         if(add_listen_iface(addr6, NULL, ipsec_client_port + i, PROTO_TCP, 0) != 0) {
218                                 LM_ERR("Error adding listen ipsec client TCP interface for IPv6\n");
219                                 return -1;
220                         }
221
222                         if(add_listen_iface(addr6, NULL, ipsec_server_port + i, PROTO_TCP, 0) != 0) {
223                                 LM_ERR("Error adding listen ipsec server TCP interface for IPv6\n");
224                                 return -1;
225                         }
226
227                         if(add_listen_iface(addr6, NULL, ipsec_client_port + i, PROTO_UDP, 0) != 0) {
228                                 LM_ERR("Error adding listen ipsec client UDP interface for IPv6\n");
229                                 return -1;
230                         }
231
232                         if(add_listen_iface(addr6, NULL, ipsec_server_port + i, PROTO_UDP, 0) != 0) {
233                                 LM_ERR("Error adding listen ipsec server UDP interface for IPv6\n");
234                                 return -1;
235                         }
236                 }
237         }
238
239         if(fix_all_socket_lists() != 0) {
240                 LM_ERR("Error calling fix_all_socket_lists()\n");
241                 return -1;
242         }
243
244         ipsec_print_all_socket_lists();
245
246         return 0;
247 }
248
249 /*! \brief
250  * Initialize parent
251  */
252 static int mod_init(void) {
253         bind_usrloc_t bind_usrloc;
254
255         bind_usrloc = (bind_usrloc_t) find_export("ul_bind_ims_usrloc_pcscf", 1, 0);
256         if (!bind_usrloc) {
257                 LM_ERR("can't bind ims_usrloc_pcscf\n");
258                 return -1;
259         }
260
261         if (bind_usrloc(&ul) < 0) {
262                 return -1;
263         }
264         LM_INFO("Successfully bound to PCSCF Usrloc module\n");
265
266         /* load the TM API */
267         if (load_tm_api(&tmb) != 0) {
268                 LM_ERR("can't load TM API\n");
269                 return -1;
270         }
271         LM_INFO("Successfully bound to TM module\n");
272
273         if(ipsec_add_listen_ifaces() != 0){
274                 return -1;
275         }
276
277         if(ipsec_cleanall() != 0) {
278                 LM_ERR("Error ipsec tunnels during for module initialisation\n");
279                 return -1;
280         }
281
282         int res = 0;
283         if((res = init_spi_gen(spi_id_start, spi_id_range)) != 0) {
284                 LM_ERR("Error initialising spi generator. Error: %d\n", res);
285                 return -1;
286         }
287
288         if((res = init_port_gen(ipsec_server_port, ipsec_client_port, ipsec_max_connections)) != 0) {
289                 LM_ERR("Error initialising port generator. Error: %d\n", res);
290                 return -1;
291         }
292
293         init_flag = 1;
294
295         return 0;
296 }
297
298 static void mod_destroy(void)
299 {
300         if(ipsec_cleanall() != 0) {
301                 LM_ERR("Error ipsec tunnels during for module cleanup\n");
302         }
303
304         if(destroy_spi_gen() != 0) {
305                 LM_ERR("Error destroying spi generator\n");
306         }
307
308         if(destroy_port_gen() != 0){
309                 LM_ERR("Error destroying port generator\n");
310         }
311 }
312
313 static int child_init(int rank)
314 {
315         return 0;
316 }
317
318 /* fixups */
319 static int domain_fixup(void** param, int param_no)
320 {
321         udomain_t* d;
322
323         if (param_no == 1) {
324                 if (ul.register_udomain((char*)*param, &d) < 0) {
325                         LM_ERR("failed to register domain\n");
326                         return E_UNSPEC;
327                 }
328                 *param = (void*)d;
329         }
330         return 0;
331 }
332
333 /*! \brief
334  * Fixup for "save" function - both domain and flags
335  */
336 static int save_fixup2(void** param, int param_no)
337 {
338         if (param_no == 1) {
339                 return domain_fixup(param,param_no);
340         }
341         return 0;
342 }
343
344
345 /*! \brief
346  * Wrapper to ipsec functions
347  */
348 static int w_create(struct sip_msg* _m, char* _d, char* _cflags)
349 {
350         return ipsec_create(_m, (udomain_t*)_d);
351 }
352
353 static int w_forward(struct sip_msg* _m, char* _d, char* _cflags)
354 {
355         return ipsec_forward(_m, (udomain_t*)_d);
356 }
357
358 static int w_destroy(struct sip_msg* _m, char* _d, char* _cflags)
359 {
360         return ipsec_destroy(_m, (udomain_t*)_d);
361 }