[asterisk-commits] oej: branch oej/midcomstuff r53657 - in
/team/oej/midcomstuff/res: ./ midcom/
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Thu Feb 8 15:15:33 MST 2007
Author: oej
Date: Thu Feb 8 16:15:32 2007
New Revision: 53657
URL: http://svn.digium.com/view/asterisk?view=rev&rev=53657
Log:
Move res_netsec into the asterisk side of things.
res_netsec.a is a library that is needed to create res_netsec.so,
but we'll worry about that later.
res_netsec.a is created in the midcom-x.x.x branch now.
Added:
team/oej/midcomstuff/res/midcom/
team/oej/midcomstuff/res/midcom/res_netsec.h (with props)
team/oej/midcomstuff/res/res_netsec.c (with props)
Added: team/oej/midcomstuff/res/midcom/res_netsec.h
URL: http://svn.digium.com/view/asterisk/team/oej/midcomstuff/res/midcom/res_netsec.h?view=auto&rev=53657
==============================================================================
--- team/oej/midcomstuff/res/midcom/res_netsec.h (added)
+++ team/oej/midcomstuff/res/midcom/res_netsec.h Thu Feb 8 16:15:32 2007
@@ -1,0 +1,74 @@
+/*
+ * res_netsec.h -- Header file
+ *
+ * Copyright (C) 2005, Ranch Networks, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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
+ *
+ * Author : Srivatsa Chivukula <srivatsa at ranchnetworks.com>
+ *
+ */
+
+/*! \file res_netsec.h
+ This file glues res_netsec to client channels
+ *
+ * \author Srivatsa Chivukula <srivatsa at ranchnetworks.com>
+*/
+extern int midcom_load_module(void);
+extern void midcom_unload_module(void);
+
+/* The RTP helper module */
+struct ast_rtp_helper_cb {
+ void (* const ast_rtp_get_peer_audio_helper)(void *p, struct sockaddr_in *them);
+ void (* const ast_rtp_get_peer_video_helper)(void *p, struct sockaddr_in *them);
+ void (* const ast_rtp_get_us_audio_helper)(void *p, struct sockaddr_in *sin, struct sockaddr_in *pbx_rtp);
+ void (* const ast_rtp_get_us_video_helper)(void *p, struct sockaddr_in *vsin);
+ void (* const ast_map_hook_struct)(void *p, void *r);
+ void *(* const ast_get_hook_struct)(void *p);
+ int (* const ast_get_flag_novideo)(void *p);
+ int (* const ast_cmp_sa_addr)(void *p, struct sockaddr_in *addr);
+ void (* const ast_get_recv_addr)(void *p, struct in_addr *addr);
+ char *(* const ast_get_username)(void *p);
+ struct ast_channel *(* const ast_channel_helper)(void *p);
+ struct ast_channel *(* const ast_bridged_channel_helper)(void *p);
+ void (*const ast_get_capability_helper)(void *p, int *codec, int *dtmf_payload );
+ void (* const ast_softhangup_helper)(void *p);
+};
+
+/*! Hooks into the SIP channel
+ \note Can we make this more generic so it works for other channels
+ or do we need to have one per channel?
+ I think we can define various stages in the media setup process
+ instead or "transmit_response_with_sdp" etc - those are
+ function calls and not states.
+ A good way would be to compare chan_jingle and chan_sip
+ to find these hooks.
+*/
+struct ast_sip_hook_cb {
+ int (* const handle_request_invite_hook)(void *p);
+ int (* const handle_response_invite_hook)(void *p);
+ int (* const transmit_response_with_sdp_hook)(void *p);
+ int (* const transmit_reinvite_with_sdp_hook)(void *p, int redir_audio, int redir_video);
+ int (* const __sip_destroy_hook)(void *p);
+ void (* const ast_rtp_nat_us_audio_hook)(struct ast_rtp *rtp, void *r);
+ void (* const ast_rtp_nat_us_video_hook)(struct ast_rtp *rtp, void *r);
+ void (* const ast_get_redirip_audio_hook)(void *r, struct sockaddr_in *redirip);
+ void (* const ast_get_vredirip_video_hook)(void *r, struct sockaddr_in *vredirip);
+ void (* const ast_rtp_get_their_nat_audio_hook)(struct ast_rtp *rtp, void *r);
+ void (* const ast_rtp_get_their_nat_video_hook)(struct ast_rtp *vrtp, void *r);
+ void (* const ast_sip_helper_register)(struct ast_rtp_helper_cb *cb);
+ void (* const ast_sip_helper_unregister)(void);
+};
+
+
Propchange: team/oej/midcomstuff/res/midcom/res_netsec.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/oej/midcomstuff/res/midcom/res_netsec.h
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/oej/midcomstuff/res/midcom/res_netsec.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/oej/midcomstuff/res/res_netsec.c
URL: http://svn.digium.com/view/asterisk/team/oej/midcomstuff/res/res_netsec.c?view=auto&rev=53657
==============================================================================
--- team/oej/midcomstuff/res/res_netsec.c (added)
+++ team/oej/midcomstuff/res/res_netsec.c Thu Feb 8 16:15:32 2007
@@ -1,0 +1,2520 @@
+/*
+ * res_netsec.c -- Provides the MIDCOM services to Asterisk
+ *
+ * Copyright (C) 2005, Ranch Networks, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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
+ *
+ * Initial Author : Srivatsa Chivukula <srivatsa at ranchnetworks.com>
+ *
+ * History:
+ * 01 Aug 2006 - release of version 0.2.0
+ * 05 Nov 2006 - major overhaul of libmidcom code. Release Version 0.5.1
+ *
+ */
+
+/*! \file
+ * res_netsec.c -- Provides the MIDCOM services to Asterisk
+ *
+ * \author Srivatsa Chivukula <srivatsa at ranchnetworks.com>
+ *
+ * \todo
+ * - Create registration in rtp.c for a remote RTP handler
+ * - Make interface less SIP-specific (this can be used for
+ * all RTP based channels - H.323, jingle, mgcp)
+ * - Make source code follow coding guidelines
+ * - Check licensing
+ * - Fix proper reload function
+ - How does this affect midcom connections to a device?
+ * - fix autoconfigure to set MIDCOM_EXISTS flag if libmidcom is installed
+ */
+
+/*** MODULEINFO
+***/
+///*** MODULEINFO
+// <depend>libmidcom</depend>
+//**/
+#define MODULE_DESCRIPTION "MIDCOM/Simco module for Asterisk"
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <regex.h>
+#include <assert.h>
+
+#include <asterisk/channel.h>
+#include <asterisk/rtp.h>
+#include <asterisk/config.h>
+#include <asterisk/options.h>
+#include <asterisk/logger.h>
+#include <asterisk/utils.h>
+#include <asterisk/cli.h>
+#include <asterisk/module.h>
+
+#include "midcom/simco_client.h"
+//#include "timer/voipTimerP.h"
+//#include "res_netsec.h"
+#include "midcom/voipTimerP.h"
+#include "midcom/res_netsec.h"
+
+#define NO_MIDCOM 0
+#define NEAREND 1
+#define FAREND 2
+
+#define MIDCOM_ALLOW_AUDIO 1
+#define MIDCOM_ALLOW_VIDEO 1
+#define MIDCOM_BRIDGE_AUDIO 1
+#define MIDCOM_BRIDGE_VIDEO 1
+
+#define MIDCOM_DEF_MUTEX_TRY_CNT 10
+#define MIDCOM_DEF_MUTEX_TRY_DELAY 10
+
+#define MIDCOM_MAX_SIMCO_RETRY_CNT 1
+
+static const char version[] = "Libmidcom version 0.5.3.2";
+static const char desc[] = "MiddleBox Communication Module (MIDCOM/SIMCO)";
+static unsigned int midcomnat = FAREND;
+static char cert[512];
+static char* config = "midcom.conf";
+static int midcom_enabled = 1;
+static int midcom_err_state = 0;
+static int told_them_that_midcom_is_not_enabled = 0;
+
+#define MIDCOM_NO_CONFIG 0x1
+#define MIDCOM_NO_INIT 0x2
+#define MIDCOM_NO_TIMER 0x4
+
+static int usecnt = 0;
+AST_MUTEX_DEFINE_STATIC(usecnt_lock);
+
+typedef enum {
+
+ MBOX_S_DISC = 0,
+ MBOX_S_CONNECTING,
+ MBOX_S_CONN,
+ MBOX_S_SSN_EST,
+ MBOX_S_SSN_AUTH,
+ MBOX_S_MAX
+
+} mbox_state_t;
+
+#define MBOX_SSN_RETRY_CNT 2
+
+#define MBOX_LOC_LOCAL 0
+#define MBOX_LOC_REMOTE 1
+
+#define MBOX_ROLE_MASTER 0
+#define MBOX_ROLE_SLAVE 1
+
+#define SAFE_INTERVAL 60 /* seconds */
+
+#define DEFAULT_FREQ_OK 60 /* How often to check for the midbox to be up */
+#define DEFAULT_FREQ_NOTOK 10 /* How often to check, if the midbox is down... */
+
+timer_task_context_t timer_context, *timer;
+
+static timer_task_context_t *timer_context_create(void);
+static void timer_context_delete(timer_task_context_t *ttc);
+
+/*! Midcom ruleset, one per session (pvt)
+ \note this structure needs a pointer in the channel's
+ pvt structure
+*/
+
+static struct midcom_rule {
+ char username[256];
+ unsigned int nat_done:1,
+ firewall_done:1,
+ bridge_done:1,
+ bye_done:1,
+ novideo:1,
+ enable_rtcp:1,
+ bridged_node:1, /*!< bridged_node = 1 - bridging done throught this rule */
+ tls:1,
+ invalid:1,
+ audio_to_asterisk:1,
+ video_to_asterisk:1,
+ may_xfer_call:1, /*!< call may be transferred to another extension */
+ unused:20;
+ struct connection *conn; /*!< midbox to which we are talking to for this rule */
+ int ruleid;
+ int vruleid;
+ int aux_ruleid;
+ int aux_vruleid;
+ struct sockaddr_in our_internal_addr; /*!< audio - internal address of the endpoint (pre NAT) */
+ struct sockaddr_in our_external_addr; /*!< audio - external address of the endpoint (post NAT) */
+ struct sockaddr_in our_natted_addr; /*!< audio - address assigned to endpoint by Midbox */
+ struct sockaddr_in our_internal_vaddr; /*!< video - internal address of the endpoint (pre NAT) */
+ struct sockaddr_in our_external_vaddr; /*!< video - external address of the endpoint (post NAT) */
+ struct sockaddr_in our_natted_vaddr; /*!< video - address assigned to endpoint by Midbox */
+ /* XXX For Asterisk 1.6, we need text RTP. */
+ int lifetime;
+ timer_id_t timer_handle;
+ void *p; /*!< handle to tech pvt data structure */
+ struct midcom_rule *pr; /*!< peer MIDCOM rule for the other leg of a bridged call. */
+ struct midcom_rule *next;
+} *midcom_rule_head = NULL;
+
+
+/*! \brief midcom connection to the remote device */
+static struct connection {
+ struct in_addr ipaddress;
+ char name[256];
+ char username[256];
+ char password[256];
+ int tls;
+ int location;
+ int role;
+ int sock;
+ int pingsock;
+ mbox_state_t state;
+ ast_mutex_t lock;
+ unsigned int thread; /* thread currently holding lock */
+ timer_id_t timer_handle;
+ struct connection *next;
+} *connl = NULL;
+
+/*! \brief Protect the midcom rule list */
+AST_MUTEX_DEFINE_STATIC(netsec_lock);
+
+/*! Forward declarations */
+static int midcom_config_reload(void);
+
+static struct connection * get_primary_midbox(void);
+static int is_nearend_nat(void);
+static int is_farend_nat(void);
+static struct connection *get_optimal_midbox(struct midcom_rule *rule, struct midcom_rule *peer);
+static struct connection *get_midbox_by_addr(struct in_addr endpoint_addr);
+
+static struct midcom_rule *midcom_rule_alloc(void *p);
+
+static timer_task_context_t *timer_context_create(void);
+static void timer_context_delete(timer_task_context_t *ttc);
+static int timer_setup_tick(void *data, size_t datalen, unsigned int timeout, timer_id_t *handleP);
+static int timer_change_tick(void *data, size_t datalen, unsigned int mew_timeout);
+static int timer_cancel_tick(void *data, size_t datalen);
+static int timer_tick_handler(void *argptr, size_t arglen);
+
+static void midcom_connect_all(void);
+static int midcom_connect(struct in_addr midbox, int *lifetime, int *cached);
+static int midcom_fetch_session(struct connection *curr);
+static int midcom_change_lifetime(struct connection *conn, int rule, int *lifetime);
+static int midcom_reserve_nat(struct connection *conn, int *rule, struct sockaddr_in *nat_addr, int enable_rtcp, int *lifetime);
+static int midcom_open_firewall(struct midcom_rule *r, int allow_audio, int allow_video );
+static int midcom_add_firewall(struct connection *conn, int rule, struct sockaddr_in *their_external, struct sockaddr_in *our_internal, int *lifetime, int codec);
+static int midcom_bridge_firewall(struct midcom_rule *r, struct midcom_rule *peer, int bridge_audio, int bridge_video );
+static int midcom_delete_rule(struct connection *conn, int rule, struct midcom_rule *r);
+static int midcom_dump_rule(struct midcom_rule *r);
+static int midcom_close_bridge(struct connection *conn, int rule);
+static void midcom_disconnect(int con, int cached);
+
+static int midcom_enable_firewall(int fd, int argc, char *argv[]);
+static int midcom_disable_firewall(int fd, int argc, char *argv[]);
+static int midcom_show_firewall(int fd, int argc, char *argv[]);
+static int midcom_enable_debug(int fd, int argc, char *argv[]);
+static int midcom_disable_debug(int fd, int argc, char *argv[]);
+static int midcom_show_version(int fd, int argc, char *argv[]);
+static int midcom_show_conn(int fd, int argc, char *argv[]);
+
+static int midcom_handle_request_invite_hook(void *p);
+static int midcom_handle_response_invite_hook(void *p);
+static int midcom_transmit_response_with_sdp_hook(void *p);
+static int midcom_transmit_reinvite_with_sdp_hook(void *p, int redir_audio, int redir_video);
+static int midcom__sip_destroy_hook(void *p);
+static void midcom_rtp_nat_us_audio_hook(struct ast_rtp *rtp, void *r);
+static void midcom_rtp_nat_us_video_hook(struct ast_rtp *rtp, void *r);
+static void midcom_get_redirip_audio_hook(void *r, struct sockaddr_in *redirip);
+static void midcom_get_vredirip_video_hook(void *r, struct sockaddr_in *vredirip);
+static void midcom_rtp_get_their_nat_audio_hook(struct ast_rtp *rtp, void *r);
+static void midcom_rtp_get_their_nat_video_hook(struct ast_rtp *vrtp, void *r);
+static void midcom_sip_helper_register(struct ast_rtp_helper_cb *cb);
+static void midcom_sip_helper_unregister(void);
+
+static struct midcom_rule *get_peer_rule(struct midcom_rule *r);
+static int midcom_handle_non_bridged_reinvite(struct midcom_rule *r);
+static int midcom_handle_bridged_reinvite(struct midcom_rule *r, int redir_audio, int redir_video);
+
+static int midcom_conn_mutex_lock(struct connection *conn);
+static int midcom_conn_mutex_unlock(struct connection *conn);
+static int midcom_mutex_lock(ast_mutex_t *mutex);
+static int midcom_mutex_unlock(ast_mutex_t *mutex);
+
+static struct ast_rtp_helper_cb *channel_cb = NULL;
+
+struct ast_sip_hook_cb *midcom_cb = NULL; /*move this to the core asterisk files */
+
+static char enable_firewall_usage[] =
+"Usage: netsec enable firewall\n"
+" Enable the midcom communication between Asterisk and middlebox.\n";
+
+static char disable_firewall_usage[] =
+"Usage: netsec disable firewall\n"
+" Disable the midcom communication between Asterisk and middlebox.\n";
+
+static char show_firewall_usage[] =
+"Usage: netsec show firewall\n"
+" Lists all currently active midcom firewalled/bridged rules.\n";
+
+static char show_conn_usage[] =
+"Usage: netsec show midbox\n"
+" Show the state of the configured midboxes.\n";
+
+static char show_version_usage[] =
+"Usage: netsec show version\n"
+" Display the current verison of the res_netsec module.\n";
+
+static char enable_debug_usage[] =
+"Usage: netsec debug\n"
+" Enable printing of debug messages on the res_netsec module.\n";
+
+static char disable_debug_usage[] =
+"Usage: netsec no debug\n"
+" Disable printing of debug messages on the res_netsec module.\n";
+
+static struct ast_cli_entry my_clis[] = {
+ { { "netsec", "enable", "firewall", NULL }, midcom_enable_firewall, "Enable the midcom communication between Asterisk and middlebox", enable_firewall_usage },
+ { { "netsec", "disable", "firewall", NULL }, midcom_disable_firewall, "Disable the midcom communication between Asterisk and middlebox", disable_firewall_usage },
+ { { "netsec", "show", "status", NULL }, midcom_show_firewall, "Show the status of all Netsec rules created by Asterisk", show_firewall_usage /*,complete_midcom_show_firewall*/ },
+ { { "netsec", "show", "midbox", NULL }, midcom_show_conn, "Show the state of the configured midboxes", show_conn_usage /*,complete_midcom_show_firewall*/ },
+ { { "netsec", "debug", NULL }, midcom_enable_debug, "Enable debug prints in res_netsec module", enable_debug_usage },
+ { { "netsec", "no", "debug", NULL }, midcom_disable_debug, "Disable debug prints in res_netsec module", disable_debug_usage },
+ { { "netsec", "show", "version", NULL }, midcom_show_version, "Display the current version of the res_netsec module", show_version_usage }
+};
+
+/*--- midcom_sip: Interface structure with callbacks used to connect to sip module --*/
+static struct ast_sip_hook_cb sip_hook = {
+ handle_request_invite_hook: midcom_handle_request_invite_hook,
+ handle_response_invite_hook: midcom_handle_response_invite_hook,
+ transmit_response_with_sdp_hook: midcom_transmit_response_with_sdp_hook,
+ transmit_reinvite_with_sdp_hook: midcom_transmit_reinvite_with_sdp_hook,
+ __sip_destroy_hook: midcom__sip_destroy_hook,
+ ast_rtp_nat_us_audio_hook: midcom_rtp_nat_us_audio_hook,
+ ast_rtp_nat_us_video_hook: midcom_rtp_nat_us_video_hook,
+ ast_get_redirip_audio_hook: midcom_get_redirip_audio_hook,
+ ast_get_vredirip_video_hook: midcom_get_vredirip_video_hook,
+ ast_rtp_get_their_nat_audio_hook: midcom_rtp_get_their_nat_audio_hook,
+ ast_rtp_get_their_nat_video_hook: midcom_rtp_get_their_nat_video_hook,
+ ast_sip_helper_register: midcom_sip_helper_register,
+ ast_sip_helper_unregister: midcom_sip_helper_unregister,
+};
+
+static void midcom_sip_helper_register(struct ast_rtp_helper_cb *cb)
+{
+ channel_cb = cb;
+}
+
+static void midcom_sip_helper_unregister(void)
+{
+ channel_cb = NULL;
+}
+
+
+static int load_module(void)
+{
+ midcom_enabled = 0;
+ midcom_err_state = 0;
+ if (midcom_config_reload()) {
+ midcom_err_state |= MIDCOM_NO_CONFIG;
+ }
+ fflush(stdout);
+ if (!mc_init(cert)) {
+ ast_log(LOG_ERROR, "Unable to initialize midcom\n");
+ midcom_err_state |= MIDCOM_NO_INIT;
+ }
+
+ if (midcom_err_state == 0) {
+ timer = timer_context_create();
+ if (!timer) {
+ ast_log(LOG_ERROR, "Unable to create (midcom) timer context\n");
+ midcom_err_state |= MIDCOM_NO_TIMER;
+ }
+ }
+
+ /* Register the sip hook functions */
+ midcom_cb = &sip_hook;
+
+ /* Register all CLI functions for midcom */
+ ast_cli_register_multiple(my_clis, sizeof(my_clis)/ sizeof(my_clis[0]));
+
+ midcom_connect_all();
+ if (midcom_err_state == 0)
+ midcom_enabled = 1;
+ return 0;
+}
+
+static int unload_module(void)
+{
+ struct midcom_rule *r;
+ struct connection *c, *tconn;
+
+ r = midcom_rule_head;
+ if (r) {
+ if (!ast_mutex_lock(&netsec_lock)) {
+ /* Hangup all interfaces if they have an owner */
+ while (r) {
+ if (channel_cb)
+ channel_cb->ast_softhangup_helper(r->p);
+ r = r->next;
+ }
+ midcom_rule_head = NULL;
+ ast_mutex_unlock(&netsec_lock);
+ } else {
+ ast_log(LOG_WARNING, "Unable to lock the midcom rule list\n");
+ }
+ }
+
+ c = connl;
+ while (c) {
+ timer_cancel_tick(c, sizeof(struct connection));
+ /* mc_comm_disconnect(c->pingsock); */
+ mc_comm_disconnect(c->sock);
+ tconn = c;
+ c = c->next;
+ /******** TODO: try to find if it is locked and if so unlock it ******/
+ ast_mutex_destroy(&tconn->lock);
+ free(tconn);
+ }
+ connl = NULL;
+
+ if (timer == NULL) {
+ timer_context_delete(timer);
+ timer = NULL;
+ }
+
+ ast_mutex_destroy(&netsec_lock);
+ /* Unregister the sip hook functions */
+ midcom_cb = NULL;
+
+ ast_cli_unregister_multiple(my_clis, sizeof(my_clis)/ sizeof(my_clis[0]));
+ mc_close();
+ midcom_enabled = 0;
+ usecnt = 0;
+ ast_mutex_destroy(&usecnt_lock);
+ return 0;
+}
+
+
+
+/*--- midcom_enable_firewall: Turn on Midcom firewall (CLI command) */
+static int midcom_enable_firewall(int fd, int argc, char *argv[])
+{
+ int oldflag = midcom_enabled;
+ if(midcom_err_state)
+ {
+ ast_cli(fd, "Can not enable firewall. Module in inconsistent state. Run status command for more information\n");
+ return RESULT_FAILURE;
+ }
+ if (argc != 3)
+ return RESULT_SHOWUSAGE;
+ midcom_enabled = 1;
+ if (oldflag)
+ ast_cli(fd, "Netsec Firewalling re-enabled\n");
+ else
+ ast_cli(fd, "Netsec Firewalling enabled\n");
+ return RESULT_SUCCESS;
+}
+
+/*--- midcom_disable_firewall: Turn off Midcom firewall (CLI command) */
+static int midcom_disable_firewall(int fd, int argc, char *argv[])
+{
+ if (argc != 3)
+ return RESULT_SHOWUSAGE;
+ midcom_enabled = 0;
+ ast_cli(fd, "Netsec Firewalling disabled\n");
+ return RESULT_SUCCESS;
+}
+
+/*--- midcom_show_firewall: Show Midcom firewall rules (CLI command) */
+static int midcom_show_firewall(int fd, int argc, char *argv[])
+{
+ regex_t regexbuf;
+ int havepattern = 0;
+
+#define FORMAT2 "%-15.15s %-21.20s %-8s %-15.15s %-8s %-15.15s %-8s %-5.5s %-10s %-8s %-8s\n"
+#define FORMAT "%-15.15s %-21.20s %-8d %-15.15s %-8d %-15.15s %-8d %-5.5s %-10s %-8d %-8d\n"
+
+ struct midcom_rule *r = midcom_rule_head;
+ char name[256];
+ struct midcom_rule *peer_rule;
+ struct sockaddr_in peer_ip;
+ char status[20] = "";
+
+ switch (argc) {
+ case 5:
+ if (!strcasecmp(argv[3], "like")) {
+ if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB))
+ return RESULT_SHOWUSAGE;
+ havepattern = 1;
+ } else
+ return RESULT_SHOWUSAGE;
+ case 3:
+ break;
+ default:
+ return RESULT_SHOWUSAGE;
+ }
+
+ if( midcom_enabled )
+ ast_cli(fd,"Midcom module status : Enabled.\n");
+ else
+ ast_cli(fd,"Midcom module status : Disabled.\n");
+ if (midcom_err_state) {
+ ast_cli(fd, "Midcom module came up with errors.\n");
+ if (midcom_err_state & MIDCOM_NO_CONFIG)
+ ast_cli(fd, "Midcom config file not loaded because of configuration errors\n");
+ if (midcom_err_state & MIDCOM_NO_INIT)
+ ast_cli(fd, "Midcom initialization failed.\n");
+ if (midcom_err_state & MIDCOM_NO_TIMER)
+ ast_cli(fd, "Midcom Timer initialization failed.\n");
+ return RESULT_SUCCESS;
+ }
+ ast_cli(fd, FORMAT2, "Username", "Originating Address", "Port", "Natted Address", "Port", "Peer Address", "Port", "Media", "Status", "Ruleid", "Aux-ruleid");
+
+ for ( ; r ; r = r->next) {
+
+
+ if (havepattern && regexec(®exbuf, r->username, 0, NULL, 0)) {
+ continue;
+ }
+
+ strncpy(name, r->username, sizeof(name));
+ memset(&peer_ip, 0, sizeof(peer_ip));
+
+
+ if (r->bridge_done)
+ strncpy(status, "Bridged", sizeof(status));
+ else if (r->nat_done)
+ strncpy(status, "Nat done", sizeof(status));
+ else if (r->firewall_done)
+ strncpy(status, "Firewalled", sizeof(status));
+ else if (r->bye_done)
+ strncpy(status, "Deleted", sizeof(status));
+
+ peer_rule = r->pr;
+ if (peer_rule)
+ peer_ip = peer_rule->our_natted_addr;
+
+ ast_cli(fd, FORMAT, name,
+ r->our_internal_addr.sin_addr.s_addr ? ast_inet_ntoa(r->our_internal_addr.sin_addr) : "(Unspecified)",
+ ntohs(r->our_internal_addr.sin_port),
+ r->our_natted_addr.sin_addr.s_addr ? ast_inet_ntoa(r->our_natted_addr.sin_addr) : "(Unspecified)",
+ ntohs(r->our_natted_addr.sin_port),
+ peer_ip.sin_addr.s_addr ? ast_inet_ntoa(peer_ip.sin_addr) : "(Unspecified)",
+ ntohs(peer_ip.sin_port),
+ "Audio",
+ status, r->ruleid, r->aux_ruleid);
+ if (!r->novideo) {
+
+ if (peer_rule)
+ peer_ip = peer_rule->our_natted_vaddr;
+ ast_cli(fd, FORMAT, name,
+ r->our_internal_vaddr.sin_addr.s_addr ? ast_inet_ntoa(r->our_internal_vaddr.sin_addr) : "(Unspecified)",
+ ntohs(r->our_internal_vaddr.sin_port),
+ r->our_natted_vaddr.sin_addr.s_addr ? ast_inet_ntoa( r->our_natted_vaddr.sin_addr) : "(Unspecified)",
+ ntohs(r->our_natted_vaddr.sin_port),
+ peer_ip.sin_addr.s_addr ? ast_inet_ntoa(peer_ip.sin_addr) : "(Unspecified)",
+ ntohs(peer_ip.sin_port),
+ "Video",
+ status, r->vruleid, r->aux_vruleid);
+
+ }
+ };
+
+ if (havepattern)
+ regfree(®exbuf);
+
+ return RESULT_SUCCESS;
+#undef FORMAT
+#undef FORMAT2
+}
+
+
+static int midcom_show_conn(int fd, int argc, char *argv[])
+{
+ regex_t regexbuf;
+ int havepattern = 0;
+
+ struct connection *conn = connl;
+ char status[128] = "";
+
+ switch (argc) {
+ case 5:
+ if (!strcasecmp(argv[3], "like")) {
+ if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB))
+ return RESULT_SHOWUSAGE;
+ havepattern = 1;
+ } else
+ return RESULT_SHOWUSAGE;
+ case 3:
+ break;
+ default:
+ return RESULT_SHOWUSAGE;
+ }
+ ast_cli(fd, "\n\n\n");
+ for ( ; conn ; conn = conn->next) {
+
+
+ if (havepattern && regexec(®exbuf, conn->name, 0, NULL, 0)) {
+ continue;
+ }
+ switch (conn->state) {
+ case MBOX_S_DISC :
+ sprintf(status, "%s", "Disconnected");
+ break;
+ case MBOX_S_CONNECTING :
+ sprintf(status, "%s", "Initiated connection");
+ break;
+ case MBOX_S_CONN :
+ sprintf(status, "%s", "Connected");
+ break;
+ case MBOX_S_SSN_EST :
+ sprintf(status, "%s", "Session Established");
+ break;
+ case MBOX_S_SSN_AUTH :
+ sprintf(status, "%s", "Session Authenticated, Ready to send commands");
+ break;
+ default:
+ sprintf(status, "%s", "Unknown");
+
+ }
+ ast_cli(fd, "Midbox Name: %s\n", conn->name);
+ ast_cli(fd, "\t\t IP Adress: %s\n", ast_inet_ntoa(conn->ipaddress));
+ ast_cli(fd, "\t\t Role: %s\n", (conn->role == MBOX_ROLE_MASTER) ? "Master" : "Slave");
+ ast_cli(fd, "\t\t Status: %s\n", status);
+ ast_cli(fd, "\t\t Transport Mode: %s\n", conn->tls ? "tls": "plain-text");
+ ast_cli(fd, "\t\t Location: %s\n\n", (conn->location == MBOX_LOC_LOCAL) ? "Local" : "Remote");
+
+ }
+
+ if (havepattern)
+ regfree(®exbuf);
+
+ return RESULT_SUCCESS;
+}
+
+
+/*--- midcom_show_version: Show the current version of Midcom module */
+static int midcom_show_version(int fd, int argc, char *argv[])
+{
+
+ if (argc != 3)
+ return RESULT_SHOWUSAGE;
+ ast_cli(fd, "%s\n", version);
+ return RESULT_SUCCESS;
+}
+
+
+/*--- midcom_enable_debug: Enable debug prints on the Midcom module */
+static int midcom_enable_debug(int fd, int argc, char *argv[])
+{
+
+ if (argc != 2)
+ return RESULT_SHOWUSAGE;
+ set_debug_midbox(1);
+ ast_cli(fd, "Debug printing enabled on NETSEC\n");
+ return RESULT_SUCCESS;
+}
+
+
+/*--- midcom_disable_debug: Disable debug prints on the Midcom module */
+static int midcom_disable_debug(int fd, int argc, char *argv[])
+{
+
+ if (argc != 3)
+ return RESULT_SHOWUSAGE;
+ set_debug_midbox(0);
+ ast_cli(fd, "Debug printing disabled on NETSEC\n");
+ return RESULT_SUCCESS;
+}
+
+
+
+static int midcom_config_reload(void)
+{
+ struct ast_config *cfg;
+ const char *s;
+ char *cat;
+ const char *utype;
+ struct connection *conn, *curr, *prev = NULL;
+ struct ast_variable *v;
+ int dupl = 0;
+
+ cfg = ast_config_load(config);
+ if (cfg) {
+
+ if ((s = ast_variable_retrieve(cfg, "general", "certificate"))) {
+ ast_copy_string(cert, s, sizeof(cert));
+ }
+
+ cat = ast_category_browse(cfg, NULL);
+ while (cat) {
+ if (strcasecmp(cat, "general")) {
+ utype = ast_variable_retrieve(cfg, cat, "type");
+ if (utype) {
+ if (!strcasecmp(utype, "midbox")) {
+ conn = (struct connection*)malloc(sizeof(struct connection));
+ if (!conn)
+ break;
+ memset(conn, 0, sizeof(struct connection));
+ ast_copy_string(conn->name, cat, sizeof(conn->name));
+ v = ast_variable_browse(cfg, cat);
+ while (v) {
+ if (!strcasecmp(v->name, "ip")) {
+ inet_aton(v->value, &(conn->ipaddress));
+ } else if (!strcasecmp(v->name, "username")) {
+ ast_copy_string(conn->username, v->value, sizeof(conn->username));
+ } else if (!strcasecmp(v->name, "password")) {
+ ast_copy_string(conn->password, v->value, sizeof(conn->password));
+ } else if (!strcasecmp(v->name, "transport")) {
+ if (!strcasecmp(v->value, "tls")) {
+ ast_log(LOG_WARNING, "Transport mode TLS currently not supported.\n");
+ ast_log(LOG_WARNING, "Ignoring device %s configured for TLC and switching to plain-text.\n", conn->name);
+ conn->tls = 0;
+ }
+ }
+
+ else if (!strcasecmp(v->name, "location")) {
+ if (!strcasecmp(v->value, "remote"))
+ conn->location = MBOX_LOC_REMOTE;
+ else
+ conn->location = MBOX_LOC_LOCAL;
+
+ } else if (!strcasecmp(v->name, "role")) {
+ if (!strcasecmp(v->value, "master")) {
+ if (conn->location == MBOX_LOC_LOCAL)
+ conn->role = MBOX_ROLE_MASTER;
+ else {
+ conn->role = MBOX_ROLE_SLAVE;
+ ast_log(LOG_WARNING, "Can not set device %s as MASTER as it is configured with location=remote.\n", conn->name);
+ ast_log(LOG_WARNING, "Setting device %s as SLAVE.\n", conn->name);
+ }
+ }
+ else
+ conn->role = MBOX_ROLE_SLAVE;
+ }
+ v= v->next;
+ }
+
+ prev = NULL;
+ curr = connl;
+ while (curr) {
+ if (curr->ipaddress.s_addr == conn->ipaddress.s_addr) {
+ dupl = 1;
+ break;
+ }
+ if ((curr->role == MBOX_ROLE_MASTER) && (curr->role == conn->role)) {
+ ast_log(LOG_WARNING, "Can not set device %s as MASTER as %s is already configured as MASTER.\n", conn->name, curr->name);
+ ast_log(LOG_WARNING, "Setting device %s as SLAVE.\n", conn->name);
+ conn->role = MBOX_ROLE_SLAVE;
+ }
+ prev = curr;
+ curr = curr->next;
+ }
+ if (!dupl) {
+
+ ast_mutex_init(&conn->lock);
+ if (!prev)
+ connl = conn;
+ else
+ prev->next = conn;
+
+ } else {
+ ast_log(LOG_NOTICE, "Ignoring device '%s' as device with IP %s is already defined earlier.\n", cat, ast_inet_ntoa(conn->ipaddress));
+ free(conn);
+ }
+ } else {
+ ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config);
+ }
+ } else
+ ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
+ }
+ cat = ast_category_browse(cfg, cat);
+ }
+ ast_config_destroy(cfg);
+ } else {
+ ast_log(LOG_WARNING, "Unable to load config file %s. MIDCOM is disabled\n", config);
+ midcom_enabled = 0;
+ return -1;
+ }
+
+ for (curr=connl; curr; curr=curr->next)
+ if (curr->role == MBOX_ROLE_MASTER)
+ break;
+
+ if (curr == NULL) {
+
+ ast_log(LOG_WARNING, "Midcom: Error - No Midbox confugired as MASTER\n");
+ ast_log(LOG_WARNING, "%s has errors and is not loaded. MIDCOM is disabled\n", config);
+ midcom_enabled = 0;
+ curr=connl;
+ while (curr) {
+ conn = curr;
+ curr = curr->next;
+ free (conn);
+ }
+ connl = NULL;
+ return -1;
+ }
+
+ if (option_verbose > 1)
+ ast_verbose(VERBOSE_PREFIX_2 "Midcom Reloaded, Midbox %s with IP adress %s configured as MASTER.\n", curr->username, ast_inet_ntoa(curr->ipaddress));
+
+ return 0;
+}
+
+static struct midcom_rule *midcom_rule_alloc(void *p)
+{
+ struct midcom_rule *r;
+ r = malloc(sizeof(struct midcom_rule));
+ if (r == NULL) {
+ ast_log(LOG_WARNING, "Not enough resources\n");
+ return NULL;
+ }
+ memset(r, 0, sizeof(struct midcom_rule));
+ r->novideo = (channel_cb->ast_get_flag_novideo(p)) ? 1 : 0;
+ channel_cb->ast_rtp_get_peer_audio_helper(p, &r->our_internal_addr);
+ if (!r->novideo) {
+ channel_cb->ast_rtp_get_peer_video_helper(p, &r->our_internal_vaddr);
+ }
+ strncpy(r->username, channel_cb->ast_get_username(p), 256);
+ r->ruleid = -1;
+ r->vruleid = -1;
+ r->aux_ruleid = -1;
+ r->aux_vruleid = -1;
+ r->lifetime = 600;
+ r->p = p;
+ return r;
+}
+
+static int midcom_handle_request_invite_hook(void *p)
+{
+ /* will be used later when near-end is supported */
+ return 1;
+}
+
+static int midcom_handle_response_invite_hook(void *p)
+{
+ struct midcom_rule *r = NULL;
+
+ if (!midcom_enabled) {
+ ast_log(LOG_ERROR, "Midcom: Module not enabled\n");
+ if (option_verbose > 1)
+ ast_verbose("Midcom: Module currently disabled\n");
+ return 1;
+ }
+
+ if (!channel_cb) {
+ ast_log(LOG_ERROR, "Midcom: Module not initialized properly\n");
+ if (option_verbose > 1)
+ ast_verbose("Midcom: Error!! - Module not initialized\n");
+ return 0;
+ }
+
+ if ((r = channel_cb->ast_get_hook_struct(p)))
+ return 1;
+
+ r = midcom_rule_alloc(p);
+ if (r == NULL)
+ return 0;
+
+ if (option_verbose > 1)
+ ast_verbose("Midcom: Allocating new midcom rule for phone: %s\n", r->username);
+
+ if ( (r->conn = get_primary_midbox()) == NULL)
+ return 0;
+
+ if(midcom_open_firewall(r, MIDCOM_ALLOW_AUDIO, MIDCOM_ALLOW_VIDEO) != 0)
+ {
+ free(r);
+ r = 0;
+ return 0;
+ }
+
+ r->firewall_done = 1;
+
+ ast_mutex_lock(&usecnt_lock);
+ usecnt++;
+ ast_mutex_unlock(&usecnt_lock);
+ ast_update_use_count();
+
+ if (ast_mutex_lock(&netsec_lock)) {
+ ast_log(LOG_ERROR, "Midcom: Error: Unable to obtain netsec mutex\n");
+ free(r);
+ return 0;
+ }
+ if (check_debug_midbox())
+ ast_log(LOG_DEBUG, "Acquired netsec_lock in the context of thread id 0x%x\n", (unsigned) pthread_self());
+ channel_cb->ast_map_hook_struct(p, (void *)r);
+ r->next = midcom_rule_head;
+ midcom_rule_head = r;
+ ast_mutex_unlock(&netsec_lock);
+ timer_setup_tick(r, sizeof(struct midcom_rule), r->lifetime, &r->timer_handle);
+ if (check_debug_midbox())
+ ast_log(LOG_DEBUG, "Released netsec_lock in the context of thread id 0x%x\n", (unsigned) pthread_self());
+ return 1;
+}
+
+static int midcom_transmit_response_with_sdp_hook(void *p)
+{
+ struct midcom_rule *r = NULL;
+
+ if (!midcom_enabled) {
+ ast_log(LOG_ERROR, "Midcom: Module not enabled\n");
+ if (option_verbose > 1)
+ ast_verbose("Midcom: Module currently disabled\n");
+ return 1;
+ }
+
+ if (!channel_cb) {
+ ast_log(LOG_ERROR, "Midcom: Module not initialized properly\n");
+ if (option_verbose > 1)
+ ast_verbose("Midcom: Error!! - Module not initialized\n");
+ return 0;
+ }
+
+ if ((r = channel_cb->ast_get_hook_struct(p)))
+ return 1;
+
+ r = midcom_rule_alloc(p);
+ if (r == NULL)
+ return 0;
+
+ if (option_verbose > 1)
+ ast_verbose("Midcom: Allocating new rule for phone: %s\n", r->username);
+ /* channel_cb->ast_get_recv_addr(p, &r->midbox_addr); */
+ if ( (r->conn = get_primary_midbox()) == NULL)
+ return 0;
+ if(midcom_open_firewall(r, MIDCOM_ALLOW_AUDIO, MIDCOM_ALLOW_VIDEO) != 0)
+ {
+ free(r);
+ r = NULL;
+ return 0;
+ }
+
+ r->firewall_done = 1;
+
+ ast_mutex_lock(&usecnt_lock);
+ usecnt++;
+ ast_mutex_unlock(&usecnt_lock);
+ ast_update_use_count();
+
+ if (ast_mutex_lock(&netsec_lock)) {
+ ast_log(LOG_ERROR, "Midcom: Error: Unable to obtain netsec mutex\n");
+ free(r);
+ return 0;
+ }
+ if (check_debug_midbox())
+ ast_log(LOG_DEBUG, "Acquired netsec_lock in the context of thread id 0x%x\n", (unsigned) pthread_self());
+ channel_cb->ast_map_hook_struct(p, (void *)r);
+ r->next = midcom_rule_head;
+ midcom_rule_head = r;
+ ast_mutex_unlock(&netsec_lock);
+ timer_setup_tick(r, sizeof(struct midcom_rule), r->lifetime, &r->timer_handle);
+ if (check_debug_midbox())
+ ast_log(LOG_DEBUG, "Released netsec_lock in the context of thread id 0x%x\n", (unsigned) pthread_self());
+ return 1;
+}
+
+static int midcom_transmit_reinvite_with_sdp_hook(void *p, int redir_audio, int redir_video)
+{
+ int ret = 0;
+ struct midcom_rule *r = NULL;
+
+ if (!midcom_enabled) {
+ ast_log(LOG_ERROR, "Midcom: Module not enabled\n");
+ if (option_verbose > 1)
+ ast_verbose("Midcom: Module currently disabled\n");
+ return 1;
+ }
+
+ if (!channel_cb) {
+ ast_log(LOG_ERROR, "Midcom: Module not initialized properly\n");
+ if (option_verbose > 1)
+ ast_verbose("Midcom: Error!! - Module not initialized\n");
+ return 0;
+ }
+
+ if (!(r = channel_cb->ast_get_hook_struct(p))) {
+
+ ast_log(LOG_ERROR, "Midcom: Unable to retrieve Midcom Rule for phone: %s\n", channel_cb->ast_get_username(p));
+ if (option_verbose > 1)
+ ast_verbose("Midcom: Error!! - Unable to retrieve Midcom Rule for phone: %s\n", channel_cb->ast_get_username(p));
+ return 0;
+ }
+
+ if (!r->bridge_done)
+ {
+ ret = midcom_handle_non_bridged_reinvite(r);
+ }
+ else
+ {
+ ret = midcom_handle_bridged_reinvite(r, redir_audio, redir_video);
+ }
+
+ return ret;
+}
+
+
+
+static int midcom_handle_non_bridged_reinvite(struct midcom_rule *r)
+{
+ int res = -1;
+ struct midcom_rule *peer=NULL;
+ struct connection *conn=NULL;
+ int lifetime;
+ int first_phone = 0;
+ if (option_debug)
+ ast_log(LOG_DEBUG, "MIDCOM :: We are here!\n");
+
+ peer = get_peer_rule(r);
+ if (peer == NULL)
+ return 0;
+ if (option_debug)
+ ast_log(LOG_DEBUG, "MIDCOM :: We are still here (have a peer)!\n");
+ if (peer->nat_done == 0) {
+
+ first_phone = 1;
+ /* Implement intelligent media bridging - check if we can bridge at
+ another optimal midcom aware device */
+ conn = get_optimal_midbox(r, peer);
+ if (conn == NULL) {
+ if (option_verbose > 1)
+ ast_verbose("Midcom: Failed to obtain Master midbox for user %s \n", r->username);
+ return 0;
+ }
+ }
+ else
+ {
+ conn = peer->conn;
+ }
+
+ if (option_debug)
+ ast_log(LOG_DEBUG, "MIDCOM :: We are still here (refuse to leave)!\n");
+
+ if (r->firewall_done) {
+
+ if (r->aux_ruleid != -1) {
+
+ timer_cancel_tick(r, sizeof(struct midcom_rule));
+ if (r->aux_ruleid != -1) {
+ midcom_delete_rule(r->conn, r->aux_ruleid, r);
+ }
+ if (!r->novideo) {
+ if (r->aux_vruleid != -1)
[... 1507 lines stripped ...]
More information about the asterisk-commits
mailing list