implement asTrapWrite

This commit is contained in:
Marty Kraimer
2000-12-15 15:02:32 +00:00
parent f4397da253
commit 34198a1824
7 changed files with 294 additions and 12 deletions

View File

@@ -4,11 +4,13 @@ include $(TOP)/configure/CONFIG
INC += asLib.h
INC += asDbLib.h
INC += asCa.h
INC += asTrapWrite.h
LIBSRCS += asLib.c
asIoc_SRCS += asDbLib.c
asIoc_SRCS += asCa.c
asIoc_SRCS += asTrapWrite.c
LIBRARY_HOST = asHost
LIBRARY_IOC = asIoc

View File

@@ -35,13 +35,19 @@ long asCheckGet(ASCLIENTPVT asClientPvt);
long asCheckPut(ASCLIENTPVT asClientPvt);
*/
#define asCheckGet(asClientPvt)\
(asActive ?\
((asClientPvt)->access>=asREAD ? TRUE : FALSE)\
(asActive \
? ((asClientPvt)->access>=asREAD ? TRUE : FALSE)\
: TRUE)
#define asCheckPut(asClientPvt)\
(asActive ?\
((asClientPvt)->access>=asWRITE ? TRUE : FALSE)\
(asActive \
? ((asClientPvt)->access>=asWRITE ? TRUE : FALSE)\
: TRUE)
#define asTrapWriteBefore(asClientPvt,user,host,addr) \
(((asActive) && (asClientPvt)->trapMask) \
? asTrapWriteBeforeWrite((user),(host),(addr)) \
: 0)
#define asTrapWriteAfter(pvt) if((pvt)) asTrapWriteAfterWrite((pvt))
epicsShareFunc long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction);
epicsShareFunc long epicsShareAPI asInitFile(const char *filename,const char *substitutions);
@@ -76,6 +82,11 @@ epicsShareFunc int epicsShareAPI asDumpRules(char *asgname);
epicsShareFunc int epicsShareAPI asDumpMem(char *asgname,void (*memcallback)(ASMEMBERPVT),int clients);
epicsShareFunc int epicsShareAPI asDumpHash(void);
epicsShareFunc void * epicsShareAPI asTrapWriteBeforeWrite(
char *userid,char *hostid,void *addr);
epicsShareFunc void epicsShareAPI asTrapWriteAfterWrite(void *pvt);
#define S_asLib_clientsExist (M_asLib| 1) /*Client Exists*/
#define S_asLib_noUag (M_asLib| 2) /*User Access Group does not exist*/
#define S_asLib_noHag (M_asLib| 3) /*Host Access Group does not exist*/
@@ -137,6 +148,7 @@ typedef struct {
ELLNODE node;
HAG *phag;
}ASGHAG;
#define AS_TRAP_WRITE 1
typedef struct{
ELLNODE node;
asAccessRights access;
@@ -147,6 +159,7 @@ typedef struct{
void *rpcl;
ELLLIST uagList; /*List of ASGUAG*/
ELLLIST hagList; /*List of ASGHAG*/
int trapMask;
} ASGRULE;
typedef struct{
ELLNODE node;
@@ -173,6 +186,7 @@ typedef struct asgMember {
char *asgName;
void *userPvt;
} ASGMEMBER;
typedef struct asgClient {
ELLNODE node;
ASGMEMBER *pasgMember;
@@ -182,6 +196,7 @@ typedef struct asgClient {
ASCLIENTCALLBACK pcallback;
int level;
asAccessRights access;
int trapMask;
} ASGCLIENT;
epicsShareFunc long epicsShareAPI asComputeAsg(ASG *pasg);

View File

@@ -132,7 +132,9 @@ inp_body: tokenNAME
rule_config: tokenRULE rule_head rule_body
| tokenRULE rule_head
rule_head: '(' tokenINTEGER ',' tokenNAME ')'
rule_head: rule_head_manditory rule_head_options
rule_head_manditory: '(' tokenINTEGER ',' tokenNAME
{
asAccessRights rights;
@@ -151,6 +153,21 @@ rule_head: '(' tokenINTEGER ',' tokenNAME ')'
}
;
rule_head_options: ')'
| rule_log_options
rule_log_options: ',' tokenNAME ')'
{
if((strcmp($2,"TRAPWRITE")==0)) {
long status;
status = asAsgAddRuleOptions(yyAsgRule,AS_TRAP_WRITE);
if(status) yyerror("");
} else if((strcmp($2,"NOTRAPWRITE")!=0)) {
yyerror("Illegal access type");
}
free((void *)$2);
}
;
rule_body: '{' rule_list '}'
;

View File

@@ -69,6 +69,7 @@ static long asHagAddHost(HAG *phag,char *host);
static ASG *asAsgAdd(char *asgName);
static long asAsgAddInp(ASG *pasg,char *inp,int inpIndex);
static ASGRULE *asAsgAddRule(ASG *pasg,asAccessRights access,int level);
static long asAsgAddRuleOptions(ASGRULE *pasgrule,int trapMask);
static long asAsgRuleUagAdd(ASGRULE *pasgrule,char *name);
static long asAsgRuleHagAdd(ASGRULE *pasgrule,char *name);
static long asAsgRuleCalc(ASGRULE *pasgrule,char *calc);
@@ -465,6 +466,7 @@ long epicsShareAPI asCompute(ASCLIENTPVT asClientPvt)
/*The dump routines do not lock. Thus they may get inconsistant data.*/
/*HOWEVER if they did lock and a user interrupts one of then then BAD BAD*/
static char *asAccessName[] = {"NONE","READ","WRITE"};
static char *asTrapOption[] = {"NOTRAPWRITE","TRAPWRITE"};
static char *asLevelName[] = {"ASL0","ASL1"};
int epicsShareAPI asDump(
void (*memcallback)(struct asgMember *),
@@ -541,8 +543,9 @@ int epicsShareAPI asDump(
while(pasgrule) {
int print_end_brace;
printf("\tRULE(%d,%s)",
pasgrule->level,asAccessName[pasgrule->access]);
printf("\tRULE(%d,%s,%s)",
pasgrule->level,asAccessName[pasgrule->access],
asTrapOption[pasgrule->trapMask]);
pasguag = (ASGUAG *)ellFirst(&pasgrule->uagList);
pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
if(pasguag || pasghag || pasgrule->calc) {
@@ -592,7 +595,9 @@ int epicsShareAPI asDump(
else
printf(" Illegal Level %d",pasgclient->level);
if(pasgclient->access>=0 && pasgclient->access<=2)
printf(" %s",asAccessName[pasgclient->access]);
printf(" %s %s",
asAccessName[pasgclient->access],
asTrapOption[pasgclient->trapMask]);
else
printf(" Illegal Access %d",pasgclient->access);
if(clientcallback) clientcallback(pasgclient);
@@ -698,8 +703,9 @@ int epicsShareAPI asDumpRules(char *asgname)
while(pasgrule) {
int print_end_brace;
printf("\tRULE(%d,%s)",
pasgrule->level,asAccessName[pasgrule->access]);
printf("\tRULE(%d,%s,%s)",
pasgrule->level,asAccessName[pasgrule->access],
asTrapOption[pasgrule->trapMask]);
pasguag = (ASGUAG *)ellFirst(&pasgrule->uagList);
pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
if(pasguag || pasghag || pasgrule->calc) {
@@ -771,7 +777,9 @@ int epicsShareAPI asDumpMem(char *asgname,void (*memcallback)(ASMEMBERPVT),int c
else
printf(" Illegal Level %d",pasgclient->level);
if(pasgclient->access>=0 && pasgclient->access<=2)
printf(" %s",asAccessName[pasgclient->access]);
printf(" %s %s",
asAccessName[pasgclient->access],
asTrapOption[pasgclient->trapMask]);
else
printf(" Illegal Access %d",pasgclient->access);
printf("\n");
@@ -891,6 +899,7 @@ static long asComputeAsgPvt(ASG *pasg)
static long asComputePvt(ASCLIENTPVT asClientPvt)
{
asAccessRights access=asNOACCESS;
int trapMask=0;
ASGCLIENT *pasgclient = asClientPvt;
ASGMEMBER *pasgMember;
ASG *pasg;
@@ -943,12 +952,15 @@ check_hag:
}
check_calc:
if(!pasgrule->calc
|| (!(pasg->inpBad & pasgrule->inpUsed) && (pasgrule->result==1)))
|| (!(pasg->inpBad & pasgrule->inpUsed) && (pasgrule->result==1))) {
access = pasgrule->access;
trapMask = pasgrule->trapMask;
}
next_rule:
pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule);
}
pasgclient->access = access;
pasgclient->trapMask = trapMask;
if(pasgclient->pcallback && oldaccess!=access) {
(*pasgclient->pcallback)(pasgclient,asClientCOAR);
}
@@ -1187,6 +1199,7 @@ static ASGRULE *asAsgAddRule(ASG *pasg,asAccessRights access,int level)
if(!pasg) return(0);
pasgrule = asCalloc(1,sizeof(ASGRULE));
pasgrule->access = access;
pasgrule->trapMask = 0;
pasgrule->level = level;
ellInit(&pasgrule->uagList);
ellInit(&pasgrule->hagList);
@@ -1194,6 +1207,16 @@ static ASGRULE *asAsgAddRule(ASG *pasg,asAccessRights access,int level)
return(pasgrule);
}
static long asAsgAddRuleOptions(ASGRULE *pasgrule,int trapMask)
{
if(!pasgrule) {
errMessage(S_asLib_badConfig," Access Security internal failure");
return(0);
}
pasgrule->trapMask = trapMask;
return(0);
}
static long asAsgRuleUagAdd(ASGRULE *pasgrule,char *name)
{
ASGUAG *pasguag;

166
src/as/asTrapWrite.c Normal file
View File

@@ -0,0 +1,166 @@
/*asTrapWrite.c */
/* Author: Marty Kraimer Date: 07NOV2000 */
/*****************************************************************
COPYRIGHT NOTIFICATION
*****************************************************************
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
This software was developed under a United States Government license
described on the COPYRIGHT_UniversityOfChicago file included as part
of this distribution.
**********************************************************************/
/* Matthias Clausen and Vladis Korobov at DESY
* implemented the first logging of Channel Access Puts
* This implementation uses many ideas from their implementation
*/
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "ellLib.h"
#include "freeList.h"
#include "cantProceed.h"
#include "asLib.h"
#include "asTrapWrite.h"
#include "osiSem.h"
#include "ellLib.h"
typedef struct listenerPvt {
ELLNODE node;
struct listener *plistener;
void *userPvt;
}listenerPvt;
typedef struct listener{
ELLNODE node;
asTrapWriteListener func;
}listener;
typedef struct writeMessage {
ELLNODE node;
asTrapWriteMessage message;
ELLLIST listenerPvtList;
}writeMessage;
typedef struct asTrapWritePvt
{
ELLLIST listenerList;
ELLLIST writeMessageList;
void *freeListWriteMessage;
void *freeListListenerPvt;
semMutexId lock;
}asTrapWritePvt;
static asTrapWritePvt *pasTrapWritePvt = 0;
static void asTrapWriteInit(void)
{
pasTrapWritePvt = callocMustSucceed(1,sizeof(asTrapWritePvt),"asTrapWriteInit");
ellInit(&pasTrapWritePvt->listenerList);
ellInit(&pasTrapWritePvt->writeMessageList);
freeListInitPvt(
&pasTrapWritePvt->freeListWriteMessage,sizeof(writeMessage),20);
freeListInitPvt(
&pasTrapWritePvt->freeListListenerPvt,sizeof(listenerPvt),20);
pasTrapWritePvt->lock = semMutexMustCreate();
}
asTrapWriteId epicsShareAPI asTrapWriteRegisterListener(
asTrapWriteListener func)
{
listener *plistener;
if(pasTrapWritePvt==0) asTrapWriteInit();
plistener = callocMustSucceed(1,sizeof(listener),"asTrapWriteRegisterListener");
plistener->func = func;
semMutexMustTake(pasTrapWritePvt->lock);
ellAdd(&pasTrapWritePvt->listenerList,&plistener->node);
semMutexGive(pasTrapWritePvt->lock);
return((asTrapWriteId)plistener);
}
void epicsShareAPI asTrapWriteUnregisterListener(asTrapWriteId id)
{
listener *plistener = (listener *)id;
writeMessage *pwriteMessage;
if(pasTrapWritePvt==0) return;
semMutexMustTake(pasTrapWritePvt->lock);
pwriteMessage = (writeMessage *)ellFirst(&pasTrapWritePvt->writeMessageList);
while(pwriteMessage) {
listenerPvt *plistenerPvt
= (listenerPvt *)ellFirst(&pwriteMessage->listenerPvtList);
while(plistenerPvt) {
listenerPvt *pnext
= (listenerPvt *)ellNext(&plistenerPvt->node);
if(plistenerPvt->plistener == plistener) {
ellDelete(&pwriteMessage->listenerPvtList,&plistenerPvt->node);
freeListFree(pasTrapWritePvt->freeListListenerPvt,(void *)plistenerPvt);
}
plistenerPvt = pnext;
}
pwriteMessage = (writeMessage *)ellNext(&pwriteMessage->node);
}
ellDelete(&pasTrapWritePvt->listenerList,&plistener->node);
free((void *)plistener);
semMutexGive(pasTrapWritePvt->lock);
}
void * epicsShareAPI asTrapWriteBeforeWrite(
char *userid,char *hostid,void *addr)
{
writeMessage *pwriteMessage;
listener *plistener;
listenerPvt *plistenerPvt;
if(pasTrapWritePvt==0) return(0);
if(ellCount(&pasTrapWritePvt->listenerList)<=0) return 0;
pwriteMessage = (writeMessage *)freeListCalloc(
pasTrapWritePvt->freeListWriteMessage);
pwriteMessage->message.userid = userid;
pwriteMessage->message.hostid = hostid;
pwriteMessage->message.serverSpecific = addr;
ellInit(&pwriteMessage->listenerPvtList);
semMutexMustTake(pasTrapWritePvt->lock);
ellAdd(&pasTrapWritePvt->writeMessageList,&pwriteMessage->node);
plistener = (listener *)ellFirst(&pasTrapWritePvt->listenerList);
while(plistener) {
plistenerPvt = (listenerPvt *)freeListCalloc(
pasTrapWritePvt->freeListListenerPvt);
plistenerPvt->plistener = plistener;
pwriteMessage->message.userPvt = 0;
(*plistener->func)(&pwriteMessage->message,0);
plistenerPvt->userPvt = pwriteMessage->message.userPvt;
ellAdd(&pwriteMessage->listenerPvtList,&plistenerPvt->node);
plistener = (listener *)ellNext(&plistener->node);
}
semMutexGive(pasTrapWritePvt->lock);
return((void *)pwriteMessage);
}
void epicsShareAPI asTrapWriteAfterWrite(void *pvt)
{
writeMessage *pwriteMessage = (writeMessage *)pvt;
listenerPvt *plistenerPvt;
if(pwriteMessage==0 || pasTrapWritePvt==0) return;
semMutexMustTake(pasTrapWritePvt->lock);
plistenerPvt = (listenerPvt *)ellFirst(&pwriteMessage->listenerPvtList);
while(plistenerPvt) {
listenerPvt *pnext = (listenerPvt *)ellNext(&plistenerPvt->node);
listener *plistener;
plistener = plistenerPvt->plistener;
pwriteMessage->message.userPvt = plistenerPvt->userPvt;
(*plistener->func)(&pwriteMessage->message,1);
ellDelete(&pwriteMessage->listenerPvtList,&plistenerPvt->node);
freeListFree(pasTrapWritePvt->freeListListenerPvt,(void *)plistenerPvt);
plistenerPvt = pnext;
}
ellDelete(&pasTrapWritePvt->writeMessageList,&pwriteMessage->node);
freeListFree(pasTrapWritePvt->freeListWriteMessage,(void *)pwriteMessage);
semMutexGive(pasTrapWritePvt->lock);
}

55
src/as/asTrapWrite.h Normal file
View File

@@ -0,0 +1,55 @@
/*asTrapWrite.h*/
/* Author: Marty Kraimer Date: 07NOV2000 */
/*****************************************************************
COPYRIGHT NOTIFICATION
*****************************************************************
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
This software was developed under a United States Government license
described on the COPYRIGHT_UniversityOfChicago file included as part
of this distribution.
**********************************************************************/
#ifndef INCasTrapWriteh
#define INCasTrapWriteh
#include "shareLib.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct asTrapWriteMessage {
char *userid;
char *hostid;
void *serverSpecific;
void *userPvt;
} asTrapWriteMessage;
typedef void *asTrapWriteId;
typedef void(*asTrapWriteListener)(asTrapWriteMessage *pmessage,int after);
epicsShareFunc asTrapWriteId epicsShareAPI asTrapWriteRegisterListener(
asTrapWriteListener func);
epicsShareFunc void epicsShareAPI asTrapWriteUnregisterListener(
asTrapWriteId id);
/*
* asTrapWriteListener is called before and after the write is performed.
* The listener can set userPvt on the before call and retrieve it after
* after = (0,1) (before,after) the put.
*
* Each asTrapWriteMessage can change or may be deleted after
* the user's asTrapWriteListener returns
*
* asTrapWriteListener delays the associated server thread so it must not
* do anything that causes to to block.
*/
#ifdef __cplusplus
}
#endif
#endif /*INCasTrapWriteh*/

View File

@@ -651,6 +651,7 @@ struct client *client
struct channel_in_use *pciu;
int v41;
long status;
void *asWritePvt;
pciu = MPTOPCIU(mp);
if(!pciu){
@@ -699,11 +700,14 @@ struct client *client
mp->m_count);
#endif
asWritePvt = asTrapWriteBefore(pciu->asClientPVT,
pciu->client->pUserName,pciu->client->pHostName,(void *)&pciu->addr);
status = db_put_field(
&pciu->addr,
mp->m_dataType,
mp + 1,
mp->m_count);
asTrapWriteAfter(asWritePvt);
if (status < 0) {
SEND_LOCK(client);
send_err(