[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(&regexbuf, 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(&regexbuf, 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(&regexbuf);
+
+  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(&regexbuf, 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(&regexbuf, 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(&regexbuf);
+
+  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