Compare commits

..

4 Commits

Author SHA1 Message Date
Kevin P. Fleming
c362443bfa remove CVS ignore lists
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.2.0-beta2@267 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2005-11-29 18:40:06 +00:00
Kevin P. Fleming
52c6ae7729 remove extraneous svn:executable properties
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.2.0-beta2@266 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2005-11-29 18:39:18 +00:00
Kevin P. Fleming
400b3fca62 manual tag renames
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.2.0-beta2@262 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2005-11-27 04:16:28 +00:00
Admin Commit
0c747df13b This commit was manufactured by cvs2svn to create tag 'v1-2-0-beta2'.
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/v1-2-0-beta2@258 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2005-10-25 16:59:59 +00:00
17 changed files with 346 additions and 1143 deletions

View File

@@ -1 +0,0 @@
1.4.3

108
ChangeLog
View File

@@ -1,98 +1,16 @@
2007-12-13 Russell Bryant <russell@digium.com> libpri 0.3.0
-- Fix talking to switch
-- Add pri dump
-- Add test application
-- Fix strncpy stuff
libpri 0.1.2
-- Added PRI_EVENT_HANGUP_ACK so you can know when the disconnect was
acknowledged
* libpri 1.4.3 released. libpri 0.1.1
-- Added PRI_DEBUG_Q931_ANOMALY flag so that certain non-error-related
messages would not be output unless specifically desired.
2007-10-22 15:10 +0000 [r479] Kevin P. Fleming <kpfleming@digium.com> libpri 0.1.0
-- Initial release
* pri_internal.h, /: Merged revisions 478 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r478
| kpfleming | 2007-10-22 10:09:27 -0500 (Mon, 22 Oct 2007) | 3
lines we need to include stddef.h for 'size_t' ........
2007-10-16 Matthew Fredrickson <creslin@digium.com>
* libpri 1.4.2 released.
2007-10-05 16:45 +0000 [r470] Jason Parker <jparker@digium.com>
* libpri.h: Fix an incorrect pri_event structure definition. Issue
10832, patch by flefoll
2007-09-25 21:37 +0000 [r468] Matthew Fredrickson <creslin@digium.com>
* q931.c: Fix user-user IE order in setup message (#10705)
2007-09-14 21:32 +0000 [r465] Matthew Fredrickson <creslin@digium.com>
* q931.c, libpri.h: Fix for #10189. Make sure we properly report
the user layer 1 for H.223 and H.245
2007-09-06 15:11 +0000 [r462] Matthew Fredrickson <creslin@digium.com>
* pri.c, pri_facility.c, /: Merged revisions 460 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r460
| mattf | 2007-09-06 10:06:42 -0500 (Thu, 06 Sep 2007) | 1 line
TBCT now works. It should work for NI2, 4E, and 5E. This code was
tested on NI2. ........
2007-08-27 19:21 +0000 [r446] Jason Parker <jparker@digium.com>
* Makefile, /: Merged revisions 445 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r445
| qwell | 2007-08-27 14:20:23 -0500 (Mon, 27 Aug 2007) | 2 lines
Make sure we build both the static and shared modules with -fPIC.
........
2007-08-06 19:58 +0000 [r441] Jason Parker <jparker@digium.com>
* Makefile: Allow setting CC to something with a space, such as
`make CC="gcc -m32"` Issue 10253.
2007-07-09 Russell Bryant <russell@digium.com>
* libpri 1.4.1 released.
2007-06-19 18:23 +0000 [r427] Matthew Fredrickson <creslin@digium.com>
* q931.c, /: Merged revisions 426 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r426
| mattf | 2007-06-19 13:22:33 -0500 (Tue, 19 Jun 2007) | 1 line
Try to send pending facility messages if we receive alerting (for
when we don't get proceeding) (#9651) ........
2007-06-06 21:58 +0000 [r416-424] Matthew Fredrickson <creslin@digium.com>
* pri_facility.c, /: Merged revisions 423 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r423
| mattf | 2007-06-06 16:57:15 -0500 (Wed, 06 Jun 2007) | 1 line
Oops, that should not be on one line ........
* pri_facility.c, /: Merged revisions 415 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r415
| mattf | 2007-06-06 08:20:05 -0500 (Wed, 06 Jun 2007) | 2 lines
Make sure we only send the NFE when we are talking QSIG ........
2007-01-22 22:29 +0000 [r390] Matthew Fredrickson <creslin@digium.com>
* q931.c, /: Merged revisions 389 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r389
| mattf | 2007-01-22 16:20:59 -0600 (Mon, 22 Jan 2007) | 2 lines
Make sure we send DISCONNECT if we reached the active state and a
call is disconnected, regardless of cause code. ........
2006-12-30 19:17 +0000 [r386] Joshua Colp <jcolp@digium.com>
* Makefile, /: Merged revisions 385 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r385
| file | 2006-12-30 14:16:17 -0500 (Sat, 30 Dec 2006) | 2 lines
Specify full path to restorecon instead of assuming it will be
available from what is in $PATH. (issue #8670 reported by djflux)
........
2006-12-23 Kevin P. Fleming <kpfleming@digium.com>
* libpri 1.4.0 released.
2006-09-20 Kevin P. Fleming <kpfleming@digium.com>
* libpri 1.4.0-beta1 released.

View File

@@ -32,22 +32,23 @@ CC=gcc
OSARCH=$(shell uname -s) OSARCH=$(shell uname -s)
PROC?=$(shell uname -m) PROC?=$(shell uname -m)
TOBJS=testpri.o
T2OBJS=testprilib.o
STATIC_LIBRARY=libpri.a STATIC_LIBRARY=libpri.a
DYNAMIC_LIBRARY=libpri.so.1.0 DYNAMIC_LIBRARY=libpri.so.1.0
STATIC_OBJS=copy_string.o pri.o q921.o prisched.o q931.o pri_facility.o STATIC_OBJS=copy_string.o pri.o q921.o prisched.o q931.o pri_facility.o
DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS) CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS)
INSTALL_PREFIX=$(DESTDIR) INSTALL_PREFIX?=
INSTALL_BASE=/usr INSTALL_BASE=/usr
SOFLAGS = -Wl,-hlibpri.so.1.0 SOFLAGS = -Wl,-hlibpri.so.1
LDCONFIG = /sbin/ldconfig LDCONFIG = /sbin/ldconfig
ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX)) ifeq (${OSARCH},Linux)
LDCONFIG_FLAGS=-n LDCONFIG_FLAGS=-n
else else
ifeq (${OSARCH},FreeBSD) ifeq (${OSARCH},FreeBSD)
LDCONFIG_FLAGS=-m LDCONFIG_FLAGS=-m
CFLAGS += -I../zaptel -I../zapata CFLAGS += -I../zaptel -I../zapata
INSTALL_BASE=/usr/local
endif endif
endif endif
ifeq (${OSARCH},SunOS) ifeq (${OSARCH},SunOS)
@@ -69,11 +70,11 @@ endif
all: depend $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY) all: depend $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
update: update:
@if [ -d .svn ]; then \ @if [ -d CVS ]; then \
echo "Updating from Subversion..." ; \ echo "Updating from CVS..." ; \
svn update -q; \ cvs -q -z3 update -Pd; \
else \ else \
echo "Not under version control"; \ echo "Not CVS"; \
fi fi
install: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY) install: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
@@ -82,14 +83,14 @@ install: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
ifneq (${OSARCH},SunOS) ifneq (${OSARCH},SunOS)
install -m 644 libpri.h $(INSTALL_PREFIX)$(INSTALL_BASE)/include install -m 644 libpri.h $(INSTALL_PREFIX)$(INSTALL_BASE)/include
install -m 755 $(DYNAMIC_LIBRARY) $(INSTALL_PREFIX)$(INSTALL_BASE)/lib install -m 755 $(DYNAMIC_LIBRARY) $(INSTALL_PREFIX)$(INSTALL_BASE)/lib
if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then /sbin/restorecon -v $(INSTALL_PREFIX)$(INSTALL_BASE)/lib/$(DYNAMIC_LIBRARY); fi if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then restorecon -v $(INSTALL_PREFIX)$(INSTALL_BASE)/lib/$(DYNAMIC_LIBRARY); fi
( cd $(INSTALL_PREFIX)$(INSTALL_BASE)/lib ; ln -sf libpri.so.1.0 libpri.so ; ln -sf libpri.so.1.0 libpri.so.1 ) ( cd $(INSTALL_PREFIX)$(INSTALL_BASE)/lib ; ln -sf libpri.so.1 libpri.so )
install -m 644 $(STATIC_LIBRARY) $(INSTALL_PREFIX)$(INSTALL_BASE)/lib install -m 644 $(STATIC_LIBRARY) $(INSTALL_PREFIX)$(INSTALL_BASE)/lib
if test $$(id -u) = 0; then $(LDCONFIG) $(LDCONFIG_FLAGS) $(INSTALL_PREFIX)$(INSTALL_BASE)/lib; fi if test $$(id -u) = 0; then $(LDCONFIG); fi
else else
install -f $(INSTALL_PREFIX)$(INSTALL_BASE)/include -m 644 libpri.h install -f $(INSTALL_PREFIX)$(INSTALL_BASE)/include -m 644 libpri.h
install -f $(INSTALL_PREFIX)$(INSTALL_BASE)/lib -m 755 $(DYNAMIC_LIBRARY) install -f $(INSTALL_PREFIX)$(INSTALL_BASE)/lib -m 755 $(DYNAMIC_LIBRARY)
( cd $(INSTALL_PREFIX)$(INSTALL_BASE)/lib ; ln -sf libpri.so.1.0 libpri.so ; $(SOSLINK) ) ( cd $(INSTALL_PREFIX)$(INSTALL_BASE)/lib ; ln -sf libpri.so.1 libpri.so ; $(SOSLINK) )
install -f $(INSTALL_PREFIX)$(INSTALL_BASE)/lib -m 644 $(STATIC_LIBRARY) install -f $(INSTALL_PREFIX)$(INSTALL_BASE)/lib -m 644 $(STATIC_LIBRARY)
endif endif
@@ -118,7 +119,7 @@ include .depend
endif endif
%.lo : %.c %.lo : %.c
$(CC) $(CFLAGS) -o $@ -c $< $(CC) -fPIC $(CFLAGS) -o $@ -c $<
$(STATIC_LIBRARY): $(STATIC_OBJS) $(STATIC_LIBRARY): $(STATIC_OBJS)
ar rcs $(STATIC_LIBRARY) $(STATIC_OBJS) ar rcs $(STATIC_LIBRARY) $(STATIC_OBJS)
@@ -127,17 +128,16 @@ $(STATIC_LIBRARY): $(STATIC_OBJS)
$(DYNAMIC_LIBRARY): $(DYNAMIC_OBJS) $(DYNAMIC_LIBRARY): $(DYNAMIC_OBJS)
$(CC) -shared $(SOFLAGS) -o $@ $(DYNAMIC_OBJS) $(CC) -shared $(SOFLAGS) -o $@ $(DYNAMIC_OBJS)
$(LDCONFIG) $(LDCONFIG_FLAGS) . $(LDCONFIG) $(LDCONFIG_FLAGS) .
ln -sf libpri.so.1.0 libpri.so ln -sf libpri.so.1 libpri.so
ln -sf libpri.so.1.0 libpri.so.1
$(SOSLINK) $(SOSLINK)
clean: clean:
rm -f *.o *.so *.lo *.so.1 *.so.1.0 rm -f *.o *.so *.lo *.so.1 *.so.1.0
rm -f testprilib $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY) rm -f testpri testprilib $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
rm -f pritest pridump rm -f pritest pridump
rm -f .depend rm -f .depend
depend: .depend depend: .depend
.depend: .depend:
CC="$(CC)" ./mkdep ${CFLAGS} `ls *.c` CC=$(CC) ./mkdep ${CFLAGS} `ls *.c`

2
README
View File

@@ -1,4 +1,4 @@
libpri: An implementation of Primary Rate ISDN libpri: An implementation of Primate Rate ISDN
Written by Mark Spencer <markster@digium.com> Written by Mark Spencer <markster@digium.com>

4
TODO
View File

@@ -1,8 +1,10 @@
General: General:
-- D-Channel Backup
-- Test against 4e
Q.921: Q.921:
-- Support unnumbered information frames -- Support unnumbered information frames
-- Get TEI codes working for BRI interfaces
Q.931: Q.931:
-- Locking Shift IE
-- Implement the 11 missing Q.931 timers -- Implement the 11 missing Q.931 timers

View File

@@ -142,10 +142,10 @@
/* Causes for disconnection */ /* Causes for disconnection */
#define PRI_CAUSE_UNALLOCATED 1 #define PRI_CAUSE_UNALLOCATED 1
#define PRI_CAUSE_NO_ROUTE_TRANSIT_NET 2 /* !Q.SIG */ #define PRI_CAUSE_NO_ROUTE_TRANSIT_NET 2
#define PRI_CAUSE_NO_ROUTE_DESTINATION 3 #define PRI_CAUSE_NO_ROUTE_DESTINATION 3
#define PRI_CAUSE_CHANNEL_UNACCEPTABLE 6 #define PRI_CAUSE_CHANNEL_UNACCEPTABLE 6
#define PRI_CAUSE_CALL_AWARDED_DELIVERED 7 /* !Q.SIG */ #define PRI_CAUSE_CALL_AWARDED_DELIVERED 7
#define PRI_CAUSE_NORMAL_CLEARING 16 #define PRI_CAUSE_NORMAL_CLEARING 16
#define PRI_CAUSE_USER_BUSY 17 #define PRI_CAUSE_USER_BUSY 17
#define PRI_CAUSE_NO_USER_RESPONSE 18 #define PRI_CAUSE_NO_USER_RESPONSE 18
@@ -154,29 +154,27 @@
#define PRI_CAUSE_NUMBER_CHANGED 22 #define PRI_CAUSE_NUMBER_CHANGED 22
#define PRI_CAUSE_DESTINATION_OUT_OF_ORDER 27 #define PRI_CAUSE_DESTINATION_OUT_OF_ORDER 27
#define PRI_CAUSE_INVALID_NUMBER_FORMAT 28 #define PRI_CAUSE_INVALID_NUMBER_FORMAT 28
#define PRI_CAUSE_FACILITY_REJECTED 29 /* !Q.SIG */ #define PRI_CAUSE_FACILITY_REJECTED 29
#define PRI_CAUSE_RESPONSE_TO_STATUS_ENQUIRY 30 #define PRI_CAUSE_RESPONSE_TO_STATUS_ENQUIRY 30
#define PRI_CAUSE_NORMAL_UNSPECIFIED 31 #define PRI_CAUSE_NORMAL_UNSPECIFIED 31
#define PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION 34 #define PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION 34
#define PRI_CAUSE_NETWORK_OUT_OF_ORDER 38 /* !Q.SIG */ #define PRI_CAUSE_NETWORK_OUT_OF_ORDER 38
#define PRI_CAUSE_NORMAL_TEMPORARY_FAILURE 41 #define PRI_CAUSE_NORMAL_TEMPORARY_FAILURE 41
#define PRI_CAUSE_SWITCH_CONGESTION 42 /* !Q.SIG */ #define PRI_CAUSE_SWITCH_CONGESTION 42
#define PRI_CAUSE_ACCESS_INFO_DISCARDED 43 /* !Q.SIG */ #define PRI_CAUSE_ACCESS_INFO_DISCARDED 43
#define PRI_CAUSE_REQUESTED_CHAN_UNAVAIL 44 #define PRI_CAUSE_REQUESTED_CHAN_UNAVAIL 44
#define PRI_CAUSE_PRE_EMPTED 45 /* !Q.SIG */ #define PRI_CAUSE_PRE_EMPTED 45
#define PRI_CAUSE_FACILITY_NOT_SUBSCRIBED 50 /* !Q.SIG */ #define PRI_CAUSE_FACILITY_NOT_SUBSCRIBED 50
#define PRI_CAUSE_OUTGOING_CALL_BARRED 52 /* !Q.SIG */ #define PRI_CAUSE_OUTGOING_CALL_BARRED 52
#define PRI_CAUSE_INCOMING_CALL_BARRED 54 /* !Q.SIG */ #define PRI_CAUSE_INCOMING_CALL_BARRED 54
#define PRI_CAUSE_BEARERCAPABILITY_NOTAUTH 57 #define PRI_CAUSE_BEARERCAPABILITY_NOTAUTH 57
#define PRI_CAUSE_BEARERCAPABILITY_NOTAVAIL 58 #define PRI_CAUSE_BEARERCAPABILITY_NOTAVAIL 58
#define PRI_CAUSE_SERVICEOROPTION_NOTAVAIL 63 /* Q.SIG */
#define PRI_CAUSE_BEARERCAPABILITY_NOTIMPL 65 #define PRI_CAUSE_BEARERCAPABILITY_NOTIMPL 65
#define PRI_CAUSE_CHAN_NOT_IMPLEMENTED 66 /* !Q.SIG */ #define PRI_CAUSE_CHAN_NOT_IMPLEMENTED 66
#define PRI_CAUSE_FACILITY_NOT_IMPLEMENTED 69 /* !Q.SIG */ #define PRI_CAUSE_FACILITY_NOT_IMPLEMENTED 69
#define PRI_CAUSE_INVALID_CALL_REFERENCE 81 #define PRI_CAUSE_INVALID_CALL_REFERENCE 81
#define PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST 82 /* Q.SIG */
#define PRI_CAUSE_INCOMPATIBLE_DESTINATION 88 #define PRI_CAUSE_INCOMPATIBLE_DESTINATION 88
#define PRI_CAUSE_INVALID_MSG_UNSPECIFIED 95 /* !Q.SIG */ #define PRI_CAUSE_INVALID_MSG_UNSPECIFIED 95
#define PRI_CAUSE_MANDATORY_IE_MISSING 96 #define PRI_CAUSE_MANDATORY_IE_MISSING 96
#define PRI_CAUSE_MESSAGE_TYPE_NONEXIST 97 #define PRI_CAUSE_MESSAGE_TYPE_NONEXIST 97
#define PRI_CAUSE_WRONG_MESSAGE 98 #define PRI_CAUSE_WRONG_MESSAGE 98
@@ -184,9 +182,9 @@
#define PRI_CAUSE_INVALID_IE_CONTENTS 100 #define PRI_CAUSE_INVALID_IE_CONTENTS 100
#define PRI_CAUSE_WRONG_CALL_STATE 101 #define PRI_CAUSE_WRONG_CALL_STATE 101
#define PRI_CAUSE_RECOVERY_ON_TIMER_EXPIRE 102 #define PRI_CAUSE_RECOVERY_ON_TIMER_EXPIRE 102
#define PRI_CAUSE_MANDATORY_IE_LENGTH_ERROR 103 /* !Q.SIG */ #define PRI_CAUSE_MANDATORY_IE_LENGTH_ERROR 103
#define PRI_CAUSE_PROTOCOL_ERROR 111 #define PRI_CAUSE_PROTOCOL_ERROR 111
#define PRI_CAUSE_INTERWORKING 127 /* !Q.SIG */ #define PRI_CAUSE_INTERWORKING 127
/* Transmit capabilities */ /* Transmit capabilities */
#define PRI_TRANS_CAP_SPEECH 0x0 #define PRI_TRANS_CAP_SPEECH 0x0
@@ -202,7 +200,7 @@
#define PRI_LAYER_1_ALAW 0x23 #define PRI_LAYER_1_ALAW 0x23
#define PRI_LAYER_1_G721 0x24 #define PRI_LAYER_1_G721 0x24
#define PRI_LAYER_1_G722_G725 0x25 #define PRI_LAYER_1_G722_G725 0x25
#define PRI_LAYER_1_H223_H245 0x26 #define PRI_LAYER_1_G7XX_384K 0x26
#define PRI_LAYER_1_NON_ITU_ADAPT 0x27 #define PRI_LAYER_1_NON_ITU_ADAPT 0x27
#define PRI_LAYER_1_V120_RATE_ADAPT 0x28 #define PRI_LAYER_1_V120_RATE_ADAPT 0x28
#define PRI_LAYER_1_X31_RATE_ADAPT 0x29 #define PRI_LAYER_1_X31_RATE_ADAPT 0x29
@@ -361,7 +359,6 @@ typedef struct pri_event_proceeding {
typedef struct pri_event_setup_ack { typedef struct pri_event_setup_ack {
int e; int e;
int channel; int channel;
q931_call *call;
} pri_event_setup_ack; } pri_event_setup_ack;
typedef struct pri_event_notify { typedef struct pri_event_notify {
@@ -386,7 +383,7 @@ typedef union {
pri_event_ring ring; /* Ring */ pri_event_ring ring; /* Ring */
pri_event_hangup hangup; /* Hang up */ pri_event_hangup hangup; /* Hang up */
pri_event_ringing ringing; /* Ringing */ pri_event_ringing ringing; /* Ringing */
pri_event_answer answer; /* Answer */ pri_event_ringing answer; /* Answer */
pri_event_restart_ack restartack; /* Restart Acknowledge */ pri_event_restart_ack restartack; /* Restart Acknowledge */
pri_event_proceeding proceeding; /* Call proceeding & Progress */ pri_event_proceeding proceeding; /* Call proceeding & Progress */
pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */ pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */
@@ -465,10 +462,6 @@ extern int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int in
/* Send a digit in overlap mode */ /* Send a digit in overlap mode */
extern int pri_information(struct pri *pri, q931_call *call, char digit); extern int pri_information(struct pri *pri, q931_call *call, char digit);
#define PRI_KEYPAD_FACILITY_TX
/* Send a keypad facility string of digits */
extern int pri_keypad_facility(struct pri *pri, q931_call *call, char *digits);
/* Answer the incomplete(call without called number) call on the given channel. /* Answer the incomplete(call without called number) call on the given channel.
Set non-isdn to non-zero if you are not connecting to ISDN equipment */ Set non-isdn to non-zero if you are not connecting to ISDN equipment */
extern int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn); extern int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn);
@@ -531,9 +524,9 @@ extern int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername,
extern int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason); extern int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
#define PRI_USER_USER_TX #define PRI_USER_USER_TX
/* Set the user user field. Warning! don't send binary data accross this field */ /* Set the user user field. Warning! don't send binary data accross this field */
extern void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars); extern void pri_sr_set_useruser(struct pri_sr *sr, char *userchars);
extern void pri_call_set_useruser(q931_call *sr, const char *userchars); extern void pri_call_set_useruser(q931_call *sr, char *userchars);
extern int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req); extern int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req);

2
mkdep
View File

@@ -1,4 +1,4 @@
#!/bin/sh - #!/bin/bash -
# #
# $OpenBSD: mkdep.gcc.sh,v 1.8 1998/09/02 06:40:07 deraadt Exp $ # $OpenBSD: mkdep.gcc.sh,v 1.8 1998/09/02 06:40:07 deraadt Exp $
# $NetBSD: mkdep.gcc.sh,v 1.9 1994/12/23 07:34:59 jtc Exp $ # $NetBSD: mkdep.gcc.sh,v 1.9 1994/12/23 07:34:59 jtc Exp $

39
pri.c
View File

@@ -247,13 +247,13 @@ static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *maste
return p; return p;
} }
void pri_call_set_useruser(q931_call *c, const char *userchars) void pri_call_set_useruser(q931_call *c, char *userchars)
{ {
if (userchars) if (userchars)
libpri_copy_string(c->useruserinfo, userchars, sizeof(c->useruserinfo)); libpri_copy_string(c->useruserinfo, userchars, sizeof(c->useruserinfo));
} }
void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars) void pri_sr_set_useruser(struct pri_sr *sr, char *userchars)
{ {
sr->useruserinfo = userchars; sr->useruserinfo = userchars;
} }
@@ -471,14 +471,6 @@ int pri_information(struct pri *pri, q931_call *call, char digit)
return q931_information(pri, call, digit); return q931_information(pri, call, digit);
} }
int pri_keypad_facility(struct pri *pri, q931_call *call, char *digits)
{
if (!pri || !call || !digits || !digits[0])
return -1;
return q931_keypad_facility(pri, call, digits);
}
int pri_notify(struct pri *pri, q931_call *call, int channel, int info) int pri_notify(struct pri *pri, q931_call *call, int channel, int info)
{ {
if (!pri || !call) if (!pri || !call)
@@ -529,36 +521,24 @@ int pri_channel_bridge(q931_call *call1, q931_call *call2)
if (!call1 || !call2) if (!call1 || !call2)
return -1; return -1;
/* Make sure we have compatible switchtypes */ /* Check switchtype compatibility */
if (call1->pri->switchtype != call2->pri->switchtype) if (call1->pri->switchtype != PRI_SWITCH_LUCENT5E ||
call2->pri->switchtype != PRI_SWITCH_LUCENT5E)
return -1; return -1;
/* Check for bearer capability */ /* Check for bearer capability */
if (call1->transcapability != call2->transcapability) if (call1->transcapability != call2->transcapability)
return -1; return -1;
/* Check to see if calls are on the same PRI dchannel
/* Check to see if we're on the same PRI */ * Currently only support calls on the same dchannel
*/
if (call1->pri != call2->pri) if (call1->pri != call2->pri)
return -1; return -1;
switch (call1->pri->switchtype) {
case PRI_SWITCH_NI2:
case PRI_SWITCH_LUCENT5E:
case PRI_SWITCH_ATT4ESS:
if (eect_initiate_transfer(call1->pri, call1, call2)) if (eect_initiate_transfer(call1->pri, call1, call2))
return -1; return -1;
else
return 0; return 0;
break;
case PRI_SWITCH_DMS100:
if (rlt_initiate_transfer(call1->pri, call1, call2))
return -1;
else
return 0;
break;
default:
return -1;
}
} }
int pri_hangup(struct pri *pri, q931_call *call, int cause) int pri_hangup(struct pri *pri, q931_call *call, int cause)
@@ -795,7 +775,6 @@ char *pri_dump_info_str(struct pri *pri)
len += sprintf(buf + len, "T203 Timer: %d\n", pri->timers[PRI_TIMER_T203]); len += sprintf(buf + len, "T203 Timer: %d\n", pri->timers[PRI_TIMER_T203]);
len += sprintf(buf + len, "T305 Timer: %d\n", pri->timers[PRI_TIMER_T305]); len += sprintf(buf + len, "T305 Timer: %d\n", pri->timers[PRI_TIMER_T305]);
len += sprintf(buf + len, "T308 Timer: %d\n", pri->timers[PRI_TIMER_T308]); len += sprintf(buf + len, "T308 Timer: %d\n", pri->timers[PRI_TIMER_T308]);
len += sprintf(buf + len, "T309 Timer: %d\n", pri->timers[PRI_TIMER_T309]);
len += sprintf(buf + len, "T313 Timer: %d\n", pri->timers[PRI_TIMER_T313]); len += sprintf(buf + len, "T313 Timer: %d\n", pri->timers[PRI_TIMER_T313]);
len += sprintf(buf + len, "N200 Counter: %d\n", pri->timers[PRI_TIMER_N200]); len += sprintf(buf + len, "N200 Counter: %d\n", pri->timers[PRI_TIMER_N200]);

View File

@@ -32,132 +32,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
static char *asn1id2text(int id)
{
static char data[32];
static char *strings[] = {
"none",
"Boolean",
"Integer",
"Bit String",
"Octet String",
"NULL",
"Object Identifier",
"Object Descriptor",
"External Reference",
"Real Number",
"Enumerated",
"Embedded PDV",
"UTF-8 String",
"Relative Object ID",
"Reserved (0e)",
"Reserved (0f)",
"Sequence",
"Set",
"Numeric String",
"Printable String",
"Tele-Text String",
"IA-5 String",
"UTC Time",
"Generalized Time",
};
if (id > 0 && id <= 0x18) {
return strings[id];
} else {
sprintf(data, "Unknown (%02x)", id);
return data;
}
}
static int asn1_dumprecursive(struct pri *pri, void *comp_ptr, int len, int level)
{
unsigned char *vdata = (unsigned char *)comp_ptr;
struct rose_component *comp;
int i = 0;
int j, k, l;
int clen = 0;
while (len > 0) {
GET_COMPONENT(comp, i, vdata, len);
pri_message(pri, "%*s%02X %04X", 2 * level, "", comp->type, comp->len);
if ((comp->type == 0) && (comp->len == 0))
return clen + 2;
if ((comp->type & ASN1_PC_MASK) == ASN1_PRIMITIVE) {
for (j = 0; j < comp->len; ++j)
pri_message(pri, " %02X", comp->data[j]);
}
if ((comp->type & ASN1_CLAN_MASK) == ASN1_UNIVERSAL) {
switch (comp->type & ASN1_TYPE_MASK) {
case 0:
pri_message(pri, " (none)");
break;
case ASN1_BOOLEAN:
pri_message(pri, " (BOOLEAN: %d)", comp->data[0]);
break;
case ASN1_INTEGER:
for (k = l = 0; k < comp->len; ++k)
l = (l << 8) | comp->data[k];
pri_message(pri, " (INTEGER: %d)", l);
break;
case ASN1_BITSTRING:
pri_message(pri, " (BITSTRING:");
for (k = 0; k < comp->len; ++k)
pri_message(pri, " %02x", comp->data[k]);
pri_message(pri, ")");
break;
case ASN1_OCTETSTRING:
pri_message(pri, " (OCTETSTRING:");
for (k = 0; k < comp->len; ++k)
pri_message(pri, " %02x", comp->data[k]);
pri_message(pri, ")");
break;
case ASN1_NULL:
pri_message(pri, " (NULL)");
break;
case ASN1_OBJECTIDENTIFIER:
pri_message(pri, " (OBJECTIDENTIFIER:");
for (k = 0; k < comp->len; ++k)
pri_message(pri, " %02x", comp->data[k]);
pri_message(pri, ")");
break;
case ASN1_ENUMERATED:
for (k = l = 0; k < comp->len; ++k)
l = (l << 8) | comp->data[k];
pri_message(pri, " (ENUMERATED: %d)", l);
break;
case ASN1_SEQUENCE:
pri_message(pri, " (SEQUENCE)");
break;
default:
pri_message(pri, " (component %02x - %s)", comp->type, asn1id2text(comp->type & ASN1_TYPE_MASK));
break;
}
}
else if ((comp->type & ASN1_CLAN_MASK) == ASN1_CONTEXT_SPECIFIC) {
pri_message(pri, " (CONTEXT SPECIFIC [%d])", comp->type & ASN1_TYPE_MASK);
}
else {
pri_message(pri, " (component %02x)", comp->type);
}
pri_message(pri, "\n");
if ((comp->type & ASN1_PC_MASK) == ASN1_CONSTRUCTOR)
j = asn1_dumprecursive(pri, comp->data, (comp->len ? comp->len : INT_MAX), level+1);
else
j = comp->len;
j += 2;
len -= j;
vdata += j;
clen += j;
}
return clen;
}
int asn1_dump(struct pri *pri, void *comp, int len)
{
return asn1_dumprecursive(pri, comp, len, 0);
}
static unsigned char get_invokeid(struct pri *pri) static unsigned char get_invokeid(struct pri *pri)
{ {
@@ -172,44 +46,28 @@ struct addressingdataelements_presentednumberunscreened {
int pres; int pres;
}; };
#define PRI_CHECKOVERFLOW(size) \
if (msgptr - message + (size) >= sizeof(message)) { \
*msgptr = '\0'; \
pri_message(pri, "%s", message); \
msgptr = message; \
}
static void dump_apdu(struct pri *pri, unsigned char *c, int len) static void dump_apdu(struct pri *pri, unsigned char *c, int len)
{ {
#define MAX_APDU_LENGTH 255 #define MAX_APDU_LENGTH 255
static char hexs[16] = "0123456789ABCDEF";
int i; int i;
char message[(2 + MAX_APDU_LENGTH * 3 + 6 + MAX_APDU_LENGTH + 3)] = ""; /* please adjust here, if you make changes below! */ char message[(2 + MAX_APDU_LENGTH * 3 + 6 + MAX_APDU_LENGTH + 3)] = ""; /* please adjust here, if you make changes below! */
char *msgptr;
msgptr = message; if (len > MAX_APDU_LENGTH)
*msgptr++ = ' '; return;
*msgptr++ = '[';
snprintf(message, sizeof(message)-1, " [");
for (i=0; i<len; i++)
snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, " %02x", c[i]);
snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, " ] - [");
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
PRI_CHECKOVERFLOW(3); if (c[i] < 20 || c[i] >= 128)
*msgptr++ = ' '; snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "<EFBFBD>");
*msgptr++ = hexs[(c[i] >> 4) & 0x0f]; else
*msgptr++ = hexs[(c[i]) & 0x0f]; snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "%c", c[i]);
} }
PRI_CHECKOVERFLOW(6); snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "]\n");
strcpy(msgptr, " ] - ["); pri_message(pri, message);
msgptr += strlen(msgptr);
for (i=0; i<len; i++) {
PRI_CHECKOVERFLOW(1);
*msgptr++ = ((c[i] < ' ') || (c[i] > '~')) ? '.' : c[i];
} }
PRI_CHECKOVERFLOW(2);
*msgptr++ = ']';
*msgptr++ = '\n';
*msgptr = '\0';
pri_message(pri, "%s", message);
}
#undef PRI_CHECKOVERFLOW
int redirectingreason_from_q931(struct pri *pri, int redirectingreason) int redirectingreason_from_q931(struct pri *pri, int redirectingreason)
{ {
@@ -706,11 +564,9 @@ static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *ca
unsigned char buffer[256]; unsigned char buffer[256];
int len = 253; int len = 253;
#if 0 /* This is not required by specifications */
if (!strlen(call->callername)) { if (!strlen(call->callername)) {
return -1; return -1;
} }
#endif
buffer[i] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS); buffer[i] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
i++; i++;
@@ -838,84 +694,6 @@ static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *ca
return 0; return 0;
} }
/* Send the rltThirdParty: Invoke */
int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
{
int i = 0;
unsigned char buffer[256];
struct rose_component *comp = NULL, *compstk[10];
const unsigned char rlt_3rd_pty = RLT_THIRD_PARTY;
q931_call *callwithid = NULL, *apdubearer = NULL;
int compsp = 0;
if (c2->transferable) {
apdubearer = c1;
callwithid = c2;
} else if (c1->transferable) {
apdubearer = c2;
callwithid = c1;
} else
return -1;
buffer[i++] = (Q932_PROTOCOL_ROSE);
buffer[i++] = (0x80 | RLT_SERVICE_ID); /* Service Identifier octet */
ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
/* Invoke ID is set to the operation ID */
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_3rd_pty);
/* Operation Tag */
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_3rd_pty);
/* Additional RLT invoke info - Octet 12 */
ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
ASN1_PUSH(compstk, compsp, comp);
ASN1_ADD_WORDCOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, callwithid->rlt_call_id & 0xFFFFFF); /* Length is 3 octets */
/* Reason for redirect - unused, set to 129 */
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i);
ASN1_FIXUP(compstk, compsp, buffer, i);
if (pri_call_apdu_queue(apdubearer, Q931_FACILITY, buffer, i, NULL, NULL))
return -1;
if (q931_facility(apdubearer->pri, apdubearer)) {
pri_message(pri, "Could not schedule facility message for call %d\n", apdubearer->cr);
return -1;
}
return 0;
}
static int add_dms100_transfer_ability_apdu(struct pri *pri, q931_call *c)
{
int i = 0;
unsigned char buffer[256];
struct rose_component *comp = NULL, *compstk[10];
const unsigned char rlt_op_ind = RLT_OPERATION_IND;
int compsp = 0;
buffer[i++] = (Q932_PROTOCOL_ROSE); /* Note to self: DON'T set the EXT bit */
buffer[i++] = (0x80 | RLT_SERVICE_ID); /* Service Identifier octet */
ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
/* Invoke ID is set to the operation ID */
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind);
/* Operation Tag - basically the same as the invoke ID tag */
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind);
ASN1_FIXUP(compstk, compsp, buffer, i);
if (pri_call_apdu_queue(c, Q931_SETUP, buffer, i, NULL, NULL))
return -1;
else
return 0;
}
/* Sending callername information functions */ /* Sending callername information functions */
static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe) static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
{ {
@@ -943,13 +721,11 @@ static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS); buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
/* Interpretation component */ /* Interpretation component */
if (pri->switchtype == PRI_SWITCH_QSIG) {
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i); ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
ASN1_PUSH(compstk, compsp, comp); ASN1_PUSH(compstk, compsp, comp);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_FIXUP(compstk, compsp, buffer, i);
}
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
@@ -973,7 +749,7 @@ static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
} }
/* Now the APDU that contains the information that needs sent. /* Now the ADPu that contains the information that needs sent.
* We can reuse the buffer since the queue function doesn't * We can reuse the buffer since the queue function doesn't
* need it. */ * need it. */
@@ -986,13 +762,11 @@ static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS); buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
/* Interpretation component */ /* Interpretation component */
if (pri->switchtype == PRI_SWITCH_QSIG) {
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i); ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
ASN1_PUSH(compstk, compsp, comp); ASN1_PUSH(compstk, compsp, comp);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_FIXUP(compstk, compsp, buffer, i);
}
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
@@ -1029,7 +803,7 @@ static void mwi_activate_encode_cb(void *data)
return; return;
} }
int mwi_message_send(struct pri* pri, q931_call *call, struct pri_sr *req, int activate) extern int mwi_message_send(struct pri* pri, q931_call *call, struct pri_sr *req, int activate)
{ {
int i = 0; int i = 0;
unsigned char buffer[255] = ""; unsigned char buffer[255] = "";
@@ -1079,12 +853,15 @@ int mwi_message_send(struct pri* pri, q931_call *call, struct pri_sr *req, int a
/* End MWI */ /* End MWI */
/* EECT functions */ /* EECT functions */
int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2) extern int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
{ {
/* Did all the tests to see if we're on the same PRI and
* are on a compatible switchtype */
/* TODO */
int i = 0; int i = 0;
int res = 0; int res = 0;
unsigned char buffer[255] = ""; unsigned char buffer[255] = "";
short call_reference = c2->cr ^ 0x8000; /* Let's do the trickery to make sure the flag is correct */ unsigned short call_reference = c2->cr;
struct rose_component *comp = NULL, *compstk[10]; struct rose_component *comp = NULL, *compstk[10];
int compsp = 0; int compsp = 0;
static unsigned char op_tag[] = { static unsigned char op_tag[] = {
@@ -1097,7 +874,16 @@ int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
0x08, 0x08,
}; };
buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE); buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
/* Interpretation component */
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i);
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i); ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
ASN1_PUSH(compstk, compsp, comp); ASN1_PUSH(compstk, compsp, comp);
@@ -1117,7 +903,7 @@ int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, i, NULL, NULL); res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, i, NULL, NULL);
if (res) { if (res) {
pri_message(pri, "Could not queue APDU in facility message\n"); pri_message(pri, "Could not queue ADPU in facility message\n");
return -1; return -1;
} }
@@ -1324,7 +1110,7 @@ static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long cha
/* code below is untested */ /* code below is untested */
res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL); res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL);
if (res) { if (res) {
pri_message(pri, "Could not queue APDU in facility message\n"); pri_message(pri, "Could not queue ADPU in facility message\n");
return -1; return -1;
} }
@@ -1340,201 +1126,7 @@ static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long cha
} }
/* End AOC */ /* End AOC */
int rose_reject_decode(struct pri *pri, q931_call *call, unsigned char *data, int len) extern int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
{
int i = 0;
int problemtag = -1;
int problem = -1;
int invokeidvalue = -1;
unsigned char *vdata = data;
struct rose_component *comp = NULL;
char *problemtagstr, *problemstr;
do {
/* Invoke ID stuff */
GET_COMPONENT(comp, i, vdata, len);
CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
ASN1_GET_INTEGER(comp, invokeidvalue);
NEXT_COMPONENT(comp, i);
GET_COMPONENT(comp, i, vdata, len);
problemtag = comp->type;
problem = comp->data[0];
if (pri->switchtype == PRI_SWITCH_DMS100) {
switch (problemtag) {
case 0x80:
problemtagstr = "General problem";
break;
case 0x81:
problemtagstr = "Invoke problem";
break;
case 0x82:
problemtagstr = "Return result problem";
break;
case 0x83:
problemtagstr = "Return error problem";
break;
default:
problemtagstr = "Unknown";
}
switch (problem) {
case 0x00:
problemstr = "Unrecognized component";
break;
case 0x01:
problemstr = "Mistyped component";
break;
case 0x02:
problemstr = "Badly structured component";
break;
default:
problemstr = "Unknown";
}
pri_error(pri, "ROSE REJECT:\n");
pri_error(pri, "\tINVOKE ID: 0x%X\n", invokeidvalue);
pri_error(pri, "\tPROBLEM TYPE: %s (0x%x)\n", problemtagstr, problemtag);
pri_error(pri, "\tPROBLEM: %s (0x%x)\n", problemstr, problem);
return 0;
} else {
pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
return -1;
}
} while(0);
return -1;
}
int rose_return_error_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
{
int i = 0;
int errorvalue = -1;
int invokeidvalue = -1;
unsigned char *vdata = data;
struct rose_component *comp = NULL;
char *invokeidstr, *errorstr;
do {
/* Invoke ID stuff */
GET_COMPONENT(comp, i, vdata, len);
CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
ASN1_GET_INTEGER(comp, invokeidvalue);
NEXT_COMPONENT(comp, i);
GET_COMPONENT(comp, i, vdata, len);
CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if second component in return error is 0x%x\n");
ASN1_GET_INTEGER(comp, errorvalue);
if (pri->switchtype == PRI_SWITCH_DMS100) {
switch (invokeidvalue) {
case RLT_OPERATION_IND:
invokeidstr = "RLT_OPERATION_IND";
break;
case RLT_THIRD_PARTY:
invokeidstr = "RLT_THIRD_PARTY";
break;
default:
invokeidstr = "Unknown";
}
switch (errorvalue) {
case 0x10:
errorstr = "RLT Bridge Fail";
break;
case 0x11:
errorstr = "RLT Call ID Not Found";
break;
case 0x12:
errorstr = "RLT Not Allowed";
break;
case 0x13:
errorstr = "RLT Switch Equip Congs";
break;
default:
errorstr = "Unknown";
}
pri_error(pri, "ROSE RETURN ERROR:\n");
pri_error(pri, "\tOPERATION: %s\n", invokeidstr);
pri_error(pri, "\tERROR: %s\n", errorstr);
return 0;
} else {
pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
return -1;
}
} while(0);
return -1;
}
int rose_return_result_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
{
int i = 0;
int operationidvalue = -1;
int invokeidvalue = -1;
unsigned char *vdata = data;
struct rose_component *comp = NULL;
do {
/* Invoke ID stuff */
GET_COMPONENT(comp, i, vdata, len);
CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
ASN1_GET_INTEGER(comp, invokeidvalue);
NEXT_COMPONENT(comp, i);
if (pri->switchtype == PRI_SWITCH_DMS100) {
switch (invokeidvalue) {
case RLT_THIRD_PARTY:
if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Successfully completed RLT transfer!\n");
return 0;
case RLT_OPERATION_IND:
if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Received RLT_OPERATION_IND\n");
/* Have to take out the rlt_call_id */
GET_COMPONENT(comp, i, vdata, len);
CHECK_COMPONENT(comp, ASN1_SEQUENCE, "Protocol error detected in parsing RLT_OPERATION_IND return result!\n");
/* Traverse the contents of this sequence */
/* First is the Operation Value */
SUB_COMPONENT(comp, i);
GET_COMPONENT(comp, i, vdata, len);
CHECK_COMPONENT(comp, ASN1_INTEGER, "RLT_OPERATION_IND should be of type ASN1_INTEGER!\n");
ASN1_GET_INTEGER(comp, operationidvalue);
if (operationidvalue != RLT_OPERATION_IND) {
pri_message(pri, "Invalid Operation ID value (0x%x) in return result!\n", operationidvalue);
return -1;
}
/* Next is the Call ID */
NEXT_COMPONENT(comp, i);
GET_COMPONENT(comp, i, vdata, len);
CHECK_COMPONENT(comp, ASN1_TAG_0, "Error check failed on Call ID!\n");
ASN1_GET_INTEGER(comp, call->rlt_call_id);
/* We have enough data to transfer the call */
call->transferable = 1;
return 0;
default:
pri_message(pri, "Could not parse invoke of type 0x%x!\n", invokeidvalue);
return -1;
}
} else {
pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
return -1;
}
} while(0);
return -1;
}
int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
{ {
int i = 0; int i = 0;
int operation_tag; int operation_tag;
@@ -1544,17 +1136,13 @@ int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char *data, in
do { do {
/* Invoke ID stuff */ /* Invoke ID stuff */
GET_COMPONENT(comp, i, vdata, len); GET_COMPONENT(comp, i, vdata, len);
#if 0
CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n"); CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
#endif
invokeid = comp; invokeid = comp;
NEXT_COMPONENT(comp, i); NEXT_COMPONENT(comp, i);
/* Operation Tag */ /* Operation Tag */
GET_COMPONENT(comp, i, vdata, len); GET_COMPONENT(comp, i, vdata, len);
#if 0
CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if second ROSE component is of type 0x%x\n"); CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if second ROSE component is of type 0x%x\n");
#endif
operationid = comp; operationid = comp;
ASN1_GET_INTEGER(comp, operation_tag); ASN1_GET_INTEGER(comp, operation_tag);
NEXT_COMPONENT(comp, i); NEXT_COMPONENT(comp, i);
@@ -1653,7 +1241,7 @@ int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char *data, in
return -1; return -1;
} }
int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data) extern int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data)
{ {
struct apdu_event *cur = NULL; struct apdu_event *cur = NULL;
struct apdu_event *new_event = NULL; struct apdu_event *new_event = NULL;
@@ -1687,7 +1275,7 @@ int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_l
return 0; return 0;
} }
int pri_call_apdu_queue_cleanup(q931_call *call) extern int pri_call_apdu_queue_cleanup(q931_call *call)
{ {
struct apdu_event *cur_event = NULL, *free_event = NULL; struct apdu_event *cur_event = NULL, *free_event = NULL;
@@ -1705,7 +1293,7 @@ int pri_call_apdu_queue_cleanup(q931_call *call)
return 0; return 0;
} }
int pri_call_add_standard_apdus(struct pri *pri, q931_call *call) extern int pri_call_add_standard_apdus(struct pri *pri, q931_call *call)
{ {
if (!pri->sendfacility) if (!pri->sendfacility)
return 0; return 0;
@@ -1717,7 +1305,6 @@ int pri_call_add_standard_apdus(struct pri *pri, q931_call *call)
return 0; return 0;
} }
#if 0
if (pri->localtype == PRI_NETWORK) { if (pri->localtype == PRI_NETWORK) {
switch (pri->switchtype) { switch (pri->switchtype) {
case PRI_SWITCH_NI2: case PRI_SWITCH_NI2:
@@ -1737,16 +1324,6 @@ int pri_call_add_standard_apdus(struct pri *pri, q931_call *call)
} }
return 0; return 0;
} }
#else
if (pri->switchtype == PRI_SWITCH_NI2)
add_callername_facility_ies(pri, call, (pri->localtype == PRI_CPE));
#endif
if ((pri->switchtype == PRI_SWITCH_DMS100) && (pri->localtype == PRI_CPE)) {
add_dms100_transfer_ability_apdu(pri, call);
}
return 0; return 0;
} }

View File

@@ -135,11 +135,6 @@
#define Q932_TON_SUBSCRIBER 0x04 #define Q932_TON_SUBSCRIBER 0x04
#define Q932_TON_ABBREVIATED 0x06 #define Q932_TON_ABBREVIATED 0x06
/* RLT related Operations */
#define RLT_SERVICE_ID 0x3e
#define RLT_OPERATION_IND 0x01
#define RLT_THIRD_PARTY 0x02
struct rose_component { struct rose_component {
u_int8_t type; u_int8_t type;
u_int8_t len; u_int8_t len;
@@ -151,7 +146,7 @@ struct rose_component {
break; \ break; \
(component) = (struct rose_component*)&((ptr)[idx]); \ (component) = (struct rose_component*)&((ptr)[idx]); \
if ((idx)+(component)->len+2 > (length)) { \ if ((idx)+(component)->len+2 > (length)) { \
if ((component)->len != ASN1_LEN_INDEF) \ if ((component)->len != 128) \
pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \ pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \
} }
/* /*
@@ -174,7 +169,6 @@ struct rose_component {
#define CHECK_COMPONENT(component, comptype, message) \ #define CHECK_COMPONENT(component, comptype, message) \
if ((component)->type && ((component)->type & ASN1_TYPE_MASK) != (comptype)) { \ if ((component)->type && ((component)->type & ASN1_TYPE_MASK) != (comptype)) { \
pri_message(pri, (message), (component)->type); \ pri_message(pri, (message), (component)->type); \
asn1_dump(pri, (component), (component)->len+2); \
break; \ break; \
} }
@@ -235,48 +229,35 @@ struct rose_component {
(stack)[(stackpointer)]->len = (unsigned char *)&((data)[(idx)]) - (unsigned char *)(stack)[(stackpointer)] - 2; \ (stack)[(stackpointer)]->len = (unsigned char *)&((data)[(idx)]) - (unsigned char *)(stack)[(stackpointer)] - 2; \
} while (0) } while (0)
/* Decoder for the invoke ROSE component */ /* Decoder for the invoke part of a ROSE request */
int rose_invoke_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len); extern int rose_invoke_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
/* Decoder for the return result ROSE component */ extern int asn1_copy_string(char * buf, int buflen, struct rose_component *comp);
int rose_return_result_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
/* Decoder for the return error ROSE component */ extern int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len);
int rose_return_error_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
/* Decoder for the reject ROSE component */
int rose_reject_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
int asn1_copy_string(char * buf, int buflen, struct rose_component *comp);
int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len);
/* Get Name types from ASN.1 */ /* Get Name types from ASN.1 */
int asn1_name_decode(void * data, int len, char *namebuf, int buflen); extern int asn1_name_decode(void * data, int len, char *namebuf, int buflen);
int typeofnumber_from_q931(struct pri *pri, int ton); extern int typeofnumber_from_q931(struct pri *pri, int ton);
int redirectingreason_from_q931(struct pri *pri, int redirectingreason); extern int redirectingreason_from_q931(struct pri *pri, int redirectingreason);
/* Queues an MWI apdu on a the given call */ /* Queues an MWI apdu on a the given call */
int mwi_message_send(struct pri *pri, q931_call *call, struct pri_sr *req, int activate); extern int mwi_message_send(struct pri *pri, q931_call *call, struct pri_sr *req, int activate);
/* starts a 2BCT */ /* starts a 2BCT */
int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2); extern int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2); /* Use this function to queue a facility-IE born ADPU onto a call
/* Use this function to queue a facility-IE born APDU onto a call
* call is the call to use, messagetype is any one of the Q931 messages, * call is the call to use, messagetype is any one of the Q931 messages,
* apdu is the apdu data, apdu_len is the length of the apdu data */ * apdu is the apdu data, apdu_len is the length of the apdu data */
int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data); extern int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data);
/* Used by q931.c to cleanup the apdu queue upon destruction of a call */ /* Used by q931.c to cleanup the apdu queue upon destruction of a call */
int pri_call_apdu_queue_cleanup(q931_call *call); extern int pri_call_apdu_queue_cleanup(q931_call *call);
/* Adds the "standard" APDUs to a call */ /* Adds the "standard" ADPUs to a call */
int pri_call_add_standard_apdus(struct pri *pri, q931_call *call); extern int pri_call_add_standard_apdus(struct pri *pri, q931_call *call);
int asn1_dump(struct pri *pri, void *comp, int len);
#endif /* _PRI_FACILITY_H */ #endif /* _PRI_FACILITY_H */

View File

@@ -25,12 +25,8 @@
#ifndef _PRI_INTERNAL_H #ifndef _PRI_INTERNAL_H
#define _PRI_INTERNAL_H #define _PRI_INTERNAL_H
#include <stddef.h>
#include <sys/time.h> #include <sys/time.h>
#define DBGHEAD __FILE__ ":%d %s: "
#define DBGINFO __LINE__,__PRETTY_FUNCTION__
struct pri_sched { struct pri_sched {
struct timeval when; struct timeval when;
void (*callback)(void *data); void (*callback)(void *data);
@@ -133,8 +129,7 @@ struct pri_sr {
int redirectingpres; int redirectingpres;
int redirectingreason; int redirectingreason;
int justsignalling; int justsignalling;
const char *useruserinfo; char *useruserinfo;
int transferable;
}; };
/* Internal switch types */ /* Internal switch types */
@@ -211,7 +206,7 @@ struct q931_call {
char callernum[256]; char callernum[256];
char callername[256]; char callername[256];
char keypad_digits[64]; /* Buffer for digits that come in KEYPAD_FACILITY */ char digitbuf[64]; /* Buffer for digits that come in KEYPAD_FACILITY */
int ani2; /* ANI II */ int ani2; /* ANI II */
@@ -244,9 +239,6 @@ struct q931_call {
long aoc_units; /* Advice of Charge Units */ long aoc_units; /* Advice of Charge Units */
struct apdu_event *apdus; /* APDU queue for call */ struct apdu_event *apdus; /* APDU queue for call */
int transferable;
unsigned int rlt_call_id; /* RLT call id */
}; };
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data); extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);

View File

@@ -243,10 +243,6 @@ typedef struct q931_ie {
/* EuroISDN */ /* EuroISDN */
#define Q931_SENDING_COMPLETE 0xa1 #define Q931_SENDING_COMPLETE 0xa1
/* Q.SIG specific */
#define QSIG_IE_TRANSIT_COUNT 0x31
extern int q931_receive(struct pri *pri, q931_h *h, int len); extern int q931_receive(struct pri *pri, q931_h *h, int len);
extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info); extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
@@ -261,8 +257,6 @@ extern int q931_setup_ack(struct pri *pri, q931_call *call, int channel, int non
extern int q931_information(struct pri *pri, q931_call *call, char digit); extern int q931_information(struct pri *pri, q931_call *call, char digit);
extern int q931_keypad_facility(struct pri *pri, q931_call *call, char *digits);
extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn); extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
extern int q931_release(struct pri *pri, q931_call *call, int cause); extern int q931_release(struct pri *pri, q931_call *call, int cause);
@@ -286,6 +280,4 @@ extern void q931_dump(struct pri *pri, q931_h *h, int len, int txrx);
extern void __q931_destroycall(struct pri *pri, q931_call *c); extern void __q931_destroycall(struct pri *pri, q931_call *c);
extern void q931_dl_indication(struct pri *pri, int event);
#endif #endif

View File

@@ -37,7 +37,11 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/types.h> #include <sys/types.h>
#include <zaptel/zaptel.h> #if defined(__linux__)
#include <linux/zaptel.h>
#elif defined(__FreeBSD__)
#include <zaptel.h>
#endif
#include "libpri.h" #include "libpri.h"
#include "pri_q921.h" #include "pri_q921.h"
#include "pri_q931.h" #include "pri_q931.h"

View File

@@ -40,7 +40,11 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/time.h> #include <sys/time.h>
#include <zaptel/zaptel.h> #if defined(__linux__)
#include <linux/zaptel.h>
#elif defined(__FreeBSD__)
#include <zaptel.h>
#endif
#include <zap.h> #include <zap.h>
#include "libpri.h" #include "libpri.h"

84
q921.c
View File

@@ -80,7 +80,7 @@ static int q921_transmit(struct pri *pri, q921_h *h, int len)
pri->q921_txcount++; pri->q921_txcount++;
#endif #endif
/* Just send it raw */ /* Just send it raw */
if (pri->debug & (PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW)) if (pri->debug & PRI_DEBUG_Q921_DUMP)
q921_dump(pri, h, len, pri->debug & PRI_DEBUG_Q921_RAW, 1); q921_dump(pri, h, len, pri->debug & PRI_DEBUG_Q921_RAW, 1);
/* Write an extra two bytes for the FCS */ /* Write an extra two bytes for the FCS */
res = pri->write_func ? pri->write_func(pri, h, len + 2) : 0; res = pri->write_func ? pri->write_func(pri, h, len + 2) : 0;
@@ -111,7 +111,7 @@ static void q921_send_ua(struct pri *pri, int pfbit)
pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype); pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
return; return;
} }
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP)) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "Sending Unnumbered Acknowledgement\n"); pri_message(pri, "Sending Unnumbered Acknowledgement\n");
q921_transmit(pri, &h, 3); q921_transmit(pri, &h, 3);
} }
@@ -143,11 +143,9 @@ static void q921_send_sabme(void *vpri, int now)
pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype); pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
return; return;
} }
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP)) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "Sending Set Asynchronous Balanced Mode Extended\n"); pri_message(pri, "Sending Set Asynchronous Balanced Mode Extended\n");
q921_transmit(pri, &h, 3); q921_transmit(pri, &h, 3);
if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_AWAITING_ESTABLISH)
pri_message(pri, DBGHEAD "q921_state now is Q921_AWAITING_ESTABLISH\n", DBGINFO);
pri->q921_state = Q921_AWAITING_ESTABLISH; pri->q921_state = Q921_AWAITING_ESTABLISH;
} }
@@ -168,7 +166,7 @@ static int q921_ack_packet(struct pri *pri, int num)
prev->next = f->next; prev->next = f->next;
else else
pri->txqueue = f->next; pri->txqueue = f->next;
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue ? pri->txqueue->h.n_s : -1); pri_message(pri, "-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue ? pri->txqueue->h.n_s : -1);
/* Update v_a */ /* Update v_a */
pri->v_a = num; pri->v_a = num;
@@ -182,7 +180,7 @@ static int q921_ack_packet(struct pri *pri, int num)
while(f) { while(f) {
if (!f->transmitted) { if (!f->transmitted) {
/* Send it now... */ /* Send it now... */
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Finally transmitting %d, since window opened up\n", f->h.n_s); pri_message(pri, "-- Finally transmitting %d, since window opened up\n", f->h.n_s);
f->transmitted++; f->transmitted++;
pri->windowlen++; pri->windowlen++;
@@ -208,7 +206,7 @@ static void reschedule_t203(struct pri *pri)
{ {
if (pri->t203_timer) { if (pri->t203_timer) {
pri_schedule_del(pri, pri->t203_timer); pri_schedule_del(pri, pri->t203_timer);
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Restarting T203 counter\n"); pri_message(pri, "-- Restarting T203 counter\n");
/* Nothing to transmit, start the T203 counter instead */ /* Nothing to transmit, start the T203 counter instead */
pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri); pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
@@ -231,31 +229,31 @@ static pri_event *q921_ack_rx(struct pri *pri, int ack)
return ev; return ev;
} }
/* Cancel each packet as necessary */ /* Cancel each packet as necessary */
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- ACKing all packets from %d to (but not including) %d\n", pri->v_a, ack); pri_message(pri, "-- ACKing all packets from %d to (but not including) %d\n", pri->v_a, ack);
for (x=pri->v_a; x != ack; Q921_INC(x)) for (x=pri->v_a; x != ack; Q921_INC(x))
cnt += q921_ack_packet(pri, x); cnt += q921_ack_packet(pri, x);
if (!pri->txqueue) { if (!pri->txqueue) {
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Since there was nothing left, stopping T200 counter\n"); pri_message(pri, "-- Since there was nothing left, stopping T200 counter\n");
/* Something was ACK'd. Stop T200 counter */ /* Something was ACK'd. Stop T200 counter */
pri_schedule_del(pri, pri->t200_timer); pri_schedule_del(pri, pri->t200_timer);
pri->t200_timer = 0; pri->t200_timer = 0;
} }
if (pri->t203_timer) { if (pri->t203_timer) {
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Stopping T203 counter since we got an ACK\n"); pri_message(pri, "-- Stopping T203 counter since we got an ACK\n");
pri_schedule_del(pri, pri->t203_timer); pri_schedule_del(pri, pri->t203_timer);
pri->t203_timer = 0; pri->t203_timer = 0;
} }
if (pri->txqueue) { if (pri->txqueue) {
/* Something left to transmit, Start the T200 counter again if we stopped it */ /* Something left to transmit, Start the T200 counter again if we stopped it */
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue->h.n_s); pri_message(pri, "-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue->h.n_s);
if (!pri->t200_timer) if (!pri->t200_timer)
pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
} else { } else {
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Nothing left, starting T203 counter\n"); pri_message(pri, "-- Nothing left, starting T203 counter\n");
/* Nothing to transmit, start the T203 counter instead */ /* Nothing to transmit, start the T203 counter instead */
pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri); pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
@@ -283,7 +281,7 @@ static void q921_reject(struct pri *pri, int pf)
pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype); pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
return; return;
} }
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "Sending Reject (%d)\n", pri->v_r); pri_message(pri, "Sending Reject (%d)\n", pri->v_r);
pri->sentrej = 1; pri->sentrej = 1;
q921_transmit(pri, &h, 4); q921_transmit(pri, &h, 4);
@@ -315,7 +313,7 @@ static void q921_rr(struct pri *pri, int pbit, int cmd) {
return; return;
} }
pri->v_na = pri->v_r; /* Make a note that we've already acked this */ pri->v_na = pri->v_r; /* Make a note that we've already acked this */
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "Sending Receiver Ready (%d)\n", pri->v_r); pri_message(pri, "Sending Receiver Ready (%d)\n", pri->v_r);
q921_transmit(pri, &h, 4); q921_transmit(pri, &h, 4);
} }
@@ -325,7 +323,7 @@ static void t200_expire(void *vpri)
struct pri *pri = vpri; struct pri *pri = vpri;
if (pri->txqueue) { if (pri->txqueue) {
/* Retransmit first packet in the queue, setting the poll bit */ /* Retransmit first packet in the queue, setting the poll bit */
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- T200 counter expired, What to do...\n"); pri_message(pri, "-- T200 counter expired, What to do...\n");
/* Force Poll bit */ /* Force Poll bit */
pri->txqueue->h.p_f = 1; pri->txqueue->h.p_f = 1;
@@ -337,23 +335,21 @@ static void t200_expire(void *vpri)
/* Up to three retransmissions */ /* Up to three retransmissions */
if (pri->retrans < pri->timers[PRI_TIMER_N200]) { if (pri->retrans < pri->timers[PRI_TIMER_N200]) {
/* Reschedule t200_timer */ /* Reschedule t200_timer */
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Retransmitting %d bytes\n", pri->txqueue->len); pri_message(pri, "-- Retransmitting %d bytes\n", pri->txqueue->len);
if (pri->busy) if (pri->busy)
q921_rr(pri, 1, 1); q921_rr(pri, 1, 0);
else { else {
if (!pri->txqueue->transmitted) if (!pri->txqueue->transmitted)
pri_error(pri, "!! Not good - head of queue has not been transmitted yet\n"); pri_error(pri, "!! Not good - head of queue has not been transmitted yet\n");
q921_transmit(pri, (q921_h *)&pri->txqueue->h, pri->txqueue->len); q921_transmit(pri, (q921_h *)&pri->txqueue->h, pri->txqueue->len);
} }
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Rescheduling retransmission (%d)\n", pri->retrans); pri_message(pri, "-- Rescheduling retransmission (%d)\n", pri->retrans);
pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
} else { } else {
if (pri->debug & PRI_DEBUG_Q921_STATE) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Timeout occured, restarting PRI\n"); pri_message(pri, "-- Timeout occured, restarting PRI\n");
if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_LINK_CONNECTION_RELEASED)
pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_RELEASED\n",DBGINFO);
pri->q921_state = Q921_LINK_CONNECTION_RELEASED; pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
pri->t200_timer = 0; pri->t200_timer = 0;
q921_dchannel_down(pri); q921_dchannel_down(pri);
@@ -361,7 +357,7 @@ static void t200_expire(void *vpri)
pri->schedev = 1; pri->schedev = 1;
} }
} else if (pri->solicitfbit) { } else if (pri->solicitfbit) {
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Retrying poll with f-bit\n"); pri_message(pri, "-- Retrying poll with f-bit\n");
pri->retrans++; pri->retrans++;
if (pri->retrans < pri->timers[PRI_TIMER_N200]) { if (pri->retrans < pri->timers[PRI_TIMER_N200]) {
@@ -371,8 +367,6 @@ static void t200_expire(void *vpri)
} else { } else {
if (pri->debug & PRI_DEBUG_Q921_STATE) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Timeout occured, restarting PRI\n"); pri_message(pri, "-- Timeout occured, restarting PRI\n");
if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_LINK_CONNECTION_RELEASED)
pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_RELEASED\n", DBGINFO);
pri->q921_state = Q921_LINK_CONNECTION_RELEASED; pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
pri->t200_timer = 0; pri->t200_timer = 0;
q921_dchannel_down(pri); q921_dchannel_down(pri);
@@ -429,23 +423,23 @@ int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
q921_transmit(pri, (q921_h *)(&f->h), f->len); q921_transmit(pri, (q921_h *)(&f->h), f->len);
f->transmitted++; f->transmitted++;
} else { } else {
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "Delaying transmission of %d, window is %d/%d long\n", pri_message(pri, "Delaying transmission of %d, window is %d/%d long\n",
f->h.n_s, pri->windowlen, pri->window); f->h.n_s, pri->windowlen, pri->window);
} }
} }
if (pri->t203_timer) { if (pri->t203_timer) {
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "Stopping T_203 timer\n"); pri_message(pri, "Stopping T_203 timer\n");
pri_schedule_del(pri, pri->t203_timer); pri_schedule_del(pri, pri->t203_timer);
pri->t203_timer = 0; pri->t203_timer = 0;
} }
if (!pri->t200_timer) { if (!pri->t200_timer) {
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "Starting T_200 timer\n"); pri_message(pri, "Starting T_200 timer\n");
pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
} else } else
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "T_200 timer already going (%d)\n", pri->t200_timer); pri_message(pri, "T_200 timer already going (%d)\n", pri->t200_timer);
} else { } else {
@@ -459,7 +453,7 @@ static void t203_expire(void *vpri)
{ {
struct pri *pri = vpri; struct pri *pri = vpri;
if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) { if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) {
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "T203 counter expired, sending RR and scheduling T203 again\n"); pri_message(pri, "T203 counter expired, sending RR and scheduling T203 again\n");
/* Solicit an F-bit in the other's RR */ /* Solicit an F-bit in the other's RR */
pri->solicitfbit = 1; pri->solicitfbit = 1;
@@ -468,7 +462,7 @@ static void t203_expire(void *vpri)
/* Start timer T200 to resend our RR if we don't get it */ /* Start timer T200 to resend our RR if we don't get it */
pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
} else { } else {
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "T203 counter expired in weird state %d\n", pri->q921_state); pri_message(pri, "T203 counter expired in weird state %d\n", pri->q921_state);
pri->t203_timer = 0; pri->t203_timer = 0;
} }
@@ -660,16 +654,11 @@ static pri_event *q921_dchannel_up(struct pri *pri)
pri->sentrej = 0; pri->sentrej = 0;
/* Go into connection established state */ /* Go into connection established state */
if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED)
pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_ESTABLISHED\n", DBGINFO);
pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED; pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED;
/* Start the T203 timer */ /* Start the T203 timer */
pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri); pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
/* Notify Layer 3 */
q931_dl_indication(pri, PRI_EVENT_DCHAN_UP);
/* Report event that D-Channel is now up */ /* Report event that D-Channel is now up */
pri->ev.gen.e = PRI_EVENT_DCHAN_UP; pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
return &pri->ev; return &pri->ev;
@@ -680,9 +669,6 @@ static pri_event *q921_dchannel_down(struct pri *pri)
/* Reset counters, reset sabme timer etc */ /* Reset counters, reset sabme timer etc */
q921_reset(pri); q921_reset(pri);
/* Notify Layer 3 */
q931_dl_indication(pri, PRI_EVENT_DCHAN_DOWN);
/* Report event that D-Channel is now up */ /* Report event that D-Channel is now up */
pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN; pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
return &pri->ev; return &pri->ev;
@@ -705,8 +691,6 @@ void q921_reset(struct pri *pri)
pri->t200_timer = 0; pri->t200_timer = 0;
pri->busy = 0; pri->busy = 0;
pri->solicitfbit = 0; pri->solicitfbit = 0;
if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_LINK_CONNECTION_RELEASED)
pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_RELEASED\n", DBGINFO);
pri->q921_state = Q921_LINK_CONNECTION_RELEASED; pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
pri->retrans = 0; pri->retrans = 0;
pri->sentrej = 0; pri->sentrej = 0;
@@ -755,10 +739,10 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
if (h->s.p_f) { if (h->s.p_f) {
/* If it's a p/f one then send back a RR in return with the p/f bit set */ /* If it's a p/f one then send back a RR in return with the p/f bit set */
if (pri->solicitfbit) { if (pri->solicitfbit) {
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Got RR response to our frame\n"); pri_message(pri, "-- Got RR response to our frame\n");
} else { } else {
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Unsolicited RR with P/F bit, responding\n"); pri_message(pri, "-- Unsolicited RR with P/F bit, responding\n");
q921_rr(pri, 1, 0); q921_rr(pri, 1, 0);
} }
@@ -767,7 +751,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
break; break;
case 1: case 1:
/* Receiver not ready */ /* Receiver not ready */
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Got receiver not ready\n"); pri_message(pri, "-- Got receiver not ready\n");
if(h->s.p_f) { if(h->s.p_f) {
/* Send RR if poll bit set */ /* Send RR if poll bit set */
@@ -777,7 +761,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
break; break;
case 2: case 2:
/* Just retransmit */ /* Just retransmit */
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r); pri_message(pri, "-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r);
if (h->s.p_f) { if (h->s.p_f) {
/* If it has the poll bit set, send an appropriate supervisory response */ /* If it has the poll bit set, send an appropriate supervisory response */
@@ -834,7 +818,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
if (h->u.p_f) { if (h->u.p_f) {
/* Section 5.7.1 says we should restart on receiving a DM response with the f-bit set to /* Section 5.7.1 says we should restart on receiving a DM response with the f-bit set to
one, but we wait T200 first */ one, but we wait T200 first */
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP)) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Got DM Mode from peer.\n"); pri_message(pri, "-- Got DM Mode from peer.\n");
/* Disconnected mode, try again after T200 */ /* Disconnected mode, try again after T200 */
ev = q921_dchannel_down(pri); ev = q921_dchannel_down(pri);
@@ -842,7 +826,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
return ev; return ev;
} else { } else {
if (pri->debug & PRI_DEBUG_Q921_DUMP) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Ignoring unsolicited DM with p/f set to 0\n"); pri_message(pri, "-- Ignoring unsolicited DM with p/f set to 0\n");
#if 0 #if 0
/* Requesting that we start */ /* Requesting that we start */
@@ -855,7 +839,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
} }
break; break;
case 2: case 2:
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP)) if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Got Disconnect from peer.\n"); pri_message(pri, "-- Got Disconnect from peer.\n");
/* Acknowledge */ /* Acknowledge */
q921_send_ua(pri, h->u.p_f); q921_send_ua(pri, h->u.p_f);
@@ -865,7 +849,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
case 3: case 3:
if (h->u.m2 == 3) { if (h->u.m2 == 3) {
/* SABME */ /* SABME */
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP)) { if (pri->debug & PRI_DEBUG_Q921_STATE) {
pri_message(pri, "-- Got SABME from %s peer.\n", h->h.c_r ? "network" : "cpe"); pri_message(pri, "-- Got SABME from %s peer.\n", h->h.c_r ? "network" : "cpe");
} }
if (h->h.c_r) { if (h->h.c_r) {
@@ -887,7 +871,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
} else if (h->u.m2 == 0) { } else if (h->u.m2 == 0) {
/* It's a UA */ /* It's a UA */
if (pri->q921_state == Q921_AWAITING_ESTABLISH) { if (pri->q921_state == Q921_AWAITING_ESTABLISH) {
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP)) { if (pri->debug & PRI_DEBUG_Q921_STATE) {
pri_message(pri, "-- Got UA from %s peer Link up.\n", h->h.c_r ? "cpe" : "network"); pri_message(pri, "-- Got UA from %s peer Link up.\n", h->h.c_r ? "cpe" : "network");
} }
return q921_dchannel_up(pri); return q921_dchannel_up(pri);
@@ -917,7 +901,7 @@ static pri_event *__q921_receive(struct pri *pri, q921_h *h, int len)
/* Discard FCS */ /* Discard FCS */
len -= 2; len -= 2;
if (!pri->master && pri->debug & (PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW)) if (!pri->master && pri->debug & PRI_DEBUG_Q921_DUMP)
q921_dump(pri, h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0); q921_dump(pri, h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0);
/* Check some reject conditions -- Start by rejecting improper ea's */ /* Check some reject conditions -- Start by rejecting improper ea's */

486
q931.c
View File

@@ -32,7 +32,6 @@
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <limits.h> #include <limits.h>
@@ -44,7 +43,7 @@ struct msgtype {
int mandies[MAX_MAND_IES]; int mandies[MAX_MAND_IES];
}; };
static struct msgtype msgs[] = { struct msgtype msgs[] = {
/* Call establishment messages */ /* Call establishment messages */
{ Q931_ALERTING, "ALERTING" }, { Q931_ALERTING, "ALERTING" },
{ Q931_CALL_PROCEEDING, "CALL PROCEEDING" }, { Q931_CALL_PROCEEDING, "CALL PROCEEDING" },
@@ -90,7 +89,7 @@ static struct msgtype msgs[] = {
{ NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE" }, { NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE" },
}; };
static struct msgtype causes[] = { struct msgtype causes[] = {
{ PRI_CAUSE_UNALLOCATED, "Unallocated (unassigned) number" }, { PRI_CAUSE_UNALLOCATED, "Unallocated (unassigned) number" },
{ PRI_CAUSE_NO_ROUTE_TRANSIT_NET, "No route to specified transmit network" }, { PRI_CAUSE_NO_ROUTE_TRANSIT_NET, "No route to specified transmit network" },
{ PRI_CAUSE_NO_ROUTE_DESTINATION, "No route to destination" }, { PRI_CAUSE_NO_ROUTE_DESTINATION, "No route to destination" },
@@ -120,11 +119,9 @@ static struct msgtype causes[] = {
{ PRI_CAUSE_BEARERCAPABILITY_NOTAUTH, "Bearer capability not authorized" }, { PRI_CAUSE_BEARERCAPABILITY_NOTAUTH, "Bearer capability not authorized" },
{ PRI_CAUSE_BEARERCAPABILITY_NOTAVAIL, "Bearer capability not available" }, { PRI_CAUSE_BEARERCAPABILITY_NOTAVAIL, "Bearer capability not available" },
{ PRI_CAUSE_BEARERCAPABILITY_NOTIMPL, "Bearer capability not implemented" }, { PRI_CAUSE_BEARERCAPABILITY_NOTIMPL, "Bearer capability not implemented" },
{ PRI_CAUSE_SERVICEOROPTION_NOTAVAIL, "Service or option not available, unspecified" },
{ PRI_CAUSE_CHAN_NOT_IMPLEMENTED, "Channel not implemented" }, { PRI_CAUSE_CHAN_NOT_IMPLEMENTED, "Channel not implemented" },
{ PRI_CAUSE_FACILITY_NOT_IMPLEMENTED, "Facility not implemented" }, { PRI_CAUSE_FACILITY_NOT_IMPLEMENTED, "Facility not implemented" },
{ PRI_CAUSE_INVALID_CALL_REFERENCE, "Invalid call reference value" }, { PRI_CAUSE_INVALID_CALL_REFERENCE, "Invalid call reference value" },
{ PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST, "Identified channel does not exist" },
{ PRI_CAUSE_INCOMPATIBLE_DESTINATION, "Incompatible destination" }, { PRI_CAUSE_INCOMPATIBLE_DESTINATION, "Incompatible destination" },
{ PRI_CAUSE_INVALID_MSG_UNSPECIFIED, "Invalid message unspecified" }, { PRI_CAUSE_INVALID_MSG_UNSPECIFIED, "Invalid message unspecified" },
{ PRI_CAUSE_MANDATORY_IE_MISSING, "Mandatory information element is missing" }, { PRI_CAUSE_MANDATORY_IE_MISSING, "Mandatory information element is missing" },
@@ -139,7 +136,7 @@ static struct msgtype causes[] = {
{ PRI_CAUSE_INTERWORKING, "Interworking, unspecified" }, { PRI_CAUSE_INTERWORKING, "Interworking, unspecified" },
}; };
static struct msgtype facilities[] = { struct msgtype facilities[] = {
{ PRI_NSF_SID_PREFERRED, "CPN (SID) preferred" }, { PRI_NSF_SID_PREFERRED, "CPN (SID) preferred" },
{ PRI_NSF_ANI_PREFERRED, "BN (ANI) preferred" }, { PRI_NSF_ANI_PREFERRED, "BN (ANI) preferred" },
{ PRI_NSF_SID_ONLY, "CPN (SID) only" }, { PRI_NSF_SID_ONLY, "CPN (SID) only" },
@@ -216,18 +213,6 @@ static char *msg2str(int msg);
#define FUNC_RECV(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len) #define FUNC_RECV(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
#define FUNC_SEND(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len, int order) #define FUNC_SEND(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
#if 1
/* Update call state with transition trace. */
#define UPDATE_OURCALLSTATE(pri,c,newstate) do {\
if (pri->debug & (PRI_DEBUG_Q931_STATE) && c->ourcallstate != newstate) \
pri_message(pri, DBGHEAD "call %d on channel %d enters state %d (%s)\n", DBGINFO, \
c->cr, c->channelno, newstate, callstate2str(newstate)); \
c->ourcallstate = newstate; \
} while (0)
#else
/* Update call state with no trace. */
#define UPDATE_OURCALLSTATE(pri,c,newstate) c->ourcallstate = newstate
#endif
struct ie { struct ie {
/* Maximal count of same IEs at the message (0 - any, 1..n - limited) */ /* Maximal count of same IEs at the message (0 - any, 1..n - limited) */
@@ -418,7 +403,7 @@ static FUNC_DUMP(dump_channel_id)
"No channel selected", "As indicated in following octets", "Reserved","Any channel selected" "No channel selected", "As indicated in following octets", "Reserved","Any channel selected"
}; };
pri_message(pri, "%c Channel ID (len=%2d) [ Ext: %d IntID: %s %s Spare: %d %s Dchan: %d\n", pri_message(pri, "%c Channel ID (len=%2d) [ Ext: %d IntID: %s, %s Spare: %d, %s Dchan: %d\n",
prefix, len, (ie->data[0] & 0x80) ? 1 : 0, (ie->data[0] & 0x40) ? "Explicit" : "Implicit", prefix, len, (ie->data[0] & 0x80) ? 1 : 0, (ie->data[0] & 0x40) ? "Explicit" : "Implicit",
(ie->data[0] & 0x20) ? "PRI" : "Other", (ie->data[0] & 0x10) ? 1 : 0, (ie->data[0] & 0x20) ? "PRI" : "Other", (ie->data[0] & 0x10) ? 1 : 0,
(ie->data[0] & 0x08) ? "Exclusive" : "Preferred", (ie->data[0] & 0x04) ? 1 : 0); (ie->data[0] & 0x08) ? "Exclusive" : "Preferred", (ie->data[0] & 0x04) ? 1 : 0);
@@ -548,7 +533,7 @@ static char *l12str(int proto)
{ PRI_LAYER_1_ALAW, "A-Law" }, { PRI_LAYER_1_ALAW, "A-Law" },
{ PRI_LAYER_1_G721, "G.721 ADPCM" }, { PRI_LAYER_1_G721, "G.721 ADPCM" },
{ PRI_LAYER_1_G722_G725, "G.722/G.725 7kHz Audio" }, { PRI_LAYER_1_G722_G725, "G.722/G.725 7kHz Audio" },
{ PRI_LAYER_1_H223_H245, "H.223 and H.245" }, /* Recommendation Q.931(05/98) page 60) */ { PRI_LAYER_1_G7XX_384K, "G.7xx 384k Video" },
{ PRI_LAYER_1_NON_ITU_ADAPT, "Non-ITU Rate Adaption" }, { PRI_LAYER_1_NON_ITU_ADAPT, "Non-ITU Rate Adaption" },
{ PRI_LAYER_1_V120_RATE_ADAPT, "V.120 Rate Adaption" }, { PRI_LAYER_1_V120_RATE_ADAPT, "V.120 Rate Adaption" },
{ PRI_LAYER_1_X31_RATE_ADAPT, "X.31 Rate Adaption" }, { PRI_LAYER_1_X31_RATE_ADAPT, "X.31 Rate Adaption" },
@@ -662,8 +647,7 @@ static FUNC_SEND(transmit_bearer_capability)
} }
ie->data[0] = 0x80 | tc; ie->data[0] = 0x80 | tc;
ie->data[1] = call->transmoderate | 0x80; ie->data[1] = call->transmoderate | 0x80;
if ( (tc & PRI_TRANS_CAP_DIGITAL) && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) && if ((tc & PRI_TRANS_CAP_DIGITAL)&&(pri->switchtype == PRI_SWITCH_EUROISDN_E1)) {
(call->transmoderate == TRANS_MODE_PACKET) ) {
/* Apparently EuroISDN switches don't seem to like user layer 2/3 */ /* Apparently EuroISDN switches don't seem to like user layer 2/3 */
return 4; return 4;
} }
@@ -752,7 +736,7 @@ char *pri_pres2str(int pres)
static void q931_get_number(unsigned char *num, int maxlen, unsigned char *src, int len) static void q931_get_number(unsigned char *num, int maxlen, unsigned char *src, int len)
{ {
if ((len < 0) || (len > maxlen - 1)) { if (len > maxlen - 1) {
num[0] = 0; num[0] = 0;
return; return;
} }
@@ -796,7 +780,7 @@ static FUNC_DUMP(dump_calling_party_number)
static FUNC_DUMP(dump_calling_party_subaddr) static FUNC_DUMP(dump_calling_party_subaddr)
{ {
unsigned char cnum[256]; unsigned char cnum[256];
q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3); q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
pri_message(pri, "%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n", pri_message(pri, "%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
prefix, len, ie->data[0] >> 7, prefix, len, ie->data[0] >> 7,
subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4, subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
@@ -905,7 +889,7 @@ static FUNC_DUMP(dump_redirecting_subaddr)
static FUNC_RECV(receive_calling_party_subaddr) static FUNC_RECV(receive_calling_party_subaddr)
{ {
/* copy digits to call->callingsubaddr */ /* copy digits to call->callingsubaddr */
q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 1, len - 3); q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 2, len - 4);
return 0; return 0;
} }
@@ -1073,12 +1057,8 @@ static FUNC_RECV(receive_display)
static FUNC_SEND(transmit_display) static FUNC_SEND(transmit_display)
{ {
int i; int i;
if ((pri->switchtype != PRI_SWITCH_NI1) && (pri->switchtype != PRI_SWITCH_QSIG)
if ((pri->switchtype == PRI_SWITCH_QSIG) || && *call->callername) {
((pri->switchtype == PRI_SWITCH_EUROISDN_E1) && (pri->localtype == PRI_CPE)) ||
!call->callername[0])
return 0;
i = 0; i = 0;
if(pri->switchtype != PRI_SWITCH_EUROISDN_E1) { if(pri->switchtype != PRI_SWITCH_EUROISDN_E1) {
ie->data[0] = 0xb1; ie->data[0] = 0xb1;
@@ -1087,6 +1067,8 @@ static FUNC_SEND(transmit_display)
memcpy(ie->data + i, call->callername, strlen(call->callername)); memcpy(ie->data + i, call->callername, strlen(call->callername));
return 2 + i + strlen(call->callername); return 2 + i + strlen(call->callername);
} }
return 0;
}
static FUNC_RECV(receive_progress_indicator) static FUNC_RECV(receive_progress_indicator)
{ {
@@ -1136,21 +1118,22 @@ static FUNC_SEND(transmit_facility)
int i = 0; int i = 0;
for (tmp = call->apdus; tmp; tmp = tmp->next) { for (tmp = call->apdus; tmp; tmp = tmp->next) {
if ((tmp->message == msgtype) && !tmp->sent) if (tmp->message == msgtype)
break; break;
} }
if (!tmp) /* No APDU found */ if (!tmp) /* No APDU found */
return 0; return 0;
if (tmp->apdu_len > 235) { /* TODO: find out how much space we can use */ if (tmp->apdu_len > 235) { /* TODO: find out how much sapce we can use */
pri_message(pri, "Requested APDU (%d bytes) is too long\n", tmp->apdu_len); pri_message(pri, "Requested ADPU (%d bytes) is too long\n", tmp->apdu_len);
return 0; return 0;
} }
memcpy(&ie->data[i], tmp->apdu, tmp->apdu_len); memcpy(ie->data, tmp->apdu, tmp->apdu_len);
i += tmp->apdu_len; i += tmp->apdu_len;
tmp->sent = 1;
return i + 2; return i + 2;
} }
@@ -1191,6 +1174,10 @@ static FUNC_RECV(receive_facility)
if (ie->len < 1) if (ie->len < 1)
return -1; return -1;
if ((ie->data[i] & 0xe0) != 0x80) {
pri_error(pri, "!! Invalid Protocol Profile field 0x%X\n", ie->data[i]);
return -1;
}
switch(next_protocol = protocol = (ie->data[i] & 0x1f)) { switch(next_protocol = protocol = (ie->data[i] & 0x1f)) {
case Q932_PROTOCOL_CMIP: case Q932_PROTOCOL_CMIP:
case Q932_PROTOCOL_ACSE: case Q932_PROTOCOL_ACSE:
@@ -1207,9 +1194,6 @@ static FUNC_RECV(receive_facility)
pri_error(pri, "!! Invalid Q.932 Protocol Profile of type 0x%X received\n", protocol); pri_error(pri, "!! Invalid Q.932 Protocol Profile of type 0x%X received\n", protocol);
return -1; return -1;
} }
/* Service indicator octet - Just ignore for now */
if (!(ie->data[i] & 0x80))
i++;
i++; i++;
if (ie->len < 3) if (ie->len < 3)
@@ -1232,9 +1216,9 @@ static FUNC_RECV(receive_facility)
case Q932_PROTOCOL_ROSE: case Q932_PROTOCOL_ROSE:
switch (comp->type) { switch (comp->type) {
Q932_HANDLE_PROC(COMP_TYPE_INVOKE, Q932_STATE_SERVICE, "ROSE Invoke", rose_invoke_decode); Q932_HANDLE_PROC(COMP_TYPE_INVOKE, Q932_STATE_SERVICE, "ROSE Invoke", rose_invoke_decode);
Q932_HANDLE_PROC(COMP_TYPE_RETURN_RESULT, Q932_STATE_SERVICE, "ROSE return result", rose_return_result_decode); Q932_HANDLE_NULL(COMP_TYPE_RETURN_RESULT, Q932_STATE_SERVICE, "ROSE return result", NULL);
Q932_HANDLE_PROC(COMP_TYPE_RETURN_ERROR, Q932_STATE_SERVICE, "ROSE return error", rose_return_error_decode); Q932_HANDLE_NULL(COMP_TYPE_RETURN_ERROR, Q932_STATE_SERVICE, "ROSE return error", NULL);
Q932_HANDLE_PROC(COMP_TYPE_REJECT, Q932_STATE_SERVICE, "ROSE reject", rose_reject_decode); Q932_HANDLE_NULL(COMP_TYPE_REJECT, Q932_STATE_SERVICE, "ROSE reject", NULL);
default: default:
if (pri->debug & PRI_DEBUG_APDU) if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, "Don't know how to handle ROSE component of type 0x%X\n", comp->type); pri_message(pri, "Don't know how to handle ROSE component of type 0x%X\n", comp->type);
@@ -1387,8 +1371,7 @@ static FUNC_DUMP(dump_keypad_facility)
if (ie->len == 0 || ie->len > sizeof(tmp)) if (ie->len == 0 || ie->len > sizeof(tmp))
return; return;
memcpy(tmp, ie->data, ie->len); libpri_copy_string(tmp, (char *) ie->data, sizeof(tmp));
tmp[ie->len] = '\0';
pri_message(pri, "%c Keypad Facility (len=%2d) [ %s ]\n", prefix, ie->len, tmp ); pri_message(pri, "%c Keypad Facility (len=%2d) [ %s ]\n", prefix, ie->len, tmp );
} }
@@ -1399,42 +1382,21 @@ static FUNC_RECV(receive_keypad_facility)
if (ie->len == 0) if (ie->len == 0)
return -1; return -1;
if (ie->len > (sizeof(call->keypad_digits) - 1)) if (ie->len > sizeof(call->digitbuf))
mylen = (sizeof(call->keypad_digits) - 1); mylen = sizeof(call->digitbuf);
else else
mylen = ie->len; mylen = ie->len;
memcpy(call->keypad_digits, ie->data, mylen); libpri_copy_string(call->digitbuf, (char *) ie->data, mylen);
call->keypad_digits[mylen] = 0;
return 0; return 0;
} }
static FUNC_SEND(transmit_keypad_facility)
{
int sublen;
sublen = strlen(call->keypad_digits);
if (sublen > 32) {
sublen = 32;
call->keypad_digits[32] = '\0';
}
if (sublen) {
libpri_copy_string((char *)ie->data, (char *)call->keypad_digits, sizeof(call->keypad_digits));
/* Make sure we clear the field */
call->keypad_digits[0] = '\0';
return sublen + 2;
} else
return 0;
}
static FUNC_DUMP(dump_display) static FUNC_DUMP(dump_display)
{ {
int x, y; int x, y;
char *buf = malloc(len + 1); char *buf = malloc(len + 1);
char tmp[80] = ""; char tmp[80];
if (buf) { if (buf) {
x=y=0; x=y=0;
if ((x < ie->len) && (ie->data[x] & 0x80)) { if ((x < ie->len) && (ie->data[x] & 0x80)) {
@@ -1449,72 +1411,59 @@ static FUNC_DUMP(dump_display)
} }
} }
#define CHECK_OVERFLOW(limit) \ static void dump_ie_data(unsigned char *c, int len)
if (tmpptr - tmp + limit >= sizeof(tmp)) { \
*tmpptr = '\0'; \
pri_message(pri, "%s", tmpptr = tmp); \
}
static void dump_ie_data(struct pri *pri, unsigned char *c, int len)
{ {
static char hexs[16] = "0123456789ABCDEF"; char tmp[1024] = "";
char tmp[1024], *tmpptr; int x=0;
int lastascii = 0; int lastascii = 0;
tmpptr = tmp; while(len) {
for (; len; --len, ++c) { if (((*c >= 'A') && (*c <= 'Z')) ||
CHECK_OVERFLOW(7); ((*c >= 'a') && (*c <= 'z')) ||
if (isprint(*c)) { ((*c >= '0') && (*c <= '9'))) {
if (!lastascii) { if (!lastascii) {
if (tmpptr != tmp) { if (*tmp) {
*tmpptr++ = ','; tmp[x++] = ',';
*tmpptr++ = ' '; tmp[x++] = ' ';
} }
*tmpptr++ = '\''; tmp[x++] = '\'';
}
tmp[x++] = *c;
lastascii = 1; lastascii = 1;
}
*tmpptr++ = *c;
} else { } else {
if (lastascii) { if (lastascii) {
*tmpptr++ = '\''; tmp[x++] = '\'';
}
if (*tmp) {
tmp[x++] = ',';
tmp[x++] = ' ';
}
sprintf (tmp + x, "0x%02x", *c);
x += 4;
lastascii = 0; lastascii = 0;
} }
if (tmpptr != tmp) { c++;
*tmpptr++ = ','; len--;
*tmpptr++ = ' ';
}
*tmpptr++ = '0';
*tmpptr++ = 'x';
*tmpptr++ = hexs[(*c >> 4) & 0x0f];
*tmpptr++ = hexs[(*c) & 0x0f];
}
} }
if (lastascii) if (lastascii)
*tmpptr++ = '\''; tmp[x++] = '\'';
*tmpptr = '\0'; pri_message(NULL, tmp);
pri_message(pri, "%s", tmp);
} }
static FUNC_DUMP(dump_facility) static FUNC_DUMP(dump_facility)
{ {
int dataat = (ie->data[0] & 0x80) ? 1 : 2;
pri_message(pri, "%c Facility (len=%2d, codeset=%d) [ ", prefix, len, Q931_IE_CODESET(full_ie)); pri_message(pri, "%c Facility (len=%2d, codeset=%d) [ ", prefix, len, Q931_IE_CODESET(full_ie));
dump_ie_data(pri, ie->data, ie->len); dump_ie_data(ie->data, ie->len);
pri_message(NULL, " ]\n"); pri_message(NULL, " ]\n");
if (ie->len > 1) {
pri_message(pri, "PROTOCOL %02X\n", ie->data[0] & ASN1_TYPE_MASK);
asn1_dump(pri, &ie->data[dataat], ie->len - dataat);
}
} }
static FUNC_DUMP(dump_network_spec_fac) static FUNC_DUMP(dump_network_spec_fac)
{ {
pri_message(pri, "%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len); pri_message(pri, "%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len);
if (ie->data[0] == 0x00) { if (ie->data[0] == 0x00) {
pri_message(pri, "%s", code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0]))); pri_message(pri, code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0])));
} }
else else
dump_ie_data(pri, ie->data, ie->len); dump_ie_data(ie->data, ie->len);
pri_message(pri, " ]\n"); pri_message(pri, " ]\n");
} }
@@ -1548,11 +1497,11 @@ static char *pri_causeclass2str(int cause)
static struct msgtype causeclasses[] = { static struct msgtype causeclasses[] = {
{ 0, "Normal Event" }, { 0, "Normal Event" },
{ 1, "Normal Event" }, { 1, "Normal Event" },
{ 2, "Network Congestion (resource unavailable)" }, { 2, "Network Congestion" },
{ 3, "Service or Option not Available" }, { 3, "Service or Option not Available" },
{ 4, "Service or Option not Implemented" }, { 4, "Service or Option not Implemented" },
{ 5, "Invalid message (e.g. parameter out of range)" }, { 5, "Invalid message" },
{ 6, "Protocol Error (e.g. unknown message)" }, { 6, "Protocol Error" },
{ 7, "Interworking" }, { 7, "Interworking" },
}; };
return code2str(cause, causeclasses, sizeof(causeclasses) / sizeof(causeclasses[0])); return code2str(cause, causeclasses, sizeof(causeclasses) / sizeof(causeclasses[0]));
@@ -1561,7 +1510,7 @@ static char *pri_causeclass2str(int cause)
static FUNC_DUMP(dump_cause) static FUNC_DUMP(dump_cause)
{ {
int x; int x;
pri_message(pri, "%c Cause (len=%2d) [ Ext: %d Coding: %s (%d) Spare: %d Location: %s (%d)\n", pri_message(pri, "%c Cause (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5, prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5,
(ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf); (ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf);
pri_message(pri, "%c Ext: %d Cause: %s (%d), class = %s (%d) ]\n", pri_message(pri, "%c Ext: %d Cause: %s (%d), class = %s (%d) ]\n",
@@ -1955,19 +1904,8 @@ static FUNC_DUMP(dump_signal)
pri_message(pri, "Signal %s (%d)\n", signal2str(ie->data[0]), ie->data[0]); pri_message(pri, "Signal %s (%d)\n", signal2str(ie->data[0]), ie->data[0]);
} }
static FUNC_DUMP(dump_transit_count)
{
/* Defined in ECMA-225 */
pri_message(pri, "%c Transit Count (len=%02d): ", prefix, len);
if (len < 3) {
pri_message(pri, "Invalid length\n");
return;
}
pri_message(pri, "Count=%d (0x%02x)\n", ie->data[0] & 0x1f, ie->data[0] & 0x1f);
}
struct ie ies[] = {
static struct ie ies[] = {
/* Codeset 0 - Common */ /* Codeset 0 - Common */
{ 1, NATIONAL_CHANGE_STATUS, "Change Status" }, { 1, NATIONAL_CHANGE_STATUS, "Change Status" },
{ 0, Q931_LOCKING_SHIFT, "Locking Shift", dump_shift }, { 0, Q931_LOCKING_SHIFT, "Locking Shift", dump_shift },
@@ -1995,7 +1933,7 @@ static struct ie ies[] = {
{ 0, Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" }, { 0, Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" },
{ 0, Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" }, { 0, Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
{ 1, Q931_PACKET_SIZE, "Packet Size" }, { 1, Q931_PACKET_SIZE, "Packet Size" },
{ 0, Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility }, { 1, Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
{ 1, Q931_IE_REDIRECTION_NUMBER, "Redirection Number" }, { 1, Q931_IE_REDIRECTION_NUMBER, "Redirection Number" },
{ 1, Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" }, { 1, Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" },
{ 1, Q931_IE_FEATURE_ACTIVATE, "Feature Activation" }, { 1, Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
@@ -2007,7 +1945,7 @@ static struct ie ies[] = {
{ 1, Q931_IE_NOTIFY_IND, "Notification Indicator", dump_notify, receive_notify, transmit_notify }, { 1, Q931_IE_NOTIFY_IND, "Notification Indicator", dump_notify, receive_notify, transmit_notify },
{ 1, Q931_DISPLAY, "Display", dump_display, receive_display, transmit_display }, { 1, Q931_DISPLAY, "Display", dump_display, receive_display, transmit_display },
{ 1, Q931_IE_TIME_DATE, "Date/Time", dump_time_date }, { 1, Q931_IE_TIME_DATE, "Date/Time", dump_time_date },
{ 1, Q931_IE_KEYPAD_FACILITY, "Keypad Facility", dump_keypad_facility, receive_keypad_facility, transmit_keypad_facility }, { 1, Q931_IE_KEYPAD_FACILITY, "Keypad Facility", dump_keypad_facility, receive_keypad_facility },
{ 0, Q931_IE_SIGNAL, "Signal", dump_signal }, { 0, Q931_IE_SIGNAL, "Signal", dump_signal },
{ 1, Q931_IE_SWITCHHOOK, "Switch-hook" }, { 1, Q931_IE_SWITCHHOOK, "Switch-hook" },
{ 1, Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user, transmit_user_user }, { 1, Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user, transmit_user_user },
@@ -2020,8 +1958,6 @@ static struct ie ies[] = {
{ 1, Q931_IE_USER_USER_FACILITY, "User-User Facility" }, { 1, Q931_IE_USER_USER_FACILITY, "User-User Facility" },
{ 1, Q931_IE_UPDATE, "Update" }, { 1, Q931_IE_UPDATE, "Update" },
{ 1, Q931_SENDING_COMPLETE, "Sending Complete", dump_sending_complete, receive_sending_complete, transmit_sending_complete }, { 1, Q931_SENDING_COMPLETE, "Sending Complete", dump_sending_complete, receive_sending_complete, transmit_sending_complete },
/* Codeset 4 - Q.SIG specific */
{ 1, QSIG_IE_TRANSIT_COUNT | Q931_CODESET(4), "Transit Count", dump_transit_count },
/* Codeset 6 - Network specific */ /* Codeset 6 - Network specific */
{ 1, Q931_IE_ORIGINATING_LINE_INFO, "Originating Line Information", dump_line_information, receive_line_information, transmit_line_information }, { 1, Q931_IE_ORIGINATING_LINE_INFO, "Originating Line Information", dump_line_information, receive_line_information, transmit_line_information },
{ 1, Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility, transmit_facility }, { 1, Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility, transmit_facility },
@@ -2132,17 +2068,15 @@ static inline void q931_dumpie(struct pri *pri, int codeset, q931_ie *ie, char p
unsigned int x; unsigned int x;
int full_ie = Q931_FULL_IE(codeset, ie->ie); int full_ie = Q931_FULL_IE(codeset, ie->ie);
int base_ie; int base_ie;
char *buf = malloc(ielen(ie) * 3 + 1);
int buflen = 0;
buf[0] = '\0'; pri_message(NULL, "%c [", prefix);
pri_message(NULL, "%02x", ie->ie);
if (!(ie->ie & 0x80)) { if (!(ie->ie & 0x80)) {
buflen += sprintf(buf, " %02x", ielen(ie)-2); pri_message(NULL, " %02x", ielen(ie)-2);
for (x = 0; x + 2 < ielen(ie); ++x) for (x = 0; x + 2 < ielen(ie); ++x)
buflen += sprintf(buf + buflen, " %02x", ie->data[x]); pri_message(NULL, " %02x", ie->data[x]);
} }
pri_message(pri, "%c [%02x%s]\n", prefix, ie->ie, buf); pri_message(NULL, "]\n");
free(buf);
/* Special treatment for shifts */ /* Special treatment for shifts */
if((full_ie & 0xf0) == Q931_LOCKING_SHIFT) if((full_ie & 0xf0) == Q931_LOCKING_SHIFT)
@@ -2159,7 +2093,7 @@ static inline void q931_dumpie(struct pri *pri, int codeset, q931_ie *ie, char p
return; return;
} }
pri_error(pri, "!! %c Unknown IE %d (cs%d, len = %d)\n", prefix, Q931_IE_IE(base_ie), Q931_IE_CODESET(base_ie), ielen(ie)); pri_error(pri, "!! %c Unknown IE %d (len = %d)\n", prefix, base_ie, ielen(ie));
} }
static q931_call *q931_getcall(struct pri *pri, int cr) static q931_call *q931_getcall(struct pri *pri, int cr)
@@ -2422,6 +2356,7 @@ static int send_message(struct pri *pri, q931_call *c, int msgtype, int ies[])
int offset=0; int offset=0;
int x; int x;
int codeset; int codeset;
struct apdu_event *facevent = c->apdus;
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
len = sizeof(buf); len = sizeof(buf);
@@ -2430,7 +2365,24 @@ static int send_message(struct pri *pri, q931_call *c, int msgtype, int ies[])
x=0; x=0;
codeset = 0; codeset = 0;
while(ies[x] > -1) { while(ies[x] > -1) {
if (ies[x] == Q931_IE_FACILITY) {
res = 0;
while (facevent) {
if (!facevent->sent && (facevent->message == msgtype)) {
int tmpres;
tmpres = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
if (tmpres < 0) {
pri_error(pri, "!! Unable to add IE '%s'\n", ie2str(ies[x]));
return -1;
}
res += tmpres;
facevent->sent = 1;
}
facevent = facevent->next;
}
} else {
res = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset); res = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
}
if (res < 0) { if (res < 0) {
pri_error(pri, "!! Unable to add IE '%s'\n", ie2str(ies[x])); pri_error(pri, "!! Unable to add IE '%s'\n", ie2str(ies[x]));
@@ -2476,7 +2428,7 @@ static int q931_status(struct pri *pri, q931_call *c, int cause)
return send_message(pri, cur, Q931_STATUS, status_ies); return send_message(pri, cur, Q931_STATUS, status_ies);
} }
static int information_ies[] = { Q931_IE_KEYPAD_FACILITY, Q931_CALLED_PARTY_NUMBER, -1 }; static int information_ies[] = { Q931_CALLED_PARTY_NUMBER, -1 };
int q931_information(struct pri *pri, q931_call *c, char digit) int q931_information(struct pri *pri, q931_call *c, char digit)
{ {
@@ -2485,19 +2437,11 @@ int q931_information(struct pri *pri, q931_call *c, char digit)
return send_message(pri, c, Q931_INFORMATION, information_ies); return send_message(pri, c, Q931_INFORMATION, information_ies);
} }
static int keypad_facility_ies[] = { Q931_IE_KEYPAD_FACILITY, -1 };
int q931_keypad_facility(struct pri *pri, q931_call *call, char *digits)
{
libpri_copy_string(call->keypad_digits, digits, sizeof(call->keypad_digits));
return send_message(pri, call, Q931_INFORMATION, keypad_facility_ies);
}
static int restart_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 }; static int restart_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };
static int restart_ack(struct pri *pri, q931_call *c) static int restart_ack(struct pri *pri, q931_call *c)
{ {
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL); c->ourcallstate = Q931_CALL_STATE_NULL;
c->peercallstate = Q931_CALL_STATE_NULL; c->peercallstate = Q931_CALL_STATE_NULL;
return send_message(pri, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies); return send_message(pri, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
} }
@@ -2568,7 +2512,7 @@ int q931_call_proceeding(struct pri *pri, q931_call *c, int channel, int info)
} }
c->chanflags &= ~FLAG_PREFERRED; c->chanflags &= ~FLAG_PREFERRED;
c->chanflags |= FLAG_EXCLUSIVE; c->chanflags |= FLAG_EXCLUSIVE;
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_INCOMING_CALL_PROCEEDING); c->ourcallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING;
c->peercallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING; c->peercallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING;
if (info) { if (info) {
c->progloc = LOC_PRIV_NET_LOCAL_USER; c->progloc = LOC_PRIV_NET_LOCAL_USER;
@@ -2596,7 +2540,7 @@ int q931_alerting(struct pri *pri, q931_call *c, int channel, int info)
c->progressmask = PRI_PROG_INBAND_AVAILABLE; c->progressmask = PRI_PROG_INBAND_AVAILABLE;
} else } else
c->progressmask = 0; c->progressmask = 0;
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_RECEIVED); c->ourcallstate = Q931_CALL_STATE_CALL_RECEIVED;
c->peercallstate = Q931_CALL_STATE_CALL_DELIVERED; c->peercallstate = Q931_CALL_STATE_CALL_DELIVERED;
c->alive = 1; c->alive = 1;
return send_message(pri, c, Q931_ALERTING, alerting_ies); return send_message(pri, c, Q931_ALERTING, alerting_ies);
@@ -2620,7 +2564,7 @@ int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
c->progressmask = PRI_PROG_CALLED_NOT_ISDN; c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
} else } else
c->progressmask = 0; c->progressmask = 0;
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_OVERLAP_RECEIVING); c->ourcallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING; c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
c->alive = 1; c->alive = 1;
return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies); return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
@@ -2660,11 +2604,9 @@ static void pri_release_finaltimeout(void *data)
pri->schedev = 1; pri->schedev = 1;
pri->ev.e = PRI_EVENT_HANGUP_ACK; pri->ev.e = PRI_EVENT_HANGUP_ACK;
pri->ev.hangup.channel = c->channelno; pri->ev.hangup.channel = c->channelno;
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.cref = c->cr; pri->ev.hangup.cref = c->cr;
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.call = c; pri->ev.hangup.call = c;
pri->ev.hangup.aoc_units = c->aoc_units;
libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
q931_hangup(pri, c, c->cause); q931_hangup(pri, c, c->cause);
} }
@@ -2694,17 +2636,14 @@ int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
c->progressmask = PRI_PROG_CALLED_NOT_ISDN; c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
} else } else
c->progressmask = 0; c->progressmask = 0;
if(pri->localtype == PRI_NETWORK || pri->switchtype == PRI_SWITCH_QSIG) c->ourcallstate = Q931_CALL_STATE_CONNECT_REQUEST;
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
else
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CONNECT_REQUEST);
c->peercallstate = Q931_CALL_STATE_ACTIVE; c->peercallstate = Q931_CALL_STATE_ACTIVE;
c->alive = 1; c->alive = 1;
/* Connect request timer */ /* Setup timer */
if (c->retranstimer) if (c->retranstimer)
pri_schedule_del(pri, c->retranstimer); pri_schedule_del(pri, c->retranstimer);
c->retranstimer = 0; c->retranstimer = 0;
if ((c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) && (!pri->subchannel)) if ((pri->localtype == PRI_CPE) && (!pri->subchannel))
c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T313], pri_connect_timeout, c); c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T313], pri_connect_timeout, c);
return send_message(pri, c, Q931_CONNECT, connect_ies); return send_message(pri, c, Q931_CONNECT, connect_ies);
} }
@@ -2713,7 +2652,7 @@ static int release_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
int q931_release(struct pri *pri, q931_call *c, int cause) int q931_release(struct pri *pri, q931_call *c, int cause)
{ {
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RELEASE_REQUEST); c->ourcallstate = Q931_CALL_STATE_RELEASE_REQUEST;
/* c->peercallstate stays the same */ /* c->peercallstate stays the same */
if (c->alive) { if (c->alive) {
c->alive = 0; c->alive = 0;
@@ -2752,7 +2691,7 @@ int q931_restart(struct pri *pri, int channel)
c->channelno = channel; c->channelno = channel;
c->chanflags &= ~FLAG_PREFERRED; c->chanflags &= ~FLAG_PREFERRED;
c->chanflags |= FLAG_EXCLUSIVE; c->chanflags |= FLAG_EXCLUSIVE;
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RESTART); c->ourcallstate = Q931_CALL_STATE_RESTART;
c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST; c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST;
return send_message(pri, c, Q931_RESTART, restart_ies); return send_message(pri, c, Q931_RESTART, restart_ies);
} }
@@ -2761,7 +2700,7 @@ static int disconnect_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
int q931_disconnect(struct pri *pri, q931_call *c, int cause) int q931_disconnect(struct pri *pri, q931_call *c, int cause)
{ {
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_DISCONNECT_REQUEST); c->ourcallstate = Q931_CALL_STATE_DISCONNECT_REQUEST;
c->peercallstate = Q931_CALL_STATE_DISCONNECT_INDICATION; c->peercallstate = Q931_CALL_STATE_DISCONNECT_INDICATION;
if (c->alive) { if (c->alive) {
c->alive = 0; c->alive = 0;
@@ -2777,9 +2716,8 @@ int q931_disconnect(struct pri *pri, q931_call *c, int cause)
return 0; return 0;
} }
static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY, static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY, Q931_IE_USER_USER,
Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_REDIRECTING_NUMBER, Q931_IE_USER_USER, Q931_SENDING_COMPLETE, Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_REDIRECTING_NUMBER, Q931_SENDING_COMPLETE, Q931_IE_ORIGINATING_LINE_INFO, Q931_IE_GENERIC_DIGITS, -1 };
Q931_IE_ORIGINATING_LINE_INFO, Q931_IE_GENERIC_DIGITS, -1 };
static int gr303_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 }; static int gr303_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 };
@@ -2858,8 +2796,6 @@ int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
if (req->useruserinfo) if (req->useruserinfo)
libpri_copy_string(c->useruserinfo, req->useruserinfo, sizeof(c->useruserinfo)); libpri_copy_string(c->useruserinfo, req->useruserinfo, sizeof(c->useruserinfo));
else
c->useruserinfo[0] = '\0';
if (req->nonisdn && (pri->switchtype == PRI_SWITCH_NI2)) if (req->nonisdn && (pri->switchtype == PRI_SWITCH_NI2))
c->progressmask = PRI_PROG_CALLER_NOT_ISDN; c->progressmask = PRI_PROG_CALLER_NOT_ISDN;
@@ -2878,7 +2814,7 @@ int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
c->alive = 1; c->alive = 1;
/* make sure we call PRI_EVENT_HANGUP_ACK once we send/receive RELEASE_COMPLETE */ /* make sure we call PRI_EVENT_HANGUP_ACK once we send/receive RELEASE_COMPLETE */
c->sendhangupack = 1; c->sendhangupack = 1;
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_INITIATED); c->ourcallstate = Q931_CALL_STATE_CALL_INITIATED;
c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING; c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
} }
return res; return res;
@@ -2890,7 +2826,7 @@ static int release_complete_ies[] = { Q931_IE_USER_USER, -1 };
static int q931_release_complete(struct pri *pri, q931_call *c, int cause) static int q931_release_complete(struct pri *pri, q931_call *c, int cause)
{ {
int res = 0; int res = 0;
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL); c->ourcallstate = Q931_CALL_STATE_NULL;
c->peercallstate = Q931_CALL_STATE_NULL; c->peercallstate = Q931_CALL_STATE_NULL;
if (cause > -1) { if (cause > -1) {
c->cause = cause; c->cause = cause;
@@ -2965,6 +2901,8 @@ int q931_hangup(struct pri *pri, q931_call *c, int cause)
/* sent CONNECT */ /* sent CONNECT */
case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING: case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
/* we sent CALL_PROCEEDING */ /* we sent CALL_PROCEEDING */
case Q931_CALL_STATE_ACTIVE:
/* received CONNECT */
case Q931_CALL_STATE_OVERLAP_RECEIVING: case Q931_CALL_STATE_OVERLAP_RECEIVING:
/* received SETUP_ACKNOWLEDGE */ /* received SETUP_ACKNOWLEDGE */
/* send DISCONNECT in general */ /* send DISCONNECT in general */
@@ -2978,10 +2916,6 @@ int q931_hangup(struct pri *pri, q931_call *c, int cause)
} else } else
pri_error(pri, "Wierd, doing nothing but this shouldn't happen, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate)); pri_error(pri, "Wierd, doing nothing but this shouldn't happen, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
break; break;
case Q931_CALL_STATE_ACTIVE:
/* received CONNECT */
q931_disconnect(pri,c,cause);
break;
case Q931_CALL_STATE_DISCONNECT_REQUEST: case Q931_CALL_STATE_DISCONNECT_REQUEST:
/* sent DISCONNECT */ /* sent DISCONNECT */
q931_release(pri,c,cause); q931_release(pri,c,cause);
@@ -3110,7 +3044,6 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
case Q931_PROGRESS: case Q931_PROGRESS:
c->useruserinfo[0] = '\0'; c->useruserinfo[0] = '\0';
c->cause = -1; c->cause = -1;
/* Fall through */
case Q931_CALL_PROCEEDING: case Q931_CALL_PROCEEDING:
c->progress = -1; c->progress = -1;
c->progressmask = 0; c->progressmask = 0;
@@ -3136,7 +3069,6 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
pri_schedule_del(pri, c->retranstimer); pri_schedule_del(pri, c->retranstimer);
c->retranstimer = 0; c->retranstimer = 0;
c->useruserinfo[0] = '\0'; c->useruserinfo[0] = '\0';
/* Fall through */
case Q931_STATUS: case Q931_STATUS:
c->cause = -1; c->cause = -1;
c->causecode = -1; c->causecode = -1;
@@ -3148,7 +3080,6 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
c->channelno = -1; c->channelno = -1;
break; break;
case Q931_INFORMATION: case Q931_INFORMATION:
c->callednum[0] = '\0';
break; break;
case Q931_STATUS_ENQUIRY: case Q931_STATUS_ENQUIRY:
break; break;
@@ -3174,13 +3105,12 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
pri_error(pri, "!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); pri_error(pri, "!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
/* Fall through */ /* Fall through */
default: default:
pri_error(pri, "!! Don't know how to pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); pri_error(pri, "!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST); q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
if (c->newcall) if (c->newcall)
q931_destroycall(pri,c->cr); q931_destroycall(pri,c->cr);
return -1; return -1;
} }
/* Handle IEs */
memset(mandies, 0, sizeof(mandies)); memset(mandies, 0, sizeof(mandies));
missingmand = 0; missingmand = 0;
for (x=0;x<sizeof(msgs) / sizeof(msgs[0]); x++) { for (x=0;x<sizeof(msgs) / sizeof(msgs[0]); x++) {
@@ -3275,7 +3205,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
q931_destroycall(pri, c->cr); q931_destroycall(pri, c->cr);
break; break;
} }
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RESTART); c->ourcallstate = Q931_CALL_STATE_RESTART;
c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST; c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST;
/* Send back the Restart Acknowledge */ /* Send back the Restart Acknowledge */
restart_ack(pri, c); restart_ack(pri, c);
@@ -3295,7 +3225,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN) if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN)
c->nonisdn = 1; c->nonisdn = 1;
c->newcall = 0; c->newcall = 0;
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_PRESENT); c->ourcallstate = Q931_CALL_STATE_CALL_PRESENT;
c->peercallstate = Q931_CALL_STATE_CALL_INITIATED; c->peercallstate = Q931_CALL_STATE_CALL_INITIATED;
/* it's not yet a call since higher level can respond with RELEASE or RELEASE_COMPLETE */ /* it's not yet a call since higher level can respond with RELEASE or RELEASE_COMPLETE */
c->alive = 0; c->alive = 0;
@@ -3340,7 +3270,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
break; break;
} }
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_DELIVERED); c->ourcallstate = Q931_CALL_STATE_CALL_DELIVERED;
c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED; c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
pri->ev.e = PRI_EVENT_RINGING; pri->ev.e = PRI_EVENT_RINGING;
pri->ev.ringing.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); pri->ev.ringing.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
@@ -3348,18 +3278,8 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
pri->ev.ringing.call = c; pri->ev.ringing.call = c;
pri->ev.ringing.progress = c->progress; pri->ev.ringing.progress = c->progress;
pri->ev.ringing.progressmask = c->progressmask; pri->ev.ringing.progressmask = c->progressmask;
libpri_copy_string(pri->ev.ringing.useruserinfo, c->useruserinfo, sizeof(pri->ev.ringing.useruserinfo)); libpri_copy_string(pri->ev.ringing.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo));
c->useruserinfo[0] = '\0'; c->useruserinfo[0] = '\0';
cur = c->apdus;
while (cur) {
if (!cur->sent && cur->message == Q931_FACILITY) {
q931_facility(pri, c);
break;
}
cur = cur->next;
}
return Q931_RES_HAVEEVENT; return Q931_RES_HAVEEVENT;
case Q931_CONNECT: case Q931_CONNECT:
if (c->newcall) { if (c->newcall) {
@@ -3370,7 +3290,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE); q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE);
break; break;
} }
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE); c->ourcallstate = Q931_CALL_STATE_ACTIVE;
c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST; c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
pri->ev.e = PRI_EVENT_ANSWER; pri->ev.e = PRI_EVENT_ANSWER;
pri->ev.answer.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); pri->ev.answer.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
@@ -3378,7 +3298,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
pri->ev.answer.call = c; pri->ev.answer.call = c;
pri->ev.answer.progress = c->progress; pri->ev.answer.progress = c->progress;
pri->ev.answer.progressmask = c->progressmask; pri->ev.answer.progressmask = c->progressmask;
libpri_copy_string(pri->ev.answer.useruserinfo, c->useruserinfo, sizeof(pri->ev.answer.useruserinfo)); libpri_copy_string(pri->ev.answer.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo));
c->useruserinfo[0] = '\0'; c->useruserinfo[0] = '\0';
q931_connect_acknowledge(pri, c); q931_connect_acknowledge(pri, c);
if (c->justsignalling) { /* Make sure WE release when we initiatie a signalling only connection */ if (c->justsignalling) { /* Make sure WE release when we initiatie a signalling only connection */
@@ -3425,35 +3345,24 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
if (mh->msg == Q931_CALL_PROCEEDING) { if (mh->msg == Q931_CALL_PROCEEDING) {
pri->ev.e = PRI_EVENT_PROCEEDING; pri->ev.e = PRI_EVENT_PROCEEDING;
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING); c->ourcallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING;
c->peercallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING; c->peercallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING;
} }
pri->ev.proceeding.progress = c->progress; pri->ev.proceeding.progress = c->progress;
pri->ev.proceeding.progressmask = c->progressmask; pri->ev.proceeding.progressmask = c->progressmask;
pri->ev.proceeding.cref = c->cr; pri->ev.proceeding.cref = c->cr;
pri->ev.proceeding.call = c; pri->ev.proceeding.call = c;
cur = c->apdus;
while (cur) {
if (!cur->sent && cur->message == Q931_FACILITY) {
q931_facility(pri, c);
break;
}
cur = cur->next;
}
return Q931_RES_HAVEEVENT; return Q931_RES_HAVEEVENT;
case Q931_CONNECT_ACKNOWLEDGE: case Q931_CONNECT_ACKNOWLEDGE:
if (c->newcall) { if (c->newcall) {
q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
break; break;
} }
if (!(c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) && if (c->ourcallstate != Q931_CALL_STATE_CONNECT_REQUEST) {
!(c->ourcallstate == Q931_CALL_STATE_ACTIVE &&
(pri->localtype == PRI_NETWORK || pri->switchtype == PRI_SWITCH_QSIG))) {
q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE); q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
break; break;
} }
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE); c->ourcallstate = Q931_CALL_STATE_ACTIVE;
c->peercallstate = Q931_CALL_STATE_ACTIVE; c->peercallstate = Q931_CALL_STATE_ACTIVE;
break; break;
case Q931_STATUS: case Q931_STATUS:
@@ -3475,13 +3384,11 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
/* Workaround for S-12 ver 7.3 - it responds for invalid/non-implemented IEs at SETUP with null call state */ /* Workaround for S-12 ver 7.3 - it responds for invalid/non-implemented IEs at SETUP with null call state */
if (!c->sugcallstate && (c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED)) { if (!c->sugcallstate && (c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED)) {
pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.cref = c->cr; pri->ev.hangup.cref = c->cr;
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.call = c; pri->ev.hangup.call = c;
pri->ev.hangup.aoc_units = c->aoc_units;
libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
/* Free resources */ /* Free resources */
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL); c->ourcallstate = Q931_CALL_STATE_NULL;
c->peercallstate = Q931_CALL_STATE_NULL; c->peercallstate = Q931_CALL_STATE_NULL;
if (c->alive) { if (c->alive) {
pri->ev.e = PRI_EVENT_HANGUP; pri->ev.e = PRI_EVENT_HANGUP;
@@ -3500,14 +3407,13 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
} }
break; break;
case Q931_RELEASE_COMPLETE: case Q931_RELEASE_COMPLETE:
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL); c->ourcallstate = Q931_CALL_STATE_NULL;
c->peercallstate = Q931_CALL_STATE_NULL; c->peercallstate = Q931_CALL_STATE_NULL;
pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.cref = c->cr; pri->ev.hangup.cref = c->cr;
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.call = c; pri->ev.hangup.call = c;
pri->ev.hangup.aoc_units = c->aoc_units; libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo));
libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
c->useruserinfo[0] = '\0'; c->useruserinfo[0] = '\0';
/* Free resources */ /* Free resources */
if (c->alive) { if (c->alive) {
@@ -3535,14 +3441,14 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
else { else {
c->peercallstate = Q931_CALL_STATE_RELEASE_REQUEST; c->peercallstate = Q931_CALL_STATE_RELEASE_REQUEST;
} }
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL); c->ourcallstate = Q931_CALL_STATE_NULL;
pri->ev.e = PRI_EVENT_HANGUP; pri->ev.e = PRI_EVENT_HANGUP;
pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.cref = c->cr; pri->ev.hangup.cref = c->cr;
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.call = c; pri->ev.hangup.call = c;
pri->ev.hangup.aoc_units = c->aoc_units; pri->ev.hangup.aoc_units = c->aoc_units;
libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo)); libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo));
c->useruserinfo[0] = '\0'; c->useruserinfo[0] = '\0';
/* Don't send release complete if they send us release /* Don't send release complete if they send us release
while we sent it, assume a NULL state */ while we sent it, assume a NULL state */
@@ -3560,25 +3466,23 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
break; break;
} }
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_DISCONNECT_INDICATION); c->ourcallstate = Q931_CALL_STATE_DISCONNECT_INDICATION;
c->peercallstate = Q931_CALL_STATE_DISCONNECT_REQUEST; c->peercallstate = Q931_CALL_STATE_DISCONNECT_REQUEST;
c->sendhangupack = 1; c->sendhangupack = 1;
/* Return such an event */ /* Return such an event */
pri->ev.e = PRI_EVENT_HANGUP_REQ; pri->ev.e = PRI_EVENT_HANGUP_REQ;
pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.cref = c->cr; pri->ev.hangup.cref = c->cr;
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.call = c; pri->ev.hangup.call = c;
pri->ev.hangup.aoc_units = c->aoc_units; pri->ev.hangup.aoc_units = c->aoc_units;
libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
c->useruserinfo[0] = '\0';
if (c->alive) if (c->alive)
return Q931_RES_HAVEEVENT; return Q931_RES_HAVEEVENT;
else else
q931_hangup(pri,c,c->cause); q931_hangup(pri,c,c->cause);
break; break;
case Q931_RESTART_ACKNOWLEDGE: case Q931_RESTART_ACKNOWLEDGE:
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL); c->ourcallstate = Q931_CALL_STATE_NULL;
c->peercallstate = Q931_CALL_STATE_NULL; c->peercallstate = Q931_CALL_STATE_NULL;
pri->ev.e = PRI_EVENT_RESTART_ACK; pri->ev.e = PRI_EVENT_RESTART_ACK;
pri->ev.restartack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); pri->ev.restartack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
@@ -3596,9 +3500,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
pri->ev.e = PRI_EVENT_KEYPAD_DIGIT; pri->ev.e = PRI_EVENT_KEYPAD_DIGIT;
pri->ev.digit.call = c; pri->ev.digit.call = c;
pri->ev.digit.channel = c->channelno | (c->ds1no << 8); pri->ev.digit.channel = c->channelno | (c->ds1no << 8);
libpri_copy_string(pri->ev.digit.digits, c->keypad_digits, sizeof(pri->ev.digit.digits)); libpri_copy_string(pri->ev.digit.digits, c->digitbuf, sizeof(pri->ev.digit.digits));
/* Make sure we clear it out before we return */
c->keypad_digits[0] = '\0';
return Q931_RES_HAVEEVENT; return Q931_RES_HAVEEVENT;
} }
pri->ev.e = PRI_EVENT_INFO_RECEIVED; pri->ev.e = PRI_EVENT_INFO_RECEIVED;
@@ -3619,11 +3521,10 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
break; break;
} }
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_OVERLAP_SENDING); c->ourcallstate = Q931_CALL_STATE_OVERLAP_SENDING;
c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING; c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
pri->ev.e = PRI_EVENT_SETUP_ACK; pri->ev.e = PRI_EVENT_SETUP_ACK;
pri->ev.setup_ack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); pri->ev.setup_ack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
pri->ev.setup_ack.call = c;
cur = c->apdus; cur = c->apdus;
while (cur) { while (cur) {
@@ -3668,131 +3569,6 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
return 0; return 0;
} }
/* Clear a call, although we did not receive any hangup notification. */
static int pri_internal_clear(void *data)
{
struct q931_call *c = data;
struct pri *pri = c->pri;
int res;
if (c->retranstimer)
pri_schedule_del(pri, c->retranstimer);
c->retranstimer = 0;
c->useruserinfo[0] = '\0';
c->cause = -1;
c->causecode = -1;
c->causeloc = -1;
c->sugcallstate = -1;
c->aoc_units = -1;
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
c->peercallstate = Q931_CALL_STATE_NULL;
pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.cref = c->cr;
pri->ev.hangup.call = c;
pri->ev.hangup.aoc_units = c->aoc_units;
libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
/* Free resources */
if (c->alive) {
pri->ev.e = PRI_EVENT_HANGUP;
res = Q931_RES_HAVEEVENT;
c->alive = 0;
} else if (c->sendhangupack) {
res = Q931_RES_HAVEEVENT;
pri->ev.e = PRI_EVENT_HANGUP_ACK;
q931_hangup(pri, c, c->cause);
} else {
res = 0;
q931_hangup(pri, c, c->cause);
}
return res;
}
/* Handle T309 timeout for an active call. */
static void pri_dl_down_timeout(void *data)
{
struct q931_call *c = data;
struct pri *pri = c->pri;
if (pri->debug & PRI_DEBUG_Q931_STATE)
pri_message(pri, DBGHEAD "Timed out waiting for data link re-establishment\n", DBGINFO);
c->cause = PRI_CAUSE_DESTINATION_OUT_OF_ORDER;
if (pri_internal_clear(c) == Q931_RES_HAVEEVENT)
pri->schedev = 1;
}
/* Handle Layer 2 down event for a non active call. */
static void pri_dl_down_cancelcall(void *data)
{
struct q931_call *c = data;
struct pri *pri = c->pri;
if (pri->debug & PRI_DEBUG_Q931_STATE)
pri_message(pri, DBGHEAD "Cancel non active call after data link failure\n", DBGINFO);
c->cause = PRI_CAUSE_DESTINATION_OUT_OF_ORDER;
if (pri_internal_clear(c) == Q931_RES_HAVEEVENT)
pri->schedev = 1;
}
/* Receive an indication from Layer 2 */
void q931_dl_indication(struct pri *pri, int event)
{
q931_call *cur = NULL;
/* Just return if T309 is not enabled. */
if (!pri || pri->timers[PRI_TIMER_T309] < 0)
return;
switch (event) {
case PRI_EVENT_DCHAN_DOWN:
pri_message(pri, DBGHEAD "link is DOWN\n", DBGINFO);
cur = *pri->callpool;
while(cur) {
if (cur->ourcallstate == Q931_CALL_STATE_ACTIVE) {
/* For a call in Active state, activate T309 only if there is no timer already running. */
if (!cur->retranstimer) {
pri_message(pri, DBGHEAD "activate T309 for call %d on channel %d\n", DBGINFO, cur->cr, cur->channelno);
cur->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T309], pri_dl_down_timeout, cur);
}
} else if (cur->ourcallstate != Q931_CALL_STATE_NULL) {
/* For a call that is not in Active state, schedule internal clearing of the call 'ASAP' (delay 0). */
pri_message(pri, DBGHEAD "cancel call %d on channel %d in state %d (%s)\n", DBGINFO,
cur->cr, cur->channelno, cur->ourcallstate, callstate2str(cur->ourcallstate));
if (cur->retranstimer)
pri_schedule_del(pri, cur->retranstimer);
cur->retranstimer = pri_schedule_event(pri, 0, pri_dl_down_cancelcall, cur);
}
cur = cur->next;
}
break;
case PRI_EVENT_DCHAN_UP:
pri_message(pri, DBGHEAD "link is UP\n", DBGINFO);
cur = *pri->callpool;
while(cur) {
if (cur->ourcallstate == Q931_CALL_STATE_ACTIVE && cur->retranstimer) {
pri_message(pri, DBGHEAD "cancel T309 for call %d on channel %d\n", DBGINFO, cur->cr, cur->channelno);
pri_schedule_del(pri, cur->retranstimer);
cur->retranstimer = 0;
q931_status(pri, cur, PRI_CAUSE_NORMAL_UNSPECIFIED);
} else if (cur->ourcallstate != Q931_CALL_STATE_NULL &&
cur->ourcallstate != Q931_CALL_STATE_DISCONNECT_REQUEST &&
cur->ourcallstate != Q931_CALL_STATE_DISCONNECT_INDICATION &&
cur->ourcallstate != Q931_CALL_STATE_RELEASE_REQUEST) {
/* The STATUS message sent here is not required by Q.931, but it may help anyway. */
q931_status(pri, cur, PRI_CAUSE_NORMAL_UNSPECIFIED);
}
cur = cur->next;
}
break;
default:
pri_message(pri, DBGHEAD "unexpected event %d.\n", DBGINFO, event);
}
}
int q931_call_getcrv(struct pri *pri, q931_call *call, int *callmode) int q931_call_getcrv(struct pri *pri, q931_call *call, int *callmode)
{ {
if (callmode) if (callmode)

View File

@@ -42,7 +42,11 @@
#include <sys/time.h> #include <sys/time.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <zaptel/zaptel.h> #if defined(__linux__)
#include <linux/zaptel.h>
#elif defined(__FreeBSD__) || defined(SOLARIS)
#include <zaptel.h>
#endif
#ifndef SOLARIS #ifndef SOLARIS
#include <zap.h> #include <zap.h>
#endif #endif
@@ -143,7 +147,7 @@ static void event2(struct pri *pri, pri_event *e)
} }
} }
static void testmsg(struct pri *pri, char *s) static void testmsg(char *s)
{ {
char *c; char *c;
static int keeplast = 0; static int keeplast = 0;
@@ -169,7 +173,7 @@ static void testmsg(struct pri *pri, char *s)
keeplast = 0; keeplast = 0;
} }
static void testerr(struct pri *pri, char *s) static void testerr(char *s)
{ {
char *c; char *c;
static int keeplast = 0; static int keeplast = 0;
@@ -260,7 +264,6 @@ int main(int argc, char *argv[])
} }
first = pri; first = pri;
pri_set_debug(pri, DEBUG_LEVEL); pri_set_debug(pri, DEBUG_LEVEL);
pri_facility_enable(pri);
if (pthread_create(&tmp, NULL, dchan, pri)) { if (pthread_create(&tmp, NULL, dchan, pri)) {
perror("thread(0)"); perror("thread(0)");
exit(1); exit(1);
@@ -270,7 +273,6 @@ int main(int argc, char *argv[])
exit(1); exit(1);
} }
pri_set_debug(pri, DEBUG_LEVEL); pri_set_debug(pri, DEBUG_LEVEL);
pri_facility_enable(pri);
if (pthread_create(&tmp, NULL, dchan, pri)) { if (pthread_create(&tmp, NULL, dchan, pri)) {
perror("thread(1)"); perror("thread(1)");
exit(1); exit(1);