Al Brajnikoff, IBM TPF Development
The two Mapping of Airline Traffic over Internet Protocol
(MATIP) releases (APAR PJ26161 on PUT 9 and APAR PJ26963 on PUT 11)
provide a number of user exits that you need to customize for MATIP
to work correctly. The user exits divide into two types: those for
TPF as a server and those for TPF as a client. Naturally, some
exits are used for both directions of message flow.
Server User Exits
MATIP message traffic is handled identically as much as
possible, irrespective of message type. When a TPF server receives
a Type-A Conversational session open request from a MATIP client,
the session manager code checks the number of agent set control
units (or ASCUs) that are being defined by the incoming client
request. If the number of ASCUs passed by the client side is zero,
the session manager calls the ASCU List user exit, UMATAS,
to see whether there are ASCUs predefined for the sort of message
that is requesting the session. Type-A host-to-host and Type-B
sessions do not pass ASCU lists and, therefore, skip this user
exit.
Our list of ASCUs (two-byte ASCUlist) in the example is very
simple, but yours might be more complex depending on your ACSA/A2CS
configuration. For instance, we define some 2-byte ASCUs, we say
how many there are in the list (11), we copy the list into a
pointer to a pointer to char supplied by the caller, and return the
number of ASCUs in the list.
unsigned short two_byte_ASCUlist[20] = {0x0100, 0x0902, 0x1501,
0x0903, 0x1305, 0xD404,
0xD004, 0xD202, 0xFE16,
0x0901, 0xD001, 0};
:
if (ASCU_size == 2)
{
numASCUs = 11;
*list = (unsigned char *)malloc (numASCUs * 2);
memcpy (*list, two_byte_ASCUlist, numASCUs * 2);
:
return(numASCUs);
The ASCUlist that is returned is added to the session definition
and will be used for more transmissions for this session. An
ASCUlist can also be read into main storage from offline storage
during MATIP start. This ASCUlist is defined using the ZMATP DEFINE
and ZMATP ADD functional messages (commands).
If the number of ASCUs is not zero or if the session open
request is for Type-A host-to-host or Type-B sessions, the Security
user exit, UMATSE, is called.
The IP address and session-type-specific information (ASCUlist,
H1H2, or flow ID) for the remote client is passed to the Security
exit. The Security exit contains code that ensures TPF servers only
start sessions with recognized remote hosts.
Type-A Conversational sessions present a list of ASCUs to the
user exit while Type-A host-to-host and Type-B sessions present the
IP address of the remote host and either H1H2 or resource
identifier to the user exit. The Security user exit goes through
the information and selects only those ASCUs that are defined. The
ASCUs not found in the user exit list are removed from the list of
acceptable ASCUs and are added to a reject list. The rejected ASCUs
are not validated for the session. Both lists are returned to the
caller when the user exit is completed, along with the number of
ASCUs in each list. If there are ASCUs to be rejected, they are
included in the Session Open Response with an indication that they
were not defined in the session. If all ASCUs are acceptable, the
list of acceptable ASCUs is returned to the remote host.
Type-A host-to-host and Type-B sessions are easier to verify
because they have only the IP address and either the H1H2 or
resource identifier to verify against. If the incoming IP address
for the remote client is not in a list with the correct
characteristic, the session request is rejected. A return code
indicates whether the remote host is acceptable or not.
When a MATIP inbound session is open and data is flowing, other
user exits come into play. One is the flow identifier user exit,
UMATFI. This exit is for Type-A host-to-host messages and it
allows messages to be distinguished from each other so that
journaling (logging) can be performed. The types of hosts
distinguished during UMATFI include IATA host-to-host
traffic subtype and SITA host-to-host traffic subtype.
When a destination (an LNIATA) cannot be determined from the
MATIP session block or the data packet for a message, the Assign
LNIATA user exit, UMATAL, is called to determine one. The
UMATAL user exit is especially important for IP Bridge
devices. This user exit is also used for outbound (client) Type-A
Conversational sessions with 4-byte ASCUs. In the following example
for Type-A Conversational sessions, the H1H2, A1A2, and terminal
address (TA) characteristics are searched for in the table. If they
are found, the LNIATA associated with them is returned for use. If
not found, the Router user exit is called if the message packet is
inbound. If an outbound Type-A Conversational session cannot
determine an LNIATA, the message packet is dropped.
#define CONVERSATIONAL_LNIATAS { \
{0x1111, 0x2205, 0x01, 0x00D40404}, \
{0x1111, 0x2205, 0x02, 0x00D40405}, \
{0x1111, 0x2205, 0x03, 0x00D40406}, \
{0x1111, 0x2205, 0x04, 0x00D00404}, \
:
struct conv_lniata
{
unsigned short H1H2;
unsigned short A1A2;
unsigned char TA;
unsigned int lniata;
};
:
struct conv_lniata table[] = CONVERSATIONAL_LNIATAS;
:
for (i = 0; i < MAXCONV_LNIATAS; i++)
{
if (table[i].H1H2 == msg_ID->H1H2)
{
if (table[i].A1A2 == msg_ID->A1A2)
{
if (memcmp (&table[i].TA, &msg_ID->TA, 1) == 0)
{
*lniata = table[i].lniata;
i = MAXCONV_LNIATAS;
found = 1;
} /* end if TA's are equal */
} /* end if A1A2's are equal */
} /* end if H1H2's are equal */
The Router user exit, UMATRO, is called when routing
cannot be determined by the UMATAL user exit. For Type-A
host-to-host and Type-B messages, the Router user exit identifies
an associated application on the basis of H1H2 and flow ID or
high-level designator (HLD). By analyzing this information in the
Router user exit, routing can be done without requiring
applications to have WGTA table entries. The easiest way to do this
is to call the appropriate application directly in the
UMATRO user exit.
Before the messages are routed to their appropriate
applications, they are shuttled through the Translation user exit,
UMATTR. This user exit translates message text from the
encoding specified when the session was opened to the EBCDIC
encoding. The possible encodings are padded Baudot, IPARS, and
ASCII. Similarly, for outbound messages, the translation takes
place from EBCDIC to what was specified during session open.
UMATTR could be used to make translations to and from other
code pages as well. For this, translation would use EBCDIC as
either the source or the target depending on the direction of
message flow.
Client User Exits
When TPF acts as a client, it starts outbound traffic to a
remote host. Some of the same user exits we have already seen come
into play as well as some new ones. When a message is routed from a
TPF application for the first time to a MATIP device, a new session
is started. To start this session, an association between an LNIATA
and a host name is used to determine where to send the message. An
LNIATA can be associated with a host name in the Check Host user
exit, UMATCH.
#define LNIATA_TBL { \
{0x00123456, "HOST1.POK.IBM.COM" }, \
{0x00555555, "HOST2.POK.IBM.COM" }, \
{0, "" } } ;
:
STRUCT MATIP_IP_addr typea_table[] = LNIATA_TBL ;
:
host_rec = (struct host_record *) NULL ;
/* search type a table */
if (host_rec == (struct host_record *) NULL)
{
iii = 0 ;
while (iii >= 0)
{
if (typea_table[iii].h_lniata == lniata)
{
host_rec =
lookup_host(typea_table[iii].hostname) ;
if (host_rec != NULL)
return (host_rec) ;
}
++iii ;
if (typea_table[iii].h_lniata == 0) iii = -1 ;
} ;
}
return (NULL) ;
In the previous example there are two hosts and two LNIATAs
listed. The code goes through the list of LNIATAs looking for the
one that was passed. If the passed LNIATA is found, the host
associated with it is checked by looking it up in the online MATIP
host name table. If the host has been defined to MATIP previously,
a pointer to the host record in the table is returned to the
caller. The host record contains, among other things, a 256-byte
area for users. This user exit is one place where this user area
could be manipulated.
When the Check Host user exit returns, the remote host is
verified to be on the network by doing address resolution on the
host name. Its current IP address is requested from the name server
as well. The IP address and LNIATA are given to the Session Start
user exit, UMATSS, to pick up the MATIP characteristics for
the session being opened.
In the example that follows, the Type-A Conversational sessions
are listed according to their LNIATAs. The LNIATA table is searched
for an LNIATA specified by the caller. Once found, the IP address,
session type, session ID (H1H2), encoding, subtype, and
multiplexing characteristics are set for the session from the table
data. Similar code can be written for Type-A host-to-host and
Type-B sessions. For Type-A host-to-host and Type B, the IP address
is used as the distinguishing characteristic.
struct MATIP_lniata
{
unsigned int h_lniata;
unsigned int h_ipaddr;
unsigned int h_session_type;
unsigned int h_session_ID;
char h_encoding;
char h_subtype;
char h_multiplex;
};
:
#define CONV_LNIATA { \
{0x00D40103, 0x0975935C, 0x42, 0x00001111, 0x02, 0x01, 0x01},\
{0x00D40104, 0x0975938B, 0x42, 0x00001111, 0x02, 0x01, 0x02},\
{0x00D40105, 0x09756BBD, 0x42, 0x00001111, 0x02, 0x01, 0x00},\
:
struct MATIP_lniata table[] = CONV_LNIATA;
:
for (i = 0; i < MAX_LNIATA; i++)
{
if (table[i]. h_lniata == *lniata)
{
Ip_addr = table[i].h_ipaddr;
*session_type = table[i].h_session_type;
memcpy(session_ID, &(table[i].h_session_ID), 4);
*encoding = table[i].h_encoding;
*subtype = table[i].h_subtype;
*multiplex = table[i].h_multiplex;
i = MAX_LNIATA;
rc = 0;
}
:
Outbound (client) Type-A Conversational sessions define their
ASCUlists during the Assign LNIATA user exit just as inbound
(server) ones do. So, the UMATAL user exit is called during
Session Open for TPF clients as well as for TPF servers.
Why MATIP user exits? The MATIP user exits provide customers
with strong control over the configuration and the security of
their MATIP network.