599 lines
16 KiB
C
599 lines
16 KiB
C
/* $Id: assoc.c,v 1.2 1999/07/25 21:55:47 he Exp $ */
|
|
/*
|
|
Copyright 1997 by Henner Eisen
|
|
|
|
This code is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This code is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <tdu_user.h>
|
|
#include "tdu.h"
|
|
|
|
|
|
tdu_handler tdu_released = tdu_aborted;
|
|
|
|
/*
|
|
* Check if association is deactivated ( released or aborted )
|
|
*/
|
|
static int tdu_not_associated( struct tdu_fsm * fsm )
|
|
{
|
|
return ( * (fsm -> regime_handler) == fsm->idle.handler );
|
|
}
|
|
|
|
/*
|
|
* Check if in idle state of association regime as slave
|
|
*/
|
|
static int in_idle_assoc_regime_slave( struct tdu_fsm * fsm )
|
|
{
|
|
return (
|
|
( (fsm -> regime_handler) == &( fsm->assoc.handler ) )
|
|
&&
|
|
( fsm->assoc.handler == fsm->assoc.slave_handler )
|
|
);
|
|
}
|
|
|
|
/*
|
|
* Check if in idle state of association regime as master
|
|
*/
|
|
int in_idle_assoc_regime_master( struct tdu_fsm * fsm )
|
|
{
|
|
return (
|
|
( (fsm -> regime_handler) == &( fsm->assoc.handler ) )
|
|
&&
|
|
( fsm->assoc.handler == fsm->assoc.master_handler )
|
|
);
|
|
}
|
|
|
|
/*
|
|
* process events until the association regime ceases to be established
|
|
*/
|
|
int tdu_wait_for_release(struct tdu_fsm * fsm, struct timeval * timeout)
|
|
{
|
|
tdu_printf(TDU_LOG_TRC, "tdu_wait_for_release()\n");
|
|
return tdu_wait( fsm, timeout, tdu_not_associated );
|
|
}
|
|
|
|
/*
|
|
* Fill in parameters in a t_associate request packet
|
|
*/
|
|
int tdu_add_assoc_params( struct tdu_buf * tb, struct tdu_assoc_param * par)
|
|
{
|
|
int ret=0;
|
|
unsigned char byte;
|
|
|
|
if( par->udata && (par->udata_len >= 0) )
|
|
ret += tdu_add_string_par(tb, TDU_PI_USER_DATA, par->udata
|
|
, LIMIT(par->udata_len,TDU_PLEN_UDATA) );
|
|
if( par->req_ident >= 0){
|
|
ret += tdu_add_byte_par(tb,TDU_PI_REQUEST_IDENT,
|
|
par->req_ident? TDU_BIT_REQ_ID : 0);
|
|
}
|
|
|
|
if( par->ident && (par->ident_len >= 0) )
|
|
ret += tdu_add_string_par(tb, TDU_PI_IDENTIFICATION, par->ident
|
|
, LIMIT(par->ident_len,TDU_PLEN_IDENT) );
|
|
if( par->expl_conf >= 0 ){
|
|
ret += tdu_add_byte_par(tb,TDU_PI_EX_CONF_1ST_LAST_BLNO,
|
|
par->expl_conf? TDU_BIT_EXPL_CONF : 0);
|
|
}
|
|
|
|
byte = 0;
|
|
if( par->symm_service ) byte|= TDU_BIT_SYMM_SERVICE;
|
|
if( par->basic_kernel ) byte|= TDU_BIT_BASIC_KERNEL;
|
|
|
|
ret += tdu_add_byte_par(tb,TDU_PI_SERVICE_CLASS,
|
|
byte);
|
|
|
|
ret += tdu_add_byte_par(tb,TDU_PI_APPL_RESPONSE_TIMEOUT,
|
|
12);
|
|
|
|
if( par->appl_name && (par->appl_len >= 0) )
|
|
ret += tdu_add_string_par(tb, TDU_PI_APPLICATION_NAME,
|
|
par->appl_name
|
|
, LIMIT(par->appl_len,TDU_PLEN_APPLNAME) );
|
|
if( par->calling_addr && (par->calling_len >= 0) )
|
|
ret += tdu_add_string_par(tb, TDU_PI_CALLING_ADDRESS
|
|
, par->calling_addr
|
|
, LIMIT(par->calling_len,TDU_PLEN_ADDR) );
|
|
if( par->called_addr && (par->called_len >= 0) )
|
|
ret += tdu_add_string_par(tb, TDU_PI_CALLED_ADDRESS
|
|
, par->called_addr
|
|
, LIMIT(par->called_len,TDU_PLEN_ADDR) );
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Parse parameters of an association_request or positive response message.
|
|
* returns:
|
|
* 0 on success
|
|
* an integer reason code from the TDU_RE_* set when an error is detected.
|
|
*/
|
|
int tdu_parse_assoc( struct tdu_assoc_param *par, struct tdu_buf *tb)
|
|
{
|
|
int pi, pv;
|
|
|
|
tdu_printf(TDU_LOG_TRC, "tdu_parse_assoc()\n");
|
|
do {
|
|
tdu_printf(TDU_LOG_DBG, "parsing parameter %d=%s\n",*tb->data,
|
|
tdu_param_descr(*tb->data) );
|
|
pi = tdu_get_next_pi(tb);
|
|
if( pi < 0 ) return -pi;
|
|
switch( pi ){
|
|
case TDU_PI_RESULT_REASON:
|
|
tdu_printf(TDU_LOG_DBG, "result/reason\n");
|
|
if( *tb->ci == TDU_CI_T_RESPONSE_POSITIVE ){
|
|
if( (pv=tdu_parse_byte(tb)) < 0 )
|
|
return TDU_RE_SYNTAX_ERROR;
|
|
if( pv != TDU_CI_T_ASSOCIATE )
|
|
return TDU_RE_PROTOCOL_CONFLICT;
|
|
};
|
|
tb->data = tb->pn;
|
|
break;
|
|
case TDU_PI_CALLED_ADDRESS:
|
|
tdu_printf(TDU_LOG_DBG, "called addr\n");
|
|
par->called_len =
|
|
tdu_parse_string(tb, par->called_addr,
|
|
TDU_PLEN_ADDR);
|
|
break;
|
|
case TDU_PI_CALLING_ADDRESS:
|
|
tdu_printf(TDU_LOG_DBG, "calling addr\n");
|
|
par->calling_len =
|
|
tdu_parse_string(tb, par->calling_addr,
|
|
TDU_PLEN_ADDR);
|
|
break;
|
|
case TDU_PI_APPLICATION_NAME:
|
|
tdu_printf(TDU_LOG_DBG, "appl name\n");
|
|
par->appl_len =
|
|
tdu_parse_string(tb, par->appl_name,
|
|
TDU_PLEN_APPLNAME);
|
|
break;
|
|
case TDU_PI_APPL_RESPONSE_TIMEOUT:
|
|
tdu_printf(TDU_LOG_DBG, "resp timout\n");
|
|
par->resp_timeout = tdu_parse_li(tb);
|
|
break;
|
|
case TDU_PI_SERVICE_CLASS:
|
|
tdu_printf(TDU_LOG_DBG, "svc class\n");
|
|
if( (pv=tdu_parse_byte(tb)) < 0 )
|
|
return TDU_RE_SYNTAX_ERROR;
|
|
par->symm_service = pv & TDU_BIT_SYMM_SERVICE;
|
|
par->basic_kernel = pv & TDU_BIT_BASIC_KERNEL;
|
|
break;
|
|
case TDU_PI_EX_CONF_1ST_LAST_BLNO:
|
|
tdu_printf(TDU_LOG_DBG, "expl conf\n");
|
|
if( (pv=tdu_parse_byte(tb)) < 0 )
|
|
return TDU_RE_SYNTAX_ERROR;
|
|
par->expl_conf = pv & TDU_BIT_EXPL_CONF;
|
|
break;
|
|
case TDU_PI_IDENTIFICATION:
|
|
tdu_printf(TDU_LOG_DBG, "ident\n");
|
|
par->ident_len =
|
|
tdu_parse_string(tb, par->ident,
|
|
TDU_PLEN_IDENT);
|
|
break;
|
|
case TDU_PI_REQUEST_IDENT:
|
|
tdu_printf(TDU_LOG_DBG, "req ident\n");
|
|
if( (pv=tdu_parse_byte(tb)) < 0 )
|
|
return TDU_RE_SYNTAX_ERROR;
|
|
par->req_ident = pv & TDU_BIT_REQ_ID;
|
|
break;
|
|
case TDU_PI_USER_DATA:
|
|
tdu_printf(TDU_LOG_DBG, "user data\n");
|
|
par->udata_len =
|
|
tdu_parse_string(tb, par->udata,
|
|
TDU_PLEN_UDATA);
|
|
break;
|
|
default:
|
|
tdu_printf(TDU_LOG_LOG, "tdu_parse_assoc(): unexpected"
|
|
" parameter '%s' ignored\n",
|
|
tdu_param_descr(pi) );
|
|
tb->data = tb->pn;
|
|
};
|
|
} while( tb->pn < tb->tail );
|
|
return 0;
|
|
}
|
|
|
|
|
|
void tdu_assoc_set_master(struct tdu_fsm *);
|
|
void tdu_assoc_set_slave(struct tdu_fsm *);
|
|
|
|
/*
|
|
* Set application response timer to the value received from peer
|
|
* during association establishment.
|
|
*/
|
|
static void tdu_set_timeout( struct tdu_fsm * fsm)
|
|
{
|
|
fsm->assoc.resp_timeout = fsm->assoc.remote.resp_timeout;
|
|
if( fsm->assoc.resp_timeout <= 0 ) fsm->assoc.resp_timeout = 600;
|
|
if( fsm->assoc.resp_timeout > 254 ) fsm->assoc.resp_timeout = 254;
|
|
}
|
|
|
|
|
|
static int tdu_send_assoc( struct tdu_fsm * fsm, int resp )
|
|
{
|
|
struct tdu_buf tb[1];
|
|
|
|
tdu_init_tb(tb);
|
|
tdu_printf(TDU_LOG_TRC, "tdu_send_assoc()\n");
|
|
tdu_add_assoc_params( tb, & fsm->assoc.local );
|
|
if( resp ) {
|
|
tdu_add_reason(tb, TDU_CI_T_ASSOCIATE, 0, NULL);
|
|
tdu_add_ci_header( tb, TDU_CI_T_RESPONSE_POSITIVE );
|
|
} else {
|
|
tdu_add_ci_header( tb, TDU_CI_T_ASSOCIATE );
|
|
}
|
|
return tdu_send_packet( tb, fsm );
|
|
}
|
|
|
|
/*
|
|
* process an association establishment indication
|
|
*/
|
|
static int assoc_req_received(struct tdu_fsm *fsm, struct tdu_buf * tb)
|
|
{
|
|
int err;
|
|
struct tdu_param par;
|
|
|
|
tdu_printf(TDU_LOG_TRC, "assoc_req_received()\n");
|
|
par.reason = TDU_RE_ROLE_REFUSED_U;
|
|
par.other_reason[0] = 0;
|
|
|
|
if( ! fsm->assoc.slave_handler ) goto refuse;
|
|
if( ! fsm->user->t_associate) goto refuse;
|
|
|
|
tdu_set_default_assoc_param( &fsm->assoc.remote );
|
|
tdu_set_default_assoc_param( &fsm->assoc.local );
|
|
|
|
par.reason = tdu_parse_assoc(&fsm->assoc.remote,tb);
|
|
if ( par.reason ) goto refuse;
|
|
|
|
par.par.assoc = &fsm->assoc.remote;
|
|
par.res.assoc = &fsm->assoc.local;
|
|
err = fsm->user->t_associate(fsm->user,&par);
|
|
if( err>0 ) goto refuse;
|
|
|
|
/* remove parameters not allowed in response */
|
|
|
|
par.res.assoc->calling_len = -1;
|
|
par.res.assoc->appl_len = -1;
|
|
par.res.assoc->expl_conf = -1;
|
|
par.res.assoc->req_ident = -1;
|
|
|
|
|
|
if( tdu_send_assoc(fsm,1) > 0 ){
|
|
tdu_assoc_set_slave(fsm);
|
|
tdu_assoc_set_idle(fsm);
|
|
tdu_set_timeout(fsm);
|
|
return 0;
|
|
} else {
|
|
tdu_abort(fsm);
|
|
return -3;
|
|
}
|
|
|
|
refuse:
|
|
tdu_send_response_neg(fsm,TDU_CI_T_ASSOCIATE,
|
|
par.reason,par.other_reason);
|
|
return -3;
|
|
}
|
|
|
|
/*
|
|
* refuse accepting association request.
|
|
*/
|
|
int dont_accept(struct tdu_fsm * fsm, struct tdu_buf * dummy)
|
|
{
|
|
tdu_printf(TDU_LOG_TRC, "dont_acept()\n");
|
|
|
|
tdu_abort_req(fsm,TDU_RE_PROTOCOL_CONFLICT,NULL);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Set master mode of association regime
|
|
*/
|
|
void tdu_assoc_set_master(struct tdu_fsm * fsm)
|
|
{
|
|
fsm -> assoc.handler = fsm->assoc.master_handler;
|
|
fsm -> assoc.idle_assoc_req_processor = dont_accept;
|
|
}
|
|
|
|
/*
|
|
* Set slave mode of association regime
|
|
*/
|
|
void tdu_assoc_set_slave(struct tdu_fsm * fsm)
|
|
{
|
|
tdu_printf(TDU_LOG_TRC, "tdu_assoc_set_slave()\n");
|
|
|
|
fsm -> assoc.handler = fsm->assoc.slave_handler;
|
|
fsm -> assoc.idle_assoc_req_processor = dont_accept;
|
|
}
|
|
|
|
/*
|
|
* Pepare fsm for usage as listener (server) before any regime is
|
|
* established
|
|
*/
|
|
void tdu_assoc_allow_listen(struct tdu_fsm * fsm)
|
|
{
|
|
fsm -> assoc.idle_assoc_req_processor = assoc_req_received;
|
|
}
|
|
|
|
/*
|
|
* Set idle state of association regime
|
|
*/
|
|
void tdu_assoc_set_idle(struct tdu_fsm * fsm)
|
|
{
|
|
tdu_printf(TDU_LOG_TRC, "tdu_assoc_set_idle()\n");
|
|
|
|
fsm -> regime_handler = & fsm->assoc.handler;
|
|
tdu_del_timer(fsm);
|
|
fsm->wait=0;
|
|
}
|
|
|
|
|
|
static void tdu_release_received(struct tdu_fsm * fsm)
|
|
{
|
|
tdu_printf(TDU_LOG_TRC, "tdu_release_received()\n");
|
|
#if 0
|
|
tdu_printf(TDU_LOG_AP3, "tdu_release_received()\n");
|
|
#endif
|
|
if( fsm->regime_handler == & fsm->assoc.handler ){
|
|
tdu_send_response_pos(fsm, TDU_CI_T_RELEASE);
|
|
fsm->idle.handler = tdu_released;
|
|
fsm->regime_handler = & fsm->idle.handler;
|
|
tdu_del_timer(fsm);
|
|
} else {
|
|
tdu_abort_req(fsm,TDU_RE_PROTOCOL_CONFLICT,NULL);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* association regime handler for master
|
|
*/
|
|
int tdu_assoc_master ( struct tdu_fsm *fsm, int event, struct tdu_buf *tb)
|
|
{
|
|
tdu_printf(TDU_LOG_TRC, "tdu_assoc_master(), event = %s\n",
|
|
tdu_cmd_descr(event) );
|
|
switch (event) {
|
|
case TDU_CI_T_RELEASE:
|
|
tdu_release_received(fsm);
|
|
break;
|
|
case TDU_CI_T_ABORT:
|
|
/* fall through */
|
|
case TDU_CI_SOCK_READ_ERROR:
|
|
case TDU_CI_TC_DISCONNECT:
|
|
tdu_abort(fsm);
|
|
break;
|
|
default:
|
|
tdu_abort_req(fsm,TDU_RE_PROTOCOL_CONFLICT,NULL);
|
|
};
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Association regime handler for slave.
|
|
* If "basic kernel" service class gets
|
|
* supported once, this needs to be changed.
|
|
*/
|
|
int tdu_assoc_slave ( struct tdu_fsm *fsm, int event, struct tdu_buf *tb)
|
|
{
|
|
tdu_printf(TDU_LOG_TRC, "tdu_assoc_slave(), event = %s\n",
|
|
tdu_cmd_descr(event) );
|
|
switch (event) {
|
|
case TDU_CI_T_ACCESS:
|
|
tdu_access_received(fsm,tb);
|
|
break;
|
|
case TDU_CI_T_RELEASE:
|
|
tdu_release_received(fsm);
|
|
break;
|
|
case TDU_CI_T_ABORT:
|
|
/* fall through */
|
|
case TDU_CI_SOCK_READ_ERROR:
|
|
case TDU_CI_TC_DISCONNECT:
|
|
tdu_abort(fsm);
|
|
break;
|
|
default:
|
|
tdu_abort_req(fsm,TDU_RE_PROTOCOL_CONFLICT,NULL);
|
|
};
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* association regime handler, waiting for confirmation of t_release
|
|
*/
|
|
int tdu_await_release( struct tdu_fsm *fsm, int event, struct tdu_buf *tb)
|
|
{
|
|
int err, pi;
|
|
|
|
tdu_printf(TDU_LOG_TRC, "tdu_await_release(), event = %s\n",
|
|
tdu_cmd_descr(event) );
|
|
switch (event) {
|
|
case TDU_CI_T_RESPONSE_POSITIVE:
|
|
pi = tdu_get_next_pi(tb);
|
|
err = tdu_check_response(tb,pi,fsm->wait);
|
|
if( err ) goto error;
|
|
/* fall through */
|
|
case TDU_CI_T_ABORT:
|
|
/* fall through */
|
|
case TDU_CI_SOCK_READ_ERROR:
|
|
case TDU_CI_TC_DISCONNECT:
|
|
tdu_abort(fsm);
|
|
break;
|
|
case TDU_CI_RESPONSE_TIMEOUT:
|
|
default:
|
|
error:
|
|
tdu_printf(TDU_LOG_ERR, "unexpected event %s while waiting for t_release"
|
|
" confirmation\n", tdu_cmd_descr(event) );
|
|
tdu_abort_req(fsm,TDU_RE_PROTOCOL_CONFLICT,NULL);
|
|
};
|
|
fsm->wait = 0;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Request termination of association regime.
|
|
* Specifying user data not yet supported.
|
|
*
|
|
* FIXME: this is ugly and return logic not consistent with tdu_end_access_req
|
|
*/
|
|
int tdu_release_req(struct tdu_fsm * fsm)
|
|
{
|
|
int ret;
|
|
struct tdu_buf tb[1];
|
|
|
|
tdu_printf(TDU_LOG_TRC, "tdu_release_req()\n");
|
|
|
|
ret = in_idle_assoc_regime_master( fsm );
|
|
if( ret <= 0 ) {
|
|
tdu_printf( TDU_LOG_ERR, "tdu_release_req: not in idle master"
|
|
" state of association regime\n");
|
|
return ret;
|
|
}
|
|
|
|
tdu_init_tb(tb);
|
|
tdu_add_ci_header(tb,TDU_CI_T_RELEASE);
|
|
ret = tdu_send_packet(tb,fsm);
|
|
|
|
if ( ret < 0 ) {
|
|
perror("tdu_release_req:send_packet");
|
|
tdu_abort(fsm);
|
|
return ret;
|
|
}
|
|
fsm -> assoc.handler = tdu_await_release;
|
|
fsm->wait = TDU_CI_T_RELEASE;
|
|
tdu_start_timer(fsm);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* idle regime handler, waiting for t_associate confirmation
|
|
*/
|
|
int tdu_await_assoc( struct tdu_fsm *fsm, int event, struct tdu_buf *tb)
|
|
{
|
|
int err;
|
|
|
|
tdu_printf(TDU_LOG_TRC, "tdu_await_assoc(), event = %s\n",
|
|
tdu_cmd_descr(event) );
|
|
switch (event) {
|
|
case TDU_CI_T_RESPONSE_POSITIVE:
|
|
tdu_del_timer(fsm);
|
|
tdu_set_default_assoc_param( &fsm->assoc.remote );
|
|
err = tdu_parse_assoc( & fsm->assoc.remote, tb );
|
|
if( err ) {
|
|
tdu_abort_req( fsm, err, NULL );
|
|
} else {
|
|
/* initial role is master */
|
|
tdu_assoc_set_master(fsm);
|
|
tdu_assoc_set_idle(fsm);
|
|
tdu_set_timeout(fsm);
|
|
tdu_printf(TDU_LOG_DBG,"Timeout set to %d\n",fsm->assoc.resp_timeout);
|
|
}
|
|
break;
|
|
case TDU_CI_T_ASSOCIATE:
|
|
/* association establish request conflict. The initator
|
|
of the physical connection wins */
|
|
tdu_printf(TDU_LOG_LOG,"resolving association req conflict\n");
|
|
if( fsm->idle.initiator ) {
|
|
/* ignore, continue waiting for t_response */
|
|
} else {
|
|
fsm->assoc.idle_assoc_req_processor(fsm,tb);
|
|
}
|
|
break;
|
|
case TDU_CI_T_RESPONSE_NEGATIVE:
|
|
tdu_printf(TDU_LOG_ERR,"association req rejected by peer\n");
|
|
tdu_del_timer(fsm);
|
|
fsm->idle.handler = tdu_aborted;
|
|
break;
|
|
case TDU_CI_T_ABORT:
|
|
/* fall through */
|
|
case TDU_CI_SOCK_READ_ERROR:
|
|
case TDU_CI_TC_DISCONNECT:
|
|
tdu_abort(fsm);
|
|
break;
|
|
default:
|
|
tdu_printf(TDU_LOG_ERR,"unexpected event %s while waiting for t_associate"
|
|
" confirmation\n", tdu_cmd_descr(event) );
|
|
tdu_abort_req(fsm,TDU_RE_PROTOCOL_CONFLICT,NULL);
|
|
};
|
|
fsm->wait = 0;
|
|
return 0;
|
|
}
|
|
/*
|
|
* Check if not awaiting association establishment
|
|
*/
|
|
static int not_associating( struct tdu_fsm * fsm )
|
|
{
|
|
return ! ( ( fsm->regime_handler == &fsm->idle.handler )
|
|
&&(fsm->idle.handler == tdu_await_assoc ) );
|
|
}
|
|
|
|
/*
|
|
process events until no longer awaiting association regime establishment
|
|
returns: >0 if idle state of association regime master is reached
|
|
<0 if other state != awaiting association is reached
|
|
*/
|
|
int tdu_wait_for_not_associating(struct tdu_fsm * fsm, struct timeval * timeout)
|
|
{
|
|
int ret;
|
|
tdu_printf(TDU_LOG_TRC, "wait_for_not_associating()\n");
|
|
ret = tdu_wait( fsm, timeout, not_associating );
|
|
|
|
if ( in_idle_assoc_regime_master(fsm) ) return 1;
|
|
if ( in_idle_assoc_regime_slave(fsm) ) return 1;
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* establish association regime
|
|
*/
|
|
int tdu_assoc_req( struct tdu_fsm * fsm, struct tdu_assoc_param * par )
|
|
{
|
|
/* when the association regime is established, we need to become
|
|
master. Reject, if this is not possible*/
|
|
tdu_printf(TDU_LOG_TRC, "tdu_assoc_req()\n");
|
|
if ( (! tdu_before_regime(fsm) ) ||
|
|
(! fsm->assoc.master_handler) ){
|
|
tdu_printf(TDU_LOG_ERR,"tdu_assoc_req(): no association request possible\n");
|
|
return -1;
|
|
}
|
|
fsm->assoc.local = *par;
|
|
/* FIXME: contents of *par needs checking */
|
|
|
|
if( tdu_send_assoc( fsm, 0 ) > 0 ){
|
|
fsm->idle.handler = tdu_await_assoc;
|
|
fsm->wait = TDU_CI_T_ASSOCIATE;
|
|
tdu_start_timer( fsm );
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
void tdu_set_default_assoc_param( struct tdu_assoc_param * par )
|
|
{
|
|
tdu_printf(TDU_LOG_TRC, "tdu_set_default_assoc_param()\n");
|
|
|
|
par->called_len = -1;
|
|
par->calling_len = -1;
|
|
par->appl_len = -1;
|
|
par->resp_timeout = 0;
|
|
par->symm_service=1;
|
|
par->basic_kernel=0;
|
|
par->expl_conf= TDU_BIT_EXPL_CONF;
|
|
par->ident_len = -1;
|
|
par->req_ident = 0;
|
|
par->udata_len = -1;
|
|
}
|
|
|