From: Andreas Eversberg Date: Sun, 23 Dec 2012 05:45:43 +0000 (+0100) Subject: Experimental crypto feature: Support for libvootp X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=commitdiff_plain;h=e233557e40043050c72b46d4b32b3a04cfd3d947 Experimental crypto feature: Support for libvootp --- diff --git a/Makefile.am b/Makefile.am index 6330219..fd0cbea 100644 --- a/Makefile.am +++ b/Makefile.am @@ -132,6 +132,18 @@ SIP_LIB += $(SOFIA_LIBS) endif +VOOTP_LIB = + +if ENABLE_VOOTP + +VOOTP_INCLUDE = -DWITH_VOOTP $(VOOTP_CFLAGS) + +VOOTP_SOURCE = + +VOOTP_LIB += $(VOOTP_LIBS) + +endif + bin_PROGRAMS = lcradmin gentones genwave sbin_PROGRAMS = lcr genrc genextension @@ -166,17 +178,17 @@ uninstall-hook: cd '$(DESTDIR)$(astmoddir)' && rm -f chan_lcr.so endif -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include $(MISDN_INCLUDE) $(GSM_INCLUDE) $(SS5_INCLUDE) $(SIP_INCLUDE) -Wall $(INSTALLATION_DEFINES) +AM_CPPFLAGS = $(all_includes) $(MISDN_INCLUDE) $(GSM_INCLUDE) $(SS5_INCLUDE) $(SIP_INCLUDE) $(VOOTP_INCLUDE) -Wall $(INSTALLATION_DEFINES) lcr_SOURCES = \ main.c select.c trace.c options.c tones.c alawulaw.c cause.c interface.c message.c callerid.c socket_server.c \ port.cpp vbox.cpp remote.cpp \ - $(MISDN_SOURCE) $(GSM_SOURCE) $(SS5_SOURCE) $(SIP_SOURCE) \ + $(MISDN_SOURCE) $(GSM_SOURCE) $(SS5_SOURCE) $(SIP_SOURCE) $(VOOTP_SOURCE) \ endpoint.cpp endpointapp.cpp \ appbridge.cpp apppbx.cpp route.c action.cpp action_efi.cpp action_vbox.cpp extension.c mail.c \ join.cpp joinpbx.cpp -lcr_LDADD = $(LIBCRYPTO) $(MISDN_LIB) -lpthread $(GSM_LIB) $(SIP_LIB) +lcr_LDADD = $(LIBCRYPTO) $(MISDN_LIB) -lpthread $(GSM_LIB) $(SIP_LIB) $(VOOTP_LIB) lcradmin_SOURCES = lcradmin.c cause.c options.c diff --git a/apppbx.cpp b/apppbx.cpp index b976393..7dfdf45 100644 --- a/apppbx.cpp +++ b/apppbx.cpp @@ -525,6 +525,18 @@ void EndpointAppPBX::keypad_function(char digit) join_join_dss1(); break; + /* VOOTP on */ + case '1': + PDEBUG(DEBUG_EPOINT, "EPOINT(%d) enable VoOTP.\n", ea_endpoint->ep_serial); + vootp_on(1); + break; + + /* VOOTP off */ + case '2': + PDEBUG(DEBUG_EPOINT, "EPOINT(%d) disable VoOTP.\n", ea_endpoint->ep_serial); + vootp_on(0); + break; + #ifdef WITH_CRYPT /* crypt shared */ case '7': @@ -544,7 +556,6 @@ void EndpointAppPBX::keypad_function(char digit) encrypt_off(); break; #endif - default: PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit); } @@ -2430,6 +2441,24 @@ void EndpointAppPBX::port_disable_dejitter(struct port_list *portlist, int messa } +/* port MESSAGE_UPDATEBRIDGE */ +void EndpointAppPBX::port_updatebridge(struct port_list *portlist, int message_type, union parameter *param) +{ + struct lcr_msg *message; + + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_UPDATEBRIDGE); + message_put(message); +} + + +/* port MESSAGE_VOOTP */ +void EndpointAppPBX::port_vootp(struct port_list *portlist, int message_type, union parameter *param) +{ + if (param->vootp.failed) + set_tone(ea_endpoint->ep_portlist, "crypt_off"); +} + + /* port sends message to the endpoint */ void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param) @@ -2626,6 +2655,16 @@ void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, uni port_disable_dejitter(portlist, message_type, param); break; + case MESSAGE_UPDATEBRIDGE: + PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming updatebridge message (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id); + port_updatebridge(portlist, message_type, param); + break; + + case MESSAGE_VOOTP: + PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming vootp message (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id); + port_vootp(portlist, message_type, param); + break; + default: PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message_type); @@ -4302,6 +4341,30 @@ int EndpointAppPBX::check_external(const char **errstr, class Port **port) return(0); } +int EndpointAppPBX::vootp_on(int on) +{ +#ifndef WITH_VOOTP + set_tone(ea_endpoint->ep_portlist, "crypt_off"); +#else + if (!e_ext.otp_ident[0]) { + set_tone(ea_endpoint->ep_portlist, "crypt_off"); + return -EINVAL; + } + if(ea_endpoint->ep_portlist) { + struct lcr_msg *message; + + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_VOOTP); + message->param.vootp.enable = on; + SCPY(message->param.vootp.id, e_ext.otp_ident); + message_put(message); + } + if (!on) + set_tone(ea_endpoint->ep_portlist, "crypt_off"); +#endif + + return 0; +} + void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir) { const char *logtext = "unknown"; diff --git a/apppbx.h b/apppbx.h index 1d372b1..aea434e 100644 --- a/apppbx.h +++ b/apppbx.h @@ -217,6 +217,8 @@ class EndpointAppPBX : public EndpointApp void port_resume(struct port_list *portlist, int message_type, union parameter *param); void port_enablekeypad(struct port_list *portlist, int message_type, union parameter *param); void port_disable_dejitter(struct port_list *portlist, int message_type, union parameter *param); + void port_updatebridge(struct port_list *portlist, int message_type, union parameter *param); + void port_vootp(struct port_list *portlist, int message_type, union parameter *param); void ea_message_join(unsigned int join_id, int message, union parameter *param); void join_crypt(struct port_list *portlist, int message_type, union parameter *param); void join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param); @@ -365,6 +367,8 @@ class EndpointAppPBX : public EndpointApp void cryptman_msg2crengine(int msg, unsigned char *buf, int len); void cryptman_state(int state); void cryptman_timeout(int secs); + int vootp_on(int enable); + void message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display); void logmessage(int message_type, union parameter *param, unsigned int port_id, int dir); void trace_header(const char *name, int direction); diff --git a/configure.ac b/configure.ac index 3cb6cb5..dafd9e2 100644 --- a/configure.ac +++ b/configure.ac @@ -230,6 +230,20 @@ AS_IF([test "x$with_sip" == xyes -o "x$with_sip" == xyes], [ PKG_CHECK_MODULES(SOFIA, sofia-sip-ua >= 1.12) ]) +# check for VoOTP +AC_ARG_WITH([vootp], + [AS_HELP_STRING([--with-vootp], + [compile with VoOTP support (libvootp is required) @<:@default=no@:>@]) + ], + [], + [with_vootp="check"]) + +AM_CONDITIONAL(ENABLE_VOOTP, test "x$with_vootp" == "xyes" ) + +AS_IF([test "x$with_vootp" == xyes -o "x$with_vootp" == xyes], [ + PKG_CHECK_MODULES(VOOTP, libvootp >= 0.0) + ]) + # Checks for libraries. AC_CHECK_LIB([m], [main]) AC_CHECK_LIB([ncurses], [main]) @@ -275,4 +289,5 @@ AS_IF([test "x$found_opencore_amrnb" == xyes],[AC_MSG_NOTICE( Compiled with GSM AS_IF([test "x$with_asterisk" == xyes],[AC_MSG_NOTICE( Compiled with Asterisk channel driver support )],[AC_MSG_NOTICE( Not compiled with Asterisk channel driver support)]) AS_IF([test "x$with_ss5" == xyes],[AC_MSG_NOTICE( Compiled with CCITT No.5 support )],[AC_MSG_NOTICE( Not compiled with CCITT No.5 support)]) AS_IF([test "x$with_sip" == xyes],[AC_MSG_NOTICE( Compiled with SIP support )],[AC_MSG_NOTICE( Not compiled with SIP support)]) +AS_IF([test "x$with_vootp" == xyes],[AC_MSG_NOTICE( Compiled with VoOTP support )],[AC_MSG_NOTICE( Not compiled with VoOTP support)]) diff --git a/default/options.conf b/default/options.conf index 9ee0860..a8dfa2a 100644 --- a/default/options.conf +++ b/default/options.conf @@ -109,3 +109,7 @@ # This feature is temporarily for test purpose. Don't enable it #polling +# Define OTP directory and identity +#otp-dir /root/ +#otp-ident myname + diff --git a/dss1.cpp b/dss1.cpp index 4f3d000..43452bb 100644 --- a/dss1.cpp +++ b/dss1.cpp @@ -2552,18 +2552,7 @@ void Pdss1::message_connect(unsigned int epoint_id, int message_id, union parame /* screen outgoing caller id */ do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface->name); - /* only display at connect state */ - if (p_state == PORT_STATE_CONNECT) - if (p_connectinfo.display[0]) { - /* sending information */ - l3m = create_l3msg(); - l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT); - if (p_m_d_ntmode || p_m_d_tespecial) - enc_ie_display(l3m, (unsigned char *)p_connectinfo.display); - end_trace(); - p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_INFORMATION, p_m_d_l3id, l3m); - return; - } + set_display(p_connectinfo.display); if (p_state!=PORT_STATE_IN_SETUP && p_state!=PORT_STATE_IN_OVERLAP && p_state!=PORT_STATE_IN_PROCEEDING && p_state!=PORT_STATE_IN_ALERTING) { /* connect command only possible in setup, proceeding or alerting state */ @@ -3088,6 +3077,23 @@ int stack2manager(struct mISDNport *mISDNport, unsigned int cmd, unsigned int pi return(0); } +void Pdss1::set_display(const char *text) +{ + l3_msg *l3m; + + /* only display at connect state */ + if (p_state == PORT_STATE_CONNECT) + if (text[0]) { + /* sending information */ + l3m = create_l3msg(); + l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT); + if (p_m_d_ntmode || p_m_d_tespecial) + enc_ie_display(l3m, (unsigned char *)text); + end_trace(); + p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_INFORMATION, p_m_d_l3id, l3m); + return; + } +} diff --git a/dss1.h b/dss1.h index 0c603d4..d9487b3 100644 --- a/dss1.h +++ b/dss1.h @@ -20,6 +20,7 @@ class Pdss1 : public PmISDN void message_isdn(unsigned int cmd, unsigned int pid, struct l3_msg *l3m); int p_m_d_ces; /* ntmode: tei&sapi */ int message_epoint(unsigned int epoint_id, int message, union parameter *param); + void set_display(const char *text); int p_m_d_ntmode; /* flags the nt-mode */ int p_m_d_tespecial; /* special te-mode with all nt-mode IEs */ diff --git a/extension.c b/extension.c index edfe5eb..7332551 100644 --- a/extension.c +++ b/extension.c @@ -755,6 +755,10 @@ int read_extension(struct extension *ext, char *num) } else { PDEBUG(DEBUG_CONFIG, "unknown param for seconds: %s\n", param); } + } else + if (!strcmp(option,"otp-ident")) { + SCPY(ext->otp_ident, param); + PDEBUG(DEBUG_CONFIG, "otp-ident: %s\n",param); } else { PERROR_RUNTIME("Error in %s (line %d): wrong option keyword %s.\n",filename,line,option); } @@ -1144,6 +1148,9 @@ int write_extension(struct extension *ext, char *number) fprintf(fp,"# Include seconds (time) in the connect message. (Should be always enabled.)\n"); fprintf(fp,"seconds %s\n\n",ext_yesno[1-ext->no_seconds]); + fprintf(fp,"# Identity string for VoOTP encryption\n"); + fprintf(fp,"otp-ident %s\n\n", ext->otp_ident); + fprintf(fp,"# Last outgoing and incoming numbers (including prefix)\n"); i = 0; while(i < MAX_REMEMBER) { diff --git a/extension.h b/extension.h index cb5f149..29f81b1 100644 --- a/extension.h +++ b/extension.h @@ -169,6 +169,8 @@ struct extension { int facility; /* must be set to forward facility to terminal */ int datacall; /* data calls are handled as voice calls */ int no_seconds; /* don't include seconds in the connect message */ + + char otp_ident[9]; /* up to 8 bytes of ident */ }; int read_extension(struct extension *ext, char *number); diff --git a/gsm.cpp b/gsm.cpp index 5d4b64d..ec33695 100644 --- a/gsm.cpp +++ b/gsm.cpp @@ -412,6 +412,11 @@ bfi: /* send traffic to gsm */ int Pgsm::bridge_rx(unsigned char *data, int len) { + int ret; + + if ((ret = Port::bridge_rx(data, len))) + return ret; + if (p_tone_name[0]) return -EINVAL; diff --git a/joinpbx.cpp b/joinpbx.cpp index 5d88fa2..71e7e1c 100644 --- a/joinpbx.cpp +++ b/joinpbx.cpp @@ -358,6 +358,17 @@ void JoinPBX::bridge(void) relation = relation->next; continue; } +#ifdef WITH_VOOTP + if (port->p_vootp) { + PDEBUG(DEBUG_JOIN, "join%d ignoring relation ep%d because it's port uses VoOTP.\n", j_serial, epoint->ep_serial); + if (allmISDN) { + PDEBUG(DEBUG_JOIN, "join%d not all endpoints can support mISDN bridging.\n", j_serial); + allmISDN = 0; + } + relation = relation->next; + continue; + } +#endif relation = relation->next; } @@ -412,6 +423,17 @@ no need to count, because j_3pty is taken into account below when checking relat relation = relation->next; continue; } +#ifdef WITH_VOOTP + if (port->p_vootp) { + PDEBUG(DEBUG_JOIN, "join%d ignoring relation ep%d because it's port uses VoOTP.\n", joinpbx_3pty->j_serial, epoint->ep_serial); + if (allmISDN) { + PDEBUG(DEBUG_JOIN, "join%d not all endpoints can support mISDN bridging.\n", joinpbx_3pty->j_serial); + allmISDN = 0; + } + relation = relation->next; + continue; + } +#endif relation = relation->next; } @@ -807,6 +829,11 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par } return; + case MESSAGE_UPDATEBRIDGE: + trigger_work(&j_updatebridge); + joinpbx_debug(this, "Join::message_epoint{bridge is updated due to request from mISDN port}"); + break; + /* track notify */ case MESSAGE_NOTIFY: switch(param->notifyinfo.notify) { diff --git a/mISDN.cpp b/mISDN.cpp index 179646b..bac0e84 100644 --- a/mISDN.cpp +++ b/mISDN.cpp @@ -1435,17 +1435,44 @@ void PmISDN::message_crypt(unsigned int epoint_id, int message_id, union paramet } +/* MESSAGE_VOOTP */ +void PmISDN::message_vootp(unsigned int epoint_id, int message_id, union parameter *param) +{ + struct lcr_msg *message; + + message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_UPDATEBRIDGE); + message_put(message); + +#if 0 +does not make sense, since remote port may dejitter + if (param->vootp.enable) { + PDEBUG(DEBUG_ISDN, "PmISDN(%s) received vootp enable order, so we disable de-jitter.\n", p_name); + p_m_disable_dejitter = 1; + } +#endif + update_rxoff(); +} + /* * endpoint sends messages to the port */ int PmISDN::message_epoint(unsigned int epoint_id, int message_id, union parameter *param) { + /* messages also handled by base class */ + switch(message_id) { + case MESSAGE_VOOTP: /* crypt control command */ + PDEBUG(DEBUG_ISDN, "PmISDN(%s) received VoOTP encryption\n", p_name); + message_vootp(epoint_id, message_id, param); + break; + } + if (Port::message_epoint(epoint_id, message_id, param)) { if (message_id == MESSAGE_BRIDGE) update_rxoff(); return 1; } + /* messages not handled by base class */ switch(message_id) { case MESSAGE_mISDNSIGNAL: /* user command */ PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message); @@ -2275,6 +2302,9 @@ int PmISDN::bridge_rx(unsigned char *data, int length) struct mISDNhead *hh = (struct mISDNhead *)buf; int ret; + if ((ret = Port::bridge_rx(data, length))) + return ret; + if (p_m_b_index < 0) return -EIO; if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_ACTIVE) diff --git a/mISDN.h b/mISDN.h index e3c278d..6c704f4 100644 --- a/mISDN.h +++ b/mISDN.h @@ -109,6 +109,7 @@ class PmISDN : public Port int message_epoint(unsigned int epoint_id, int message, union parameter *param); void message_mISDNsignal(unsigned int epoint_id, int message_id, union parameter *param); void message_crypt(unsigned int epoint_id, int message_id, union parameter *param); + void message_vootp(unsigned int epoint_id, int message_id, union parameter *param); struct mISDNport *p_m_mISDNport; /* pointer to port */ int p_m_delay; /* use delay instead of dejitter */ int p_m_tx_dejitter; /* use dejitter on transmit data to DSP */ diff --git a/main.c b/main.c index dddc64a..1e85e39 100644 --- a/main.c +++ b/main.c @@ -221,6 +221,12 @@ int main(int argc, char *argv[]) crc_init(); #endif +#ifdef WITH_VOOTP + /* init VoOTP */ + vootp_init(stderr); + vootp_loglevel(VOOTP_LOGL_INFO); +#endif + /* the mutex init */ if (pthread_mutex_init(&mutexd, NULL)) { fprintf(stderr, "cannot create 'PDEBUG' mutex\n"); diff --git a/main.h b/main.h index b1c407c..17ea68c 100644 --- a/main.h +++ b/main.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -147,6 +148,15 @@ void debug(const char *file, const char *function, int line, const char *prefix, #include "appbridge.h" #include "callerid.h" #include "route.h" +#ifdef WITH_VOOTP + #ifdef __cplusplus + extern "C" { + #endif +#include + #ifdef __cplusplus + } + #endif +#endif #include "port.h" #include "remote.h" #ifdef WITH_MISDN diff --git a/message.h b/message.h index 68abd5d..8a8bc44 100644 --- a/message.h +++ b/message.h @@ -351,6 +351,12 @@ struct param_3pty { unsigned char invoke_id; }; +struct param_vootp { + int enable; + int failed; + char id[32]; +}; + /* structure of message parameter */ union parameter { struct param_tone tone; /* MESSAGE_TONE */ @@ -379,6 +385,7 @@ union parameter { struct param_traffic traffic; /* MESSAGE_TRAFFIC */ struct param_3pty threepty; /* MESSAGE_TRAFFIC */ unsigned int queue; /* MESSAGE_DISABLE_DEJITTER */ + struct param_vootp vootp; /* MESSAGE_VOOTP */ }; enum { /* message flow */ @@ -435,7 +442,9 @@ enum { /* messages between entities */ MESSAGE_TRAFFIC, /* exchange bchannel traffic */ MESSAGE_3PTY, /* 3PTY call invoke */ MESSAGE_TRANSFER, /* call transfer invoke */ - MESSAGE_DISABLE_DEJITTER/* tell (mISDN) port not to dejitter */ + MESSAGE_DISABLE_DEJITTER,/* tell (mISDN) port not to dejitter */ + MESSAGE_UPDATEBRIDGE, /* tell join to update bridge. (sent by mISDN port) */ + MESSAGE_VOOTP, /* enable/disable VoOTP */ }; #define MESSAGES static const char *messages_txt[] = { \ @@ -475,6 +484,8 @@ enum { /* messages between entities */ "MESSAGE_3PTY", \ "MESSAGE_TRANSFER", \ "MESSAGE_DISABLE_DEJITTER", \ + "MESSAGE_UPDATEBRIDGE", \ + "MESSAGE_VOOTP", \ }; diff --git a/options.c b/options.c index 081e2c5..9274eb1 100644 --- a/options.c +++ b/options.c @@ -35,7 +35,8 @@ struct options options = { 0700, /* rights of lcr admin socket */ -1, /* socket user (-1= no change) */ -1, /* socket group (-1= no change) */ - 1, /* use polling of main loop */ + 0, /* use polling of main loop */ + "/root", /* OTP directory */ }; char options_error[256]; @@ -235,6 +236,13 @@ int read_options(char *options_error) } else if (!strcmp(option,"polling")) { options.polling = 1; + } else + if (!strcmp(option,"otp-dir")) { + if (param[0]==0) { + UPRINT(options_error, "Error in %s (line %d): parameter for option %s missing.\n", filename,line,option); + goto error; + } + SCPY(options.otp_dir, param); } else { UPRINT(options_error, "Error in %s (line %d): wrong option keyword %s.\n", filename,line,option); goto error; diff --git a/options.h b/options.h index 574cd68..d7e7603 100644 --- a/options.h +++ b/options.h @@ -30,6 +30,7 @@ struct options { int socketuser; /* socket chown to this user */ int socketgroup; /* socket chgrp to this group */ int polling; + char otp_dir[256]; /* directory of OTP files */ }; extern struct options options; diff --git a/port.cpp b/port.cpp index 3dc5f68..16fcd72 100644 --- a/port.cpp +++ b/port.cpp @@ -188,6 +188,11 @@ Port::Port(int type, const char *portname, struct port_settings *settings, struc p_record_buffer_writep = 0; p_record_buffer_dir = 0; + /* VoOTP */ +#ifdef WITH_VOOTP + p_vootp = NULL; +#endif + /* append port to chain */ next = NULL; temp = port_first; @@ -214,6 +219,13 @@ Port::~Port(void) PDEBUG(DEBUG_PORT, "removing port (%d) of type 0x%x, name '%s' interface '%s'\n", p_serial, p_type, p_name, p_interface_name); +#ifdef WITH_VOOTP + if (p_vootp) { + vootp_destroy(p_vootp); + p_vootp = NULL; + } +#endif + if (p_bridge) { PDEBUG(DEBUG_PORT, "Removing us from bridge %u\n", p_bridge->bridge_id); remove_bridge(p_bridge, this); @@ -377,6 +389,10 @@ void Port::set_tone(const char *dir, const char *name) } +void Port::set_display(const char *text) +{ +} + /* * set the file in the tone directory for vbox playback * also set the play_eof-flag @@ -637,6 +653,13 @@ int Port::message_epoint(unsigned int epoint_id, int message_id, union parameter PDEBUG(DEBUG_PORT, "PORT(%s) bridging to id %d\n", p_name, param->bridge_id); bridge(param->bridge_id); return 1; + +#ifdef WITH_VOOTP + case MESSAGE_VOOTP: /* enable / disable VoOTP */ + PDEBUG(DEBUG_PORT, "PORT(%s) VoOTP enabled: %d\n", p_name, param->vootp.enable); + set_vootp(¶m->vootp); + return 1; +#endif } return 0; @@ -1312,6 +1335,11 @@ int Port::bridge_tx(unsigned char *data, int len) signed long *sum; unsigned char *buf; +#ifdef WITH_VOOTP + if (p_vootp) + vootp_encrypt_stream(p_vootp, data, len); +#endif + /* less than two ports, so drop */ if (!p_bridge || !p_bridge->first || !p_bridge->first->next) return -EIO; @@ -1427,9 +1455,47 @@ int bridge_timeout(struct lcr_timer *timer, void *instance, int index) } -/* receive data from remote Port (dummy, needs to be inherited) */ +/* receive data from remote Port */ int Port::bridge_rx(unsigned char *data, int len) { - return 0; /* datenklo */ + +#ifdef WITH_VOOTP + if (p_vootp) + vootp_decrypt_stream(p_vootp, data, len); +#endif + + return 0; +} + +#ifdef WITH_VOOTP +static void vootp_info(void *priv, const char *text) +{ + class Port *port = (class Port *)priv; + char display[strlen(text) + 1]; + + SCPY(display, text); + if (display[0]) + display[strlen(display) - 1] = '\0'; + + port->set_display(display); } +void Port::set_vootp(struct param_vootp *vootp) +{ + if (p_vootp) { + vootp_destroy(p_vootp); + p_vootp = NULL; + } + if (vootp->enable) { + p_vootp = vootp_create(this, (options.law=='a'), options.otp_dir, NULL, NULL, vootp->id, vootp_info); +// vootp_loglevel(VOOTP_LOGL_DEBUG); + if (!p_vootp) { + struct lcr_msg *message; + + message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_VOOTP); + message->param.vootp.failed = 1; + message_put(message); + } + } +} +#endif diff --git a/port.h b/port.h index 6cfc6b5..56bd47b 100644 --- a/port.h +++ b/port.h @@ -196,6 +196,7 @@ class Port virtual void set_tone(const char *dir, const char *name); virtual int read_audio(unsigned char *buffer, int length); virtual void update_load(void); + virtual void set_display(const char *text); struct port_settings p_settings; char p_interface_name[64]; @@ -270,6 +271,11 @@ class Port int p_record_vbox_email_file; virtual void update_rxoff(void); /* inherited by mISDNport, to control rxoff */ +#ifdef WITH_VOOTP + vootp_t *p_vootp; /* VoOTP instance */ + void set_vootp(struct param_vootp *vootp); +#endif + void free_epointlist(struct epoint_list *epointlist); void free_epointid(unsigned int epoint_id); struct epoint_list *epointlist_new(unsigned int epoint_id); diff --git a/remote.cpp b/remote.cpp index f8c8621..273779c 100644 --- a/remote.cpp +++ b/remote.cpp @@ -233,6 +233,10 @@ int Premote::bridge_rx(unsigned char *data, int len) { union parameter newparam; int l; + int ret; + + if ((ret = Port::bridge_rx(data, len))) + return ret; /* send tones, if connected, or if early audio is enabled in proceeding/alerting state */ if (p_state != PORT_STATE_CONNECT diff --git a/sip.cpp b/sip.cpp index 4e33421..640631b 100644 --- a/sip.cpp +++ b/sip.cpp @@ -597,10 +597,15 @@ we only support alaw and ulaw! /* receive from remote */ int Psip::bridge_rx(unsigned char *data, int len) { + int ret; + /* don't bridge, if tones are provided */ if (p_tone_name[0]) return -EBUSY; + if ((ret = Port::bridge_rx(data, len))) + return ret; + /* write to rx buffer */ while(len--) { p_s_rxdata[p_s_rxpos++] = flip[*data++]; diff --git a/vbox.cpp b/vbox.cpp index 15475d9..8447b89 100644 --- a/vbox.cpp +++ b/vbox.cpp @@ -191,6 +191,11 @@ void VBoxPort::send_announcement(void) int VBoxPort::bridge_rx(unsigned char *data, int len) { + int ret; + + if ((ret = Port::bridge_rx(data, len))) + return ret; + if (p_record) record(data, len, 1); // from up return 0;