- added support for cli callback.
- added support for incoming calls. - added support for leased lines. - added manual page.
This commit is contained in:
parent
a4f59461cf
commit
5374218260
|
@ -4,7 +4,7 @@ LDFLAGS = -shared -L../capi20
|
|||
|
||||
PLUGINDIR=${DESTDIR}/etc/ppp/plugins
|
||||
PEERDIR=${DESTDIR}/etc/ppp/peers/isdn
|
||||
PEERS= arcor otelo talkline avm avm-ml
|
||||
PEERS= arcor otelo talkline avm avm-ml leased
|
||||
INSTALL=./install-sh -c
|
||||
|
||||
ALL = capiplugin.so userpass.so
|
||||
|
@ -33,6 +33,12 @@ install: $(ALL)
|
|||
echo $(INSTALL) peers/$$i $(PEERDIR); \
|
||||
$(INSTALL) peers/$$i $(PEERDIR); \
|
||||
done
|
||||
for i in /usr/share/man /usr/man; do \
|
||||
if [ -d $$i/man8 ] ; then \
|
||||
echo $(INSTALL) capiplugin.8 $$i/man8; \
|
||||
$(INSTALL) capiplugin.8 $$i/man8; \
|
||||
fi ; \
|
||||
done
|
||||
|
||||
config:
|
||||
@echo nothing to configure
|
||||
|
|
|
@ -0,0 +1,393 @@
|
|||
.\" manual page [] for capiplugin 2.3
|
||||
.\" $Id: capiplugin.8,v 1.1 2000/10/20 17:19:20 calle Exp $
|
||||
.\" SH section heading
|
||||
.\" SS subsection heading
|
||||
.\" LP paragraph
|
||||
.\" IP indented paragraph
|
||||
.\" TP hanging label
|
||||
.TH CAPIPLUGIN 8
|
||||
.SH NAME
|
||||
capiplugin \- Plugin for pppd (Point to Point Protocol daemon)
|
||||
.SH SYNOPSIS
|
||||
.B pppd
|
||||
[\fIoptions\fR]
|
||||
.B plugin
|
||||
.B /etc/ppp/plugins/capiplugin.so
|
||||
[\fIoptions for capiplugin\fR]
|
||||
.SH DESCRIPTION
|
||||
.LP
|
||||
The capiplugin provides a method to use PPP over ISDN with
|
||||
ISDN controllers that provide a CAPI2.0 interface.
|
||||
The plugin is responsible for the call setup with CAPI2.0.
|
||||
You can dial out, wait for incoming calls and setup communication over
|
||||
leased lines. It implements the feature to reject a incoming call
|
||||
and call back. When dialing out this feature can also be used.
|
||||
In this case the called party has to reject the call and call back soon.
|
||||
.SH HOW IS WORKS
|
||||
.LP
|
||||
The capiplugin registers a new_phase_hook and its own options to the pppd
|
||||
when loaded. When the pppd goes into phase SERIALCONN the capiplugin
|
||||
will setup a connection and sets the global variable devnam.
|
||||
The capiplugin will register a timer function that is
|
||||
called every second to handle the capi messages while pppd is running.
|
||||
To let pppd wakeup when capi messages arrive, the capi file desciptor
|
||||
is added to the list of file descriptors on which the pppd waits for input.
|
||||
After the connection is established the pppd will start PPP negotiation
|
||||
on device devnam. When the pppd goes into phase DEAD, the connection will
|
||||
be dropped (if not already dropped) and the timer function and the capi file
|
||||
desciptor will be unregistered.
|
||||
|
||||
.SH MODES OF OPERATION
|
||||
.TP
|
||||
.B normal dial out
|
||||
Simply make a connection, for example to your internet provider.
|
||||
.br
|
||||
Required options: \fInumber\fR.
|
||||
Recommended options: \fImsn\fR.
|
||||
Other possible options:
|
||||
\fIcontroller\fR,
|
||||
\fIdialmax\fR,
|
||||
\fIdialtimeout\fR,
|
||||
\fIprotocol\fR and
|
||||
\fIredialdelay\fR.
|
||||
.TP
|
||||
.B dial out with callback
|
||||
Call a given number, the called party call back after rejecting the call
|
||||
and then call back.
|
||||
.br
|
||||
Required options: \fInumber\fR and \fIclicb\fR.
|
||||
Recommended options: \fIcli\fR and \fImsn\fR or \fIinmsn\fR.
|
||||
Other possible options:
|
||||
\fIcbwait\fR,
|
||||
\fIcontroller\fR,
|
||||
\fIconnectdelay\fR,
|
||||
\fIdialtimeout\fR,
|
||||
\fIprotocol\fR
|
||||
.TP
|
||||
.B wait for dial in
|
||||
Wait for calls and accept incoming calls.
|
||||
.br
|
||||
Recommended options: \fIcli\fR and \fImsn\fR or \fIinmsn\fR.
|
||||
Possible options:
|
||||
\fIconnectdelay\fR,
|
||||
\fIcontroller\fR,
|
||||
\fIdialtimeout\fR,
|
||||
\fIprotocol\fR
|
||||
.TP
|
||||
.B wait for dial in and call back.
|
||||
Wait for calls, reject the call and then call back.
|
||||
.br
|
||||
Required options: \fIcbnumber\fR.
|
||||
Recommended options: \fIcli\fR and \fImsn\fR or \fIinmsn\fR.
|
||||
Other possible options:
|
||||
\fIcbdelay\fR,
|
||||
\fIconnectdelay\fR,
|
||||
\fIcontroller\fR,
|
||||
\fIdialtimeout\fR,
|
||||
\fIprotocol\fR
|
||||
|
||||
.TP
|
||||
.B leased line
|
||||
setup a leased line connection, with or without CAPI channel bundling
|
||||
.br
|
||||
Required options: \fIchannels\fR.
|
||||
Other possible options:
|
||||
\fIconnectdelay\fR,
|
||||
\fIcontroller\fR,
|
||||
\fIdialtimeout\fR and
|
||||
\fIprotocol\fR
|
||||
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.TP
|
||||
.B cbdelay \fI<seconds>
|
||||
Number of seconds to wait before callback, when acting as
|
||||
dialin server with callback. Default is 2 seconds.
|
||||
|
||||
.TP
|
||||
.B cbnumber \fI<phone numbers>
|
||||
Comma seperated list of phone numbers for call back, when acting as
|
||||
dialin server with callback.
|
||||
|
||||
.TP
|
||||
.B cbwait \fI<seconds>
|
||||
Time to wait for a call back, before giving up. Default is 60 seconds.
|
||||
|
||||
.TP
|
||||
.B channels \fI<channel specification>
|
||||
Comma seperated list of b-channels or ranges to activate leased line mode.
|
||||
|
||||
.TP
|
||||
.B cli \fI<telephon numbers>
|
||||
A comma seperated list of numbers from where incoming calls will be accepted.
|
||||
|
||||
.TP
|
||||
.B clicb
|
||||
Enable callback mode. When option \fInumber\fR is present, call number
|
||||
and wait for callback. When option \fInumber\fR is not present,
|
||||
wait for incoming call, reject the call and call back.
|
||||
This option is is optional if option \fIcbnumber\fR is present.
|
||||
|
||||
.TP
|
||||
.B connectdelay \fI<seconds>
|
||||
Number of seconds to wait after connecting is established,
|
||||
before PPP negotiation starts. Defaultvalue is 0 seconds.
|
||||
This option is use full, when connecting with protocol \fImodem\fR.
|
||||
Some internet access servers will hang up, if they get data immediatly
|
||||
after connection is established.
|
||||
|
||||
.TP
|
||||
.B controller \fI<controller specification>
|
||||
For point to multipoint \fI<controller specification\fR is only the
|
||||
CAPI2.0 controller number , default is 1.
|
||||
For point-to-point specify \fI<controller number>\fR,\fI<ddi>\fR,\fI<length of internal numbers\>
|
||||
|
||||
.TP
|
||||
.B dialmax \fI<times>
|
||||
Maximum number of times the list of phone numbers is tried before give up.
|
||||
Default is 4.
|
||||
|
||||
.TP
|
||||
.B dialtimeout \fI<seconds>
|
||||
Time to wait until connection established or failed before giving up.
|
||||
Default is 60 seconds.
|
||||
|
||||
.TP
|
||||
.B inmsn \fI<msn>
|
||||
Phone umber to listen on for calls, when different from option \fImsn\fR.
|
||||
|
||||
.TP
|
||||
.B msn \fI<msn>
|
||||
Phone umber from where to call out. Also used for incoming calls
|
||||
if option \fIinmsn\fR is not present.
|
||||
|
||||
.TP
|
||||
.B number \fI<phone numbers>
|
||||
Comma seperated list of phone numbers to call.
|
||||
Every number in the list is called until a connection can be established.
|
||||
When the end of the list is reached, the first number is called again.
|
||||
See option \fIdialmax\fR.
|
||||
|
||||
.TP
|
||||
.B numberprefix \fI<prefix>
|
||||
phone number to dial to get outline access. For example. \fInumberprefix 0\fR.
|
||||
|
||||
.TP
|
||||
.B protocol \fIhdlc\fR | \fIx75\fR | \fIv42bis\fR | \fImodem\fR
|
||||
ISDN protocol to use. With \fIhdlc\fR you need to add option \fIsync\fR
|
||||
to the pppd. With \fIx75\fR,\fIv42bis\fR and \fImodem\fR option \fIsync\fR
|
||||
MUST NOT be present. Defaultvalue is \fIhdlc\fR.
|
||||
Not all controllers support \fIv42bis\fR and \fImodem\fR.
|
||||
Use capiinfo(8) to see the features your controller support.
|
||||
|
||||
.TP
|
||||
.B redialdelay \fI<seconds>
|
||||
Number of seconds to wait between redialing. Default is 5 seconds.
|
||||
|
||||
.SH EXAMPLE FOR NORMAL DIAL OUT
|
||||
.LP
|
||||
Probably the most common use of pppd is to dial out to an ISP. This
|
||||
can be done with a command such as
|
||||
.IP
|
||||
pppd call isp
|
||||
.LP
|
||||
where the /etc/ppp/peers/isp file is set up by the system
|
||||
administrator to contain something like this:
|
||||
.IP
|
||||
sync
|
||||
.br
|
||||
noauth
|
||||
.br
|
||||
defaultroute
|
||||
.br
|
||||
name USERNAME
|
||||
.br
|
||||
plugin /etc/ppp/plugins/capiplugin.so
|
||||
.r
|
||||
msn MSN
|
||||
.br
|
||||
number PHONENUMBER
|
||||
.br
|
||||
protocol hdlc
|
||||
.br
|
||||
ipcp-accept-local
|
||||
.br
|
||||
ipcp-accept-remote
|
||||
.br
|
||||
/dev/null
|
||||
.LP
|
||||
where the /etc/ppp/pap-secrets and /etc/ppp/chap-secrets file is set up by
|
||||
the system administrator to contain something like this:
|
||||
.IP
|
||||
USERNAME * PASSWORD *
|
||||
|
||||
.SH EXAMPLE FOR DIAL OUT WITH CALLBACK
|
||||
.LP
|
||||
Dial out with callback can be done with a command such as
|
||||
.IP
|
||||
pppd call isp-callback
|
||||
.LP
|
||||
where the /etc/ppp/peers/isp-callback file is set up by the system
|
||||
administrator to contain something like this:
|
||||
.IP
|
||||
sync
|
||||
.br
|
||||
noauth
|
||||
.br
|
||||
defaultroute
|
||||
.br
|
||||
name USERNAME
|
||||
.br
|
||||
plugin /etc/ppp/plugins/capiplugin.so
|
||||
.br
|
||||
msn MSN
|
||||
.br
|
||||
number PHONENUMBER
|
||||
.br
|
||||
clicb
|
||||
.br
|
||||
cli PHONENUMBER
|
||||
.br
|
||||
protocol hdlc
|
||||
.br
|
||||
ipcp-accept-local
|
||||
.br
|
||||
ipcp-accept-remote
|
||||
.br
|
||||
/dev/null
|
||||
.LP
|
||||
where the /etc/ppp/pap-secrets and /etc/ppp/chap-secrets file is set up by
|
||||
the system administrator to contain something like this:
|
||||
.br
|
||||
USERNAME * PASSWORD *
|
||||
|
||||
.SH EXAMPLE FOR WAIT FOR DIAL IN WITHOUT CLI AUTHENTICATION
|
||||
.LP
|
||||
Wait for incoming calls, accept them according to options \fImsn\fR,
|
||||
\fIinmsn\fR, and \fIprotocol\fI.
|
||||
.LP
|
||||
Do not provide option \fIcli\fR to the capiplugin.
|
||||
Start a pppd for every b channel.
|
||||
Authorisation is made with PAP or CHAP and the ip numbers are assigned
|
||||
according to file /etc/ppp/pap-secrets or file /etc/ppp/chap-secrets.
|
||||
Let's assume the server has ip number 192.168.0.1 and the clients should
|
||||
have the ip numbers starting at 192.168.0.2 and the hostname of the
|
||||
server is \"dialinserver\".
|
||||
Add this two lines to the file /etc/inittab:
|
||||
.IP
|
||||
p0:23:respawn:/usr/sbin/pppd call incoming
|
||||
.br
|
||||
p1:23:respawn:/usr/sbin/pppd call incoming
|
||||
.LP
|
||||
where the /etc/ppp/peers/incoming file is set up
|
||||
to contain something like this:
|
||||
.IP
|
||||
sync
|
||||
.br
|
||||
auth
|
||||
.br
|
||||
persist
|
||||
.br
|
||||
plugin /etc/ppp/plugins/capiplugin.so
|
||||
.br
|
||||
inmsn MSN
|
||||
.br
|
||||
protocol hdlc
|
||||
192.168.0.1:
|
||||
.LP
|
||||
with the file /etc/ppp/pap-secrets and file /etc/ppp/chap-secrets file is set up
|
||||
to contain something like this:
|
||||
.IP
|
||||
user1 dialinserver PASSWORD1 192.168.0.2
|
||||
.br
|
||||
user2 dialinserver PASSWORD2 192.168.0.2
|
||||
|
||||
.SH EXAMPLE FOR WAIT FOR DIAL IN WITH CLI AUTHENTICATION
|
||||
.LP
|
||||
Wait for incoming calls, accept them according to options \fImsn\fR,
|
||||
\fIinmsn\fR, \fIcli\fR and \fIprotocol\fI.
|
||||
.LP
|
||||
Start a pppd for every client.
|
||||
Let's assume the server has ip number 192.168.0.1 and the clients should
|
||||
have the ip numbers starting at 192.168.0.2.
|
||||
Add this three lines to file /etc/inittab:
|
||||
.IP
|
||||
p0:23:respawn:/usr/sbin/pppd call incoming cli 04711 192.168.0.1:192.168.0.2
|
||||
.br
|
||||
p1:23:respawn:/usr/sbin/pppd call incoming cli 04712 192.168.0.1:192.168.0.3
|
||||
.br
|
||||
p2:23:respawn:/usr/sbin/pppd call incoming cli 04713 192.168.0.1:192.168.0.4
|
||||
|
||||
.LP
|
||||
where the /etc/ppp/peers/incoming file is set up
|
||||
to contain something like this:
|
||||
.IP
|
||||
sync
|
||||
.br
|
||||
auth
|
||||
.br
|
||||
persist
|
||||
.br
|
||||
plugin /etc/ppp/plugins/capiplugin.so
|
||||
.br
|
||||
inmsn MSN
|
||||
.br
|
||||
protocol hdlc
|
||||
|
||||
.SH EXAMPLE FOR WAIT FOR DIAL IN WITH CLI AUTHENTICATION AND CALLBACK
|
||||
.LP
|
||||
Wait for incoming calls, accept them according to options \fImsn\fR,
|
||||
\fIinmsn\fR, \fIcli\fR and \fIprotocol\fI, reject incoming calls
|
||||
and call back.
|
||||
.LP
|
||||
.B start a pppd for every client
|
||||
Let assume the server has ip numbers 192.168.0.1 and the clients should
|
||||
have the ip numbers starting at 192.168.0.2.
|
||||
Add this three lines to the file /etc/inittab.
|
||||
.IP
|
||||
p0:23:respawn:/usr/sbin/pppd call incoming cli 04711 cbnumber 4711 192.168.0.1:192.168.0.2
|
||||
.br
|
||||
p1:23:respawn:/usr/sbin/pppd call incoming cli 04712 cbnumber 4712 192.168.0.1:192.168.0.3
|
||||
.br
|
||||
p2:23:respawn:/usr/sbin/pppd call incoming cli 04713 cbnumber 4713 192.168.0.1:192.168.0.4
|
||||
|
||||
.LP
|
||||
where the /etc/ppp/peers/incoming file is set up
|
||||
to contain something like this:
|
||||
.IP
|
||||
sync
|
||||
.br
|
||||
auth
|
||||
.br
|
||||
persist
|
||||
.br
|
||||
plugin /etc/ppp/plugins/capiplugin.so
|
||||
.br
|
||||
inmsn MSN
|
||||
.br
|
||||
protocol hdlc
|
||||
|
||||
.SH CAVEATS
|
||||
.LP
|
||||
Every pppd waiting for incoming calls can get an incoming call first.
|
||||
So when you start two pppd listening on the same MSN, one with
|
||||
CLI Authentication and the other not, the following can happen:
|
||||
.IP
|
||||
The Client with the CLI specified to the first pppd calls, but the pppd
|
||||
without option \fIcli\fR will get the call first and accepts the call.
|
||||
.LP
|
||||
So if you want to mix CLI Authentication and PAP/CHAP Authentication
|
||||
use one MSN for CLI authenticated calls and another for the PAP/CHAP
|
||||
authenticated calls.
|
||||
|
||||
.SH DIAGNOSTICS
|
||||
.LP
|
||||
Messages are sent to the syslog daemon like pppd did usually, see
|
||||
pppd manual page.
|
||||
|
||||
.SH SEE ALSO
|
||||
pppd(8), capiinfo(8), capiinit(8), capictrl(8)
|
||||
|
||||
.SH AUTHORS
|
||||
Carsten Paeth (calle@calle.in-berlin.de)
|
|
@ -8,35 +8,78 @@
|
|||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include "pppd.h"
|
||||
#include "capiconn.h"
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
static char *revision = "$Revision: 1.5 $";
|
||||
static char *revision = "$Revision: 1.6 $";
|
||||
|
||||
static capiconn_context *ctx;
|
||||
static capi_connection *conn = 0;
|
||||
static int isconnected = 0;
|
||||
static unsigned applid;
|
||||
#define CM(x) (1<<(x))
|
||||
#define CIPMASK_ALL 0x1FFF03FF
|
||||
#define CIPMASK_VOICE (CM(1)|CM(4)|CM(5)|CM(16)|CM(26))
|
||||
#define CIPMASK_DATA (CM(2)|CM(3))
|
||||
static unsigned long cipmask = CIPMASK_ALL;
|
||||
static int controller = 1;
|
||||
static capi_contrinfo cinfo = { 0 , 0, 0 };
|
||||
|
||||
static int opt_contr = 1;
|
||||
static char *opt_controller = "1";
|
||||
static char *opt_numberprefix = 0;
|
||||
static char *opt_number = 0;
|
||||
static char *opt_callbacknumber = 0;
|
||||
static char *opt_msn = 0;
|
||||
static char *opt_inmsn = 0;
|
||||
static char *opt_proto = 0;
|
||||
static char *opt_channels = 0;
|
||||
static unsigned char AdditionalInfo[1+2+2+31];
|
||||
static int opt_dialtimeout = 60;
|
||||
static int opt_dialmax = 4;
|
||||
static int opt_redialdelay = 5;
|
||||
static int opt_cbdelay = 2;
|
||||
static int opt_connectdelay = 0;
|
||||
|
||||
static char *opt_cli = 0;
|
||||
static int opt_cbflag = 0;
|
||||
static int opt_cbwait = 60;
|
||||
static int opt_acceptdelayflag = 0;
|
||||
|
||||
typedef struct stringlist {
|
||||
struct stringlist *next;
|
||||
char *s;
|
||||
} STRINGLIST;
|
||||
|
||||
static STRINGLIST *numbers;
|
||||
static STRINGLIST *callbacknumbers;
|
||||
static STRINGLIST *clis;
|
||||
static STRINGLIST *parsed_controller;
|
||||
|
||||
static int optcb(void)
|
||||
{
|
||||
return opt_cbflag = 1;
|
||||
}
|
||||
static int optacceptdelay(void)
|
||||
{
|
||||
return opt_acceptdelayflag = 1;
|
||||
}
|
||||
|
||||
static option_t my_options[] = {
|
||||
{
|
||||
"controller", o_int, &opt_contr,
|
||||
"capi controller"
|
||||
"controller", o_string, &opt_controller,
|
||||
"capi controller specification"
|
||||
},
|
||||
{
|
||||
"number", o_string, &opt_number,
|
||||
"number to call"
|
||||
"number to call (may be comma separated)"
|
||||
},
|
||||
{
|
||||
"numberprefix", o_string, &opt_numberprefix,
|
||||
|
@ -48,13 +91,112 @@ static option_t my_options[] = {
|
|||
},
|
||||
{
|
||||
"protocol", o_string, &opt_proto,
|
||||
"protocol x75 or hdlc"
|
||||
"protocol x75, hdlc or modem"
|
||||
},
|
||||
{
|
||||
"inmsn", o_string, &opt_inmsn,
|
||||
"called number for incoming calls"
|
||||
},
|
||||
{
|
||||
"cli", o_string, &opt_cli,
|
||||
"calling number for incoming calls (may be comma separated list)"
|
||||
},
|
||||
{
|
||||
"clicb", o_special_noarg, &optcb,
|
||||
"call number and wait for callback"
|
||||
},
|
||||
{
|
||||
"cbwait", o_int, &opt_cbwait,
|
||||
"number of seconds to wait for callback"
|
||||
},
|
||||
{
|
||||
"dialtimeout", o_int, &opt_dialtimeout,
|
||||
"number of seconds to wait for connection or reject"
|
||||
},
|
||||
{
|
||||
"dialmax", o_int, &opt_dialmax,
|
||||
"number of dial retries"
|
||||
},
|
||||
{
|
||||
"redialdelay", o_int, &opt_redialdelay,
|
||||
"number of seconds to wait between dial retries"
|
||||
},
|
||||
{
|
||||
"channels", o_string, &opt_channels,
|
||||
"channel to use for leased line (may be comma separated list)"
|
||||
},
|
||||
|
||||
{
|
||||
"cbdelay", o_int, &opt_cbdelay,
|
||||
"number of seconds to wait before calling back"
|
||||
},
|
||||
{
|
||||
"cbnumber", o_string, &opt_callbacknumber,
|
||||
"number to call (may be comma separated)"
|
||||
},
|
||||
{
|
||||
"connectdelay", o_int, &opt_connectdelay,
|
||||
"number of seconds to wait after connection is established"
|
||||
},
|
||||
{
|
||||
"acceptdelay", o_special_noarg, &optacceptdelay,
|
||||
"wait 1 second before accept incoming call"
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void stringlist_free(STRINGLIST **pp)
|
||||
{
|
||||
STRINGLIST *p, *next;
|
||||
|
||||
p = *pp;
|
||||
while (p) {
|
||||
next = p->next;
|
||||
if (p->s) free(p->s);
|
||||
free(p);
|
||||
p = next;
|
||||
}
|
||||
*pp = 0;
|
||||
}
|
||||
|
||||
static int stringlist_append_string(STRINGLIST **pp, char *s)
|
||||
{
|
||||
STRINGLIST *p;
|
||||
for (; *pp; pp = &(*pp)->next) ;
|
||||
if ((p = (STRINGLIST *)malloc(sizeof(STRINGLIST))) == 0)
|
||||
return -1;
|
||||
memset(p, 0, sizeof(STRINGLIST));
|
||||
if ((p->s = strdup(s)) == 0) {
|
||||
free(p);
|
||||
return -1;
|
||||
}
|
||||
p->next = 0;
|
||||
*pp = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static STRINGLIST *stringlist_split(char *tosplit, char *seps)
|
||||
{
|
||||
STRINGLIST *p = 0;
|
||||
char *str = strdup(tosplit);
|
||||
char *s;
|
||||
if (!str) return 0;
|
||||
for (s = strtok(str, seps); s; s = strtok(0, seps)) {
|
||||
if (*s == 0) continue; /* if strtok is not working correkt */
|
||||
if (stringlist_append_string(&p, s) < 0) {
|
||||
stringlist_free(&p);
|
||||
free(str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
free(str);
|
||||
return p;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static int timeoutrunning = 0;
|
||||
static int timeoutshouldrun = 0;
|
||||
|
||||
|
@ -85,112 +227,474 @@ static void unsetup_timeout(void)
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void dodisconnect(void)
|
||||
static void handlemessages(void)
|
||||
{
|
||||
if (!conn)
|
||||
return;
|
||||
(void)capiconn_disconnect(conn, 0);
|
||||
while (conn) {
|
||||
unsigned char *msg = 0;
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
if (capi20_waitformessage(applid, &tv) == 0) {
|
||||
if (capi20_get_message (applid, &msg) == 0)
|
||||
capiconn_inject(applid, msg);
|
||||
}
|
||||
unsigned char *msg = 0;
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
if (capi20_waitformessage(applid, &tv) == 0) {
|
||||
if (capi20_get_message(applid, &msg) == 0)
|
||||
capiconn_inject(applid, msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void makeconnection(void)
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void dodisconnect(void)
|
||||
{
|
||||
time_t t;
|
||||
if (!conn)
|
||||
return;
|
||||
(void)capiconn_disconnect(conn, 0);
|
||||
t = time(0)+10;
|
||||
while (conn && time(0) < t)
|
||||
handlemessages();
|
||||
if (conn)
|
||||
fatal("capiplugin: timeout while waiting for disconnect");
|
||||
}
|
||||
|
||||
static void setupconnection(char *num)
|
||||
{
|
||||
char number[256];
|
||||
|
||||
if (opt_number == 0) {
|
||||
fatal("capiplugin: no number");
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(number, sizeof(number), "%s%s",
|
||||
opt_numberprefix ? opt_numberprefix : "",
|
||||
opt_number);
|
||||
opt_numberprefix ? opt_numberprefix : "", num);
|
||||
|
||||
if (opt_proto == 0 || strcasecmp(opt_proto, "hdlc") == 0) {
|
||||
conn = capiconn_connect(ctx,
|
||||
opt_contr, /* contr */
|
||||
controller, /* contr */
|
||||
2, /* cipvalue */
|
||||
number,
|
||||
opt_msn,
|
||||
opt_channels ? 0 : number,
|
||||
opt_channels ? 0 : opt_msn,
|
||||
0, 1, 0,
|
||||
0, 0, 0, 0, 0);
|
||||
0, 0, 0,
|
||||
opt_channels ? AdditionalInfo : 0,
|
||||
0);
|
||||
} else if (strcasecmp(opt_proto, "x75") == 0) {
|
||||
conn = capiconn_connect(ctx,
|
||||
opt_contr, /* contr */
|
||||
controller, /* contr */
|
||||
2, /* cipvalue */
|
||||
number,
|
||||
opt_msn,
|
||||
opt_channels ? 0 : number,
|
||||
opt_channels ? 0 : opt_msn,
|
||||
0, 0, 0,
|
||||
0, 0, 0, 0, 0);
|
||||
0, 0, 0,
|
||||
opt_channels ? AdditionalInfo : 0,
|
||||
0);
|
||||
} else if (strcasecmp(opt_proto, "v42bis") == 0) {
|
||||
conn = capiconn_connect(ctx,
|
||||
controller, /* contr */
|
||||
2, /* cipvalue */
|
||||
opt_channels ? 0 : number,
|
||||
opt_channels ? 0 : opt_msn,
|
||||
0, 8, 0,
|
||||
0, 0, 0,
|
||||
opt_channels ? AdditionalInfo : 0,
|
||||
0);
|
||||
} else if (strcasecmp(opt_proto, "modem") == 0) {
|
||||
conn = capiconn_connect(ctx,
|
||||
opt_contr, /* contr */
|
||||
controller, /* contr */
|
||||
1, /* cipvalue */
|
||||
number,
|
||||
opt_msn,
|
||||
opt_channels ? 0 : number,
|
||||
opt_channels ? 0 : opt_msn,
|
||||
8, 1, 0,
|
||||
0, 0, 0, 0, 0);
|
||||
0, 0, 0,
|
||||
opt_channels ? AdditionalInfo : 0,
|
||||
0);
|
||||
} else {
|
||||
fatal("capiplugin: unknown protocol \"%s\"", opt_proto);
|
||||
return;
|
||||
}
|
||||
while (!isconnected && conn) {
|
||||
unsigned char *msg = 0;
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
if (capi20_waitformessage(applid, &tv) == 0) {
|
||||
if (capi20_get_message (applid, &msg) == 0)
|
||||
capiconn_inject(applid, msg);
|
||||
if (opt_channels) {
|
||||
info("capiplugin: leased line (%s)",
|
||||
opt_proto ? opt_proto : "hdlc");
|
||||
} else {
|
||||
info("capiplugin: dial %s (%s)",
|
||||
number, opt_proto ? opt_proto : "hdlc");
|
||||
}
|
||||
}
|
||||
|
||||
static void makeleasedline(void)
|
||||
{
|
||||
time_t t;
|
||||
|
||||
setupconnection("");
|
||||
|
||||
t = time(0)+opt_dialtimeout;
|
||||
do {
|
||||
handlemessages();
|
||||
if (status != EXIT_OK && conn)
|
||||
dodisconnect();
|
||||
} while (time(0) < t && conn && !isconnected);
|
||||
|
||||
if (status != EXIT_OK)
|
||||
die(status);
|
||||
|
||||
if (conn && isconnected) {
|
||||
t = time(0)+opt_connectdelay;
|
||||
do {
|
||||
handlemessages();
|
||||
} while (time(0) < t);
|
||||
}
|
||||
|
||||
if (status != EXIT_OK)
|
||||
die(status);
|
||||
|
||||
if (!conn)
|
||||
fatal("capiplugin: couldn't make connection");
|
||||
}
|
||||
|
||||
static void makeconnection(STRINGLIST *numbers)
|
||||
{
|
||||
time_t t;
|
||||
STRINGLIST *p;
|
||||
int retry = 0;
|
||||
|
||||
do {
|
||||
for (p = numbers; p; p = p->next) {
|
||||
if (retry || p != numbers) {
|
||||
t = time(0)+opt_redialdelay;
|
||||
do {
|
||||
handlemessages();
|
||||
if (status != EXIT_OK)
|
||||
die(status);
|
||||
} while (time(0) < t);
|
||||
}
|
||||
|
||||
setupconnection(p->s);
|
||||
|
||||
t = time(0)+opt_dialtimeout;
|
||||
do {
|
||||
handlemessages();
|
||||
if (status != EXIT_OK && conn)
|
||||
dodisconnect();
|
||||
} while (time(0) < t && conn && !isconnected);
|
||||
|
||||
if (conn && isconnected)
|
||||
goto connected;
|
||||
|
||||
if (status != EXIT_OK)
|
||||
die(status);
|
||||
}
|
||||
} while (++retry < opt_dialmax);
|
||||
connected:
|
||||
|
||||
if (!conn)
|
||||
fatal("capiplugin: couldn't make connection after %d retries",
|
||||
retry);
|
||||
}
|
||||
|
||||
static void makeconnection_with_callback(void)
|
||||
{
|
||||
STRINGLIST *p;
|
||||
time_t t;
|
||||
|
||||
for (p = numbers; p; p = p->next) {
|
||||
|
||||
setupconnection(p->s);
|
||||
|
||||
info("capiplugin: wait for call reject");
|
||||
/* Wait specific time for the server rejecting the call */
|
||||
t = time(0)+opt_dialtimeout;
|
||||
do {
|
||||
handlemessages();
|
||||
if (status != EXIT_OK)
|
||||
die(status);
|
||||
} while (time(0) < t && conn && !isconnected);
|
||||
|
||||
if (!conn) { /* Call has been rejected */
|
||||
|
||||
(void) capiconn_listen(ctx, controller, cipmask, 0);
|
||||
info("capiplugin: waiting for callback...");
|
||||
|
||||
/* Wait for server calling back */
|
||||
t = time(0)+opt_cbwait;
|
||||
do {
|
||||
handlemessages();
|
||||
if (status != EXIT_OK) {
|
||||
(void) capiconn_listen(ctx, controller, 0, 0);
|
||||
die(status);
|
||||
}
|
||||
} while (!isconnected && time(0) < t);
|
||||
|
||||
if (isconnected) {
|
||||
add_fd(capi20_fileno(applid));
|
||||
setup_timeout();
|
||||
return;
|
||||
}
|
||||
if (p->next == 0)
|
||||
fatal("capiplugin: callback failed (no call)");
|
||||
else
|
||||
info("capiplugin: callback failed (no call)");
|
||||
} else {
|
||||
dodisconnect();
|
||||
fatal("capiplugin: callback failed (no reject)");
|
||||
}
|
||||
}
|
||||
if (!conn)
|
||||
fatal("capiplugin: couldn't make connection");
|
||||
}
|
||||
|
||||
static void makecallback(void)
|
||||
{
|
||||
time_t t;
|
||||
|
||||
t = time(0)+opt_cbdelay;
|
||||
do {
|
||||
handlemessages();
|
||||
if (status != EXIT_OK)
|
||||
die(status);
|
||||
} while (time(0) < t);
|
||||
|
||||
makeconnection(callbacknumbers);
|
||||
}
|
||||
|
||||
static void waitforcall(void)
|
||||
{
|
||||
(void) capiconn_listen(ctx, controller, cipmask, 0);
|
||||
info("capiplugin: waiting for incoming call ...");
|
||||
|
||||
do {
|
||||
handlemessages();
|
||||
if (status != EXIT_OK) {
|
||||
(void) capiconn_listen(ctx, controller, 0, 0);
|
||||
die(status);
|
||||
}
|
||||
} while (!isconnected);
|
||||
|
||||
add_fd(capi20_fileno(applid));
|
||||
setup_timeout();
|
||||
}
|
||||
|
||||
static void init_capiconn(void)
|
||||
{
|
||||
static capi_contrinfo cinfo = { 0 , 0, 0 };
|
||||
static int init = 0;
|
||||
|
||||
if (init)
|
||||
return;
|
||||
init = 1;
|
||||
|
||||
if (capiconn_addcontr(ctx, opt_contr, &cinfo) != CAPICONN_OK) {
|
||||
if (capiconn_addcontr(ctx, controller, &cinfo) != CAPICONN_OK) {
|
||||
(void)capiconn_freecontext(ctx);
|
||||
(void)capi20_release(applid);
|
||||
fatal("capiplugin: add controller %d failed", opt_contr);
|
||||
fatal("capiplugin: add controller %d failed", controller);
|
||||
return;
|
||||
}
|
||||
if (cinfo.ddi)
|
||||
dbglog("capiplugin: contr=%d ddi=\"%s\" n=%d",
|
||||
controller, cinfo.ddi, cinfo.ndigits);
|
||||
else
|
||||
dbglog("capiplugin: contr=%d", controller);
|
||||
|
||||
add_fd(capi20_fileno(applid));
|
||||
setup_timeout();
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle leased lines (CAPI-Bundling)
|
||||
*/
|
||||
|
||||
static int decodechannels(char *teln, unsigned long *bmaskp, int *activep)
|
||||
{
|
||||
unsigned long bmask = 0;
|
||||
int active = !0;
|
||||
char *s;
|
||||
int channel;
|
||||
int i;
|
||||
|
||||
s = teln;
|
||||
while (*s && *s == ' ') s++;
|
||||
if (!*s)
|
||||
fatal("capiplugin; option channels: list empty");
|
||||
if (*s == 'p' || *s == 'P') {
|
||||
active = 0;
|
||||
s++;
|
||||
}
|
||||
if (*s == 'a' || *s == 'A') {
|
||||
active = !0;
|
||||
s++;
|
||||
}
|
||||
while (*s) {
|
||||
int digit1 = 0;
|
||||
int digit2 = 0;
|
||||
if (!isdigit(*s))
|
||||
goto illegal;
|
||||
while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; }
|
||||
channel = digit1;
|
||||
if (channel <= 0 && channel > 30)
|
||||
goto rangeerror;
|
||||
if (*s == 0 || *s == ',' || *s == ' ') {
|
||||
bmask |= (1 << digit1);
|
||||
digit1 = 0;
|
||||
if (*s) s++;
|
||||
continue;
|
||||
}
|
||||
if (*s != '-')
|
||||
goto illegal;
|
||||
s++;
|
||||
if (!isdigit(*s)) return -3;
|
||||
while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; }
|
||||
channel = digit2;
|
||||
if (channel <= 0 && channel > 30)
|
||||
goto rangeerror;
|
||||
if (*s == 0 || *s == ',' || *s == ' ') {
|
||||
if (digit1 > digit2)
|
||||
for (i = digit2; i <= digit1 ; i++)
|
||||
bmask |= (1 << i);
|
||||
else
|
||||
for (i = digit1; i <= digit2 ; i++)
|
||||
bmask |= (1 << i);
|
||||
digit1 = digit2 = 0;
|
||||
if (*s) s++;
|
||||
continue;
|
||||
}
|
||||
goto illegal;
|
||||
}
|
||||
if (activep) *activep = active;
|
||||
if (bmaskp) *bmaskp = bmask;
|
||||
return 0;
|
||||
illegal:
|
||||
fatal("capiplugin: option channels: illegal octet '%c'", *s);
|
||||
return -1;
|
||||
rangeerror:
|
||||
fatal("capiplugin: option channels: channel %d out of range", channel);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int channels2capi20(char *teln, unsigned char *AdditionalInfo)
|
||||
{
|
||||
unsigned long bmask;
|
||||
int active;
|
||||
int i;
|
||||
|
||||
decodechannels(teln, &bmask, &active);
|
||||
/* info("capiplugin: \"%s\" 0x%lx %d\n", teln, bmask, active); */
|
||||
/* Length */
|
||||
AdditionalInfo[0] = 2+2+31;
|
||||
/* Channel: 3 => use channel allocation */
|
||||
AdditionalInfo[1] = 3; AdditionalInfo[2] = 0;
|
||||
/* Operation: 0 => DTE mode, 1 => DCE mode */
|
||||
if (active) {
|
||||
AdditionalInfo[3] = 0; AdditionalInfo[4] = 0;
|
||||
} else {
|
||||
AdditionalInfo[3] = 1; AdditionalInfo[4] = 0;
|
||||
}
|
||||
/* Channel mask array */
|
||||
AdditionalInfo[5] = 0; /* no D-Channel */
|
||||
for (i=1; i <= 30; i++)
|
||||
AdditionalInfo[5+i] = (bmask & (1 << i)) ? 0xff : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_options(void)
|
||||
{
|
||||
if ( opt_proto
|
||||
&& strcasecmp(opt_proto, "hdlc")
|
||||
&& strcasecmp(opt_proto, "x75")
|
||||
&& strcasecmp(opt_proto, "v42bis")
|
||||
&& strcasecmp(opt_proto, "modem")) {
|
||||
option_error("capiplugin: unknown protocol \"%s\"", opt_proto);
|
||||
die(1);
|
||||
}
|
||||
if (strcasecmp(opt_proto, "modem") == 0)
|
||||
cipmask = CIPMASK_VOICE;
|
||||
else cipmask = CIPMASK_DATA;
|
||||
|
||||
if (opt_channels) {
|
||||
channels2capi20(opt_channels, AdditionalInfo);
|
||||
if (opt_number)
|
||||
option_error("capiplugin: option number ignored");
|
||||
if (opt_numberprefix)
|
||||
option_error("capiplugin: option numberprefix ignored");
|
||||
if (opt_callbacknumber)
|
||||
option_error("capiplugin: option callbacknumber ignored");
|
||||
if (opt_msn)
|
||||
option_error("capiplugin: option msn ignored");
|
||||
if (opt_inmsn)
|
||||
option_error("capiplugin: option inmsn ignored");
|
||||
} else if (opt_number) {
|
||||
stringlist_free(&numbers);
|
||||
numbers = stringlist_split(opt_number, " \t,");
|
||||
if (opt_callbacknumber)
|
||||
option_error("capiplugin: option callbacknumber ignored");
|
||||
} else if (opt_cbflag) {
|
||||
if (opt_callbacknumber == 0) {
|
||||
option_error("capiplugin: option callbacknumber missing");
|
||||
die(1);
|
||||
}
|
||||
stringlist_free(&callbacknumbers);
|
||||
callbacknumbers = stringlist_split(opt_callbacknumber, " \t,");
|
||||
} else {
|
||||
if (opt_callbacknumber) {
|
||||
opt_cbflag = 1;
|
||||
stringlist_free(&callbacknumbers);
|
||||
callbacknumbers = stringlist_split(opt_callbacknumber, " \t,");
|
||||
}
|
||||
}
|
||||
if (opt_cli) {
|
||||
stringlist_free(&clis);
|
||||
clis = stringlist_split(opt_cli, " \t,");
|
||||
}
|
||||
if (opt_controller) {
|
||||
STRINGLIST *sl;
|
||||
char *tmp;
|
||||
stringlist_free(&parsed_controller);
|
||||
memset(&cinfo, 0, sizeof(cinfo));
|
||||
parsed_controller = stringlist_split(opt_controller, " \t,");
|
||||
sl = parsed_controller;
|
||||
if (!sl) goto illcontr;
|
||||
tmp = sl->s;
|
||||
controller = strtol(sl->s, &tmp, 10);
|
||||
if (tmp == sl->s || *tmp) goto illcontr;
|
||||
if (sl->next) {
|
||||
sl = sl->next;
|
||||
cinfo.ddi = sl->s;
|
||||
if (sl->next && sl->next->s) {
|
||||
sl = sl->next;
|
||||
cinfo.ndigits = strtol(sl->s, &tmp, 10);
|
||||
if (tmp == sl->s || *tmp) goto illcontr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memset(&cinfo, 0, sizeof(cinfo));
|
||||
controller = 1;
|
||||
}
|
||||
return;
|
||||
|
||||
illcontr:
|
||||
option_error("capiplugin: illegal controller specification \"%s\"",
|
||||
opt_controller);
|
||||
die(1);
|
||||
}
|
||||
|
||||
static int capi_new_phase_hook(int phase)
|
||||
{
|
||||
int fd;
|
||||
switch (phase) {
|
||||
case PHASE_DEAD:
|
||||
info("capiplugin: phase dead");
|
||||
if ((fd = capi20_fileno(applid)) >= 0)
|
||||
remove_fd(fd);
|
||||
unsetup_timeout();
|
||||
dodisconnect();
|
||||
break;
|
||||
case PHASE_INITIALIZE:
|
||||
info("capiplugin: phase initialize");
|
||||
break;
|
||||
case PHASE_SERIALCONN:
|
||||
info("capiplugin: phase serialconn");
|
||||
info("capiplugin: phase serialconn%s",
|
||||
opt_cbflag ? " (callback)" : "");
|
||||
check_options();
|
||||
init_capiconn();
|
||||
makeconnection();
|
||||
if (opt_number) {
|
||||
if (opt_cbflag) {
|
||||
makeconnection_with_callback();
|
||||
} else {
|
||||
makeconnection(numbers);
|
||||
}
|
||||
} else if (opt_channels) {
|
||||
makeleasedline();
|
||||
} else {
|
||||
waitforcall();
|
||||
}
|
||||
break;
|
||||
case PHASE_DORMANT:
|
||||
info("capiplugin: phase dormant");
|
||||
|
@ -212,9 +716,6 @@ static int capi_new_phase_hook(int phase)
|
|||
break;
|
||||
case PHASE_TERMINATE:
|
||||
info("capiplugin: phase terminate");
|
||||
if ((fd = capi20_fileno(applid)) >= 0)
|
||||
remove_fd(fd);
|
||||
unsetup_timeout();
|
||||
break;
|
||||
case PHASE_DISCONNECT:
|
||||
info("capiplugin: phase disconnect");
|
||||
|
@ -232,13 +733,28 @@ static char *conninfo(capi_connection *p)
|
|||
{
|
||||
static char buf[1024];
|
||||
capi_conninfo *cp = capiconn_getinfo(p);
|
||||
char *callingnumber = "";
|
||||
char *callednumber = "";
|
||||
|
||||
snprintf(buf, sizeof(buf),
|
||||
"plci=0x%x ncci=0x%x %s",
|
||||
cp->plci,
|
||||
cp->ncci,
|
||||
cp->isincoming ? "incoming" : "outgoing"
|
||||
);
|
||||
if (cp->callingnumber && cp->callingnumber[0] > 2)
|
||||
callingnumber = cp->callingnumber+3;
|
||||
if (cp->callednumber && cp->callednumber[0] > 1)
|
||||
callednumber = cp->callednumber+2;
|
||||
|
||||
if (debug) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"\"%s\" -> \"%s\" %s (pcli=0x%x/ncci=0x%x)",
|
||||
callingnumber, callednumber,
|
||||
cp->isincoming ? "incoming" : "outgoing",
|
||||
cp->plci, cp->ncci
|
||||
);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"\"%s\" -> \"%s\" %s",
|
||||
callingnumber, callednumber,
|
||||
cp->isincoming ? "incoming" : "outgoing");
|
||||
}
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -247,14 +763,136 @@ static void disconnected(capi_connection *cp,
|
|||
unsigned reason,
|
||||
unsigned reason_b3)
|
||||
{
|
||||
info("capiplugin: disconnected(%s): %s: 0x%04x (0x%04x) - %s",
|
||||
conninfo(cp),
|
||||
if (reason != 0x3304 || debug) /* Another Applikation got the call */
|
||||
info("capiplugin: disconnect(%s): %s 0x%04x (0x%04x) - %s",
|
||||
localdisconnect ? "local" : "remote",
|
||||
conninfo(cp),
|
||||
reason, reason_b3, capi_info2str(reason));
|
||||
conn = 0;
|
||||
isconnected = 0;
|
||||
}
|
||||
|
||||
static void incoming(capi_connection *cp,
|
||||
unsigned contr,
|
||||
unsigned cipvalue,
|
||||
char *callednumber,
|
||||
char *callingnumber)
|
||||
{
|
||||
STRINGLIST *p;
|
||||
char *s;
|
||||
|
||||
info("capiplugin: incoming call: %s (0x%x)", conninfo(cp), cipvalue);
|
||||
|
||||
if (opt_inmsn) {
|
||||
if ( (s = strstr(callednumber, opt_inmsn)) == 0
|
||||
|| strcmp(s, opt_inmsn) != 0) {
|
||||
info("capiplugin: ignoring call, msn mismatch (%s != %s)",
|
||||
opt_inmsn, callednumber);
|
||||
(void) capiconn_ignore(cp);
|
||||
return;
|
||||
}
|
||||
} else if (opt_msn) {
|
||||
if ( (s = strstr(callednumber, opt_msn)) == 0
|
||||
|| strcmp(s, opt_msn) != 0) {
|
||||
info("capiplugin: ignoring call, msn mismatch (%s != %s)",
|
||||
opt_msn, callednumber);
|
||||
(void) capiconn_ignore(cp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_cli) {
|
||||
for (p = clis; p; p = p->next) {
|
||||
if (strcmp(p->s, callingnumber) == 0)
|
||||
break;
|
||||
}
|
||||
if (!p) {
|
||||
info("capiplugin: ignoring call, cli mismatch (%s != %s)",
|
||||
opt_cli, callingnumber);
|
||||
(void) capiconn_ignore(cp);
|
||||
return;
|
||||
}
|
||||
} else if (opt_number) {
|
||||
for (p = numbers; p; p = p->next) {
|
||||
if ( (s = strstr(callingnumber, p->s)) != 0
|
||||
|| strcmp(s, p->s) == 0)
|
||||
break;
|
||||
}
|
||||
if (!p) {
|
||||
info("capiplugin: ignoring call, number mismatch (%s != %s)",
|
||||
opt_number, callingnumber);
|
||||
(void) capiconn_ignore(cp);
|
||||
return;
|
||||
}
|
||||
} else if (opt_acceptdelayflag) {
|
||||
/*
|
||||
* non cli or number match,
|
||||
* give more specific listen a chance (bad)
|
||||
*/
|
||||
info("capiplugin: accept delayed, no cli or number match");
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
switch (cipvalue) {
|
||||
case 1: /* Speech */
|
||||
case 4: /* 3.1 kHz audio */
|
||||
case 5: /* 7 kHz audio */
|
||||
case 16: /* Telephony */
|
||||
case 26: /* 7 kHz telephony */
|
||||
if (opt_proto && strcasecmp(opt_proto, "modem") == 0) {
|
||||
if (opt_cbflag) goto callback;
|
||||
(void) capiconn_accept(cp, 8, 1, 0, 0, 0, 0, 0);
|
||||
goto accepted;
|
||||
} else {
|
||||
info("capiplugin: ignoring speech call from %s",
|
||||
callingnumber);
|
||||
(void) capiconn_ignore(cp);
|
||||
}
|
||||
break;
|
||||
case 2: /* Unrestricted digital information */
|
||||
case 3: /* Restricted digital information */
|
||||
if (opt_proto == 0
|
||||
|| strcasecmp(opt_proto, "hdlc") == 0) {
|
||||
if (opt_cbflag) goto callback;
|
||||
(void) capiconn_accept(cp, 0, 1, 0, 0, 0, 0, 0);
|
||||
goto accepted;
|
||||
} else if (strcasecmp(opt_proto, "x75") == 0) {
|
||||
if (opt_cbflag) goto callback;
|
||||
(void) capiconn_accept(cp, 0, 0, 0, 0, 0, 0, 0);
|
||||
goto accepted;
|
||||
} else if (strcasecmp(opt_proto, "v42bis") == 0) {
|
||||
if (opt_cbflag) goto callback;
|
||||
(void) capiconn_accept(cp, 0, 8, 0, 0, 0, 0, 0);
|
||||
goto accepted;
|
||||
} else {
|
||||
info("capiplugin: ignoring digital call from %s",
|
||||
callingnumber);
|
||||
(void) capiconn_ignore(cp);
|
||||
}
|
||||
break;
|
||||
case 17: /* Group 2/3 facsimile */
|
||||
info("capiplugin: ignoring fax call from %s",
|
||||
callingnumber);
|
||||
(void) capiconn_ignore(cp);
|
||||
break;
|
||||
default:
|
||||
info("capiplugin: ignoring type %d call from %s",
|
||||
cipvalue, callingnumber);
|
||||
(void) capiconn_ignore(cp);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
accepted:
|
||||
(void) capiconn_listen(ctx, controller, 0, 0);
|
||||
return;
|
||||
callback:
|
||||
(void) capiconn_listen(ctx, controller, 0, 0);
|
||||
info("capiplugin: rejecting call: %s (0x%x)", conninfo(cp), cipvalue);
|
||||
capiconn_reject(cp);
|
||||
makecallback();
|
||||
return;
|
||||
}
|
||||
|
||||
static void connected(capi_connection *cp, _cstruct NCPI)
|
||||
{
|
||||
capi_conninfo *p = capiconn_getinfo(cp);
|
||||
|
@ -262,8 +900,10 @@ static void connected(capi_connection *cp, _cstruct NCPI)
|
|||
char *tty;
|
||||
|
||||
tty = capi20ext_get_tty_devname(p->appid, p->ncci, buf, sizeof(buf));
|
||||
info("capiplugin: connected(%s) %s", conninfo(cp), tty);
|
||||
info("capiplugin: connected(%s): %s", conninfo(cp), tty);
|
||||
strcpy(devnam, tty);
|
||||
if (opt_connectdelay)
|
||||
sleep(opt_connectdelay);
|
||||
isconnected = 1;
|
||||
}
|
||||
|
||||
|
@ -272,7 +912,7 @@ void put_message(unsigned appid, unsigned char *msg)
|
|||
unsigned err;
|
||||
err = capi20_put_message (appid, msg);
|
||||
if (err)
|
||||
fatal("capiplugin: putmessage(appid=%u) = 0x%x", appid, err);
|
||||
fatal("capiplugin: putmessage(appid=%d) = 0x%x", appid, err);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -282,7 +922,7 @@ capiconn_callbacks callbacks = {
|
|||
free: free,
|
||||
|
||||
disconnected: disconnected,
|
||||
incoming: 0,
|
||||
incoming: incoming,
|
||||
connected: connected,
|
||||
received: 0,
|
||||
datasent: 0,
|
||||
|
@ -299,7 +939,7 @@ void plugin_init(void)
|
|||
{
|
||||
int err;
|
||||
|
||||
info("plugin_init: capiconnect (%s)", revision);
|
||||
info("capiplugin: %s", revision);
|
||||
|
||||
add_options(my_options);
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
debug
|
||||
sync
|
||||
noauth
|
||||
defaultroute
|
||||
lcp-echo-interval 5
|
||||
lcp-echo-failure 3
|
||||
lcp-max-configure 50
|
||||
lcp-max-terminate 2
|
||||
noccp
|
||||
noipx
|
||||
persist
|
||||
plugin /etc/ppp/plugins/capiplugin.so
|
||||
channels 1
|
||||
protocol hdlc
|
||||
ipcp-accept-local
|
||||
ipcp-accept-remote
|
||||
:
|
Loading…
Reference in New Issue