implement asTrapWrite
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 '}'
|
||||
;
|
||||
|
||||
@@ -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
166
src/as/asTrapWrite.c
Normal 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
55
src/as/asTrapWrite.h
Normal 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*/
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user