/* ** sxf_clr_activity - Clear the server activity. ** ** History: ** 11-dec-92 (robf) ** Created ** Inputs: ** None ** ** Outputs: ** None ** */ VOID sxf_clr_activity(void) { SCF_CB scb; DB_STATUS status; i4 error; scb.scf_len_union.scf_blength=0; scb.scf_nbr_union.scf_atype = SCS_A_MAJOR; scb.scf_type=SCF_CB_TYPE; scb.scf_length=SCF_CB_SIZE; scb.scf_session=DB_NOSESSION; scb.scf_facility=DB_SXF_ID; status=scf_call(SCS_CLR_ACTIVITY, &scb); if (status!=E_DB_OK) { /* ** Log something went wrong and continue. */ _VOID_ ule_format(scb.scf_error.err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &error, 0); _VOID_ ule_format(E_SX1063_SCF_CLR_ACTIVITY, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &error, 0); } }
/* ** Name: sxapo_close - close an audit trail ** ** Description: ** This routine closes an audit trail that has previously been opened ** by a call to sxap_open. ** ** Overview of algorithm:- ** ** Call SAclose. ** close the memory stream ascociated with this audit trail. ** ** Inputs: ** sxf_rscb The SXF_RSCB structure associated with this ** audit trail ** ** Outputs: ** err_code Error code returned to the caller. ** ** Returns: ** DB_STATUS ** ** History: ** 6-jan-94 (stephenb) ** Initial creation. ** 11-feb-94 (stephenb) ** Update SA call to current spec. */ sxapo_close( SXF_RSCB *rscb, i4 *err_code) { SXAPO_RSCB *sxapo_rscb = (SXAPO_RSCB *)rscb->sxf_sxap; STATUS cl_stat; CL_ERR_DESC cl_err; DB_STATUS status; ULM_RCB ulm_rcb; i4 local_err; *err_code = E_SX0000_OK; for(;;) { if (!sxapo_rscb) { *err_code = E_SX0004_BAD_PARAMETER; _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); break; } /* ** incriment stats counter */ Sxf_svcb->sxf_stats->close_count++; cl_stat = SAclose(&sxapo_rscb->sxapo_desc, &cl_err); if (cl_stat != OK) { *err_code = E_SX1018_FILE_ACCESS_ERROR; _VOID_ ule_format(*err_code, &cl_err, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); } /* ** Close memory stream */ ulm_rcb.ulm_facility = DB_SXF_ID; ulm_rcb.ulm_streamid_p = &sxapo_rscb->rs_memory; ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz; status = ulm_closestream(&ulm_rcb); if (status != E_DB_OK) { *err_code = E_SX106B_MEMORY_ERROR; _VOID_ ule_format(ulm_rcb.ulm_error.err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); } /* ULM has nullified rs_memory */ rscb->sxf_sxap = NULL; break; } if (*err_code != E_SX0000_OK) { *err_code = E_SX1026_SXAP_CLOSE; status = E_DB_ERROR; } return (status); }
/* ** Name: SXC_DESTROY_SCB - destroy a SXF session control block ** ** Description: ** This routine frees all the resourses associated with a session control ** block (SXF_SCB). ** ** Overview of algorithm:- ** ** Release the SCB's lock list. ** Close the SCB's memory stream. ** ** Inputs: ** scb pointer to session control block to be destroyed ** ** Outputs: ** err_code ** ** Returns: ** DB_STATUS ** History: ** 25-sept-92 (markg) ** Initial creation. ** 26-oct-1992 (markg) ** Updated error handling. ** 10-mar-1993 (markg) ** Fixed problem where errors returned from ulm were not getting ** handled correctly. ** 10-may-1993 (robf) ** Added handling for database cb in session. */ DB_STATUS sxc_destroy_scb( SXF_SCB *scb, i4 *err_code) { DB_STATUS status = E_DB_OK; i4 local_err; CL_ERR_DESC cl_err; ULM_RCB ulm_rcb; *err_code = E_SX0000_OK; for (;;) { if (LKrelease(LK_ALL, scb->sxf_lock_list, NULL, NULL, NULL, &cl_err) != OK) { *err_code = E_SX1008_BAD_LOCK_RELEASE; _VOID_ ule_format(*err_code, &cl_err, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); } /* ** Release database cb */ sxc_freedbcb(scb, scb->sxf_db_info); ulm_rcb.ulm_facility = DB_SXF_ID; ulm_rcb.ulm_streamid_p = &scb->sxf_scb_mem; ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz; status = ulm_closestream(&ulm_rcb); if (status != E_DB_OK) { *err_code = E_SX106B_MEMORY_ERROR; _VOID_ ule_format(ulm_rcb.ulm_error.err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); } /* ULM has nullified sxf_scb_mem */ break; } /* Handle any errors */ if (*err_code != E_SX0000_OK) { if (*err_code > E_SXF_INTERNAL) *err_code = E_SX1007_BAD_SCB_DESTROY; if (status == E_DB_OK) status = E_DB_ERROR; } return (status); }
/*{ ** Name: opx_lerror - an error handling routine, which accepts ** variable arguments ** ** Description: ** This routine logs information in the dbms.log. It accepts up ** to 4 variable arguments. ** ** Inputs: ** error optimizer error code to report ** p1 .. p4 pointers to variable arguments ** ** Outputs: ** Returns: ** VOID ** Exceptions: ** none ** ** Side Effects: ** the exception handling routines are responsible for ** deallocating OPF resources bound to this session. ** ** History: ** 07-nov-90 (stec) ** initial creation ** 24-oct-92 (andre) ** interface of ule_format() has changed to accept (DB_SQLSTATE *). ** Since we are not using the sqlstate value here, simply pass NULL to ** ule_format() */ VOID opx_lerror( OPX_ERROR error, i4 num_parms, PTR p1, PTR p2, PTR p3, PTR p4) { i4 uletype; i4 ulecode; i4 msglen; char errbuf[DB_ERR_SIZE]; if (num_parms > 4) return; uletype = ULE_LOG; (VOID) ule_format(error, 0L, uletype, (DB_SQLSTATE *) NULL, errbuf, (i4) sizeof(errbuf), &msglen, &ulecode, num_parms, (i4)0, p1, (i4)0, p2, (i4)0, p3, (i4)0, p4); return; }
/* ** Name: ascs_avformat - Show info on the current thread during an AV ** ** Description: ** This routine calls scs_iformat to show what thread was running ** when the server got an AV. ** ** Inputs: ** None. ** ** Outputs: ** Returns: ** STATUS ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 27-feb-1992 (rog) ** Created. ** 29-Jun-1993 (daveb) ** correctly cast arg to CSget_scb(). ** 02-Jul-1993 (daveb) ** prototyped. ** 07-jul-1993 (rog) ** Changed the message from saying a fatal error occurred to just ** saying that an error occurred. [@history_template@]... */ STATUS ascs_avformat(void) { STATUS ret_val; EX_CONTEXT ex; if (EXdeclare(ascs_fhandler, &ex) != OK) { ret_val = FAIL; } else { SCD_SCB *scb; i4 err_code; char *msg_buffer; i4 msg_length; msg_buffer = "An error occurred in the following session:"; msg_length = STlength(msg_buffer); CSget_scb((CS_SCB **)&scb); ule_format(0, 0, ULE_MESSAGE, 0, msg_buffer, msg_length,0,&err_code,0); ret_val = ascs_iformat(scb, 1, 0, 1); } EXdelete(); return(ret_val); }
/*{ ** Name: opx_rerror - this routine will report an optimizer error ** ** Description: ** This routine will log an optimizer error. ** ** Inputs: ** opfcb ptr to caller's control block ** error optimizer error code to log ** ** Outputs: ** Returns: ** VOID ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 3-jul-86 (seputis) ** initial creation ** 21-may-89 (jrb) ** now passes generic error to opx_sccerror ** 24-oct-92 (andre) ** interfaces of ule_format() and opx_sccerror() have been changed to ** receive (DB_SQLSTATE *) ** 24-june-03 (inkdo01) ** Add OP04C0 to list for which error is NOT returned to user. ** 22-june-06 (dougi) ** Make E_OP0018 (timeoutabort) go to log where the query text also ** gets dumped. ** 24-jun-08 (hayke02) ** Treat E_OP04C1 like E_OP04C0: soft failure, error reported to ** errlog.log and retry using non-greedy enumeration, unless op247 is ** set. [@history_line@]... */ VOID opx_rerror( OPF_CB *opfcb, OPX_ERROR error) { DB_STATUS ule_status; /* return status from ule_format */ i4 ule_error; /* ule cannot format message */ char msg_buffer[DB_ERR_SIZE]; /* error message buffer */ i4 msg_buf_length; /* length of message returned */ i4 log; /* should this error be logged */ DB_SQLSTATE sqlstate; bool enumnomsg = FALSE; opfcb->opf_errorblock.err_code = error; /* save error code */ if ((error % 256) < 128 && error != E_OP0018_TIMEOUTABORT) log = ULE_LOOKUP; else log = ULE_LOG; ule_status = ule_format( error, (CL_SYS_ERR *)NULL, log, &sqlstate, msg_buffer, (i4) (sizeof(msg_buffer)-1), &msg_buf_length, &ule_error, 0); if (ule_status != E_DB_OK) { (VOID)STprintf(msg_buffer, "ULE error = %x, Optimizer message cannot be found - error no. = %x\n", ule_error, error ); } else msg_buffer[msg_buf_length] = 0; /* null terminate */ if ((error == E_OP04C0_NEWENUMFAILURE) || (error == E_OP04C1_GREEDYCONSISTENCY)) { OPS_CB *opscb; OPS_STATE *global; i4 temp; /* Check if new enumeration is result of tp op247 - if not, ** message isn't displayed. */ opscb = ops_getcb(); global = opscb->ops_state; if (!global->ops_cb->ops_check || !opt_svtrace( global->ops_cb, OPT_F119_NEWENUM, &temp, &temp)) enumnomsg = TRUE; } if (error != E_OP0003_ASYNCABORT && !enumnomsg) /* do not report control C errors ** or "new enumeration" errors ** to the user */ { (VOID) opx_sccerror(E_DB_ERROR, &sqlstate, error, msg_buffer, (i4)msg_buf_length); } }
/* ** Name: sxapo_bgn_ses - register a session with the auditing system ** ** Description: ** This routine is called at session startup time to initialize the ** audit specific data structures associated with a session. It should ** be called only once for each session. ** ** The only session specific data structure need for the operating system ** audit log version of auditing is the record identifier that keeps ** count of the number of records written since the last flush for this ** session. ** ** Inputs: ** scb SXF session control block ** ** Outputs: ** err_code Error code returned to the caller ** ** Returns: ** DB_STATUS ** ** History: ** 1-dec-93 (stephenb) ** Initial creation. ** */ DB_STATUS sxapo_bgn_ses ( SXF_SCB *scb, i4 *err_code) { ULM_RCB ulm_rcb; DB_STATUS status; i4 local_err; *err_code = E_SX0000_OK; ulm_rcb.ulm_facility = DB_SXF_ID; ulm_rcb.ulm_streamid_p = &scb->sxf_scb_mem; ulm_rcb.ulm_psize = sizeof (SXAPO_RECID); ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz; status = ulm_palloc(&ulm_rcb); if (status != E_DB_OK) { if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM) *err_code = E_SX106B_MEMORY_ERROR; else *err_code = E_SX106B_MEMORY_ERROR; _VOID_ ule_format(ulm_rcb.ulm_error.err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); } else scb->sxf_sxap_scb = ulm_rcb.ulm_pptr; /* handle errors */ if (*err_code != E_SX0000_OK) { _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); *err_code = E_SX101D_SXAP_BGN_SESSION; status = E_DB_ERROR; } return(status); }
/*{ ** Name: opx_2perror - print error with 2 parameters ** ** Description: ** Print error with exactly 2 parameters, do not use variable parameters to ** avoid lint errors ** ** Inputs: ** error error message number ** p1 parameter 1 ** p2 parameter 2 ** ** Outputs: ** ** Returns: ** VOID ** Exceptions: ** exits via exception handler ** ** Side Effects: ** does not return ** ** History: ** 18-may-92 (seputis) ** initial creation for tech support ** 24-oct-92 (andre) ** interfaces of ule_format() and opx_sccerror() have been changed to ** receive (DB_SQLSTATE *) [@history_template@]... */ VOID opx_2perror( OPX_ERROR error, PTR p1, PTR p2) { DB_STATUS ule_status; /* return status from ule_format */ i4 ule_error; /* ule cannot format message */ char msg_buffer[DB_ERR_SIZE]; /* error message buffer */ i4 msg_buf_length; /* length of message returned */ i4 log; /* should this error be logged */ DB_SQLSTATE sqlstate; OPS_CB *opscb; /* ptr to session control block ** for this optimization */ opscb = ops_getcb(); opscb->ops_retstatus = E_DB_ERROR; /* return status code */ opscb->ops_callercb->opf_errorblock.err_code = error; /* save error code */ if ((error % 256) < 128) log = ULE_LOOKUP; else log = ULE_LOG; ule_status = ule_format( error, (CL_SYS_ERR *)NULL, log, &sqlstate, msg_buffer, (i4) (sizeof(msg_buffer)-1), &msg_buf_length, &ule_error, 2 /* 2 parameters */, (i4)0, p1, (i4)0, p2); if (ule_status != E_DB_OK) { (VOID)STprintf(msg_buffer, "ULE error = %x, Optimizer message cannot be found - error no. = %x\n", ule_error, error ); } else msg_buffer[msg_buf_length] = 0; /* null terminate */ (VOID) opx_sccerror(E_DB_ERROR, &sqlstate, error, msg_buffer, (i4)msg_buf_length); EXsignal( (EX)EX_JNP_LJMP, (i4)1, (long)error);/* signal an optimizer long ** jump */ }
/*{ ** Name: sxf_trace - SXF trace entry point. ** ** Description: ** This routine takes a standard trace control block as input, and ** sets or clears the given trace point. The trace points are either ** specific to a session or server wide. ** ** Inputs: ** debug_cb A standard debug control block. ** ** Outputs: ** Returns: ** E_DB_OK ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 16-jun-93 (robf) ** Created for Secure 2.0 ** 11-oct-93 (robf) ** Rework includes per current integration ** 30-mar-94 (robf) ** Add tracing of shared memory info. ** 09-Sep-2008 (jonj) ** Correct mis-typed ule_format output error_code. */ DB_STATUS sxf_trace( DB_DEBUG_CB *trace_cb ) { i4 bitno = trace_cb->db_trace_point; DB_STATUS status=E_DB_OK; i4 *vector ; i4 err_code; SXF_SCB *scb; i4 error; switch (bitno) { case SXS_TDUMP_SHM: /* ** Dump shared memory */ sxap_shm_dump(); SXF_DISPLAY("SXF shared memory info dumped to trace log"); break; case SXS_TDUMP_STATS: /* ** Dump statistics */ sxc_printstats(); SXF_DISPLAY("SXF server statistics dumped to trace log"); break; case SXS_TDUMP_SESSION: /* ** Dump session info */ status = sxau_get_scb(&scb, &err_code); if (status != E_DB_OK) { _VOID_ ule_format(err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &error, 0); _VOID_ ule_format(E_SX001E_TRACE_FLAG_ERR, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &error, 0); break; } SXF_DISPLAY("SXF Session info dumped to trace log"); break; case 0: case SXS_TAUD_LOG: case SXS_TAUD_PHYS: case SXS_TAUD_STATE: case SXS_TAUD_SHM: case SXS_TAUD_PLOCK: status = sxau_get_scb(&scb, &err_code); if (status != E_DB_OK) { _VOID_ ule_format(err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &error, 0); _VOID_ ule_format(E_SX001E_TRACE_FLAG_ERR, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &error, 0); break; } if (trace_cb->db_trswitch == DB_TR_ON) { if (ult_set_macro(&scb->sxf_trace, (trace_cb->db_trace_point), trace_cb->db_vals[0], trace_cb->db_vals[1]) != E_DB_OK) { _VOID_ ule_format(E_SX001E_TRACE_FLAG_ERR, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &error, 0); } } else if (trace_cb->db_trswitch == DB_TR_OFF) { if (ult_clear_macro(&scb->sxf_trace, (trace_cb->db_trace_point)) != E_DB_OK) { _VOID_ ule_format(E_SX001E_TRACE_FLAG_ERR, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &error, 0); } } break; default: _VOID_ ule_format(E_SX001E_TRACE_FLAG_ERR, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &error, 0); } sxf_tracing_on=TRUE; return (status); }
/* ** Name: sxapo_open - open an audit trail ** ** Description: ** This routine is used to open an audit trail that can, in theory, be used ** for either reading or writing audit records, although reading of ** operating system audit records is not currently supported. SXF supports ** the ability to have a maximum of one audit trail open for writing at ** a time. This routine ** returns an access identifier (actually a pointer to a SXAPO_RSCB ** structure) that must be specified for all other operations requested ** on this trail. if no filename is specified the current audit trail ** will be opened. ** ** Overview of algorithm:- ** ** Validate the parameters passed to the routine. ** Open a memory stream and allocate and build a SXAPO_RSCB. ** If filename is NULL get the name of the current audit trail. ** Call the SAopen routine to perform the physical open call. ** ** ** Inputs: ** filename Name of the audit trail to open, if this is NULL ** the current audit trail will be opened. ** mode either SXF_READ of SXF_WRITE (must currently ** be SXF_WRITE). ** sxf_rscb the SXF_RSCB for the audit trail ** ** Outputs: ** sxf_rscb Access identifier for audit file. ** err_code Error code returned to the caller. ** ** Returns: ** DB_STATUS ** ** History: ** 6-jan-94 (stephenb) ** Initial Creation. ** 7-feb-94 (stephenb) ** log error E_SX002E_OSAUDIT_NO_READ since we don't do it anywhere ** else yet. ** 11-feb-94 (stephenb) ** Update SA call to current spec. */ DB_STATUS sxapo_open( PTR filename, i4 mode, SXF_RSCB *sxf_rscb, i4 *filesize, PTR sptr, i4 *err_code) { ULM_RCB ulm_rcb; DB_STATUS status = E_DB_OK; i4 local_err; bool stream_open = FALSE; SXAPO_RSCB *sxapo_rscb; STATUS cl_stat; CL_ERR_DESC cl_err; *err_code = E_SX0000_OK; for (;;) { /* validate parameters, write is currently the only valid mode */ if (sxf_rscb == NULL) { *err_code = E_SX0004_BAD_PARAMETER; break; } else if (mode != SXF_WRITE) { *err_code = E_SX002E_OSAUDIT_NO_READ; /* ** Log this here since we don't yet do it anywhere else. */ _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); break; } /* ** Open a memory stream and allocate some memory for the SXAPO_RSCB */ ulm_rcb.ulm_facility = DB_SXF_ID; ulm_rcb.ulm_poolid = Sxf_svcb->sxf_pool_id; ulm_rcb.ulm_blocksize = 0; ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz; ulm_rcb.ulm_streamid_p = &ulm_rcb.ulm_streamid; /* No other allocations on this stream - make it private */ /* Open stream and allocate SXAPO_RSCB with one call */ ulm_rcb.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC; ulm_rcb.ulm_psize = sizeof (SXAPO_RSCB); status = ulm_openstream(&ulm_rcb); if (status != E_DB_OK) { if(ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM) *err_code = E_SX1002_NO_MEMORY; else *err_code = E_SX106B_MEMORY_ERROR; _VOID_ ule_format(ulm_rcb.ulm_error.err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); break; } stream_open = TRUE; sxf_rscb->sxf_sxap = ulm_rcb.ulm_pptr; sxapo_rscb = (SXAPO_RSCB *) sxf_rscb->sxf_sxap; sxapo_rscb->rs_memory = ulm_rcb.ulm_streamid; /* ** Filename should not be supplied for OS audit trail writes */ if (filename) { *err_code = E_SX101E_INVALID_FILENAME; break; } else { /* ** Auditing must be enabled to use "current" file */ if (Sxapo_cb->sxapo_status & SXAPO_STOPAUDIT) { _VOID_ ule_format(E_SX10A7_NO_CURRENT_FILE, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); *err_code = E_SX0015_FILE_NOT_FOUND; break; } } /* ** Open the audit trail with SAopen */ cl_stat = SAopen(NULL, SA_WRITE, &sxapo_rscb->sxapo_desc, &cl_err); if (cl_stat != OK) { *err_code = E_SX1018_FILE_ACCESS_ERROR; _VOID_ ule_format(*err_code, &cl_err, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); break; } break; } /* ** Handle any errors */ if (*err_code != E_SX0000_OK) { if (stream_open) _VOID_ ulm_closestream(&ulm_rcb); if (*err_code > E_SXF_INTERNAL) { _VOID_ ule_format(E_SX10B6_OSAUDIT_OPEN_FAILED, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); *err_code = E_SX1023_SXAP_OPEN; } if (status == E_DB_OK) status = E_DB_ERROR; } else { /* ** Incriment stats counter */ Sxf_svcb->sxf_stats->open_write++; } return (status); }
/* ** Name: SXC_END_SESSION - end a SXF session ** ** Description: ** This routine is used to end a SXF session, it is called at ** session end time via the sxf_call(SXC_END_SESSION) request. ** This request must be made by a session that has previously been ** registered with SXF via the sxc_bgn_session routine. All resourses ** allocated by this session will be released. ** ** Overview of algorithm:- ** ** Locate the SXF_SCB for this session. ** Call sxac_end_session to remove the session from the auditing system. ** Unlink SXF_SCB from SCB list in the server control block. ** Destroy the SXF_SCB. ** ** Inputs: ** rcb ** .sxf_scb Pointer to the session control block. ** ** Outputs: ** rcb ** .sxf_error error code returned to the caller ** ** Returns: ** DB_STATUS ** ** History: ** 11-aug-92 (markg) ** Initial creation. ** 26-oct-1992 (markg) ** Updated error handling. */ DB_STATUS sxc_end_session( SXF_RCB *rcb) { DB_STATUS status = E_DB_OK; i4 err_code = E_SX0000_OK; i4 local_err; SXF_SCB *scb; bool scb_found = FALSE; for (;;) { /* Locate SCB and remove the session from the audit system */ if (Sxf_svcb->sxf_svcb_status & SXF_SNGL_USER) { if (Sxf_svcb->sxf_scb_list == NULL) { err_code = E_SX000D_INVALID_SESSION; break; } else { scb = Sxf_svcb->sxf_scb_list; } } else { CSp_semaphore(TRUE, &Sxf_svcb->sxf_svcb_sem); for (scb = Sxf_svcb->sxf_scb_list; scb != NULL; scb = scb->sxf_next) { if (scb == (SXF_SCB *) rcb->sxf_scb) { scb_found = TRUE; break; } } CSv_semaphore(&Sxf_svcb->sxf_svcb_sem); if (scb_found == FALSE) { err_code = E_SX000D_INVALID_SESSION; break; } } status = sxac_end_session(scb, &local_err); if (status != E_DB_OK) { err_code = local_err; _VOID_ ule_format(err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); } /* Remove SCB from list of active sessions and destroy it */ CSp_semaphore(TRUE, &Sxf_svcb->sxf_svcb_sem); if (scb->sxf_prev != NULL) scb->sxf_prev->sxf_next = scb->sxf_next; else Sxf_svcb->sxf_scb_list = scb->sxf_next; if (scb->sxf_next != NULL) scb->sxf_next->sxf_prev = scb->sxf_prev; Sxf_svcb->sxf_active_ses--; CSv_semaphore(&Sxf_svcb->sxf_svcb_sem); status = sxc_destroy_scb(scb, &local_err); if (status != E_DB_OK) { err_code = local_err; _VOID_ ule_format(err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); } break; } /* Handle any errors */ if (err_code != E_SX0000_OK) { if (err_code > E_SXF_INTERNAL) err_code = E_SX000E_BAD_SESSION_END; rcb->sxf_error.err_code = err_code; if (status == E_DB_OK) status = E_DB_ERROR; } return (status); }
/*{ ** Name: sxf_call - The main SXF entry point. ** ** Description: ** The routine checks that the arguments to sxf_call look reasonable. ** The implementing function is then called and operation completion ** status is returned to the caller. ** ** Inputs: ** op_code The SXF operation code. ** rcb The SXF request control block for the operation. ** ** Outputs: ** Returns: ** DB_STATUS ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 9-July-1992 (markg) ** Initial creation. ** 03-sep-1992 (pholman) ** Give calls NULL functionlaity for initial integration ** 20-oct-1992 (markg) ** Updated to have entry points for all SXF operations. */ DB_STATUS sxf_call( SXF_OPERATION op_code, SXF_RCB *rcb) { DB_STATUS status = E_DB_OK; EX_CONTEXT context; i4 error; CLRDBERR(&rcb->sxf_error); /* Make a cursury check for bad parameters. */ if (op_code < SXF_MIN_OPCODE || op_code > SXF_MAX_OPCODE || rcb->sxf_cb_type != SXFRCB_CB || rcb->sxf_length != sizeof (SXF_RCB) || (Sxf_svcb == NULL && op_code != SXC_STARTUP)) { /* Figure out the error in more detail. */ if (op_code < SXF_MIN_OPCODE || op_code > SXF_MAX_OPCODE) SETDBERR(&rcb->sxf_error, 0, E_SX0001_BAD_OP_CODE); else if (rcb->sxf_cb_type != SXFRCB_CB) SETDBERR(&rcb->sxf_error, 0, E_SX0002_BAD_CB_TYPE); else if (rcb->sxf_length != sizeof (SXF_RCB)) { TRdisplay("Bad SXF CB length. Input length %d expected %d\n", rcb->sxf_length, sizeof(SXF_RCB)); SETDBERR(&rcb->sxf_error, 0, E_SX0003_BAD_CB_LENGTH); } else SETDBERR(&rcb->sxf_error, 0, E_SX000F_SXF_NOT_ACTIVE); return (E_DB_ERROR); } if (EXdeclare(ex_handler, &context) == OK && (Sxf_svcb == NULL || (Sxf_svcb->sxf_svcb_status & SXF_CHECK) == 0)) { switch (op_code) { /* Control operations. */ case SXC_STARTUP: status = sxc_startup(rcb); break; case SXC_SHUTDOWN: status = sxc_shutdown(rcb); break; case SXC_BGN_SESSION: status = sxc_bgn_session(rcb); break; case SXC_END_SESSION: status = sxc_end_session(rcb); break; case SXC_ALTER_SESSION: status = sxc_alter_session(rcb); break; case SXC_AUDIT_THREAD: status = sxac_audit_thread(rcb); break; case SXC_AUDIT_WRITER_THREAD: status = sxac_audit_writer_thread(rcb); break; /* Audit file oerations */ case SXA_OPEN: status = sxaf_open(rcb); break; case SXA_CLOSE: status = sxaf_close(rcb); break; /* Audit record operations */ case SXR_WRITE: status = sxar_write(rcb); break; case SXR_POSITION: status = sxar_position(rcb); break; case SXR_READ: status = sxar_read(rcb); break; case SXR_FLUSH: status = sxar_flush(rcb); break; /* Audit state operations */ case SXS_ALTER: status = sxas_alter(rcb); break; case SXS_SHOW: status = sxas_show(rcb); break; } EXdelete(); return (status); } /* ** If exception handler declares or the SXF_SVCB has already been ** marked inconsistent, this is a server fatal condition. In most ** cases it is sufficient to return a server fatal error, and let the ** caller handle the rest. ** ** However, if this is an audit record write operation we have to ** nuke the server ourselves. The reason for this is that if the ** client code does not handle the return status correctly the ** security of the system could be compromised. */ EXdelete(); if (op_code == SXR_WRITE) { _VOID_ ule_format(E_SX0005_INTERNAL_ERROR, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &error, 0); _VOID_ ule_format(E_SX1048_SERVER_TERMINATE, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &error, 0); _VOID_ CSterminate(CS_KILL, NULL); } SETDBERR(&rcb->sxf_error, 0, E_SX0005_INTERNAL_ERROR); return (E_DB_FATAL); }
/*{ ** Name: uld_prtree - Format and print a tree ** ** Description: ** This function formats and prints a tree, with help from caller- ** supplied functions. The algorithm was adapted by Bob Kooi from ** Wetherell, C. and Shannon, A., "Tidy Drawings of Trees," ** IEEE Transactions on Software Engineering, Vol. SE-5, No. 5 ** September, 1979 ** ** Later mods made it re-entrant so it could run as part of a server. ** ** EXAMPLE: ** suppose you have a tree made out of nodes of type tnode: ** ** struct tnode ** { ** i4 data1; ** i4 data2; ** struct tnode *left; ** struct tnode *right; ** } ** ** where Root is a pointer to the root. you must provide ** three routines, call them leftson, rightson and printnode: ** ** PTR ** leftson(t) ** PTR t; ** { ** return ((PTR) ((struct tnode *) t)->left); ** } ** ** PTR ** rightson(t) ** PTR t; ** { ** return ((PTR) ((struct tnode *) t)->right); ** } ** ** VOID ** printnode(t, control) ** PTR t; ** PTR control; ** { ** struct tnode *node = (struct tnode *) t; ** ** uld_prnode(control, "*****"); ** TRformat(uld_tr_callback, (i4 *)0, ** global_buffer, sizeof(global_buffer), ** "* %d *", ** node->data1); ** uld_prnode(control, global_buffer); ** TRformat(uld_tr_callback, (i4 *)0, ** global_buffer, sizeof(global_buffer), ** %d*", ** node->data2, node->data1); ** uld_prnode(control, global_buffer); ** uld_prnode(control, "*****"); ** } ** ** ** then the call: ** ** uld_prtree(0, (PTR) Root, printnode, leftson, rightson, 8, 5); ** ** would print a tree where each node is 8 characters wide ** by 5 characters long and would contain data1 on the first ** line, data2 and data1 on the second line with a border of ** stars. ** ** a sample output might be: ***** * 7 * *3 7* ***** / \ ***** ***** * 4 * * 3 * *3 4* *3 3* ***** ***** / \ / \ ***** ***** ***** ***** * 3 * * 1 * * 2 * * 1 * *3 3* *3 1* *3 2* *3 1* ***** ***** ***** ***** / \ / \ ***** ***** ***** ***** * 2 * * 1 * * 1 * * 1 * *3 2* *3 1* *3 1* *3 1* ***** ***** ***** ***** / \ ***** ***** * 1 * * 1 * *3 1* *3 1* ***** ***** ** ** Parts of a tree that exceed the manifest constants are not printed ** but should not otherwise cause difficulty (supposedly). ** ** ** the main difference between this and the reference is that here a ** "parallel" tree is built to hold the info (x,modifier) that, in the ** reference, is held in the nodes of the tree being printed. ** this means that the user need not plan for this routine but can ** easily add it in later. this is almost imperative when the user ** is working with variable size nodes in his tree. ** ** Inputs: ** root Pointer to the root of the tree ** printnode Pointer to function to format a node ** leftson Pointer to function to find left son ** rightson Pointer to function to find right son ** indent Indent scale factor (number of spaces ** to indent for each horizontal level) ** lbl Lines between levels (should at least ** equal the maximum number of lines that ** the user would ever print for a node ** to ensure an evenly spaced tree) ** facility facility ID of caller ** ** Outputs: ** None ** Returns: ** None ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 06-may-86 (jeff) ** Adapted from fmttree() in jutil!fmttree.c in 4.0 ** 24-mar-87 (daved) ** set exclusive semaphore so that large static structures ** for the control struct are single threaded. ** 18-Jun-87 (DaveS) ** Modified to get memory from ULM instead of using statics. ** SCF semaphore removed since we no longer need it. ** 04-nov-87 (thurston) ** On ulm_startup() call, I made the block size almost as large as the ** pool since all that this routine does is create a pool, start a ** stream, and allocate one L*A*R*G*E piece out of it. (Wouldn't this ** be better served by SCU_MALLOC directly??? ** 08-feb-89 (jrb) ** Fixed calls to ule_format which made no sense at all. ** 21-may-89 (jrb) ** Updated for new ule_format interface. ** 22-sep-1992 (bryanp) ** Pass an err_code argument to ule_format. It demands one. ** 7-oct-2004 (thaju02) ** Change memleft to SIZE_TYPE. ** 19-Aug-2009 (kibro01) b122509 ** Add new uld_prtree_x function which allows an extra sc930-tracing ** parameter to uld_prtree ** 17-Aug-2010 (horda03) b124274 ** Allow Trees to be printed in connected segments to aid readability. */ VOID uld_prtree_x( i4 flags, PTR root, VOID (*printnode)(), PTR (*leftson)(), PTR (*rightson)(), i4 indent, i4 lbl, i4 facility, PTR sc930_trace ) { register i4 i; register PARATREE *pnode; ULD_CONTROL control; ULD_STORAGE *storage = 0; ULM_RCB ulm_rcb; SIZE_TYPE memleft; STATUS status; i4 err_code; i4 max_nodes; ULD_PARAM *uld_param = 0; control.facility = facility; ulm_rcb.ulm_facility = DB_ULF_ID; ulm_rcb.ulm_sizepool = sizeof(ULD_STORAGE) + 1024; ulm_rcb.ulm_blocksize = sizeof(ULD_STORAGE) + 128; memleft = sizeof(ULD_STORAGE) + 1024; ulm_rcb.ulm_memleft = &memleft; /* create a memory pool */ status = ulm_startup(&ulm_rcb); if (status != E_DB_OK) { (VOID) ule_format(ulm_rcb.ulm_error.err_code, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &err_code, 0); (VOID) ule_format(E_UL0201_ULM_FAILED, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &err_code, 0); return; } /* open the private memory stream and allocate ULD_STORAGE */ ulm_rcb.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC; ulm_rcb.ulm_psize = sizeof (ULD_STORAGE); ulm_rcb.ulm_streamid_p = NULL; if ((status = ulm_openstream(&ulm_rcb)) != E_DB_OK) { (VOID) ule_format(ulm_rcb.ulm_error.err_code, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &err_code, 0); (VOID) ule_format(E_UL0201_ULM_FAILED, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &err_code, 0); return; } storage = (ULD_STORAGE *)ulm_rcb.ulm_pptr; control.lbl = lbl + 1; control.isf = indent; control.pti = 0; control.ptp = storage->pts; control.ncmx = indent * 2; control.first = 0; if (flags & ULD_FLAG_OUT_SEG) { uld_param = (ULD_PARAM *) root; root = uld_param->root; control.max_level = uld_param->control->max_level; control.segments = uld_param->control->segments; control.num_segments = uld_param->control->num_segments; } else if (flags & ULD_FLAG_SEGMENTS) { control.segments = storage->segments; control.num_segments = &storage->num_segments; storage->num_segments = 0; max_nodes = 132 / control.ncmx; for (i = 1; i < sizeof(nodes_per_level)/sizeof(i4); i++) { if (max_nodes < nodes_per_level [i]) break; } control.max_level = i - 1; } else control.max_level = 0; for (i = PMX + 1; i--; ) control.pbuf[i] = &(storage->pbf[i][0]); control.modifier = storage->mod; control.next_pos = storage->ned; /* Initialize line buffers */ control.bmax = PMX; prflsh(1, &control, NULL); /* Initialize arrays */ for (i = MAXH; i--; ) { control.next_pos[i] = '\1'; control.modifier[i] = '\0'; } /* Initialize the function pointers */ control.lson = leftson; control.rson = rightson; control.pnod = printnode; /* Do the first post-order walk */ control.maxh = -1; pnode = walk1(root, 0, &control); if (uld_param) { pnode->new_root = uld_param->root_num; } /* Do the second pre-order walk */ control.modfsum = 0; walk2(pnode, &control); /* For each level, print out the nodes at that level */ control.type = ROOT; for (i = 0; i <= control.maxh; i++) { walk3(root, pnode, 0, i, &control); prflsh(0, &control, sc930_trace); } if ( !uld_param && control.max_level) { ULD_PARAM u_root; u_root.control = &control; for (i = 0; i < *control.num_segments; i++ ) { u_root.root = control.segments [i]; u_root.root_num = i + 1; uld_prtree_x( ULD_FLAG_OUT_SEG, (PTR) &u_root, printnode, leftson, rightson, indent, -lbl, facility, sc930_trace ); } } /* if we got any memory, return it */ if (storage) ulm_shutdown(&ulm_rcb); }
/* ** Name: sxapo_init_cnf - Initialize SXAPO configuration from the PM file. ** ** Description: ** This routine initializes the SXAPO configuration from the ** PM configuration file. ** ** Inputs: ** None. ** ** Outputs: ** err_code Error code returned to caller. ** ** Returns: ** DB_STATUS ** ** History: ** 6-jan-94 (stephenb) ** Initial creation. */ static DB_STATUS sxapo_init_cnf( i4 *err_code) { DB_STATUS status = E_DB_OK; STATUS clstat; i4 local_err; char *pmfile; char *pmvalue; *err_code = E_SX0000_OK; for (;;) { /* ** Allow private override on PM file */ NMgtAt("II_SXF_PMFILE", &pmfile); if (pmfile && *pmfile) { LOCATION pmloc; TRdisplay("Loading SXF-PM file '%s'\n",pmfile); LOfroms(PATH & FILENAME, pmfile, &pmloc); if(PMload(&pmloc,NULL)!=OK) TRdisplay("Error loading PMfile '%s'\n",pmfile); } /* ** Get auditing status */ if (PMget(SX_C2_MODE,&pmvalue) == OK) { if (!STbcompare(pmvalue, 0, SX_C2_MODE_ON, 0, TRUE)) { /* ** Auditing on */ Sxapo_cb->sxapo_status=SXAPO_ACTIVE; } else if ((STbcompare(pmvalue, 0, SX_C2_MODE_OFF, 0, TRUE)!=0)) { /* ** Niether ON nor OFF, Invalid mode */ *err_code=E_SX1061_SXAP_BAD_MODE; break; } } else { /* ** No value, this is an error */ *err_code=E_SX1061_SXAP_BAD_MODE; break; } /* ** Get action on error */ if ((PMget("II.*.C2.ON_ERROR",&pmvalue) == OK)) { if (!STcasecmp(pmvalue, "STOPAUDIT" )) { Sxf_svcb->sxf_act_on_err=SXF_ERR_STOPAUDIT; } else if (!STcasecmp(pmvalue, "SHUTDOWN" )) { Sxf_svcb->sxf_act_on_err=SXF_ERR_SHUTDOWN; } else { /* ** Invalid value */ *err_code=E_SX1060_SXAP_BAD_ONERROR; break; } } else { /* ** No value, this is an error */ *err_code=E_SX1060_SXAP_BAD_ONERROR; break; } break; } /* handle errors */ if (*err_code != E_SX0000_OK) { _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); *err_code = E_SX1020_SXAP_INIT_CNF; status = E_DB_ERROR; } return (status); }
/* ** Name: sxapo_startup - startup the low level auditing system ** ** Description: ** ** This routine initializes the operating system audit log version of ** the SXAP auditing system. It should ** be called once at SXF startup time. Its purpose is to allocate ** and initialize the resources needed for the running of the low level ** auditing system. ** ** This routine also initializes the vector used to access all other ** SXAP routines, all these routines must be called using this vector. ** ** Inputs: ** None. ** ** Outputs: ** rscb RSCB for the current write audit file. ** err_code Error code returned to the caller. ** ** Returns: ** DB_STATUS ** ** History: ** 2-dec-93 (stephenb) ** first written. ** 4-jan-94 (stephenb) ** Add sxapo_alter entry point to the sxap vector. */ DB_STATUS sxapo_startup( SXF_RSCB *rscb, i4 *err_code) { DB_STATUS status = E_DB_OK; i4 local_err; SXAPO_RSCB *rs; ULM_RCB ulm_rcb; SXAP_VECTOR *v; bool file_open = FALSE; *err_code = E_SX0000_OK; for (;;) { /* Build the SXAP main control block */ ulm_rcb.ulm_facility = DB_SXF_ID; ulm_rcb.ulm_streamid_p = &Sxf_svcb->sxf_svcb_mem; ulm_rcb.ulm_psize = sizeof (SXAPO_CB); ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz; status = ulm_palloc(&ulm_rcb); if (status != E_DB_OK) { if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM) *err_code = E_SX1002_NO_MEMORY; else *err_code = E_SX106B_MEMORY_ERROR; _VOID_ ule_format(ulm_rcb.ulm_error.err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); break; } Sxapo_cb = (SXAPO_CB *) ulm_rcb.ulm_pptr; Sxapo_cb->sxapo_curr_rscb = NULL; /* Build and initialize the SXAP call vector */ ulm_rcb.ulm_psize = sizeof (SXAP_VECTOR); status = ulm_palloc(&ulm_rcb); if (status != E_DB_OK) { if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM) *err_code = E_SX1002_NO_MEMORY; else *err_code = E_SX106B_MEMORY_ERROR; _VOID_ ule_format(ulm_rcb.ulm_error.err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); break; } Sxap_vector = (SXAP_VECTOR *) ulm_rcb.ulm_pptr; v = Sxap_vector; v->sxap_init = sxapo_startup; v->sxap_term = sxapo_shutdown; v->sxap_begin = sxapo_bgn_ses; v->sxap_end = sxapo_end_ses; v->sxap_open = sxapo_open; v->sxap_close = sxapo_close; v->sxap_pos = sxapo_position; v->sxap_read = sxapo_read; v->sxap_write = sxapo_write; v->sxap_flush = sxapo_flush; v->sxap_show = sxapo_show; v->sxap_alter = sxapo_alter; /* Initialize the audit file configuration data */ status = sxapo_init_cnf(&local_err); if (status != E_DB_OK) { *err_code = local_err; _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); break; } /* ** Open the audit file for writing. */ status = sxapo_open( NULL, SXF_WRITE, rscb, NULL, NULL, &local_err); if (status != E_DB_OK) { *err_code = local_err; _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L, NULL, &local_err, 0); break; } file_open = TRUE; rs = (SXAPO_RSCB *) rscb->sxf_sxap; Sxapo_cb->sxapo_curr_rscb = rs; Sxapo_cb->sxapo_status |= SXAPO_ACTIVE; break; } /* Cleanup after any errors */ if (*err_code != E_SX0000_OK) { if (file_open) _VOID_ sxapo_close(rscb, &local_err); *err_code = E_SX101A_SXAP_STARTUP; /* ** Errors during startup of the auditing system are ** considered to be severe errors. */ status = E_DB_SEVERE; } return (status); }
/*{ ** Name: scs_monitor - Implement the SCS part of the monitor task ** ** Description: ** This routine is called ala the regular thread processing routine. ** It parses its input, decides what to do, and returns the output. ** ** The commmands completely interpreted here are: ** ** set server shut (CS_CLOSE) ** Disallow new connections, shutdown when ** last current session exits. ** ** remove SESSION ** New improved "safe" version, acts the same ** as front-end exiting and dropping GCA connection. ** ** kill SESSION ** Signal CS_KILL_EVENT to a user session actively ** running a query. ** ** NEW: ** set server closed ** Disallow new regular user sessions. ** ** set server open ** Reallow new regular user sessions. Cancel ** any pending 'set server shut' shutdown. ** ** show server listen ** ** crash session SESSIONID ** ** Commands partially handled here and partially in CSmonitor are: ** ** stop server (CS_KILL) ** Kill user sessions, shutdown when they're gone. ** ** stop server conditional (CS_COND_CLOSE) ** Shutdown if no sessions, which never works because ** this session always exists. ** ** crash server (CS_CRASH) ** Take the server down immediately. ** ** All other commands are passed to CSmonitor for handling. ** ** Inputs: ** mode Mode of operation ** CS_INPUT, _OUPUT, ... ** scb Sessions control block to monitor ** *command Text of the command ** powerful Is this user powerful ** output_fcn Function to call to perform the output. ** This routine will be called as ** (*output_fcn)(newline_present, ** length, ** buffer) ** where buffer is the length character ** output string, and newline_present ** indicates whether a newline needs to ** be added to the end of the string. ** ** Outputs: ** next_mode As above. ** Returns: ** OK ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 26-Jul-1993 (daveb) ** created. ** 15-Sep-1993 (daveb) ** ifdef out all but drop connection for now. ** 1-Nov-1993 (daveb) ** Match LRC proposal. Drop becomes remove, remove becomes kill. ** 10-Nov-1993 (daveb) ** Match approved proposal. Kill becomes "crash session SESSIONID" ** 15-dec-93 (robf) ** Add prototype "broadcast" message request. ** 4-mar-94 (robf) ** Add initial security auditing to iimonitor events. ** 12-dec-1996 (canor01) ** Add support for sampler thread. ** 24-Apr-2003 (jenjo02) ** Added "kill" command to abort eligible queries ** while leaving the session intact, SIR 110141. ** 17-Sep-2004 (schka24) ** Manual fix to remove command so that it fires. ** 05-may-2005 (horda03) Bug 114453/INGSRV 3290 ** For server/session changes log the command. ** 22-may-2007 (horda03) Bug 117966 ** Log the command before calling CSmonitor, as ** the CS could be crashing the server. ** 23-Sep-2009 (hanal04) Bug 115316 ** Added "SHOW SERVER CAPABILITIES". */ static STATUS scs_monitor( i4 mode, CS_SCB *scb, i4 *nmode, char *command, i4 powerful, i4 (*output_fcn)(PTR, i4, char *) ) { STATUS ret_stat; char buf[81]; bool completely_done; PTR ptr_scb; SCD_SCB *an_scb; i4 log_cmd = 0; i4 local_error; SCD_SCB *my_scb = (SCD_SCB*)scb; *nmode = CS_EXCHANGE; completely_done = FALSE; ret_stat = OK; switch (mode) { case CS_INITIATE: *nmode = CS_INPUT; break; case CS_TERMINATE: break; case CS_INPUT: CVlower(command); if (STscompare("setservershut", 0, command, 0) == 0) { /* Audit log the attempt here? */ if (!powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser status required to stop servers"); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_FAIL, I_SX274D_SET_SERVER_SHUT ); } else /* disallow regular listens, exit when last conn exits */ { Sc_main_cb->sc_listen_mask = (SC_LSN_TERM_IDLE |SC_LSN_SPECIAL_OK) ; TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Server will stop. %d. sessions remaining", Sc_main_cb->sc_current_conns ); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_SUCCESS, I_SX274D_SET_SERVER_SHUT ); log_cmd = 1; } completely_done = TRUE; } else if (STscompare("setserverclosed", 0, command, 0) == 0) { /* Audit log the attempt here? */ if (!powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser status required to disable connections"); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_FAIL, I_SX2748_SET_SERVER_CLOSED ); } else /* Disallow regular listens */ { if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_SUCCESS, I_SX2748_SET_SERVER_CLOSED ); Sc_main_cb->sc_listen_mask &= (~SC_LSN_REGULAR_OK); TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "User connections now disabled" ); log_cmd = 1; } completely_done = TRUE; } else if (STscompare("setserveropen", 0, command, 0) == 0) { /* Audit log the attempt here? */ if (!powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser status required to enable connections"); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_FAIL, I_SX2749_SET_SERVER_OPEN ); } else /* allow all listens, cancel any impending shutdown */ { Sc_main_cb->sc_listen_mask = (SC_LSN_REGULAR_OK | SC_LSN_SPECIAL_OK); TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "User connections now allowed" ); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_SUCCESS, I_SX2749_SET_SERVER_OPEN ); log_cmd = 1; } completely_done = TRUE; } else if (STncasecmp("broadcast", command, 9) == 0) { /* Audit log the attempt here? */ if (!powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser status required to broadcast messages"); } else { /* ** Broadcast the message to any connected sessions */ scs_scan_scbs(scs_broadcast_mesg, (PTR)(command+10)); } completely_done = TRUE; } else if (STscompare("stopserverconditional", 0, command, 0) == 0 || STscompare("stopserver", 0, command, 0) == 0 || STscompare("crashserver", 0, command, 0) == 0 ) { /* Audit log the attempt here? */ if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, powerful? SXF_A_CONTROL|SXF_A_SUCCESS: SXF_A_CONTROL|SXF_A_FAIL, /* Action */ I_SX274A_STOP_SERVER ); log_cmd = powerful; } else if (STscompare("showservercapabilities", 0, command, 0) == 0) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "%v", SC_CAPABILITIES_FLAGS, Sc_main_cb->sc_capabilities ); completely_done = TRUE; } else if (STscompare("showserverlisten", 0, command, 0) == 0) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "%s", Sc_main_cb->sc_listen_mask & SC_LSN_REGULAR_OK ? "OPEN" : "CLOSED" ); completely_done = TRUE; } else if (STscompare("showservershutdown", 0, command, 0) == 0) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "%s", Sc_main_cb->sc_listen_mask & SC_LSN_TERM_IDLE ? "PENDING" : "OPEN" ); completely_done = TRUE; } # ifdef NOT_SUPPORTED else if (STscompare("showconnections", 0, command, 0) == 0 ) { scs_scan_scbs( scs_show_func, (PTR)&powerful ); completely_done = TRUE; } else if (STscompare("show connection", 15, command, 15) == 0 ) { completely_done = TRUE; STzapblank(command, command); if (CVaxptr(command + 14, &ptr_scb) || !scs_is_user_scb( (an_scb = (SCD_SCB *)ptr_scb) ) ) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Invalid connection id"); break; } scs_show_func( an_scb, &powerful ); } # endif else if (STscompare("remove", 6, command, 6) == 0) { completely_done = TRUE; STzapblank(command, command); if (CVaxptr(command + 6, &ptr_scb) || scb == NULL || !scs_is_user_scb( (an_scb = (SCD_SCB *)ptr_scb) ) || an_scb == my_scb ) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Invalid session id"); break; } if ((MEcmp(an_scb->cs_scb.cs_username, scb->cs_username, sizeof(scb->cs_username))) && !powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser or owner status required to remove session"); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_FAIL, I_SX274B_REMOVE_SESSION ); break; } if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_SUCCESS, I_SX274B_REMOVE_SESSION ); scs_remove_sess( an_scb ); TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Session %p removed", an_scb); log_cmd = 1; } else if (STscompare("crash session", 13, command, 13) == 0) { completely_done = TRUE; STzapblank(command, command); if (CVaxptr(command + 12, &ptr_scb) || scb == NULL || !scs_is_user_scb( (an_scb = (SCD_SCB *)ptr_scb) ) || an_scb == my_scb ) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Invalid session id"); break; } if ((MEcmp(an_scb->cs_scb.cs_username, scb->cs_username, sizeof(scb->cs_username))) && !powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser or owner status required to crash session"); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_FAIL, I_SX274C_CRASH_SESSION ); break; } if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_SUCCESS, I_SX274C_CRASH_SESSION ); scs_crash_sess( an_scb ); TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Session %p crashed", an_scb); log_cmd = 1; } else if (STscompare("kill", 4, command, 4) == 0) { completely_done = TRUE; STzapblank(command, command); if (CVaxptr(command + 4, &ptr_scb) || scb == NULL || !scs_is_user_scb( (an_scb = (SCD_SCB *)ptr_scb) ) || an_scb == my_scb ) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Invalid session id"); } else if ((MEcmp(an_scb->cs_scb.cs_username, scb->cs_username, sizeof(scb->cs_username))) && !powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser or owner status required to kill query"); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_FAIL, I_SX2755_KILL_QUERY ); } else switch ( an_scb->scb_sscb.sscb_qmode ) { case 0: TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Session %p is not executing a query", an_scb); break; /* Honor only "meaningful" types of queries: */ case PSQ_RETRIEVE: case PSQ_RETINTO: case PSQ_APPEND: case PSQ_REPLACE: case PSQ_DELETE: case PSQ_COPY: case PSQ_MODIFY: case PSQ_EXECQRY: case PSQ_EXCURS: case PSQ_CALLPROC: case PSQ_REPCURS: case PSQ_RETCURS: case PSQ_EXEDBP: case PSQ_REGPROC: case PSQ_DDEXECPROC: case PSQ_CREATE: if ( an_scb->scb_sscb.sscb_force_abort || an_scb->scb_sscb.sscb_interrupt ) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Session %p query already aborting", an_scb); } else { scs_kill_query( an_scb ); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_SUCCESS, I_SX2755_KILL_QUERY ); TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Session %p query killed", an_scb); } break; default: TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Session %p query cannot be killed", an_scb); break; } } # ifdef NOT_SUPPORTED else if (STscompare("help", 0, command, 0) == 0) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "SCS monitor commands:\nset server shut\nset server closed\nset server open\nshow server listen\nshow server shutdown\nremove SESSION\ncrash session SESSION\n\nCS monitor commands:\n"); } # endif else if (! CS_is_mt()) /* OS Thread version will start an OS thread in the CS */ if ((STscompare("start sampling", 14, command, 14) == 0)) { if (!powerful) { TRformat(output_fcn, (i4 *) 1, buf, sizeof(buf)-1, "Superuser status required to start sampling.", 0L); } else { GCA_LS_PARMS local_crb; CL_ERR_DESC errdesc; local_crb.gca_status = 0; local_crb.gca_assoc_id = 0; local_crb.gca_size_advise = 0; local_crb.gca_user_name = "<Sampler Thread>"; local_crb.gca_account_name = 0; local_crb.gca_access_point_identifier = "NONE"; local_crb.gca_application_id = 0; /* set up all the CS control blocks for the sampler */ ret_stat = CSmonitor( mode, scb, nmode, command, powerful, output_fcn ); if ( ret_stat == OK ) ret_stat = CSadd_thread(CS_LIM_PRIORITY-1, (PTR) &local_crb, SCS_SSAMPLER, (CS_SID*)NULL, &errdesc); if (ret_stat) { TRformat(output_fcn, (i4 *) 1, buf, sizeof(buf)-1, "Sampling failed to start."); } } } /* log the command before calling CSmonitor(), as the server could be left in an ** unknown state if the command CRASH SERVER or STOP SERVER are used */ if (log_cmd) { ule_format( I_SC051E_IIMONITOR_CMD, 0, ULE_LOG, NULL, 0, 0, 0, &local_error, 3, STlength(command), command, DB_OWN_MAXNAME, &((SCD_SCB *)scb)->scb_sscb.sscb_ics.ics_rusername, sizeof(DB_TERM_NAME), &((SCD_SCB *)scb)->scb_sscb.sscb_ics.ics_terminal, 0, 0); } if( !completely_done ) ret_stat = CSmonitor( mode, scb, nmode, command, powerful, output_fcn ); break; case CS_OUTPUT: break; } return( ret_stat ); }
DB_STATUS qss_end_session( QSF_RCB *qsf_rb) { STATUS status = E_DB_OK; i4 *err_code = &qsf_rb->qsf_error.err_code; QSF_CB *scb = qsf_rb->qsf_scb; QSF_RCB int_qsf_rb; QSO_OBJ_HDR *objects = (QSO_OBJ_HDR *) scb->qss_obj_list; QSO_OBJ_HDR *obj; i4 error; i4 count; #ifdef xDEBUG QSF_CB *prevses; QSF_CB *nextses; i4 trace_003; #endif /* xDEBUG */ /* Toss any uncommitted named session-owned objects first. ** There shouldn't be any, if QEF did its job right, but who knows. ** The important thing is that we NOT have objects pretending to be ** on a session list when the session has ended. */ int_qsf_rb.qsf_sid = qsf_rb->qsf_sid; int_qsf_rb.qsf_scb = scb; (void) qsf_clrsesobj(&int_qsf_rb); /* ** Look for orphaned objects that should not exist and destroy unshareable ** named objects. */ count = QSF_MAX_ORPHANS; while (objects != (QSO_OBJ_HDR *) NULL && --count > 0) { STATUS status; QSO_OBJ_HDR *current_obj = objects; objects = objects->qso_obnext; if (current_obj->qso_obid.qso_lname == 0) { char *type; switch (current_obj->qso_obid.qso_type) { case QSO_QTEXT_OBJ: type = "Query Text"; break; case QSO_QTREE_OBJ: type = "Query Tree"; break; case QSO_QP_OBJ: type = "Query Plan"; break; case QSO_SQLDA_OBJ: type = "SQLDA"; break; case QSO_ALIAS_OBJ: type = "Alias"; break; default: type = "Unknown"; break; } /* Report the orphaned object. */ ule_format( E_QS001E_ORPHANED_OBJ, NULL, (i4) ULE_LOG, NULL, NULL, (i4) 0, NULL, &error, 1, 0, type); } int_qsf_rb.qsf_obj_id = current_obj->qso_obid; int_qsf_rb.qsf_lk_state = QSO_EXLOCK; int_qsf_rb.qsf_sid = qsf_rb->qsf_sid; int_qsf_rb.qsf_scb = scb; status = qso_lock(&int_qsf_rb); if (DB_FAILURE_MACRO(status)) { ule_format( int_qsf_rb.qsf_error.err_code, NULL, (i4) ULE_LOG, NULL, NULL, (i4) 0, NULL, &error, 0); } int_qsf_rb.qsf_lk_id = current_obj->qso_lk_id; status = qso_destroy(&int_qsf_rb); if (DB_FAILURE_MACRO(status)) { ule_format( int_qsf_rb.qsf_error.err_code, NULL, (i4) ULE_LOG, NULL, NULL, (i4) 0, NULL, &error, 0); } } if (count <= 0) { ule_format( E_QS001F_TOO_MANY_ORPHANS, NULL, (i4) ULE_LOG, NULL, NULL, (i4) 0, NULL, &error, 0); } #ifdef xDEBUG if (Qsr_scb->qsr_tracing && qst_trcheck(&scb, QSF_001_ENDSES_OBJQ)) { i4 save_err = *err_code; TRdisplay("<<< Dumping QSF object queue before ending session >>>\n"); (void) qsd_obq_dump(qsf_rb); *err_code = save_err; } trace_003 = ( Qsr_scb->qsr_tracing && qst_trcheck(&scb, QSF_003_CHK_SCB_LIST) ); /* Must check before ** we blow away the ** the session CB. */ #endif /* xDEBUG */ /* First, wait to get exclusive access to QSF's SERVER CONTROL BLOCK */ /* ----------------------------------------------------------------- */ if (CSp_semaphore((i4) TRUE, &Qsr_scb->qsr_psem)) { *err_code = E_QS0008_SEMWAIT; /* Return now, instead of attempting to do a v() */ return (E_DB_ERROR); } /* Do a quick run through the global LRU-able (persistent) object list ** and clear the session if it's us. This indicates that the object ** is not on any session list, and prevents someone else from believing ** a stale qso_session. */ obj = Qsr_scb->qsr_1st_lru; while (obj != NULL) { if (obj->qso_session == scb) obj->qso_session = NULL; obj = obj->qso_lrnext; } /* Now remove this session from QSF's server CB */ /* -------------------------------------------- */ if (scb == Qsr_scb->qsr_se1st) Qsr_scb->qsr_se1st = scb->qsf_next; else scb->qsf_prev->qsf_next = scb->qsf_next; if (scb->qsf_next != NULL) scb->qsf_next->qsf_prev = scb->qsf_prev; scb->qsf_prev = scb->qsf_next = NULL; Qsr_scb->qsr_nsess--; #ifdef xDEBUG if (trace_003) { /* This code just verifies that the session CB list is intact */ /* ---------------------------------------------------------- */ count = Qsr_scb->qsr_nsess; prevses = NULL; nextses = Qsr_scb->qsr_se1st; *err_code = E_QS9999_INTERNAL_ERROR; while (count-- > 0) { if (nextses == NULL) { TRdisplay("*** Not enough QSF session CBs found"); TRdisplay(" while ending a session.\n"); return (E_DB_FATAL); } if ( (nextses->qsf_prev != prevses) || (nextses->qsf_ascii_id != QSFCB_ASCII_ID) || (nextses->qsf_type != QSFCB_CB) || (nextses->qsf_length != sizeof(QSF_CB)) ) { TRdisplay("*** QSF's session CB list found trashed"); TRdisplay(" while ending a session.\n"); return (E_DB_FATAL); } prevses = nextses; nextses = nextses->qsf_next; } if (nextses != NULL) { TRdisplay("*** Too many QSF session CBs detected"); TRdisplay(" while ending a session.\n"); return (E_DB_FATAL); } } #endif /* xDEBUG */ status = E_DB_OK; *err_code = E_QS0000_OK; exit: /* Release exclusive access to QSF's SERVER CONTROL BLOCK */ /* ------------------------------------------------------ */ if (CSv_semaphore(&Qsr_scb->qsr_psem)) { status = E_DB_ERROR; *err_code = E_QS0004_SEMRELEASE; } return (status); }
/*{ ** Name: opx_rverror - this routine will report another facility's error ** ** Description: ** This routine will log an error from another facility and the related ** optimizer error. ** ** Inputs: ** opfcb ptr to another facility's control block ** error optimizer error code to report ** facility ptr to facility's control block ** ** Outputs: ** Returns: ** VOID ** Exceptions: ** - internal exception generated ** ** Side Effects: ** the exception handling routines are responsible for ** deallocating OPF resources bound to this session. ** ** History: ** 3-jul-86 (seputis) ** initial creation ** 21-may-89 (jrb) ** now passes generic_error to opx_sccerror routine ** 24-oct-92 (andre) ** interfaces of ule_format() and opx_sccerror() have been changed to ** receive (DB_SQLSTATE *) ** 24-Oct-2008 (jonj) ** Replace ule_doformat with ule_format. [@history_line@]... */ VOID opx_rverror( OPF_CB *opfcb, DB_STATUS status, OPX_ERROR error, OPX_FACILITY facility) { DB_STATUS ule_status; /* return status from ule_format */ i4 ule_error; /* ule cannot format message */ char msg_buffer[DB_ERR_SIZE]; /* error message buffer */ i4 msg_buf_length; /* length of message returned */ i4 log; /* logging state */ DB_SQLSTATE sqlstate; opfcb->opf_errorblock.err_code = error; /* save error code */ opfcb->opf_errorblock.err_data = facility; /* save code ** from facility */ if ((error % 256) < 128) log = ULE_LOOKUP; /* lookup only user errors with range ** of 0-127 */ else log = ULE_LOG; /* log errors with range 128-255 */ #ifdef OPT_F031_WARNINGS /* if trace flag is set then warning or info errors will be reported */ if ( DB_SUCCESS_MACRO(status)) { OPS_CB *ops_cb; ops_cb = ops_getcb(); if (ops_cb && ( !ops_cb->ops_check || !opt_strace( ops_cb, OPT_F031_WARNINGS) )) return; } #endif ule_status = ule_format( error, (CL_SYS_ERR *)NULL, log, &sqlstate, msg_buffer, (i4) (sizeof(msg_buffer)-1), &msg_buf_length, &ule_error, 0); if (ule_status != E_DB_OK) { (VOID)STprintf(msg_buffer, "ULE error = %x\nOptimizer cannot be found - error no = %x Status = %x Facility error = %x \n", ule_error, error , status, facility); } else msg_buffer[msg_buf_length] = 0; /* null terminate */ /* FIXME - should check possible return status and generate a severe error ** unless it is simple (like cannot find message) */ { /* report any errors in the range 0 to 127 to the user */ DB_STATUS scf_status; if (facility) scf_status = opx_sccerror(E_DB_WARN, &sqlstate, error, msg_buffer,(i4)msg_buf_length); /* generate ** a warning, so that SCC_TRACE is ** used, this will ensure that ** SCC_ERROR will be called with ** the "facility" error code which ** will be the ingres user code ** which will be returned to the ** equel program */ else scf_status = opx_sccerror(status, &sqlstate, error, msg_buffer, (i4)msg_buf_length); if (scf_status != E_DB_OK) { TRdisplay( "Optimizer error = %x Status = %x Facility error = %x \n", error , status, facility); } } if (!facility) return; /* if facility error exists then ** report it in the same way */ ule_status = ule_format( facility, (CL_SYS_ERR *)NULL, log, &sqlstate, msg_buffer, (i4) (sizeof(msg_buffer)-1), &msg_buf_length, &ule_error, 0); if (ule_status != E_DB_OK) { (VOID)STprintf(msg_buffer, "ULE error = %x\nOptimizer error = %x Status = %x Facility error cannot be found - error no = %x \n", ule_error, error , status, facility); } else msg_buffer[msg_buf_length] = 0; /* null terminate */ { DB_STATUS scf1_status; scf1_status = opx_sccerror(status, &sqlstate, facility, msg_buffer, (i4)msg_buf_length); if (scf1_status != E_DB_OK) { TRdisplay( "Optimizer error = %x Status = %x Facility error = %x \n", error , status, facility); } } }