From 9115d74b33aefb0febad7c7fffe7d184e4066b77 Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Mon, 23 Aug 2021 21:50:50 +0300 Subject: [PATCH] lcr: source port check for from_any_gw() and from_gw(). A simple change, which allows to check, if a coming request matches not only by an IP address and a transport protocol, but also using the source port of a request. Improvements are done for the following functions of the lcr module: - from_any_gw() - from_gw() Back compatibility provided, hence it does not affect already existing behavior. --- src/modules/lcr/doc/lcr_admin.xml | 31 ++++---- src/modules/lcr/lcr_mod.c | 116 +++++++++++++++++++++++++----- 2 files changed, 116 insertions(+), 31 deletions(-) diff --git a/src/modules/lcr/doc/lcr_admin.xml b/src/modules/lcr/doc/lcr_admin.xml index 2c5bfb0d85a..f6461e1a24f 100644 --- a/src/modules/lcr/doc/lcr_admin.xml +++ b/src/modules/lcr/doc/lcr_admin.xml @@ -1425,16 +1425,16 @@ defunct_gw(60);
- <function moreinfo="none">from_gw(lcr_id[, ip_addr, proto])</function> + <function moreinfo="none">from_gw(lcr_id[, ip_addr, proto[, src_port]])</function> - Checks if request comes from IP address and transport protocol + Checks if request comes from IP address, transport protocol and source port specified for a gateway in LCR instance lcr_id. Fails if the LCR instance includes one or more gateways without IP address. - IP address and transport protocol to be checked are either - taken from source IP address of the request or - (if present) from ip_addr and proto arguments. + IP address, transport protocol and source port to be checked are either + taken from source IP address and port of the request or + (if present) from ip_addr, proto and src_port arguments. lcr_id can be an integer constant or a pseudo variable @@ -1442,7 +1442,8 @@ defunct_gw(60); variable holding a string value. proto can be an integer constant (0 = ANY, 1 = UDP, 2 = TCP, 3 = TLS, 4 = SCTP) or a pseudo variable holding such an - integer value. + integer value. src_port can be an integer or a pseudo variable + holding such an integer value. If request comes from a gateway, gateway's tag and flags are @@ -1466,7 +1467,7 @@ defunct_gw(60); <function>from_gw</function> usage ... -if (from_gw(1, $avp(real_source_addr), 2) { +if (from_gw(1, $avp(real_source_addr), 2, 5060) { ... }; ... @@ -1476,21 +1477,21 @@ if (from_gw(1, $avp(real_source_addr), 2) {
- <function moreinfo="none">from_any_gw([ip_addr, proto])</function> + <function moreinfo="none">from_any_gw([ip_addr, proto[, src_port]])</function> - Checks if request comes from IP address and transport - protocol specified for any gateway. Only LCR instances, + Checks if request comes from IP address, transport protocol and source port + specified for any gateway. Only LCR instances, where all gateways have IP address, are included in the test. - IP address and transport protocol to be checked are either - taken from source IP address and transport protocol + IP address, transport protocol and source port to be checked are either + taken from source IP address, transport protocol and source port of the request or - (if present) from ip_addr and proto arguments. See from_gw() + (if present) from ip_addr, proto and src_port arguments. See from_gw() function for more info about the arguments. - If any gateway has the IP address and transport protocol, + If any gateway has the IP address, transport protocol and source port, function returns LCR identifier of the gateway. Returns -1 on error or if the request does not come from a gateway. @@ -1515,7 +1516,7 @@ if (from_gw(1, $avp(real_source_addr), 2) { <function>from_gw</function> usage ... -$var(lcr_id) = from_any_gw("192.168.1.1", 3); +$var(lcr_id) = from_any_gw("192.168.1.1", 3, 5061); ... diff --git a/src/modules/lcr/lcr_mod.c b/src/modules/lcr/lcr_mod.c index 579ec06d4d8..858352f2c72 100644 --- a/src/modules/lcr/lcr_mod.c +++ b/src/modules/lcr/lcr_mod.c @@ -260,8 +260,10 @@ static int inactivate_gw(struct sip_msg *_m, char *_s1, char *_s2); static int defunct_gw(struct sip_msg *_m, char *_s1, char *_s2); static int from_gw_1(struct sip_msg *_m, char *_s1, char *_s2); static int from_gw_3(struct sip_msg *_m, char *_s1, char *_s2, char *_s3); +static int from_gw_4(struct sip_msg *_m, char *_s1, char *_s2, char *_s3, char *_s4); static int from_any_gw_0(struct sip_msg *_m, char *_s1, char *_s2); static int from_any_gw_2(struct sip_msg *_m, char *_s1, char *_s2); +static int from_any_gw_3(struct sip_msg *_m, char *_s1, char *_s2, char *_s3); static int to_gw_1(struct sip_msg *_m, char *_s1, char *_s2); static int to_gw_3(struct sip_msg *_m, char *_s1, char *_s2, char *_s3); static int to_any_gw_0(struct sip_msg *_m, char *_s1, char *_s2); @@ -283,10 +285,14 @@ static cmd_export_t cmds[] = { REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE}, {"from_gw", (cmd_function)from_gw_3, 3, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE}, + {"from_gw", (cmd_function)from_gw_4, 4, 0, 0, + REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE}, {"from_any_gw", (cmd_function)from_any_gw_0, 0, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE}, {"from_any_gw", (cmd_function)from_any_gw_2, 2, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE}, + {"from_any_gw", (cmd_function)from_any_gw_3, 3, 0, 0, + REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE}, {"to_gw", (cmd_function)to_gw_1, 1, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE}, {"to_gw", (cmd_function)to_gw_3, 3, 0, 0, @@ -2978,7 +2984,7 @@ static int next_gw(struct sip_msg *_m, char *_s1, char *_s2) * Checks if request comes from ip address of a gateway */ static int do_from_gw(struct sip_msg *_m, unsigned int lcr_id, - struct ip_addr *src_addr, uri_transport transport) + struct ip_addr *src_addr, uri_transport transport, unsigned int src_port) { struct gw_info *res, gw, *gws; int_str val; @@ -2997,9 +3003,10 @@ static int do_from_gw(struct sip_msg *_m, unsigned int lcr_id, sizeof(struct gw_info), comp_gws); /* Store tag and flags and return result */ - if((res != NULL) && ((transport == PROTO_NONE) - || (res->transport_code == transport))) { - LM_DBG("request game from gw\n"); + if((res != NULL) + && ((transport == PROTO_NONE) || (res->transport_code == transport)) + && ((src_port == 0) || (res->port == src_port))) { + LM_DBG("request came from gw\n"); if(tag_avp_param) { val.s.s = res->tag; val.s.len = res->tag_len; @@ -3021,22 +3028,24 @@ static int do_from_gw(struct sip_msg *_m, unsigned int lcr_id, /* * Checks if request comes from ip address of a gateway taking source - * address and transport protocol from request. + * address, transport protocol and source port from request. */ static int ki_from_gw(sip_msg_t *_m, int lcr_id) { uri_transport transport; + unsigned int src_port; if((lcr_id < 1) || (lcr_id > lcr_count_param)) { LM_ERR("invalid lcr_id parameter value %d\n", lcr_id); return -1; } - /* Get transport protocol */ + /* Get transport protocol and port */ transport = _m->rcv.proto; + src_port = _m->rcv.src_port; /* Do test */ - return do_from_gw(_m, lcr_id, &_m->rcv.src_ip, transport); + return do_from_gw(_m, lcr_id, &_m->rcv.src_ip, transport, src_port); } static int from_gw_1(struct sip_msg *_m, char *_lcr_id, char *_s2) @@ -3056,10 +3065,10 @@ static int from_gw_1(struct sip_msg *_m, char *_lcr_id, char *_s2) /* * Checks if request comes from ip address of a gateway taking source - * address and transport protocol from parameters + * address, transport protocol and source port from parameters. */ static int ki_from_gw_addr( - sip_msg_t *_m, int lcr_id, str *addr_str, int transport) + sip_msg_t *_m, int lcr_id, str *addr_str, int transport, unsigned int src_port) { struct ip_addr src_addr; struct ip_addr *ip; @@ -3084,8 +3093,14 @@ static int ki_from_gw_addr( return -1; } + /* src_port set to 0 means we don't want to check it */ + if((src_port < 0) || (src_port > 65535)) { + LM_ERR("invalid port parameter value %d\n", transport); + return -1; + } + /* Do test */ - return do_from_gw(_m, lcr_id, &src_addr, transport); + return do_from_gw(_m, lcr_id, &src_addr, transport, src_port); } static int from_gw_3( @@ -3112,7 +3127,41 @@ static int from_gw_3( return -1; } - return ki_from_gw_addr(_m, lcr_id, &addr_str, transport); + return ki_from_gw_addr(_m, lcr_id, &addr_str, transport, 0); +} + +static int from_gw_4( + struct sip_msg *_m, char *_lcr_id, char *_addr, char *_transport, char *_src_port) +{ + int lcr_id; + str addr_str; + char *tmp; + uri_transport transport; + unsigned int src_port; + + /* Get and check parameter values */ + lcr_id = strtol(_lcr_id, &tmp, 10); + if((tmp == 0) || (*tmp) || (tmp == _lcr_id)) { + LM_ERR("invalid lcr_id parameter %s\n", _lcr_id); + return -1; + } + + addr_str.s = _addr; + addr_str.len = strlen(_addr); + + transport = strtol(_transport, &tmp, 10); + if((tmp == 0) || (*tmp) || (tmp == _transport)) { + LM_ERR("invalid transport parameter %s\n", _lcr_id); + return -1; + } + tmp=0; + src_port = strtol(_src_port, &tmp, 10); + if((tmp == 0) || (*tmp) || (tmp == _src_port)) { + LM_ERR("invalid port parameter %s\n", _src_port); + return -1; + } + + return ki_from_gw_addr(_m, lcr_id, &addr_str, transport, src_port); } /* @@ -3123,11 +3172,14 @@ static int ki_from_any_gw(sip_msg_t *_m) { unsigned int i; uri_transport transport; + unsigned int src_port; + /* Get transport protocol and port */ transport = _m->rcv.proto; + src_port = _m->rcv.src_port; for(i = 1; i <= lcr_count_param; i++) { - if(do_from_gw(_m, i, &_m->rcv.src_ip, transport) == 1) { + if(do_from_gw(_m, i, &_m->rcv.src_ip, transport, src_port) == 1) { return i; } } @@ -3141,9 +3193,9 @@ static int from_any_gw_0(struct sip_msg *_m, char *_s1, char *_s2) /* * Checks if request comes from ip address of a a gateway taking source - * IP address and transport protocol from parameters. + * IP address, transport protocol and source port from parameters. */ -static int ki_from_any_gw_addr(sip_msg_t *_m, str *addr_str, int transport) +static int ki_from_any_gw_addr(sip_msg_t *_m, str *addr_str, int transport, unsigned int src_port) { unsigned int i; struct ip_addr *ip, src_addr; @@ -3163,9 +3215,15 @@ static int ki_from_any_gw_addr(sip_msg_t *_m, str *addr_str, int transport) return -1; } + /* src_port set to 0 means we don't want to check it */ + if((src_port < 0) || (src_port > 65535)) { + LM_ERR("invalid port parameter value %d\n", transport); + return -1; + } + /* Do test */ for(i = 1; i <= lcr_count_param; i++) { - if(do_from_gw(_m, i, &src_addr, transport) == 1) { + if(do_from_gw(_m, i, &src_addr, transport, src_port) == 1) { return i; } } @@ -3188,7 +3246,33 @@ static int from_any_gw_2(struct sip_msg *_m, char *_addr, char *_transport) return -1; } - return ki_from_any_gw_addr(_m, &addr_str, transport); + return ki_from_any_gw_addr(_m, &addr_str, transport, 0); +} + +static int from_any_gw_3(struct sip_msg *_m, char *_addr, char *_transport, char *_src_port) +{ + str addr_str; + uri_transport transport; + unsigned int src_port; + char *tmp; + + /* Get and check parameter values */ + addr_str.s = _addr; + addr_str.len = strlen(_addr); + + transport = strtol(_transport, &tmp, 10); + if((tmp == 0) || (*tmp) || (tmp == _transport)) { + LM_ERR("invalid transport parameter %s\n", _transport); + return -1; + } + tmp=0; + src_port = strtol(_src_port, &tmp, 10); + if((tmp == 0) || (*tmp) || (tmp == _src_port)) { + LM_ERR("invalid port parameter %s\n", _src_port); + return -1; + } + + return ki_from_any_gw_addr(_m, &addr_str, transport, src_port); } /*