* ims_ipsec_pcscf: fix issues with UEs and ipsec tunnel
UEs were not sending certain replies through the ipsec tunnel
* ims_ipsec_pcscf: fix issues pointed out in code review
Remove error logs which were not errors at all.
Fix issue in clean_spi_list where the free SPI list would get completely wiped.
* ims_ipsec_pcscf: lower log severity from error to info
Co-authored-by: Teodor Mihov <teodor.mihov@flolive.net>
... | ... |
@@ -50,7 +50,6 @@ |
50 | 50 |
|
51 | 51 |
#include "ipsec.h" |
52 | 52 |
#include "spi_gen.h" |
53 |
-#include "port_gen.h" |
|
54 | 53 |
#include "cmd.h" |
55 | 54 |
#include "sec_agree.h" |
56 | 55 |
|
... | ... |
@@ -351,57 +350,26 @@ static int update_contact_ipsec_params(ipsec_t* s, const struct sip_msg* m, ipse |
351 | 350 |
s->ik.len = ik.len; |
352 | 351 |
|
353 | 352 |
// Generate SPI |
354 |
- if((s->spi_pc = acquire_spi()) == 0) { |
|
355 |
- LM_ERR("Error generating client SPI for IPSEC tunnel creation\n"); |
|
356 |
- shm_free(s->ck.s); |
|
357 |
- s->ck.s = NULL; s->ck.len = 0; |
|
358 |
- shm_free(s->ik.s); |
|
359 |
- s->ik.s = NULL; s->ik.len = 0; |
|
360 |
- return -1; |
|
353 |
+ if(s_old) { |
|
354 |
+ if(s_old->spi_pc && s_old->spi_ps && s_old->port_pc && s_old->port_ps) { |
|
355 |
+ LM_INFO("Reusing IPSEC tunnel\n"); |
|
356 |
+ s->spi_pc = s_old->spi_pc; |
|
357 |
+ s->spi_ps = s_old->spi_ps; |
|
358 |
+ s->port_pc = s_old->port_pc; |
|
359 |
+ s->port_ps = s_old->port_ps; |
|
360 |
+ return 0; |
|
361 |
+ } |
|
361 | 362 |
} |
362 | 363 |
|
363 |
- if((s->spi_ps = acquire_spi()) == 0) { |
|
364 |
- LM_ERR("Error generating server SPI for IPSEC tunnel creation\n"); |
|
364 |
+ if(acquire_spi(&s->spi_pc, &s->spi_ps, &s->port_pc, &s->port_ps) == 0) { |
|
365 |
+ LM_ERR("Error generating client SPI for IPSEC tunnel creation\n"); |
|
365 | 366 |
shm_free(s->ck.s); |
366 | 367 |
s->ck.s = NULL; s->ck.len = 0; |
367 | 368 |
shm_free(s->ik.s); |
368 | 369 |
s->ik.s = NULL; s->ik.len = 0; |
369 |
- |
|
370 |
- release_spi(s->spi_pc); |
|
371 | 370 |
return -1; |
372 | 371 |
} |
373 | 372 |
|
374 |
- if((s->port_pc = acquire_cport()) == 0){ |
|
375 |
- LM_ERR("No free client port for IPSEC tunnel creation\n"); |
|
376 |
- shm_free(s->ck.s); |
|
377 |
- s->ck.s = NULL; s->ck.len = 0; |
|
378 |
- shm_free(s->ik.s); |
|
379 |
- s->ik.s = NULL; s->ik.len = 0; |
|
380 |
- |
|
381 |
- release_spi(s->spi_pc); |
|
382 |
- release_spi(s->spi_ps); |
|
383 |
- return -1; |
|
384 |
- } |
|
385 |
- |
|
386 |
- // use the same P-CSCF server port if it is present |
|
387 |
- if(s_old){ |
|
388 |
- s->port_ps = s_old->port_ps; |
|
389 |
- }else{ |
|
390 |
- if((s->port_ps = acquire_sport()) == 0){ |
|
391 |
- LM_ERR("No free server port for IPSEC tunnel creation\n"); |
|
392 |
- shm_free(s->ck.s); |
|
393 |
- s->ck.s = NULL; s->ck.len = 0; |
|
394 |
- shm_free(s->ik.s); |
|
395 |
- s->ik.s = NULL; s->ik.len = 0; |
|
396 |
- |
|
397 |
- release_cport(s->port_pc); |
|
398 |
- |
|
399 |
- release_spi(s->spi_pc); |
|
400 |
- release_spi(s->spi_ps); |
|
401 |
- return -1; |
|
402 |
- } |
|
403 |
- } |
|
404 |
- |
|
405 | 373 |
return 0; |
406 | 374 |
} |
407 | 375 |
|
... | ... |
@@ -508,12 +476,7 @@ static int destroy_ipsec_tunnel(str remote_addr, ipsec_t* s, unsigned short rece |
508 | 476 |
remove_policy(sock, remote_addr, ipsec_addr, s->port_us, s->port_pc, s->spi_pc, ip_addr.af, IPSEC_POLICY_DIRECTION_IN); |
509 | 477 |
|
510 | 478 |
// Release SPIs |
511 |
- release_spi(s->spi_pc); |
|
512 |
- release_spi(s->spi_ps); |
|
513 |
- |
|
514 |
- // Release the client and the server ports |
|
515 |
- release_cport(s->port_pc); |
|
516 |
- release_sport(s->port_ps); |
|
479 |
+ release_spi(s->spi_pc, s->spi_ps, s->port_pc, s->port_ps); |
|
517 | 480 |
|
518 | 481 |
close_mnl_socket(sock); |
519 | 482 |
return 0; |
... | ... |
@@ -692,74 +655,69 @@ int ipsec_create(struct sip_msg* m, udomain_t* d, int _cflags) |
692 | 655 |
|
693 | 656 |
struct sip_msg* req = t->uas.request; |
694 | 657 |
|
658 |
+ // Parse security parameters from the REGISTER request and get some data for the new tunnels |
|
659 |
+ security_t* req_sec_params = cscf_get_security(req); |
|
660 |
+ ipsec_t* s; |
|
661 |
+ ipsec_t* old_s = NULL; |
|
662 |
+ |
|
695 | 663 |
// Update contacts only for initial registration, for re-registration the existing contacts shouldn't be updated. |
696 | 664 |
if(ci.via_port == SIP_PORT){ |
697 | 665 |
LM_DBG("Registration for contact with AOR [%.*s], VIA [%d://%.*s:%d], received_host [%d://%.*s:%d]\n", |
698 | 666 |
ci.aor.len, ci.aor.s, ci.via_prot, ci.via_host.len, ci.via_host.s, ci.via_port, |
699 | 667 |
ci.received_proto, ci.received_host.len, ci.received_host.s, ci.received_port); |
700 | 668 |
|
701 |
- ipsec_t* s = pcontact->security_temp->data.ipsec; |
|
669 |
+ if(req_sec_params == NULL) |
|
670 |
+ s = pcontact->security_temp->data.ipsec; |
|
671 |
+ else |
|
672 |
+ s = req_sec_params->data.ipsec; |
|
673 |
+ }else{ |
|
674 |
+ LM_DBG("RE-Registration for contact with AOR [%.*s], VIA [%d://%.*s:%d], received_host [%d://%.*s:%d]\n", |
|
675 |
+ ci.aor.len, ci.aor.s, ci.via_prot, ci.via_host.len, ci.via_host.s, ci.via_port, |
|
676 |
+ ci.received_proto, ci.received_host.len, ci.received_host.s, ci.received_port); |
|
702 | 677 |
|
703 |
- // for initial Registration use a new P-CSCF server port |
|
704 |
- if(update_contact_ipsec_params(s, m, NULL) != 0) { |
|
678 |
+ if(req_sec_params == NULL) { |
|
679 |
+ LM_CRIT("No security parameters in REGISTER request\n"); |
|
705 | 680 |
goto cleanup; |
706 | 681 |
} |
707 | 682 |
|
708 |
- if(create_ipsec_tunnel(&req->rcv.src_ip, s) != 0){ |
|
709 |
- goto cleanup; |
|
710 |
- } |
|
683 |
+ s = req_sec_params->data.ipsec; |
|
684 |
+ old_s = (ipsec_reuse_server_port && pcontact->security_temp) ? pcontact->security_temp->data.ipsec : NULL; |
|
685 |
+ } |
|
711 | 686 |
|
712 |
- if (ul.update_pcontact(d, &ci, pcontact) != 0){ |
|
713 |
- LM_ERR("Error updating contact\n"); |
|
714 |
- goto cleanup; |
|
715 |
- } |
|
687 |
+ if(update_contact_ipsec_params(s, m, old_s) != 0) { |
|
688 |
+ goto cleanup; |
|
689 |
+ } |
|
716 | 690 |
|
691 |
+ if(create_ipsec_tunnel(&req->rcv.src_ip, s) != 0){ |
|
692 |
+ goto cleanup; |
|
693 |
+ } |
|
694 |
+ |
|
695 |
+ if (ul.update_pcontact(d, &ci, pcontact) != 0){ |
|
696 |
+ LM_ERR("Error updating contact\n"); |
|
697 |
+ goto cleanup; |
|
698 |
+ } |
|
699 |
+ |
|
700 |
+ if(ci.via_port == SIP_PORT){ |
|
717 | 701 |
// Update temp security parameters |
718 | 702 |
if(ul.update_temp_security(d, pcontact->security_temp->type, pcontact->security_temp, pcontact) != 0){ |
719 | 703 |
LM_ERR("Error updating temp security\n"); |
720 | 704 |
} |
705 |
+ } |
|
721 | 706 |
|
722 |
- if(add_supported_secagree_header(m) != 0) { |
|
723 |
- goto cleanup; |
|
724 |
- } |
|
725 | 707 |
|
726 |
- if(add_security_server_header(m, s) != 0) { |
|
727 |
- goto cleanup; |
|
728 |
- } |
|
708 |
+ if(add_supported_secagree_header(m) != 0) { |
|
709 |
+ goto cleanup; |
|
710 |
+ } |
|
729 | 711 |
|
712 |
+ if(add_security_server_header(m, s) != 0) { |
|
713 |
+ goto cleanup; |
|
714 |
+ } |
|
715 |
+ |
|
716 |
+ if(ci.via_port == SIP_PORT){ |
|
730 | 717 |
if(ul.register_ulcb(pcontact, PCSCF_CONTACT_EXPIRE|PCSCF_CONTACT_DELETE, ipsec_on_expire, (void*)&pcontact->received_port) != 1) { |
731 | 718 |
LM_ERR("Error subscribing for contact\n"); |
732 | 719 |
goto cleanup; |
733 | 720 |
} |
734 |
- }else{ |
|
735 |
- LM_DBG("RE-Registration for contact with AOR [%.*s], VIA [%d://%.*s:%d], received_host [%d://%.*s:%d]\n", |
|
736 |
- ci.aor.len, ci.aor.s, ci.via_prot, ci.via_host.len, ci.via_host.s, ci.via_port, |
|
737 |
- ci.received_proto, ci.received_host.len, ci.received_host.s, ci.received_port); |
|
738 |
- |
|
739 |
- security_t* req_sec_params = NULL; |
|
740 |
- |
|
741 |
- // Parse security parameters from the REGISTER request and get some data for the new tunnels |
|
742 |
- if((req_sec_params = cscf_get_security(req)) == NULL) { |
|
743 |
- LM_CRIT("No security parameters in REGISTER request\n"); |
|
744 |
- goto cleanup; |
|
745 |
- } |
|
746 |
- |
|
747 |
- // for Re-Registration use the same P-CSCF server port if 'ipsec reuse server port' is enabled |
|
748 |
- if(update_contact_ipsec_params(req_sec_params->data.ipsec, m, ipsec_reuse_server_port ? pcontact->security_temp->data.ipsec : NULL) != 0) { |
|
749 |
- goto cleanup; |
|
750 |
- } |
|
751 |
- |
|
752 |
- if(create_ipsec_tunnel(&req->rcv.src_ip, req_sec_params->data.ipsec) != 0){ |
|
753 |
- goto cleanup; |
|
754 |
- } |
|
755 |
- |
|
756 |
- if(add_supported_secagree_header(m) != 0) { |
|
757 |
- goto cleanup; |
|
758 |
- } |
|
759 |
- |
|
760 |
- if(add_security_server_header(m, req_sec_params->data.ipsec) != 0) { |
|
761 |
- goto cleanup; |
|
762 |
- } |
|
763 | 721 |
} |
764 | 722 |
|
765 | 723 |
ret = IPSEC_CMD_SUCCESS; // all good, set ret to SUCCESS, and exit |
... | ... |
@@ -1004,10 +962,9 @@ int ipsec_reconfig() |
1004 | 962 |
return 0; |
1005 | 963 |
} |
1006 | 964 |
|
1007 |
- clean_spi_list(); |
|
1008 |
- clean_port_lists(); |
|
1009 |
- |
|
1010 |
- LM_DBG("Clean all ipsec tunnels\n"); |
|
965 |
+ if(clean_spi_list() != 0) { |
|
966 |
+ return 1; |
|
967 |
+ } |
|
1011 | 968 |
|
1012 | 969 |
return ipsec_cleanall(); |
1013 | 970 |
} |
... | ... |
@@ -82,7 +82,7 @@ modparam("ims_ipsec_pcscf", "ipsec_listen_addr6", "") |
82 | 82 |
<section> |
83 | 83 |
<title><varname>ipsec_client_port</varname> (int)</title> |
84 | 84 |
|
85 |
- <para>Start port number which will be bound for incoming (server) IPSec traffic.</para> |
|
85 |
+ <para>Port number which will be bound for incoming (server) IPSec traffic.</para> |
|
86 | 86 |
|
87 | 87 |
<para><emphasis>Default value is 5062.</emphasis></para> |
88 | 88 |
|
... | ... |
@@ -100,7 +100,7 @@ modparam("ims_ipsec_pcscf", "ipsec_client_port", 5062) |
100 | 100 |
<section> |
101 | 101 |
<title><varname>ipsec_server_port</varname> (int)</title> |
102 | 102 |
|
103 |
- <para>Start port number which will be bound for incoming (server) IPSec traffic.</para> |
|
103 |
+ <para>Port number which will be bound for incoming (server) IPSec traffic.</para> |
|
104 | 104 |
|
105 | 105 |
<para><emphasis>Default value is 5063.</emphasis></para> |
106 | 106 |
|
... | ... |
@@ -118,9 +118,7 @@ modparam("ims_ipsec_pcscf", "ipsec_server_port", 5063) |
118 | 118 |
<section> |
119 | 119 |
<title><varname>ipsec_max_connections</varname> (int)</title> |
120 | 120 |
|
121 |
- <para>Maximum IPSec connections for the process. E.g. if ipsec_client_port=5100, ipsec_server_port=6100 and |
|
122 |
- ipsec_max_connections=10, all client ports between 5100 and 5109 and all server ports between 6100 and 6109 |
|
123 |
- will be used for maximum to 10 IPSec connections.</para> |
|
121 |
+ <para>Maximum simultanious IPSec connections</para> |
|
124 | 122 |
|
125 | 123 |
<para><emphasis>Default value is 2.</emphasis></para> |
126 | 124 |
|
... | ... |
@@ -138,11 +136,9 @@ modparam("ims_ipsec_pcscf", "ipsec_max_connections", 10) |
138 | 136 |
<section> |
139 | 137 |
<title><varname>ipsec_reuse_server_port</varname> (int)</title> |
140 | 138 |
|
141 |
- <para>Reuse (1) or not (0) the P-CSCF Server port for Re-registration for one UA. |
|
142 |
- When set to 0 - During Re-registration P-CSCF will distribute new P-CSCF client and |
|
143 |
- P-CSCF server ports. |
|
144 |
- When set to 1 - During Re-registration P-CSCF will reuse the old P-CSCF server port and |
|
145 |
- will distribute a new P-CSCF client port.</para> |
|
139 |
+ <para>Reuse (1) or not (0) the P-CSCF IPSec information for Re-registration for one UA. |
|
140 |
+ When set to 0 - During Re-registration P-CSCF will create new IPSec tunnels. |
|
141 |
+ When set to 1 - During Re-registration P-CSCF will reuse the old IPSec tunnels.</para> |
|
146 | 142 |
|
147 | 143 |
<para><emphasis>Default value is 1.</emphasis></para> |
148 | 144 |
|
... | ... |
@@ -192,6 +188,40 @@ modparam("ims_ipsec_pcscf", "ipsec_spi_id_start", 100) |
192 | 188 |
<programlisting format="linespecific"> |
193 | 189 |
... |
194 | 190 |
modparam("ims_ipsec_pcscf", "ipsec_spi_id_range", 1000) |
191 |
+... |
|
192 |
+ </programlisting> |
|
193 |
+ </example> |
|
194 |
+ </section> |
|
195 |
+ |
|
196 |
+ <section> |
|
197 |
+ <title><varname>ipsec_preferred_alg</varname> (string)</title> |
|
198 |
+ |
|
199 |
+ <para>A name of an authentication algorithm which the Proxy-CSCF will <emphasis>prefer</emphasis> when creating IPSec tunnels.</para> |
|
200 |
+ <para><emphasis>Default value is empty string (null) - the last algorithm in the Sec-Agree header will be used.</emphasis></para> |
|
201 |
+ |
|
202 |
+ <example> |
|
203 |
+ <title><varname>ipsec_preferred_alg</varname> parameter usage</title> |
|
204 |
+ |
|
205 |
+ <programlisting format="linespecific"> |
|
206 |
+... |
|
207 |
+modparam("ims_ipsec_pcscf", "ipsec_preferred_alg", "hmac-sha-1-96") |
|
208 |
+... |
|
209 |
+ </programlisting> |
|
210 |
+ </example> |
|
211 |
+ </section> |
|
212 |
+ |
|
213 |
+ <section> |
|
214 |
+ <title><varname>ipsec_preferred_ealg</varname> (string)</title> |
|
215 |
+ |
|
216 |
+ <para>A name of an encrytion algorithm which the Proxy-CSCF will <emphasis>prefer</emphasis> when creating IPSec tunnels.</para> |
|
217 |
+ <para><emphasis>Default value is empty string (null) - the last algorithm in the Sec-Agree header will be used. Note that the possibility of it being the "null" algorithm is not insignificant.</emphasis></para> |
|
218 |
+ |
|
219 |
+ <example> |
|
220 |
+ <title><varname>ipsec_preferred_ealg</varname> parameter usage</title> |
|
221 |
+ |
|
222 |
+ <programlisting format="linespecific"> |
|
223 |
+... |
|
224 |
+modparam("ims_ipsec_pcscf", "ipsec_preferred_ealg", "aes-cbc") |
|
195 | 225 |
... |
196 | 226 |
</programlisting> |
197 | 227 |
</example> |
... | ... |
@@ -28,8 +28,6 @@ |
28 | 28 |
|
29 | 29 |
#include "cmd.h" |
30 | 30 |
#include "spi_gen.h" |
31 |
-#include "port_gen.h" |
|
32 |
- |
|
33 | 31 |
|
34 | 32 |
MODULE_VERSION |
35 | 33 |
|
... | ... |
@@ -45,6 +43,8 @@ int ipsec_reuse_server_port = 1; |
45 | 43 |
int ipsec_max_connections = 2; |
46 | 44 |
int spi_id_start = 100; |
47 | 45 |
int spi_id_range = 1000; |
46 |
+str ipsec_preferred_alg= STR_NULL; |
|
47 |
+str ipsec_preferred_ealg= STR_NULL; |
|
48 | 48 |
int xfrm_user_selector = 143956232; |
49 | 49 |
|
50 | 50 |
ip_addr_t ipsec_listen_ip_addr; |
... | ... |
@@ -92,6 +92,8 @@ static param_export_t params[] = { |
92 | 92 |
{"ipsec_max_connections", INT_PARAM, &ipsec_max_connections }, |
93 | 93 |
{"ipsec_spi_id_start", INT_PARAM, &spi_id_start }, |
94 | 94 |
{"ipsec_spi_id_range", INT_PARAM, &spi_id_range }, |
95 |
+ {"ipsec_preferred_alg", PARAM_STR, &ipsec_preferred_alg }, |
|
96 |
+ {"ipsec_preferred_ealg", PARAM_STR, &ipsec_preferred_ealg }, |
|
95 | 97 |
{0, 0, 0} |
96 | 98 |
}; |
97 | 99 |
|
... | ... |
@@ -302,16 +304,11 @@ static int mod_init(void) { |
302 | 304 |
} |
303 | 305 |
|
304 | 306 |
int res = 0; |
305 |
- if((res = init_spi_gen(spi_id_start, spi_id_range)) != 0) { |
|
307 |
+ if((res = init_spi_gen(spi_id_start, spi_id_range, ipsec_server_port, ipsec_client_port, ipsec_max_connections)) != 0) { |
|
306 | 308 |
LM_ERR("Error initialising spi generator. Error: %d\n", res); |
307 | 309 |
return -1; |
308 | 310 |
} |
309 | 311 |
|
310 |
- if((res = init_port_gen(ipsec_server_port, ipsec_client_port, ipsec_max_connections)) != 0) { |
|
311 |
- LM_ERR("Error initialising port generator. Error: %d\n", res); |
|
312 |
- return -1; |
|
313 |
- } |
|
314 |
- |
|
315 | 312 |
init_flag = 1; |
316 | 313 |
|
317 | 314 |
return 0; |
... | ... |
@@ -327,9 +324,6 @@ static void mod_destroy(void) |
327 | 324 |
LM_ERR("Error destroying spi generator\n"); |
328 | 325 |
} |
329 | 326 |
|
330 |
- if(destroy_port_gen() != 0){ |
|
331 |
- LM_ERR("Error destroying port generator\n"); |
|
332 |
- } |
|
333 | 327 |
} |
334 | 328 |
|
335 | 329 |
static int child_init(int rank) |
... | ... |
@@ -24,7 +24,6 @@ |
24 | 24 |
|
25 | 25 |
#include "ipsec.h" |
26 | 26 |
#include "spi_gen.h" |
27 |
-#include "port_gen.h" |
|
28 | 27 |
|
29 | 28 |
#include "../../core/dprint.h" |
30 | 29 |
#include "../../core/mem/pkg.h" |
... | ... |
@@ -198,27 +197,19 @@ int add_sa(struct mnl_socket* nl_sock, const struct ip_addr *src_addr_param, con |
198 | 197 |
|
199 | 198 |
// add encription algorithm for this SA |
200 | 199 |
l_enc_algo = (struct xfrm_algo *)l_enc_algo_buf; |
201 |
- // cipher_null, des, des3_ede, aes |
|
202 |
- strcpy(l_enc_algo->alg_name,"cipher_null"); |
|
203 | 200 |
if (strncasecmp(r_ealg.s,"aes-cbc",r_ealg.len) == 0) { |
204 |
- LM_DBG("Creating security associations: AES\n"); |
|
205 | 201 |
strcpy(l_enc_algo->alg_name,"aes"); |
206 | 202 |
l_enc_algo->alg_key_len = ck.len * 4; |
207 | 203 |
string_to_key(l_enc_algo->alg_key, ck); |
208 | 204 |
} |
209 | 205 |
else if (strncasecmp(r_ealg.s,"des-ede3-cbc",r_ealg.len) == 0) { |
210 |
- LM_DBG("Creating security associations: DES, ck.len=%d\n",ck.len); |
|
211 | 206 |
strcpy(l_enc_algo->alg_name,"des3_ede"); |
212 |
- str ck1; |
|
213 |
- ck1.s = pkg_malloc (128); |
|
214 |
- strncpy(ck1.s,ck.s,32); |
|
215 |
- strncat(ck1.s,ck.s,16); |
|
216 |
- ck1.len=32+16; |
|
217 |
- |
|
218 |
- l_enc_algo->alg_key_len = ck1.len * 4; |
|
219 |
- string_to_key(l_enc_algo->alg_key, ck1); |
|
220 |
- |
|
221 |
- pkg_free(ck1.s); |
|
207 |
+ l_enc_algo->alg_key_len = ck.len * 4; |
|
208 |
+ string_to_key(l_enc_algo->alg_key, ck); |
|
209 |
+ } else { |
|
210 |
+ // set default algorithm to null |
|
211 |
+ strcpy(l_enc_algo->alg_name,"cipher_null"); |
|
212 |
+ l_enc_algo->alg_key_len = 0; |
|
222 | 213 |
} |
223 | 214 |
|
224 | 215 |
mnl_attr_put(l_nlh, XFRMA_ALG_CRYPT, sizeof(struct xfrm_algo) + l_enc_algo->alg_key_len, l_enc_algo); |
... | ... |
@@ -814,13 +805,7 @@ static int delete_unused_sa_cb(const struct nlmsghdr *nlh, void *data) |
814 | 805 |
|
815 | 806 |
// NOTE: Release the Proxy SPIs and Ports only here. Do not release the same SPIs and ports in delete unsused policy callback. |
816 | 807 |
// Release SPIs |
817 |
- release_spi(ipsec.spi_pc); |
|
818 |
- release_spi(ipsec.spi_ps); |
|
819 |
- |
|
820 |
- // Release the client and the server ports |
|
821 |
- release_cport(ipsec.port_pc); |
|
822 |
- release_sport(ipsec.port_ps); |
|
823 |
- |
|
808 |
+ release_spi(ipsec.spi_pc, ipsec.spi_ps, ipsec.port_pc, ipsec.port_ps); |
|
824 | 809 |
return MNL_CB_OK; |
825 | 810 |
} |
826 | 811 |
|
827 | 812 |
deleted file mode 100644 |
... | ... |
@@ -1,227 +0,0 @@ |
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 "spi_gen.h" |
|
26 |
-#include "spi_list.h" |
|
27 |
-#include <pthread.h> |
|
28 |
-#include "../../core/mem/shm_mem.h" |
|
29 |
- |
|
30 |
-typedef struct port_generator{ |
|
31 |
- pthread_mutex_t sport_mut; // server port mutex |
|
32 |
- pthread_mutex_t cport_mut; // client port mutex |
|
33 |
- spi_list_t used_sports; // list with used server ports |
|
34 |
- spi_list_t used_cports; // list with used client ports |
|
35 |
- uint32_t sport_val; // the last acquired server port |
|
36 |
- uint32_t cport_val; // the last acquired client port |
|
37 |
- uint32_t min_sport; |
|
38 |
- uint32_t min_cport; |
|
39 |
- uint32_t max_sport; |
|
40 |
- uint32_t max_cport; |
|
41 |
-} port_generator_t; |
|
42 |
- |
|
43 |
-port_generator_t* port_data = NULL; |
|
44 |
- |
|
45 |
-int init_port_gen(uint32_t sport_start_val, uint32_t cport_start_val, uint32_t range) |
|
46 |
-{ |
|
47 |
- if(sport_start_val < 1 || cport_start_val < 1){ |
|
48 |
- return 1; |
|
49 |
- } |
|
50 |
- |
|
51 |
- if((UINT32_MAX - range < sport_start_val) || (UINT32_MAX - range < cport_start_val)){ |
|
52 |
- return 2; |
|
53 |
- } |
|
54 |
- |
|
55 |
- if(port_data){ |
|
56 |
- return 3; |
|
57 |
- } |
|
58 |
- |
|
59 |
- port_data = shm_malloc(sizeof(port_generator_t)); |
|
60 |
- if(port_data == NULL){ |
|
61 |
- return 4; |
|
62 |
- } |
|
63 |
- |
|
64 |
- if(pthread_mutex_init(&port_data->sport_mut, NULL)){ |
|
65 |
- shm_free(port_data); |
|
66 |
- return 5; |
|
67 |
- } |
|
68 |
- |
|
69 |
- if(pthread_mutex_init(&port_data->cport_mut, NULL)){ |
|
70 |
- pthread_mutex_destroy(&port_data->sport_mut); |
|
71 |
- shm_free(port_data); |
|
72 |
- return 6; |
|
73 |
- } |
|
74 |
- |
|
75 |
- port_data->used_sports = create_list(); |
|
76 |
- port_data->used_cports = create_list(); |
|
77 |
- |
|
78 |
- port_data->sport_val = port_data->min_sport = sport_start_val; |
|
79 |
- port_data->cport_val = port_data->min_cport = cport_start_val; |
|
80 |
- port_data->max_sport = sport_start_val + range; |
|
81 |
- port_data->max_cport = cport_start_val + range; |
|
82 |
- |
|
83 |
- return 0; |
|
84 |
-} |
|
85 |
- |
|
86 |
-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) |
|
87 |
-{ |
|
88 |
- //save the initial value for the highly unlikely case where there are no free PORTs |
|
89 |
- uint32_t initial_val = *port_val; |
|
90 |
- uint32_t ret = 0; // by default return invalid port |
|
91 |
- |
|
92 |
- if(pthread_mutex_lock(port_mut) != 0) { |
|
93 |
- return ret; |
|
94 |
- } |
|
95 |
- |
|
96 |
- while(1){ |
|
97 |
- if(spi_in_list(used_ports, *port_val) == 0) { |
|
98 |
- ret = *port_val; |
|
99 |
- (*port_val)++; |
|
100 |
- |
|
101 |
- if(*port_val >= max_port) { //reached the top of the range - reset |
|
102 |
- *port_val = min_port; |
|
103 |
- } |
|
104 |
- |
|
105 |
- break; |
|
106 |
- } |
|
107 |
- |
|
108 |
- (*port_val)++; //the current server port is not available - increment |
|
109 |
- |
|
110 |
- if(*port_val >= max_port) { //reached the top of the range - reset |
|
111 |
- *port_val = min_port; |
|
112 |
- } |
|
113 |
- |
|
114 |
- if(*port_val == initial_val) { //there are no free server ports |
|
115 |
- pthread_mutex_unlock(port_mut); |
|
116 |
- return ret; |
|
117 |
- } |
|
118 |
- } |
|
119 |
- |
|
120 |
- // found unused server port - add it to the used list |
|
121 |
- if(spi_add(used_ports, ret) != 0) { |
|
122 |
- ret = 0; |
|
123 |
- } |
|
124 |
- |
|
125 |
- pthread_mutex_unlock(port_mut); |
|
126 |
- return ret; |
|
127 |
-} |
|
128 |
- |
|
129 |
-uint32_t acquire_sport() |
|
130 |
-{ |
|
131 |
- if(!port_data){ |
|
132 |
- return 0; |
|
133 |
- } |
|
134 |
- |
|
135 |
- return acquire_port(&port_data->used_sports, &port_data->sport_mut, &port_data->sport_val, port_data->min_sport, port_data->max_sport); |
|
136 |
-} |
|
137 |
- |
|
138 |
-uint32_t acquire_cport() |
|
139 |
-{ |
|
140 |
- if(!port_data){ |
|
141 |
- return 0; |
|
142 |
- } |
|
143 |
- |
|
144 |
- return acquire_port(&port_data->used_cports, &port_data->cport_mut, &port_data->cport_val, port_data->min_cport, port_data->max_cport); |
|
145 |
-} |
|
146 |
- |
|
147 |
-int release_sport(uint32_t port) |
|
148 |
-{ |
|
149 |
- if(!port_data){ |
|
150 |
- return 1; |
|
151 |
- } |
|
152 |
- |
|
153 |
- if(pthread_mutex_lock(&port_data->sport_mut) != 0){ |
|
154 |
- return 1; |
|
155 |
- } |
|
156 |
- |
|
157 |
- spi_remove(&port_data->used_sports, port); |
|
158 |
- |
|
159 |
- pthread_mutex_unlock(&port_data->sport_mut); |
|
160 |
- return 0; |
|
161 |
-} |
|
162 |
- |
|
163 |
-int release_cport(uint32_t port) |
|
164 |
-{ |
|
165 |
- if(!port_data){ |
|
166 |
- return 1; |
|
167 |
- } |
|
168 |
- |
|
169 |
- if(pthread_mutex_lock(&port_data->cport_mut) != 0){ |
|
170 |
- return 1; |
|
171 |
- } |
|
172 |
- |
|
173 |
- spi_remove(&port_data->used_cports, port); |
|
174 |
- |
|
175 |
- pthread_mutex_unlock(&port_data->cport_mut); |
|
176 |
- return 0; |
|
177 |
-} |
|
178 |
- |
|
179 |
-int clean_port_lists() |
|
180 |
-{ |
|
181 |
- if(!port_data){ |
|
182 |
- return 1; |
|
183 |
- } |
|
184 |
- |
|
185 |
- if(pthread_mutex_lock(&port_data->sport_mut) != 0){ |
|
186 |
- return 1; |
|
187 |
- } |
|
188 |
- |
|
189 |
- destroy_list(&port_data->used_sports); |
|
190 |
- |
|
191 |
- pthread_mutex_unlock(&port_data->sport_mut); |
|
192 |
- |
|
193 |
- if(pthread_mutex_lock(&port_data->cport_mut) != 0){ |
|
194 |
- return 1; |
|
195 |
- } |
|
196 |
- |
|
197 |
- destroy_list(&port_data->used_cports); |
|
198 |
- |
|
199 |
- pthread_mutex_unlock(&port_data->cport_mut); |
|
200 |
- |
|
201 |
- return 0; |
|
202 |
-} |
|
203 |
- |
|
204 |
-int destroy_port_gen() |
|
205 |
-{ |
|
206 |
- if(!port_data){ |
|
207 |
- return 1; |
|
208 |
- } |
|
209 |
- |
|
210 |
- int ret; |
|
211 |
- |
|
212 |
- destroy_list(&port_data->used_sports); |
|
213 |
- destroy_list(&port_data->used_cports); |
|
214 |
- |
|
215 |
- port_data->sport_val = port_data->min_sport; |
|
216 |
- port_data->cport_val = port_data->min_cport; |
|
217 |
- |
|
218 |
- ret = pthread_mutex_destroy(&port_data->sport_mut); |
|
219 |
- if(ret != 0){ |
|
220 |
- shm_free(port_data); |
|
221 |
- return ret; |
|
222 |
- } |
|
223 |
- |
|
224 |
- ret = pthread_mutex_destroy(&port_data->cport_mut); |
|
225 |
- shm_free(port_data); |
|
226 |
- return ret; |
|
227 |
-} |
228 | 0 |
deleted file mode 100644 |
... | ... |
@@ -1,41 +0,0 @@ |
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 |
-#ifndef _SPI_GEN_H_ |
|
26 |
- |
|
27 |
-#include <stdint.h> |
|
28 |
- |
|
29 |
-// |
|
30 |
-// PORT GEN is based on SPI list, because the logics of the SPI gen and PORT gen are basically the same. |
|
31 |
-// It is used as an unique port generator for the TCP client and server ports. |
|
32 |
- |
|
33 |
-int init_port_gen(uint32_t sport_start_val, uint32_t cport_start_val, uint32_t range); |
|
34 |
-int clean_port_lists(); |
|
35 |
-int destroy_port_gen(); |
|
36 |
-uint32_t acquire_sport(); // acquare server port |
|
37 |
-uint32_t acquire_cport(); // acquare client port |
|
38 |
-int release_sport(uint32_t port); // release server port |
|
39 |
-int release_cport(uint32_t port); // release client port |
|
40 |
- |
|
41 |
-#endif /* _SPI_GEN_H_ */ |
... | ... |
@@ -25,6 +25,9 @@ |
25 | 25 |
#include "../../core/parser/msg_parser.h" |
26 | 26 |
#include "../../core/mem/mem.h" |
27 | 27 |
|
28 |
+extern str ipsec_preferred_alg; |
|
29 |
+extern str ipsec_preferred_ealg; |
|
30 |
+ |
|
28 | 31 |
static uint32_t parse_digits(str value) |
29 | 32 |
{ |
30 | 33 |
uint32_t ret = 0; |
... | ... |
@@ -68,13 +71,17 @@ static void trim_whitespaces(str* string) { |
68 | 71 |
DST.len = SRC.len; |
69 | 72 |
|
70 | 73 |
|
71 |
-static int process_sec_agree_param(str name, str value, ipsec_t *ret) |
|
74 |
+static int process_sec_agree_param(str name, str value, ipsec_t *ret, char *alg_found, char *ealg_found) |
|
72 | 75 |
{ |
73 | 76 |
trim_whitespaces(&name); |
74 | 77 |
trim_whitespaces(&value); |
75 | 78 |
|
76 | 79 |
if(strncasecmp(name.s, "alg", name.len) == 0) { |
77 | 80 |
SEC_COPY_STR_PARAM(ret->r_alg, value); |
81 |
+ |
|
82 |
+ if(ipsec_preferred_alg.len && STR_EQ(value, ipsec_preferred_alg)) { |
|
83 |
+ *alg_found = 1; |
|
84 |
+ } |
|
78 | 85 |
} |
79 | 86 |
else if(strncasecmp(name.s, "prot", name.len) == 0) { |
80 | 87 |
SEC_COPY_STR_PARAM(ret->prot, value); |
... | ... |
@@ -84,6 +91,10 @@ static int process_sec_agree_param(str name, str value, ipsec_t *ret) |
84 | 91 |
} |
85 | 92 |
else if(strncasecmp(name.s, "ealg", name.len) == 0) { |
86 | 93 |
SEC_COPY_STR_PARAM(ret->r_ealg, value); |
94 |
+ |
|
95 |
+ if(ipsec_preferred_ealg.len && STR_EQ(value, ipsec_preferred_ealg)) { |
|
96 |
+ *ealg_found = 1; |
|
97 |
+ } |
|
87 | 98 |
} |
88 | 99 |
else if(strncasecmp(name.s, "spi-c", name.len) == 0) { |
89 | 100 |
ret->spi_uc = parse_digits(value); |
... | ... |
@@ -157,11 +168,14 @@ static security_t* parse_sec_agree(struct hdr_field* h) |
157 | 168 |
body.s=body.s+i+1; |
158 | 169 |
body.len=body.len-i-1; |
159 | 170 |
|
171 |
+ char preferred_alg_found = 0; |
|
172 |
+ char preferred_ealg_found = 0; |
|
173 |
+ |
|
160 | 174 |
// get the rest of the parameters |
161 | 175 |
i = 0; |
162 | 176 |
while(i <= body.len) { |
163 | 177 |
//look for end of buffer or parameter separator |
164 |
- if(i == body.len || body.s[i] == ';' ) { |
|
178 |
+ if(i == body.len || body.s[i] == ';' || body.s[i] == ',' || body.s[i] == ' ') { |
|
165 | 179 |
if(name.len) { |
166 | 180 |
// if(name.len) => a param name is parsed |
167 | 181 |
// and now i points to the end of its value |
... | ... |
@@ -176,9 +190,25 @@ static security_t* parse_sec_agree(struct hdr_field* h) |
176 | 190 |
i=0; |
177 | 191 |
|
178 | 192 |
if(name.len && value.len) { |
179 |
- if(process_sec_agree_param(name, value, params->data.ipsec)) { |
|
193 |
+ if(strncasecmp(name.s, "alg", name.len) == 0) { |
|
194 |
+ if(preferred_alg_found && preferred_ealg_found) { |
|
195 |
+ break; |
|
196 |
+ } |
|
197 |
+ preferred_alg_found = 0; |
|
198 |
+ preferred_ealg_found = 0; |
|
199 |
+ } |
|
200 |
+ |
|
201 |
+ char alg_found = 0; |
|
202 |
+ char ealg_found = 0; |
|
203 |
+ if(process_sec_agree_param(name, value, params->data.ipsec, &alg_found, &ealg_found)) { |
|
180 | 204 |
goto cleanup; |
181 | 205 |
} |
206 |
+ if(alg_found) { |
|
207 |
+ preferred_alg_found = 1; |
|
208 |
+ } |
|
209 |
+ if(ealg_found) { |
|
210 |
+ preferred_ealg_found = 1; |
|
211 |
+ } |
|
182 | 212 |
} |
183 | 213 |
//else - something's wrong. Ignore! |
184 | 214 |
|
... | ... |
@@ -26,23 +26,65 @@ |
26 | 26 |
#include <pthread.h> |
27 | 27 |
#include "../../core/mem/shm_mem.h" |
28 | 28 |
|
29 |
+#define MAX_HASH_SPI 10000 |
|
30 |
+ |
|
29 | 31 |
typedef struct spi_generator{ |
30 | 32 |
pthread_mutex_t spis_mut; |
31 |
- spi_list_t used_spis; |
|
33 |
+ spi_list_t used_spis[MAX_HASH_SPI]; |
|
34 |
+ spi_list_t free_spi; |
|
32 | 35 |
uint32_t spi_val; |
33 | 36 |
uint32_t min_spi; |
34 | 37 |
uint32_t max_spi; |
38 |
+ uint32_t sport_start_val; |
|
39 |
+ uint32_t cport_start_val; |
|
40 |
+ uint32_t port_range; |
|
35 | 41 |
} spi_generator_t; |
36 | 42 |
|
37 | 43 |
spi_generator_t* spi_data = NULL; |
38 | 44 |
|
39 |
-int init_spi_gen(uint32_t start_val, uint32_t range) |
|
45 |
+static int init_free_spi() |
|
40 | 46 |
{ |
41 |
- if(start_val < 1) { |
|
47 |
+ uint32_t sport_start_val, cport_start_val, port_range, sport, cport, j; |
|
48 |
+ |
|
49 |
+ if(!spi_data) { |
|
50 |
+ return 1; |
|
51 |
+ } |
|
52 |
+ |
|
53 |
+ sport_start_val = spi_data->sport_start_val; |
|
54 |
+ cport_start_val = spi_data->cport_start_val; |
|
55 |
+ port_range = spi_data->port_range; |
|
56 |
+ //save the initial value for the highly unlikely case where there are no free SPIs |
|
57 |
+ sport = sport_start_val; |
|
58 |
+ cport = cport_start_val; |
|
59 |
+ |
|
60 |
+ spi_data->free_spi = create_list(); |
|
61 |
+ for(j = spi_data->min_spi; j < spi_data->max_spi; j+=2) |
|
62 |
+ { |
|
63 |
+ spi_add(&spi_data->free_spi, j, j+1, cport, sport); |
|
64 |
+ cport++; |
|
65 |
+ sport++; |
|
66 |
+ |
|
67 |
+ if(cport >= cport_start_val + port_range) { |
|
68 |
+ cport = cport_start_val; |
|
69 |
+ } |
|
70 |
+ |
|
71 |
+ if(sport >= sport_start_val + port_range) { |
|
72 |
+ sport = sport_start_val; |
|
73 |
+ } |
|
74 |
+ } |
|
75 |
+ |
|
76 |
+ return 0; |
|
77 |
+} |
|
78 |
+ |
|
79 |
+int init_spi_gen(uint32_t spi_start_val, uint32_t spi_range, uint32_t sport_start_val, uint32_t cport_start_val, uint32_t port_range) |
|
80 |
+{ |
|
81 |
+ uint32_t j; |
|
82 |
+ |
|
83 |
+ if(spi_start_val < 1) { |
|
42 | 84 |
return 1; |
43 | 85 |
} |
44 | 86 |
|
45 |
- if(UINT32_MAX - range < start_val) { |
|
87 |
+ if(UINT32_MAX - spi_range < spi_start_val) { |
|
46 | 88 |
return 2; |
47 | 89 |
} |
48 | 90 |
|
... | ... |
@@ -64,67 +106,60 @@ int init_spi_gen(uint32_t start_val, uint32_t range) |
64 | 106 |
return 6; |
65 | 107 |
} |
66 | 108 |
|
67 |
- spi_data->used_spis = create_list(); |
|
109 |
+ for(j = 0; j < MAX_HASH_SPI; j++) { |
|
110 |
+ spi_data->used_spis[j] = create_list(); |
|
111 |
+ } |
|
112 |
+ |
|
113 |
+ spi_data->spi_val = spi_data->min_spi = spi_start_val; |
|
114 |
+ spi_data->max_spi = spi_start_val + spi_range; |
|
115 |
+ spi_data->sport_start_val = sport_start_val; |
|
116 |
+ spi_data->cport_start_val = cport_start_val; |
|
117 |
+ spi_data->port_range = port_range; |
|
68 | 118 |
|
69 |
- spi_data->spi_val = spi_data->min_spi = start_val; |
|
70 |
- spi_data->max_spi = start_val + range; |
|
119 |
+ if(init_free_spi() != 0) { |
|
120 |
+ return 7; |
|
121 |
+ } |
|
71 | 122 |
|
72 | 123 |
pthread_mutex_unlock(&spi_data->spis_mut); |
73 | 124 |
|
74 | 125 |
return 0; |
75 | 126 |
} |
76 | 127 |
|
77 |
-uint32_t acquire_spi() |
|
128 |
+uint32_t acquire_spi(uint32_t* spi_cid, uint32_t* spi_sid, uint16_t* cport, uint16_t* sport) |
|
78 | 129 |
{ |
79 | 130 |
if(!spi_data){ |
131 |
+ LM_ERR("spi_data is NULL\n"); |
|
80 | 132 |
return 0; |
81 | 133 |
} |
82 | 134 |
|
83 | 135 |
if(pthread_mutex_lock(&spi_data->spis_mut) != 0){ |
136 |
+ LM_ERR("spi_data failed to lock\n"); |
|
84 | 137 |
return 0; |
85 | 138 |
} |
86 | 139 |
|
87 |
- //save the initial value for the highly unlikely case where there are no free SPIs |
|
88 |
- uint32_t initial_val = spi_data->spi_val; |
|
89 |
- uint32_t ret = 0; // by default return invalid SPI |
|
90 |
- |
|
91 |
- while(1) { |
|
92 |
- if(spi_in_list(&spi_data->used_spis, spi_data->spi_val) == 0){ |
|
93 |
- ret = spi_data->spi_val; |
|
94 |
- spi_data->spi_val++; |
|
95 |
- |
|
96 |
- if(spi_data->spi_val >= spi_data->max_spi) { //reached the top of the range - reset |
|
97 |
- spi_data->spi_val = spi_data->min_spi; |
|
98 |
- } |
|
99 |
- |
|
100 |
- break; |
|
101 |
- } |
|
102 |
- |
|
103 |
- spi_data->spi_val++; //the current SPI is not available - increment |
|
104 |
- |
|
105 |
- if(spi_data->spi_val >= spi_data->max_spi){ //reached the top of the range - reset |
|
106 |
- spi_data->spi_val = spi_data->min_spi; |
|
107 |
- } |
|
108 |
- |
|
109 |
- if(spi_data->spi_val == initial_val){ //there are no free SPIs |
|
110 |
- pthread_mutex_unlock(&spi_data->spis_mut); |
|
111 |
- return ret; |
|
112 |
- } |
|
113 |
- |
|
140 |
+ if(!spi_data->free_spi.head) |
|
141 |
+ { |
|
142 |
+ LM_ERR("spi_data:%p spi_data->free_spi.head %p\n", spi_data, spi_data->free_spi.head); |
|
143 |
+ pthread_mutex_unlock(&spi_data->spis_mut); |
|
144 |
+ return 0; |
|
114 | 145 |
} |
115 | 146 |
|
116 |
- //found unused SPI - add it to the used list |
|
117 |
- if(spi_add(&spi_data->used_spis, ret) != 0){ |
|
118 |
- ret = 0; |
|
119 |
- } |
|
147 |
+ *spi_cid = spi_data->free_spi.head->spi_cid; |
|
148 |
+ *spi_sid = spi_data->free_spi.head->spi_sid; |
|
149 |
+ *sport = spi_data->free_spi.head->sport; |
|
150 |
+ *cport = spi_data->free_spi.head->cport; |
|
151 |
+ spi_remove_head(&spi_data->free_spi); |
|
152 |
+ spi_add(&spi_data->used_spis[*spi_cid % MAX_HASH_SPI], *spi_cid, *spi_sid, *cport, *sport); |
|
153 |
+ pthread_mutex_unlock(&spi_data->spis_mut); |
|
120 | 154 |
|
121 |
- pthread_mutex_unlock(&spi_data->spis_mut); |
|
155 |
+ LM_DBG("spi acquired spi_cid:%u spi_sid:%u sport:%u cport:%u \n", *spi_cid, *spi_sid, *sport, *cport); |
|
122 | 156 |
|
123 |
- return ret; |
|
157 |
+ return 1; |
|
124 | 158 |
} |
125 | 159 |
|
126 |
-int release_spi(uint32_t id) |
|
160 |
+int release_spi(uint32_t spi_cid, uint32_t spi_sid, uint16_t cport, uint16_t sport) |
|
127 | 161 |
{ |
162 |
+ LM_DBG("releasing spi spi_data:%p spi_cid:%u spi_sid:%u cport:%u sport:%u\n", spi_data, spi_cid, spi_sid, cport, sport); |
|
128 | 163 |
if(!spi_data){ |
129 | 164 |
return 1; |
130 | 165 |
} |
... | ... |
@@ -133,7 +168,11 @@ int release_spi(uint32_t id) |
133 | 168 |
return 1; |
134 | 169 |
} |
135 | 170 |
|
136 |
- spi_remove(&spi_data->used_spis, id); |
|
171 |
+ // if we successfully remove from used spi we will insert into free spi |
|
172 |
+ if(spi_remove(&spi_data->used_spis[spi_cid % MAX_HASH_SPI], spi_cid, spi_sid)) |
|
173 |
+ { |
|
174 |
+ spi_add(&spi_data->free_spi, spi_cid, spi_sid, cport, sport); |
|
175 |
+ } |
|
137 | 176 |
|
138 | 177 |
pthread_mutex_unlock(&spi_data->spis_mut); |
139 | 178 |
|
... | ... |
@@ -142,6 +181,8 @@ int release_spi(uint32_t id) |
142 | 181 |
|
143 | 182 |
int clean_spi_list() |
144 | 183 |
{ |
184 |
+ uint32_t j; |
|
185 |
+ |
|
145 | 186 |
if(!spi_data){ |
146 | 187 |
return 1; |
147 | 188 |
} |
... | ... |
@@ -150,7 +191,13 @@ int clean_spi_list() |
150 | 191 |
return 1; |
151 | 192 |
} |
152 | 193 |
|
153 |
- destroy_list(&spi_data->used_spis); |
|
194 |
+ for(j = 0; j < MAX_HASH_SPI; j++) { |
|
195 |
+ destroy_list(&spi_data->used_spis[j]); |
|
196 |
+ } |
|
197 |
+ |
|
198 |
+ destroy_list(&spi_data->free_spi); |
|
199 |
+ init_free_spi(); |
|
200 |
+ |
|
154 | 201 |
spi_data->spi_val = spi_data->min_spi; |
155 | 202 |
|
156 | 203 |
pthread_mutex_unlock(&spi_data->spis_mut); |
... | ... |
@@ -164,7 +211,7 @@ int destroy_spi_gen() |
164 | 211 |
return 1; |
165 | 212 |
} |
166 | 213 |
|
167 |
- destroy_list(&spi_data->used_spis); |
|
214 |
+ clean_spi_list(); |
|
168 | 215 |
|
169 | 216 |
int ret = pthread_mutex_destroy(&spi_data->spis_mut); |
170 | 217 |
shm_free(spi_data); |
... | ... |
@@ -31,10 +31,10 @@ |
31 | 31 |
// is important not to use generate ID which is still in use. For this reason there are |
32 | 32 |
// acquire_spi() and release_spi(uint32_t id) functions. |
33 | 33 |
|
34 |
-int init_spi_gen(uint32_t start_val, uint32_t range); |
|
34 |
+int init_spi_gen(uint32_t spi_start_val, uint32_t spi_range, uint32_t sport_start_val, uint32_t cport_start_val, uint32_t port_range); |
|
35 | 35 |
int clean_spi_list(); |
36 | 36 |
int destroy_spi_gen(); |
37 |
-uint32_t acquire_spi(); |
|
38 |
-int release_spi(uint32_t id); |
|
37 |
+uint32_t acquire_spi(uint32_t* spi_cid, uint32_t* spi_sid, uint16_t* cport, uint16_t* sport); |
|
38 |
+int release_spi(uint32_t spi_cid, uint32_t spi_sid, uint16_t cport, uint16_t sport); |
|
39 | 39 |
|
40 | 40 |
#endif /* _SPI_GEN_H_ */ |
... | ... |
@@ -50,7 +50,7 @@ void destroy_list(spi_list_t* lst) |
50 | 50 |
lst->tail = NULL; |
51 | 51 |
} |
52 | 52 |
|
53 |
-int spi_add(spi_list_t* list, uint32_t id) |
|
53 |
+int spi_add(spi_list_t* list, uint32_t spi_cid, uint32_t spi_sid, uint16_t sport, uint16_t cport) |
|
54 | 54 |
{ |
55 | 55 |
if(!list){ |
56 | 56 |
return 1; |
... | ... |
@@ -62,7 +62,10 @@ int spi_add(spi_list_t* list, uint32_t id) |
62 | 62 |
return 1; |
63 | 63 |
|
64 | 64 |
n->next = NULL; |
65 |
- n->id = id; |
|
65 |
+ n->spi_cid = spi_cid; |
|
66 |
+ n->spi_sid = spi_sid; |
|
67 |
+ n->sport = sport; |
|
68 |
+ n->cport = cport; |
|
66 | 69 |
|
67 | 70 |
//when list is empty |
68 | 71 |
if(!list->head) { |
... | ... |
@@ -71,37 +74,31 @@ int spi_add(spi_list_t* list, uint32_t id) |
71 | 74 |
return 0; |
72 | 75 |
} |
73 | 76 |
|
74 |
- //all other cases - list should be sorted |
|
75 |
- spi_node_t* c = list->head; |
|
76 |
- spi_node_t* p = NULL; |
|
77 |
- while(c && (n->id > c->id)) { |
|
78 |
- p = c; |
|
79 |
- c = c->next; |
|
80 |
- } |
|
77 |
+ list->tail->next = n; |
|
78 |
+ list->tail = n; |
|
81 | 79 |
|
80 |
+ return 0; |
|
81 |
+} |
|
82 | 82 |
|
83 |
- if(c == NULL) { //first of all - at the end of the list? |
|
84 |
- list->tail->next = n; |
|
85 |
- list->tail = n; |
|
86 |
- } |
|
87 |
- else if(n->id == c->id) { //c is not NULL, so check for duplicates |
|
88 |
- shm_free(n); |
|
83 |
+int spi_remove_head(spi_list_t* list) |
|
84 |
+{ |
|
85 |
+ if(!list) { |
|
89 | 86 |
return 1; |
90 | 87 |
} |
91 |
- else if(c == list->head) { //at the start of the list? |
|
92 |
- n->next = list->head; |
|
93 |
- list->head = n; |
|
94 |
- } |
|
95 |
- else { //not a special case - just add it |
|
96 |
- p->next = n; |
|
97 |
- n->next = c; |
|
88 |
+ |
|
89 |
+ //when list is empty |
|
90 |
+ if(!list->head) { |
|
91 |
+ return 1; |
|
98 | 92 |
} |
99 | 93 |
|
94 |
+ spi_node_t* t = list->head; |
|
95 |
+ list->head = t->next; |
|
96 |
+ shm_free(t); |
|
97 |
+ |
|
100 | 98 |
return 0; |
101 | 99 |
} |
102 | 100 |
|
103 |
- |
|
104 |
-int spi_remove(spi_list_t* list, uint32_t id) |
|
101 |
+int spi_remove(spi_list_t* list, uint32_t spi_cid, uint32_t spi_sid) |
|
105 | 102 |
{ |
106 | 103 |
if(!list){ |
107 | 104 |
return 0; |
... | ... |
@@ -113,7 +110,7 @@ int spi_remove(spi_list_t* list, uint32_t id) |
113 | 110 |
} |
114 | 111 |
|
115 | 112 |
//when target is head |
116 |
- if(list->head->id == id) { |
|
113 |
+ if(list->head->spi_cid == spi_cid && list->head->spi_sid == spi_sid) { |
|
117 | 114 |
spi_node_t* t = list->head; |
118 | 115 |
list->head = t->next; |
119 | 116 |
|
... | ... |
@@ -123,7 +120,7 @@ int spi_remove(spi_list_t* list, uint32_t id) |
123 | 120 |
} |
124 | 121 |
|
125 | 122 |
shm_free(t); |
126 |
- return 0; |
|
123 |
+ return 1; |
|
127 | 124 |
} |
128 | 125 |
|
129 | 126 |
|
... | ... |
@@ -131,7 +128,7 @@ int spi_remove(spi_list_t* list, uint32_t id) |
131 | 128 |
spi_node_t* curr = list->head->next; |
132 | 129 |
|
133 | 130 |
while(curr) { |
134 |
- if(curr->id == id) { |
|
131 |
+ if(curr->spi_cid == spi_cid && curr->spi_sid == spi_sid) { |
|
135 | 132 |
spi_node_t* t = curr; |
136 | 133 |
|
137 | 134 |
//detach node |
... | ... |
@@ -143,7 +140,7 @@ int spi_remove(spi_list_t* list, uint32_t id) |
143 | 140 |
} |
144 | 141 |
|
145 | 142 |
shm_free(t); |
146 |
- return 0; |
|
143 |
+ return 1; |
|
147 | 144 |
} |
148 | 145 |
|
149 | 146 |
prev = curr; |
... | ... |
@@ -153,7 +150,7 @@ int spi_remove(spi_list_t* list, uint32_t id) |
153 | 150 |
return -1; // out of scope |
154 | 151 |
} |
155 | 152 |
|
156 |
-int spi_in_list(spi_list_t* list, uint32_t id) |
|
153 |
+int spi_in_list(spi_list_t* list, uint32_t spi_cid, uint32_t spi_sid) |
|
157 | 154 |
{ |
158 | 155 |
if(!list){ |
159 | 156 |
return 0; |
... | ... |
@@ -162,14 +159,11 @@ int spi_in_list(spi_list_t* list, uint32_t id) |
162 | 159 |
if(!list->head) |
163 | 160 |
return 0; |
164 | 161 |
|
165 |
- if(id < list->head->id || id > list->tail->id) |
|
166 |
- return 0; |
|
167 |
- |
|
168 | 162 |
spi_node_t* n = list->head; |
169 | 163 |
while(n) { |
170 |
- if (n->id == id) |
|
164 |
+ if (n->spi_cid == spi_cid && n->spi_sid == spi_sid) { |
|
171 | 165 |
return 1; |
172 |
- |
|
166 |
+ } |
|
173 | 167 |
n = n->next; |
174 | 168 |
} |
175 | 169 |
|
... | ... |
@@ -35,7 +35,10 @@ typedef struct _spi_node spi_node_t; |
35 | 35 |
|
36 | 36 |
struct _spi_node { |
37 | 37 |
spi_node_t* next; |
38 |
- uint32_t id; |
|
38 |
+ uint32_t spi_cid; |
|
39 |
+ uint32_t spi_sid; |
|
40 |
+ uint16_t sport; |
|
41 |
+ uint16_t cport; |
|
39 | 42 |
}; |
40 | 43 |
|
41 | 44 |
typedef struct _spi_list { |
... | ... |
@@ -46,8 +49,9 @@ typedef struct _spi_list { |
46 | 49 |
|
47 | 50 |
spi_list_t create_list(); |
48 | 51 |
void destroy_list(spi_list_t* lst); |
49 |
-int spi_add(spi_list_t* list, uint32_t id); |
|
50 |
-int spi_remove(spi_list_t* list, uint32_t id); |
|
51 |
-int spi_in_list(spi_list_t* list, uint32_t id); |
|
52 |
+int spi_add(spi_list_t* list, uint32_t spi_cid, uint32_t spi_sid, uint16_t cport, uint16_t sport); |
|
53 |
+int spi_remove_head(spi_list_t* list); |
|
54 |
+int spi_remove(spi_list_t* list, uint32_t spi_cid, uint32_t spi_sid); |
|
55 |
+int spi_in_list(spi_list_t* list, uint32_t spi_cid, uint32_t spi_sid); |
|
52 | 56 |
|
53 | 57 |
#endif /* _SPI_LIST_H_ */ |