	.TITLE	JTED ; enable/disable JTdriver intercepts
	.IDENT	'V001'
; Copyright (c) 1994, 1996 Glenn C. Everhart. All Rights Reserved.
;
; FACILITY:
; Sets or resets JTdriver intercept via pcb mods
; entry EXEMPT exempts from Safety
; entry UNEXEMPT undoes the exemption
; 
;
; Note: define VMS$V5 to build for Version 5.x of VMS.
VMS$V5=1
;
; 
; AUTHOR:
; 
; G. EVERHART
;
; 04-Aug-1989	D. HITTNER	Cleaned up definitions, added messages
; 29-Aug-1989   G. Everhart	Added more flexible device geometry selection
; 01-Dec-1993	G. Everhart	Build JTdriver misc. daemon
;--
	.PAGE
	.SBTTL	EXTERNAL AND LOCAL DEFINITIONS

	.LIBRARY /SYS$SHARE:LIB/
; 
; EXTERNAL SYMBOLS
; 

	$dyndef
	$ADPDEF				;DEFINE ADAPTER CONTROL BLOCK
	$ATRDEF
	$CRBDEF				;DEFINE CHANNEL REQUEST BLOCK
	$DCDEF				;DEFINE DEVICE CLASS
	$DDBDEF				;DEFINE DEVICE DATA BLOCK
	$ddtdef				;define driver dispatch tbl
	$DEVDEF				;DEFINE DEVICE CHARACTERISTICS
	$DPTDEF				;DEFINE DRIVER PROLOGUE TABLE
	$DVIDEF				;Symbols for $GETDVI service.
	$EMBDEF				;DEFINE ERROR MESSAGE BUFFER
	$FABDEF
	$FATDEF
	$pcbdef
	.iif ndf, PCB$M_NOUNSHELVE, PCB$M_NOUNSHELVE=^x80000
	.iif ndf, PCB$M_SHELVING_RESERVED,PCB$M_SHELVING_RESERVED=^x100000
	.iif ndf, PCB$V_NOUNSHELVE,PCB$V_NOUNSHELVE=19
	.iif ndf, PCB$V_SHELVING_RESERVED,PCB$V_SHELVING_RESERVED=20
	$acbdef
	$ccbdef
	$FIBDEF				;Symbols for file information block.
	$IDBDEF				;DEFINE INTERRUPT DATA BLOCK
	$IODEF				;DEFINE I/O FUNCTION CODES
	$IRPDEF				;DEFINE I/O REQUEST PACKET
	$NAMDEF
	$PRDEF				;DEFINE PROCESSOR REGISTERS
	$RMSDEF
	$SBDEF
	$SCSDEF
	$SSDEF				;DEFINE SYSTEM STATUS CODES
	$STSDEF				;Symbols for returned status.
	$TPADEF				;Symbols for LIB$TPARSE calls.
	$UCBDEF				;DEFINE UNIT CONTROL BLOCK
	$VECDEF				;DEFINE INTERRUPT VECTOR BLOCK
	$XABDEF

; 
; UCB OFFSETS WHICH FOLLOW THE STANDARD UCB FIELDS
; DEFINE THESE SO WE KNOW WHERE IN THE UCB TO ACCESS. WE MUST
; SET THE ONLINE BIT OR CLEAR IT, AND ALSO SET
; UCB$HUCB (HOST UCB ADDRESS), UCB$HFSZ (HOST FILE SIZE),
; AND UCB$HLBN (HOST LOGICAL BLOCK NUMBER OF FILE START)
;

	$DEFINI	UCB			;START OF UCB DEFINITIONS
;.=UCB$W_BCR+2				;BEGIN DEFINITIONS AT END OF UCB
.=UCB$K_LCL_DISK_LENGTH	;v4 def end of ucb
; USE THESE FIELDS TO HOLD OUR LOCAL DATA FOR VIRT DISK.
; Add our stuff at the end to ensure we don't mess some fields up that some
; areas of VMS may want.
; Leave thisfield first so we can know all diskswill have it at the
; same offset.
$def	ucb$l_oldfdt	.blkl	1	;fdt tbl of prior fdt chain
;
;
$def	ucb$l_hucbs	.blkl	1	;host ucb table
;
; Add other fields here if desired.
;
$def	ucb$l_exdmn	.blkl	1	;extend dmn pid
$def	ucb$l_exmbx	.blkl	1	;extend dmn mbx ucb
$def	ucb$l_deldmn	.blkl	1	;delete daemon pid
$def	ucb$l_delmbx	.blkl	1	;delete dmn mailbox ucb
;
;
$def	ucb$l_ctlflgs	.blkl	1		;flags to control modes
;
;
$def	ucb$l_prcvec	.blkl	1		;process local data tbl
$def	ucb$l_daemon	.blkl	1		;daemon pid for open daemon
$def	ucb$l_mbxucb	.blkl	1		;mailbox for input to daemon
$def	ucb$l_keycry	.blkl	2		;ucb resident "key" for ACEs
						;use as part of authenticator
						;for security-relevant fcns.
		;auth=f(file id, key, priv-info), match ace and computed
		;auth tag.
$def	ucb$l_cbtctr	.blkl	1		;how many extents
$def	ucb$l_cbtini	.blkl	1		;init for counter
; preceding 2 fields allow specifying of contig-best-try extents
; on every Nth extend, not every one. This should still help keep
; file extensions from preferentially picking up chaff
$def	ucb$JTcontfil	.blkb	80
$def	ucb$l_asten	.blkl	1		;ast enable mask store
;
$DEF	ucb$l_minxt	.blkl	1		;min. extent
$def	ucb$l_maxxt	.blkl	1		;max extent
$def	ucb$l_frac	.blkl	1		;fraction to extend by
$def	ucb$l_slop	.blkl	1		;slop blocks to leave free
; DDT intercept fields
; following must be contiguous.
$def    ucb$s_ppdbgn            ;add any more prepended stuff after this
$def    ucb$l_uniqid    .blkl   1       ;driver-unique ID, gets filled in
                                        ; by DPT address for easy following
                                        ; by SDA
$def    ucb$l_intcddt   .blkl   1       ; Our interceptor's DDT address if
                                        ; we are intercepted
$def    ucb$l_prevddt   .blkl   1       ; previous DDT address
$def    ucb$l_icsign    .blkl   1       ; unique pattern that identifies
                                        ; this as a DDT intercept block
; NOTE: Jon Pinkley suggests that the DDT size should be encoded in part of this
; unique ID so that incompatible future versions will be guarded against.
$DEF    UCB$L_ICPFGS    .BLKL   2       ; Flags. Reserve 2 longs so we need
                                        ; not mess with this later.
        $VIELD UCB,0,<-
                <FI8OK,,M>,-            ; 1 if this intercept and all
                        >               ; below understand finipl8.
$def    ucb$l_ufil1     .blkl   8       ; for others' intercepts if needed
$def    ucb$s_ppdend
$def    ucb$a_vicddt    .blkb   ddt$k_length
                                        ; space for victim's DDT
			.blkl	4	;safety
$def	ucb$l_backlk	.blkl	1	;backlink to victim ucb
; Make the "unique magic number" depend on the DDT length, and on the
; length of the prepended material. If anything new is added, be sure that
; this magic number value changes.
magic=^xF0070000 + ddt$k_length + <256*<ucb$s_ppdend-ucb$s_ppdbgn>>
p.magic=^xF0070000 + ddt$k_length + <256*<ucb$s_ppdend-ucb$s_ppdbgn>>
	.iif	ndf,f.nums,f.nums=16
ucb$l_fnums:	.blkw	f.nums	;store for file numbers to inspect whether
				;an ACE is there or not.
$DEF	UCB$L_JT_HOST_DESCR	.BLKL	2	;host dvc desc.
;
; Set FDT table start mask for each unit by keeping it here.
; We need just enough to get back to user's FDTs.
$def	ucb$l_fdtlgl	.blkl	2	;legal fcn msks
$def	ucb$l_fdtbuf	.blkl	2	;buffered fcn msks
$def	ucb$l_fdtmfy	.blkl	3	;modify fcn
$def	ucb$l_fdtbak	.blkl	3	;"go back" fcn
$def	ucb$l_vict	.blkl	1	;victim ucb, for unmung check
$def	ucb$l_mungd	.blkl	1
$def	ucb$l_exempt	.blkl	4
$DEF	UCB$K_JT_LEN	.BLKW	1	;LENGTH OF UCB
;UCB$K_JT_LEN=.				;LENGTH OF UCB
	$DEFEND	UCB			;END OF UCB DEFINITONS

; TO SET ONLINE:
;	BISW	#UCB$M_ONLINE,UCB$W_STS(R5)  ;SET UCB STATUS ONLINE

; Macro to check return status of system calls.
;
	.MACRO	ON_ERR	THERE,?HERE
	BLBS	R0,HERE
	BRW	THERE
HERE:	.ENDM	ON_ERR
; Define LDT offsets here.
ldt$l_fwd	=	0		;forward link. (LDTs are singly linked)
ldt$l_ccb	=	4		;CCB address so we can check ID
ldt$l_accmd	=	8		;accmd from user FIB (tells how open)
ldt$l_wprv	=	12		;working privs
ldt$l_aprv	=	20		;auth privs
ldt$l_bprio	=	28		;process base priority
ldt$l_prcstr	=	32		;pointer to per-process delblk count block
ldt$l_synch	=	36		;address of "iosb" block used to
					;end process waits & deallocated at
					;end of those waits.
ldt$l_iosb	=	40		;iosb for internal $qio
ldt$l_jtucb	=	48		;pointer to jt: ucb
ldt$l_fresiz	=	52		;length of LDT left since we will chop
					;off unused parts of ACE after we read
					;it to regain pool
; Keep chnucb in "permanent" part of LDT since it hangs around till close
; if we do a softlink. It will be zero unless there is a softlink so
; it acts as a flag to restore the channel, too.
ldt$l_chnucb	=	56		;original channel UCB address
ldt$l_softf	=	60		;flag nonzero if doing softlink
ldt$l_ace	=	64		;start of our ACE, up to 256 bytes long
; chop off what's below here, as we need it no more after the file is open.
ldt$l_regs	=	320		;register save, r0 to r15
ldt$l_flgs	=	376		;slop storage for flags
ldt$l_parm	=	380		;storage for up to 6 params (6 longs)
ldt$l_fib	=	404		;FIB we use for OUR I/O
; 72 bytes max for our FIB
ldt$l_acl	=	476		;storage for ACL read-in; 512 bytes
ldt$l_itmlst	=	988		;item list to read the ACL all in if
					;we can.
ldt$l_aclsiz	=	1020		;size of the ACL on the file
ldt$l_rtnsts	=	1024		;status back from daemon
ldt$l_myfid	=	1032		;file id from read-acl call
ldt$l_mydid	=	1040		;dir id in user's fib
ldt$l_psl	=	1048		;psl of original i/o
ldt$l_fnd	=	1052		;filename desc of orig i/o (p2 arg)
					;2 longs
ldt$l_fndd	=	1060		;data area for filename (256 bytes)
ldt$l_size	=       1324
ldt$k_clrsiz	=	1320		;allocate a little slop.

; ACE format:
;ace:	.byte	length
;	.byte	type = ace$c_info ;application ACE
;	.word	flags		;stuff like hidden, protected...
;	.long	info-flags	;use 1 bit to mean call the daemon
;	.ascii	/GCEV/		;my identifier
;	.blkb	data		;up to 244 bytes of data.

; data is a variable length list of stuff.
; Codes are as follows:
; 00 - nothing. Terminates list.
; 01 - starts "inspectme" record. Nothing more. We send FID from the LDT
;		in this case. This makes these real fast to forge.
; 02 - "moveme" record. Again we send FID from LDT and need nothing more.
;		We use info from the daemon to find the actual file based
;		on the file ID here.
; 03 - "bprio" record. Format:
;	03, prio, <long auth info>	;total 6 bytes
; 04 - "priv" record. Format:
;	04, <priv quadword> <auth quadword>	;total 17 bytes
; 05 - "ident" record, format:
;	05, <ident quadword> <auth quadword>	;total 17 bytes
; 06 - "softlink" record, format:
;	06, len, flgs, <file id to link to> <devicename> ;variable len
; flags for softlinks:
;	0 = normal
;	1 = softlink only on read, act like moveme record if r/w open
;	2 = directory file softlink, pass to daemon for special
;		handling so we can pull the dir in.
; more flags later as I think of them.
; more types as needed too.

;
;
;
	.PSECT	ADVDD_DATA,RD,WRT,NOEXE,LONG
;
	.ALIGN LONG

lpct:	.long	0	;scratch

dvl:	.long	0
IOSTATUS: .BLKQ 1
BUFG:	.long	1		;bash flag
; DESCRIPTOR FOR NODE$FWAN: DEVICE NAME
	.ALIGN LONG
deafg:	.long	0
allflg:	.long	0
;
;
	.macro	beqlw	lbl,?lbl2
	bneq	lbl2
	brw	lbl
lbl2:
	.endm
	.macro	bneqw	lbl,?lbl2
	beql	lbl2
	brw	lbl
lbl2:
	.endm
	.macro	bgtrw	lbl,?lbl2
	bleq	lbl2
	brw	lbl
lbl2:
	.endm
	.macro	bleqw	lbl,?lbl2
	bgtr	lbl2
	brw	lbl
lbl2:
	.endm
	.macro	bgeqw	lbl,?lbl2
	blss	lbl2
	brw	lbl
lbl2:
	.endm
; allocate does not zero its result area.
	.macro	zapz	addr,size
	pushr	#^m<r0,r1,r2,r3,r4,r5>	;save regs from movc5
	movc5	#0,addr,#0,size,addr
	popr	#^m<r0,r1,r2,r3,r4,r5>	;save regs from movc5
	.endm
	.if	ndf,evax
	.macro .jsb_entry
; entry
	.endm
	.endc
	.PSECT	ADVDD_CODE,RD,NOWRT,EXE,LONG
	.ENTRY	EXEMPT,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
	clrl	deafg
	clrl	allflg
	$CMKRNL_S -
		ROUTIN=Blatucb
	CMPL	R0,#SS$_NORMAL				;Any errors?
300$:
	RET
	.ENTRY	UNEXEMPT,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
	clrl	deafg
	incl	deafg
	clrl	allflg
	$CMKRNL_S -
		ROUTIN=Blatucb
	CMPL	R0,#SS$_NORMAL				;Any errors?
300$:
	RET
	.ENTRY	Blatucb,^M<R2,R3,R4,R5,R6,R7,R8,r9,r10,r11>
; TAKEN LOOSELY FROM ZERO.MAR
	.if	ndf,vms$v5
	MOVL	G^SCH$GL_CURPCB,R4	;;; NEED OUR PCB
	.iff
	MOVL	G^CTL$GL_PCB,R4		;;; NEED OUR PCB (VMS V5)
	.endc
	JSB	G^SCH$IOLOCKW		;;; LOCK I/O DATABASE
	movl	g^ctl$gl_pcb,r4		;get our pcb, for safety
	tstl	deafg		;deassigning ourselves?
	beql	1178$		;if not branch
	bicl	#<pcb$m_nounshelve!pcb$m_shelving_reserved>,pcb$l_sts2(r4)
1179$:
	movl	#1,r0
	brw	bsh_xit
1178$:
; SET "exempt" status
; if "all" flag was set set both shelving bits, else set reserved one only
	bisl	#<pcb$m_nounshelve!pcb$m_shelving_reserved>,pcb$l_sts2(r4)
	MOVL	#SS$_NORMAL,R0
BSH_XIT:
	movl	#1,r0
	JSB	G^SCH$IOUNLOCK		;;; UNLOCK I/O DATABASE (DROP IPL)
	movl	#1,r0
	RET	;;; BACK TO USER MODE NOW
	.END
