Net2/usr/src/contrib/isode/quipu/conn_init.c

/* conn_init.c - deal with incoming association requests */

#ifndef lint
static char *rcsid = "$Header: /f/osi/quipu/RCS/conn_init.c,v 7.6 91/02/22 09:38:30 mrose Interim $";
#endif

/*
 * $Header: /f/osi/quipu/RCS/conn_init.c,v 7.6 91/02/22 09:38:30 mrose Interim $
 *
 *
 * $Log:	conn_init.c,v $
 * Revision 7.6  91/02/22  09:38:30  mrose
 * Interim 6.8
 * 
 * Revision 7.5  90/10/17  11:53:23  mrose
 * sync
 * 
 * Revision 7.4  90/07/09  14:45:24  mrose
 * sync
 * 
 * Revision 7.3  90/03/15  11:18:42  mrose
 * quipu-sync
 * 
 * Revision 7.2  89/12/19  16:20:03  mrose
 * sync
 * 
 * Revision 7.1  89/11/24  16:21:53  mrose
 * sync
 * 
 * Revision 7.0  89/11/23  22:16:46  mrose
 * Release 6.0
 * 
 */

/*
 *                                NOTICE
 *
 *    Acquisition, use, and distribution of this module and related
 *    materials are subject to the restrictions of a license agreement.
 *    Consult the Preface in the User's Manual for the full terms of
 *    this agreement.
 *
 */


#include "quipu/dsap.h"
#include "tsap.h"
#include "quipu/util.h"
#include "quipu/connection.h"

extern LLog * log_dsap;
#ifndef NO_STATS
extern LLog * log_stat;
#endif
 extern  struct PSAPaddr		* dsaladdr;

 void	  ds_log();

 struct connection	* conn_alloc();
 void    acs_log();

 extern  time_t timenow;

 conn_init(cn)
 struct connection	* cn;
 {
     int				  result;
     char			**vec;
     struct DSAPstart		* ds;
     struct DSAPindication	  di_s;
     struct DSAPindication	* di = &di_s;
     struct DSAPabort		* da = &(di->di_abort);
     struct TSAPdisconnect	  td_s;
     struct TSAPdisconnect	* td = &td_s;

     DLOG (log_dsap,LLOG_TRACE,( "conn_init()"));

     vec = cn->cn_start.cs_vec;
     ds = &(cn->cn_start.cs_ds);

     result = DBindInit (cn->cn_start.cs_vecp, vec, ds, di);

     if (result != OK)
     {
	 LLOG (log_dsap,LLOG_EXCEPTIONS,( "conn_init(): DBindInit() != OK"));
	 ds_log(da, "initialization fails");
	 conn_extract (cn);
	 return;
     }

     if (conns_used >= MAX_CONNS) {
	 LLOG (log_dsap,LLOG_EXCEPTIONS,( "Too many connections"));
         (void) DBindReject (ds, ACS_PERMANENT, ACS_USER_NOREASON, di);
	 conn_extract (cn);
	 return;
     }

     if ( (ds->ds_start.acs_start.ps_called.pa_selectlen != 
	                   dsaladdr->pa_selectlen) ||
	  (dsaladdr->pa_selectlen && bcmp (
	   ds->ds_start.acs_start.ps_called.pa_selector,
           dsaladdr->pa_selector,
	   dsaladdr->pa_selectlen) == 0)) {
	
out:;	  
        LLOG (log_dsap,LLOG_EXCEPTIONS, ("Bad Selector (%d): %s",
	   ds->ds_sd, paddr2str(&(ds->ds_start.acs_start.ps_calling),NULLNA)));

        (void) DBindReject (ds, ACS_PERMANENT, ACS_USER_NOREASON, di);
	conn_extract (cn);
	return;
	  }
     if ( (ds->ds_start.acs_start.ps_called.pa_addr.sa_selectlen != 
	                   dsaladdr->pa_addr.sa_selectlen) ||
	  (dsaladdr->pa_addr.sa_selectlen && bcmp (
	   ds->ds_start.acs_start.ps_called.pa_addr.sa_selector,
           dsaladdr->pa_addr.sa_selector,
	   dsaladdr->pa_addr.sa_selectlen) == 0)) 
	goto out;

     /* tsels are checked in the lower layers - just check the NULL ones */
     if ( (dsaladdr->pa_addr.sa_addr.ta_selectlen == 0) && 
	 ( ds->ds_start.acs_start.ps_called.pa_addr.sa_addr.ta_selectlen != 0))
	goto out;

    DLOG (log_dsap,LLOG_TRACE,( "conn_init(): DBindInit() OK"));

    /*
    * Log the arrival of a connection request.
    */
    LLOG (log_dsap,LLOG_NOTICE, ("Association (%d) from %s",
	   ds->ds_sd, paddr2str(&(ds->ds_start.acs_start.ps_calling),NULLNA)));

    DLOG (log_dsap,LLOG_NOTICE, ("Context: %s; Caller: %s; Callee: %s.",
		oid2ode(ds->ds_start.acs_context),
		sprintaei (&ds->ds_start.acs_callingtitle),
		sprintaei (&ds->ds_start.acs_calledtitle)));

    cn->cn_ad = ds->ds_sd;
    cn->cn_initiator = FALSE;
    cn->cn_ctx = ds->ds_ctx;

#ifndef NO_STATS
    switch (cn->cn_ctx)
    {
	case DS_CTX_X500_DAP:
	    LLOG (log_stat, LLOG_NOTICE, ("X500 DAP context association (%d): %s", cn->cn_ad, paddr2str (&(ds->ds_start.acs_start.ps_calling), NULLNA)));
	    break;
	case DS_CTX_X500_DSP:
	    LLOG (log_stat, LLOG_NOTICE, ("X500 DSP context association (%d): %s", cn->cn_ad, paddr2str (&(ds->ds_start.acs_start.ps_calling), NULLNA)));
	    break;
	case DS_CTX_QUIPU_DSP:
	    LLOG (log_stat, LLOG_NOTICE, ("QUIPU DSP context association (%d): %s", cn->cn_ad, paddr2str (&(ds->ds_start.acs_start.ps_calling), NULLNA)));
	    break;
	default :
	    LLOG (log_stat, LLOG_EXCEPTIONS, ("UNKNOWN context association (%d): %s", cn->cn_ad, paddr2str (&(ds->ds_start.acs_start.ps_calling), NULLNA)));
	    break;
    }
#endif

    cn->cn_dn = dn_cpy(ds->ds_bind_arg.dba_dn);

    /*
    *  If we haven't returned yet then the protocol for binding has been
    *  satisfactorily completed.
    *  Now attempt to perform the ds_bind for the argument decoded, which
    *  can either succeed, fail or suspend waiting for a remote compare.
    *  If a remote compare has been scheduled then return, otherwise
    *  complete the connection initialisation by sending a bind result.
    */

    if (TSetQueuesOK (cn->cn_ad, 1, td) == NOTOK) 
	td_log (td, "TSetQueuesOK (incoming)");

    switch(ds_bind_init(cn))
    {
    case DS_OK:
	conn_init_res(cn);
	break;
    case DS_ERROR_CONNECT:
	conn_init_err(cn);
	break;
    case DS_CONTINUE:
	cn->cn_state = CN_INDICATED;
	break;
    default:
	LLOG(log_dsap, LLOG_EXCEPTIONS, ("Unexpected return by ds_bind_init"));
        (void) DBindReject (ds, ACS_TRANSIENT, ACS_USER_NOREASON, di);
	break;
    }
}

conn_init_res(cn)
struct connection       * cn;
{
    int				  result;
    struct DSAPindication      di_s;
    struct DSAPindication      *di = &(di_s);
    struct DSAPabort           *da = &(di->di_abort);
    struct DSAPstart           * ds = &(cn->cn_start.cs_ds);
    struct AcSAPstart           * acs = &(ds->ds_start);
    struct PSAPstart            * ps = &(acs->acs_start);

    DLOG(log_dsap,LLOG_TRACE, ("conn_init_res()"));

    DLOG(log_dsap,LLOG_NOTICE, ("D-BIND.RESULT"));

#ifdef DEBUG
    {
	int	  i;

	for(i=0; i<ps->ps_ctxlist.pc_nctx; i++)
	{
	    DLOG(log_dsap, LLOG_DEBUG, ("ctx[%d] id = %d, res = %d.", i,
		ps->ps_ctxlist.pc_ctx[i].pc_id,
		ps->ps_ctxlist.pc_ctx[i].pc_result));
	}
    }
#endif

    result = DBindResult (cn->cn_ad, acs->acs_context, NULLAEI, NULLPA,
	&(ps->ps_ctxlist), ps->ps_defctxresult, PR_MYREQUIRE,
	ps->ps_srequirements & (ROS_MYREQUIRE | SR_NEGOTIATED),
	SERIAL_NONE, ps->ps_settings, &(ps->ps_connect),
	&(cn->cn_start.cs_res), ds->ds_pctx_id, di);

    if (result == OK)
    {
	cn->cn_state = CN_OPEN;
    }
    else
    {
	ds_log(da, "D-BIND.RESULT");
	DLOG(log_dsap, LLOG_DEBUG, ("conn_init_res(): DBindResult failed, extracting conn"));
	conn_extract(cn);
    }

    ACSFREE (acs);
}

conn_init_err(cn)
struct connection       * cn;
{
    int				  result;
    struct DSAPindication      di_s;
    struct DSAPindication      *di = &di_s;
    struct DSAPabort           *da = &di->di_abort;
    struct DSAPstart           * ds = &(cn->cn_start.cs_ds);
    struct AcSAPstart           * acs = &(ds->ds_start);
    struct PSAPstart            * ps = &(acs->acs_start);

    DLOG(log_dsap,LLOG_TRACE, ("conn_init_err()"));

    DLOG(log_dsap,LLOG_NOTICE, ("D-BIND.ERROR"));

#ifdef DEBUG
    {
	int	  i;

	for(i=0; i<ps->ps_ctxlist.pc_nctx; i++)
	{
	    DLOG(log_dsap, LLOG_DEBUG, ("ctx[%d] id = %d, res = %d.", i,
		ps->ps_ctxlist.pc_ctx[i].pc_id,
		ps->ps_ctxlist.pc_ctx[i].pc_result));
	}
    }
#endif

    result = DBindError (cn->cn_ad, acs->acs_context, NULLAEI, NULLPA,
	&(ps->ps_ctxlist), ps->ps_defctxresult, PR_MYREQUIRE,
	ps->ps_srequirements & (ROS_MYREQUIRE | SR_NEGOTIATED),
	SERIAL_NONE, ps->ps_settings, &(ps->ps_connect),
	&(cn->cn_start.cs_err), ds->ds_pctx_id, di);

    if (result == OK)
    {
	    DLOG(log_dsap,LLOG_TRACE, ("status != ACS_ACCEPT"));
	    DLOG(log_dsap, LLOG_DEBUG, ("conn_init_err(): DBindError succeeded, extracting conn"));
	    conn_extract(cn);
    }
    else
    {
	ds_log(da, "D-BIND.ERROR");
	DLOG(log_dsap, LLOG_DEBUG, ("conn_init_err(): DBindError failed, extracting conn"));
	conn_extract(cn);
    }

}

conn_pre_init(newfd, vecp, vec)
int newfd;
int	  vecp;
char	**vec;
{
    struct connection	* cn;

    cn = conn_alloc();

    cn->cn_next = connlist;
    connlist = cn;
    conns_used++;

    cn->cn_ad = newfd;
    cn->cn_initiator = FALSE;

    cn->cn_start.cs_vecp = vecp;
    if (vec[0])
	cn->cn_start.cs_svec[0] = cn->cn_start.cs_vec[0] = strdup (vec[0]);
    if (vec[1])
	cn->cn_start.cs_svec[1] = cn->cn_start.cs_vec[1] = strdup (vec[1]);
    if (vec[2])
	cn->cn_start.cs_svec[2] = cn->cn_start.cs_vec[2] = strdup (vec[2]);
    if (vec[3])
	cn->cn_start.cs_svec[3] = cn->cn_start.cs_vec[3] = strdup (vec[3]);

    cn->cn_state = CN_OPENING;

    cn->cn_last_used = timenow;

    if (newfd == NOTOK)
	conn_init (cn);
    else 
	DLOG (log_dsap,LLOG_NOTICE, ("opening association on %d",newfd ));
}