HPlogo X25/9000: X.25/9000 Programmer's Guide > Chapter 5  Receiving and Transmitting Out-of-Band Information

Transmitting Out-of-Band Events

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Index

There are three types of out-of-band events that can be sent by the X.25 application: CLEAR packets, RESET packets, and INTERRUPT packets. These packets can be sent at any time as the needs of the program dictate. While Chapter 3 “ Establishing and Terminating a Socket Connection” discussed the use of the close() system call for the transmission of CLEAR packets, this chapter covers the use of the cause and diagnostic codes, as well as the facilities and user data fields.

Clearing a Switched Virtual Circuit

An SVC can be cleared when one of the processes that use it (X.25 or the network provider) issues a CLEAR REQUEST packet. A CLEAR REQUEST packet can be sent by the X.25 application (with a close() call) otherwise it will be sent if the process terminates without executing a close() call.

Once a CLEAR REQUEST packet is issued, data cannot be sent or received over the connection because the connection is destroyed. The X.25 application can control the contents of certain data fields in the CLEAR REQUEST packet. These fields and the ioctl() calls which control them are:

  • cause code—ioctl(X25_WR_CAUSE_DIAG)

  • diagnostic code—ioctl(X25_WR_CAUSE_DIAG)

  • facilities—ioctl(X25_WR_FACILITIES)

  • user data—ioctl(X25_WR_USER_DATA)

All of these calls must be issued prior to the close() call. The ioctl(X25_WR_CAUSE_DIAG) and ioctl(X25_WR_USER_DATA) calls are described below. The ioctl(X25_WR_FACILITIES) call is described in Chapter 6 “Extended Features”.

The ioctl(X25_WR_CAUSE_DIAG) Call

The cause code that is sent depends upon the cause code specified with the ioctl(X25_WR_CAUSE_DIAG)call and the network type specified during X.25 interface configuration. The table below summarizes cause code settings.

Table 5-2 Setting Cause Codes

Network Type

Cause Specified

Cause Sent

DTE 84

any

as specified

DCE (1980 or 1984)

any

as specified

DTE 80

any

0

 

The ioctl(X25_WR_CAUSE_DIAG) call must be issued prior to a RESET or CLEAR packet in order to set cause and diagnostic codes.

NOTE: When using this call over a PDN (Public Data Network) avoid using the same cause codes as those already employed by the network. This will facilitate eventual troubleshooting by eliminating ambiguity regarding the originator of RESET packets.

Syntax for ioctl(X25_WR_CAUSE_DIAG)

The ioctl(X25_WR_CAUSE_DIAG) call and its parameters are described below.

#include <x25/x25ioctls.h>
#include <x25/x25str.h>
/* struct x25_cause_diag {
* u_char x25_cd_loc_rem;
* u_char x25_cd_cause;
* u_char x25_cd_diag;
* }
*/
int err;
int sd;
struct x25_cause_diag diag;
err = ioctl(sd, X25_WR_CAUSE_DIAG, &diag);
sd

A socket descriptor for an SVC socket.

X25_WR_CAUSE_DIAG

The definition for the request.

diag

Indicates the cause and diagnostic codes to be sent.

err

Upon successful completion, err is set to 0. Otherwise, a value of -1 is returned and errno is set to indicate the error.

The ioctl(X25_WR_USER_DATA) Call

The ioctl(X25_WR_USER_DATA) call is used to write data to the user data fields in CLEAR REQUEST, CALL REQUEST, and CALL ACCEPTED packets. Call acceptance must be in effect before the call can be used on a CALL ACCEPTED packet. You can use this call in any of the these three situations:

  • Before issuing a connect() call (to write call user data to the CALL REQUEST packet).

  • Before issuing an ioctl(X25_SEND_CALL_ACCEPT)call when call-accept approval is in effect on the listen() socket (to write call user data to the CALL ACCEPTED packet).

  • Before issuing a close() call (to write clear user data to the CLEAR REQUEST packet, when the fast select facility must be in effect), or shutdown() with the how parameter set to 1 or 2.

NOTE: The call user data field in CALL REQUEST and CALL ACCEPTED packets can be up to 16 bytes unless the fast select facility is specified. In which case it may contain up to 128 bytes. When the fast select facility has been specified, the clear user data field of a CLEAR REQUEST packet may contain 128 bytes of data.

The ioctl(X25_RD_USER_DATA) call cannot be used to read data previously written with the ioctl(X25_WR_USER_DATA) call.

Syntax for ioctl(X25_WR_USER_DATA)

The ioctl(X25_WR_USER_DATA) call and its parameters are described below.

#include <x25/x25ioctls.h>
#include <x25/x25str.h>
/* define X25_MAX_CU_LEN 126
* struct x25_userdata {
* u_char x25_cud_len;
* u_char x25_cud_data[X25_MAX_CU_LEN];
* }
*/
int err;
int sd;
struct x25_userdata udata;
err = ioctl(sd, X25_WR_USER_DATA, &udata);
sd

A socket descriptor for an SVC socket.

X25_WR_USER_DATA

The definition for the request.

udata

Contains the length and the data for the user data field (x25_cud_data). The maximum length is 126 bytes. If you want to send more than this, the ioctl() call must be called again. Usually the maximum length of the call user data field is 16 bytes. If the fast select facility is specified, the maximum length of the call user data field is 128 bytes.

err

Upon successful completion, err is set to 0. Otherwise, a value of -1 is returned and errno is set to indicate the error.

WARNING! Avoid using 0xCC in the first byte of the call user data field. If this is not possible, the interface must not be used for X.25/IP. If the first byte of an incoming call's call user data field contains 0xCC, and it arrives over an X.25 interface which has been assigned an IP address (see the x25init command in your X.25/9000 User's Guide), then the X.25 subsystem will assume the call is meant for the X.25/IP interface, and not the programmatic access interface.

The ioctl(X25_RD_USER_DATA) Call

The ioctl(X25_RD_USER_DATA) call can read any data in the clear user data field of a CLEAR INDICATION packet or the call user data field of an incoming CALL INDICATION or CALL CONNECTED packet. This call is best used with the ioctl(X25_NEXT_MSG_STAT) call. The ioctl(X25_NEXT_MSG_STAT) call can determine whether call user data is available in the next message, and whether or not clear user data is available.

There may not be any user data available or there may only be clear or call user data available. Also both clear and call user data may be available. Use ioctl(X25_NEXT_MESG_STAT) to determine if both are available. If both call user data and clear user data are available, you should issue an ioctl(X25_RD_USER_DATA) call sequence to read the call user data first, until ioctl(X25_NEXT_MSG_STAT) says there is no longer call user data available, then issue an additional ioctl(X25_RD_USER_DATA) call sequence to read the clear user data.

The ioctl(X25_RD_USER_DATA) call can read a maximum of 126 bytes of call or clear user data (one byte must contain the length) per ioctl() call. If more than 126 bytes of call or clear user data is received, the ioctl(X25_RD_USER_DATA) must be called, until returned buffer length is 0.

Syntax for ioctl(X25_RD_USER_DATA)

The syntax for the ioctl(X25_RD_USER_DATA) call and its parameters are described below.

#include <x25/x25ioctls.h>
#include <x25/x25str.h>
/* struct x25_userdata {
* u_char x25_cud_len;
* u_char x25_cud_data[X25_MAX_CU_LEN];
*/ }
int err;
int sd;
struct x25_userdata udata;
err = ioctl(sd, X25_RD_USER_DATA, &udata);
sd

A socket descriptor for an SVC socket over which a CLEAR INDICATION packet, CALL INDICATION packet, or CALL CONNECTED packet has been received.

X25_RD_USER_DATA

The definition for the request.

udata

Contains the length of and data for the user data field, where the maximum length is 126 bytes. If there is more than 126 bytes of call or clear user data, the ioctl() must be called, until udata.x25_cud_len is 0.

err

Upon successful completion, err is set to 0. Otherwise, a value of -1 is returned and errno is set to indicate the error.

The code example below shows how to use the ioctl(X25_RD_USER_DATA) call to obtain the data from a CALL or CLEAR packet.

struct x25_userdata userdata;
struct x25_msg_stat msgstat;
unsigned char call_udata[128], clear_udata[128];
int i, call_ndata = 0,clear_ndata = 0, error = 0;
while ( !error )
{
error = ioctl(s, X25_NEXT_MSG_STAT, &msgstat);
if (error< 0 ) {
perror("ioctl(X25_NEXT_MSG_STAT) failed");
exit(1);
}
if (msgstat.x25_msg_flags & (1 << X25_CA_DATA_AVAIL))
{
error = ioctl(s, X25_RD_USER_DATA, &userdata);
if (error != 0)
{
perror("X25_RD_USER_DATA returned error");
break;
}
if (userdata.x25_cud_len == 0) break;
for (i = 0; i < userdata.x25_cud_len; i++)
call_udata[call_ndata++] =
userdata.x25_cu_data[i];
}else break;
}
/*
* If error = 0 at this point all of the call data is now
in "call_udata".
* "call_ndata" gives the number of bytes of data.
*/
while ( !error )
{
error = ioctl(s, X25_NEXT_MSG_STAT, &msgstat);
if (error != 0 )
{
perror("ioctl(X25_NEXT_MSG_STAT) failed");
exit(1);
}
if (msgstat.x25_msg_flags & (1 << X25_CL_DATA_AVAIL))
{
error = ioctl(s, X25_RD_USER_DATA, &userdata);
if (error != 0)
{
perror("X25_RD_USER_DATA returned error");
break;
}
if (userdata.x25_cud_len == 0) break;
for (i = 0; i < userdata.x25_cud_len; i++)
clear_udata[clear_ndata++] =
userdata.x25_cu_data[i];
}else break;
}
/*
* If error = 0 at this point all of the clear data is now
in "clear_udata".
* "clear_ndata" gives the number of bytes of data.
*/

Resetting a Virtual Circuit

This section describes how to send RESET packets. A RESET packet clears all data on a connection, including any inbound data queued but not yet read, while maintaining the virtual circuit. The user application must be prepared to handle RESET packets; the handling of RESET packets at the application level is not defined by X.25. RESET packets can be generated by the X.25 subsystem, by the application processes on either side of the VC, or by the network provider.

If the user application wants to send a RESET packet, the application can set a cause code and diagnostic code with the ioctl(X25_WR_CAUSE_DIAG) call, then issue a RESET packet with the ioctl(X25_RESET_VC). The ioctl(X25_WR_CAUSE_DIAG) call is described above under "Clearing a Switched Virtual Circuit".

The ioctl(X25_RESET_VC) Call

The ioctl(X25_RESET_VC) call sends a RESET REQUEST packet over the virtual circuit. A VC cannot be reset before a connection is established or after a connection has been cleared.

When a user application resets a circuit, and blocking I/O is in effect, the application is blocked until a RESET CONFIRMATION packet is received.

The X.25 subsystem sends a RESET CONFIRMATION packet when the application reads the RESET out-of-band event without the MSG_PEEK flag set.

If nonblocking I/O is in effect, the ioctl(X25_RESET_VC) call does not block the caller. When the RESET CONFIRMATION packet arrives and the socket is in the nonblocking state, an out-of-band event (OOB_RESET_CONF) is placed in the socket's out-of-band queue. Also, SIGURG is sent to the process, which must have a signal handler installed for the SIGURG signal and enabled the socket to transmit SIGURG signals.

Syntax for ioctl(X25_RESET_VC)

The ioctl(X25_RESET_VC) and its parameters are described below.

int err;
int sd;
err = ioctl(sd, X25_RESET_VC, 0);
sd

A socket descriptor for an SVC socket.

X25_RESET_VC

The definition for the request which cause a RESET packet to be sent on the VC.

0

A dummy parameter for the system call.

err

Upon successful completion, err is set to 0. Otherwise, a value of -1 is returned and errno is set to indicate the error.

WARNING! All X.25 applications should be designed to handle out-of-band information. Failure to do so can cause SVCs to be cleared and PVCs to become unusable until your application process is killed.

Sending Interrupts on a VC

An INTERRUPT packet can be sent at any time by either side of a VC after call connection has been established.

X.25 supports sending up to 32 bytes of interrupt data in an INTERRUPT packet.

To send an INTERRUPT packet, issue the send() system call with the MSG_OOB flag set. If blocking I/O is being used, the application process remains blocked until the INTERRUPT CONFIRMATION packet is received. If nonblocking I/O is being used, the confirmation is received as an out-of-band event (00B_VC_INTERRUPT_CONF). See Chapter 4 “ Sending and Receiving Data” for a description of how to send interrupt data.

NOTE: CCITT 1980 X.25 networks and equipment only support one byte of interrupt data. If your X.25 interface is configured in the x25init(1M) network type file as 1980 version, and you attempt to send more than 1 byte of interrupt data, an EMSGSIZE error will be returned. If the network provider will not support more than 1 byte of interrupt data, and you try to send more, the circuit will be reset. The network type file is described in your X.25/9000 User's Guide.