Not for humans but for search engine – BPX

BPXF024I

You get this message if the syslogd program is not running.

BPXP015I HFS PROGRAM /usr/lpp/zosmf/lib/libIzuCommandJni.so IS NOT MARKED PROGRAM CONTROLLED.   BPXP014I ENVIRONMENT MUST BE CONTROLLED FOR DAEMON (BPX.DAEMON) PROCESSING.

Use the command extattr /usr/lpp/zosmf/lib/libIzuCommandJni.so to check the Program Controlled attribute is set. Use the extattr +p…. to set it if required.

I had the wrong SAF_PREFIX(‘IZUDFLT‘) in USER.Z24A.PARMLIB(IZUPRMCP).   IZUDFLT was correct.

I had other problems like invalid password when I logged onto the web browser.

Fix the problem and regenerate.

BPXO042I with D OMVS,PFS

I was expecing D OMVS,PFS or D OMVS,P to give me BPXO068I and a list of Physical File Systems.

it gives BPXO042I when the command failed.

This was due to having an HFS definition in my z/OS 3.1 system. HFS is not supported on 3.1 . I removed the definition and it worked.

BPX1SOC TTLS_INIT_CONNECTION rv -1 rc ECONNRESET(1121) rs 2007593789 (0x77a9733d) 77a9733d EDC8121I Connection reset

The bpxmtext 77a9733d gives

TCPIP
JrTtlsHandshakeFailed: AT-TLS was unable to successfully negotiate a secure
TCP connection with the remote end.
Action: Review message EZD1286I for more information about the error.

On syslog was

EZD1287I TTLS Error RC: 403 Initial Handshake

Where 403 is The required certificate was not received from the communication partner.

The Wireshark output had a Certificate flow from the client to the server. This had no certificate in it.

The reason for this was,

  • the client had an RSA certificate
  • the Signature Hash Algorithms sent from the server did not include RSA.

The client was thus unable to send a certificate matching the SHA.

If I specified RSA only signature pairs, I could only use an RSA certificate. An Elliptic Curve certificate (ECDSA) had the same message and error code.

BPX1BND rv -1 rc EADDRINUSE(1115) rs 1951167047 (0x744c7247) EDC8115I Address already in use.

Because a program may not know that the “FIN” (end of conversation) has got to the other end, a socket enters a TIMEWAIT state. The IBM documentation says

If the server cannot wait for one to four minutes, you can use the setsockopt() call in the server to specify SO_REUSEADDR before it issues the bind() call. In that case, the server will be able to bind its socket to the same port number it was using before, even if the TIMEWAIT period has not elapsed. However, the TCP protocol layer still prevents it from establishing a connection to the same partner socket address. As clients normally initiate connections and clients use ephemeral port numbers, the likelihood of this is low.

BPX1SND rv -1 rc EOPNOTSUPP(1112) rs 1977578120 (0x75df7288) EDC8112I Operation not supported on socket.

I got this trying to issue bpx1snd() when there was data in the receive buffer. I used bpx1rcv to read the data, and the problem went away.

I peeked at the data before getting it, so I knew the length of the data to get, and so avoided waiting for data.

char buf[4000];
int lbuff = sizeof(buf);
int alet = 0;
int flags = MSG_PEEK;
BPX1RCV( &sd, // socket desciptor
&lbuff,
&buf,
&alet,
&flags,
&rv, // -1 or number of bytes
&rc,
&rs);

printf("BPX1RCV Peek bytes %d data... n",rv );

lbuff = rv; // the number of bytes in the buffer
flags = 0 ;
BPX1RCV( &sd, // socket descriptor
&lbuff,
&buf,
&alet,
&flags,
&rv, // -1 or number of bytes
&rc,
&rs);

printf("BPX1RCV bytes %d data... n",rv );

BPXF135E RETURN CODE 00000079, REASON CODE 055B005C

I got this using the command

MOUNT FILESYSTEM(‘COLIN.ZFS2’) TYPE(ZFS) MOUNTPOINT(‘/u/ibmuser/temp’ )

code 79 is invalid. The 005b005c means already in use. Either

  • COLIN.ZFS2 is already mounted
  • there is something else mounted on /u/ibmuser/temp

You can use the D OMVS,F command to display the file system and where they are mounted.

BPXF135E RETURN CODE 00000081, REASON CODE 053B006C

May because the file system is mounted READ and it needs to be RDWR.

BPXMTEXT 053B006C -> JRFileNotThere: The requested file does not exist.

Problem 1

I had MOUNTPOINT(‘/u/ibmuser/test’ ) (which did not exit) not the correct MOUNTPOINT(‘/u/ibmuser/temp’ )

Problem 2

I was trying to mount it at /my. I had to go into Unix and issue mkdir /my only then could I mount the file system.

BPXF137E RETURN CODE 00000079, REASON CODE 0588002E.

THE UNMOUNT FAILED FOR FILE SYSTEM …

002E is JRFilesysNotThere. Check the file system is mounted

BPXF137E RETURN CODE 00000072, REASON CODE 058800AA

BPXF137E RETURN CODE 00000072 (the resource is busy) , REASON CODE 058800AA JRFsParentFs The file system has file systems mounted on it.

I was trying to unmount a ZFS file systemm, and got the above messages. It means you cannot unmount it, because you have other file systems attached to it. On the z/OS console it had

BPXF271I FILE SYSTEM ZFS.USERS                             
FAILED TO UNMOUNT BECAUSE IT CONTAINS MOUNTPOINT DIRECTORIES FOR
ONE OR MORE OTHER FILE SYSTEMS WHICH MUST BE UNMOUNTED FIRST,
INCLUDING FILE SYSTEM COLIN.ZFS2

I used

unmount filesystem('COLIN.ZFS2') Immediate

and got message on the console

IOEZ00048I Detaching aggregate COLIN.ZFS2

BPXF002I FILE SYSTEM … NOT MOUNTED. RETURN CODE = 0000009D, REASON CODE = 11B900B7

With a Physical File System (PFS) there was a bad parameter in the OSI_THREAD block. The value of threadParm.ot_modname ( program to execute) did not exist.

Where’s my dump?

I had been working on a bug and getting out a System Dump (SDUMP). Then, after a fix, I stopped getting dumps, and just got a message with a return code indicating an abend had occurred. So where was my dump?

z/OS has Dump Elimination and Analysis DAE. This keeps a note of the dumps being taken, and can be configured to say “If you get the same abend many times, don’t bother taking a dump”. This stops you getting many identical dumps, and filling your disk storage.

In IPCS option 3 UTILITY – Perform utility functions, 5 DAE – Process DAE data, you can display the contents of the DAE information. On my system the data set is SYS1.DAE.

Command ===>                                                  Scroll ===> PAGE
Enter an Action Code next to an entry.
Enter / next to an entry to choose from a list of Action Codes.

Dataset: 'SYS1.DAE'
Dumps since last DAE Display: 0 Total Dumps suppressed: 214
Events since last DAE Display: 0 Suppression rate: 81%

A Last Last Total Date of Symptom String information:
C Date System Events Dump Abend Reason Module CSECT
_ 05/01/26 S0W1 7 04/28/26 S0EC6 055B0718 BPXINPVT BPXFSMNT
_ 05/01/26 S0W1 66 04/28/26 S00C4 00000004 BPXINPVT BPXVOTHD
_ 05/01/26 S0W1 10 04/28/26 S00C4 00000004 BPXINPVT BPXVOTHD
s 05/01/26 S0W1 53 04/28/26 S00C4 00000004 BPXINPVT BPXVOTHD

Selecting a record with S gave

                           Date      Time       System Name                    
Last (most recent) Event: 05/01/26 19:02:16 S0W1
Dump Taken: 04/28/26 18:44:59 S0W1

Symptoms used for Dump Suppression:
MVS RETAIN
Key Key Symptom Data Explanation
MOD/ RIDS/ BPXINPVT LOAD MODULE NAME
CSECT/ RIDS/ BPXVOTHD ASSEMBLY MODULE CSECT NAME
PIDS/ PIDS/ 5752SCPX1 PRODUCT/COMPONENT IDENTIFIER
AB/S AB/S 00C4 ABEND CODE-SYSTEM
REXN/ RIDS/ BPXMIPCE RECOVERY ROUTINE CSECT NAME
FI/ VALU/H 7542A0704742A0708BB917 FAILING INSTRUCTION AREA
REGS/ REGS/ C07DC REG/PSW DIFFERENCE
HRC1/ PRCS/ 00000004 ABEND REASON CODE
SUB1/ VALU/C OPENMVS COMPONENT SUBFUNCTION

This information is called a Symptom String. It provides a very short summary of the problem. You can search the internet with this information, to see if the problem has been found before.

For me, this symptom string, there has been 66 occurrences of it in my system (see the first display).

DAE can be configured to say if you get the same symptom string, do not take a dump, as is is most probably the same problem. This means your disks are not fully of identical system dumps.

Similar dumps

In

Command ===>                                                  Scroll ===> PAGE
Enter an Action Code next to an entry.
Enter / next to an entry to choose from a list of Action Codes.

Dataset: 'SYS1.DAE'
Dumps since last DAE Display: 0 Total Dumps suppressed: 214
Events since last DAE Display: 0 Suppression rate: 81%

A Last Last Total Date of Symptom String information:
C Date System Events Dump Abend Reason Module CSECT
_ 05/01/26 S0W1 7 04/28/26 S0EC6 055B0718 BPXINPVT BPXFSMNT
_ 05/01/26 S0W1 66 04/28/26 S00C4 00000004 BPXINPVT BPXVOTHD
_ 05/01/26 S0W1 10 04/28/26 S00C4 00000004 BPXINPVT BPXVOTHD
_ 05/01/26 S0W1 53 04/28/26 S00C4 00000004 BPXINPVT BPXVOTHD

There is a record for S0EC6 055B0718, and several records for S00C4 00000004. The detailed symptom string for these S00C4 abends are similar but different. The abend occurred at a different place, so the symptom string is slightly different.

Configuring DAE

You configure DAE through parmlib members ADYSETXX

On my system member ADYSET01 stops DAE, so I get a dump for every abend.

In member ADYSET00 I have

 SVCDUMP(MATCH,SUPPRESSALL,UPDATE,NOTIFY(3,30)),   

Where

  • MATCH: Specifies that DAE is to compare the symptoms from the current memory dump to those that have already been recorded in the DAE data set. (Coding MATCH does not indicate that DAE suppresses duplicate memory dumps or update the DAE data set.)
  • SUPPRESSALL: Specifies that duplicate memory dumps are to be suppressed when all criteria for matching and suppressing memory dumps are met except for the VRADAE key.
  • Update: Specifies that the DAE data set is to be updated with the results of matching.
  • Notify: This sends an internal signal to system applications listening, that a dump has occurred. The default is three memory dumps in 30 minutes for a particular symptom string.

How am I meant to know what’s happened?

As well as DAE processing, a record is written to EREP/LOGREC. EREP is a repository for hardware errors, and software errors.

For example, formatting the dataset, gave me

TYPE:  SOFTWARE RECORD      REPORT:  SOFTWARE EDIT REPORT           DAY.YEAR      
(PROGRAM INTERRUPT) REPORT DATE: 121.26
...
SEARCH ARGUMENT ABSTRACT
PIDS/5752SCPX1 RIDS/BPXINPVT#L RIDS/BPXVOTHD AB/S00C4 PRCS/00000004 REGS/C082C
RIDS/BPXMIPCE#R

SYMPTOM DESCRIPTION
------- -----------
PIDS/5752SCPX1 PROGRAM ID: 5752SCPX1
RIDS/BPXINPVT#L LOAD MODULE NAME: BPXINPVT
RIDS/BPXVOTHD CSECT NAME: BPXVOTHD
AB/S00C4 SYSTEM ABEND CODE: 00C4
PRCS/00000004 ABEND REASON CODE: 00000004
REGS/C082C REGISTER/PSW DIFFERENCE FOR R0C:-082C
RIDS/BPXMIPCE#R RECOVERY ROUTINE CSECT NAME: BPXMIPCE
...
TIME OF ERROR INFORMATION
PSW: 07047001 80000000 00000000 20E1F2F4
INSTRUCTION LENGTH: 04 INTERRUPT CODE: 0004
FAILING INSTRUCTION TEXT: 00175045 00005049 01B0E368
TRANSLATION EXCEPTION ADDRESS: 00000000_01B6A404
BREAKING EVENT ADDRESS: 00000000_20E1F280

AR/GR 0-1 FFF00001/00000000_00000097 00000000/00000051_01B6AC90
AR/GR 2-3 00000001/00000000_0239A000 00000000/00000051_02FCFA00
...

HOME ASID: 0010 PRIMARY ASID: 0010 SECONDARY ASID: 0056
PKM: 8040 AX: 0001 EAX: 0000

RECOVERY ROUTINE ACTION
THE RECOVERY ROUTINE RETRIED TO ADDRESS 20E1F7DA.
THE REQUESTED SVC DUMP WAS NOT TAKEN. THE DUMP WAS SUPPRESSED BY DAE.
NO LOCKS WERE REQUESTED TO BE FREED.
THE SDWA WAS REQUESTED TO BE FREED BEFORE RETRY.

The information is a superset of the information in DAE. You get the registers at the point of failure, and what recovery action was taken. (Programs can ignore some abends, or pass the decision to a program higher up the stack).

In this case I can see there was no dump taken because of DAE.

The information in the logrec record was enough for me to debug the program. I did not need an SDUMP.

Processing LOGREC

Logrec is a z/OS dataset which records information about events, such as hardware problems, and software abends. Information is written to the dataset even though the information may have been suppressed elsewhere.

JCL to print it

//IBMPEREP JOB (ACCT),'PRINT LOGREC',CLASS=A,MSGCLASS=H 
//STEP EXEC PGM=IFCEREP1,PARM='CARD'
//SERLOG DD DISP=SHR,DSN=SYS1.S0W1.LOGREC
//DIRECTWK DD UNIT=SYSDA,SPACE=(CYL,10,,CONTIG)
//EREPPT DD SYSOUT=A,DCB=BLKSIZE=133
//TOURIST DD SYSOUT=A,DCB=BLKSIZE=133
//ZERLOG DD SYSOUT=A,DCB=BLKSIZE=133
//SYSIN DD *
PRINT=PS
ACC=N
ZERO=N
ENDPARM
//

To print and clear specify ZERO=Y.

The command syntax is given here.

Example output

IPL record

IPL RECORD EDIT AND PRINTING SECTION                                                        
DAY YEAR HH MM SS TH
DATE -122 26 TIME -06 05 01 52
MODEL - 1090 CPU SERIAL NO. - 011238
MVS/ESA V7 R3

IPL REASON CODE - DF DEFAULT -U-
SUBSYSTEM ID - 00 SUBSYSTEM NAME - NULL
HIGHEST STORAGE ADDRESS 7FFFFFFF

LAST ACTIVITY INFORMATION :
DAY YEAR HH MM SS TH
DATE -121 26 TIME -19 14 13 68
END OF IPL RECORD

3270 termination

DEVICE NUMBER:  000703                DAY YEAR       JOB IDENTITY: VTAM                     

DEVICE TYPE: 3277
MODEL: 1090 HH MM SS.TH
ERROR PATH: EF-0703 CPU ID: 111238 TIME: 19 16 26.42
RECORD IS: TEMPORARY
MODE IS: 370XA

---UNIT STATUS---- SUB-CHANNEL STATUS
....

DEVICE DEPENDENT DATA

TYPE OF RECORD: CLOSEDOWN (X'20')

TERMINAL NAME: LCL703 SIO CNTR: 00000003 TEMP. ERRORS: 00

Software abend

See Where’s my dump?

How often should I clear it?

Periodically you should archive the data, so you can later do trend analysis, such as which disks are having more I/O problems than usual.

When logrec fills up, your automation can trigger a job to copy the logrec dataset, and clear it.

Getting the z/OS standard image to work.

I had a lot of challenges getting the zD&T replacement (the standard image) to work. I do not know if this is the same image that every one else gets, or if mine was “a special” one. Some things did not work, somethings were not best practice.

I also wanted to use the data from my previous systems, my PDS, my Unix file systems, my keyrings etc. I also wanted to future proof migrating to the next code drop from IBM.

Summary of actions

Below is a list of the things I did to get the system up and working as I expected it to look.

I’ve grouped them by area. In the main body of the document, they are in the approximate order of execution

Problems

Customising

Before you start using it

Missing download and setting the IBMUSER password

The files on the IBM Passport Advantage site are incomplete. The documentation tells you do download the ZDTDPY volume, edit it to set the password, and boot the system. This download was not on the download site.

I had an old z/OS system I could use and so could reset the password. See Help, I cannot logon to my z/OS system

It is not difficult to write a C program to prompt for a password on the z/OS console – and have the value not displayed. See How do I enter a password on the z/OS console for my program?

I needed to configure my laptop

The IP address of z/OS is 172.26.1.2. I configured my startup script to have

#  define route from my laptop to my server
sudo ip route add 10.1.1.0/24 via 10.1.0.3

# define route from my laptop to z/OS on the server
sudo ip route add 172.26.1.0/24 via 10.1.0.3

# connect to the server
ssh -X colin@10.1.0.3

The sample devmap is wrong, it does not provide 3270’s

The system would not IPL with a console, the output came out printer like.

I edited the devmap file:

  • add the 3270port 3270. Without this you do not get any 3270’s defined, and you get a line printer like console.
  • Change the processors to match what your server has. My dongle has support for 3 CPUs – but I can define 3-1 ZIIPs
  • Check the memory to match you configuration
  • I removed the IPL and put it in my shell script.

The top of my devmap is

[system]
processors 5 cp cp cp ziip ziip # number of processors
memory 10G
system_name VS01

3270port 3270 # port number for TN3270 connections

First IPL

The IPL parameters are configured to start up lots of subsystems I didn’t want to use I used

ipl DE27 parm DE28AU

Logon with userid IBMUSER and the password you configured.

Configure parmlib

The sys0.iplparm points to loadxx members. You need a load member with USER.PARMLIB in it (such as LOADAU)

  • Copy LOADAU to LOADCP
  • In LOADCP change SYSPARM to SYSPARM AU,CP
  • In user.parmlib create IEASYSCP (CP matching the CP above)
  • add your parameters, such as OMVS=(CP) for IP(V6) support

You can IPL with this

ipl DE27 parm DE28CP

If this fails to IPL, to back to parm DE28AU

Add userids

The userid IBMUSER is all powerful. I prefer using a less powerful userid.

I wanted to save my userids from the previous system. I wrote code makeRACF. With this you run a program on your old system, and specify a userid or dataset prefix. The program then generates the RACF commands to recreate the userid or resource.

Because the TSO configuration is different from the previous zD&T systems I had to configure the definitions

TSO (ACCTNUM ('ACCT001') - 
COMMAND ('ex ''colin.zlogon.clist''') -
PROC (PROC001 ) -
SIZE (2096128) -
MAXSIZE (2096128) -
USERDATA (0000) -
UNIT (3390))

I created some definitions to my userid COLIN access to resources on the new system

ALTUSER COLIN SPECIAL AUDITOR OPERATIONS                             
ALTUSER COLIN DFLTGRP(SYS1)
ALTUSER COLIN tso( ACCTNUM('ACCT001') -
CoMMAND('ISPF') PROC(PROC001 ) -
SIZE(2096128) MAXSIZE(2096128) USERDATA(0000) UNIT(SYSDA))
permit ACCT001 class(ACCTNUM) id(COLIN ) access(READ )
permit ACCT# class(ACCTNUM) id(COLIN ) access(READ )
permit JCL class(TSOAUTH)id(COLIN) access(REAd)
permit CONSOLE class(TSOAUTH)id(COLIN) access(REAd)
permit PROC001 class(TSOPROC)id(COLIN) access(REAd)
permit ISPFPROC class(TSOPROC)id(COLIN) access(REAd)
setropts raclist(TSOAUTH) refresh
setropts raclist(ACCTNUM) refresh
setropts raclist(TSOPROC) refresh
PERMIT *.** CLASS(JESSPOOL) ID(COLIN) ACCESS(ALTER)
SETR RACLIST(JESSPOOL) REFRESH

I created JCL for these definitions, so for system refreshes, I just rerun the jobs.

I did not use the UNIX facility to allocate a (random) UID. I specified the UID I had before.

On the ZFS with my files, I needed the uid of the file owner to be the same as my users uid. If z/OS allocated me a uid, I would not be able to access my files. I would then have to go through and change the owner of them.

I recreated userids COLIN and START1.

You need to see what groups the userids belonged to, and you may need to recreate the groups, or just us what are already defined.

Import user catalogs

I have user catalogs for all of my data sets. These catalogs need to be imported into the master catalog

//IBMUSERT JOB 1,MSGCLASS=H                                           
//S1 EXEC PGM=IDCAMS,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
IMPORT CONNECT -
OBJECTS -
(('A4USR1.ICFCAT' VOLUME(A4USR1) DEVICETYPE(3390) -
))
/*

How do you find out what user catalogs you have?

On the old system.

//IBMUSERT JOB 1,MSGCLASS=H                               
//S1 EXEC PGM=IDCAMS,REGION=0M
//SYSPRINT DD SYSOUT=*
//DD1 DD DISP=SHR,VOL=SER=D5SYS1,UNIT=3390
//SYSIN DD *
LISTCAT CATALOG(CATALOG.Z31B.MASTER) USERCATALOG ALL FILE(DD1)
/*

or

//IBMUSERT JOB 1,MSGCLASS=H                               
//S1 EXEC PGM=IDCAMS,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
LISTCAT USERCATALOG ALL
/*

The ALL Parameter also lists the Aliases using the user catalog.

Define aliases to map high level qualifier to a user catalog.

Once you have imported the catalogs you can define the data set aliases

//IBMUSERT JOB 1,MSGCLASS=H                                     
//S1 EXEC PGM=IDCAMS,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DEFINE ALIAS (NAME(BACKUP) RELATE('A4USR1.ICFCAT') )
DEFINE ALIAS (NAME(COLIN ) RELATE('A4USR1.ICFCAT') )
/*

What aliases do I have?

//IBMUSERT JOB 1,MSGCLASS=H                                         
//S1 EXEC PGM=IDCAMS,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
LISTCAT ALIAS
/*

Define user directories

For each file system, and each user, they need a directory defined. The standard image uses automount to create a ZFS for each entry in /u. If my RACF profile says my home directory is /u/colin, it will create a ZFS for this. If /u/colin already existed, it will not be used.

I created entries in /usr. If you try to make a directory, it may fail because /usr is mounted read only.

From userid IBMUSER to into Unix ( TSO OMVS)

  • mkdir /usr/colin
  • If this fails use
    • chmount -w /usr … do your work … chmount -r /usr
  • mkdir /usr/tmp
  • mkdir /usr/tmp/zowet
  • mkdir /usr/tmp/zowet/colin Userid COLIN has HOME= /usr/tmp/zowet/colin
  • You may need to change the ownership of the directory
    • chown -R colin:sys1 mkdir /usr/tmp/zowet/colin
  • If you need to…
    • chmount -r /usr

Mount the ZFS

Once I had imported the catalogs, and defined the aliases I could try to mount my ZFS

I created USER.PARMLIB(BPXPRMUS) and added

MOUNT FILESYSTEM('COLIN.ZFS.ZOWE.TEMP') TYPE(ZFS) 
MOUNTPOINT('/usr/tmp/zowet') MODE(RDWR)
PARM('AGGRGROW') AUTOMOVE

MOUNT FILESYSTEM('COLIN.ZOPEN.ZFS') TYPE(ZFS)
MOUNTPOINT('/usr/zopen') MODE(RDWR)
PARM('AGGRGROW') AUTOMOVE

The activate using the operator command

T OMVS=(US)

I was then able to logon to my newly created userid COLIN, and go into z/OS Unix.

Configure VTAM to give you greater than 80 *24 screen size

VTAM configuration

  • Edit SYS1.VTAMLST(EXLOCAL). You have to edit this because NET does not have USER.VTAMLST configured.
  • Create EXLOCALO from it (for backup)
  • change DLOGMOD to have value D4B32XX3,
  • create an entry for CUADDR=061,

Clean up

  • Edit SYS1.VTAMLST(ATCCON00). Remove IVPLCLI,IVPLCLT because the devices they reference do not exist.

If your changes to EXLOCAL do not work, use

V NET,ACT,ID=EXLOCALO

TCPIP

The provided TCPIP procedure creates certificates etc and does other work. It creates a new CA certificate, I need to export it, and sent it to my machines which connect in, and to all my keyrings.

I want to use the set up I have, so my TCPIP V6 Procedure is

USER.PROCLIB(TCPIP)

//TCPIP    PROC PARMS='CTRACE(CTIEZB00)' 
//TCPIP EXEC PGM=EZBTCPIP,PARM='&PARMS',REGION=0M,TIME=1440
//SYSPRINT DD SYSOUT=*
//SYSERR DD SYSOUT=*
//SYSERROR DD SYSOUT=*
//ERRORFIL DD SYSOUT=*
//SYSDEBUG DD SYSOUT=*
//PROFILE DD DISP=SHR,DSN=USER.TCPPARMS(PROFILE)
//SYSTCPD DD DISP=SHR,DSN=TCPIP.TCPPARMS(TCPDATA)

Support TCPIP V6

The TCPIP as shipped does not support IP V6. You need to create a BPXPRMxx member and activate it

You need a BPXPRMv6 member in user.parmlib

FILESYSTYPE TYPE(CINET) 
ENTRYPOINT(BPXTCINT)
SUBFILESYSTYPE NAME(TCPIP)
TYPE(CINET)
ENTRYPOINT(EZBPFINI)
DEFAULT
NETWORK DOMAINNAME(AF_INET6)
DOMAINNUMBER(19)
MAXSOCKETS(50000)
TYPE(CINET)

In USER.PARMLIB(IEASYSXX) use BPX=(V6).

In USER.TCPPARMS(PROFILE) I have

...
DATASETPREFIX TCPIP

TCPCONFIG TTLS
INCLUDE USER.TCPPARMS(IPV6)

...

and the IPV6 member has

IPCONFIG6 MULTIPATH

TCPIP Resolver

See Why is the wrong TCPIP Resolver proc being used?

Create USER.PROCLIB(RESOLVER)

//* TCPIP RESOLVER - COLINS 
//*
//RESOLVER PROC PARMS=CTRACE(CTIRES00)
//*
//EZBREINI EXEC PGM=EZBREINI,REGION=0M,TIME=1440,
// PARM=('&PARMS',
// 'ENVAR("RESOLVER_TRACE=/var/log/resolver"/')
//SETUP DD DISP=SHR,DSN=COLIN.TCPPARMS(GBLRESOL),FREE=CLOSE
//SYSTCPT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//*

Create COLIN.TCPPARMS(GBLRESOL) with

Copy

  DEFAULTTCPIPDATA('COLIN.TCPPARMS(GBLTDATA)') 
GLOBALTCPIPDATA('COLIN.TCPPARMS(RESOLVE)')
# GLOBALTCPIPDATA(/etc/resolv.conf)
;
# -----------------------------------------------------------------
# Default zPDT Linux Base to z/OS Tunnel (Stand-Alone)
# -----------------------------------------------------------------
;
# GLOBALIPNODES(/etc/hosts)
GLOBALIPNODES('COLIN.TCPPARMS(HOSTS)')
....

Change the operator console PFKeys (to add the shutdown command)

See How do I change the PFKeys on the console?

Copy SYS1.PARMLIB(PFKTAB00) to USER.PARMLIB

  • Change PF12 to be PFK(12) CMD(“%NETV SHUTSYS”) CON(Y)
  • Change any other keys you fancy.

Fix SMF

Message HSF0066W

I was getting

HSF0066W Required exit IEFU86 for SMF subsystem SYS not enabled. Some data may be missing in SDSF event log.

Copy SYS1.PARMLIB(SMFPRM00) to USER.PARMLIB(SMFPRM00) add IEFU86

SYS(EXITS(IEFACTRT,IEFUJI,IEFU83,IEFU84,IEFU85,IEFUJV,IEFU86)), 
SUBSYS(STC,EXITS(IEFU83,IEFU84,IEFU85,IEFU29,IEFU86),
INTERVAL(SMF,SYNC))

Message IEE391A

IEE391A SMF ENTER DUMP FOR DATA SET ON VOLSER OPEVS1 DSN=SYS1.VS01.MAN1

Create in USER.PROCLIUB(SMFCLEAR)

//SMFCLEAR PROC MAN='SYS1.VS01.MAN1' 
//*
//* CLEAR SMF DATASET -
//* SMF MAN DATASET DUMPED REQUIRED MESSAGE RECIEVED
//* OR ISSUE SWITCH, I SMF, THEN THAT FILE WILL BE CLEARED
//*
//*
//DUMP1 EXEC PGM=IFASMFDP,REGION=1M
//INDD1 DD DSN=&MAN,DISP=SHR
//DUMPOUT DD DUMMY
//SYSPRINT DD SYSOUT=D
//SYSIN DD *
INDD(INDD1,OPTIONS(CLEAR))

Then you can use either of

S SMFCLEAR
S SMFCLEAR,MAN='SYS1.VS01.MAN2'

SETSMF command not enabled

I could not issue

setsmf recording(logstream)
setsmf recording(dataset)

setsmf recording(logstream)

commands, to be able to change the SMF LOGSTREAM.

I created USER.PARMLIB(SMFPRM00) from SYS1.PARMLIB and added AUTHSETSMF – it defaults to NONE.

...
DEFAULTLSNAME(IFASMF.VS01.DATA)
AUTHSETSMF
NOPROMPT,
REC(PERM),
,,,

Configure SYSLOGD

Define the started task

//IBMUSERT JOB 1,MSGCLASS=H 
//S1 EXEC PGM=IKJEFT01,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *
RDEFINE STARTED SYSLOGD.* STDATA(USER(IBMUSER))
SETR RACLIST(STARTED) REFRESH

SYSLOGD is used by many Unix processes for recording errors and other information.

Create USER.PROCLIB(SYSLOGD)

//SYSLOGD PROC 
//* Licensed Materials - Property of IBM *
//* "Restricted Materials of IBM" *
//* 5650-ZOS *
//* Copyright IBM Corp. 1992, 2013 *
//* Read parms from /etc/syslog.conf
//CONFHFS EXEC PGM=SYSLOGD,REGION=4096K,TIME=NOLIMIT,
// PARM='ENVAR(''CEE_ENVFILE_S=DD:STDENV'')/-c -i '
//STDENV DD DISP=SHR,DSN=USER.PROCLIB(SYSLOGDD)
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
//SYSERR DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//CEEDUMP DD SYSOUT=*

Create USER.PROCLIB(SYSLOGDD)

I have

*.INETD*.*.*       /var/log/inetd.log 
auth.* /var/log/auth.log
mail.* /var/log//mail -F 640 -D 770
local1.err /var/log/local1.log
*.err /var/log/errors.log
# *.CPAGENT.*.* /var/log/CPAGENT.log
*.CPATTLS.*.* /var/log/CPATTLS
*.TTLS*.*.* /var/log/TTLS.log
*.Pagent.*.* /var/log/Pagent.log
*.TCPIP.*.debug /var/log/TCPIPdebug.log
*.TCPIP.*.warning /var/log/TCPIP.log
*.TCPIP.*.err /var/log/TCPIPerr.log
*.TCPIP.*.info /var/log/TCPIPinfo.log
*.SYSLOGD*.*.* /var/log/syslogd.log
*.TN3270*.*.* /var/log/tn3270.log
*.SSHD*.*.* /var/log/SSHD.log
*.FTPD*.*.* /var/log/FTPD.log
daemon.debug /var/log/SSHDdebug.log
*.TCPIP.*.none;
*.err /var/log/errors
*.CPAGENT.*.* /var/log/CPAGENT.log
*.TRMD1.*.info /var/log/TRMD1I.log
*.DMD.*.* /var/log/DMD.log

You can use this as a basis and change it as needed.

Configure SSHD

The SSHD procedure in SYS1.PROCLIB, invokes a shell script which then spawns the SSHD code with a name like SSHD.

I use

//SSHD    PROC 
//SSHD EXEC PGM=BPXBATCH,REGION=0M,TIME=NOLIMIT,
// PARM='PGM /usr/sbin/sshd -f /etc/ssh/sshd_config '
//* PARM='PGM /bin/sh -c /etc/ssh/sshd.sh'
//* STDIN AND STDOUT ARE BOTH DEFAULTED TO /dev/null
//STDERR DD PATH='/tmp/sshd.stderr',PATHOPTS=(OWRONLY,OCREAT,OAPPEND),
// PATHMODE=(SIRWXU)
//STDOUT DD PATH='/tmp/sshd.stdout',PATHOPTS=(OWRONLY,OCREAT,OAPPEND),
// PATHMODE=(SIRWXU)

Note that SSHD uses the /etc/ssh/sshd_config directory. You should back this up regulary. When IBM replaces the image this would be replace

After thought, I could always use -f /usr/colin/ssh/

Edit the configuration file and add either userids or groups.

# Allow specific user IDs 
AllowUsers IBMUSER COLIN
AllowGroups SYS1 IZUADMIN

If you add groups and not userids, you need to connect the userid to a group.

RACF changes

You can issue some racf commands on the z/OS console for example

<RVARY

To change this character (<) copy SYS1.PARMLIB(IEFSSN00) to USER.PARMLIB(IEFSSN01) and change the entry for RACF.

Define IXGLOGR as a started task to eliminate security messages

//IBMIXL  JOB 1,MSGCLASS=H 
//STEPNAME EXEC PGM=IKJEFT01
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *
* IXGLOGR EXISTS AS A GROUP - IT REALLY SHOULD BE A USERID
ADDUSER IXGLUSER
CONNECT IXGLUSER GROUP(IXGLOGR)
RDEFINE STARTED IXGLOGR.* STDATA(USER(IXGLUSER) +
PRIVILEGED(YES) TRUSTED(YES) GROUP(IXGLOGR ))
SETROPTS RACLIST(STARTED) REFRESH
/*

Add missing groups

To protect datasets such as SYS1.*, the high level qualifier should be defined as a group. I have JCL ADDGROUP

//IBMKEY2 JOB 1,MSGCLASS=H 
//STEPNAME EXEC PGM=IKJEFT01
//SYSTSIN DD *
ADDGROUP SYS1
ADDGROUP ADCD
ADDGROUP AOK
ADDGROUP AOP
ADDGROUP AZD
ADDGROUP BBL
ADDGROUP CATALOG
ADDGROUP CBC
ADDGROUP CEE
ADDGROUP CFZ
ADDGROUP CNJ
ADDGROUP COUPLE
ADDGROUP CSD
ADDGROUP CSF
ADDGROUP CSQARC1
ADDGROUP CSQARC2
ADDGROUP EUVF
ADDGROUP FEU
ADDGROUP FEU1
ADDGROUP FFST
ADDGROUP GDDM
ADDGROUP GIM
ADDGROUP GLD
ADDGROUP GSK
ADDGROUP GTFNO
ADDGROUP GTFRACF
ADDGROUP HAP
ADDGROUP HLA
*DDGROUP IBMUSER
ADDGROUP ICQ
ADDGROUP IOE
ADDGROUP ISF
ADDGROUP ISP
ADDGROUP IXGLOGR
ADDGROUP IZU
ADDGROUP IZUSVR
ADDGROUP NETVIEW
ADDGROUP NFS
ADDGROUP SMPE
ADDGROUP STCJMON
ADDGROUP SYT1
ADDGROUP TCPIP
ADDGROUP USER
ADDGROUP ZFS
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=* g

Protect system data sets

You should define profiles for all datasets. I had a a member ADDSD.

//IBMKEY2 JOB 1,MSGCLASS=H 
//STEPNAME EXEC PGM=IKJEFT01
//SYSTSIN DD *
ADDSD 'SYS1.**' GENERIC UACC(READ) WARNING
PERMIT 'SYS1.**' ACCESS(ALTER) ID(SYS1)
ADDSD 'ADCD.**' GENERIC UACC(READ) WARNING
ADDSD 'AOK.**' GENERIC UACC(READ) WARNING
ADDSD 'AOP.**' GENERIC UACC(READ) WARNING
ADDSD 'AZD.**' GENERIC UACC(READ) WARNING
ADDSD 'BBL.**' GENERIC UACC(READ) WARNING
ADDSD 'CATALOG.**' GENERIC UACC(READ) WARNING
ADDSD 'CBC.**' GENERIC UACC(READ) WARNING
ADDSD 'CEE.**' GENERIC UACC(READ) WARNING
ADDSD 'CFZ.**' GENERIC UACC(READ) WARNING
ADDSD 'CNJ.**' GENERIC UACC(READ) WARNING
ADDSD 'COUPLE.**' GENERIC UACC(READ) WARNING
ADDSD 'CSD.**' GENERIC UACC(READ) WARNING
ADDSD 'CSF.**' GENERIC UACC(READ) WARNING
ADDSD 'CSQARC1.**' GENERIC UACC(READ) WARNING
ADDSD 'CSQARC2.**' GENERIC UACC(READ) WARNING
ADDSD 'EUVF.**' GENERIC UACC(READ) WARNING
ADDSD 'FEU.**' GENERIC UACC(READ) WARNING
ADDSD 'FEU1.**' GENERIC UACC(READ) WARNING
ADDSD 'FFST.**' GENERIC UACC(READ) WARNING
ADDSD 'GDDM.**' GENERIC UACC(READ) WARNING
ADDSD 'GIM.**' GENERIC UACC(READ) WARNING
ADDSD 'GLD.**' GENERIC UACC(READ) WARNING
ADDSD 'GSK.**' GENERIC UACC(READ) WARNING
ADDSD 'GTFNO.**' GENERIC UACC(READ) WARNING
ADDSD 'GTFRACF.**' GENERIC UACC(READ) WARNING
ADDSD 'HAP.**' GENERIC UACC(READ) WARNING
ADDSD 'HLA.**' GENERIC UACC(READ) WARNING
ADDSD 'IBMUSER.**' GENERIC UACC(READ) WARNING
ADDSD 'ICQ.**' GENERIC UACC(READ) WARNING
ADDSD 'IOE.**' GENERIC UACC(READ) WARNING
ADDSD 'ISF.**' GENERIC UACC(READ) WARNING
ADDSD 'ISP.**' GENERIC UACC(READ) WARNING
ADDSD 'IXGLOGR.**' GENERIC UACC(READ) WARNING
ADDSD 'IZU.**' GENERIC UACC(READ) WARNING
ADDSD 'IZUSVR.**' GENERIC UACC(READ) WARNING
ADDSD 'NETVIEW.**' GENERIC UACC(READ) WARNING
ADDSD 'NFS.**' GENERIC UACC(READ) WARNING
ADDSD 'SMPE.**' GENERIC UACC(READ) WARNING
ADDSD 'STCJMON.**' GENERIC UACC(READ) WARNING
ADDSD 'SYT1.**' GENERIC UACC(READ) WARNING
ADDSD 'TCPIP.**' GENERIC UACC(READ) WARNING
ADDSD 'USER.**' GENERIC UACC(READ) WARNING
ADDSD 'ZFS.**' GENERIC UACC(READ) WARNING
PERMIT 'ADCD.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'AOK.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'AOP.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'AZD.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'BBL.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'CATALOG.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'CBC.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'CEE.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'CFZ.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'CNJ.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'COUPLE.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'CSD.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'CSF.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'CSQARC1.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'CSQARC2.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'EUVF.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'FEU.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'FEU1.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'FFST.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'GDDM.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'GIM.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'GLD.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'GSK.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'GTFNO.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'GTFRACF.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'HAP.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'HLA.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'IBMUSER.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'ICQ.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'IOE.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'ISF.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'ISP.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'IXGLOGR.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'IZU.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'IZUSVR.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'NETVIEW.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'NFS.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'SMPE.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'STCJMON.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'SYT1.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'TCPIP.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'USER.**' ACCESS(ALTER) ID(SYS1)
PERMIT 'ZFS.**' ACCESS(ALTER) ID(SYS1)
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*

You should have started tasks defined

Started tasks should be defined, so end users cannot just create a Started Task, and run it as an authorised task.

Define a default

//IBMKEY2 JOB 1,MSGCLASS=H 
//STEPNAME EXEC PGM=IKJEFT01
//SYSTSIN DD *
RDEFINE STARTED *.* OWNER(IBMUSER) +
DATA('GENERIC DEFINITION - COLIN') +
STDATA( USER(=MEMBER)
SETROPTS RACLIST(STARTED) REFRESH

Export certificates and keyrings

I have member EXPRING. this runs the LRING Rexx which creates a data set containing certificates used by the userid. They are stored in &USERID..CERTS.START1

//IBMKEYR JOB 1,MSGCLASS=H 
//STEPNAME EXEC PGM=IKJEFT01,PARM='LRING START1',REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSEXEC DD DISP=SHR,DSN=USER.Z31B.CLIST
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD DUMMY

Import certificates and keyrings

Use the Rexx program to export certificates from your old system, and import them into the new system.

Import

//IBMKEYR JOB 1,MSGCLASS=H
//STEPNAME EXEC PGM=IKJEFT01,PARM='IRING COLIN.CERTS.START1',
// REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSEXEC DD DISP=SHR,DSN=USER.Z31B.CLIST,UNIT=3390,VOL=SER=B3CFG1
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD DUMMY

RRS Error messages

At the start up of RRS I got

ATR132I RRS LOGSTREAM CONNECT HAS FAILED FOR
– OPTIONAL LOGSTREAM ATR.VS01.ARCHIVE.
– RC=00000008, RSN=0000080B

See here

Issue the operator command

SETRRS ARCHIVELOGGING,DISABLE 

ICSF

ICSF

I have my own (I)CSF data sets, containing my keys. My Started Task JCL is the same as the default, but with a different member

//CSF  PROC PRM=CP 
//CSF EXEC PGM=CSFINIT,PARM=&PRM,REGION=0M,TIME=1440,MEMLIMIT=NOLIMIT

You could use the provided JCL, then stop and restart CSF

P CSF
S CSF,PRM=CP

The PARM=CP points to a member CSFPRMCP in USER.PARMLIB. Mine has

CKDSN(COLIN.SCSFCKDS) 
PKDSN(COLIN.SCSFPKDS)
TKDSN(COLIN.SCSFTKDS) qq
DOMAIN(0)
SSM(YES)
KEYARCHMSG(YES)

If this member does not exist you get an abend

IEF764I CSF CSF IEFPARM CSFMIOPD HCR77F0 PARMLIB READ FAILED - MEMBER CSFPRMCP NOT FOUND.        
CSFO0016 ERROR OCCURRED OPENING OPTIONS FILE. MEMBER CSFPRMCP IN DDNAME IEFPARM RC=12 RS=1.
...
DUMP TITLE=COMPON=CSF...ABEND=S018F,REASON=0000001B

Logrec EREP

When LOGREC fills up, you get a retained message on the console.

You can print the contents of the EREP file using

//PRINTLOG JOB (ACCT),'PRINT LOGREC',CLASS=A,MSGCLASS=H           
//STEP EXEC PGM=IFCEREP1,PARM='CARD'
//SERLOG DD DISP=SHR,DSN=VSPROV.VS01.LOGREC
//DIRECTWK DD UNIT=SYSDA,SPACE=(CYL,10,,CONTIG)
//EREPPT DD SYSOUT=A,DCB=BLKSIZE=133
//TOURIST DD SYSOUT=A,DCB=BLKSIZE=133
//ZERLOG DD SYSOUT=A,DCB=BLKSIZE=133
//SYSIN DD *
PRINT=PS
ACC=N
ZERO=Y
ENDPARM
/*

and clear it using a procedure in USER.PROCLIB(CLLOGREC)

//CLLOGREC  PROC 
//STEP1 EXEC PGM=IFCDIP00
//SERERDS DD DISP=OLD,DSN=VSPROV.VS01.LOGREC,
// UNIT=3390,VOL=SER=OPEVS1

and the started task definition in STLOGREC

//IBMUSERT JOB 1,MSGCLASS=H 
//S1 EXEC PGM=IKJEFT01,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *
RDEFINE STARTED CLLOGREC.* STDATA(USER(IBMUSER))
RDEFINE STARTED PRLOGREC.* STDATA(USER(IBMUSER))
SETR RACLIST(STARTED) REFRESH

JAVA message and SMFLIM

I was getting messages

JVMJ9VM015W Initialization error for library j9shr29(11): JVMJ9VM009E J9VMDllMain failed
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

See JVMJ9VM015W Initialization error for library j9shr29(11): JVMJ9VM009E J9VMDllMain failed

I created USER.PARMLIB(SMFLIM00) with

REGION JOBNAME(JCACHER) JOBMSG(ISSUE) MAXSHARE(80000) 

SMF logstream data sets are too small

Im getting message allocating data sets like IXGLOGR.IFASMF.VS01.DATA… every couple of minutes.

The log stream is define with

LOGSTREAM NAME(IFASMF.VS01.DATA) STRUCTNAME() LS_DATACLAS()
LS_MGMTCLAS() LS_STORCLAS() HLQ(IXGLOGR) MODEL(NO) LS_SIZE(500)
STG_MGMTCLAS() STG_STORCLAS() STG_DATACLAS() STG_SIZE(500)
LOWOFFLOAD(0) HIGHOFFLOAD(80) STG_DUPLEX(YES) DUPLEXMODE(UNCOND)
RMNAME() DESCRIPTION() RETPD(2) AUTODELETE(YES) OFFLOADRECALL(YES)
DASDONLY(YES) DIAG(NO) LOGGERDUPLEX() EHLQ(NO_EHLQ) GROUP()
MAXBUFSIZE(65532)

Where LS_SIZE(500) is 45 tracks.

I used JCL

//IBMLOG JOB 1,MSGCLASS=H                                   
//LOGDEF EXEC PGM=IXCMIAPU,REGION=4M
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DATA TYPE(LOGR) REPORT(YES)
UPDATE LOGSTREAM NAME(IFASMF.VS01.DATA)
LS_SIZE(15000)
/*

I could not run this, because the log stream was in use.

I had to create an USER.PARMLIB(SMFPRMNO) with

ACTIVE, 
DSNAME(SYS1.VS01.MAN1,
SYS1.VS01.MAN2),
RECORDING(DATASET)
DEFAULTLSNAME(IFASMF.VS01.DATA)
...

Then use

T SMF=NO

The run the command to update the logstream

and then switch back

T SMF=00

What’s next?

That’s as far as I’ve got. As I do more I’ll update this document.

I have to renew my TLS certificate every 47 days. What?!

There has been some discussion about this, and what it means. With the help of Matt Hogstrom, I now understand this a bit more.

Background

Symmetric encryption is when you change A-> B->6 etc. You use the same mapping to decrypt as you used to encrypt. If you have the mapping to encode, you can decode it. If several people use the same mapping – you can read other people’s messages.

Most digital encryption is done these days using asymmetric encryption. With an asymmetric encryption there are two keys. You encrypt with one key, and need the other key to decrypt it.

You make one key public, so anyone can have access to it, and keep the other key private and secure.

  • When you encrypt with my public key, and I decrypt it with my private key.
  • When I encrypt with my private key, you decrypt with my public key, and you know it came from me, because you used my public key.

A certificate is a package of a public key, and other information such as who it belongs to, what the certificate can be used for, and validity dates. This is packaged up, sent to a certificate authority, who digitally signs it, and returns it.

TLS is a protocol for exchanging information between a client and a server. As part of the handshake the server sends down the server’s certificate. The client checks the digital signature, and if valid, can use the enclosed public certificate to encrypt data to be sent to the server.

The problem

Your organisation, (company or country) has been using the same certificate, and so the same public key for the last 10 years. Some bad guys have been monitoring the network traffic from your organisation during this time, and saving it on tape.

Somehow the private key has escaped. Perhaps the person who looks after the plants was bribed to come in and steal the private key, or you left your laptop on the train. The bad guys have 10 years worth of data, and your private key, and can now read all the traffic sent to and from you!

This scenario has been recognised as a problem.

One solution is to change the public/private keys more frequently.

This leads to a different problem,

How often do you change the public/private key?

A year is too long. Every day is too much of an overhead. Let’s aim for one month – 30 days.

It may be that the person whose job it is to renew certificates take annual leave (up to two weeks). It would be unfortunate for a certificate to expire because that person has just gone on holiday, so let’s allow two weeks for this (Friday to Monday, 16 days). We need to give them a day to go through their mail inbox – so let’s set an expiry interval of 30 days + 16 days +1 = 47 days.

What do you renew?

In the discussion people were talking about renewing the certificate. You can renew the certificate, but specify the old public key – this defeats the purpose of the change.

You need to renew your public/private key every 47 days, and as a consequence, renew your certificate. You do not just renew the certificate with the old key.

What’s the impact?

A certificate is about to expire, so you renew it. You have a program using the old certificate. Your program needs to read the new certificate. This may mean stopping and restarting your program. For those programs which are operational all day, every day, you need to factor restarting your program. This may mean restarting it every Sunday night between 0200 and 0400. If the certificate expires during normal operation you have an emergency set of changes; renew the certificate and restart your application.

This change is for certificates used in TLS, transfering information between client and server. The certificate has a flag saying this can be used as a server, or a client (but do not specify both).

A certificate with its public key can be used for other purposes besides TLS.

For example, signing data.

Signing data

When a file is signed, you calculate the checksum (a hash value) of the file, encrypt this checksum with your private key, and attach this encrypted checksum, and your certificate to the file.

When you receive the signed file. You extract the certificate, validate it, and use the public certificate to decrypt the encrypted checksum. You do the same checksum calculation on the data and compare the two checksums. If they match the data is as the originator provided.

In this case, the public/private key does not have the same problem as TLS. The originator could be recreating the public/private key every week, it would not affect you with the package.

Intermediate certificates

You may not want every user’s certificate to be sent to the commercial certificate authorities for digital signing. You could have your own Certificate Authority.

You send a certificate to the commercial Certificate Authority, and get it signed. You then use this certificate to sign all certificates in your organisation. In this case a user’s certificate has two CA certificates attached to it. When validating a certificate the code checks that the commercial CA matches what is stored in the computer. If that matches, it uses the public key in that certificate to validate the checksum from your CA. If that matches then the public key from your CA is used to validate the end certificate.

If any CA certificate has expired, the whole certificate chain will fail validation. In this case you need your intermediate CA to be long lasting. One of the commercial CA’s has a validity period of 17+ years!

Summary

Renewing a certificate used in Client to Server (TLS) communications should have the public/private keys renewed regularly. It is recommended to have no more than 47 days.

You may want other certificates, which have longer validity periods, such as intermediate certificates.

You may want certificates where you do not care how often the public/keys are refreshed – such as code signing.

One lesson from this is you should have a different public/private key/certificate for each area; TLS, CA, and signing. The areas have different requirements.

How do you validate files on z/OS, at install time and long term?

You’ve been asked to install some files. You are not sure of their provenance, or if they have been changed from what the author wrote, and what you have received. How can you check these files?

You have some systems which are meant to be identical how can you easily check this?

One way of doing these activities is to calculate a digital hash of the file, sign the hash value, and use it.

See background for information on public/private keys.

Digitally signing is to take value, encrypt it with your private key and send it out with your certificate. To verify the signature you use the public key from the certificate to decrypt the data. It should match your copy of the value. If it matches you know it came from the certificate owner.

On z/OS you can sign load modules. These are signed at bind time, and, if configured, are checked at execution time.

Packages like openssl, and GPG (Pretty Good Privacy) have the facilities to sign objects.

This blog post covers

Installing packages

On the author’s machine

You have the Certificate Authorities file ca256.pem. This is available to every one. This could have been provided by a commercial Certificate Authority.

You have a public certificate which you will send with your package.

You have a private key matching the public certificate.

On the recipient’s machine

You have the Certificate Authority file ca256.pem.

How you do it

Create the package

You want to package data.file and distribute it. Calculate the digest of the file, and digitaly sign it

openssl dgst -sign cert.key.pem -out data.file.signature  data.file

The signature is put into data.file.signature. The signature data is in binary.

Send the following to the recipient

  • data.file
  • data.file.signature
  • your public certificate matching the private key used to sign the data. (colins.cert.pem)

Validate the package

Validate the certificate against the CA.pem 

openssl verify -CAfile ca256.pem colins.cert.pem 

If this works, you can trust the certificate.

Extract the public key from the certificate

openssl x509 -pubkey -noout -in colins.cert.pem > colins.pubkey

Validate the checksum of the file

This uses the public key extracted above

openssl dgst -verify ./colins.pubkey  -signature data.file.signature  data.file

z/OS dataset

You can use z/OS dataset, for example

openssl dgst -sign z256.key.pem -out upa.signature "//'USER.Z31B.PARMLIB(AUTORCP)'"  

where you need the double quotes and the single quotes.

Package up a package

You could create a shell script to work on a directory. For example

#!/bin/bash
for filename in ./*; do
[ -e "$filename" ] || continue
echo $filename
FILE="$(basename "${filename}")"
openssl dgst -sign z256.key.pem -out signatures/$FILE.signature $filename
done

When I ran this, the signatures directory contained the signatures of the files in the current directory.

Long term validation

You’ve validated that the files you have installed are the correct ones. Has anyone changed them since they’ve been installed?


You can issue the command to calculate the digest(hash) of a file.

openssl dgst index.txt >> dgst.txt

Which says calculate the digest – but do not sign it. The output is

SHA256(index.txt)= 1c6e0089a3ceebddf1f8e475c164162c06d7d58f29cc0b2d4c230e4e7a79cbce
SHA256(aa.txt)= d8b1fb09ac7649b61d13ca9cde72851037a83c0bca60a8545310645bb0b3da7d

You can now periodically reissue the commands, and check the value are the same as they were previously. If the values have changed – the files have changed. You can also extend this (with a small bit of Python or shell code) to include the system name

SYS1 2026/04/22 SHA256(index.txt)= 1c6e0089a3ceebddf1f8e475c...e7a79cbce
SYS2 2026/04/22 SHA256(index.txt)= d8b1fb09ac7649b61d13ca9cd...bb0b3da7d

If those files are meant to be the same on both of the systems, they clearly are not. If you run the digest command weekly you will be able to see approximately when the file was changed. It may be that maintenance was applied to one system, and the other system was overlooked.

Using code signing on z/OS

There is an IBM document Task roadmap for program signing and signature verification, this provides some of the information, and some of the information is wrong!

I’ve documented Signing load modules on z/OS.

I hit various problems. The return code from the program signing function are documented here.

Using signed modules on your system

You have been sent some modules which have been signed, and you want to user the signature verification on these modules.

One-of system wide setup

Define the system wide keyring

For the validation of signed modules there is one system wide key ring. It needs to have the signing certificates (or the CA certificates) for all of the modules being used.

RACDCERT ADDRING(VERIFY) ID(COLIN ) 

* now the profile
RDEFINE RDATALIB COLIN.VERIFY.LST UACC(NONE)
PERMIT COLIN.VERIFY.LST CLASS(RDATALIB) ID(COLIN ) ACCESS(UPDATE)
SETROPTS RACLIST(RDATALIB) REFRESH

Connect the IBM CA to the keyring

You need to connect the IBM Provided Certificate authority, to be able to verify the signature of IBM provided modules. See Listing of RACF supplied certificates.

RACDCERT ID(COLIN )CONNECT(RING(VERIFY) - 
CERTAUTH -
LABEL('STG Code Signing CA - G2')

RACDCERT LISTRING(VERIFY) ID(COLIN )

Note the lower case name.

Tell the certificate certificate facility which key ring to use.

 RDEFINE FACILITY IRR.PROGRAM.SIGNATURE.VERIFICATION  - 
APPLDATA('COLIN/VERIFY')

This ring has the certificates needed to verify.

Define the program that does the signature validation.

RDEFINE PROGRAM IRRPVERS ADDMEM('SYS1.SIEALNKE'//NOPADCHK) UACC(READ)- 
SIGVER(SIGREQUIRED(YES) FAILLOAD(ANYBAD) SIGAUDIT(ANYBAD))

Run the IRRVELD job

I had to run this when setting up for the first time. When I next IPLed, I did not need to run it. I think that RACF checks to see if the above RACF profile exists – if so – loads the code.

See here.

//IRRVERLD JOB                        
//IRRVERLD EXEC PGM=IRRVERLD

When successful, this starts and ends with return code 0 and

ICH448I RACF program signature verification function is loaded. Program signature verification is available on this system.

Define your programs that need validation

RDEFINE PROGRAM ZZZDATA  ADDMEM('COLIN.ZWIRESHA.LOAD'//NOPADCHK) - 
UACC(READ) -
SIGVER(SIGREQUIRED(YES) FAILLOAD(ANYBAD) SIGAUDIT(ANYBAD))

SETROPTS WHEN(PROGRAM) REFRESH

Where my program is called ZZZDATA and it is loaded from COLIN.ZWIRESHA.LOAD. The definition SIGVER(SIGREQUIRED(YES) FAILLOAD(ANYBAD) SIGAUDIT(ANYBAD)) says that signature is required, and if verification fails do not load the module, and write an audit record.

Each userid (or group) needs a RACF profile to specify which keyring to use to sign the programs

If you want to do IPL data signing for Validated Boot for z/OS you need the profile IRR.PROGRAM.V2.SIGNING…..

If you want to validate a general program you need the profile IRR.PROGRAM.SIGNING….

Where you can specif userid, group, or group and userid.

  • IRR.PROGRAM.SIGNING.userid
  • IRR.PROGRAM.SIGNING.goup
  • IRR.PROGRAM.SIGNING.group.user
                              
RDELETE FACILITY IRR.PROGRAM.SIGNING.COLIN
RDEFINE FACILITY IRR.PROGRAM.SIGNING.COLIN -
APPLDATA('SHA256 COLIN/SIGNING')
PERMIT IRR.PROGRAM.SIGNING.COLIN CLASS(FACILITY) -
ID(COLIN) ACCESS(CONTROL)
SETROPTS RACLIST(FACILITY) refresh

This says for userid COLIN use SHA256 and keyring COLIN/SIGNING. It will use the default key in the keyring.

You sign a module at bind time, by specifying the binder options SIGN=YES.

I added sign=yes to the binder JCL

Create a certificate to sign it

RACDCERT ID(COLIN) GENCERT -                                 
SUBJECTSDN(CN('10.1.1.2') -
O('SIGNER521') -
OU('SSS')) -
ALTNAME(IP(10.1.1.2))-
SIZE(2048) -
NOTAFTER( DATE(2026-04-22) TIME(15:22:00) ) -
KEYUSAGE(HANDSHAKE DOCSIGN) -
SIGNWITH (CERTAUTH LABEL('SIGNCA')) -
WITHLABEL('SIGNER521')

RACDCERT id(COLIN) ALTER(LABEL('SIGNER521'))TRUST

SETROPTS RACLIST(DIGTCERT) REFRESH
RACDCERT ID(COLIN )CONNECT(RING(SIGNING) -
ID(COLIN) -
DEFAULT -
LABEL('SIGNER521') )

It seems to need KEYUSAGE HANDSHAKE and DOCSIGN.

It needed the default RSA size 2048. It did not work with an ECC algorithm.

It needs to be the default in the keyring.

Execute the program

When you come to execute the signed program, the system uses the keyring defined in the

IRR.PROGRAM.SIGNATURE.VERIFICATION CLASS(FACILITY) profile. I believe this has the certificates needed to verify the programs signature.

I used keyring COLIN/VERIFY.

IEW2494E 9116 A PROBLEM WAS ENCOUNTERED WITH THE SETUP OF THE DIGITAL CERTIFICATES REQUIRED FOR PROGRAM SIGNING. RACF RETURNED SAF RETURN CODE 8 RACF RETURN CODE 8 RACF REASON CODE 00000070.

R_PgmSign 70 Ver Key ring or token does not exist or does not contain a default certificate.

Signing load modules on z/OS

There is an IBM document Task roadmap for program signing and signature verification, this provides some of the information, and some of the information is wrong!

This blog post describes how to set up your environment to sign load modules. I’ve documented Using code signing on z/OS

I hit various problems. The return code from the program signing function are documented here.

Create RACF profiles

Each userid (or group) needs a RACF profile to specify which keyring to use to sign the programs

If you want to do IPL data signing for Validated Boot for z/OS you need the profile IRR.PROGRAM.V2.SIGNING…..

If you want to validate a general program you need the profile IRR.PROGRAM.SIGNING….

Where you can specify userid, group, or group and userid.

  • IRR.PROGRAM.SIGNING.userid
  • IRR.PROGRAM.SIGNING.goup
  • IRR.PROGRAM.SIGNING.group.user
                              
RDELETE FACILITY IRR.PROGRAM.SIGNING.COLIN
RDEFINE FACILITY IRR.PROGRAM.SIGNING.COLIN -
APPLDATA('SHA256 COLIN/SIGNING')
PERMIT IRR.PROGRAM.SIGNING.COLIN CLASS(FACILITY) -
ID(COLIN) ACCESS(CONTROL)
SETROPTS RACLIST(FACILITY) refresh

This says for userid COLIN use SHA256 and keyring COLIN/SIGNING. It uses the default key in the keyring.

How to sign a load module

You sign a module at bind time, by specifying the binder options SIGN=YES.

I added SIGN=YES to the binder JCL

When it failed, there were messages like

IEW2494E 9116 A PROBLEM WAS ENCOUNTERED WITH THE SETUP OF THE DIGITAL CERTIFICATES REQUIRED FOR PROGRAM SIGNING. RACF RETURNED SAF RETURN CODE 8 RACF RETURN CODE 8 RACF REASON CODE 00000098.

These are from the R_PgmSignVer (IRRSPS00): Program Sign and Verify callable service. See the return codes. The return codes in the messages are in hex; in the documentation they are in decimal. 0x98 is decimal 152. 152 is CA or signing certificate is expired or not yet active. This was true – my signing certificate had expired.

Create a certificate to sign load modules.

RACDCERT ID(COLIN) GENCERT -                                 
SUBJECTSDN(CN('10.1.1.2') -
O('SIGNER521') -
OU('SSS')) -
ALTNAME(IP(10.1.1.2))-
SIZE(2048) -
NOTAFTER( DATE(2026-04-22) TIME(15:22:00) ) -
KEYUSAGE(HANDSHAKE DOCSIGN) -
SIGNWITH (CERTAUTH LABEL('SIGNCA')) -
WITHLABEL('SIGNER521')

RACDCERT id(COLIN) ALTER(LABEL('SIGNER521'))TRUST

SETROPTS RACLIST(DIGTCERT) REFRESH
RACDCERT ID(COLIN )CONNECT(RING(SIGNING) -
ID(COLIN) -
DEFAULT -
LABEL('SIGNER521') )

It seems to need KEYUSAGE HANDSHAKE and DOCSIGN.

It needed the default RSA size 2048. It did not work with an ECC algorithm.

It needs to be the default in the keyring.

Code signing – error messages

The messages I received were from R_PgmSignVer (IRRSPS00 or IRRSPS64): Program Sign and Verify

Return code hex 70, decimal 112

  • ICH440I Program signature error 0x10/0x00000070 for program IRRPVERS in library SYS1.SIEALNKE.
  • The program was not loaded.
  • ICH442I The digital signature appears to be valid but the root signer is not trusted.
  • ICH451I RACF encountered an error while attempting to load the program verification module. Operation code = X’06’.
  • Return code X’00000306′ and Reason code X’00000040′.
  • Supplemental diagnostic code 1 = X’00000000′.
  • Supplemental diagnostic code 2 = X’00000000′.
  • Supplemental diagnostic code 3 = X’00000000′.
  • Supplemental diagnostic code 4 = X’00000000′.
  • Supplemental diagnostic code 5 = X’00000000′.

The certificate CERTAUTH LABEL(‘STG Code Signing CA – G2’) was not trusted.

R_PgmSignVer return codes code 0x70 is 112. Key ring or token does not exist or does not contain a default certificate.

I had mis typed the certificate name.

Action:

The the name of the keyring, there is a default certificate, and the certificate has not expired.

Return code hex 64, decimal 100

At execution time I got.

ICH440I Program signature error 0x10/0x00000064 for program ZZZDATA in library COLIN.ZWIRESHA.LOAD. The program was not loaded. ICH442I The digital signature appears to be valid but the root signer is not trusted.

code 0x64 is decimal 100 which is

The program appears to be correctly signed but one of the following conditions exists:

  • The root CA certificate in the zOSSignatureInfo structure of the program object is not connected to the signature-verification key ring.
  • The root CA certificate is marked NOTRUST.

The CA of the signing code was not in the verify keyring at execution time.

Action:

Connect the certificate or its CA to the verify keyring.

Return code hex 88, decimal 136

IEW2494E 9116 A PROBLEM WAS ENCOUNTERED WITH THE SETUP OF THE DIGITAL CERTIFICATES REQUIRED FOR PROGRAM SIGNING. RACF RETURNED SAF RETURN CODE 8 RACF RETURN CODE 8 RACF REASON CODE 00000088.

The default certificate in the key ring or token does not have code signing capability.

  • When Num_parms = 10, the keyUsage extension is optional. If the extension is present, the digitalSignature bit must be set.
  • When Num_parms = 11, the keyUsage extension must be present and the digitalSignature bit must be set.

The real reason is “HANDSHAKE” or “DOCSIGN” was missing from the KEYUSAGE().

Action:

Fix the keyusage field.

Return code hex 90, decimal 144

IEW2494E 9116 A PROBLEM WAS ENCOUNTERED WITH THE SETUP OF THE DIGITAL CERTIFICATES REQUIRED FOR PROGRAM SIGNING. RACF RETURNED SAF RETURN CODE 8 RACF RETURN CODE 8 RACF REASON CODE 00000090.

The key type of one or more certificates in the key ring or token is not supported. This reason code is also issued for the following conditions:

  • When Num_parms = 11, the signing key can be stored in ICSF, but it must be a 521-bits NIST Elliptic Curve Cryptography (ECC) key. Also, the key size of any other certificates in the key ring or token must be at least 2048 bits for RSA keys, or 224 bits for NIST ECC and Brainpool ECC keys.
  • When Num_parms = 10 and an RSA CA certificate in the chain has a key size less than 2048 bits.

This was caused by using a key with

NISTECC -
SIZE(521 ) -

using the followin

RSA
SIZE(2048) -

Works.

Action:

Use RSA key with size 2048;

First steps in using system ssl

System SSL also known as GS kit provides an API for doing

  • TLS handshakes
  • Keyring manipulation
  • Encryption and signing of data

This blog post covers background information for using GSKit. I wrote it because I could not find useful samples to get me started.

Introduction

It took me some time to understand how System SSL has been written. Now I understand it, I think it is a good API. They can be more than one way of doing something, so working out what you want to to can be hard.

Use of structures

It took me a while to understand the structures. I thought they were a little complex, and started designing my own equivalent, but I then found my “improved” definition were very similar to the original ones.

For example, I want to process some application data. It has an address and a length.
With my simplistic view I would define

  • char * pBuffer;
  • int lBuffer;

You could the use these in your application.

GSKIT provides the same files in a structure.

gsk_buffer mybuffer;
mybuffer.data = "ABCD"; // data is a void * pointing to the data
mybuffer.length = 4; //

I can then do

gsk_buffer in;
gsk_buffer out;
in.data = ...
in.length = ...
gsk_rc gsk_copy_buffer(*in,*out)

For gsk_buffers that are output from a GSKIT call you need to free the contents.

gsk_free_buffer(&in);

This will release any storage which had been allocated to the structure, and set the values to 0.

Do not use this for gsk_buffers you created, because it will free the storage the data is using.

Arrays of objects

Some API functions take one certificate, and others take an array of certificates.

You define one certificate-key

 pkcs_cert_key cert_key;

For an array of certificate keys you use

// Define the array (of 2)
pkcs_cert_key cert_key[2];
// Initialise it
cert_key[0].certificate = cert;
cert_key[0].privateKey = pRecord -> privateKey;
cert_key[1].certificate = cert1;
cert_key[1].privateKey = pRecord1 -> privateKey;
// Define the structure of array of keys
pkcs_cert_keys cert_keys;
cert_keys.count = 2;
cert_keys.certKeys = &cert_key[0];

Processing arrays of objects

void print_certs(pkcs_certificates * pcs)
{
// pkcs_certificate has a count and array of certs
// iterate over them all
int i;
pkcs_certificate * pc = & pcs-> certificates[0];
for (i = 1; i <= pcs-> count;i++)
{
printf("Certificate %i\n",i);
printf("==========\n");
print_cert(pc);
pc ++;
printf(" \n");
}
}

Where print_cert() is the program I wrote which prints information about one certificate.

Useful functions

Most gskit functions return a gsk_status. You can print the interpretation of this using

if ( gskrc != 0)
printf("Error return: %s\n" gsk_strerror(gskrc));

Definitions are in

  • /usr/include/gsktypes
  • /usr/include/gskcms.h