summaryrefslogtreecommitdiff
path: root/net/ser/files/patch-modules__nathelper__natping.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ser/files/patch-modules__nathelper__natping.c')
-rw-r--r--net/ser/files/patch-modules__nathelper__natping.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/net/ser/files/patch-modules__nathelper__natping.c b/net/ser/files/patch-modules__nathelper__natping.c
new file mode 100644
index 000000000000..ecd5ec1b0f3a
--- /dev/null
+++ b/net/ser/files/patch-modules__nathelper__natping.c
@@ -0,0 +1,258 @@
+
+$FreeBSD$
+
+--- /dev/null
++++ modules/nathelper/natping.c
+@@ -0,0 +1,252 @@
++/* $Id: patch-modules::nathelper::natping.c,v 1.4 2005/04/27 13:35:34 sobomax Exp $
++ *
++ * Copyright (C) 2005 Porta Software Ltd
++ *
++ * This file is part of ser, a free SIP server.
++ *
++ * ser 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
++ *
++ * For a license to use the ser software under conditions
++ * other than those described here, or to purchase support for this
++ * software, please contact iptel.org by e-mail at the following addresses:
++ * info@iptel.org
++ *
++ * ser 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ */
++
++#include <unistd.h>
++#include <signal.h>
++#include "../usrloc/usrloc.h"
++#include "../tm/tm_load.h"
++#include "../../dprint.h"
++#include "../../parser/parse_hostport.h"
++#include "../../resolve.h"
++#include "nathelper.h"
++
++int natping_interval = 0;
++/*
++ * If this parameter is set then the natpinger will ping only contacts
++ * that have the NAT flag set in user location database
++ */
++int ping_nated_only = 0;
++
++/*
++ * Ping method. Any word except NULL is treated as method name.
++ */
++char *natping_method = NULL;
++
++static pid_t aux_process = -1;
++static usrloc_api_t ul;
++/* TM bind */
++static struct tm_binds tmb;
++static int cblen = 0;
++static const char sbuf[4] = {0, 0, 0, 0};
++
++static void natping(unsigned int ticks, void *param);
++static void natping_cycle(void);
++
++int
++natpinger_init(void)
++{
++ bind_usrloc_t bind_usrloc;
++ load_tm_f load_tm;
++ char *p;
++
++ if (natping_interval > 0) {
++ bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);
++ if (!bind_usrloc) {
++ LOG(L_ERR, "ERROR: nathelper: natpinger_init: Can't find usrloc module\n");
++ return -1;
++ }
++
++ if (bind_usrloc(&ul) < 0) {
++ return -1;
++ }
++ if (natping_method != NULL) {
++ for (p = natping_method; *p != '\0'; ++p)
++ *p = toupper(*p);
++ if (strcmp(natping_method, "NULL") == 0)
++ natping_method = NULL;
++ }
++ if (natping_method != NULL) {
++ /* import the TM auto-loading function */
++ if (!(load_tm = (load_tm_f)find_export("load_tm", NO_SCRIPT, 0))) {
++ LOG(L_ERR, "ERROR: nathelper: natpinger_init: can't import load_tm\n");
++ return -1;
++ }
++ /* let the auto-loading function load all TM stuff */
++ if (load_tm(&tmb) == -1)
++ return -1;
++ }
++
++ /*
++ * Use timer only in single process. For forked SER,
++ * use separate process (see natpinger_child_init())
++ */
++ if (dont_fork)
++ register_timer(natping, NULL, natping_interval);
++ }
++
++ return 0;
++}
++
++int
++natpinger_child_init(int rank)
++{
++
++ /* If forking is prohibited, use only timer. */
++ if (dont_fork)
++ return 0;
++
++ /* don't do anything for main process and TCP manager process */
++ if (rank == PROC_MAIN || rank == PROC_TCP_MAIN)
++ return 0;
++
++ /* only child 1 will fork the aux process */
++ if (rank != 1)
++ return 0;
++
++ aux_process = fork();
++ if (aux_process == -1) {
++ LOG(L_ERR, "natping_child_init(): fork: %s\n", strerror(errno));
++ return -1;
++ }
++ if (aux_process == 0) {
++ natping_cycle();
++ /*UNREACHED*/
++ _exit(1);
++ }
++ return 0;
++}
++
++int
++natpinger_cleanup(void)
++{
++
++ if (aux_process != -1)
++ kill(aux_process, SIGTERM);
++ return 0;
++}
++
++static void
++natping_cycle(void)
++{
++
++ signal(SIGTERM, SIG_DFL); /* no special treat */
++ for(;;) {
++ sleep(natping_interval);
++ natping(0, NULL);
++ }
++}
++
++static void
++natping(unsigned int ticks, void *param)
++{
++ int rval, n;
++ void *buf, *cp;
++ str c;
++ struct sip_uri curi;
++ union sockaddr_union to;
++ struct hostent* he;
++ struct socket_info* send_sock;
++ char t;
++ str p_method, p_from;
++
++ buf = NULL;
++ if (cblen > 0) {
++ buf = pkg_malloc(cblen);
++ if (buf == NULL) {
++ LOG(L_ERR, "ERROR: nathelper::natping: out of memory\n");
++ return;
++ }
++ }
++ rval = ul.get_all_ucontacts(buf, cblen, (ping_nated_only ? FL_NAT : 0));
++ if (rval > 0) {
++ if (buf != NULL)
++ pkg_free(buf);
++ cblen = rval * 2;
++ buf = pkg_malloc(cblen);
++ if (buf == NULL) {
++ LOG(L_ERR, "ERROR: nathelper::natping: out of memory\n");
++ return;
++ }
++ rval = ul.get_all_ucontacts(buf, cblen, (ping_nated_only ? FL_NAT : 0));
++ if (rval != 0) {
++ pkg_free(buf);
++ return;
++ }
++ }
++
++ if (buf == NULL)
++ return;
++
++ cp = buf;
++ n = 0;
++ while (1) {
++ memcpy(&(c.len), cp, sizeof(c.len));
++ if (c.len == 0)
++ break;
++ c.s = (char*)cp + sizeof(c.len);
++ cp = (char*)cp + sizeof(c.len) + c.len;
++ if (parse_uri(c.s, c.len, &curi) < 0) {
++ LOG(L_ERR, "ERROR: nathelper::natping: can't parse contact uri\n");
++ continue;
++ }
++ if (curi.proto != PROTO_UDP && curi.proto != PROTO_NONE)
++ continue;
++
++ if ((++n % 50) == 0)
++ usleep(1);
++
++ if (natping_method != NULL) {
++ p_method.s = natping_method;
++ p_method.len = strlen(p_method.s);
++ p_from.s = "sip:registrar"; /* XXX */
++ p_from.len = strlen(p_from.s);
++ if (tmb.t_request(&p_method, &c, &c, &p_from,
++ NULL, NULL, NULL, NULL) == -1)
++ {
++ LOG(L_ERR, "nathelper::natping(): request() failed\n");
++ }
++ } else {
++ if (curi.maddr_val.len != 0) {
++ t = curi.maddr_val.s[curi.maddr_val.len];
++ curi.maddr_val.s[curi.maddr_val.len] = '\0';
++ parse_hostport(curi.maddr_val.s, &curi.host, &curi.port_no);
++ curi.maddr_val.s[curi.maddr_val.len] = t;
++ if (curi.host.len <= 0) {
++ LOG(L_ERR, "ERROR: nathelper::natping: invalid maddr in contact uri\n");
++ continue;
++ }
++ }
++
++ if (curi.port_no == 0)
++ curi.port_no = SIP_PORT;
++ he = sip_resolvehost(&curi.host, &curi.port_no, PROTO_UDP);
++ if (he == NULL){
++ LOG(L_ERR, "ERROR: nathelper::natping: can't resolve host\n");
++ continue;
++ }
++ hostent2su(&to, he, 0, curi.port_no);
++ send_sock=force_socket ? force_socket :
++ get_send_socket(0, &to, PROTO_UDP);
++ if (send_sock == NULL) {
++ LOG(L_ERR, "ERROR: nathelper::natping: can't get sending socket\n");
++ continue;
++ }
++ udp_send(send_sock, (char *)sbuf, sizeof(sbuf), &to);
++ }
++ }
++ pkg_free(buf);
++}