.TITLE BYEBYENODE ; ; This is a quick hack to force a remote system out of the cluster. It can ; be used when a remote system hangs for example at high IPL (bewteen 3 ; and 6), or when the SMIserver does not respond. ; ; It uses an internal routine in the connection manager. There is one ; problem with this approach, and that is that this routine (CNX$DISC_REMOVE) ; is not available in any symboltable which we can include in the link. ; So what we do is use MATCHC to find the sequence of instructions around ; the place where we expect the code, and issue an error if we can't find it. ; If we got the address, we JSB to it and let that routine do the dirty work. ; The net result will be that the remote node will CLUEXIT. ; ; This is strictly a HACK, and as such it may fail at any time. Use at ; your own risk. (I included a check to prevent removal of the node from ; which this program runs, although it was fun to get a system in a state ; in which the only clusternode was removed from the cluster and in longbreak, ; without quorum....). It was tested on VMS V5.5 thru T6.2-FT1. ; ; Author: Jur van der Burg ; UTRTSC::VDBURG ; ; .library 'sys$library:lib.mlb' .link 'sys$system:sys.stb'/selective_search ; $clubdef $sbdef $ssdef ; lckarr: .long lockbeg ; Point to area to lock in memory .long lockend ; tbl: ; Start of the interesting instructions ; ; This is copied from CNXMAN.LIS ; .enabl lsb cnx$disc_bugcheck: movzwl #^x8104,r0 brb 20$ cnx$disc_incluver: movzwl #^x8106,r0 brb 20$ cnx$disc_remove: 10$: movzwl #^x800a,r0 20$: .dsabl lsb tblend=. tbllen=tblend-tbl ; lockbeg=. ; indsc: .long 80 .long inbuf inbuf: .blkb 80 reslen: .word 0 prompt: .ascid /Enter node name: / ; .entry start,0 ; pushal reslen ; Resultant length pushaq prompt ; Prompt pushaq indsc ; Input line descriptor calls #3,g^lib$get_foreign ; Get nodename blbc r0,30$ ; Exit on error movzwl #ss$_nosuchnode,r0 ; Assume such node movw reslen,indsc ; Copy resultant length beql 30$ ; Nothing there... cmpw reslen,#sb$s_nodename ; Check against maximum size bgtr 30$ ; Exit if more pushaq indsc ; Pointer to nodename pushaq indsc calls #2,g^str$upcase ; Make sure it's upper case pushaq lckarr ; Address of lock array $lkwset_s inadr=lckarr ; Lock pages blbc r0,30$ ; Exit on error $cmkrnl_s routin=work ; Do the dirty work 30$: ret ; ; Kernel mode routine to do the dirty work ; .entry work,^m ; ; The code we are looking for is around CLUSTRLOA+^X700 ; addl3 #^x700,g^clu$gl_loa_addr,r2 matchc #tbllen,tbl,#256,(r2) ; Try to locate the code beql 10$ ; If EQ it's there, R3 points to the end ; ; If NE, not found. Code has probably changed. ; movzwl #ss$_bugcheck,r0 brw 30$ ; 10$: subl2 #tblend-cnx$disc_remove,r3 ; This points us to CNX$DISC_REMOVE movl r3,r7 ; Save for later movab indsc,r2 ; Point to nodename descriptor lock scs ; Synch with SCS bsbw nodename_to_csb ; Get CSB blbc r0,20$ ; Not there jsb (r7) ; Call CNX$DISC_REMOVE, ; it does not return status movzwl #ss$_normal,r0 ; Okay 20$: unlock scs ; Release lock 30$: ret ; nodename_to_csb: movl g^clu$gl_club,r6 ; Point to CLUB movl club$l_local_csb(r6),r6 ; Get our own CSB movaq g^scs$gq_config,r3 ; Get cluster listhead movl r3,r0 ; Save start address 10$: movl (r3),r3 ; Next CSB cmpl r3,r0 ; Back at the beginning? beql 20$ ; Yes, quit pushr #^m movzwl (r2),r0 ; Get length from input descriptor cmpb r0,sb$t_nodename(r3) ; Lenght match? bneq 15$ ; No, next one please cmpc3 r0,@4(r2),sb$t_nodename+1(r3) ; Nodename match? 15$: popr #^m bneq 10$ ; No match movl sb$l_csb(r3),r5 ; Get CSB beql 40$ ; Not there anymore cmpl r5,r6 ; Is it our own? beql 30$ ; Yes, don't allow that movzwl #ss$_normal,r0 ; Okay rsb 20$: movzwl #ss$_nosuchnode,r0 rsb 30$: movzwl #ss$_ivaddr,r0 rsb 40$: movzwl #ss$_nodeleave,r0 rsb lockend=. .end start