ims_ipsec_pcscf: Bug fixes and memory improvements 2023/head
authorAleksandar Yosifov <alexyosifov@gmail.com>
Fri, 2 Aug 2019 12:07:54 +0000 (15:07 +0300)
committerAleksandar Yosifov <alexyosifov@gmail.com>
Fri, 2 Aug 2019 12:13:20 +0000 (15:13 +0300)
- Fix a problem with spi_list, spi_gen and port_gen.
  Now the global data structs for SPIs and IPSec ports
  lists are placed into shared memory to be accessible
  from different processes. SPIs and IPSec ports for expired
  contacts are released properly. That process is
  performed in timer's threads and for that reason the
  global structs are placed into the shared memory.
- Add api for ipsec reconfig tunnels. Used in  registrar
  module. Improve update_contact_ipsec_params() to avoid
  memory leak if the method fails.

src/modules/ims_ipsec_pcscf/cmd.c
src/modules/ims_ipsec_pcscf/cmd.h
src/modules/ims_ipsec_pcscf/port_gen.c
src/modules/ims_ipsec_pcscf/port_gen.h
src/modules/ims_ipsec_pcscf/spi_gen.c
src/modules/ims_ipsec_pcscf/spi_gen.h
src/modules/ims_ipsec_pcscf/spi_list.c
src/modules/ims_ipsec_pcscf/spi_list.h

index 1f63ec9..c273351 100644 (file)
@@ -86,7 +86,8 @@ int bind_ipsec_pcscf(ipsec_pcscf_api_t* api) {
                return -1;
        }
 
-       api->ipsec_on_expire = ipsec_on_expire;
+       api->ipsec_on_expire    = ipsec_on_expire;
+       api->ipsec_reconfig             = ipsec_reconfig;
 
        return 0;
 }
@@ -290,19 +291,34 @@ static int update_contact_ipsec_params(ipsec_t* s, const struct sip_msg* m)
         s->ck.s = NULL; s->ck.len = 0;
         shm_free(s->ik.s);
         s->ik.s = NULL; s->ik.len = 0;
+
+               release_spi(s->spi_pc);
         return -1;
     }
 
-    s->port_pc = acquire_cport();
-    s->port_ps = acquire_sport();
-
-    if(s->port_pc == 0){
+    if((s->port_pc = acquire_cport()) == 0){
         LM_ERR("No free client port for IPSEC tunnel creation\n");
+               shm_free(s->ck.s);
+               s->ck.s = NULL; s->ck.len = 0;
+               shm_free(s->ik.s);
+               s->ik.s = NULL; s->ik.len = 0;
+
+               release_spi(s->spi_pc);
+               release_spi(s->spi_ps);
         return -1;
     }
 
-    if(s->port_ps == 0){
+    if((s->port_ps = acquire_sport()) == 0){
         LM_ERR("No free server port for IPSEC tunnel creation\n");
+               shm_free(s->ck.s);
+               s->ck.s = NULL; s->ck.len = 0;
+               shm_free(s->ik.s);
+               s->ik.s = NULL; s->ik.len = 0;
+
+               release_cport(s->port_pc);
+
+               release_spi(s->spi_pc);
+               release_spi(s->spi_ps);
         return -1;
     }
 
@@ -834,6 +850,20 @@ cleanup:
     return ret;
 }
 
+int ipsec_reconfig()
+{
+       if(ul.get_number_of_contacts() != 0){
+               return 0;
+       }
+
+       clean_spi_list();
+       clean_port_lists();
+
+       LM_DBG("Clean all ipsec tunnels\n");
+
+       return ipsec_cleanall();
+}
+
 int ipsec_cleanall()
 {
     struct mnl_socket* nlsock = init_mnl_socket();
index 497f97a..cc7aace 100644 (file)
 #define IPSEC_CMD_H
 
 typedef void (*contact_expired_t)(pcontact_t* c, int type, void* param);
+typedef int (*reconfig_tunnels_t)();
 
 /*! ipsec pcscf API export structure */
 typedef struct ipsec_pcscf_api {
-    contact_expired_t ipsec_on_expire;
+    contact_expired_t  ipsec_on_expire;
+       reconfig_tunnels_t      ipsec_reconfig;
 } ipsec_pcscf_api_t;
 
 /*! ipsec pcscf API export bind function */
@@ -64,6 +66,7 @@ int ipsec_create(struct sip_msg* m, udomain_t* d);
 int ipsec_forward(struct sip_msg* m, udomain_t* d);
 int ipsec_destroy(struct sip_msg* m, udomain_t* d);
 int ipsec_cleanall();
+int ipsec_reconfig();
 void ipsec_on_expire(pcontact_t* c, int type, void* param);
 
 #endif /* IPSEC_CMD_H */
index 590f26c..d722eef 100644 (file)
 #include "spi_gen.h"
 #include "spi_list.h"
 #include <pthread.h>
-
-pthread_mutex_t sport_mut;  // server port mutex
-pthread_mutex_t cport_mut;  // client port mutex
-spi_list_t used_sports;     // list with used server ports
-spi_list_t used_cports;     // list with used client ports
-uint32_t sport_val;         // the last acquired server port
-uint32_t cport_val;         // the last acquired client port
-uint32_t min_sport;
-uint32_t min_cport;
-uint32_t max_sport;
-uint32_t max_cport;
+#include "../../core/mem/shm_mem.h"
+
+typedef struct port_generator{
+       pthread_mutex_t sport_mut;              // server port mutex
+       pthread_mutex_t cport_mut;              // client port mutex
+       spi_list_t              used_sports;    // list with used server ports
+       spi_list_t              used_cports;    // list with used client ports
+       uint32_t                sport_val;              // the last acquired server port
+       uint32_t                cport_val;              // the last acquired client port
+       uint32_t                min_sport;
+       uint32_t                min_cport;
+       uint32_t                max_sport;
+       uint32_t                max_cport;
+} port_generator_t;
+
+port_generator_t* port_data = NULL;
 
 int init_port_gen(uint32_t sport_start_val, uint32_t cport_start_val, uint32_t range)
 {
@@ -47,24 +52,40 @@ int init_port_gen(uint32_t sport_start_val, uint32_t cport_start_val, uint32_t r
         return 2;
     }
 
-    if(pthread_mutex_init(&sport_mut, NULL) || pthread_mutex_init(&cport_mut, NULL)){
-        return 3;
-    }
+       if(port_data){
+               return 3;
+       }
+
+       port_data = shm_malloc(sizeof(port_generator_t));
+       if(port_data == NULL){
+               return 4;
+       }
+
+       if(pthread_mutex_init(&port_data->sport_mut, NULL)){
+               shm_free(port_data);
+               return 5;
+       }
 
-    used_sports = create_list();
-    used_cports = create_list();
+       if(pthread_mutex_init(&port_data->cport_mut, NULL)){
+               pthread_mutex_destroy(&port_data->sport_mut);
+               shm_free(port_data);
+               return 6;
+       }
 
-    sport_val = min_sport = sport_start_val;
-    cport_val = min_cport = cport_start_val;
-    max_sport = sport_start_val + range;
-    max_cport = cport_start_val + range;
+       port_data->used_sports = create_list();
+       port_data->used_cports = create_list();
+
+       port_data->sport_val = port_data->min_sport = sport_start_val;
+       port_data->cport_val = port_data->min_cport = cport_start_val;
+       port_data->max_sport = sport_start_val + range;
+       port_data->max_cport = cport_start_val + range;
 
     return 0;
 }
 
 uint32_t acquire_port(spi_list_t* used_ports, pthread_mutex_t* port_mut, uint32_t* port_val, uint32_t min_port, uint32_t max_port)
 {
-    //save the initial value for the highly unlikely case where there are no free server PORTs
+       //save the initial value for the highly unlikely case where there are no free PORTs
     uint32_t initial_val = *port_val;
     uint32_t ret = 0; // by default return invalid port
 
@@ -76,6 +97,11 @@ uint32_t acquire_port(spi_list_t* used_ports, pthread_mutex_t* port_mut, uint32_
         if(spi_in_list(used_ports, *port_val) == 0) {
             ret = *port_val;
             (*port_val)++;
+
+                       if(*port_val >= max_port) { //reached the top of the range - reset
+                               *port_val = min_port;
+                       }
+
             break;
         }
 
@@ -102,44 +128,100 @@ uint32_t acquire_port(spi_list_t* used_ports, pthread_mutex_t* port_mut, uint32_
 
 uint32_t acquire_sport()
 {
-    return acquire_port(&used_sports, &sport_mut, &sport_val, min_sport, max_sport);
+       if(!port_data){
+               return 0;
+       }
+
+       return acquire_port(&port_data->used_sports, &port_data->sport_mut, &port_data->sport_val, port_data->min_sport, port_data->max_sport);
 }
 
 uint32_t acquire_cport()
 {
-    return acquire_port(&used_cports, &cport_mut, &cport_val, min_cport, max_cport);
+       if(!port_data){
+               return 0;
+       }
+
+       return acquire_port(&port_data->used_cports, &port_data->cport_mut, &port_data->cport_val, port_data->min_cport, port_data->max_cport);
 }
 
 int release_sport(uint32_t port)
 {
-    if(pthread_mutex_lock(&sport_mut) != 0){
+       if(!port_data){
+               return 1;
+       }
+
+       if(pthread_mutex_lock(&port_data->sport_mut) != 0){
         return 1;
     }
 
-    spi_remove(&used_sports, port);
+       spi_remove(&port_data->used_sports, port);
 
-    pthread_mutex_unlock(&sport_mut);
+       pthread_mutex_unlock(&port_data->sport_mut);
     return 0;
 }
 
 int release_cport(uint32_t port)
 {
-    if(pthread_mutex_lock(&cport_mut) != 0){
+       if(!port_data){
+               return 1;
+       }
+
+       if(pthread_mutex_lock(&port_data->cport_mut) != 0){
         return 1;
     }
 
-    spi_remove(&used_cports, port);
+       spi_remove(&port_data->used_cports, port);
 
-    pthread_mutex_unlock(&cport_mut);
+       pthread_mutex_unlock(&port_data->cport_mut);
     return 0;
 }
 
+int clean_port_lists()
+{
+       if(!port_data){
+               return 1;
+       }
+
+       if(pthread_mutex_lock(&port_data->sport_mut) != 0){
+               return 1;
+       }
+
+       destroy_list(&port_data->used_sports);
+
+       pthread_mutex_unlock(&port_data->sport_mut);
+
+       if(pthread_mutex_lock(&port_data->cport_mut) != 0){
+               return 1;
+       }
+
+       destroy_list(&port_data->used_cports);
+
+       pthread_mutex_unlock(&port_data->cport_mut);
+
+       return 0;
+}
+
 int destroy_port_gen()
 {
-    int ret = pthread_mutex_destroy(&sport_mut);
+       if(!port_data){
+               return 1;
+       }
+
+       int ret;
+
+       destroy_list(&port_data->used_sports);
+       destroy_list(&port_data->used_cports);
+
+       port_data->sport_val = port_data->min_sport;
+       port_data->cport_val = port_data->min_cport;
+
+       ret = pthread_mutex_destroy(&port_data->sport_mut);
     if(ret != 0){
+               shm_free(port_data);
         return ret;
     }
 
-    return pthread_mutex_destroy(&cport_mut);
+       ret = pthread_mutex_destroy(&port_data->cport_mut);
+       shm_free(port_data);
+       return ret;
 }
index 1978f64..29a792a 100644 (file)
@@ -31,6 +31,7 @@
 // It is used as an unique port generator for the TCP client and server ports.
 
 int init_port_gen(uint32_t sport_start_val, uint32_t cport_start_val, uint32_t range);
+int clean_port_lists();
 int destroy_port_gen();
 uint32_t acquire_sport(); // acquare server port
 uint32_t acquire_cport(); // acquare client port
index ebd2820..997cb86 100644 (file)
 #include "spi_gen.h"
 #include "spi_list.h"
 #include <pthread.h>
+#include "../../core/mem/shm_mem.h"
 
-pthread_mutex_t spis_mut;
-spi_list_t used_spis;
-uint32_t spi_val;
-uint32_t min_spi;
-uint32_t max_spi;
+typedef struct spi_generator{
+       pthread_mutex_t spis_mut;
+       spi_list_t              used_spis;
+       uint32_t                spi_val;
+       uint32_t                min_spi;
+       uint32_t                max_spi;
+} spi_generator_t;
+
+spi_generator_t* spi_data = NULL;
 
 int init_spi_gen(uint32_t start_val, uint32_t range)
 {
@@ -40,72 +45,121 @@ int init_spi_gen(uint32_t start_val, uint32_t range)
     if(UINT32_MAX - range < start_val)
         return 2;
 
-    if(pthread_mutex_init(&spis_mut, NULL))
-        return 3;
+       if(spi_data){
+               return 3;
+       }
+
+       spi_data = shm_malloc(sizeof(spi_generator_t));
+       if(spi_data == NULL){
+               return 4;
+       }
 
-    used_spis = create_list();
+       if(pthread_mutex_init(&spi_data->spis_mut, NULL)){
+               shm_free(spi_data);
+               return 5;
+       }
 
-    spi_val = start_val;
-    min_spi = start_val;
-    max_spi = start_val + range;
+       spi_data->used_spis = create_list();
+
+       spi_data->spi_val = spi_data->min_spi = start_val;
+       spi_data->max_spi = start_val + range;
 
     return 0;
 }
 
 uint32_t acquire_spi()
 {
+       if(!spi_data){
+               return 0;
+       }
+
     //save the initial value for the highly unlikely case where there are no free SPIs
-    uint32_t initial_val = spi_val;
+       uint32_t initial_val = spi_data->spi_val;
     uint32_t ret = 0; // by default return invalid SPI
 
-    if(pthread_mutex_lock(&spis_mut) != 0) {
+       if(pthread_mutex_lock(&spi_data->spis_mut) != 0){
         return ret;
     }
 
     while(1) {
-        if(spi_in_list(&used_spis, spi_val) == 0) {
-            ret = spi_val;
-            spi_val++;
+               if(spi_in_list(&spi_data->used_spis, spi_data->spi_val) == 0){
+                       ret = spi_data->spi_val;
+                       spi_data->spi_val++;
+
+                       if(spi_data->spi_val >= spi_data->max_spi) { //reached the top of the range - reset
+                               spi_data->spi_val = spi_data->min_spi;
+                       }
+
             break;
         }
 
-        spi_val++; //the current SPI is not available - increment
+               spi_data->spi_val++; //the current SPI is not available - increment
 
-        if(spi_val >= max_spi) { //reached the top of the range - reset
-            spi_val = min_spi;
+               if(spi_data->spi_val >= spi_data->max_spi){ //reached the top of the range - reset
+                       spi_data->spi_val = spi_data->min_spi;
         }
 
-        if(spi_val == initial_val) { //there are no free SPIs
-            pthread_mutex_unlock(&spis_mut);
+               if(spi_data->spi_val == initial_val){ //there are no free SPIs
+                       pthread_mutex_unlock(&spi_data->spis_mut);
             return ret;
         }
 
     }
 
     //found unused SPI - add it to the used list
-    if(spi_add(&used_spis, ret) != 0) {
+       if(spi_add(&spi_data->used_spis, ret) != 0){
         ret = 0;
     }
 
-    pthread_mutex_unlock(&spis_mut);
+       pthread_mutex_unlock(&spi_data->spis_mut);
 
     return ret;
 }
 
 int release_spi(uint32_t id)
 {
-    if(pthread_mutex_lock(&spis_mut) != 0) {
+       if(!spi_data){
+               return 1;
+       }
+
+       if(pthread_mutex_lock(&spi_data->spis_mut) != 0){
         return 1;
     }
 
-    spi_remove(&used_spis, id);
+       spi_remove(&spi_data->used_spis, id);
 
-    pthread_mutex_unlock(&spis_mut);
+       pthread_mutex_unlock(&spi_data->spis_mut);
 
     return 0;
 }
 
+int clean_spi_list()
+{
+       if(!spi_data){
+               return 1;
+       }
+
+       if(pthread_mutex_lock(&spi_data->spis_mut) != 0){
+               return 1;
+       }
+
+       destroy_list(&spi_data->used_spis);
+       spi_data->spi_val = spi_data->min_spi;
+
+       pthread_mutex_unlock(&spi_data->spis_mut);
+
+       return 0;
+}
+
 int destroy_spi_gen()
 {
-    return pthread_mutex_destroy(&spis_mut);
+       if(!spi_data){
+               return 1;
+       }
+
+       destroy_list(&spi_data->used_spis);
+
+       int ret = pthread_mutex_destroy(&spi_data->spis_mut);
+       shm_free(spi_data);
+       return ret;
 }
index dcb8475..af68728 100644 (file)
@@ -32,6 +32,7 @@
 // acquire_spi() and release_spi(uint32_t id) functions.
 
 int init_spi_gen(uint32_t start_val, uint32_t range);
+int clean_spi_list();
 int destroy_spi_gen();
 uint32_t acquire_spi();
 int release_spi(uint32_t id);
index 6d780e0..358beb7 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include "spi_list.h"
+#include "../../core/mem/shm_mem.h"
 
 
 spi_list_t create_list()
@@ -32,21 +33,31 @@ spi_list_t create_list()
     return lst;
 }
 
-void destroy_list(spi_list_t lst)
+void destroy_list(spi_list_t* lst)
 {
-    spi_node_t* l = lst.head;
+       if(!lst){
+               return;
+       }
+       
+    spi_node_t* l = lst->head;
     while(l) {
         spi_node_t* n = l->next;
-        free(l);
+        shm_free(l);
         l = n;
     }
+
+       lst->head = NULL;
+       lst->tail = NULL;
 }
 
 int spi_add(spi_list_t* list, uint32_t id)
 {
-    // create new node
-    spi_node_t* n = malloc(sizeof(spi_node_t));
+       if(!list){
+               return 1;
+       }
 
+       // create new node
+       spi_node_t* n = shm_malloc(sizeof(spi_node_t));
     if(!n)
         return 1;
 
@@ -74,7 +85,7 @@ int spi_add(spi_list_t* list, uint32_t id)
         list->tail = n;
     }
     else if(n->id == c->id) { //c is not NULL, so check for duplicates
-        free(n);
+        shm_free(n);
         return 1;
     }
     else if(c == list->head) { //at the start of the list?
@@ -92,6 +103,10 @@ int spi_add(spi_list_t* list, uint32_t id)
 
 int spi_remove(spi_list_t* list, uint32_t id)
 {
+       if(!list){
+               return 0;
+       }
+
     //when list is empty
     if(!list->head) {
         return 0;
@@ -107,7 +122,7 @@ int spi_remove(spi_list_t* list, uint32_t id)
             list->tail = list->head;
         }
 
-        free(t);
+               shm_free(t);
         return 0;
     }
 
@@ -127,7 +142,7 @@ int spi_remove(spi_list_t* list, uint32_t id)
                 list->tail = prev;
             }
 
-            free(t);
+                       shm_free(t);
             return 0;
         }
 
@@ -135,11 +150,15 @@ int spi_remove(spi_list_t* list, uint32_t id)
         curr = curr->next;
     }
 
-    return 0;
+    return -1; // out of scope
 }
 
 int spi_in_list(spi_list_t* list, uint32_t id)
 {
+       if(!list){
+               return 0;
+       }
+
     if(!list->head)
         return 0;
 
index 05a555c..a7cdb3b 100644 (file)
@@ -45,6 +45,7 @@ typedef struct _spi_list {
 
 
 spi_list_t create_list();
+void destroy_list(spi_list_t* lst);
 int spi_add(spi_list_t* list, uint32_t id);
 int spi_remove(spi_list_t* list, uint32_t id);
 int spi_in_list(spi_list_t* list, uint32_t id);