diff options
Diffstat (limited to 'net/ser/files/patch-modules__nathelper__natping.c')
-rw-r--r-- | net/ser/files/patch-modules__nathelper__natping.c | 258 |
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); ++} |