[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP TCP/IP Services for OpenVMS
Sockets API and System Services Programming


Previous Contents Index

  1. The $QIO(IO$_ACCESS|IO$M_ACCEPT) function establishes the connection with the client.
  2. The IO$WRITEVBLK function specifies the address of the return buffer in p1, and the length of the return buffer in p2.
  3. You can also specify a list of write buffers by omitting the p1 and p2 parameters and instead passing the list of buffers as the p5 parameter.
  4. When writing a list of buffers, the p5 parameter is used; when reading a list, the p6 parameter is used. For information about specifying input parameter lists, see Section 5.5.1.

2.14 Writing OOB Data (TCP Protocol)

If your application uses TCP, you can send out-of-band (OOB) data to a remote process. At the remote process, the message is delivered to the user through either the data receive or the OBB data receive mechanism. You can write only 1 byte of OOB data at a time.

2.14.1 Writing OOB Data (Sockets API)

To send OOB data to a remote process, use the MSG_OOB flag with the send() , sendmsg() , and sendto() functions.

Example 2-22 shows a TCP server using the MSG_OOB flag with the send() routine.

Example 2-22 Writing OOB Data (Sockets API)

/* This program accepts a connection on TCP port 1234, sends the string,
   "Hello, world!", waits two seconds, sends an urgent BEL (^G), waits
   another two seconds, repeats the Hello message, and terminates. */

#include <types.h>
#include <in.h>
#include <socket.h>
#include <unixio.h>

#define PORTNUM 123
main() {
   struct sockaddr_in lcladdr;
   int r, s, one = 1;
   char *message = "Hello, world!\r\n",
        *oob_message = "\007";
   memset()

   lcladdr.sin_family = AF_INET;
   lcladdr.sin_addr.s_addr = INADDR_ANY;
   lcladdr.sin_port = htons(PORTNUM);
   if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) perror("socket");
   if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)))
      perror("setsockopt");
   if (bind(s, &lcladdr, sizeof(lcladdr))) perror("bind");
   if (listen(s, 1)) perror("listen");
   if ((r = accept(s, 0, 0)) < 0) perror("accept");
   if (send(r, message, strlen(message), 0) != strlen(message))
      perror("send");
   sleep(2);
   if (send(r,(1) oob_message,(2) strlen(oob_message),(3) MSG_OOB (4)) !=
              strlen(oob_message)) perror("send");
   sleep(2);
   if (send(r, message, strlen(message), 0) != strlen(message))
      perror("send");
   sleep(2);
   if (close(r)) perror("close");
   if (close(s)) perror("close");
}

The send() routine is used to send OOB data to a remote socket, as follows:

  1. r specifies the remote socket descriptor connected to the local socket as a result of a call to the socket() routine.
  2. oob_message is the buffer containing the OOB data.
  3. strlen(oob_message) specifies the length, in bytes, of the buffer containing the out-of-band data.
  4. MSG_OOB is the flag that indicates the data will be sent out of band.

2.14.2 Writing OOB Data (System Services)

To send out-of-band data to a remote process, use the IO$_WRITEVBLK function with the IO$M_INTERRUPT modifier. Example 2-23 shows a TCP server using the TCPIP$C_MSG_OOB flag.

Example 2-23 Writing OOB Data (System Services)

/*
**
**  Attempt to send Out Of Band data to a previously established network
**  connection. Use the function code of IO$_WRITEVBLK, passing the address
**  of the buffer to P1, and the OOB code, TCPIP$C_MSG_OOB, to P4.
**
*/
    OOBBuff = 7;
    sysSrvSts = sys$qiow( 0,                /* efn.v | 0              */
                          IOChannel,        /* chan.v                 */
                   (1)     IO$_WRITEVBLK,    /* func.v                 */
                          &iosb,            /* iosb.r | 0             */
                          0, 0,             /* astadr, astprm: UNUSED */
                   (2)     &OOBBuff,         /* p1.r IO buffer         */
                          1,                /* p2.v IO buffer  size   */
                          0,                /* p3 UNUSED              */
                   (3)     TCPIP$C_MSG_OOB,  /* p4.v IO options flag   */
                          0, 0              /* p5, p6 UNUSED          */
                       );
    if((( sysSrvSts & 1  ) != 1 ) || /* Validate the system service status. */
       ((  iosb.cond_value & 1  ) != 1))  /* Validate the IO status. */
        {
        cleanup( IOChannel );
        errorExit( sysSrvSts, iosb.cond_value );
        }
    else
        if( iosb.count == 0 )
            printf( "    FAILED to send the OOB message, no connection.\n" );
        else
            printf( "    SUCCEEDED in sending the OOB message.\n" );

This example writes the data that is in the buffer.

  1. Use the IO$_WRITEVBLK function to send OOB data.
  2. Specify the buffer address of the OOB data in p1 and the length of the buffer in p2.
  3. Specify the TCPIP$C_MSG_OOB flag to indicate the type of data, in p4.

2.15 Sending Datagrams (UDP Protocol)

An application that uses UDP can send a datagram to a remote host, send broadcast datagrams to multiple remote hosts, or send multicast datagrams to members of a group.

With broadcasting, you send datagrams in one operation to multiple remote hosts on the specified subnetwork. With multicasting, you send datagrams in one operation to all hosts that are members of a particular group. The member hosts can be located on the local network or on remote networks, as long as the routers are configured to support multicasting.

2.15.1 Sending Datagrams (System Services)

You can use either of the following methods to send datagrams:

  • To send datagrams from the local host to one remote host, use the $QIO system service with the IO$_ACCESS modifier. This allows you to specify the remote socket name once, and then to use the IO$_WRITEVBLK routine to send each datagram without specifying the socket name again.
  • To send datagrams from the local host to several remote hosts, use the $QIO system service with the IO$_WRITEVBLK routine, and specify the remote socket name in the p3 argument field.

2.15.2 Sending Broadcast Datagrams (Sockets API)

You can broadcast datagrams by calling the sendto() function.

2.15.3 Sending Broadcast Datagrams (System Services)

To broadcast datagrams, use a $QIO system service command with the IO$_WRITEVBLK routine.

Before issuing broadcast messages, the application must issue the IO$_SETMODE function. This sets the broadcast option in the socket. The process must have SYSPRV, BYPASS, or OPER privilege to issue broadcast messages. However, the system manager can disable privilege checking by using the management command SET PROTOCOL UDP /BROADCAST. For more information, refer to the HP TCP/IP Services for OpenVMS Management Command Reference guide.

2.15.4 Sending Multicast Datagrams

To send IP multicast datagrams, specify the IP destination address in the range of 224.0.0.0 to 239.255.255.255 using the IO$_WRITEVBLK routine or the sendto() Sockets API function. Make sure you include the IN.H header file.

The system maps the specified IP destination address to the appropriate Ethernet or FDDI multicast address before it transmits the datagram.

You can control multicast options by specifying the following arguments to the setsockopt() Sockets API, or the IO$SETMODE system service.

  • Time to Live (TTL)
    IP_MULTICAST_TTL (Sockets API)
    TCPIP$C_IP_MULTICAST_TTL (OpenVMS system services)
    Specifies the distance the multicast datagrame will travel as an integer value between 0 and 255.
    Value Result
    0 Restricts distribution to applications running on the local host.
    1 Forwards the multicast datagram to hosts on the local subnet.
    1---255 With a multicast router attached to the sending host's network, forwards multicast datagrams beyond the local subnet.
      Multicast routers forward the datagram to known networks that have hosts belonging to the specified multicast group. The TTL value is decremented by each multicast router in the path. When the TTL value reaches 0, the datagram is no longer forwarded.

    For example:


    u_char ttl;
    ttl=2;
    
    if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
             sizeof(ttl)) == -1)
     perror("setsockopt");
    
  • Multicast interface
    IP_MULTICAST_IF (Sockets API)
    TCPIP$C_MULTICAST_IF (OpenVMS system services)
    Specifies a network interface other than that specified by the route in the kernel routing table.
    Unless the application specifies that an alternate network interface is associated with the socket, the datagram addressed to an IP multicast destination is transmitted from the default network interface. The default interface is determined by the interface associated with the default route in the kernel routing table or by the interface associated with an explicit route, if one exists.
    For example:


    int sock;
    
    struct in_addr ifaddress;
    
    char *if_to_use = "16.141.64.251";
    .
    .
    .
    
      ifaddress.s_addr = inet_addr(if_to_use);
    
      if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &ifaddress,
    
                                  sizeof(ifaddress)) == -1)
    
         perror ("error from setsockopt IP_MULTICAST_IF");
    
      else
    
         printf ("new interface set for sending multicast datagrams\n");
    
  • Disable loopback
    IP_MULTICAST_LOOP (Sockets API)
    TCPIP$C_MULTICAST_LOOP (OpenVMS system services)
    If a multicast datagram is sent to a group of which the sending host is a member, a copy of the datagram is looped back by the IP layer for local delivery (default). To disable loopback delivery, specify the loop value as 0.
    For example:


    u_char loop=0;
    if (setsockopt( sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop
             sizeof(loop)) == -1)
     perror("setsockopt");
    

    To enable loopback delivery, specify a loop value of 1. For improved performance, HP recommends that you disable loopback unless the host must receive copies of the datagrams.

For a complete list of socket options, see Appendix A.

2.16 Using the Berkeley Internet Name Domain Service

The Berkeley Internet Name Domain (BIND) service is a host name and address lookup service for the Internet. If BIND is enabled on your system, you can make a call to the BIND resolver to obtain host names and addresses.

Typically, you make a call to the BIND resolver either before you bind a socket or before you make a connection to a socket. You can also use this service to translate either the local or remote host name to an address before making a connection.

2.16.1 BIND Lookups (Sockets API)

If the BIND resolver is enabled on your system and the host name is not found in the local database, you can use either of the following functions to search the BIND database:

  • gethostbyaddr() gets a host record from the local host or BIND database when given the host address.
  • gethostbyname() gets a host record from the local host or BIND database when given the host name.

The host record contains both name and address information.

Example 2-24 shows how to use the gethostname() , gethostbyname() , and gethostbyaddr() functions to find a local host name and address.

Example 2-24 BIND Lookup (Sockets API)


#include <in.h>                     /* define internet related constants,   */
                                    /* functions, and structures            */
#include <inet.h>                   /* define network address info          */
#include <netdb.h>                  /* define network database library info */
#include <stdio.h>                  /* define standard i/o functions        */
#include <stdlib.h>                 /* define standard library functions    */

int main( void )
{
    char host[1024];
    struct in_addr addr;
    struct hostent *hptr;
    /*
     * get name of local host
     */
    if ( (gethostname(host, sizeof(host))) < 0 )  (1)
        {
        perror( "Failed to get host's local name" );
        exit( EXIT_FAILURE );
        }

    printf( "Local hostname: %s\n", host );

    /*
     * lookup local host record by name
     */

    if ( !(hptr = gethostbyname(host)) )   (2)
        {
        perror( "Failed to find record for local host" );
        exit( EXIT_FAILURE );
        }

    addr.s_addr = *(int *) HPtr->h_addr;
    printf( "Official hostname: %s  address: %s\n",
            HPtr->h_name, inet_ntoa(addr) );

    /*
     * lookup local host record by address
     */

    HPtr = gethostbyaddr( &addr.s_addr, sizeof(addr.s_addr), AF_INET );  (3)
    if ( !hptr )
        {
        perror( "Failed to find record for local host" );
        exit( EXIT_FAILURE );
        }

    printf( "Back-translated hostname: %s\n", HPtr->h_name );

    exit( EXIT_SUCCESS );
}

In this example, the following functions and arguments were used to find a local host name and address:

  1. gethostname() gets the local host name.
    host is the address of the buffer that receives the host name.
    sizeof(host) is the size of the buffer that receives the host name.
  2. gethostbyname() looks for the host record that has the specified name.
    On successful return of the gethostbyname() function, hptr receives the address of a hostent structure containing the host name, alias names, host address type, length of address (4 or 16), and an array of IPv4 addresses of the host being sought.
  3. gethostbyaddr() looks for the host record that has the specified address.
    addr.s_addr specifies the address of the host being sought. It points to a series of bytes in network order, not to an ASCII string.
    sizeof(addr.s_addr) specifies the number of bytes in the address to which the first argument points.
    AF_INET points to the IPv4 Internet address family.

2.16.2 BIND Lookups (System Services)

If BIND is enabled on your system, the IO$_ACPCONTROL system service searches the BIND database for the host name if it does not find the name in the local host database.

Example 2-25 shows how to use OpenVMS system services to find a host name and address.

Example 2-25 BIND Lookup (System Services)


#include <descrip.h>                /* define OpenVMS descriptors           */
#include <efndef.h>                 /* define 'EFN$C_ENF' event flag        */
#include <in.h>                     /* define internet related constants,   */
                                    /* functions, and structures            */
#include <inet.h>                   /* define network address info          */
#include <iodef.h>                  /* define i/o function codes            */
#include <netdb.h>                  /* define network database library info */
#include <ssdef.h>                  /* define system service status codes   */
#include <starlet.h>                /* define system service calls          */
#include <stdio.h>                  /* define standard i/o functions        */
#include <stdlib.h>                 /* define standard library functions    */
#include <string.h>                 /* define string handling functions     */
#include <stsdef.h>                 /* define condition value fields        */
#include <tcpip$inetdef.h>          /* define tcp/ip network constants,     */
                                    /* structures, and functions            */

struct iosb
    {                                   /* i/o status block                 */
    unsigned short status;              /* i/o completion status            */
    unsigned short bytcnt;              /* bytes transferred if read/write  */
    void *details;                      /* address of buffer or parameter   */
    };

struct acpfunc
    {                                   /* acp subfunction                  */
    unsigned char code;                 /* subfunction code                 */
    unsigned char type;                 /* call code                        */
    unsigned short reserved;            /* reserved (must be zero)          */
    };


int main( void )
{
    char host[1024];
    char hostent[2048];
    struct in_addr addr;
    struct hostent *hptr;

    struct iosb iosb;                   /* i/o status block                 */
    unsigned int status;                /* system service return status     */
    unsigned short channel;             /* network device i/o channel       */

(1)  struct acpfunc func_byaddr =        /* acp gethostbyaddr function code  */
        { INETACP_FUNC$C_GETHOSTBYADDR, INETACP$C_HOSTENT_OFFSET, 0 };

    struct acpfunc func_byname =        /* acp gethostbyname function code  */
        { INETACP_FUNC$C_GETHOSTBYNAME, INETACP$C_HOSTENT_OFFSET, 0 };

    struct dsc$descriptor p1_dsc =      /* acp function descriptor          */
        { 0, DSC$K_CLASS_S, DSC$K_DTYPE_T, 0 };

    struct dsc$descriptor p2_dsc =      /* acp p2 argument descriptor       */
        { 0, DSC$K_CLASS_S, DSC$K_DTYPE_T, 0 };

    struct dsc$descriptor p4_dsc =      /* acp p4 argument descriptor       */
        { 0, DSC$K_CLASS_S, DSC$K_DTYPE_T, 0 };

    $DESCRIPTOR( inet_device,           /* string descriptor with logical   */
                 "TCPIP$DEVICE:" );     /* name of network pseudodevice     */

    /*
     * get name of local host
     */

    if ( (gethostname(host, sizeof(host))) < 0 )
        {
        perror( "Failed to get host's local name" );
        exit( EXIT_FAILURE );
        }

    printf( "Local hostname: %s\n", host );
    /*
     * assign i/o channel to network device
     */

    status = sys$assign( &inet_device,      /* device name                  */
                         &channel,          /* i/o channel                  */
                         0,                 /* access mode                  */
                         0                  /* not used                     */
                       );

    if ( !(status & STS$M_SUCCESS) )
        {
        printf( "Failed to assign i/o channel\n" );
        exit( status );
        }

    /*
     * lookup local host record by name
     */

(2)  p1_dsc.dsc$w_length  = sizeof(func_byname);
    p1_dsc.dsc$a_pointer = (char *) &func_byname;

    p2_dsc.dsc$w_length  = strlen( host );
    p2_dsc.dsc$a_pointer = host;

    p4_dsc.dsc$w_length  = sizeof(hostent);
    p4_dsc.dsc$a_pointer = hostent;
(3)
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                       channel,             /* i/o channel                  */
                       IO$_ACPCONTROL,      /* i/o function code            */
                       &iosb,               /* i/o status block             */
                       0,                   /* ast service routine          */
                       0,                   /* ast parameter                */
                       &p1_dsc,             /* p1 - acp subfunction code    */
                       &p2_dsc,             /* p2 - hostname to lookup      */
                       &p4_dsc.dsc$w_length,/* p3 - return length address   */
                       &p4_dsc,             /* p4 - output buffer address   */
                       0,                   /* p5                           */
                       0                    /* p6                           */
                     );

    if ( status & STS$M_SUCCESS )
        status = iosb.status;

    if ( !(status & STS$M_SUCCESS) )
        {
        printf( "Failed to find record for local host\n" );
        exit( status );
        }
    HPtr = (struct hostent *) hostent;
    HPtr->h_name += (unsigned int) HPtr;
    *(char **) &hptr->h_addr_list += (unsigned int) HPtr;
    *(char **) HPtr->h_addr_list  += (unsigned int) HPtr;

    addr.s_addr = *(int *) HPtr->h_addr;
    printf( "Official hostname: %s  address: %s\n",
            HPtr->h_name, inet_ntoa(addr) );

    /*
     * lookup local host record by address
     */

    p1_dsc.dsc$w_length  = sizeof(func_byaddr);
    p1_dsc.dsc$a_pointer = (char *) &func_byaddr;

    p2_dsc.dsc$w_length  = strlen( inet_ntoa(addr) );
    p2_dsc.dsc$a_pointer = inet_ntoa( addr );

    p4_dsc.dsc$w_length  = sizeof(hostent);
    p4_dsc.dsc$a_pointer = hostent;
(4)
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                       channel,             /* i/o channel                  */
                       IO$_ACPCONTROL,      /* i/o function code            */
                       &iosb,               /* i/o status block             */
                       0,                   /* ast service routine          */
                       0,                   /* ast parameter                */
                       &p1_dsc,             /* p1 - acp subfunction code    */
                       &p2_dsc,             /* p2 - ip address to lookup    */
                       &p4_dsc.dsc$w_length,/* p3 - return length address   */
                       &p4_dsc,             /* p4 - output buffer address   */
                       0,                   /* p5                           */
                       0                    /* p6                           */
                     );

    if ( status & STS$M_SUCCESS )
        status = iosb.status;

    if ( !(status & STS$M_SUCCESS) )
        {
        printf( "Failed to find record for local host\n" );
        exit( status );
        }

    HPtr = (struct hostent *) hostent;
    HPtr->h_name += (unsigned int) HPtr;

    printf( "Back-translated hostname: %s\n", HPtr->h_name );

    /*
     * deassign i/o channel to network device
     */

    status = sys$dassgn( channel );
    if ( !(status & STS$M_SUCCESS) )
        {
        printf( "Failed to deassign i/o channel\n" );
        exit( status );
        }

    exit( EXIT_SUCCESS );
}

This example looks up nodes by either host name or IP address.


Previous Next Contents Index