From b3677f7508cfdcea54f48ed01688fa0cf9380e58 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Thu, 26 Mar 2020 16:18:17 +0100 Subject: [PATCH] usrloc: ability to send keep alive requests - GH #2223 - work in progress --- src/modules/usrloc/udomain.c | 2 + src/modules/usrloc/ul_keepalive.c | 239 ++++++++++++++++++++++++++++++ src/modules/usrloc/ul_keepalive.h | 31 ++++ src/modules/usrloc/usrloc_mod.c | 9 ++ 4 files changed, 281 insertions(+) create mode 100644 src/modules/usrloc/ul_keepalive.c create mode 100644 src/modules/usrloc/ul_keepalive.h diff --git a/src/modules/usrloc/udomain.c b/src/modules/usrloc/udomain.c index 8050a21ce5a..59ddff92d48 100644 --- a/src/modules/usrloc/udomain.c +++ b/src/modules/usrloc/udomain.c @@ -41,6 +41,7 @@ #include "utime.h" #include "usrloc.h" #include "ul_callback.h" +#include "ul_keepalive.h" #include "urecord.h" extern int ul_rm_expired_delay; @@ -1228,6 +1229,7 @@ void mem_timer_udomain(udomain_t* _d, int istart, int istep) ptr = ptr->next; mem_delete_urecord(_d, t); } else { + ul_ka_urecord(ptr); ptr = ptr->next; } } diff --git a/src/modules/usrloc/ul_keepalive.c b/src/modules/usrloc/ul_keepalive.c new file mode 100644 index 00000000000..7b6521ae512 --- /dev/null +++ b/src/modules/usrloc/ul_keepalive.c @@ -0,0 +1,239 @@ +/* + * Usrloc module - keepalive + * + * Copyright (C) 2020 Asipto.com + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * Kamailio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include + +#include "../../core/dprint.h" +#include "../../core/ut.h" +#include "../../core/resolve.h" +#include "../../core/forward.h" +#include "../../core/parser/parse_uri.h" +#include "../../core/parser/parse_from.h" +#include "../../core/parser/parse_to.h" +#include "../../core/parser/parse_rr.h" + +#include "ul_keepalive.h" + +static int ul_ka_send(str *kamsg, dest_info_t *kadst); + +/** + * +_KAMETHOD_ _URI_ SIP/2.0\r\n +Via: SIP/2.0/_PROTO_ _IP_:_PORT_\r\n +__KAROUTES__ +From: <_KAFROM_>;tag=_KAFROMTAG_\r\n +To: \r\n +Call-ID: _KACALLID_\r\n +CSeq: 1 _KAMETHOD_\r\n +Content-Length: 0\r\n\r\n" + +*/ + +#define ULKA_CALLID_PREFIX "ksrulka-" +#define ULKA_CALLID_PREFIX_LEN (sizeof(ULKA_CALLID_PREFIX) - 1) + +#define ULKA_MSG "%.*s %.*s SIP/2.0\r\n" \ + "Via: SIP/2.0/%.*s %.*s:%.*s;branch=z9hG4bKx.%u.%u.0\r\n" \ + "%.*s%.*s" \ + "From: <%.*s>;tag=%.*s-%x-%lx-%x-%x.%x\r\n" \ + "To: \r\n" \ + "Call-ID: " ULKA_CALLID_PREFIX "%u.%u\r\n" \ + "CSeq: 80 %.*s\r\n" \ + "Content-Length: 0\r\n\r\n" + +extern str ul_ka_from; +extern str ul_ka_domain; +extern str ul_ka_method; +extern int ul_ka_mode; +extern unsigned int nat_bflag; + +static unsigned int _ul_ka_counter = 0; + +int ul_ka_urecord(urecord_t *ur) +{ + ucontact_t *uc; +#define ULKA_BUF_SIZE 2048 + char kabuf[ULKA_BUF_SIZE]; + int kabuf_len; + str kamsg; + str vaddr; + str vport; + str sdst = STR_NULL; + str sproto = STR_NULL; + sip_uri_t duri; + char dproto; + struct hostent *he; + socket_info_t *ssock; + dest_info_t idst; + unsigned int bcnt = 0; + int aortype = 0; + int i; + struct timeval tv; + + if (ul_ka_mode == 0) { + return 0; + } + LM_DBG("keepalive for aor: %.*s\n", ur->aor.len, ur->aor.s); + + for(i=0; iaor.len; i++) { + if(ur->aor.s[i] == '@') { + aortype = 1; + break; + } + } + _ul_ka_counter++; + for (uc = ur->contacts; uc != NULL; uc = uc->next) { + if (uc->c.len <= 0) { + continue; + } + if(ul_ka_mode == 2) { + /* keepalive for natted contacts only */ + if (nat_bflag == 0) { + continue; + } + if ((uc->cflags & nat_bflag) != nat_bflag) { + continue; + } + } + if(uc->received.len > 0) { + sdst = uc->received; + } else { + if (uc->path.len > 0) { + if(get_path_dst_uri(&uc->path, &sdst) < 0) { + LM_ERR("failed to get first uri for path\n"); + continue; + } + } else { + sdst = uc->c; + } + } + if(parse_uri(sdst.s, sdst.len, &duri) < 0) { + LM_ERR("cannot parse next hop uri\n"); + continue; + } + + if(duri.port_no == 0) { + duri.port_no = SIP_PORT; + } + dproto = duri.proto; + he = sip_resolvehost(&duri.host, &duri.port_no, &dproto); + if(he == NULL) { + LM_ERR("can't resolve_host\n"); + continue; + } + init_dest_info(&idst); + hostent2su(&idst.to, he, 0, duri.port_no); + ssock = uc->sock; + if(ssock == NULL) { + ssock = get_send_socket(0, &idst.to, dproto); + } + if(ssock == NULL) { + LM_ERR("cannot get sending socket\n"); + continue; + } + idst.proto = dproto; + idst.send_sock = ssock; + + if(ssock->useinfo.name.len > 0) { + vaddr = ssock->useinfo.name; + } else { + vaddr = ssock->address_str; + } + if(ssock->useinfo.port_no > 0) { + vport = ssock->useinfo.port_no_str; + } else { + vport = ssock->port_no_str; + } + get_valid_proto_string(dproto, 1, 1, &sproto); + + bcnt++; + gettimeofday(&tv, NULL); + kabuf_len = snprintf(kabuf, ULKA_BUF_SIZE - 1, ULKA_MSG, + ul_ka_method.len, ul_ka_method.s, + uc->c.len, uc->c.s, + sproto.len, sproto.s, + vaddr.len, vaddr.s, + vport.len, vport.s, + _ul_ka_counter, bcnt, + (uc->path.len>0)?uc->path.len:0, + (uc->path.len>0)?uc->path.s:"", + (uc->path.len>0)?2:0, + (uc->path.len>0)?"\r\n":"", + ul_ka_from.len, ul_ka_from.s, + uc->ruid.len, uc->ruid.s, ur->aorhash, + tv.tv_sec, tv.tv_usec, _ul_ka_counter, bcnt, + ur->aor.len, ur->aor.s, + (aortype==1)?"":"@", + (aortype==1)?0:ul_ka_domain.len, (aortype==1)?"":ul_ka_domain.s, + _ul_ka_counter, bcnt, + ul_ka_method.len, ul_ka_method.s); + if(kabuf_len<=0 || kabuf_len>=ULKA_BUF_SIZE) { + LM_ERR("failed to print the keepalive request\n"); + } else { + LM_DBG("keepalive request (len: %d) [[\n%.*s]]\n", + kabuf_len, kabuf_len, kabuf); + kamsg.s = kabuf; + kamsg.len = kabuf_len; + ul_ka_send(&kamsg, &idst); + } + + } + return 0; +} + +static int ul_ka_send(str *kamsg, dest_info_t *kadst) +{ + if (kadst->proto == PROTO_UDP) { + return udp_send(kadst, kamsg->s, kamsg->len); + } + +#ifdef USE_TCP + else if(kadst->proto == PROTO_TCP) { + /*tcp*/ + kadst->id=0; + return tcp_send(kadst, 0, kamsg->s, kamsg->len); + } +#endif +#ifdef USE_TLS + else if(kadst->proto == PROTO_TLS) { + /*tls*/ + kadst->id=0; + return tcp_send(kadst, 0, kamsg->s, kamsg->len); + } +#endif +#ifdef USE_SCTP + else if(kadst->proto == PROTO_SCTP) { + /*sctp*/ + return sctp_core_msg_send(kadst, kamsg->s, kamsg->len); + } +#endif + else { + LM_ERR("unknown proto [%d] for sending keepalive\n", + kadst->proto); + return -1; + } +} \ No newline at end of file diff --git a/src/modules/usrloc/ul_keepalive.h b/src/modules/usrloc/ul_keepalive.h new file mode 100644 index 00000000000..1eaea7ffa9a --- /dev/null +++ b/src/modules/usrloc/ul_keepalive.h @@ -0,0 +1,31 @@ +/* + * Usrloc module - keepalive + * + * Copyright (C) 2020 Asipto.com + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * Kamailio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _UL_KEEPALIVE_H_ +#define _UL_KEEPALIVE_H_ + +#include "urecord.h" + +int ul_ka_urecord(urecord_t *ur); + +#endif \ No newline at end of file diff --git a/src/modules/usrloc/usrloc_mod.c b/src/modules/usrloc/usrloc_mod.c index eb05305724e..9b9c3f68bf3 100644 --- a/src/modules/usrloc/usrloc_mod.c +++ b/src/modules/usrloc/usrloc_mod.c @@ -116,6 +116,11 @@ int ul_version_table = 1; str ul_xavp_contact_name = {0}; +str ul_ka_from = str_init("sip:server@kamailio.org"); +str ul_ka_domain = str_init("kamailio.org"); +str ul_ka_method = str_init("OPTIONS"); +int ul_ka_mode = 0; + /* sruid to get internal uid for mi/rpc commands */ sruid_t _ul_sruid; @@ -242,6 +247,10 @@ static param_export_t params[] = { {"db_timer_clean", PARAM_INT, &ul_db_timer_clean}, {"rm_expired_delay", PARAM_INT, &ul_rm_expired_delay}, {"version_table", PARAM_INT, &ul_version_table}, + {"ka_mode", PARAM_INT, &ul_ka_mode}, + {"ka_from", PARAM_STR, &ul_ka_from}, + {"ka_domain", PARAM_STR, &ul_ka_domain}, + {"ka_method", PARAM_STR, &ul_ka_method}, {0, 0, 0} };