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 */ }; |
Table 1 below shows some interface retrieval commands. The information is from IBM System p™ and AIX.
Table 1. Interface retrieval commands
ioctl command | Description |
---|---|
SIOCGSIZIFCONF | Gets the memory required to get configuration information for all interfaces returned by SIOCGIFCONF.ioctl(fd, SIOCGSIZIFCONF, (caddr_t)&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)); |
SIOCGIFCONF | Returns configuration information for all the interfaces configured on the system.ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc); |
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 |
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 command | Description |
---|---|
SIOCGIFFLAGS SIOCSIFFLAGS | SIOCGIFFLAGS gets the interface flags. SIOCSIFFLAGS sets the interface flags. ioctl(fd, cmd, (caddr_t)&ifr);struct ifreq ifr; |
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 command | Description |
---|---|
SIOCGIFMTU | SIOCGIFMTU gets the Maximum Transfer Unit (MTU) for the interface.ioctl(fd, cmd, (caddr_t)&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; |
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 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 ........ ........ |
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.
Learn
- ioctl Socket Control Operations: Learn about socket ioctl commands, available on AIX Version 5.3, that perform a variety of network-related control.
- TCP/IP tutorial and technical overview: Read this IBM Redbook to learn more about the TCP/IP protocol suite.
- "Writing a simple IPv6 program" (developerWorks, Sep 2001): This article gives you the starting point as you plan to migrate to IPv6 by showing how to configure IPv6 addresses and write a sample program.
- IPv6 address: Configure IPv6 for other platforms.
- AIX and UNIX: Visit the developerWorks AIX and UNIX zone to expand your UNIX skills.
- New to AIX and UNIX: Visit the New to AIX and UNIX page to learn more about AIX and UNIX.
- developerWorks technical events and webcasts: Stay current with developerWorks technical events and webcasts.
- AIX 5L Wiki: A collaborative environment for technical information related to AIX.
- Technology bookstore: Browse this site for books and other technical topics.
- Podcasts: Tune in and catch up with IBM technical experts.
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
- Participate in the AIX and UNIX forums:
- AIX 5L -- technical
- AIX for Developers Forum
- Cluster Systems Management
- IBM Support Assistant
- Performance Tools -- technical
- Virtualization -- technical
- More AIX and UNIX forums
- Participate in the developerWorks blogs and get involved in the developerWorks community.
![Photo of Katiyar Manish](https://i-blog.csdnimg.cn/blog_migrate/8da1b390e7a0778ae52651e5bbb4ad0d.jpeg)
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](https://i-blog.csdnimg.cn/blog_migrate/c533f8ead74fba20247f9d4e929e5b8c.jpeg)
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.