Netstat, TTLS and AT-TLS

Once a session has been established using AT-TLS to do end to end TLS encryption, you can use netstat to display information about the session, and what configuration is being used. It feels slightly incomplete, in that some of the data I expected is not available.

What sessions are using a Port? – and display TTLSPolicy information

tso netstat all (port 1414

You can use other filter statements, using port 1414 was easy to specify.

This displays the high level TTLS information, see the blue text below

EZZ2350I MVS TCP/IP NETSTAT CS V2R4       TCPIP Name: TCPIP           16:40:39
EZZ2550I Client Name: CSQ9CHIN                 Client Id: 000000BB
EZZ2551I Local Socket: 10.1.1.2..1414          Foreign Socket: 10.1.0.2..51844 
EZZ2577I   BytesIn:            0000002248        BytesOut:           0000002076
EZZ2574I   SegmentsIn:         0000000020        SegmentsOut:        0000000014
EZZ2536I   StartDate:          05/31/2022        StartTime:          16:31:54
EZZ2552I   Last Touched:       16:36:57          State:              Establsh
EZZ2553I   RcvNxt:             0626077759        SndNxt:             3598815082
EZZ2554I   ClientRcvNxt:       0626076574        ClientSndNxt:       3598812426
EZZ2555I   InitRcvSeqNum:      0626074325        InitSndSeqNum:      3598810349
EZZ2556I   CongestionWindow:   0000018720        SlowStartThreshold: 0000065535
EZZ2557I   IncomingWindowNum:  0626208746        OutgoingWindowNum:  3598877418
EZZ2558I   SndWl1:             0626077759        SndWl2:             3598815082
EZZ2559I   SndWnd:             0000062336        MaxSndWnd:          0000064256
EZZ2560I   SndUna:             3598815082        rtt_seq:            3598814997
EZZ2561I   MaximumSegmentSize: 0000001440        DSField:            00
EZZ2563I   Round-trip information:
EZZ2564I     Smooth trip time: 7.000             SmoothTripVariance: 19.000
EZZ2565I   ReXmt:              0000000000        ReXmtCount:         0000000000
EZZ2572I   DupACKs:            0000000000        RcvWnd:             0000130987
EZZ2566I   SockOpt:            88                TcpTimer:           00
EZZ2567I   TcpSig:             04                TcpSel:             40
EZZ2568I   TcpDet:             E4                TcpPol:             00
EZZ2593I   TcpPrf:             89                TcpPrf2:            20
EZZ2593I   TcpPrf3:            00
EZZ2593I   DelayAck:           Yes
EZZ2537I   QOSPolicy:          No
EZZ2545I   TTLSPolicy:         Yes
EZZ2546I     TTLSRule:         REMOTE-TO-CSQ1
EZZ2547I     TTLSGrpAction:    CSQ1-GROUP-ACTION
EZZ2548I     TTLSEnvAction:    CSQ1-INBOUND-ENVIRONMENT-ACTION
EZZ2542I   RoutingPolicy:      No
EZZ2570I   ReceiveBufferSize:  0000065536        SendBufferSize:     0000065536
EZZ2538I   ReceiveDataQueued:  0000000000
EZZ2539I   SendDataQueued:     0000000000
EZZ2611I   SendStalled:        No
EZZ2609I   Ancillary Input Queue: N/A
...

From the clientid (connection id) display any TTLS information

From the netstat allconn (port 1414 command, you get each session, and its clientid (see above for clientid 000000BB).

From the tso netstat allconn (port 1414 command, you get one line per session with the connection ID and remote IP address and port.

EZZ2350I MVS TCP/IP NETSTAT CS V2R4       TCPIP Name: TCPIP           16:55:18
EZZ2585I User Id  Conn     Local Socket           Foreign Socket         State
EZZ2586I -------  ----     ------------           --------------         -----
EZZ2587I CSQ9CHIN 000000BB 10.1.1.2..1414         10.1.0.2..51844        Establsh
EZZ2587I CSQ9CHIN 00000022 0.0.0.0..1414          0.0.0.0..0             Listen

Issue the command to display the TTLS information details about connection.

tso netstat ttls conn 000000BB detail

MVS TCP/IP NETSTAT CS V2R4       TCPIP Name: TCPIP  
ConnID: 000000bb
  JobName:      CSQ9CHIN
  LocalSocket:  10.1.1.2..1414
  RemoteSocket: 10.1.0.2..53230
  SecLevel:     TLS Version 1.2
  Cipher:       003C TLS_RSA_WITH_AES_128_CBC_SHA256
  KeyShare:     N/A
  CertUserID:   N/A
  MapType:      Primary
  FIPS140:      Off
  SessionID:    01010018 0A010002 CFEE0000 00000000
                00000000 00000000 62970B05 00000001
  SIDReuseReq:  Off
TTLSRule: REMOTE-TO-CSQ1
  Priority:       1
  LocalAddr:      All
  LocalPort:      1414
  RemoteAddr:     All
  RemotePort:     All
  JobName:        CSQ9CHIN
  Direction:      Inbound
  TTLSGrpAction:  CSQ1-GROUP-ACTION
    GroupID:                    00000007
    TTLSEnabled:                On
    CtraceClearText:            Off
    Trace:                      2
    SyslogFacility:             Daemon
    SecondaryMap:               Off
    FIPS140:                    Off
  TTLSEnvAction:  CSQ1-INBOUND-ENVIRONMENT-ACTION
    HandshakeRole:              Server
    SuiteBProfile:              Off
    MiddleBoxCompatMode:        Off
    Keyring:                    START1/MQRING
    V3CipherSuites:             003C TLS_RSA_WITH_AES_128_CBC_SHA256
    Trace:                      255
    SSLV2:                      Off
    SSLV3:                      Off
    TLSV1:                      Off
    TLSV1.1:                    Off
    TLSV1.2:                    On
    TLSV1.3:                    On
    ResetCipherTimer:           0
    ApplicationControlled:      Off
    HandshakeTimeout:           10
    CertificateLabel:           ZZZZ
    SecondaryMap:               Off
    TruncatedHMAC:              Off
    ClientMaxSSLFragment:       Off
    ServerMaxSSLFragment:       Off
    ClientHandshakeSNI:         Off
    ServerHandshakeSNI:         Off
    ClientECurves:              0021 secp224r1
                                0023 secp256r1
                                0024 secp384r1
                                0025 secp521r1
                                0019 secp192r1
                                0029 X25519
    ClientKeyShareGroups:       0023 secp256r1
    ServerKeyShareGroups:       0023 secp256r1
                                0024 secp384r1
                                0025 secp521r1
                                0029 X25519
                                0030 X448
    SignaturePairs:             0601 TLS_SIGALG_SHA512_WITH_RSA
                                0603 TLS_SIGALG_SHA512_WITH_ECDSA
                                0501 TLS_SIGALG_SHA384_WITH_RSA
                                0503 TLS_SIGALG_SHA384_WITH_ECDSA
                                0401 TLS_SIGALG_SHA256_WITH_RSA
                                0403 TLS_SIGALG_SHA256_WITH_ECDSA
                                0402 TLS_SIGALG_SHA256_WITH_DSA
                                0301 TLS_SIGALG_SHA224_WITH_RSA
                                0303 TLS_SIGALG_SHA224_WITH_ECDSA
                                0302 TLS_SIGALG_SHA224_WITH_DSA
                                0201 TLS_SIGALG_SHA1_WITH_RSA
                                0203 TLS_SIGALG_SHA1_WITH_ECDSA
                                0202 TLS_SIGALG_SHA1_WITH_DSA
                                0806 TLS_SIGALG_SHA512_WITH_RSASSA_PSS
                                0805 TLS_SIGALG_SHA384_WITH_RSASSA_PSS
                                0804 TLS_SIGALG_SHA256_WITH_RSASSA_PSS
    ClientAuthType:             Required
    CertValidationMode:         Any
    Renegotiation:              Default
    RenegotiationIndicator:     Optional
    RenegotiationCertCheck:     Off
    3DesKeyCheck:               Off
    ClientEDHGroupSize:         Legacy
    ServerEDHGroupSize:         Legacy
    PeerMinCertVersion:         Any
    PeerMinDHKeySize:           1024
    PeerMinDsaKeySize:          1024
    PeerMinECCKeySize:          192
    PeerMinRsaKeySize:          1024
    ServerScsv:                 Off
    GSK_V3_SESSION_TIMEOUT:     86400
    GSK_V3_SIDCACHE_SIZE:       512
    GSK_SESSION_TICKET_CLIENT_ENABLE:      On
    GSK_SESSION_TICKET_CLIENT_MAXSIZE:     8192
    GSK_SESSION_TICKET_SERVER_ENABLE:      On
    GSK_SESSION_TICKET_SERVER_ALGORITHM:   AESCBC128
    GSK_SESSION_TICKET_SERVER_COUNT:       2
    GSK_SESSION_TICKET_SERVER_TIMEOUT:     300
    GSK_SESSION_TICKET_SERVER_KEY_REFRESH: 300
    HttpCdpEnable:              Off
    HttpCdpProxyServerPort:     80
    HttpCdpResponseTimeout:     15
    HttpCdpMaxResponseSize:     204800
    HttpCdpCacheSize:           32
    HttpCdpCacheEntryMaxsize:   0
    OcspAiaEnable:              Off
    OcspProxyServerPort:        80
    OcspRetrieveViaGet:         Off
    OcspUrlPriority:            On
    OcspRequestSigalg:          0401 TLS_SIGALG_SHA256_WITH_RSA
    OcspClientCacheSize:        256
    OcspCliCacheEntryMaxsize:   0
    OcspNonceGenEnable:         Off
    OcspNonceCheckEnable:       Off
    OcspNonceSize:              8
    OcspResponseTimeout:        15
    OcspMaxResponseSize:        20480
    OcspServerStapling:         Off

Which AT-TLS groups are being used?

I didn’t find this information very useful. It isn’t clear what a group is. The doc says

Use the TTLSGroupAction statement to specify parameters for a Language Environment process required to support secure connections. The TTLSGroupAction statement indicates whether a selected connection should use AT-TLS security.

tso netstat ttls group
tso netstat ttls

MVS TCP/IP NETSTAT CS V2R4       TCPIP Name: TCPIP         
TTLSGrpAction                             Group ID           Conns
----------------------------------------  -----------------  -----
CSQ1-GROUP-ACTION                         0000003F               1
GrpActOff                                 00000040               0
GrpActOn                                  00000041               0
GA1                                       00000042               0

tso netstat ttls group detail

MVS TCP/IP NETSTAT CS V2R4       TCPIP Name: TCPIP         
TTLSGrpAction:   CSQ1-GROUP-ACTION
  GroupID:         0000003F
  Tasks:           4                    GroupConns:      1
  WorkQElements:   0                    SyslogQElements: 0
    Env: CSQ1-INBOUND-ENVIRONMENT-ACTION           EnvConns: 1
TTLSGrpAction:   GrpActOff
  GroupID:         00000040
  Tasks:           4                    GroupConns:      0
  WorkQElements:   0                    SyslogQElements: 0
TTLSGrpAction:   GrpActOn
  GroupID:         00000041
  Tasks:           4                    GroupConns:      0
  WorkQElements:   0                    SyslogQElements: 0
TTLSGrpAction:   GA1
  GroupID:         00000042
  Tasks:           4                    GroupConns:      0
  WorkQElements:   0                    SyslogQElements: 0

Trace PAGENT and AT-TLS

Many components of TCPIP write information to syslogd. This is a process that captures the data sent to it over a UDP socket, and writes it to files in the Unix file system. If the syslogd is not active then messages may be written to the job log. When I was trying to set up AT-TLS, I had 10s of messages on the job log, each time a client tried to use AT-TLS.

The IBM documentation is not very clear, it tells you how to turn on debug, trace etc but does not clearly explain the difference, and when they are used.

It look like the PAGENT job is to take a configuration file, parse it, and pass the data to TCPIP.

If you are using AT-TLS to set up TLS channels, the trace data comes from the TCPIP address space.

Modify the PAGENT address space.

You can pass commands to the PAGENT address space.

Configuration processing.

You can control how much information is logged when parsing configuration statements. The value 127 covers most levels of information (including warnings).

F PAGENT,LOGLEVEL,LEVEL=127

You can use

F PAGENT,TRACE,LEVEL=..
F PAGENT,DEBUG,LEVEL=…

But these do not seem to control the level of trace produced.

Trace PAGENT startup and parse of the configuration

To collect the PAGENT startup and display information on the configuration file as it is processed change the started task JCL to include the -d option.


//PAGENT EXEC PGM=PAGENT,REGION=0K,TIME=NOLIMIT,
// PARM=’ENVAR(“_CEE_ENVFILE_S=DD:STDENV”)/ -d 4

By default the output trace goes to /tmp/pagent.log. It has content like

05/29 17:17:54 EVENT :005: pzos_install_A_PolicyRule: Finished installing policy rule: ‘REMOTE-TO-CSQ1’

Trace PAGENT use of TLS

You can collect the GSK calls made by PAGENT at startup by using the environment variables

GSK_TRACE=0xFF
GSK_TRACE_FILE=/var/log/GSK

You have to format the trace file using

gsktrace /var/log/GSK /var/log/GSK.txt

This has about 40 lines with information like

05/28/2022-17:53:30 Thd-5 INFO crypto_init(): SHA-1 crypto assist is available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): SHA-224 crypto assist is available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): SHA-256 crypto assist is available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): SHA-384 crypto assist is available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): SHA-512 crypto assist is available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): DES crypto assist is available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): DES3 crypto assist is available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): AES 128-bit crypto assist is available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): AES 256-bit crypto assist is available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): AES-GCM crypto assist is available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): Cryptographic accelerator is not available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): Cryptographic coprocessor is available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): Public key hardware support is available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): Max RSA key sizes in hardware – signature 4096, encryption 4096,
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): Maximum RSA token size 3500
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): ECC clear key support is available
05/28/2022-17:53:30 Thd-5 INFO crypto_init(): ECC secure key support is available. Maximum key size 521

Remember this is the PAGENT invoking GSK – but PAGENT does not do any TLS work – this is done by TCPIP.

Trace an AT-TLS connection.

You need to enable trace in the AT-TLS configuration for example

TTLSEnvironmentAction CSQ1-INBOUND-ENVIRONMENT-ACTION
{
HandshakeRole SERVER
TTLSKeyringParmsRef CSQ1-KEYRING
TTLSCipherParmsRef CSQ1-CIPHERPARM
TTLSEnvironmentAdvancedParmsRef CSQ1-ENVIRONMENT-ADVANCED
Trace 255
}

If the syslogd daemon is not configured the output goes to the TCPIP job log.

If the syslogd daemon is configured, you need to have a syslogd configuration with


*.TCPIP.*.* /var/log/TCPIP
*.*.*. /var/log/all

Where TCPIP is the TCPIP address space name, and *.*.*.* is a catch-all. It took me about a day to realize that my trace was being thrown away because I didn’t have TCPIP, and the catch-all.

The trace file has data like

May 29 09:25:30 S0W1 TTLS[67174439]: 09:25:30 TCPIP EZD1284I TTLS Flow GRPID: 00000021 ENVID: 00000009 CONNID: 00000053 RC: 0 Set GSK_USER_DATA(200) – 000000007F280610

May 29 09:25:30 S0W1 TTLS[67174439]: 09:25:30 TCPIP EZD1285I TTLS Data CONNID: 00000053 RECV CIPHER 160303007B

This shows a GSK call was made to GSK_USER_DATA which completed with return code 0, and the connection RECeiVed data which was the CIPHER specs ( 4 chars or 2 chars) 160303007b.

You need to configure the syslogd procedure.

See if SYSLOGD is running, if not, try to start it. If it does not exist…

  • Copy /usr/lpp/tcpip/samples/syslog.conf to its default configuration file /etc/syslog.conf, or another file.
  • Copy TCPIP.SEZAINST(SYSLOGD) to your proclib concatenation.
  • The program uses environment variables defined in STDENV to control operations. The default configuration file location is /etc/syslog.conf

You can configure syslog.conf for example

*.TCPIP.*.* /var/log/%Y/%m/%d/TCPIP
*.SYSLOGD.*.* /var/log/%Y/%m/%d/syslogd
*.err /var/log/%Y/%m/%d/errors

This says all messages for SYSLOGD go to a file like /var/log/2022/05/14/syslogd, and error messages go to /var/log/2022/05/14/errors

This means you get a file of messages for each day. For me, I just used /var/log/syslogd.log and /var/log/errors.log, and deleted them periodically.

I also added a the end of the file, the catchall

*.*.*.* /var/log/all.log

ISPF interface

There is an ISPF syslog browser tool which displays information about the logs, and helps you browse the logs of interest. The documentation for this is not very good.

I got this to work by experimentation. I created an exec like MYSYSLOG

/* Rexx */ 
address ispexec 
"LIBDEF ISPMLIB DATASET ID('TCPIP.SEZAMENU') STACK" 
"LIBDEF ISPPLIB DATASET ID('TCPIP.SEZAPENU') STACK" 
address tso "ALTLIB ACTIVATE APPLICATION(CLIST) 
              DATASET('TCPIP.SEZAEXEC') " 
"SELECT CMD(EZASYRGO) NEWPOOL PASSLIB NEWAPPL(EZAS)" 
address tso "ALTLIB DEACTIVATE APPLICATION(CLIST)" 
"LIBDEF ISPPLIB" 
"LIBDEF ISPMLIB" 

You can execute this from ISPF option 6 or have this built into the ISPF panels.

Originally this exec was called syslogd; when I used it, I got

SYSTEM COMPLETION CODE=4C5 REASON CODE=77A53217

Where 4C5 is TCPIP, and 3217 – the program has the wrong AC (APF related). This is because there is a command syslogd which was executed in preference to my exec. When I renamed the exec to MYSYSLOG it used the exec and it worked fine!

The first panel is

EZASYP01 ----------------- z/OS CS Syslogd Browser ---------------- Row 1 of 1
Command ===>                                                  Scroll ===> PAGE
                                                                               
Enter syslogd browser options                                                  
  Recall migrated data sets ==> NO     (Yes/No) Recall data sets or not        
  Maximum hits to display   ==> 200    (1-99999) Search results to display     
  Maximum file archives     ==> 30     (0-400) Days to look for file archives  
  Display start date/time   ==> YES    (Yes/No) Retrieve start date/time       
  Display active files only ==> NO     (Yes/No) Active files only, no archives 
  DSN Prefix override value ==>                                                
                                                                               
Enter file or data set name of syslogd configuration, or select one from below:
                                                                               
  File/DS Name ==> /etc/syslog.conf
                                                                               
Press ENTER to continue, or press END PF key to exit without a selection       
                                                                               
Line commands: S Select, R Remove from list, B Browse content, E Edit content  
                                                                               
Cmd Recently used syslogd configuration file or data set name                  
--- -------------------------------------------------------------------------- 
    /etc/syslog.conf                                                          
******************************* Bottom of data ********************************

Pressing enter, gave me another panel with

EZASYP00 ----------------- z/OS CS Syslogd Browser ---------------- Row 1 of 6
OPTION ===>                                                   Scroll ===> PAGE
                                                                               
Select one of the following, or press END PF key to exit the syslogd browser   
                                                                               
  1 Change current syslogd configuration file and/or options                   
  2 Guide me to a possible syslogd destination                                 
  3 Clear guide-me hits (indicated by ==> in the Cmd column)                   
  4 Search across all active syslogd files                                     
                                                                               
Current config file ==> /etc/syslog.conf                                      
                                                                               
Line commands: B Browse, A List archives, S Search active file and archives,   
               SF Search active file, SA Search archives, I File/DSN info      
                                                                    Archive    
Cmd Rule/Active UNIX file name                    Start Time        Type Avail.
--- --------------------------------------------- ----------------- ---- ------
    *.SYSLOGD*.*.*                                28 May 2022 13:31 None 0     
    /var/log/syslogd                                                          
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    *.INETD*.*.*                                  Empty       N/A   None 0     
    /var/log/inetd                                                            
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    auth.*                                        Empty       N/A   None 0     
    /var/log/auth                                                             

I could then browse the error log for SYSLOGD.

You can search for userid, strings etc, and give date ranges.

However for my small, one person usage, I found it was easier to use Unix services and use the command

oedit /var/syslogd.log

to edit the file.

Capturing the right data

If the config file you can specify options like

*.TCPIP.*.* /var/log/TCPIP
*.*.*. /var/log/all

The entries are Userid.Jobname.facility.priority.

PAGENT AT-TLS request are reported via TCPIP.

I could not find how to filter the TCPIP data so the AT-TLS data went to one file, and other TCPIP data went to another file. For TCPIP it looks like the “facility” is either “daemon” or “auth”, which you can specify in the TTLS configuration. So not very useful.

Getting AT-TLS and PAGENT to work on z/OS – start here.

With traditional TLS applications, the application code has to issue the requests to use TLS, for example specify the keystore, and which cipher specs to use and does the encryption and decryption of the data. The application then issues TCP send and receive request as usual.

With AT-TLS, the TLS work is moved out of the application and into the TCPIP subsystem. The application just does the normal sends and receives, and TCPIP does the work of establishing the session and handling the encryption. There are rules and policies to define how the session should be established. It uses the PAGENT address space (Policy Agent) to manage the configuration.

Is it easier than having MQ or WAS Liberty do the TLS stuff? – I don’t think so. When it works it is fine. Getting it working is a challenge, because the trace and diagnostics are poor.

My other blog posts on PAGENT and AT-TLS

What is PAGENT?

Having used PAGENT to configure AT-TLS with TCPIP, I see PAGENT is a program which reads configuration information from a file – and gives the configuration to TCPIP. TCP then does the work.

General

It feels that the PAGENT setup and configuration was not designed with the z/OS environment in mind. It “breaks” so many things.

  1. You can have only one PAGENT running per LPAR – even with different name. This means you cannot have a “test” and production PAGENT in the same LPAR.
  2. PAGENT can be configured to have information on:
    1. Common Intrusion detection services (IDS).
    2. Common IP filtering, and manual and dynamic virtual private network (VPN) tunnels (IPSEC).
    3. Common Routing (Policy-based routing enables the TCP/IP stack to make routing decisions that take into account criteria other than just the destination IP address. The additional criteria can include job name, source port, destination port, protocol type (TCP or UDP), source IP address, NetAccess security zone, and multilevel secure environment security label).
    4. AT-TLS Common definitions.
    5. AT-TLS for TCPIP Image level which can have sections on
      1. IDS
      2. IPSec
      3. Qos
      4. Routing
      5. AT-TLS.
  3. As there is only one active PAGENT allowed per LPAR, you have to make your configuration changes to the production PAGENT, refresh it, and fix any configuration errors. The documentation says “make a change to production, if it doesn’t work back out the changes”!
  4. There is one initial configuration file per PAGENT, which can “include” other files. You cannot have a concatenated list of files.
  5. You cannot validate definitions before making them active. The configuration is processed only when the referenced TCPIP stack is active.
  6. Error messages do not have error message numbers, so there is no ability to look up the errors messages.
  7. It lacks good diagnostics. For example
    1. I got error message “Resource temporarily unavailable” when it could not find the security profile “EZB.INITSTACK.*.TCPIP2” on my system. The PAGENT code checks to see if the profile exists and if not, it dies quietly. It does not actually use the security profile which would cause RACF to produce a message saying missing profile.
    2. I deliberately misconfigured a file to use a file that does not exist. It just reported …processing_Stmt_TTLSConfig: processing: ‘ TTLSConfig //’USER.Z24C.TCPPARMS(BLAHBLAH)’ . It should report file not found. Some missing files get “Cannot get FILE handle for information.”

My set up

I could not find any good guidance on setting up PAGENT and AT-TLS, so I’ve documented what I did. It may not be correct…

It took about a day to understand the AT-TLS setup – as I was a typical user with typos etc which slowed me down.

Errors

I naively assumed errors would be reported in //SYSPRINT. On my system they were in /tmp/pagent.log. This file location can be configured with an Environment variable.

The output can be verbose, so I use oedit, and ISPF search

f err 15 25

to find the errors. You may find fields SYSERR or OBJERR.

When errors occur, you do not get file and line number of the error. You have to hunt around. Invalid statements are often just ignored.

With a configuration error the PAGENT job gave me a message on syslog

EZZ8438I PAGENT POLICY DEFINITIONS CONTAIN ERRORS FOR TCPIP : TTLS

In the /tmp/pagent.log file I had

05/30 07:21:12 EVENT :005: pinit_fetch_TTLS_policy_profile: Processing Image TTLS config file: ‘//’USER.Z24C.TCPPARMS(TTLS)” for image ‘TCPIP’

05/30 07:21:12 OBJERR :005: process_TTLS_attribute_table: Unknown attribute ‘ZocalAddr’ for TTLSRule

My common mistakes were

  • spelling errors for example TLSConfig instead of TTLSConfig. (I commented, then uncommented a line and lost the initial T)
  • incorrect dataset names, either the data set, or the member.

Configuration concepts

In the PAGENT configuration file, the AT-TLS specific stuff is like

CommonTTLSConfig //’USER.Z24C.TCPPARMS(TTLSCOM)’
tcpImage TCPIP //’USER.Z24C.TCPPARMS(PAGENT)’
TcpImage TCPIP2 //’USER.Z24C.TCPPARMS(PAGENTT2)’

This defines common stuff for AT-TLS in //’USER.Z24C.TCPPARMS(TTLSCOM)’, and specific TCPIP image in its own file.

The TCPIP specific file has

TTLSConfig //’USER.Z24C.TCPPARMS(TTLS2)’ FLUSH PURGE

This says the TTLS stuff is in the member TTLS2.

You can have the entry without a file or dataset name.

TTLSConfig FLUSH PURGE

This says use the definition in the CommonTTLSConfig.

You need a TTLSConfig, statement, to get AT-TLS definitions configured in the LPAR.

How to update definitions

So I did not break “production” I created a second TCPIP stack (TCPIP2), and created a configuration within PAGENT for the TCPIP2 stack. (This seems a lot of work just to validate some definitions. I raised an RFE on this, but it was declined.

When I was happy with the definitions, I merged them with the the common/production ones.

When I defined a second TCPIP (TCPIP2), the configuration statements were only parsed, when TCPIP2 was started, and so PAGENT produced the error messages once TCPIP2 was active

PAGENT has started – what next?

Pagent operator commands

You can “modify” the PAGENT address space

For example

What is my configuration?

Once you have configured PAGENT you can use the Unix command

pasearch -c 1>a

to give output like

TCP/IP pasearch CS V2R4 Image Name: TCPIP1
Date: 05/23/2022 Time: 17:34:44
PAPI Version: 14 DLL Version: 14
TTLS Policy Object:
ConfigLocation: Local LDAPServer: False
CommonFileName: //'USER.Z24C.TCPPARMS(TTLSCOM)'
ImageFileName: 


TCP/IP pasearch CS V2R4 Image Name: TCPIP2
Date: 05/23/2022 Time: 17:34:44
PAPI Version: 14 DLL Version: 14
TTLS Policy Object:
ConfigLocation: Local LDAPServer: False
CommonFileName: //'USER.Z24C.TCPPARMS(TTLSCOM)'
ImageFileName: //'USER.Z24C.TCPPARMS(TTLS2)'

The command

pasearch -p TCPIP2 1>a

gave the configuration for just the TCPIP stack TCPIP2, including

...
policyRule:             TLSCOM 
  Rule Type:            TTLS 
...
policyRule:             TLSCP3 
  Rule Type:            TTLS 
...
policyRule:             TLSCP4 
  Rule Type:            TTLS 
...

You get the definitions – but you do not know where they came from. I happen to know that TLSCOM comes from the common definition.

A definition can be in both Common and TCPIP Image files.

Instead of relying on PAGENT to report configuration errors I used the Unix command pasearch to display the configuration.

Display the configuration for a TCPIP image

Use the Unix command pasearch to display the configuration.

pasearch -p TCPIP2 >a

Display the object types configured to PAGENT

pasearch -c 1>a d

TCP/IP pasearch CS V2R4 Image Name: TCPIP
Qos Policy Object:…
Ids Policy Object:…
IPSec Policy Object:…
IpFilter Policy Object:…
KeyExchange Policy Object:…
LocalDynVpn Policy Object:…
Routing Policy Object:…
TTLS Policy Object:…

TCP/IP pasearch CS V2R4 Image Name: TCPIP2

For example

TTLS Policy Object:
ConfigLocation: Local LDAPServer: False
CommonFileName: //'ADCD.Z24C.TCPPARMS(TLSPOLY1)'
ImageFileName: //'ADCD.Z24C.TCPPARMS(TLSPOLY1)'
ApplyFlush: True PolicyFlush: True
ApplyPurge: True PurgePolicies: True
AtomicParse: True DeleteOnNoflush: False
DummyOnEmptyPolicy: True ModifyOnIDChange: False
Configured: True UpdateInterval: 1800
TTLS Enabled: True
InstanceId: 1653375346
LastPolicyChanged: Tue May 24 07:55:46 2022

Overall

PAGENT feels like it not of the standard that I would expect z/OS products to have. For example, you cannot validate changes before making them live, and the changes are only validated when the TCPIP stack is active.

This means you are making unvalidated changes to your production system!

Configuring PAGENT for AT-TLS.

I covered the initial set up of PAGNET here.

What does TLS need?

When setting up TLS you need to make decisions, for example

Once you decide on the classification you need to decide which attributes are to be used for example

  • Is TLS to be used or not?
  • What levels of SSL and TLS will be supported?
  • Which keyring is to be used on the z/OS end?
  • Does the server need the client to authenticate and send its certificate?
  • Should there be any constraints on the TLS parameters, such as Cipher Spec, key size etc?
  • The preferred order of cipher specs to be used?
  • Any GSK specific parameters?
  • Should parameters be retrieved from LDAP?
  • Should OCSP be used to validate a certificate?

You can configure PAGENT to map sessions to TLS definitions, by giving rules and configuration data.

You need to create rules to match between the users, and the TLS configuration they get.

You can create rules based on

  • Input port numbers
  • Input IP addresses
  • Output port numbers
  • Output IP addresses
  • Jobnames (on z/OS)
  • Userids (on z/OS)

The starting point for the configuration is a TTLSRULE entry for example.

Some simple rules and associated definitions

TTLSRule TLS1414
{
   LocalPortRange 1414
   TTLSGroupActionRef GrpActOn2
   TTLSEnvironmentActionRef        TNCP3-GrpEnvAct  
}
TTLSRule TLSGRPA
{
   LocalPortRangeRef  MYPORTS
   TTLSGroupActionRef GrpActOn2
   TTLSEnvironmentActionRef        TNCP3-GrpEnvAct  
}
TTLSGroupAction                   GrpActOn2             
{                                                       
  TTLSEnabled                     On
}                                                       
PortRange MYPORTS
{
  Port 2141 2151
}
TTLSGroupAction
{
  TLSKeyringParms...
  Handshake...such as ServerWithClientAuth
  TLSCipherParms...
  Trace...
}

This example shows

  • You can have multiple rules – each with a unique name.
  • You can specify information inline – for example LocalPortRange 1414
  • You can point to a (shared) definition LocalPortRangeRef MYPORTS -> PortRange MYPORTS.
  • Every TTLSRULe needs a group action, and is pointed to by a TTLSGroupActionRef statement
  • A definition group has { } at the start of the line

If you use the pasearch -p TCPIP2 1>a unix command you get can display the configuration for the TCPIP instance, and get output like

policyRule:             TLS1414 
  Rule Type:            TTLS 
  Version:              3                 Status:            Active 
  Weight:               1                 ForLoadDist:       False 
  Priority:             1                 Sequence Actions:  Don't Care 
  No. Policy Action:    2 
  policyAction:         GA1 
   ActionType:          TTLS Group 
   Action Sequence:     0 
  policyAction:         TNCP3-GrpEnvAct 
   ActionType:          TTLS Environment 
   Action Sequence:     0 
  Time Periods: 
     ...
  TTLS Condition Summary:                 NegativeIndicator: Off 
   Local Address: 
    FromAddr:           All 
    ToAddr:             All 
   Remote Address: 
    FromAddr:           All 
    ToAddr:             All 
   LocalPortFrom:       1414              LocalPortTo:       1414 
   RemotePortFrom:      0                 RemotePortTo:      0 
   JobName:                               UserId: 
   ServiceDirection:    Inbound 
  Policy created: Tue May 24 11:01:04 2022 
  Policy updated: Tue May 24 11:01:04 2022
... 
                                                                                                           

Within this output is

TTLS Action:                  GA1 
  Version:                    3 
  Status:                     Active 
  Scope:                      Group 
   TTLSEnabled:                On 
   CtraceClearText:            Off 
   Trace:                      2 
   FIPS140:                    Off 
   TTLSGroupAdvancedParms: 
    SecondaryMap:              Off 
    SyslogFacility:            Daemon 
   Policy created: Tue May 24 11:01:04 2022 
   Policy updated: Tue May 24 11:01:04 2022 

TTLS Action:                  TNCP3-GrpEnvAct 
  Version:                    3 
  Status:                     Active 
  Scope:                      Environment 
    HandshakeRole:              Server 
    SuiteBProfile:              Off 
    TTLSKeyringParms: 
     Keyring:                   TNCP4.TTLS 
...

Where

  • Scope: Group is for the TTLSGroupAction GA1 {} definition
  • Scope: Environment is for the TTLSEnvironmentAction {} definition
  • The keyring is INCP4.TTLS

Changing the configuration

If you change the configuration files you can use the F PAGNET,REFRESH to reprocess the configuration files. You can configure PAGNET to check to see if Unix files have been changed, and do an automatic refresh.

If you have a mistake with your definitions, then the new definitions are not activated. If you stop and restart PGAGENT while the configuration has errors, then you will get no AT-TLS definitions!

Setting up syslogd on z/OS

Many components of TCPIP write information to syslogd. This is a process that captures the data sent to it over a UDP socket, and writes it to files in the Unix file system. If the syslogd is not active then messages may be written to the job log. When I was trying to set up AT-TLS, I had 10s of messages on the job log, each time a client tried to use AT-TLS.

The IBM documentation is not very clear, it tells you how to turn on debug, trace etc but does not clearly explain the difference, and when they are used.

It look like the PAGENT’s job is to take a configuration file, parse it, and pass the configuration data to TCPIP.

If you are using AT-TLS to set up TLS channels, the trace data comes from the TCPIP address space into syslogd.

Configure syslogd

See if SYSLOGD is running, if not, try to start it. If it does not exist…

  • Copy /usr/lpp/tcpip/samples/syslog.conf to its default configuration file /etc/syslog.conf, or another file.
  • Copy TCPIP.SEZAINST(SYSLOGD) to your proclib concatenation.
  • The program uses environment variables defined in STDENV to control operations. The default configuration file location is /etc/syslog.conf .

You can configure syslog.conf for example

*.TCPIP.*.* /var/log/%Y/%m/%d/TCPIP
*.SYSLOGD.*.* /var/log/%Y/%m/%d/syslogd
*.err /var/log/%Y/%m/%d/errors

This says all messages for SYSLOGD go to a file like /var/log/2022/05/14/syslogd, and error messages go to /var/log/2022/05/14/errors

This means you get a file of messages for each day. For me, I just used /var/log/syslogd.log and /var/log/errors.log, and deleted them periodically.

Priority

Data logged to syslogd has a “priority”. For example AT-TLS trace level 32 (Data) have a priority of “debug”. You can use this for example

*.TCPIP.*.debug     /var/log/TCPIPdebug 
*.TCPIP.*.*         /var/log/TCPIP 

This says

  1. for messages from TCPIP with priority debug or higher( debug, info, notice, warning, error, crit, alert, emerg) then write the data to /var/log/TCPIPdebug .
  2. Write all messages to /var/log/TCPIP

As debug is the lowest level of priority, these statements are effectively the same.

It may be better to have

*.TCPIP.*.debug     /var/log/TCPIPdebug 
*.TCPIP.*.warning   /var/log/TCPIP 

The priority can be “none” which means do not log any messages.

How do I capture messages not handled else where?

This is a bit clumsy.

When a message arrives each of the rules are check. If the check is true the message is logged.

You can have compound checks separated by a semicolon for a rule.

For example

*.*.*.* ; *.TCPIP.*.none ; *.PAGENT.*.none /var/log/all.log

This says log all messages – but not from TCPIP or PAGENT. If you have have one file for 20 jobs, you need to have 20 statements with the semicolon.

You can spread the definition over several lines. The semicolon at the end of the line says read next line. The code is not smart enough to put the /var/log/all on its own line, so using a ‘dummy’ may make it easier to maintain.

*.*.*.*; 
       *.TCPIP.*.none; 
       *.PAGENT.*.none;
       *.DUMMY.*.none /var/log/all 

Capturing the right data

If the config file you can specify options like

*.TCPIP.*.* /var/log/TCPIP
*.*.*. /var/log/all

The entries are Userid.Jobname.facility.priority.

PAGENT AT-TLS request are reported via TCPIP.

I could not find how to filter the TCPIP data so the AT-TLS data went to one file, and other TCPIP data went to another file. For TCPIP it looks like the “facility” is either “daemon” or “auth”, which

ISPF interface

There is an ISPF syslog browser tool which displays information about the logs, and helps you browse the logs of interest. The documentation for this is not very good.

I got this to work by experimentation. I created an exec like MYSYSLOG

/* Rexx */ 
address ispexec 
"LIBDEF ISPMLIB DATASET ID('TCPIP.SEZAMENU') STACK" 
"LIBDEF ISPPLIB DATASET ID('TCPIP.SEZAPENU') STACK" 
address tso "ALTLIB ACTIVATE APPLICATION(CLIST) 
              DATASET('TCPIP.SEZAEXEC') " 
"SELECT CMD(EZASYRGO) NEWPOOL PASSLIB NEWAPPL(EZAS)" 
address tso "ALTLIB DEACTIVATE APPLICATION(CLIST)" 
"LIBDEF ISPPLIB" 
"LIBDEF ISPMLIB" 

You can execute this from ISPF option 6 or have this built into the ISPF panels.

Originally this exec was called syslogd; when I used it, I got

SYSTEM COMPLETION CODE=4C5 REASON CODE=77A53217

Where 4C5 is TCPIP’s abend code and 3217 – the program has the wrong Authrorization Code (APF related). This is because there is a command syslogd which was executed in preference to my exec. When I renamed the exec to MYSYSLOG it used the exec and it worked fine!

The first panel is

EZASYP01 ----------------- z/OS CS Syslogd Browser ---------------- Row 1 of 1
Command ===>                                                  Scroll ===> PAGE
                                                                               
Enter syslogd browser options                                                  
  Recall migrated data sets ==> NO     (Yes/No) Recall data sets or not        
  Maximum hits to display   ==> 200    (1-99999) Search results to display     
  Maximum file archives     ==> 30     (0-400) Days to look for file archives  
  Display start date/time   ==> YES    (Yes/No) Retrieve start date/time       
  Display active files only ==> NO     (Yes/No) Active files only, no archives 
  DSN Prefix override value ==>                                                
                                                                               
Enter file or data set name of syslogd configuration, or select one from below:
                                                                               
  File/DS Name ==> /etc/syslog.conf
                                                                               
Press ENTER to continue, or press END PF key to exit without a selection       
                                                                               
Line commands: S Select, R Remove from list, B Browse content, E Edit content  
                                                                               
Cmd Recently used syslogd configuration file or data set name                  
--- -------------------------------------------------------------------------- 
    /etc/syslog.conf                                                          
******************************* Bottom of data ********************************

Pressing enter, gave me another panel with

EZASYP00 ----------------- z/OS CS Syslogd Browser ---------------- Row 1 of 6
OPTION ===>                                                   Scroll ===> PAGE
                                                                               
Select one of the following, or press END PF key to exit the syslogd browser   
                                                                               
  1 Change current syslogd configuration file and/or options                   
  2 Guide me to a possible syslogd destination                                 
  3 Clear guide-me hits (indicated by ==> in the Cmd column)                   
  4 Search across all active syslogd files                                     
                                                                               
Current config file ==> /etc/syslog.conf                                      
                                                                               
Line commands: B Browse, A List archives, S Search active file and archives,   
               SF Search active file, SA Search archives, I File/DSN info      
                                                                    Archive    
Cmd Rule/Active UNIX file name                    Start Time        Type Avail.
--- --------------------------------------------- ----------------- ---- ------
    *.SYSLOGD*.*.*                                28 May 2022 13:31 None 0     
    /var/log/syslogd                                                          
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    *.INETD*.*.*                                  Empty       N/A   None 0     
    /var/log/inetd                                                            
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    auth.*                                        Empty       N/A   None 0     
    /var/log/auth                                                             

I could then browse the error log for SYSLOGD.

You can search for userid, strings etc, and give date ranges.

However for my small, one person usage, I found it was easier to use Unix services and use the command

oedit /var/syslogd.log

to edit the file.

you can specify in the TTLS configuration. So not very useful.

Getting TCPIP syslogd working, and tracing PAGENT

Many components of TCPIP write information to syslogd. This is a process that captures the data sent to it over a UDP socket, and writes it to files in the Unix file system. If the syslogd is not active then messages may be written to the job log. When I was trying to set up AT-TLS, I had 10s of messages on the job log, each time a client tried to use AT-TLS.

You need to configure the syslogd procedure.

See if SYSLOGD is running, if not, try to start it. If it does not exist…

  • Copy /usr/lpp/tcpip/samples/syslog.conf to its default configuration file /etc/syslog.conf, or another file.
  • Copy TCPIP.SEZAINST(SYSLOGD) to your proclib concatenation.
  • The program uses environment variables defined in STDENV to control operations. The default configuration file location is /etc/syslog.conf

You can configure syslog.conf for example

*.SYSLOGD.*.* /var/log/%Y/%m/%d/syslogd
*.err /var/log/%Y/%m/%d/errors

This says all messages for SYSLOGD go to a file like /var/log/2022/05/14/syslogd, and error messages go to /var/log/2022/05/14/errors

This means you get a file of messages for each day. For me, I just used /var/log/syslogd.log and /var/log/errors.log, and deleted them periodically.

ISPF interface

There is an ISPF syslog browser tool which displays information about the logs, and helps you browse the logs of interest. The documentation for this is not very good.

I got this to work by experimentation. I created an exec like MYSYSLOG

/* Rexx */ 
address ispexec 
"LIBDEF ISPMLIB DATASET ID('TCPIP.SEZAMENU') STACK" 
"LIBDEF ISPPLIB DATASET ID('TCPIP.SEZAPENU') STACK" 
address tso "ALTLIB ACTIVATE APPLICATION(CLIST) 
              DATASET('TCPIP.SEZAEXEC') " 
"SELECT CMD(EZASYRGO) NEWPOOL PASSLIB NEWAPPL(EZAS)" 
address tso "ALTLIB DEACTIVATE APPLICATION(CLIST)" 
"LIBDEF ISPPLIB" 
"LIBDEF ISPMLIB" 

You can execute this from ISPF option 6 or have this built into the ISPF panels.

Originally this exec was called syslogd; when I used it, I got

SYSTEM COMPLETION CODE=4C5 REASON CODE=77A53217

Where 4C5 is TCPIP, and 3217 – the program has the wrong AC (APF related). This is because there is a command syslogd which was executed in preference to my exec. When I renamed the exec to MYSYSLOG it used the exec and it worked fine!

The first panel is

EZASYP01 ----------------- z/OS CS Syslogd Browser ---------------- Row 1 of 1
Command ===>                                                  Scroll ===> PAGE
                                                                               
Enter syslogd browser options                                                  
  Recall migrated data sets ==> NO     (Yes/No) Recall data sets or not        
  Maximum hits to display   ==> 200    (1-99999) Search results to display     
  Maximum file archives     ==> 30     (0-400) Days to look for file archives  
  Display start date/time   ==> YES    (Yes/No) Retrieve start date/time       
  Display active files only ==> NO     (Yes/No) Active files only, no archives 
  DSN Prefix override value ==>                                                
                                                                               
Enter file or data set name of syslogd configuration, or select one from below:
                                                                               
  File/DS Name ==> /etc/syslog.conf
                                                                               
Press ENTER to continue, or press END PF key to exit without a selection       
                                                                               
Line commands: S Select, R Remove from list, B Browse content, E Edit content  
                                                                               
Cmd Recently used syslogd configuration file or data set name                  
--- -------------------------------------------------------------------------- 
    /etc/syslog.conf                                                          
******************************* Bottom of data ********************************

Pressing enter, gave me another panel with

EZASYP00 ----------------- z/OS CS Syslogd Browser ---------------- Row 1 of 6
OPTION ===>                                                   Scroll ===> PAGE
                                                                               
Select one of the following, or press END PF key to exit the syslogd browser   
                                                                               
  1 Change current syslogd configuration file and/or options                   
  2 Guide me to a possible syslogd destination                                 
  3 Clear guide-me hits (indicated by ==> in the Cmd column)                   
  4 Search across all active syslogd files                                     
                                                                               
Current config file ==> /etc/syslog.conf                                      
                                                                               
Line commands: B Browse, A List archives, S Search active file and archives,   
               SF Search active file, SA Search archives, I File/DSN info      
                                                                    Archive    
Cmd Rule/Active UNIX file name                    Start Time        Type Avail.
--- --------------------------------------------- ----------------- ---- ------
    *.SYSLOGD*.*.*                                28 May 2022 13:31 None 0     
    /var/log/syslogd                                                          
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    *.INETD*.*.*                                  Empty       N/A   None 0     
    /var/log/inetd                                                            
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    auth.*                                        Empty       N/A   None 0     
    /var/log/auth                                                             

I could then browse the error log for SYSLOGD.

You can search for userid, strings etc, and give date ranges.

However for my small, one person usage, I found it was easier to use Unix services and use the command

oedit /var/syslogd.log

to edit the file.

Capturing the right data

If the config file you can specify options like

*.TCPIP.*.* /var/log/TCPIP
*.*.*. /var/log/all

The entries are Userid.Jobname.facility.priority.

PAGENT AT-TLS request are reported via TCPIP.

I could not find how to filter the TCPIP data so the AT-TLS data went to one file, and other TCPIP data went to another file. For TCPIP it looks like the “facility” is either “daemon” or “auth”, which you can specify in the TTLS configuration. So not very useful.

Tracing the z/OS ZFS file system, and using ZFS commands.

I was looking into a little Java problem, and wanted to know which files were being used by my Java program. The “obvious” answer was a trace – but the IBM documentation was about 8 years out of date!

The key lesson from this post is to use commands like

f OMVS,PFS=ZFS,… instead of MODIFY ZFS,… if you have ZFS in your OMVS address space.

zFS running in the z/OS UNIX address space says

In releases before z/OS V2R2, the amount of 31-bit virtual storage that was needed by both z/OS UNIX and zFS combined would have exceeded the size of a 2 GB address space. Due to that size limitation, zFS and z/OS UNIX could not coexist in the same address space.

In z/OS V2R2, zFS caches are moved above the 2 GB bar into 64-bit storage. You can now choose to have zFS run in its own colony address space or in the address space that is used by z/OS UNIX, which is OMVS.

When running zFS in the OMVS address space, each file system vnode operation (such as creating a directory entry, removing a directory entry, or reading from a file) will have better overall performance. Each operation will take the same amount of time while inside zFS itself. The performance benefit occurs because z/OS UNIX can call zFS for each operation in a more efficient manner.

Some inherent differences exist when zFS is run in the OMVS address space.

MODIFY commands must be passed to zFS through z/OS UNIX. Use the form MODIFY OMVS,pfs=zfs,cmd. For more information, see the section on passing a MODIFY command string to a physical file system (PFS) through a logical file system (LFS) in z/OS MVS System Commands. This form of the MODIFY command can be used whether zFS is in its own address space or in the OMVS address space.

Issuing commands

So when the documentation says issue a command

Steps for tracing on zFS

If you are re-creating a problem and need to collect a zFS trace, use the following steps:

1. Allocate the trace output data set as a PDSE, RECFM=VB, LRECL=133 with a primary allocation of at least 50 cylinders and a secondary allocation of 30 cylinders.

2. Define the zFS trace output data set to zFS by either using the IOEFSPRM trace_dsn option, or dynamically by using the zfsadm config -trace_dsn command. If you use the IOEFSPRM option, zFS must be stopped and then restarted to pick up the change, unless you also dynamically activate the trace output data set with the zfsadm config -trace_dsn command.

3. When you are ready to re-create the problem, reset the zFS trace table using the MODIFY ZFS,TRACE,RESET command.

4. Re-create the problem.

5. Enter the MODIFY ZFS,TRACE,PRINT command. This formats and prints the trace table to the PDSE defined on the trace_dsn option.

You still use the Unix command to define the output destination of the trace

zfsadm config -trace_dsn ‘IBMUSER.ZFSTRACE’

but you use the following console command to cause the trace to be formatted to the file from the internal buffer.

f OMVS,PFS=ZFS,TRACE,PRINT

Easy when you know how…

Why can’t I delete the data set?

I had some data sets which I could not delete from ISPF 3;4 as I got

IEC614I SCRATCH FAILED – RC 008, DIAGNOSTIC INFORMATION IS (04060020) ..

where the error code is

04060020 – Verification of SMS flags failed; caller indicates data set is not SMS-managed, but FMT4 DSCB indicates that it is an SMS volume. This error might be caused by a damaged catalog entry. Issuing the recatalog command might clear this error.

I tried to use various DFDSS commands such move, or backup delete, but these failed on the delete.

DATA SET BACKUP.D210201.COLIN.JCL ON VOLUME A4USR1 NOT SCRATCHED, 2-08,02 

IGD17040I ERROR IN DADSM PROCESSING ON VOLUME A4USR1 FOR DATA SET  
BACKUP.D210201.COLIN.JCL HISTORIC RETURN CODE IS 8 DIAGNOSTIC INFORMATION IS 04060020              
IGD306I UNEXPECTED ERROR DURING IGGDAS02 PROCESSING RETURN CODE 4 REASON CODE 32                                             

This all looked pretty broken – until I found an easy command

//S1 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DELETE BACKUP.D210118.USER.Z24A.CLIST
/*

That worked! Having found one way of doing it – I could take it to the next level using the MASK option.

//S1 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DELETE BACKUP.D210215.** MASK
/*

This gave me

DELETE BACKUP.D210215.** MASK
IDC0550I ENTRY (A) BACKUP.D210215.ADCD.C.SOURCE DELETED
IDC0550I ENTRY (A) BACKUP.D210215.COLIN.C DELETED
IDC0550I ENTRY (A) BACKUP.D210215.COLIN.JCL DELETED
IDC0550I ENTRY (A) BACKUP.D210215.COLIN.RACF DELETED
IDC0550I ENTRY (A) BACKUP.D210215.COLIN.WLM DELETED
IDC0550I ENTRY (A) BACKUP.D210215.IBMUSER.JCL DELETED
IDC0550I ENTRY (A) BACKUP.D210215.IBMUSER.MQ.JCL DELETED
IDC0550I ENTRY (A) BACKUP.D210215.USER.Z24A.CLIST DELETED
IDC0550I ENTRY (A) BACKUP.D210215.USER.Z24A.PARMLIB DELETED
IDC0550I ENTRY (A) BACKUP.D210215.USER.Z24A.PROCLIB DELETED
IDC0550I ENTRY (A) BACKUP.D210215.USER.Z24A.TCPPARMS DELETED
IDC0550I ENTRY (A) BACKUP.D210215.USER.Z24A.VTAMLST DELETED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

I thought this was pretty useful!

Just be a bit careful and do not say DELETE BACKUP.* MASK

How not to use SMS and other DFP opportunties

I wanted to unterse a file, and use DFDSS to restore the datasets. This pretty trivial task had a few problems, and I learned a few things from it. (Well, to be accurate, I fell over the same problems as last time I did it, but I hadn’t bother writing down the solutions.)

Running out of space

My original JCL to unterse a file was

//S1 EXEC PGM=AMATERSE,PARM=UNPACK
//SYSPRINT DD SYSOUT=*
//SYSUT2 DD DSN=COLIN.UNTRS,SPACE=(CYL,(100,100)),DISP=(,PASS)

This gave me

IGD17272I VOLUME SELECTION HAS FAILED FOR INSUFFICIENT SPACE FOR
DATA SET COLIN.UNTRS
JOBNAME (COLINMQ3) STEPNAME (S1 )
PROGNAME (AMATERSE) DDNAME (SYSUT2 )
REQUESTED SPACE QUANTITY = 83003 KB
STORCLAS (SCBASE) MGMTCLAS ( ) DATACLAS ( )
STORGRPS (SGBASE SGEXTEAV )

This was annoying as I had plenty of disks space – but not in the SMS storage groups listed.

I fixed this by allocating the dataset outside of SMS. I used

//SYSUT2 DD DSN=COLIN.UNTRS,SPACE=(CYL,(100,100)),DISP=(NEW,CATLG),
// VOL=SER=C4PRD3,UNIT=3390,STORCLAS=SCNOSMS

See One Minute SMS for more information.

DFDSS restore challenges

Having unzipped my file I needed to restore it to create the data sets. I used

//S2 EXEC PGM=ADRDSSU,REGION=0M
//SYSPRINT DD SYSOUT=*
//D1 DD DISP=SHR,DSN=.S1.SYSUT2
//DD1 DD DISP=SHR,DSN=COLIN.UNTRS
//SYSIN DD *
RESTORE –
IMPORT –
INDDNAME(DD1) –
CANCELERROR –
DATASET(INCLUDE()) – RENAMEU( – (.SCSQANLC,COLIN.MQ930.SCSQANLC) –

) –
SHARE –
NULLMGMTCLAS –
NULLSTORCLAS –
CATALOG

/*

It took several goes to get right. Once it was partially working, I got return code 8 because data sets existed.

I tried using REPLACE, but this did not work

REPLACE only applies if the data set is not being renamed. REPLACEUNCONDITIONAL should be used when renaming a data set and a
preallocated target data set should be replaced.

Restoring the datasets had problems.

The job had two steps

  1. Unterse the dataset into a temporary data set
  2. Restore from the temporary data set and recreate the libraries

Depending on the SMS setup this may not work.

If the temporary file was allocated to VIO (a Virtual data set using virtual memory), the DFDSS restore job failed with a message INPUT DEVICE TYPE IS INVALID FOR TASK. I guess the code checks to see if the data set is on a 3390 or tape drive ? If not – then it must be an error!

If a real data set was used (non VIO), it worked.

The error messages were

ADR101I (R/I)-RI01 (01), TASKID 001 HAS BEEN ASSIGNED TO COMMAND ‘RESTORE ‘
ADR109I (R/I)-RI01 (01), 2022.145 13:25:30 INITIAL SCAN OF USER CONTROL STATEMENTS COMPLETED
ADR025E (001)-DEVSU(03), INPUT DEVICE TYPE IS INVALID FOR TASK
ADR017E (001)-CLTSK(01), 2022.145 13:25:30 TASK NOT SCHEDULED DUE TO ERROR. TASK RETURN CODE 0008
ADR012I (SCH)-DSSU (01), 2022.145 13:25:30 DFSMSDSS PROCESSING COMPLETE. HIGHEST RETURN CODE IS 0008 FROM: TASK 001

When I used

//SYSUT2 DD DSN=COLIN.UNT,SPACE=(CYL,(200,200)),DISP=(NEW,CATLG),
// VOL=SER=(C4USS2,C4USS1),UNIT=3390,STORCLAS=SCNOSMS

The job worked fine with return code 0.

The name of the storage class is site dependent. Other storage classes may work. My ACS routine has the following.

WHEN (&DSTYPE = 'TEMP' && &SIZE < 2000001KB)     
  DO                                             
    SET &STORGRP = 'SGVIO','SGBASE','SGEXTEAV'   
    EXIT CODE(0)                                 
  END                                            

There are different sorts of Storage Groups

  • Pool – list of disks which can be used
  • VIO – when Virtual IO (paging) it to be used.

You need to pick a storage group associated with a Pool.

Setting up Python on z/OS

Running a Python package on z/OS is pretty easy. You just have to remember to set up the environment. This one of those little tasks you do not do very often, and forget how to do it.

When you enter OMVS your .profile shell is executed (if the file exists).

Does the file exist ?

You can use the ls command to see if the file exists

ls -altr ~/.profile

where the -a option says display all the files – including those beginning with ‘.’. By default these are omitted.

This gave

-rwx------ 1 BPXROOT TSOUSER 297 May 18 08:46 /u/colin/.profile

Note the x attribute; it means the file can be executed. You can use the following command to set this attribute.

chmod +x ~/.profile

Profile contents

My .profile file has

# set up Python path 
export PATH=/usr/lpp/IBM/cyp/v3r8/pyz/bin:$PATH 
# set up MQ Libraries
export MQ=MQM.V900 
export STEPLIB=$MQ.SCSQANLE:$MQ.SCSQANLE:$MQ.SCSQAUTH:$STEPLIB 
# set up PYTHONPATH to point to where zpymqi is
export PYTHONPATH=/u/colin/:$PYTHONPATH 
      

When my Python program has import pymqi, Python will look in directory /u/colin/pymqi