automerge commit

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40332 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Automerge script
2006-08-17 22:04:22 +00:00
parent 1e38d97c40
commit 3e1daa8f94
17 changed files with 5656 additions and 6626 deletions

View File

@@ -81,9 +81,9 @@ ifneq ($(wildcard h323/libchanh323.a),)
CHANNEL_LIBS+=chan_h323.so
endif
ifneq ($(wildcard misdn/chan_misdn_lib.a),)
ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/mISDNuser/mISDNlib.h),)
CHANNEL_LIBS+=chan_misdn.so
CFLAGS+=-Imisdn
CFLAGS+=-Imisdn
endif
CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
@@ -239,11 +239,17 @@ chan_h323.so: chan_h323.o h323/libchanh323.a
$(CC) $(SOLINK) -o $@ $< h323/libchanh323.a $(CHANH323LIB) -L$(PWLIBDIR)/lib $(PTLIB) -L$(OPENH323DIR)/lib $(H323LIB) -L/usr/lib -lcrypto -lssl -lexpat
endif
chan_misdn.so: chan_misdn.o chan_misdn_config.o misdn/chan_misdn_lib.a
$(CC) -shared -Xlinker -x -L/usr/lib -o $@ $^ -lmISDN -lisdnnet
misdn/chan_misdn_lib.a:
make -C misdn
chan_misdn.o: chan_misdn.c
$(CC) $(CFLAGS) -DCHAN_MISDN_VERSION=\"0.2.1\" -c $< -o $@
chan_misdn.so: chan_misdn.o misdn_config.o misdn/chan_misdn_lib.a
$(CC) -shared -Xlinker -x -L/usr/lib -o $@ $^ -lisdnnet -lmISDN
chan_misdn.o: chan_misdn.c
$(CC) $(CFLAGS) -DCHAN_MISDN_VERSION=\"0.3.0\" -c $< -o $@
misdn_config.o: misdn_config.c misdn/chan_misdn_config.h
$(CC) $(CFLAGS) -DCHAN_MISDN_VERSION=\"0.3.0\" -c $< -o $@
#chan_modem.so : chan_modem.o
# $(CC) -rdynamic -shared -Xlinker -x -o $@ $<

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5,10 +5,13 @@
#
# Verify those options with main Makefile
CFLAGS += -pipe -c -DMISDNUSER_JOLLY
CFLAGS = -pipe -c -Wall -ggdb
ifeq ($(shell uname -m),x86_64)
CFLAGS += -fPIC
endif
SOURCES = isdn_lib.c isdn_msg_parser.c
OBJDIR = .
OBJS = isdn_lib.o isdn_msg_parser.o
OBJS = isdn_lib.o isdn_msg_parser.o fac.o
all: chan_misdn_lib.a
@@ -16,57 +19,24 @@ all: chan_misdn_lib.a
%.o: %.c
$(CC) $(CFLAGS) -o $@ $<
chan_misdn_lib.a: $(OBJS)
ar crv $@ $(OBJS)
misdn: test_preempt
if [ ! -d lib ] ; then \
mkdir lib; \
cd lib ; \
wget http://isdn.jolly.de/download/v3.1/mISDN_for_PBX4Linux-3.0.tar.gz ;\
tar xzf mISDN_for_PBX4Linux-3.0.tar.gz; \
wget http://isdn.jolly.de/download/v3.1/mISDNuser_for_PBX4Linux-3.0.tar.gz ;\
tar xzf mISDNuser_for_PBX4Linux-3.0.tar.gz ;\
cd mISDN; patch -p1 <../../mISDN.patch; \
cd ../mISDNuser ; patch -p1 <../../mISDNuser.patch; \
fi
misdn:
@mkdir -p lib
cd lib ; cvs -d:pserver:anonymous:readonly@cvs.isdn4linux.de:/i4ldev co mISDN mISDNuser ;
cd lib/mISDN ; make install
cd lib/mISDNuser ; make install
LINUX=/lib/modules/$(uname -r)/build
GCCVERSION=$(shell $(CC) --version | grep GCC | cut -d " " -f 3 | cut -d "." -f 1)
test_preempt:
@if grep 'CONFIG_DEBUG_SPINLOCK=y' $(LINUX)/.config ; then \
echo -e "\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!\nDisable the DEBUG_SPINLOCK Setting in your Kernel Config.\n with this option set, mISDN will not work! \n\n" ;\
read ; \
exit 1 ; \
fi
@if grep 'CONFIG_DEBUG_SPINLOCK_SLEEP=y' $(LINUX)/.config ; then \
echo -e "\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!\nDisable the DEBUG_SPINLOCK_SLEEP Setting in your Kernel Config.\n with this option set, mISDN will not work! \n\n" ;\
read ; \
exit 1 ; \
fi
@if grep 'CONFIG_SMP=y' $(LINUX)/.config ; then \
echo -e "\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!\nDisable the SMP Setting in your Kernel Config.\n\n" ; \
read ; \
exit 1 ; \
fi
@if test "$(GCCVERSION)" -gt 3 ; then \
echo -e "\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!\nYou're using GCC 4! Please downgrade to gcc-3.x and type:\nexport CC=gcc-3.x\nbefore issuing make again.\nyou won't have success with gcc-4!\n\n" ; \
read ; \
exit 1 ; \
fi
portinfo: portinfo.o
$(CC) -L/usr/lib -o $@ $^ -lisdnnet -lmISDN -lpthread
FORCE:
clean:
rm -rf *.a *.o *.so
misdn_clean:
rm -rf lib
rm -rf portinfo

View File

@@ -22,47 +22,58 @@ enum misdn_cfg_elements {
/* port config items */
MISDN_CFG_FIRST = 0,
MISDN_CFG_PTP, /* int (bool) */
MISDN_CFG_GROUPNAME, /* char[] */
MISDN_CFG_ALLOWED_BEARERS, /* char[] */
MISDN_CFG_FAR_ALERTING, /* int (bool) */
MISDN_CFG_RXGAIN, /* int */
MISDN_CFG_TXGAIN, /* int */
MISDN_CFG_TE_CHOOSE_CHANNEL, /* int (bool) */
MISDN_CFG_PMP_L1_CHECK, /* int (bool) */
MISDN_CFG_ALARM_BLOCK, /* int (bool) */
MISDN_CFG_HDLC, /* int (bool) */
MISDN_CFG_CONTEXT, /* char[] */
MISDN_CFG_LANGUAGE, /* char[] */
MISDN_CFG_MUSICCLASS, /* char[] */
MISDN_CFG_CALLERID, /* char[] */
MISDN_CFG_METHOD, /* char[] */
MISDN_CFG_DIALPLAN, /* int */
MISDN_CFG_LOCALDIALPLAN, /* int */
MISDN_CFG_CPNDIALPLAN, /* int */
MISDN_CFG_NATPREFIX, /* char[] */
MISDN_CFG_INTERNATPREFIX, /* char[] */
MISDN_CFG_PRES, /* int (bool) */
MISDN_CFG_PRES, /* int */
MISDN_CFG_SCREEN, /* int */
MISDN_CFG_ALWAYS_IMMEDIATE, /* int (bool) */
MISDN_CFG_NODIALTONE, /* int (bool) */
MISDN_CFG_IMMEDIATE, /* int (bool) */
MISDN_CFG_SENDDTMF, /* int (bool) */
MISDN_CFG_HOLD_ALLOWED, /* int (bool) */
MISDN_CFG_EARLY_BCONNECT, /* int (bool) */
MISDN_CFG_USE_CALLINGPRES, /* int (bool) */
MISDN_CFG_INCOMING_EARLY_AUDIO, /* int (bool) */
MISDN_CFG_ECHOCANCEL, /* int */
MISDN_CFG_ECHOCANCELWHENBRIDGED, /* int (bool) */
MISDN_CFG_ECHOTRAINING, /* int (bool) */
MISDN_CFG_NEED_MORE_INFOS, /* bool */
MISDN_CFG_JITTERBUFFER, /* int */
MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, /* int */
MISDN_CFG_CALLGROUP, /* ast_group_t */
MISDN_CFG_PICKUPGROUP, /* ast_group_t */
MISDN_CFG_MSNS, /* char[] */
MISDN_CFG_PTP, /* int (bool) */
MISDN_CFG_LAST,
/* general config items */
MISDN_GEN_FIRST,
MISDN_GEN_MISDN_INIT, /* char[] */
MISDN_GEN_DEBUG, /* int */
MISDN_GEN_TRACEFILE, /* char[] */
MISDN_GEN_TRACE_CALLS, /* int (bool) */
MISDN_GEN_TRACE_DIR, /* char[] */
MISDN_GEN_BRIDGING, /* int (bool) */
MISDN_GEN_STOP_TONE, /* int (bool) */
MISDN_GEN_APPEND_DIGITS2EXTEN, /* int (bool) */
MISDN_GEN_L1_INFO_OK, /* int (bool) */
MISDN_GEN_CLEAR_L3, /* int (bool) */
MISDN_GEN_DYNAMIC_CRYPT, /* int (bool) */
MISDN_GEN_CRYPT_PREFIX, /* char[] */
MISDN_GEN_CRYPT_KEYS, /* char[] */
MISDN_GEN_NTDEBUGFLAGS, /* int */
MISDN_GEN_NTDEBUGFILE, /* char[] */
MISDN_GEN_LAST
};
@@ -76,6 +87,8 @@ void misdn_cfg_init(int max_ports);
void misdn_cfg_reload(void);
void misdn_cfg_destroy(void);
void misdn_cfg_update_ptp( void );
/* if you requst a general config element, the port value is ignored. if the requested
* value is not available, or the buffer is too small, the buffer will be nulled (in
* case of a char* only its first byte will be nulled). */

313
channels/misdn/fac.c Normal file
View File

@@ -0,0 +1,313 @@
#include "isdn_lib_intern.h"
#include "isdn_lib.h"
#include "string.h"
#define CENTREX_ID 0xa1
#define CALLDEFLECT_ID 0xa1
/**
This file covers the encoding and decoding of facility messages and
facility information elements.
There will be 2 Functions as Interface:
fac_enc( char **ntmsg, msg_t * msg, enum facility_type type, union facility fac, struct misdn_bchannel *bc)
fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc);
Those will either read the union facility or fill it.
internally, we will have deconding and encoding functions for each facility
IE.
**/
/* support stuff */
static void strnncpy(unsigned char *dest, unsigned char *src, int len, int dst_len)
{
if (len > dst_len-1)
len = dst_len-1;
strncpy((char *)dest, (char *)src, len);
dest[len] = '\0';
}
/**********************/
/*** FACILITY STUFF ***/
/**********************/
/* IE_FACILITY */
void enc_ie_facility(unsigned char **ntmode, msg_t *msg, unsigned char *facility, int facility_len, int nt, struct misdn_bchannel *bc)
{
unsigned char *p;
Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
int l;
if (!facility || facility_len<=0)
{
return;
}
l = facility_len;
p = msg_put(msg, l+2);
if (nt)
*ntmode = p+1;
else
qi->QI_ELEMENT(facility) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_FACILITY;
p[1] = l;
memcpy(p+2, facility, facility_len);
}
/* facility for siemens CENTEX (known parts implemented only) */
void enc_ie_facility_centrex(unsigned char **ntmode, msg_t *msg, unsigned char *cnip, int setup, int nt, struct misdn_bchannel *bc)
{
unsigned char centrex[256];
int i = 0;
if (!cnip)
return;
/* centrex facility */
centrex[i++] = FACILITY_CENTREX;
centrex[i++] = CENTREX_ID;
/* cnip */
if (strlen((char *)cnip) > 15)
{
/* if (options.deb & DEBUG_PORT) */
cb_log(1,0,"%s: CNIP/CONP text too long (max 13 chars), cutting.\n", __FUNCTION__);
cnip[15] = '\0';
}
/* dunno what the 8 bytes mean */
if (setup)
{
centrex[i++] = 0x17;
centrex[i++] = 0x02;
centrex[i++] = 0x02;
centrex[i++] = 0x44;
centrex[i++] = 0x18;
centrex[i++] = 0x02;
centrex[i++] = 0x01;
centrex[i++] = 0x09;
} else
{
centrex[i++] = 0x18;
centrex[i++] = 0x02;
centrex[i++] = 0x02;
centrex[i++] = 0x81;
centrex[i++] = 0x09;
centrex[i++] = 0x02;
centrex[i++] = 0x01;
centrex[i++] = 0x0a;
}
centrex[i++] = 0x80;
centrex[i++] = strlen((char *)cnip);
strcpy((char *)(&centrex[i]), (char *)cnip);
i += strlen((char *)cnip);
cb_log(4,0," cnip='%s'\n", cnip);
/* encode facility */
enc_ie_facility(ntmode, msg, centrex, i, nt , bc);
}
void dec_ie_facility_centrex(unsigned char *p, Q931_info_t *qi, unsigned char *centrex, int facility_len, unsigned char *cnip, int cnip_len, int nt, struct misdn_bchannel *bc)
{
int i = 0;
*cnip = '\0';
if (facility_len >= 2)
{
if (centrex[i++] != FACILITY_CENTREX)
return;
if (centrex[i++] != CENTREX_ID)
return;
}
/* loop sub IEs of facility */
while(facility_len > i+1)
{
if (centrex[i+1]+i+1 > facility_len)
{
printf("%s: ERROR: short read of centrex facility.\n", __FUNCTION__);
return;
}
switch(centrex[i])
{
case 0x80:
strnncpy(cnip, &centrex[i+2], centrex[i+1], cnip_len);
cb_log(4,0," CENTREX cnip='%s'\n", cnip);
break;
}
i += 1+centrex[i+1];
}
}
/* facility for CALL Deflect (known parts implemented only) */
void enc_ie_facility_calldeflect(unsigned char **ntmode, msg_t *msg, unsigned char *nr, int nt, struct misdn_bchannel *bc)
{
unsigned char fac[256];
if (!nr)
return;
int len = strlen(nr);
/* calldeflect facility */
/* cnip */
if (strlen((char *)nr) > 15)
{
/* if (options.deb & DEBUG_PORT) */
cb_log(1,0,"%s: NR text too long (max 13 chars), cutting.\n", __FUNCTION__);
nr[15] = '\0';
}
fac[0]=FACILITY_CALLDEFLECT; // ..
fac[1]=CALLDEFLECT_ID;
fac[2]=0x0f + len; // strlen destination + 15 = 26
fac[3]=0x02;
fac[4]=0x01;
//fac[5]=0x70;
fac[5]=0x09;
fac[6]=0x02;
fac[7]=0x01;
fac[8]=0x0d;
fac[9]=0x30;
fac[10]=0x07 + len; // strlen destination + 7 = 18
fac[11]=0x30; // ...hm 0x30
fac[12]=0x02+ len; // strlen destination + 2
fac[13]=0x80; // CLIP
fac[14]= len; // strlen destination
memcpy((unsigned char *)fac+15,nr,len);
fac[15+len]=0x01; //sending complete
fac[16+len]=0x01;
fac[17+len]=0x80;
enc_ie_facility(ntmode, msg, fac, 17+len +1 , nt , bc);
}
void dec_ie_facility_calldeflect(unsigned char *p, Q931_info_t *qi, unsigned char *fac, int fac_len, unsigned char *cd_nr, int nt, struct misdn_bchannel *bc)
{
*cd_nr = '\0';
if (fac_len >= 15)
{
if (fac[0] != FACILITY_CALLDEFLECT)
return;
if (fac[1] != CALLDEFLECT_ID)
return;
} else {
cb_log(1,bc->port, "IE too short: FAC_CALLDEFLECT\n");
return ;
}
{
int dest_len=fac[2]-0x0f;
if (dest_len <0 || dest_len > 15) {
cb_log(1,bc->port, "IE is garbage: FAC_CALLDEFLECT\n");
return ;
}
if (fac_len < 15+dest_len) {
cb_log(1,bc->port, "IE too short: FAC_CALLDEFLECT\n");
return ;
}
memcpy(cd_nr, &fac[15],dest_len);
cd_nr[dest_len]=0;
cb_log(5,bc->port, "--> IE CALLDEFLECT NR: %s\n",cd_nr);
}
}
void fac_enc( unsigned char **ntmsg, msg_t * msg, enum facility_type type, union facility fac, struct misdn_bchannel *bc)
{
switch (type) {
case FACILITY_CENTREX:
{
int setup=0;
enc_ie_facility_centrex(ntmsg, msg, fac.cnip, setup, bc->nt, bc);
}
break;
case FACILITY_CALLDEFLECT:
enc_ie_facility_calldeflect(ntmsg, msg, fac.calldeflect_nr, bc->nt, bc);
break;
default:
cb_log(1,0,"Don't know how handle this facility: %d\n", type);
}
}
void fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc)
{
int i, fac_len=0;
unsigned char facility[256];
if (!bc->nt)
{
p = NULL;
if (qi->QI_ELEMENT(facility))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
}
if (!p)
return;
fac_len = p[0] & 0xff;
memcpy(facility, p+1, fac_len);
switch(facility[0]) {
case FACILITY_CENTREX:
{
int cnip_len=15;
dec_ie_facility_centrex(p, qi,facility, fac_len, fac->cnip, cnip_len, bc->nt, bc);
*type=FACILITY_CENTREX;
}
break;
case FACILITY_CALLDEFLECT:
dec_ie_facility_calldeflect(p, qi,facility, fac_len, fac->calldeflect_nr, bc->nt, bc);
*type=FACILITY_CALLDEFLECT;
break;
default:
cb_log(3, bc->port, "Unknown Facility received: ");
i = 0;
while(i < fac_len)
{
cb_log(3, bc->port, " %02x", facility[i]);
i++;
}
cb_log(3, bc->port, " facility\n");
*type=FACILITY_NONE;
}
}
/*** FACILITY END **/

8
channels/misdn/fac.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef FAC_H
#define FAC_H
void fac_enc( unsigned char **ntmsg, msg_t * msg, enum facility_type type, union facility fac, struct misdn_bchannel *bc);
void fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc);
#endif

View File

@@ -23,17 +23,12 @@
#include <string.h>
#include "isdn_lib_intern.h"
#include <mISDNuser/mISDNlib.h>
#include <mISDNuser/isdn_net.h>
#include <mISDNuser/l3dss1.h>
#include <mISDNuser/net_l3.h>
#define CENTREX_FAC 0x88
#define CENTREX_ID 0xa1
#define MISDN_IE_DEBG 0
@@ -69,7 +64,8 @@ void enc_ie_complete(unsigned char **ntmode, msg_t *msg, int complete, int nt, s
{
*ntmode = p;
} else
qi->sending_complete = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(sending_complete) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_COMPLETE;
}
}
@@ -79,7 +75,7 @@ void dec_ie_complete(unsigned char *p, Q931_info_t *qi, int *complete, int nt, s
*complete = 0;
if (!nt)
{
if (qi->sending_complete)
if (qi->QI_ELEMENT(sending_complete))
*complete = 1;
} else
if (p)
@@ -140,7 +136,7 @@ void enc_ie_bearer(unsigned char **ntmode, msg_t *msg, int coding, int capabilit
if (nt)
*ntmode = p+1;
else
qi->bearer_capability = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(bearer_capability) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_BEARER;
p[1] = l;
p[2] = 0x80 + (coding<<5) + capability;
@@ -166,23 +162,28 @@ void dec_ie_bearer(unsigned char *p, Q931_info_t *qi, int *coding, int *capabili
*stopbits = -1;
*dbits = -1;
*parity = -1;
if (!nt)
{
p = NULL;
if (qi->llc)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->llc + 1;
else if (qi->bearer_capability)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->bearer_capability + 1;
#ifdef LLC_SUPPORT
if (qi->QI_ELEMENT(llc)) {
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(llc) + 1;
}
#endif
if (qi->QI_ELEMENT(bearer_capability))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(bearer_capability) + 1;
}
if (!p)
return;
if (p[0] < 2)
{
printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
return;
}
*coding = (p[1]&0x60) >> 5;
*capability = p[1] & 0x1f;
octet = 2;
@@ -292,7 +293,7 @@ void enc_ie_call_id(unsigned char **ntmode, msg_t *msg, unsigned char *callid, i
if (nt)
*ntmode = p+1;
else
qi->call_id = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(call_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_CALL_ID;
p[1] = l;
memcpy(p+2, callid, callid_len);
@@ -308,8 +309,8 @@ void dec_ie_call_id(unsigned char *p, Q931_info_t *qi, unsigned char *callid, in
if (!nt)
{
p = NULL;
if (qi->call_id)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->call_id + 1;
if (qi->QI_ELEMENT(call_id))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(call_id) + 1;
}
if (!p)
return;
@@ -363,7 +364,7 @@ void enc_ie_called_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, un
if (nt)
*ntmode = p+1;
else
qi->called_nr = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(called_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_CALLED_PN;
p[1] = l;
p[2] = 0x80 + (type<<4) + plan;
@@ -379,8 +380,8 @@ void dec_ie_called_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, u
if (!nt)
{
p = NULL;
if (qi->called_nr)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->called_nr + 1;
if (qi->QI_ELEMENT(called_nr))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(called_nr) + 1;
}
if (!p)
return;
@@ -437,7 +438,7 @@ void enc_ie_calling_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, i
if (nt)
*ntmode = p+1;
else
qi->calling_nr = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(calling_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_CALLING_PN;
p[1] = l;
if (present >= 0)
@@ -465,8 +466,8 @@ void dec_ie_calling_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan,
if (!nt)
{
p = NULL;
if (qi->calling_nr)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->calling_nr + 1;
if (qi->QI_ELEMENT(calling_nr))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(calling_nr) + 1;
}
if (!p)
return;
@@ -539,7 +540,7 @@ void enc_ie_connected_pn(unsigned char **ntmode, msg_t *msg, int type, int plan,
if (nt)
*ntmode = p+1;
else
qi->connected_nr = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(connected_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_CONNECT_PN;
p[1] = l;
if (present >= 0)
@@ -567,8 +568,8 @@ void dec_ie_connected_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan
if (!nt)
{
p = NULL;
if (qi->connected_nr)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->connected_nr + 1;
if (qi->QI_ELEMENT(connected_nr))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(connected_nr) + 1;
}
if (!p)
return;
@@ -624,7 +625,7 @@ void enc_ie_cause(unsigned char **ntmode, msg_t *msg, int location, int cause, i
if (nt)
*ntmode = p+1;
else
qi->cause = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(cause) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_CAUSE;
p[1] = l;
p[2] = 0x80 + location;
@@ -637,7 +638,7 @@ void enc_ie_cause_standalone(unsigned char **ntmode, msg_t *msg, int location, i
if (ntmode)
*ntmode = p+1;
else
qi->cause = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(cause) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_CAUSE;
p[1] = 2;
p[2] = 0x80 + location;
@@ -653,8 +654,8 @@ void dec_ie_cause(unsigned char *p, Q931_info_t *qi, int *location, int *cause,
if (!nt)
{
p = NULL;
if (qi->cause)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->cause + 1;
if (qi->QI_ELEMENT(cause))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(cause) + 1;
}
if (!p)
return;
@@ -705,7 +706,7 @@ void enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int ch
if (nt)
*ntmode = p+1;
else
qi->channel_id = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_CHANNEL_ID;
p[1] = l;
if (channel == 0xff)
@@ -725,7 +726,7 @@ void enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int ch
if (nt)
*ntmode = p+1;
else
qi->channel_id = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_CHANNEL_ID;
p[1] = l;
p[2] = 0x80 + 0x20 + 0x03;
@@ -737,7 +738,7 @@ void enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int ch
if (nt)
*ntmode = p+1;
else
qi->channel_id = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_CHANNEL_ID;
p[1] = l;
p[2] = 0x80 + 0x20 + (exclusive<<3) + 0x01;
@@ -758,8 +759,8 @@ void dec_ie_channel_id(unsigned char *p, Q931_info_t *qi, int *exclusive, int *c
if (!nt)
{
p = NULL;
if (qi->channel_id)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->channel_id + 1;
if (qi->QI_ELEMENT(channel_id))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(channel_id) + 1;
}
if (!p)
return;
@@ -863,7 +864,7 @@ void enc_ie_date(unsigned char **ntmode, msg_t *msg, time_t ti, int nt, struct m
if (nt)
*ntmode = p+1;
else
qi->date = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(date) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_DATE;
p[1] = l;
p[2] = tm->tm_year % 100;
@@ -900,7 +901,7 @@ void enc_ie_display(unsigned char **ntmode, msg_t *msg, unsigned char *display,
if (nt)
*ntmode = p+1;
else
qi->display = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(display) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_DISPLAY;
p[1] = l;
strncpy((char *)p+2, (char *)display, strlen((char *)display));
@@ -913,8 +914,8 @@ void dec_ie_display(unsigned char *p, Q931_info_t *qi, unsigned char *display, i
if (!nt)
{
p = NULL;
if (qi->display)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->display + 1;
if (qi->QI_ELEMENT(display))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(display) + 1;
}
if (!p)
return;
@@ -950,7 +951,7 @@ void enc_ie_keypad(unsigned char **ntmode, msg_t *msg, unsigned char *keypad, in
if (nt)
*ntmode = p+1;
else
qi->keypad = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(keypad) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_KEYPAD;
p[1] = l;
strncpy((char *)p+2, (char *)keypad, strlen((char *)keypad));
@@ -963,8 +964,8 @@ void dec_ie_keypad(unsigned char *p, Q931_info_t *qi, unsigned char *keypad, int
if (!nt)
{
p = NULL;
if (qi->keypad)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->keypad + 1;
if (qi->QI_ELEMENT(keypad))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(keypad) + 1;
}
if (!p)
return;
@@ -1000,7 +1001,7 @@ void enc_ie_notify(unsigned char **ntmode, msg_t *msg, int notify, int nt, struc
if (nt)
*ntmode = p+1;
else
qi->notify = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(notify) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_NOTIFY;
p[1] = l;
p[2] = 0x80 + notify;
@@ -1013,8 +1014,8 @@ void dec_ie_notify(unsigned char *p, Q931_info_t *qi, int *notify, int nt, struc
if (!nt)
{
p = NULL;
if (qi->notify)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->notify + 1;
if (qi->QI_ELEMENT(notify))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(notify) + 1;
}
if (!p)
return;
@@ -1060,7 +1061,7 @@ void enc_ie_progress(unsigned char **ntmode, msg_t *msg, int coding, int locatio
if (nt)
*ntmode = p+1;
else
qi->progress = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(progress) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_PROGRESS;
p[1] = l;
p[2] = 0x80 + (coding<<5) + location;
@@ -1077,8 +1078,8 @@ void dec_ie_progress(unsigned char *p, Q931_info_t *qi, int *coding, int *locati
if (!nt)
{
p = NULL;
if (qi->progress)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->progress + 1;
if (qi->QI_ELEMENT(progress))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(progress) + 1;
}
if (!p)
return;
@@ -1144,7 +1145,7 @@ void enc_ie_redir_nr(unsigned char **ntmode, msg_t *msg, int type, int plan, int
if (nt)
*ntmode = p+1;
else
qi->redirect_nr = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(redirect_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_REDIR_NR;
p[1] = l;
if (present >= 0)
@@ -1183,8 +1184,8 @@ void dec_ie_redir_nr(unsigned char *p, Q931_info_t *qi, int *type, int *plan, in
if (!nt)
{
p = NULL;
if (qi->redirect_nr)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->redirect_nr + 1;
if (qi->QI_ELEMENT(redirect_nr))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(redirect_nr) + 1;
}
if (!p)
return;
@@ -1252,7 +1253,7 @@ void enc_ie_redir_dn(unsigned char **ntmode, msg_t *msg, int type, int plan, int
*ntmode = p+1;
else
/* #warning REINSERT redir_dn, when included in te-mode */
/*qi->redir_dn = p - (unsigned char *)qi - sizeof(Q931_info_t)*/;
/*qi->QI_ELEMENT(redir_dn) = p - (unsigned char *)qi - sizeof(Q931_info_t)*/;
p[0] = IE_REDIR_DN;
p[1] = l;
if (present >= 0)
@@ -1280,8 +1281,8 @@ void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, in
{
p = NULL;
/* #warning REINSERT redir_dn, when included in te-mode */
/* if (qi->redir_dn) */
/* p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->redir_dn + 1; */
/* if (qi->QI_ELEMENT(redir_dn)) */
/* p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(redir_dn) + 1; */
}
if (!p)
return;
@@ -1306,242 +1307,6 @@ void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, in
}
/* IE_FACILITY */
void enc_ie_facility(unsigned char **ntmode, msg_t *msg, unsigned char *facility, int facility_len, int nt, struct misdn_bchannel *bc)
{
unsigned char *p;
Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
int l;
char debug[768];
int i;
if (!facility || facility_len<=0)
{
return;
}
i = 0;
while(i < facility_len)
{
if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", facility[i]);
i++;
}
if (MISDN_IE_DEBG) printf(" facility%s\n", debug);
l = facility_len;
p = msg_put(msg, l+2);
if (nt)
*ntmode = p+1;
else
qi->facility = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_FACILITY;
p[1] = l;
memcpy(p+2, facility, facility_len);
}
void dec_ie_facility(unsigned char *p, Q931_info_t *qi, unsigned char *facility, int *facility_len, int nt, struct misdn_bchannel *bc)
{
int i;
struct misdn_stack *stack=get_stack_by_bc(bc);
*facility_len = 0;
if (!nt)
{
p = NULL;
if (qi->facility)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->facility + 1;
}
if (!p)
return;
*facility_len = p[0];
memcpy(facility, p+1, *facility_len);
i = 0;
while(i < *facility_len)
{
cb_log(3, stack->port, " %02x", facility[i]);
i++;
}
cb_log(3, stack->port, " facility\n");
}
/* facility for siemens CENTEX (known parts implemented only) */
void enc_facility_centrex(unsigned char **ntmode, msg_t *msg, unsigned char *cnip, int setup, int nt, struct misdn_bchannel *bc)
{
unsigned char centrex[256];
int i = 0;
if (!cnip)
return;
/* centrex facility */
centrex[i++] = CENTREX_FAC;
centrex[i++] = CENTREX_ID;
/* cnip */
if (strlen((char *)cnip) > 15)
{
/* if (options.deb & DEBUG_PORT) */
if (MISDN_IE_DEBG) printf("%s: CNIP/CONP text too long (max 13 chars), cutting.\n", __FUNCTION__);
cnip[15] = '\0';
}
/* dunno what the 8 bytes mean */
if (setup)
{
centrex[i++] = 0x17;
centrex[i++] = 0x02;
centrex[i++] = 0x02;
centrex[i++] = 0x44;
centrex[i++] = 0x18;
centrex[i++] = 0x02;
centrex[i++] = 0x01;
centrex[i++] = 0x09;
} else
{
centrex[i++] = 0x18;
centrex[i++] = 0x02;
centrex[i++] = 0x02;
centrex[i++] = 0x81;
centrex[i++] = 0x09;
centrex[i++] = 0x02;
centrex[i++] = 0x01;
centrex[i++] = 0x0a;
}
centrex[i++] = 0x80;
centrex[i++] = strlen((char *)cnip);
strcpy((char *)(&centrex[i]), (char *)cnip);
i += strlen((char *)cnip);
if (MISDN_IE_DEBG) printf(" cnip='%s'\n", cnip);
/* encode facility */
enc_ie_facility(ntmode, msg, centrex, i, nt , bc);
}
void dec_facility_centrex(unsigned char *p, Q931_info_t *qi, unsigned char *cnip, int cnip_len, int nt, struct misdn_bchannel *bc)
{
unsigned char centrex[256];
char debug[768];
int facility_len = 0;
int i = 0, j;
*cnip = '\0';
dec_ie_facility(p, qi, centrex, &facility_len, nt, bc);
if (facility_len >= 2)
{
if (centrex[i++] != CENTREX_FAC)
return;
if (centrex[i++] != CENTREX_ID)
return;
}
/* loop sub IEs of facility */
while(facility_len > i+1)
{
if (centrex[i+1]+i+1 > facility_len)
{
printf("%s: ERROR: short read of centrex facility.\n", __FUNCTION__);
return;
}
switch(centrex[i])
{
case 0x80:
strnncpy(cnip, &centrex[i+2], centrex[i+1], cnip_len);
if (MISDN_IE_DEBG) printf(" CENTREX cnip='%s'\n", cnip);
break;
default:
j = 0;
while(j < centrex[i+1])
{
if (MISDN_IE_DEBG) printf(debug+(j*3), " %02x", centrex[i+1+j]);
i++;
}
if (MISDN_IE_DEBG) printf(" CENTREX unknown=0x%2x len=%d%s\n", centrex[i], centrex[i+1], debug);
}
i += 1+centrex[i+1];
}
}
/* facility for siemens CENTEX (known parts implemented only) */
void enc_facility_calldeflect(unsigned char **ntmode, msg_t *msg, unsigned char *nr, int nt, struct misdn_bchannel *bc)
{
unsigned char fac[256];
if (!nr)
return;
/* calldeflect facility */
/* cnip */
if (strlen((char *)nr) > 15)
{
/* if (options.deb & DEBUG_PORT) */
if (MISDN_IE_DEBG) printf("%s: NR text too long (max 13 chars), cutting.\n", __FUNCTION__);
nr[15] = '\0';
}
fac[0]=0; // len
fac[1]=0; //len
fac[2]=0x01; // Use D-Chan
fac[3]=0; // Keypad len
fac[4]=31; // user user data? len = 31 = 29 + 2
fac[5]=0x1c; // magic?
fac[6]=0x1d; // strlen destination + 18 = 29
fac[7]=0x91; // ..
fac[8]=0xA1;
fac[9]=0x1A; // strlen destination + 15 = 26
fac[10]=0x02;
fac[11]=0x01;
fac[12]=0x70;
fac[13]=0x02;
fac[14]=0x01;
fac[15]=0x0d;
fac[16]=0x30;
fac[17]=0x12; // strlen destination + 7 = 18
fac[18]=0x30; // ...hm 0x30
fac[19]=0x0d; // strlen destination + 2
fac[20]=0x80; // CLIP
fac[21]=0x0b; // strlen destination
fac[22]=0x01; // destination start
fac[23]=0x01; //
fac[24]=0x01; //
fac[25]=0x01; //
fac[26]=0x01; //
fac[27]=0x01; //
fac[28]=0x01; //
fac[29]=0x01; //
fac[30]=0x01; //
fac[31]=0x01; //
fac[32]=0x01; //
fac[33]=0x01; // 0x1 = sending complete
fac[34]=0x01;
fac[35]=0x01;
memcpy((unsigned char *)fac+22,nr,strlen(nr));
fac[22+strlen( nr)]=0x01; // fill with 0x01 if number is only 6 numbers (local call)
fac[23+strlen(nr)]=0x01;
fac[24+strlen(nr)]=0x01;
fac[25+strlen(nr)]=0x01;
fac[26+strlen(nr)]=0x01;
fac[6]=18+strlen(nr);
fac[9]=15+strlen(nr);
fac[17]=7+strlen(nr);
fac[19]=2+strlen(nr);
fac[21]=strlen(nr);
enc_ie_facility(ntmode, msg, &fac[4], 36-4, nt , bc);
}
/* IE_USERUSER */
void enc_ie_useruser(unsigned char **ntmode, msg_t *msg, int protocol, unsigned char *user, int user_len, int nt, struct misdn_bchannel *bc)
@@ -1577,7 +1342,7 @@ void enc_ie_useruser(unsigned char **ntmode, msg_t *msg, int protocol, unsigned
if (nt)
*ntmode = p+1;
else
qi->useruser = p - (unsigned char *)qi - sizeof(Q931_info_t);
qi->QI_ELEMENT(useruser) = p - (unsigned char *)qi - sizeof(Q931_info_t);
p[0] = IE_USER_USER;
p[1] = l;
p[2] = 0x80 + protocol;
@@ -1595,8 +1360,8 @@ void dec_ie_useruser(unsigned char *p, Q931_info_t *qi, int *protocol, unsigned
if (!nt)
{
p = NULL;
if (qi->useruser)
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->useruser + 1;
if (qi->QI_ELEMENT(useruser))
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(useruser) + 1;
}
if (!p)
return;
@@ -1619,3 +1384,5 @@ void dec_ie_useruser(unsigned char *p, Q931_info_t *qi, int *protocol, unsigned
}

File diff suppressed because it is too large Load Diff

View File

@@ -14,36 +14,74 @@
#ifndef TE_LIB
#define TE_LIB
/** For initialization usage **/
/* typedef int ie_nothing_t ;*/
/** end of init usage **/
#ifdef WITH_BEROEC
typedef int beroec_t;
#define MAX_BCHANS 30
enum bc_state_e {
STATE_NOTHING=0,
STATE_NULL,
STATE_CALL_INIT,
STATE_CONNECTED,
STATE_HOLD_ACKNOWLEDGE
enum beroec_type {
BEROEC_FULLBAND=0,
BEROEC_SUBBAND,
BEROEC_FASTSUBBAND
};
void beroec_init(void);
void beroec_exit(void);
beroec_t *beroec_new(int tail, enum beroec_type type, int anti_howl,
int tonedisable, int zerocoeff, int adapt, int nlp);
void beroec_destroy(beroec_t *ec);
int beroec_cancel_alaw_chunk(beroec_t *ec,
char *send,
char *receive ,
int len);
int beroec_version(void);
#endif
enum tone_e {
TONE_NONE=0,
TONE_DIAL,
TONE_ALERTING,
TONE_FAR_ALERTING,
TONE_BUSY,
TONE_HANGUP,
TONE_CUSTOM,
TONE_FILE
};
#define MAX_BCHANS 30
enum bchannel_state {
BCHAN_CLEANED=0,
BCHAN_EMPTY,
BCHAN_SETUP,
BCHAN_SETUPED,
BCHAN_ACTIVE,
BCHAN_ACTIVATED,
BCHAN_BRIDGE,
BCHAN_BRIDGED,
BCHAN_RELEASE,
BCHAN_RELEASED,
BCHAN_CLEAN,
BCHAN_CLEAN_REQUEST,
BCHAN_ERROR
};
enum misdn_err_e {
ENOCHAN=1
};
enum mISDN_NUMBER_PLAN {
NUMPLAN_UNINITIALIZED=-1,
NUMPLAN_INTERNATIONAL=0x1,
@@ -61,10 +99,11 @@ enum event_response_e {
};
enum event_e {
EVENT_NOTHING,
EVENT_TONE_GENERATE,
EVENT_BCHAN_DATA,
EVENT_BCHAN_ACTIVATED,
EVENT_CLEANUP,
EVENT_PROCEEDING,
EVENT_PROGRESS,
@@ -99,6 +138,7 @@ enum event_e {
EVENT_DTMF_TONE,
EVENT_NEW_L3ID,
EVENT_NEW_BC,
EVENT_PORT_ALARM,
EVENT_UNKNOWN
};
@@ -144,9 +184,19 @@ enum layer_e {
UNKNOWN
};
/** FACILITY STUFF **/
enum facility_type {
FACILITY_NONE,
FACILITY_CALLDEFLECT
FACILITY_CALLDEFLECT=0x91,
FACILITY_CENTREX=0x88
};
union facility {
char calldeflect_nr[15];
char cnip[256];
};
@@ -161,13 +211,21 @@ struct misdn_bchannel {
/* int b_addr; */
int layer_id;
void *ack_hdlc;
int layer;
/*state stuff*/
int need_disconnect;
int need_release;
int need_release_complete;
/** var stuff**/
int l3_id;
int pid;
int ces;
int restart_channel;
int channel;
int channel_preselected;
@@ -180,8 +238,8 @@ struct misdn_bchannel {
void *astbuf;
void *misdnbuf;
int te_choose_channel;
int early_bconnect;
@@ -190,6 +248,13 @@ struct misdn_bchannel {
int dtmf;
int send_dtmf;
/* get setup ack */
int need_more_infos;
/* may there be more infos ?*/
int sending_complete;
/* wether we should use jollys dsp or not */
int nodsp;
@@ -199,13 +264,17 @@ struct misdn_bchannel {
enum mISDN_NUMBER_PLAN dnumplan;
enum mISDN_NUMBER_PLAN rnumplan;
enum mISDN_NUMBER_PLAN onumplan;
enum mISDN_NUMBER_PLAN cpnnumplan;
int progress_coding;
int progress_location;
int progress_indicator;
enum facility_type facility;
char facility_calldeflect_nr[15];
enum facility_type fac_type;
union facility fac;
enum facility_type out_fac_type;
union facility out_fac;
enum event_e evq;
@@ -226,14 +295,18 @@ struct misdn_bchannel {
int active;
int upset;
enum tone_e tone;
int generate_tone;
int tone_cnt;
int tone_cnt2;
enum bc_state_e state;
enum bchannel_state bc_state;
enum bchannel_state next_bc_state;
int conf_id;
int holded;
int stack_holder;
struct misdn_bchannel *holded_bc;
int pres;
int screen;
@@ -246,7 +319,7 @@ struct misdn_bchannel {
int user1;
int urate;
int async;
int hdlc;
/* V110 */
unsigned char display[84];
@@ -254,16 +327,17 @@ struct misdn_bchannel {
unsigned char oad[32];
unsigned char rad[32];
unsigned char dad[32];
unsigned char cad[32];
unsigned char orig_dad[32];
unsigned char keypad[32];
unsigned char info_dad[64];
unsigned char infos_pending[64];
unsigned char info_keypad[32];
unsigned char clisub[24];
unsigned char cldsub[24];
unsigned char fac[132];
unsigned char uu[256];
/* unsigned char info_keypad[32]; */
/* unsigned char clisub[24]; */
/* unsigned char cldsub[24]; */
/* unsigned char uu[256]; */
int cause;
int out_cause;
@@ -276,6 +350,16 @@ struct misdn_bchannel {
int ec_deftaps;
int ec_whenbridged;
int ec_training;
#ifdef WITH_BEROEC
beroec_t *ec;
int bnec_tail;
int bnec_ah;
int bnec_nlp;
int bnec_td;
int bnec_adapt;
int bnec_zero;
#endif
int orig;
@@ -288,17 +372,19 @@ struct misdn_bchannel {
enum event_response_e (*cb_event) (enum event_e event, struct misdn_bchannel *bc, void *user_data);
void (*cb_log) (int level, int port, char *tmpl, ...);
int (*cb_clearl3_true)(void);
int (*cb_jb_empty)(struct misdn_bchannel *bc, char *buffer, int len);
struct misdn_lib_iface {
enum event_response_e (*cb_event)(enum event_e event, struct misdn_bchannel *bc, void *user_data);
void (*cb_log)(int level, int port, char *tmpl, ...);
int (*cb_clearl3_true)(void);
int (*cb_jb_empty)(struct misdn_bchannel *bc, char *buffer, int len);
};
/***** USER IFACE **********/
void misdn_lib_nt_debug_init( int flags, char *file );
int misdn_lib_init(char *portlist, struct misdn_lib_iface* iface, void *user_data);
int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event );
void misdn_lib_destroy(void);
@@ -313,8 +399,8 @@ struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel);
void manager_bchannel_activate(struct misdn_bchannel *bc);
void manager_bchannel_deactivate(struct misdn_bchannel * bc);
int manager_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len);
void manager_send_tone (struct misdn_bchannel *bc, enum tone_e tone);
int misdn_lib_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len);
void manager_ph_control(struct misdn_bchannel *bc, int c1, int c2);
@@ -322,7 +408,13 @@ void manager_ph_control(struct misdn_bchannel *bc, int c1, int c2);
int misdn_lib_port_restart(int port);
int misdn_lib_get_port_info(int port);
int misdn_lib_port_up(int port);
int misdn_lib_is_port_blocked(int port);
int misdn_lib_port_block(int port);
int misdn_lib_port_unblock(int port);
int misdn_lib_port_up(int port, int notcheck);
int misdn_lib_get_port_down(int port);
int misdn_lib_get_port_up (int port) ;
@@ -339,24 +431,26 @@ int misdn_lib_send_facility(struct misdn_bchannel *bc, enum facility_type fac, v
void manager_ec_enable(struct misdn_bchannel *bc);
void manager_ec_disable(struct misdn_bchannel *bc);
void misdn_lib_send_tone(struct misdn_bchannel *bc, enum tone_e tone);
void get_show_stack_details(int port, char *buf);
/** Ibuf interface **/
int misdn_ibuf_usedcount(void *buf);
int misdn_ibuf_freecount(void *buf);
void misdn_ibuf_memcpy_r(char *to, void *from, int len);
void misdn_ibuf_memcpy_w(void *buf, char *from, int len);
void misdn_lib_tone_generator_start(struct misdn_bchannel *bc);
void misdn_lib_tone_generator_stop(struct misdn_bchannel *bc);
/** Ibuf interface End **/
void misdn_lib_setup_bc(struct misdn_bchannel *bc);
void misdn_lib_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2);
void misdn_lib_split_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2);
void misdn_lib_echo(struct misdn_bchannel *bc, int onoff);
int misdn_lib_is_ptp(int port);
int misdn_lib_get_maxchans(int port);
void misdn_lib_reinit_nt_stack(int port);
#define PRI_TRANS_CAP_SPEECH 0x0
#define PRI_TRANS_CAP_DIGITAL 0x08
@@ -364,4 +458,11 @@ int misdn_lib_is_ptp(int port);
#define PRI_TRANS_CAP_3_1K_AUDIO 0x10
#define PRI_TRANS_CAP_7K_AUDIO 0x11
char *bc_state2str(enum bchannel_state state);
void bc_state_change(struct misdn_bchannel *bc, enum bchannel_state state);
#endif

View File

@@ -1,5 +1,5 @@
#ifndef ISDN_LIB_INTERN
#define ISDN_LIB_INTER
#define ISDN_LIB_INTERN
#include <mISDNuser/mISDNlib.h>
@@ -11,17 +11,13 @@
#include "isdn_lib.h"
#define QI_ELEMENT(a) a.off
#ifndef mISDNUSER_HEAD_SIZE
#ifdef MISDNUSER_JOLLY
#define mISDNUSER_HEAD_SIZE (sizeof(mISDNuser_head_t))
#else
#define mISDNUSER_HEAD_SIZE (sizeof(mISDN_head_t))
#endif
/*#define mISDNUSER_HEAD_SIZE (sizeof(mISDN_head_t))*/
#endif
@@ -37,8 +33,6 @@ struct isdn_msg {
void (*msg_parser)(struct isdn_msg *msgs, msg_t *msg, struct misdn_bchannel *bc, int nt);
msg_t *(*msg_builder)(struct isdn_msg *msgs, struct misdn_bchannel *bc, int nt);
void (*msg_printer)(struct isdn_msg *msgs);
char *info;
} ;
@@ -60,9 +54,16 @@ struct misdn_stack {
int b_stids[MAX_BCHANS + 1];
int ptp;
int l2upcnt;
int l2_id;
int lower_id;
int upper_id;
int blocked;
int l2link;
time_t l2establish;
@@ -70,7 +71,7 @@ struct misdn_stack {
int l1link;
int midev;
enum mode_e {NT_MODE, TE_MODE} mode;
int nt;
int pri;
@@ -78,6 +79,7 @@ struct misdn_stack {
int procids[0x100+1];
msg_queue_t downqueue;
msg_queue_t upqueue;
int busy;
int port;
@@ -96,4 +98,6 @@ struct misdn_stack {
struct misdn_stack* get_stack_by_bc(struct misdn_bchannel *bc);
#endif

View File

@@ -12,30 +12,57 @@
*/
#include "isdn_lib_intern.h"
#include "isdn_lib.h"
#include "ie.c"
#include "fac.h"
void set_channel(struct misdn_bchannel *bc, int channel) {
cb_log(3,bc->port,"set_channel: bc->channel:%d channel:%d\n", bc->channel, channel);
if (channel==0xff) {
/* any channel */
channel=-1;
}
/* ALERT: is that everytime true ? */
if (channel > 0 && bc->nt ) {
if (bc->channel && ( bc->channel != 0xff) ) {
cb_log(0,bc->port,"We already have a channel (%d)\n", bc->channel);
} else {
bc->channel = channel;
}
}
if (channel > 0 && !bc->nt )
bc->channel = channel;
}
void parse_proceeding (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
CALL_PROCEEDING_t *proceeding=(CALL_PROCEEDING_t*)((unsigned long)msg->data+ HEADER_LEN);
struct misdn_stack *stack=get_stack_by_bc(bc);
//struct misdn_stack *stack=get_stack_by_bc(bc);
{
int exclusive, channel;
dec_ie_channel_id(proceeding->CHANNEL_ID, (Q931_info_t *)proceeding, &exclusive, &channel, nt,bc);
set_channel(bc,channel);
if (channel==0xff) /* any channel */
channel=-1;
/* ALERT: is that everytime true ? */
if (channel > 0 && stack->mode == NT_MODE)
bc->channel = channel;
}
dec_ie_progress(proceeding->PROGRESS, (Q931_info_t *)proceeding, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
#if DEBUG
printf("Parsing PROCEEDING Msg\n");
#endif
@@ -59,9 +86,6 @@ msg_t *build_proceeding (struct isdn_msg msgs[], struct misdn_bchannel *bc, int
#endif
return msg;
}
void print_proceeding (struct isdn_msg msgs[])
{
}
void parse_alerting (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -94,9 +118,6 @@ msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt
#endif
return msg;
}
void print_alerting (struct isdn_msg msgs[])
{
}
void parse_progress (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
@@ -125,10 +146,6 @@ msg_t *build_progress (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt
#endif
return msg;
}
void print_progress (struct isdn_msg msgs[])
{
}
void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -142,87 +159,76 @@ void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc,
{
int type,plan,present, screen;
char id[32];
dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, (unsigned char *)id, sizeof(id), nt,bc);
dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, (unsigned char *)id, sizeof(id)-1, nt,bc);
bc->onumplan=type;
strcpy(bc->oad, id);
switch (present) {
case 0:
// cb_log(3, bc->stack->port, " --> Pres:0\n");
bc->pres=0; /* screened */
break;
case 1:
// cb_log(3, bc->stack->port, " --> Pres:1\n");
bc->pres=1; /* not screened */
break;
default:
// cb_log(3, bc->stack->port, " --> Pres:%d\n",present);
bc->pres=0;
}
switch (screen) {
case 0:
// cb_log(4, bc->stack->port, " --> Screen:0\n");
break;
default:
// cb_log(4, bc->stack->port, " --> Screen:%d\n",screen);
;
}
}
{
int type, plan;
char number[32];
dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *)setup, &type, &plan, (unsigned char *)number, sizeof(number), nt,bc);
dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *)setup, &type, &plan, (unsigned char *)number, sizeof(number)-1, nt,bc);
strcpy(bc->dad, number);
bc->dnumplan=type;
}
{
char keypad[32];
dec_ie_keypad(setup->KEYPAD, (Q931_info_t *)setup, (unsigned char *)keypad, sizeof(keypad), nt,bc);
dec_ie_keypad(setup->KEYPAD, (Q931_info_t *)setup, (unsigned char *)keypad, sizeof(keypad)-1, nt,bc);
strcpy(bc->keypad, keypad);
}
{
int sending_complete;
dec_ie_complete(setup->COMPLETE, (Q931_info_t *)setup, &sending_complete, nt,bc);
dec_ie_complete(setup->COMPLETE, (Q931_info_t *)setup, &bc->sending_complete, nt,bc);
}
{
int type, plan, present, screen, reason;
char id[32];
dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *)setup, &type, &plan, &present, &screen, &reason, (unsigned char *)id, sizeof(id), nt,bc);
dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *)setup, &type, &plan, &present, &screen, &reason, (unsigned char *)id, sizeof(id)-1, nt,bc);
strcpy(bc->rad, id);
bc->rnumplan=type;
// cb_log(3, bc->stack->port, " --> Redirecting number (REDIR_NR): '%s'\n", id);
}
{
int coding, capability, mode, rate, multi, user, async, urate, stopbits, dbits, parity;
dec_ie_bearer(setup->BEARER, (Q931_info_t *)setup, &coding, &capability, &mode, &rate, &multi, &user, &async, &urate, &stopbits, &dbits, &parity, nt,bc);
switch (capability) {
case -1: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
// cb_log(2, bc->stack->port, " --> cap -1 -> digital\n");
break;
case 0: bc->capability=INFO_CAPABILITY_SPEECH;
// cb_log(2, bc->stack->port, " --> cap speech\n");
break;
case 18: bc->capability=INFO_CAPABILITY_VIDEO;
break;
case 8: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
bc->user1 = user;
bc->async = async;
bc->urate = urate;
bc->rate = rate;
bc->mode = mode;
// cb_log(2, bc->stack->port, " --> cap unres Digital (user l1 %d, async %d, user rate %d\n", user, async, urate);
break;
case 9: bc->capability=INFO_CAPABILITY_DIGITAL_RESTRICTED;
// cb_log(2, bc->stack->port, " --> cap res Digital\n");
break;
default:
// cb_log(2, bc->stack->port, " --> cap Else\n");
break;
}
switch(user) {
case 2:
bc->law=INFO_CODEC_ULAW;
@@ -240,11 +246,8 @@ void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc,
{
int exclusive, channel;
dec_ie_channel_id(setup->CHANNEL_ID, (Q931_info_t *)setup, &exclusive, &channel, nt,bc);
if (channel==0xff) /* any channel */
channel=-1;
if (channel > 0)
bc->channel = channel;
set_channel(bc,channel);
}
dec_ie_progress(setup->PROGRESS, (Q931_info_t *)setup, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
@@ -260,12 +263,12 @@ msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
setup=(SETUP_t*)((msg->data+HEADER_LEN));
// cb_log(2, bc->stack->port, " --> oad %s dad %s channel %d\n",bc->oad, bc->dad,bc->channel);
if (bc->channel == 0 || bc->channel == ANY_CHANNEL || bc->channel==-1)
enc_ie_channel_id(&setup->CHANNEL_ID, msg, 0, bc->channel, nt,bc);
else
else
enc_ie_channel_id(&setup->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
{
int type=bc->onumplan,plan=1,present=bc->pres,screen=bc->screen;
enc_ie_calling_pn(&setup->CALLING_PN, msg, type, plan, present,
@@ -276,6 +279,13 @@ msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
if (bc->dad[0])
enc_ie_called_pn(&setup->CALLED_PN, msg, bc->dnumplan, 1, bc->dad, nt,bc);
}
{
if (bc->rad[0])
enc_ie_redir_nr(&setup->REDIR_NR, msg, 1, 1, bc->pres, bc->screen, 0, bc->rad, nt,bc);
}
if (*bc->display) {
enc_ie_display(&setup->DISPLAY, msg, bc->display, nt,bc);
@@ -299,6 +309,8 @@ msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
break;
case INFO_CAPABILITY_DIGITAL_UNRESTRICTED: capability = 8;
user=-1;
mode=bc->mode;
rate=bc->rate;
break;
case INFO_CAPABILITY_DIGITAL_RESTRICTED: capability = 9;
user=-1;
@@ -318,19 +330,23 @@ msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
return msg;
}
void print_setup (struct isdn_msg msgs[])
{
}
void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
CONNECT_t *connect=(CONNECT_t*)((unsigned long)(msg->data+HEADER_LEN));
int plan,pres,screen;
bc->ces = connect->ces;
bc->ces = connect->ces;
dec_ie_progress(connect->PROGRESS, (Q931_info_t *)connect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
dec_ie_connected_pn(connect->CONNECT_PN,(Q931_info_t *)connect, &bc->cpnnumplan, &plan, &pres, &screen, bc->cad, 31, nt, bc);
/*
cb_log(1,bc->port,"CONNETED PN: %s cpn_dialplan:%d\n", connected_pn, type);
*/
#if DEBUG
printf("Parsing CONNECT Msg\n");
@@ -341,7 +357,9 @@ msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
CONNECT_t *connect;
msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | REQUEST, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_t) ,nt);
cb_log(6,bc->port,"BUILD_CONNECT: bc:%p bc->l3id:%d, nt:%d\n",bc,bc->l3_id,nt);
connect=(CONNECT_t*)((msg->data+HEADER_LEN));
if (nt) {
@@ -351,8 +369,8 @@ msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
}
{
int type=0, plan=1, present=2, screen=0;
enc_ie_connected_pn(&connect->CONNECT_PN, msg, type,plan, present, screen, (unsigned char*) bc->dad , nt , bc);
int type=bc->cpnnumplan, plan=1, present=2, screen=0;
enc_ie_connected_pn(&connect->CONNECT_PN, msg, type,plan, present, screen, (unsigned char*) bc->cad, nt , bc);
}
#if DEBUG
@@ -360,10 +378,6 @@ msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
#endif
return msg;
}
void print_connect (struct isdn_msg msgs[])
{
}
void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -374,11 +388,8 @@ void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_b
int exclusive, channel;
dec_ie_channel_id(setup_acknowledge->CHANNEL_ID, (Q931_info_t *)setup_acknowledge, &exclusive, &channel, nt,bc);
if (channel==0xff) /* any channel */
channel=-1;
if (channel > 0)
bc->channel = channel;
set_channel(bc, channel);
}
dec_ie_progress(setup_acknowledge->PROGRESS, (Q931_info_t *)setup_acknowledge, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
@@ -407,10 +418,6 @@ msg_t *build_setup_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *b
return msg;
}
void print_setup_acknowledge (struct isdn_msg msgs[])
{
}
void parse_connect_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
#if DEBUG
@@ -434,10 +441,6 @@ msg_t *build_connect_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel
#endif
return msg;
}
void print_connect_acknowledge (struct isdn_msg msgs[])
{
}
void parse_user_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -460,10 +463,6 @@ msg_t *build_user_information (struct isdn_msg msgs[], struct misdn_bchannel *bc
#endif
return msg;
}
void print_user_information (struct isdn_msg msgs[])
{
}
void parse_suspend_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -486,10 +485,6 @@ msg_t *build_suspend_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc,
#endif
return msg;
}
void print_suspend_reject (struct isdn_msg msgs[])
{
}
void parse_resume_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -512,10 +507,6 @@ msg_t *build_resume_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, i
#endif
return msg;
}
void print_resume_reject (struct isdn_msg msgs[])
{
}
void parse_hold (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -538,10 +529,6 @@ msg_t *build_hold (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
#endif
return msg;
}
void print_hold (struct isdn_msg msgs[])
{
}
void parse_suspend (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -564,10 +551,6 @@ msg_t *build_suspend (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
#endif
return msg;
}
void print_suspend (struct isdn_msg msgs[])
{
}
void parse_resume (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -590,10 +573,6 @@ msg_t *build_resume (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
#endif
return msg;
}
void print_resume (struct isdn_msg msgs[])
{
}
void parse_hold_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -616,10 +595,6 @@ msg_t *build_hold_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc
#endif
return msg;
}
void print_hold_acknowledge (struct isdn_msg msgs[])
{
}
void parse_suspend_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -642,10 +617,6 @@ msg_t *build_suspend_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel
#endif
return msg;
}
void print_suspend_acknowledge (struct isdn_msg msgs[])
{
}
void parse_resume_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -668,10 +639,6 @@ msg_t *build_resume_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *
#endif
return msg;
}
void print_resume_acknowledge (struct isdn_msg msgs[])
{
}
void parse_hold_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -694,10 +661,6 @@ msg_t *build_hold_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int
#endif
return msg;
}
void print_hold_reject (struct isdn_msg msgs[])
{
}
void parse_retrieve (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -720,10 +683,6 @@ msg_t *build_retrieve (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt
#endif
return msg;
}
void print_retrieve (struct isdn_msg msgs[])
{
}
void parse_retrieve_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -747,10 +706,6 @@ msg_t *build_retrieve_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel
#endif
return msg;
}
void print_retrieve_acknowledge (struct isdn_msg msgs[])
{
}
void parse_retrieve_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -773,10 +728,6 @@ msg_t *build_retrieve_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc,
#endif
return msg;
}
void print_retrieve_reject (struct isdn_msg msgs[])
{
}
void parse_disconnect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -809,10 +760,6 @@ msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int
#endif
return msg;
}
void print_disconnect (struct isdn_msg msgs[])
{
}
void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -827,10 +774,10 @@ void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *b
{
int exclusive, channel;
dec_ie_channel_id(restart->CHANNEL_ID, (Q931_info_t *)restart, &exclusive, &channel, nt,bc);
dec_ie_channel_id(restart->CHANNEL_ID, (Q931_info_t *)restart, &exclusive, &bc->restart_channel, nt,bc);
if (channel==0xff) /* any channel */
channel=-1;
cb_log(0, stack->port, "CC_RESTART Request on channel:%d on port:%d\n",stack->port);
cb_log(3, stack->port, "CC_RESTART Request on channel:%d on this port.\n");
}
@@ -848,10 +795,6 @@ msg_t *build_restart (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
#endif
return msg;
}
void print_restart (struct isdn_msg msgs[])
{
}
void parse_release (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -874,18 +817,14 @@ msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
release=(RELEASE_t*)((msg->data+HEADER_LEN));
enc_ie_cause(&release->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
if (bc->out_cause>= 0)
enc_ie_cause(&release->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
#if DEBUG
printf("Building RELEASE Msg\n");
#endif
return msg;
}
void print_release (struct isdn_msg msgs[])
{
}
void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -895,35 +834,30 @@ void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bc
iframe_t *frm = (iframe_t*) msg->data;
struct misdn_stack *stack=get_stack_by_bc(bc);
#ifdef MISDNUSER_JOLLY
mISDNuser_head_t *hh;
hh=(mISDNuser_head_t*)msg->data;
#else
mISDN_head_t *hh;
hh=(mISDN_head_t*)msg->data;
#endif
/*hh=(mISDN_head_t*)msg->data;
mISDN_head_t *hh;*/
if (nt) {
if (hh->prim == (CC_RELEASE_COMPLETE|CONFIRM)) {
cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [NT] port:%d\n",stack->port);
cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [NT] \n");
return;
}
} else {
if (frm->prim == (CC_RELEASE_COMPLETE|CONFIRM)) {
cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [TE] port:%d\n",stack->port);
cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [TE] \n");
return;
}
}
dec_ie_cause(release_complete->CAUSE, (Q931_info_t *)(release_complete), &location, &bc->cause, nt,bc);
#if DEBUG
printf("Parsing RELEASE_COMPLETE Msg\n");
#endif
}
msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
{
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -939,31 +873,26 @@ msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc
#endif
return msg;
}
void print_release_complete (struct isdn_msg msgs[])
{
}
void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
//#define FACILITY_DECODE
#ifdef FACILITY_DECODE
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
FACILITY_t *facility=(FACILITY_t*)((unsigned long)(msg->data+HEADER_LEN));
Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
#if DEBUG
printf("Parsing FACILITY Msg\n");
#endif
{
char fac[128];
int facility_len;
dec_ie_facility(facility->FACILITY, qi, fac, &facility_len, nt, bc);
fac_dec(facility->FACILITY, qi, &bc->fac_type, &bc->fac, bc);
}
#endif
}
msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
{
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -977,17 +906,9 @@ msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt
printf("Sending %s as Display\n", bc->display);
enc_ie_display(&facility->DISPLAY, msg, bc->display, nt,bc);
}
switch ( bc->facility ) {
case FACILITY_CALLDEFLECT:
enc_facility_calldeflect(&facility->FACILITY, msg, bc->facility_calldeflect_nr, nt, bc);
break;
case FACILITY_NONE:
break;
}
fac_enc(&facility->FACILITY, msg, bc->out_fac_type, bc->out_fac, bc);
}
@@ -996,19 +917,14 @@ msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt
#endif
return msg;
}
void print_facility (struct isdn_msg msgs[])
{
}
void parse_notify (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
#if DEBUG
printf("Parsing NOTIFY Msg\n");
#endif
}
msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
{
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -1022,19 +938,14 @@ msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
#endif
return msg;
}
void print_notify (struct isdn_msg msgs[])
{
}
void parse_status_enquiry (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
#if DEBUG
printf("Parsing STATUS_ENQUIRY Msg\n");
#endif
}
msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
{
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -1048,32 +959,25 @@ msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchannel *bc,
#endif
return msg;
}
void print_status_enquiry (struct isdn_msg msgs[])
{
}
void parse_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
INFORMATION_t *information=(INFORMATION_t*)((unsigned long)(msg->data+HEADER_LEN));
{
int type, plan;
char number[32];
char keypad[32];
dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *)information, &type, &plan, (unsigned char *)number, sizeof(number), nt,bc);
dec_ie_keypad(information->KEYPAD, (Q931_info_t *)information, (unsigned char *)keypad, sizeof(keypad), nt,bc);
dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *)information, &type, &plan, (unsigned char *)number, sizeof(number)-1, nt, bc);
dec_ie_keypad(information->KEYPAD, (Q931_info_t *)information, (unsigned char *)keypad, sizeof(keypad)-1, nt, bc);
strcpy(bc->info_dad, number);
strcpy(bc->keypad,keypad);
}
#if DEBUG
printf("Parsing INFORMATION Msg\n");
#endif
}
msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
{
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -1098,10 +1002,6 @@ msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int
#endif
return msg;
}
void print_information (struct isdn_msg msgs[])
{
}
void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
@@ -1115,9 +1015,8 @@ void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc
#if DEBUG
printf("Parsing STATUS Msg\n");
#endif
}
msg_t *build_status (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
{
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -1131,19 +1030,14 @@ msg_t *build_status (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
#endif
return msg;
}
void print_status (struct isdn_msg msgs[])
{
}
void parse_timeout (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
#if DEBUG
printf("Parsing STATUS Msg\n");
#endif
#endif
}
msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
{
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@@ -1157,9 +1051,6 @@ msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
#endif
return msg;
}
void print_timeout (struct isdn_msg msgs[])
{
}
/************************************/
@@ -1171,96 +1062,96 @@ void print_timeout (struct isdn_msg msgs[])
struct isdn_msg msgs_g[] = {
{CC_PROCEEDING,L3,EVENT_PROCEEDING,
parse_proceeding,build_proceeding,print_proceeding,
parse_proceeding,build_proceeding,
"PROCEEDING"},
{CC_ALERTING,L3,EVENT_ALERTING,
parse_alerting,build_alerting,print_alerting,
parse_alerting,build_alerting,
"ALERTING"},
{CC_PROGRESS,L3,EVENT_PROGRESS,
parse_progress,build_progress,print_progress,
parse_progress,build_progress,
"PROGRESS"},
{CC_SETUP,L3,EVENT_SETUP,
parse_setup,build_setup,print_setup,
parse_setup,build_setup,
"SETUP"},
{CC_CONNECT,L3,EVENT_CONNECT,
parse_connect,build_connect,print_connect,
parse_connect,build_connect,
"CONNECT"},
{CC_SETUP_ACKNOWLEDGE,L3,EVENT_SETUP_ACKNOWLEDGE,
parse_setup_acknowledge,build_setup_acknowledge,print_setup_acknowledge,
parse_setup_acknowledge,build_setup_acknowledge,
"SETUP_ACKNOWLEDGE"},
{CC_CONNECT_ACKNOWLEDGE ,L3,EVENT_CONNECT_ACKNOWLEDGE ,
parse_connect_acknowledge ,build_connect_acknowledge ,print_connect_acknowledge ,
parse_connect_acknowledge ,build_connect_acknowledge,
"CONNECT_ACKNOWLEDGE "},
{CC_USER_INFORMATION,L3,EVENT_USER_INFORMATION,
parse_user_information,build_user_information,print_user_information,
parse_user_information,build_user_information,
"USER_INFORMATION"},
{CC_SUSPEND_REJECT,L3,EVENT_SUSPEND_REJECT,
parse_suspend_reject,build_suspend_reject,print_suspend_reject,
parse_suspend_reject,build_suspend_reject,
"SUSPEND_REJECT"},
{CC_RESUME_REJECT,L3,EVENT_RESUME_REJECT,
parse_resume_reject,build_resume_reject,print_resume_reject,
parse_resume_reject,build_resume_reject,
"RESUME_REJECT"},
{CC_HOLD,L3,EVENT_HOLD,
parse_hold,build_hold,print_hold,
parse_hold,build_hold,
"HOLD"},
{CC_SUSPEND,L3,EVENT_SUSPEND,
parse_suspend,build_suspend,print_suspend,
parse_suspend,build_suspend,
"SUSPEND"},
{CC_RESUME,L3,EVENT_RESUME,
parse_resume,build_resume,print_resume,
parse_resume,build_resume,
"RESUME"},
{CC_HOLD_ACKNOWLEDGE,L3,EVENT_HOLD_ACKNOWLEDGE,
parse_hold_acknowledge,build_hold_acknowledge,print_hold_acknowledge,
parse_hold_acknowledge,build_hold_acknowledge,
"HOLD_ACKNOWLEDGE"},
{CC_SUSPEND_ACKNOWLEDGE,L3,EVENT_SUSPEND_ACKNOWLEDGE,
parse_suspend_acknowledge,build_suspend_acknowledge,print_suspend_acknowledge,
parse_suspend_acknowledge,build_suspend_acknowledge,
"SUSPEND_ACKNOWLEDGE"},
{CC_RESUME_ACKNOWLEDGE,L3,EVENT_RESUME_ACKNOWLEDGE,
parse_resume_acknowledge,build_resume_acknowledge,print_resume_acknowledge,
parse_resume_acknowledge,build_resume_acknowledge,
"RESUME_ACKNOWLEDGE"},
{CC_HOLD_REJECT,L3,EVENT_HOLD_REJECT,
parse_hold_reject,build_hold_reject,print_hold_reject,
parse_hold_reject,build_hold_reject,
"HOLD_REJECT"},
{CC_RETRIEVE,L3,EVENT_RETRIEVE,
parse_retrieve,build_retrieve,print_retrieve,
parse_retrieve,build_retrieve,
"RETRIEVE"},
{CC_RETRIEVE_ACKNOWLEDGE,L3,EVENT_RETRIEVE_ACKNOWLEDGE,
parse_retrieve_acknowledge,build_retrieve_acknowledge,print_retrieve_acknowledge,
parse_retrieve_acknowledge,build_retrieve_acknowledge,
"RETRIEVE_ACKNOWLEDGE"},
{CC_RETRIEVE_REJECT,L3,EVENT_RETRIEVE_REJECT,
parse_retrieve_reject,build_retrieve_reject,print_retrieve_reject,
parse_retrieve_reject,build_retrieve_reject,
"RETRIEVE_REJECT"},
{CC_DISCONNECT,L3,EVENT_DISCONNECT,
parse_disconnect,build_disconnect,print_disconnect,
parse_disconnect,build_disconnect,
"DISCONNECT"},
{CC_RESTART,L3,EVENT_RESTART,
parse_restart,build_restart,print_restart,
parse_restart,build_restart,
"RESTART"},
{CC_RELEASE,L3,EVENT_RELEASE,
parse_release,build_release,print_release,
parse_release,build_release,
"RELEASE"},
{CC_RELEASE_COMPLETE,L3,EVENT_RELEASE_COMPLETE,
parse_release_complete,build_release_complete,print_release_complete,
parse_release_complete,build_release_complete,
"RELEASE_COMPLETE"},
{CC_FACILITY,L3,EVENT_FACILITY,
parse_facility,build_facility,print_facility,
parse_facility,build_facility,
"FACILITY"},
{CC_NOTIFY,L3,EVENT_NOTIFY,
parse_notify,build_notify,print_notify,
parse_notify,build_notify,
"NOTIFY"},
{CC_STATUS_ENQUIRY,L3,EVENT_STATUS_ENQUIRY,
parse_status_enquiry,build_status_enquiry,print_status_enquiry,
parse_status_enquiry,build_status_enquiry,
"STATUS_ENQUIRY"},
{CC_INFORMATION,L3,EVENT_INFORMATION,
parse_information,build_information,print_information,
parse_information,build_information,
"INFORMATION"},
{CC_STATUS,L3,EVENT_STATUS,
parse_status,build_status,print_status,
parse_status,build_status,
"STATUS"},
{CC_TIMEOUT,L3,EVENT_TIMEOUT,
parse_timeout,build_timeout,print_timeout,
parse_timeout,build_timeout,
"TIMEOUT"},
{0,0,0,NULL,NULL,NULL,NULL}
{0,0,0,NULL,NULL,NULL}
};
#define msgs_max (sizeof(msgs_g)/sizeof(struct isdn_msg))
@@ -1271,15 +1162,12 @@ int isdn_msg_get_index(struct isdn_msg msgs[], msg_t *msg, int nt)
int i;
if (nt){
#ifdef MISDNUSER_JOLLY
mISDNuser_head_t *hh = (mISDNuser_head_t*)msg->data;
#else
mISDN_head_t *hh = (mISDN_head_t*)msg->data;
#endif
for (i=0; i< msgs_max -1; i++)
for (i=0; i< msgs_max -1; i++) {
if ( (hh->prim&COMMAND_MASK)==(msgs[i].misdn_msg&COMMAND_MASK)) return i;
}
} else {
iframe_t *frm = (iframe_t*)msg->data;
@@ -1296,7 +1184,7 @@ int isdn_msg_get_index_by_event(struct isdn_msg msgs[], enum event_e event, int
for (i=0; i< msgs_max; i++)
if ( event == msgs[i].event) return i;
cb_log(4,0, "get_index: EVENT NOT FOUND!!\n");
cb_log(10,0, "get_index: event not found!\n");
return -1;
}
@@ -1320,7 +1208,10 @@ char EVENT_CLEAN_INFO[] = "CLEAN_UP";
char EVENT_DTMF_TONE_INFO[] = "DTMF_TONE";
char EVENT_NEW_L3ID_INFO[] = "NEW_L3ID";
char EVENT_NEW_BC_INFO[] = "NEW_BC";
char EVENT_PORT_ALARM_INFO[] = "ALARM";
char EVENT_BCHAN_DATA_INFO[] = "BCHAN_DATA";
char EVENT_BCHAN_ACTIVATED_INFO[] = "BCHAN_ACTIVATED";
char EVENT_TONE_GENERATE_INFO[] = "TONE_GENERATE";
char * isdn_get_info(struct isdn_msg msgs[], enum event_e event, int nt)
{
@@ -1333,6 +1224,9 @@ char * isdn_get_info(struct isdn_msg msgs[], enum event_e event, int nt)
if (event == EVENT_NEW_L3ID) return EVENT_NEW_L3ID_INFO;
if (event == EVENT_NEW_BC) return EVENT_NEW_BC_INFO;
if (event == EVENT_BCHAN_DATA) return EVENT_BCHAN_DATA_INFO;
if (event == EVENT_BCHAN_ACTIVATED) return EVENT_BCHAN_ACTIVATED_INFO;
if (event == EVENT_TONE_GENERATE) return EVENT_TONE_GENERATE_INFO;
if (event == EVENT_PORT_ALARM) return EVENT_PORT_ALARM_INFO;
return NULL;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,197 +0,0 @@
#include "isdn_lib.h"
/*
* global function to show all available isdn ports
*/
void isdn_port_info(void)
{
int err;
int i, ii, p;
int useable, nt, pri;
unsigned char buff[1025];
iframe_t *frm = (iframe_t *)buff;
stack_info_t *stinf;
int device;
/* open mISDN */
if ((device = mISDN_open()) < 0)
{
fprintf(stderr, "mISDN_open() failed: ret=%d errno=%d (%s) Check for mISDN modules and device.\n", device, errno, strerror(errno));
exit(-1);
}
/* get number of stacks */
i = 1;
ii = mISDN_get_stack_count(device);
printf("\n");
if (ii <= 0)
{
printf("Found no card. Please be sure to load card drivers.\n");
}
/* loop the number of cards and get their info */
while(i <= ii)
{
err = mISDN_get_stack_info(device, i, buff, sizeof(buff));
if (err <= 0)
{
fprintf(stderr, "mISDN_get_stack_info() failed: port=%d err=%d\n", i, err);
break;
}
stinf = (stack_info_t *)&frm->data.p;
nt = pri = 0;
useable = 1;
/* output the port info */
printf("Port %2d: ", i);
switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
{
case ISDN_PID_L0_TE_S0:
printf("TE-mode BRI S/T interface line (for phone lines)");
#if 0
if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_S0_HFC & ISDN_PID_FEATURE_MASK)
printf(" HFC multiport card");
#endif
break;
case ISDN_PID_L0_NT_S0:
nt = 1;
printf("NT-mode BRI S/T interface port (for phones)");
#if 0
if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_S0_HFC & ISDN_PID_FEATURE_MASK)
printf(" HFC multiport card");
#endif
break;
case ISDN_PID_L0_TE_U:
printf("TE-mode BRI U interface line");
break;
case ISDN_PID_L0_NT_U:
nt = 1;
printf("NT-mode BRI U interface port");
break;
case ISDN_PID_L0_TE_UP2:
printf("TE-mode BRI Up2 interface line");
break;
case ISDN_PID_L0_NT_UP2:
nt = 1;
printf("NT-mode BRI Up2 interface port");
break;
case ISDN_PID_L0_TE_E1:
pri = 1;
printf("TE-mode PRI E1 interface line (for phone lines)");
#if 0
if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_E1_HFC & ISDN_PID_FEATURE_MASK)
printf(" HFC-E1 card");
#endif
break;
case ISDN_PID_L0_NT_E1:
nt = 1;
pri = 1;
printf("NT-mode PRI E1 interface port (for phones)");
#if 0
if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_E1_HFC & ISDN_PID_FEATURE_MASK)
printf(" HFC-E1 card");
#endif
break;
default:
useable = 0;
printf("unknown type 0x%08x",stinf->pid.protocol[0]);
}
printf("\n");
if (nt)
{
if (stinf->pid.protocol[1] == 0)
{
useable = 0;
printf(" -> Missing layer 1 NT-mode protocol.\n");
}
p = 2;
while(p <= MAX_LAYER_NR) {
if (stinf->pid.protocol[p])
{
useable = 0;
printf(" -> Layer %d protocol 0x%08x is detected, but not allowed for NT lib.\n", p, stinf->pid.protocol[p]);
}
p++;
}
if (useable)
{
if (pri)
printf(" -> Interface is Point-To-Point (PRI).\n");
else
printf(" -> Interface can be Poin-To-Point/Multipoint.\n");
}
} else
{
if (stinf->pid.protocol[1] == 0)
{
useable = 0;
printf(" -> Missing layer 1 protocol.\n");
}
if (stinf->pid.protocol[2] == 0)
{
useable = 0;
printf(" -> Missing layer 2 protocol.\n");
}
if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP)
{
printf(" -> Interface is Poin-To-Point.\n");
}
if (stinf->pid.protocol[3] == 0)
{
useable = 0;
printf(" -> Missing layer 3 protocol.\n");
} else
{
printf(" -> Protocol: ");
switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
{
case ISDN_PID_L3_DSS1USER:
printf("DSS1 (Euro ISDN)");
break;
default:
useable = 0;
printf("unknown protocol 0x%08x",stinf->pid.protocol[3]);
}
printf("\n");
}
p = 4;
while(p <= MAX_LAYER_NR) {
if (stinf->pid.protocol[p])
{
useable = 0;
printf(" -> Layer %d protocol 0x%08x is detected, but not allowed for TE lib.\n", p, stinf->pid.protocol[p]);
}
p++;
}
printf(" -> childcnt: %d\n",stinf->childcnt);
}
if (!useable)
printf(" * Port NOT useable for PBX\n");
printf("--------\n");
i++;
}
printf("\n");
/* close mISDN */
if ((err = mISDN_close(device)))
{
fprintf(stderr, "mISDN_close() failed: err=%d '%s'\n", err, strerror(err));
exit(-1);
}
}
int main()
{
isdn_port_info();
return 0;
}

784
channels/misdn_config.c Normal file
View File

@@ -0,0 +1,784 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2005, Christian Richter
*
* Christian Richter <crich@beronet.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*
*/
/*!
* \file
*
* \brief chan_misdn configuration management
* \author Christian Richter <crich@beronet.com>
*
* \ingroup channel_drivers
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "chan_misdn_config.h"
#include <asterisk/config.h>
#include <asterisk/channel.h>
#include <asterisk/logger.h>
#include <asterisk/lock.h>
#include <asterisk/pbx.h>
#include <asterisk/strings.h>
#include <asterisk/utils.h>
#define AST_LOAD_CFG ast_config_load
#define AST_DESTROY_CFG ast_config_destroy
#define NO_DEFAULT "<>"
#define NONE 0
#define GEN_CFG 1
#define PORT_CFG 2
#define NUM_GEN_ELEMENTS (sizeof(gen_spec) / sizeof(struct misdn_cfg_spec))
#define NUM_PORT_ELEMENTS (sizeof(port_spec) / sizeof(struct misdn_cfg_spec))
enum misdn_cfg_type {
MISDN_CTYPE_STR,
MISDN_CTYPE_INT,
MISDN_CTYPE_BOOL,
MISDN_CTYPE_BOOLINT,
MISDN_CTYPE_MSNLIST,
MISDN_CTYPE_ASTGROUP
};
struct msn_list {
char *msn;
struct msn_list *next;
};
union misdn_cfg_pt {
char *str;
int *num;
struct msn_list *ml;
ast_group_t *grp;
void *any;
};
struct misdn_cfg_spec {
char name[BUFFERSIZE];
enum misdn_cfg_elements elem;
enum misdn_cfg_type type;
char def[BUFFERSIZE];
int boolint_def;
};
static const struct misdn_cfg_spec port_spec[] = {
{ "name", MISDN_CFG_GROUPNAME, MISDN_CTYPE_STR, "default", NONE },
{ "allowed_bearers", MISDN_CFG_ALLOWED_BEARERS, MISDN_CTYPE_STR, "all", NONE },
{ "rxgain", MISDN_CFG_RXGAIN, MISDN_CTYPE_INT, "0", NONE },
{ "txgain", MISDN_CFG_TXGAIN, MISDN_CTYPE_INT, "0", NONE },
{ "te_choose_channel", MISDN_CFG_TE_CHOOSE_CHANNEL, MISDN_CTYPE_BOOL, "no", NONE },
{ "far_alerting", MISDN_CFG_FAR_ALERTING, MISDN_CTYPE_BOOL, "no", NONE },
{ "pmp_l1_check", MISDN_CFG_PMP_L1_CHECK, MISDN_CTYPE_BOOL, "yes", NONE },
{ "block_on_alarm", MISDN_CFG_ALARM_BLOCK, MISDN_CTYPE_BOOL, "yes", NONE },
{ "hdlc", MISDN_CFG_HDLC, MISDN_CTYPE_BOOL, "no", NONE },
{ "context", MISDN_CFG_CONTEXT, MISDN_CTYPE_STR, "default", NONE },
{ "language", MISDN_CFG_LANGUAGE, MISDN_CTYPE_STR, "en", NONE },
{ "musicclass", MISDN_CFG_MUSICCLASS, MISDN_CTYPE_STR, "default", NONE },
{ "callerid", MISDN_CFG_CALLERID, MISDN_CTYPE_STR, "", NONE },
{ "method", MISDN_CFG_METHOD, MISDN_CTYPE_STR, "standard", NONE },
{ "dialplan", MISDN_CFG_DIALPLAN, MISDN_CTYPE_INT, "0", NONE },
{ "localdialplan", MISDN_CFG_LOCALDIALPLAN, MISDN_CTYPE_INT, "0", NONE },
{ "cpndialplan", MISDN_CFG_CPNDIALPLAN, MISDN_CTYPE_INT, "0", NONE },
{ "nationalprefix", MISDN_CFG_NATPREFIX, MISDN_CTYPE_STR, "0", NONE },
{ "internationalprefix", MISDN_CFG_INTERNATPREFIX, MISDN_CTYPE_STR, "00", NONE },
{ "presentation", MISDN_CFG_PRES, MISDN_CTYPE_INT, "-1", NONE },
{ "screen", MISDN_CFG_SCREEN, MISDN_CTYPE_INT, "-1", NONE },
{ "always_immediate", MISDN_CFG_ALWAYS_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE },
{ "nodialtone", MISDN_CFG_NODIALTONE, MISDN_CTYPE_BOOL, "no", NONE },
{ "immediate", MISDN_CFG_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE },
{ "senddtmf", MISDN_CFG_SENDDTMF, MISDN_CTYPE_BOOL, "no", NONE },
{ "hold_allowed", MISDN_CFG_HOLD_ALLOWED, MISDN_CTYPE_BOOL, "no", NONE },
{ "early_bconnect", MISDN_CFG_EARLY_BCONNECT, MISDN_CTYPE_BOOL, "yes", NONE },
{ "incoming_early_audio", MISDN_CFG_INCOMING_EARLY_AUDIO, MISDN_CTYPE_BOOL, "no", NONE },
{ "echocancel", MISDN_CFG_ECHOCANCEL, MISDN_CTYPE_BOOLINT, "0", 128 },
{ "need_more_infos", MISDN_CFG_NEED_MORE_INFOS, MISDN_CTYPE_BOOL, "0", NONE },
{ "jitterbuffer", MISDN_CFG_JITTERBUFFER, MISDN_CTYPE_INT, "4000", NONE },
{ "jitterbuffer_upper_threshold", MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, MISDN_CTYPE_INT, "0", NONE },
{ "callgroup", MISDN_CFG_CALLGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE },
{ "pickupgroup", MISDN_CFG_PICKUPGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE },
{ "msns", MISDN_CFG_MSNS, MISDN_CTYPE_MSNLIST, NO_DEFAULT, NONE }
};
static const struct misdn_cfg_spec gen_spec[] = {
{ "debug", MISDN_GEN_DEBUG, MISDN_CTYPE_INT, "0", NONE },
{ "misdn_init", MISDN_GEN_MISDN_INIT, MISDN_CTYPE_STR, "/etc/misdn-init.conf", NONE },
{ "tracefile", MISDN_GEN_TRACEFILE, MISDN_CTYPE_STR, "/var/log/asterisk/misdn.log", NONE },
{ "bridging", MISDN_GEN_BRIDGING, MISDN_CTYPE_BOOL, "yes", NONE },
{ "stop_tone_after_first_digit", MISDN_GEN_STOP_TONE, MISDN_CTYPE_BOOL, "yes", NONE },
{ "append_digits2exten", MISDN_GEN_APPEND_DIGITS2EXTEN, MISDN_CTYPE_BOOL, "yes", NONE },
{ "dynamic_crypt", MISDN_GEN_DYNAMIC_CRYPT, MISDN_CTYPE_BOOL, "no", NONE },
{ "crypt_prefix", MISDN_GEN_CRYPT_PREFIX, MISDN_CTYPE_STR, NO_DEFAULT, NONE },
{ "crypt_keys", MISDN_GEN_CRYPT_KEYS, MISDN_CTYPE_STR, NO_DEFAULT, NONE },
{ "ntdebugflags", MISDN_GEN_NTDEBUGFLAGS, MISDN_CTYPE_INT, "0", NONE },
{ "ntdebugfile", MISDN_GEN_NTDEBUGFILE, MISDN_CTYPE_STR, "/var/log/misdn-nt.log", NONE }
};
/* array of port configs, default is at position 0. */
static union misdn_cfg_pt **port_cfg;
/* max number of available ports, is set on init */
static int max_ports;
/* general config */
static union misdn_cfg_pt *general_cfg;
/* storing the ptp flag separated to save memory */
static int *ptp;
/* maps enum config elements to array positions */
static int *map;
static ast_mutex_t config_mutex;
#define CLI_ERROR(name, value, section) ({ \
ast_log(LOG_WARNING, "misdn.conf: \"%s=%s\" (section: %s) invalid or out of range. " \
"Please edit your misdn.conf and then do a \"misdn reload\".\n", name, value, section); \
})
static void _enum_array_map (void)
{
int i, j;
for (i = MISDN_CFG_FIRST + 1; i < MISDN_CFG_LAST; ++i) {
if (i == MISDN_CFG_PTP)
continue;
for (j = 0; j < NUM_PORT_ELEMENTS; ++j) {
if (port_spec[j].elem == i) {
map[i] = j;
break;
}
}
}
for (i = MISDN_GEN_FIRST + 1; i < MISDN_GEN_LAST; ++i) {
for (j = 0; j < NUM_GEN_ELEMENTS; ++j) {
if (gen_spec[j].elem == i) {
map[i] = j;
break;
}
}
}
}
static int get_cfg_position (char *name, int type)
{
int i;
switch (type) {
case PORT_CFG:
for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
if (!strcasecmp(name, port_spec[i].name))
return i;
}
break;
case GEN_CFG:
for (i = 0; i < NUM_GEN_ELEMENTS; ++i) {
if (!strcasecmp(name, gen_spec[i].name))
return i;
}
}
return -1;
}
static inline void misdn_cfg_lock (void)
{
ast_mutex_lock(&config_mutex);
}
static inline void misdn_cfg_unlock (void)
{
ast_mutex_unlock(&config_mutex);
}
static void _free_msn_list (struct msn_list* iter)
{
if (iter->next)
_free_msn_list(iter->next);
if (iter->msn)
free(iter->msn);
free(iter);
}
static void _free_port_cfg (void)
{
int i, j;
int gn = map[MISDN_CFG_GROUPNAME];
union misdn_cfg_pt* free_list[max_ports + 2];
memset(free_list, 0, sizeof(free_list));
free_list[0] = port_cfg[0];
for (i = 1; i <= max_ports; ++i) {
if (port_cfg[i][gn].str) {
/* we always have a groupname in the non-default case, so this is fine */
for (j = 1; j <= max_ports; ++j) {
if (free_list[j] && free_list[j][gn].str == port_cfg[i][gn].str)
break;
else if (!free_list[j]) {
free_list[j] = port_cfg[i];
break;
}
}
}
}
for (j = 0; free_list[j]; ++j) {
for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
if (free_list[j][i].any) {
if (port_spec[i].type == MISDN_CTYPE_MSNLIST)
_free_msn_list(free_list[j][i].ml);
else
free(free_list[j][i].any);
}
}
}
}
static void _free_general_cfg (void)
{
int i;
for (i = 0; i < NUM_GEN_ELEMENTS; i++)
if (general_cfg[i].any)
free(general_cfg[i].any);
}
void misdn_cfg_get (int port, enum misdn_cfg_elements elem, void *buf, int bufsize)
{
int place;
if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) {
memset(buf, 0, bufsize);
ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Port number %d is not valid.\n", port);
return;
}
misdn_cfg_lock();
if (elem == MISDN_CFG_PTP) {
if (!memcpy(buf, &ptp[port], (bufsize > ptp[port]) ? sizeof(ptp[port]) : bufsize))
memset(buf, 0, bufsize);
} else {
if ((place = map[elem]) < 0) {
memset (buf, 0, bufsize);
ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Invalid element (%d) requested.\n", elem);
} else {
if (elem < MISDN_CFG_LAST) {
switch (port_spec[place].type) {
case MISDN_CTYPE_STR:
if (port_cfg[port][place].str) {
if (!memccpy(buf, port_cfg[port][place].str, 0, bufsize))
memset(buf, 0, 1);
} else if (port_cfg[0][place].str) {
if (!memccpy(buf, port_cfg[0][place].str, 0, bufsize))
memset(buf, 0, 1);
}
break;
default:
if (port_cfg[port][place].any)
memcpy(buf, port_cfg[port][place].any, bufsize);
else if (port_cfg[0][place].any)
memcpy(buf, port_cfg[0][place].any, bufsize);
else
memset(buf, 0, bufsize);
}
} else {
switch (gen_spec[place].type) {
case MISDN_CTYPE_STR:
if (!general_cfg[place].str || !memccpy(buf, general_cfg[place].str, 0, bufsize))
memset(buf, 0, 1);
break;
default:
if (general_cfg[place].any)
memcpy(buf, general_cfg[place].any, bufsize);
else
memset(buf, 0, bufsize);
}
}
}
}
misdn_cfg_unlock();
}
int misdn_cfg_is_msn_valid (int port, char* msn)
{
int re = 0;
struct msn_list *iter;
if (!misdn_cfg_is_port_valid(port)) {
ast_log(LOG_WARNING, "Invalid call to misdn_cfg_is_msn_valid! Port number %d is not valid.\n", port);
return 0;
}
misdn_cfg_lock();
if (port_cfg[port][map[MISDN_CFG_MSNS]].ml)
iter = port_cfg[port][map[MISDN_CFG_MSNS]].ml;
else
iter = port_cfg[0][map[MISDN_CFG_MSNS]].ml;
for (; iter; iter = iter->next)
if (*(iter->msn) == '*' || ast_extension_match(iter->msn, msn)) {
re = 1;
break;
}
misdn_cfg_unlock();
return re;
}
int misdn_cfg_is_port_valid (int port)
{
return (port >= 1 && port <= max_ports);
}
int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth)
{
int i, re = 0;
char *method = NULL;
misdn_cfg_lock();
for (i = 1; i <= max_ports; i++) {
if (port_cfg[i] && port_cfg[i][map[MISDN_CFG_GROUPNAME]].str) {
if (!strcasecmp(port_cfg[i][map[MISDN_CFG_GROUPNAME]].str, group))
method = (port_cfg[i][map[MISDN_CFG_METHOD]].str ?
port_cfg[i][map[MISDN_CFG_METHOD]].str : port_cfg[0][map[MISDN_CFG_METHOD]].str);
}
}
if (method) {
switch (meth) {
case METHOD_STANDARD: re = !strcasecmp(method, "standard");
break;
case METHOD_ROUND_ROBIN: re = !strcasecmp(method, "round_robin");
break;
}
}
misdn_cfg_unlock();
return re;
}
void misdn_cfg_get_ports_string (char *ports)
{
char tmp[16];
int l, i;
int gn = map[MISDN_CFG_GROUPNAME];
*ports = 0;
misdn_cfg_lock();
for (i = 1; i <= max_ports; i++) {
if (port_cfg[i][gn].str) {
if (ptp[i])
sprintf(tmp, "%dptp,", i);
else
sprintf(tmp, "%d,", i);
strcat(ports, tmp);
}
}
misdn_cfg_unlock();
if ((l = strlen(ports)))
ports[l-1] = 0;
}
void misdn_cfg_get_config_string (int port, enum misdn_cfg_elements elem, char* buf, int bufsize)
{
int place;
char tempbuf[BUFFERSIZE] = "";
struct msn_list *iter;
if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) {
*buf = 0;
ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Port number %d is not valid.\n", port);
return;
}
place = map[elem];
misdn_cfg_lock();
if (elem == MISDN_CFG_PTP) {
snprintf(buf, bufsize, " -> ptp: %s", ptp[port] ? "yes" : "no");
}
else if (elem > MISDN_CFG_FIRST && elem < MISDN_CFG_LAST) {
switch (port_spec[place].type) {
case MISDN_CTYPE_INT:
case MISDN_CTYPE_BOOLINT:
if (port_cfg[port][place].num)
snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[port][place].num);
else if (port_cfg[0][place].num)
snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[0][place].num);
else
snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
break;
case MISDN_CTYPE_BOOL:
if (port_cfg[port][place].num)
snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[port][place].num ? "yes" : "no");
else if (port_cfg[0][place].num)
snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[0][place].num ? "yes" : "no");
else
snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
break;
case MISDN_CTYPE_ASTGROUP:
if (port_cfg[port][place].grp)
snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[port][place].grp));
else if (port_cfg[0][place].grp)
snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[0][place].grp));
else
snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
break;
case MISDN_CTYPE_MSNLIST:
if (port_cfg[port][place].ml)
iter = port_cfg[port][place].ml;
else
iter = port_cfg[0][place].ml;
if (iter) {
for (; iter; iter = iter->next)
sprintf(tempbuf, "%s%s, ", tempbuf, iter->msn);
tempbuf[strlen(tempbuf)-2] = 0;
}
snprintf(buf, bufsize, " -> msns: %s", *tempbuf ? tempbuf : "none");
break;
case MISDN_CTYPE_STR:
if ( port_cfg[port][place].str) {
snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[port][place].str);
} else if (port_cfg[0][place].str) {
snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[0][place].str);
} else {
snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
}
break;
}
} else if (elem > MISDN_GEN_FIRST && elem < MISDN_GEN_LAST) {
switch (gen_spec[place].type) {
case MISDN_CTYPE_INT:
case MISDN_CTYPE_BOOLINT:
if (general_cfg[place].num)
snprintf(buf, bufsize, " -> %s: %d", gen_spec[place].name, *general_cfg[place].num);
else
snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
break;
case MISDN_CTYPE_BOOL:
if (general_cfg[place].num)
snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, *general_cfg[place].num ? "yes" : "no");
else
snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
break;
case MISDN_CTYPE_STR:
if ( general_cfg[place].str) {
snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, general_cfg[place].str);
} else {
snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
}
break;
default:
snprintf(buf, bufsize, " -> type of %s not handled yet", gen_spec[place].name);
break;
}
} else {
*buf = 0;
ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Invalid config element (%d) requested.\n", elem);
}
misdn_cfg_unlock();
}
int misdn_cfg_get_next_port (int port)
{
int p = -1;
int gn = map[MISDN_CFG_GROUPNAME];
misdn_cfg_lock();
for (port++; port <= max_ports; port++) {
if (port_cfg[port][gn].str) {
p = port;
break;
}
}
misdn_cfg_unlock();
return p;
}
int misdn_cfg_get_next_port_spin (int port)
{
int p = misdn_cfg_get_next_port(port);
return (p > 0) ? p : misdn_cfg_get_next_port(0);
}
static int _parse (union misdn_cfg_pt *dest, char *value, enum misdn_cfg_type type, int boolint_def)
{
int re = 0;
int len, tmp;
char *valtmp;
switch (type) {
case MISDN_CTYPE_STR:
if ((len = strlen(value))) {
dest->str = (char *)malloc((len + 1) * sizeof(char));
strncpy(dest->str, value, len);
dest->str[len] = 0;
} else {
dest->str = (char *)malloc( sizeof(char));
dest->str[0] = 0;
}
break;
case MISDN_CTYPE_INT:
{
char *pat;
if (strchr(value,'x'))
pat="%x";
else
pat="%d";
if (sscanf(value, pat, &tmp)) {
dest->num = (int *)malloc(sizeof(int));
memcpy(dest->num, &tmp, sizeof(int));
} else
re = -1;
}
break;
case MISDN_CTYPE_BOOL:
dest->num = (int *)malloc(sizeof(int));
*(dest->num) = (ast_true(value) ? 1 : 0);
break;
case MISDN_CTYPE_BOOLINT:
dest->num = (int *)malloc(sizeof(int));
if (sscanf(value, "%d", &tmp)) {
memcpy(dest->num, &tmp, sizeof(int));
} else {
*(dest->num) = (ast_true(value) ? boolint_def : 0);
}
break;
case MISDN_CTYPE_MSNLIST:
for (valtmp = strsep(&value, ","); valtmp; valtmp = strsep(&value, ",")) {
if ((len = strlen(valtmp))) {
struct msn_list *ml = (struct msn_list *)malloc(sizeof(struct msn_list));
ml->msn = (char *)calloc(len+1, sizeof(char));
strncpy(ml->msn, valtmp, len);
ml->next = dest->ml;
dest->ml = ml;
}
}
break;
case MISDN_CTYPE_ASTGROUP:
dest->grp = (ast_group_t *)malloc(sizeof(ast_group_t));
*(dest->grp) = ast_get_group(value);
break;
}
return re;
}
static void _build_general_config (struct ast_variable *v)
{
int pos;
for (; v; v = v->next) {
if (((pos = get_cfg_position(v->name, GEN_CFG)) < 0) ||
(_parse(&general_cfg[pos], v->value, gen_spec[pos].type, gen_spec[pos].boolint_def) < 0))
CLI_ERROR(v->name, v->value, "general");
}
}
static void _build_port_config (struct ast_variable *v, char *cat)
{
int pos, i;
union misdn_cfg_pt cfg_tmp[NUM_PORT_ELEMENTS];
int cfg_for_ports[max_ports + 1];
if (!v || !cat)
return;
memset(cfg_tmp, 0, sizeof(cfg_tmp));
memset(cfg_for_ports, 0, sizeof(cfg_for_ports));
if (!strcasecmp(cat, "default")) {
cfg_for_ports[0] = 1;
}
if (((pos = get_cfg_position("name", PORT_CFG)) < 0) ||
(_parse(&cfg_tmp[pos], cat, port_spec[pos].type, port_spec[pos].boolint_def) < 0)) {
CLI_ERROR(v->name, v->value, cat);
return;
}
for (; v; v = v->next) {
if (!strcasecmp(v->name, "ports")) {
char *token;
char ptpbuf[BUFFERSIZE] = "";
int start, end;
for (token = strsep(&v->value, ","); token; token = strsep(&v->value, ","), *ptpbuf = 0) {
if (!*token)
continue;
if (sscanf(token, "%d-%d%s", &start, &end, ptpbuf) >= 2) {
for (; start <= end; start++) {
if (start <= max_ports && start > 0) {
cfg_for_ports[start] = 1;
ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0;
} else
CLI_ERROR(v->name, v->value, cat);
}
} else {
if (sscanf(token, "%d%s", &start, ptpbuf)) {
if (start <= max_ports && start > 0) {
cfg_for_ports[start] = 1;
ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0;
} else
CLI_ERROR(v->name, v->value, cat);
} else
CLI_ERROR(v->name, v->value, cat);
}
}
} else {
if (((pos = get_cfg_position(v->name, PORT_CFG)) < 0) ||
(_parse(&cfg_tmp[pos], v->value, port_spec[pos].type, port_spec[pos].boolint_def) < 0))
CLI_ERROR(v->name, v->value, cat);
}
}
for (i = 0; i < (max_ports + 1); ++i) {
if (cfg_for_ports[i]) {
memcpy(port_cfg[i], cfg_tmp, sizeof(cfg_tmp));
}
}
}
void misdn_cfg_update_ptp (void)
{
char misdn_init[BUFFERSIZE];
char line[BUFFERSIZE];
FILE *fp;
char *tok, *p, *end;
int port;
misdn_cfg_get(0, MISDN_GEN_MISDN_INIT, &misdn_init, sizeof(misdn_init));
if (misdn_init) {
fp = fopen(misdn_init, "r");
if (fp) {
while(fgets(line, sizeof(line), fp)) {
if (!strncmp(line, "nt_ptp", 6)) {
for (tok = strtok_r(line,",=", &p);
tok;
tok = strtok_r(NULL,",=", &p)) {
port = strtol(tok, &end, 10);
if (end != tok && misdn_cfg_is_port_valid(port)) {
misdn_cfg_lock();
ptp[port] = 1;
misdn_cfg_unlock();
}
}
}
}
fclose(fp);
} else {
ast_log(LOG_WARNING,"Couldn't open %s: %s\n", misdn_init, strerror(errno));
}
}
}
static void _fill_defaults (void)
{
int i;
for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
if (!port_cfg[0][i].any && strcasecmp(port_spec[i].def, NO_DEFAULT))
_parse(&(port_cfg[0][i]), (char *)port_spec[i].def, port_spec[i].type, port_spec[i].boolint_def);
}
for (i = 0; i < NUM_GEN_ELEMENTS; ++i) {
if (!general_cfg[i].any && strcasecmp(gen_spec[i].def, NO_DEFAULT))
_parse(&(general_cfg[i]), (char *)gen_spec[i].def, gen_spec[i].type, gen_spec[i].boolint_def);
}
}
void misdn_cfg_reload (void)
{
misdn_cfg_init (0);
}
void misdn_cfg_destroy (void)
{
misdn_cfg_lock();
_free_port_cfg();
_free_general_cfg();
free(port_cfg);
free(general_cfg);
free(ptp);
free(map);
misdn_cfg_unlock();
ast_mutex_destroy(&config_mutex);
}
void misdn_cfg_init (int this_max_ports)
{
char config[] = "misdn.conf";
char *cat, *p;
int i;
struct ast_config *cfg;
struct ast_variable *v;
if (!(cfg = AST_LOAD_CFG(config))) {
ast_log(LOG_WARNING,"no misdn.conf ?\n");
return;
}
misdn_cfg_lock();
if (this_max_ports) {
/* this is the first run */
max_ports = this_max_ports;
p = (char *)calloc(1, (max_ports + 1) * sizeof(union misdn_cfg_pt *)
+ (max_ports + 1) * NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt));
port_cfg = (union misdn_cfg_pt **)p;
p += (max_ports + 1) * sizeof(union misdn_cfg_pt *);
for (i = 0; i <= max_ports; ++i) {
port_cfg[i] = (union misdn_cfg_pt *)p;
p += NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt);
}
general_cfg = (union misdn_cfg_pt *)calloc(1, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS);
ptp = (int *)calloc(max_ports + 1, sizeof(int));
map = (int *)calloc(MISDN_GEN_LAST + 1, sizeof(int));
_enum_array_map();
}
else {
/* misdn reload */
_free_port_cfg();
_free_general_cfg();
memset(port_cfg[0], 0, NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt) * (max_ports + 1));
memset(general_cfg, 0, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS);
memset(ptp, 0, sizeof(int) * (max_ports + 1));
}
cat = ast_category_browse(cfg, NULL);
while(cat) {
v = ast_variable_browse(cfg, cat);
if (!strcasecmp(cat,"general")) {
_build_general_config(v);
} else {
_build_port_config(v, cat);
}
cat = ast_category_browse(cfg,cat);
}
_fill_defaults();
misdn_cfg_unlock();
AST_DESTROY_CFG(cfg);
}

View File

@@ -8,6 +8,10 @@
;
[general]
;
; Sets the Path to the misdn-init.conf (for nt_ptp mode checking)
;
misdn_init=/etc/misdn-init.conf
; set debugging flag:
; 0 - No Debug
@@ -20,27 +24,49 @@
;
debug=0
; set debugging file and flags for mISDNuser (NT-Stack)
;
; flags can be or'ed with the following values:
;
; DBGM_NET 0x00000001
; DBGM_MSG 0x00000002
; DBGM_FSM 0x00000004
; DBGM_TEI 0x00000010
; DBGM_L2 0x00000020
; DBGM_L3 0x00000040
; DBGM_L3DATA 0x00000080
; DBGM_BC 0x00000100
; DBGM_TONE 0x00000200
; DBGM_BCDATA 0x00000400
; DBGM_MAN 0x00001000
; DBGM_APPL 0x00002000
; DBGM_ISDN 0x00004000
; DBGM_SOCK 0x00010000
; DBGM_CONN 0x00020000
; DBGM_CDATA 0x00040000
; DBGM_DDATA 0x00080000
; DBGM_SOUND 0x00100000
; DBGM_SDATA 0x00200000
; DBGM_TOPLEVEL 0x40000000
; DBGM_ALL 0xffffffff
;
ntdebugflags=0
ntdebugfile=/var/log/misdn-nt.log
; the big trace
;
; default value: [not set]
;
;tracefile=/var/log/misdn.trace
; single call trace files
; set to true if you want to have them
; they depend on debug level
;
; default values: trace_calls : false
; trace_dir : /var/log/
;
trace_calls=false
trace_dir=/var/log/
;tracefile=/var/log/asterisk/misdn.log
; set to yes if you want mISDN_dsp to bridge the calls in HW
;
; default value: yes
;
bridging=yes
bridging=no
; stops dialtone after getting first digit on nt Port
;
@@ -54,29 +80,6 @@ stop_tone_after_first_digit=yes
;
append_digits2exten=yes
; set this to yes if you have jollys mISDN which sends correct L1 Infos
;
; default value: yes
;
l1_info_ok=yes
; set this to yes if you want to clear the l3 in case the l2 deactivates
; some environments have a flickering l2 which causes this option to
; damage active calls .. highly experimental
;
; default value: no
;
clear_l3=no
; set the method to use for channel selection:
; standard - always choose the first free channel with the lowest number
; round_robin - use the round robin algorithm to select a channel. use this
; if you want to balance your load.
;
; default value: standard
;
method=standard
;;; CRYPTION STUFF
; Wether to look for dynamic crypting attempt
@@ -125,6 +128,27 @@ context=misdn
;
language=en
;
; sets the musiconhold class
;
musicclass=default
;
; Either if we should produce DTMF Tones ourselve
;
senddtmf=yes
;
; If we should generate Ringing for chan_sip and others
;
far_alerting=no
;
; here you can define which bearers should be allowed
;
allowed_bearers=all
; Prefixes for national and international, those are put before the
; oad if an according dialplan is set by the other end.
;
@@ -149,11 +173,52 @@ txgain=0
;
te_choose_channel=no
;
; This option defines, if chan_misdn should check the L1 on a PMP
; before makeing a group call on it. The L1 may go down for PMP Ports
; so we might need this.
; But be aware! a broken or plugged off cable might be used for a group call
; as well, since chan_misdn has no chance to distinguish if the L1 is down
; because of a lost Link or because the Provider shut it down...
;
; default: yes
;
pmp_l1_check=yes
;
; Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING),
; this requests additional Infos, so we can waitfordigits
; without much issues. This works only for PTP Ports
;
; default value: no
;
need_more_infos=no
; set the method to use for channel selection:
; standard - always choose the first free channel with the lowest number
; round_robin - use the round robin algorithm to select a channel. use this
; if you want to balance your load.
;
; default value: standard
;
method=standard
;
; dialplan means Type Of Number in ISDN Terms (for outgoing calls)
;
; there are different types of the dialplan:
;
; dialplan -> outgoing Number
; localdialplan -> callerid
; cpndialplan -> connected party number
;
; dialplan options:
;
; 0 - unknown
; 1 - National
; 2 - International
; 1 - International
; 2 - National
; 4 - Subscriber
;
; This setting is used for outgoing calls
@@ -161,14 +226,26 @@ te_choose_channel=no
; default value: 0
;
dialplan=0
localdialplan=0
cpndialplan=0
; This is only for asterisk head and will result in only considering
; misdn.confs and misdn_set_opts callingpresentation informations if set to no.
; Otherwise asterisks callingpresentation overwrites misdn.confs settings.
;
; default value: yes
; turn this to no if you don't mind correct handling of Progress Indicators
;
use_callingpres=yes
early_bconnect=yes
;
; turn this on if you like to send Tone Indications to a Incoming
; isdn channel on a TE Port. Rarely used, only if the Telco allows
; you to send indications by yourself, normally the Telco sends the
; indications to the remote party.
;
; default: no
;
incoming_early_audio=no
; uncomment the following to get into s extension at extension conf
; there you can use DigitTimeout if you can't or don't want to use
@@ -179,6 +256,15 @@ use_callingpres=yes
;
;always_immediate=no
;
; set this to yes if you want to generate your own dialtone
; with always_immediate=yes, else chan_misdn generates the dialtone
;
; default value: no
;
nodialtone=no
; uncomment the following if you want callers which called exactly the
; base number (so no extension is set) jump to the s extension.
; if the user dials something more it jumps to the correct extension
@@ -201,17 +287,17 @@ use_callingpres=yes
;callgroup=1
;pickupgroup=1
; Allows/Screens Callerid
;
; possible values: allowed,not_screened
;
; be aware, if you set to allowed you need to set a correct
; callerid in the dialplan or set it here in the misdn.conf
; Some Telcos don't care about wrong callerids, others do !
;
; default value: allowed
;
;presentation=not_screened
; these are the exact isdn screening and presentation indicators
; if -1 is given for both values the presentation indicators are used
; from asterisks SetCallerPres application.
; s=0, p=0 -> callerid presented not screened
; s=1, p=1 -> callerid presented but screened (the remote end does not see it!)
;
; defaule values s=-1, p=-1
presentation=-1
screen=-1
; this enables echocancellation, with the given number of taps
; be aware, move this setting only to outgoing portgroups!
@@ -223,18 +309,22 @@ use_callingpres=yes
;
;echocancel=no
; this disables echocancellation when the call is bridged between
; mISDN channels
;
; default value: no
;
echocancelwhenbridged=no
; chan_misdns jitterbuffer, default 4000
;
jitterbuffer=4000
; Set this to no to disable echotraining
;
; default value: yes
; change this threshold to enable dejitter functionality
;
echotraining=yes
jitterbuffer_upper_threshold=0
;
; change this to yes, if you want to bridge a mISDN data channel to
; another channel type or to an application.
;
hdlc=no
[intern]
; define your ports, e.g. 1,2 (depends on mISDN-driver loading order)
@@ -243,10 +333,12 @@ ports=1,2
context=Intern
[internPP]
; if you want to have pp Protocol on one nt Port, you need
; to add a ptp directly after the portnumber, you can still add
; more ports and multiple ptp adds in your config.
ports=3ptp
;
; adding the postfix 'ptp' to a port number is obsolete now, chan_misdn
; parses /etc/misdn-init.conf and sets the ptp mode to the corresponding
; configs. For backwards compatibility you can still set ptp here.
;
ports=3
[first_extern]
; again port defs

View File

@@ -11,6 +11,7 @@ Features:
* NT and TE mode
* PP and PMP mode
* BRI and PRI (with BNE1 and BN2E1 Cards)
* Hardware Bridging
* DTMF Detection in HW+mISDNdsp (much better than asterisks internal!)
* Display Messages to Phones (which support display msg)
* HOLD/RETRIEVE/TRANSFER on ISDN Phones : )
@@ -21,6 +22,7 @@ Features:
* Data (HDLC) callthrough
* Data Calling (with app_ptyfork +pppd)
* Echo cancellation
* CallDeflection
* Some other
Supported Hardware:
@@ -54,8 +56,7 @@ channels/misdn. You just need to type:
cd channels/misdn
make misdn
Then all the necessary files are fetched from jollys homepage and are patched
with the Echocanellor.
Then all the necessary files are fetched from isdn4linux.de.
Pre-Requisites
@@ -64,7 +65,7 @@ Pre-Requisites
To compile and install this driver, you'll need at least one mISDN Driver and
the mISDNuser package. Chan_misdn works with both, the current release version
and the development (svn trunk) version of Asterisk. mISDNuser and mISDN must
be fetched from jollys homepage and must be patched with the Echocancellor.
be fetched from cvs.isdn4linux.de.
Please Note that mISDN works good for the linux-2.6.x kernels. Some of the
mISDN drivers do not compile against the 2.4.x or older kernels, you can patch
@@ -140,10 +141,6 @@ should insert here the msns which you'll like to give the Asterisk). Finally
a context variable resides in the user sections, which tells chan_misdn where
to send incoming calls to in the Asterisk dial plan (extension.conf).
In NT-Mode Ports there is a new option, directly after the port number you can
write ptp, this enables PP Mode for this port, please look at misdn.conf.sample for
an example.
Dial and Options String
-----------------------
@@ -283,31 +280,6 @@ the pci_find_subgsys funktion, so hfc_multi from mISDN doesn't compile against
it, you can just change pci_find_subsys to pci_get_subsys, this works.
- chan_misdn-0.0.3-rc1:
* linux-kernel >= 2.6.3 (but at least 2.6)
* asterisk >= v1-0
* mISDN/mISDNuser since September/04
- chan_misdn-0.0.3-rc3:
* linux-kernel >= 2.6.3 (but at least 2.6)
* asterisk >= v1-0.2
* mISDN/mISDNuser since December/04
- chan_misdn-0.0.3-rc4:
* linux-kernel >= 2.6.8 (but at least 2.6)
* asterisk >= v1-0.2
* mISDN/mISDNuser head on cvs.isdn4linux.de
- chan_misdn-0.0.3-rc6:
* linux-kernel >= 2.6.8 (but at least 2.6)
* asterisk >= v1-0.2
* mISDN/mISDNuser head on cvs.isdn4linux.de
- chan_misdn-0.1.0
* linux-kernel >= 2.6.8 (but at least 2.6)
* asterisk >= v1-0.2 , also CVS Head
* mISDN/mISDNuser (3.0-beta) from isdn.jolly.de
- chan_misdn-0.2.1
* linux-kernel >= 2.6.8 (but at least 2.6)
* asterisk >= v1.2 , also CVS Head