Network interface operations for IPv4 and IPv6 on AIX Version 5.3

Introduction

File descriptors are low-level interfaces to input and output. Descriptors might represent a connection to a device, pipe, or a socket for communicating with another process or to a normal file. The I/O control (ioctl) function calls manipulate underlying device parameters of special files. They perform control functions associated with open file descriptors. The commands cover files, streams, generic data link control, and various other devices.

This article discusses the commands associated with network operations and sockets available on AIX® Version 5.3. The socket-related commands and structures are listed in:

  • sys/ioctl.h
  • net/if_arp.h
  • net/if.h
  • net/netopt.h
  • netinet/in.h

These commands are exposed to application developers, and the commands are described in detail in the AIX Version 5.3 documentation. This article explains typical usage for a few commonly used commands for Internet Protocol version 6 (IPv6) addresses and the Internet Protocol version 4 (IPv4) stack.

Working with ioctl socket control options

Typically, network programs require information about all the network interfaces and IP addresses available on the system. The futuristic applications are now enabled for dual stack support for both IPv4 and IPv6. The ioctl structures require appropriate traversal and manipulation of pointers to handle the differences in length between the IPv4 and IPv6 address (in addition to using appropriate socket structure: sockaddr_in6 or sockaddr_storage).

AIX Version 5.3 provides a long list of ioctl socket control options to extract various information related to the network interface. These ioctl commands are used to query the state of an interface and to manipulate its properties. The following sections contain code snippets for a few such useful commands. See Resources for the complete list of ioctl commands.

Structures used with ioctl commands

The listings below show some of the most important structures that are frequently used while working with ioctl socket commands.


Listing 1. struct ifreq (/usr/include/net/if.h)
/* Interface request structure used for socket
 * ioctl's.  All interface ioctl's must have parameter
 * definitions which begin with ifr_name.  The
 * remainder may be interface specific.
 */
struct  ifreq {
#ifndef IFNAMSIZ
#define IFNAMSIZ        16
#endif
        char    ifr_name[IFNAMSIZ]; 
        union {
                struct  sockaddr ifru_addr;
                struct  sockaddr ifru_dstaddr;
                struct  sockaddr ifru_broadaddr;
                __ulong32_t     ifru_flags;
                int     ifru_metric;
                caddr_t ifru_data;
                u_short ifru_site6;
                __ulong32_t   ifru_mtu;
                int     ifru_baudrate;
        } ifr_ifru;

Following macros are provided for convenience

#define ifr_addr        ifr_ifru.ifru_addr      /* address */
#define ifr_dstaddr     ifr_ifru.ifru_dstaddr   /* other end of p-to-p link */
#define ifr_broadaddr   ifr_ifru.ifru_broadaddr /* broadcast address */
#define ifr_flags       ifr_ifru.ifru_flags     /* flags */
#define ifr_metric      ifr_ifru.ifru_metric    /* metric */
#define ifr_data        ifr_ifru.ifru_data      /* for use by interface */
#define ifr_site6       ifr_ifru.ifru_site6     /* IPv6 site index */
#define ifr_mtu         ifr_ifru.ifru_mtu       /* mtu of interface */
#define ifr_isno        ifr_ifru.ifru_data      /* pointer to if_netopts */
#define ifr_baudrate    ifr_ifru.ifru_baudrate  /* baudrate of interface */
};
      


Listing 2. struct ifconf (/usr/include/net/if.h)
/*
 * Structure used in SIOCGIFCONF request.
 * Used to retrieve interface configuration
 * for machine (useful for programs which
 * must know all networks accessible).
 */
struct  ifconf {
        int     ifc_len;                /* size of associated buffer */
        union {
                caddr_t ifcu_buf;
                struct  ifreq *ifcu_req;
        } ifc_ifcu;

Following macros are provided for convenience

#define ifc_buf ifc_ifcu.ifcu_buf       /* buffer address */
#define ifc_req ifc_ifcu.ifcu_req       /* array of structures returned */
};
      


Code examples

Table 1 below shows some interface retrieval commands. The information is from IBM System p™ and AIX.


Table 1. Interface retrieval commands
ioctl commandDescription
SIOCGSIZIFCONFGets the memory required to get configuration information for all interfaces returned by SIOCGIFCONF.

ioctl(fd, SIOCGSIZIFCONF, (caddr_t)&ifconfsize);
int ifconfsize;
SIOCGIFADDR

SIOCSIFADDR
SIOCGIFADDR gets an interface address and SIOCSIFADDR sets an interface address. The address is returned in the ifr.ifr_addr field.

ioctl(fd, SIOCGIFADDR, (caddr_t)&ifr, sizeof(struct ifreq));
ioctl(fd, SIOCSIFADDR, (caddr_t)&ifr, sizeof(struct ifreq));
struct ifreq ifr;
SIOCGIFCONFReturns configuration information for all the interfaces configured on the system.

ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc);
struct ifconf ifconf;

SIOCGSIZIFCONF

The following code snippet gets the size buffer required for populating information for all the configured interfaces.


Listing 3. Using SIOCGSIZIFCONF to get the size needed
/*Function to get the size needed to allocate for buffers*/
int get_interface_size(int sd){
    int ret,size;
    ret=ioctl(sd,SIOCGSIZIFCONF,&size);
    if(ret==-1){
       perror("Error getting size of interface :");
       return ret;
    }
    return size;
}

main
{
    struct ifconf ifc;
    int sd;
    sd=socket(AF_INET6,SOCK_DGRAM,0);
    printf("Size of memory needed = %d\n",get_interface_size(sd));
}
 
      

Output from the above code is:

$> ./myprog
Size of memory needed = 628
      

SIOCGIFCONF and SIOCGIFADDR

The SIOCGIFCONF and SIOCGIFADDR commands can be used to retrieve the addresses for the interfaces. While SIOCGIFCONF can be used to get information of all configured interfaces, SIOCGIFADDR can be used to retrieve the address for a specific interface.


Listing 4. Using SIOCGIFCONF to get configuration information

/*This function uses loops to find out buffer size instead of SIOCGSIZIFCONF 
  allocates the buffer and gets the information list*/
int alloc_buffer_size(int sd,struct ifconf *ifc){
    int ret=-1,bsz=sizeof(struct ifreq);
    int prevsz=bsz;
    ifc->ifc_req=NULL;
    ifc->ifc_len=bsz;
    do{
       ifc->ifc_req=(struct ifreq *)realloc(ifc->ifc_req,bsz);
       if(!ifc->ifc_req){
         perror("Malloc failed :");
         return ret;
       }
       ifc->ifc_len=bsz;
       ret=ioctl(sd,SIOCGIFCONF,(caddr_t)ifc);
       if(ret==-1){
          perror("Error getting size of interface :");
          return ret;
       }
      if(prevsz==ifc->ifc_len)
        break;
      else{
         bsz*=2;
         prevsz=(0==ifc->ifc_len ? bsz : ifc->ifc_len) ;
      }
    }while(1);
    ifc->ifc_req=(struct ifreq *)realloc(ifc->ifc_req,prevsz);
    return ifc->ifc_len;
}

      

Once the list is filled with the configuration information from ifreq structures, it can be traversed to retrieve required data. The pointer should be moved adequately depending on the length of socket address as populated in the structure after the call. Listing 5 below prints the available IPs on the system from the list in the code above.


Listing 5. Retrieving information from configuration list
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define SIZE(p) MAX((p).sa_len, sizeof(p))

/* This function prints all the configured IPs on the
 * system given the ifconf structure allocated previously*/
void print_ips(struct ifconf *ifc){
     char *cp,*cplim,addr[INET6_ADDRSTRLEN];
     struct ifreq *ifr=ifc->ifc_req;
     cp=(char *)ifc->ifc_req;
     cplim=cp+ifc->ifc_len;
     for(;cp<cplim;cp+=(sizeof(ifr->ifr_name) + SIZE(ifr->ifr_addr))){
        /* NOTE: You cannot just increment cp with sizeof(struct ifreq)
         * as structures returned are of different length.
         */
        ifr=(struct ifreq *)cp;
        printf("%s :",ifr->ifr_name);
        getip(ifr,addr);
        printf("%s\n",addr);
     }
      return ;
}
main
{
    struct ifconf ifc;
    int sd;
    sd=socket(AF_INET6,SOCK_DGRAM,0);
    alloc_buffer_size(sd,&ifc);
    print_ips(&ifc);
}
      

Output from the code above is:

$> ./myprog
en0 :6.3.6.0
en0 :9.182.192.169
en0 :fe80::209:6bff:feeb:70b2
sit0 :1.4.4.0
sit0 :::9.182.192.169
lo0 :24.3.0.0
lo0 :127.0.0.1
lo0 :::1
      


Listing 6. Using SIOCGIFADDR to get interface address
/* Given a ifreq structure this function returns its IP address */
void getip(struct ifreq *ifr,char *addr){
  struct sockaddr *sa;
  sa=(struct sockaddr *)&(ifr->ifr_addr);
  switch(sa->sa_family){
    case AF_INET6:
      inet_ntop(AF_INET6,(struct in6_addr *)&(((struct sockaddr_in6 *)sa)->sin6_addr),
         addr,INET6_ADDRSTRLEN);
      break;
    default : strcpy(addr,inet_ntoa(((struct sockaddr_in *)sa)->sin_addr));
    }
   return;
}

main
{
  char netaddr[INET_ADDRSTRLEN];
  int sd;
  sd=socket(AF_INET,SOCK_DGRAM,0);
  strcpy(ifr.ifr_name,"en0");
  if((ioctl(sd,SIOCGIFADDR,(caddr_t)&ifr,sizeof(struct ifreq)))<0)
     perror("Error : ");
  getip(&ifr,netaddr);
  printf("%s\n",netaddr);
}
      

Output from the code above is:

$./myprog
9.182.192.35
      

Table 2 below shows interface flags and some attribute retrieval commands.


Table 2. Interface flags and attribute retrieval commands
ioctl commandDescription
SIOCGIFFLAGS

SIOCSIFFLAGS
SIOCGIFFLAGS gets the interface flags.

SIOCSIFFLAGS sets the interface flags.

ioctl(fd, cmd, (caddr_t)&ifr);struct ifreq ifr;

SIOCGIFFLAGS

Once you get the interface list using SIOCGIFCONF, you can use the SIOCGIFFLAGS-SIOCSIFFLAGS pair to get and set the properties for the interface. Interface flags are denoted by IFF_XXX. See the file /usr/include/net/if.h for the complete list.

The following examples use a couple of flags on the interface to retrieve its current state and check for loopback. The other options can also be used.


Listing 7. Verifying the state and type of interface
   for(;cp<cplim;){
        ifr=(struct ifreq *)cp;
        cp+=(sizeof(ifr->ifr_name) + SIZE(ifr->ifr_addr));
        printf("%-9s  ",ifr->ifr_name);
        ret=ioctl(sd,SIOCGIFFLAGS,(caddr_t)ifr);
        if(ret==-1){
          perror("Error getting flags for interface :");
          return ;
        }
        if((ifr->ifr_flags)&IFF_UP)
           printf("UP");
        else printf("DOWN");
        if((ifr->ifr_flags)&IFF_LOOPBACK)
           printf(",Loopback");
	printf("\n");
     }
      

Output from the code above is:

$> ./myprog
en0        UP
en0        UP
en0        UP
sit0       UP
sit0       UP
lo0        UP,Loopback
lo0        UP,Loopback
lo0        UP,Loopback
      


Listing 8. Setting an interface flag
	Partial output of ifconfig before setting the flag

sit0: flags=4900041<UP,RUNNING,LINK0,64BIT>
        inet6 ::9.182.192.169/96

Code to set the interface flag 

int set_interface_flag(int sd,short flag,char *interface){
    struct ifreq ifr;
    int oldflags;
    strcpy(ifr.ifr_name,interface);
    if((ioctl(sd,SIOCGIFFLAGS,(caddr_t)&ifr))==-1){
      perror("Error getting interface flags :");
      return -1;
    }
    printf("Setting new interface flag 0X%x\n",flag);
    ifr.ifr_flags|=flag;
    if((ioctl(sd,SIOCSIFFLAGS,(caddr_t)&ifr))==-1){
      perror("Error setting interface flags :");
      return -1;
    }
    return 0;
}

main
{
    int sd;
    sd=socket(AF_INET6,SOCK_DGRAM,0);
    set_interface_flag(sd,IFF_NOTRAILERS,"sit0");
}

Output from the code above is:

You must have permission to change the flag

$./myprog
Setting new interface flag 0X20

$ifconfig -a
.............
.............
sit0: flags=4900061<UP,NOTRAILERS,RUNNING,LINK0,64BIT>
        inet6 ::9.182.192.169/96
.............
.............
      

Table 3 shows some commands for network tuning.


Table 3. Commands for network tuning
ioctl commandDescription
SIOCGIFMTUSIOCGIFMTU gets the Maximum Transfer Unit (MTU) for the interface.ioctl(fd, cmd, (caddr_t)&ifr);
struct ifreq ifr;


The MTU value is stored in the ifr.ifr_mtu field.
SIOCGNETOPT
SIOCGNETOPT1
SIOCGNETOPT gets the value of a network option.ioctl(fd, cmd, (caddr_t)&oreq);struct optreq oreq;

SIOCGNETOPT1 gets the current value, default value, and range of a network option.ioctl(fd, SIOCGNETOPT1, (caddr_t)&oreq);struct optreq1 oreq;

SIOCGIFMTU


Listing 9. Getting MTU from an ifreq structure
        ret=ioctl(sd,SIOCGIFMTU,ifr);
        if(ret==-1){
          perror("Error getting mtu for interface :");
          return ;
        }
        printf("  %d\n",ifr->ifr_mtu);
      

SIOCGNETOPT1

SIOCGNETOPT1 gives the current value, default value, and range of a network option.


Listing 10. Getting network options from an optreq1 structure
/*Function to get the network options*/
int print_network_options(int sd){
    int ret;
    struct optreq1 oreq;
    oreq.getnext=1;
    while((ioctl(sd,SIOCGNETOPT1,(caddr_t)&oreq))!=-1)
    printf("%s = %s\n",oreq.name,oreq.data);
   return 0;
}
      

Output from the code above is:

$> ./myprog
arpqsize = 12
arpt_killc = 20
arptab_bsiz = 7
arptab_nb = 149
........
........
........
........
ifsize = 256
inet_stack_size = 16
ip6_defttl = 64
........
      

You can also use the no command on AIX to manage network tuning parameters. See the man page for more details.


Listing 11. Output from "no" command on AIX machine
$> no -a|more
               arpqsize = 12
               arpt_killc = 20
              arptab_bsiz = 7
                arptab_nb = 149
                bcastping = 0
      clean_partial_conns = 0
                 delayack = 0
            delayackports = {}
         dgd_packets_lost = 3
            dgd_ping_time = 5
           dgd_retry_time = 5
       directed_broadcast = 0
         extendednetstats = 0
                 fasttimo = 200
........
........
      


Summary

The ioctls are powerful commands that you can use to access and modify configurable parameters for network (or other) devices. They use various data structures and should be populated with correct data to achieve desired results. You will notice differences in using AF_INET and the AF_INET6 family. This article showed code examples for a small, but common, subset of commands. Go to Resources for a complete listing of commands on AIX Version 5.3. We hope you will find this information about ioctls useful.


Resources

Learn

Get products and technologies

  • IPv6 tools: Browse this site for free online tools.

  • IBM trial software: Build your next development project with software for download directly from developerWorks.

Discuss

About the authors

Photo of Katiyar Manish

Manish Katiyar works as a software engineer for IBM India Software Labs. He has worked for IBM for the past two years, focusing on SARPC. He also has experience on data warehousing tools (Ab-Initio). Manish holds a Bachelor of Technology degree in chemical engineering from the Indian Institute of Technology Kharagpur in India. You can contact him at manish.katiyar@in.ibm.com.

Photo of Shweta Gupta

Shweta Gupta is a Staff Software Engineer for IBM India Software Labs. She has a Master's degree in computer science from Pune University in India. She works in network protocols and middleware technology, including the RPC layer over various UNIX platforms. She also has an interest in grid computing. Shweta currently resides in Pune, India and enjoys playing table tennis, teaching, reading biographies, and leisure travel. You can contact her at shwetagupta@in.ibm.com.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值