When I was young I was told that if you cannot say something good about anyone, then do not say anything; or to put it another way; focus on the positive and not the negative. Here goes…
Configuring TCPIP on z/OS
In general, some of the requirements for making changes include:
- Being able to undo or back-out a change
- Make the smallest change necessary
- Changes should be simple to implement
- Have changes being worked on in parallel
- You implement the same change in production that was tested in earlier stages, so no typing.
- Only authorised people are allowed to make changes.
What is good about TCPIP configuration
- When I configured my first TCPIP system, I thought that it was easy to configure. Since then, working with more complex changes, my views have changed.
- You can use system symbols, so you can have one configuration across many systems, and exploit symbols like SYSNAME=MVS1, or SYSNAME=MVS2. Of course where there are multiple instances of &SYSNAME – they all get the same value, which makes it even easier to configure!
How does it work
In the TCPIP procedure JCL are statements like
//SYSTCPD DSN=ADCD.Z25A.TCPPARMS(TCPDATA),DISP=SHR //PROFILE DISP=SHR,DSN=ADCD.Z25A.TCPPARMS(PROF2)
SYSTCPD is used by clients or servers. This has information about how to use TCPIP: (including which TCPIP, if there is more than one).
DOMAINORIGIN DAL-EBIS.IHOST.COM TCPIPJOBNAME TCPIP DATASETPREFIX TCPIP
PROFILE is used to configure the links, connections etc of the TCPIP address space. The remainder of the post is about configuring this dataset.
In the profile you can define:
- IP V4 route statements
- IP V6 route statements
- Which hardware connections to use, and what IP addresses these have.
- Reserved ports
- Startup trace configuration.
Conceptually this profile is one large file, but you can use includes such as
to include specific files or members. But you cannot have
BEGINRoutes include user.Z25A.tcpparms(routeinc) ENDRoutes
because each major statement has to be totally within one file.
Operator commands to change the configuration
As well as the profile you can alter the configuration by using the operator command, such as
The syntax command checks the syntax of the statements, and allows you to fix any syntax problems before you use the OBEY command.
Note: The syntax check does not check for consistency or pre requirements. I had a request which passed the syntax check but failed because a VTAM resource was not present.
You can have include files like
INTERFACE IFPORTCP6 DELETE INTERFACE IFPORTCP6 DEFINE IPAQENET6 CHPIDTYPE OSD PORTNAME PORTCP INTFID 7:7:7:7 BEGINRoutes ; Destination SubnetMask FirstHop LinkName Size ROUTE 172.25.1.0 255.255.255.0 = IFPORTCP MTU 1492 ROUTE DEFAULT 172.25.1.6 IFPORTCP MTU 1492 ROUTE 2a00::/64 IFPORTCP6 MTU 1 ENDRoutes START IFPORTCP6
This is typical of the documentation, as it is a nice self contained example. It:
- deletes an interface
- defines an interface
- defines some routes – how to route packets to different systems
- starts the interface
This is OK for a simple, one user, type of system.
You can use commands like
to manage resources.
The command syntax is a bit strange, rather than v tcpip,start…, or v tcpipprd,start.. you have to specify v tcpip,tcpipprd,start – passing the name of the TCPIP job as the second parameter.
Simplistic change control
You can change the file, and restart TCPIP to pick up the changes.
Better change control
To make a change
If you put sections in a file or member, you can change the member and use obeyfile command on the file. For example have a file called user.tcpip(route1)
BEGINRoutes ; Destination SubnetMask FirstHop LinkName Size ROUTE 172.25.1.0 255.255.255.0 = IFPORTCP MTU 1492 ROUTE DEFAULT6 fe00:: IFPORTCP6 MTU 1492 ENDRoutes
To make a change, (to replace all the static routes)
- you copy this to user.tcpip.old(route1).
- make the change
- use v tcpip,,syntax,user.tcpip(route1)
- use v tcpip,,obey,user.tcpip(route1)
If it does not work, you use obey,user.tcpip.old(route1) to undo the change, and then fix the problem.
Two stage changes
Some changes need a delete followed by a define. There is no define replace.
If you have a delete… define… in one file, this may fail because the delete is asynchronous, and the operation is ongoing after the delete command has finished. The define then fails because the object still exists.
The best way of configuring seems to be:
- Have the define statement in one file, which can be included in the TCPIP startup profile, or used in an OBEY command;
- Have a file with the matching delete in a file which is used in an obey command
- At startup the define file is used.
- To modify it, use two commands, obeyfile… delete, obeyfile… define .
Production change control
Things you may need to consider when making changes:
- There are often changes made in parallel, for example from different departments. Some of these changes can be made independently of each other. Others changes, like beginroutes… endroutes, need to be coordinated, and done serially.
- If you are using system variables, for example a statement like
- HOME &HOMEIPADDRESS1 ETH1,
- you will need to define/change the symbol on each system and activate the resource.
Where you need to be careful.
The size of the change.
When you define static routes (between BEGINROUTES and ENDRoutes) if you want to change it, you replace all of the definitions; you cannot add or delete individual routes.
It seems that a userid which is authorised to issue the OBEY command, can issue the command against any file, so could use
VARY TCPIP,,OBEY,EVIL.PERSON.CONFIG(change) ,
and so someone can issue an an unauthorised change. With VTAM, an authorised operator, can only activate a member in a PDS – not use a random PDS member. You can control who can update datasets in the VTAMLST concatentation. This gives better protection.
To give a userid OBEYFILE access use RACF definitions
RDEFINE OPERCMDS MVS.VARY.TCPIP.OBEYFILE UACC(NONE) PERMIT MVS.VARY.TCPIP.OBEYFILE ACCESS(CONTROL) CLASS(OPERCMDS) GROUP(CSYSPR)
This command seems to give authority to the obeyfile command in all address spaces, eg TCPIP, TCPIP1 etc.
I could not find a way of giving a userid permission on one TCPIP image, and no permission on another TCPIP image.
It is hard to make a small change
I wanted to make a small change to the reserved ports.
If this was VTAM, with JCL like
//VTAMLST DD DISP=SHR,DSN=USER.Z25A.VTAMLST // DD DISP=SHR,DSN=ADCD.Z25A.VTAMLST
where my local customising is in USER.VTAMLST and the IBM provided customising is in ADCD.VTAMLST. To make a change, I add the entry to USER.VTAMLST. I do not change the IBM provided stuff. When I upgrade to a newer level, I use the updated version of ADCD.VTAMLST and my changes are still in USER.VTAMLST.
With the TCPIP approach, I have to change the IBM configuration, if only to point to my user.TCPPARMS file.
I had to update ADCD.TCPPARMS(PROF2). When a new level is available, I have to look at the dates, and compare the members, and reapply my changes! Not just a simple step.
If it had been me, I would have conditional includes so you would have
include USER.Z25A.TCPPARMS(ports) cond include ADCD.Z25A.TCPPARMS(ports) required
where I put my configuration of TCPIP port numbers in the user…tcpparms(ports). If this member is not found, it produces a warning. When adcd…tcpparms(ports) is processed, it adds to my port definitions. If this file does not exist, and required is specified, then TCPIP does not start up.
Of course TCPIP configuration would also have to change to allow two or more BEGINROUTES…ENDROUTES sections.
Overall, the configuration is not too bad. I think VTAM configuration works well. Once you are used to the different syntax used by TCPIP commands, TCPIP is OK, but it does feel like extra typing! I would rather have “add route” and “delete route” instead of having to replace all of the static routes. It goes against the “minimum change” aspect of change control.
I do wonder why TCPIP did a completely different configuration interface to VTAM – but it will not change now.