一、函数原型
#include <unistd.h> int ioctl(int fd, int request, .../* void *arg */); 返回:成功返回0,否则为-1
二、和网络相关的请求(request)
(1)套接字操作
(2)文件操作
(3)接口操作
(4)ARP告诉缓存操作
(5)路由表操作
(6)流系统
三、request参数及arg地址必须指向的数据类型
四、案列:获取所有网络设备接口名称
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <net/if.h> struct ifreq *get_ifreq(); int main(int argc, char **argv) { struct ifreq *ifr, *tobefree; ifr = tobefree = get_ifreq(); do { printf("%s ", ifr->ifr_name); ifr++; } while (ifr->ifr_name[0] != 0); free(tobefree); exit(0); } struct ifreq *get_ifreq() { int sockfd, len, lastlen; char *buf; struct ifconf ifc; sockfd = socket(AF_INET, SOCK_DGRAM, 0); lastlen = 0; len = 40 * sizeof(struct ifreq); /* initial buffer size guess */ for ( ; ; ) { buf = malloc(len); ifc.ifc_len = len; ifc.ifc_buf = buf; if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { if (errno != EINVAL || lastlen != 0) { perror("ioctl"); exit(-1); } } else { if (ifc.ifc_len == lastlen) { break; /* success, len has not changed */ } lastlen = ifc.ifc_len; } len += 10 * sizeof(struct ifreq); /* increment */ free(buf); } return ((struct ifreq *)ifc.ifc_buf); }
五、关于ioctl函数应该注意
六、get_ifi_info函数
#include "unpifi.h" struct ifi_info *get_ifi_info(int family, int doaliases) { int sockfd, len, lastlen, flags, myflags, idx = 0, hlen = 0; char *ptr, *buf, lastname[IFNAMSIZ], *cptr, *haddr, *sdlname; struct ifconf ifc; struct ifreq *ifr, ifrcopy; struct sockaddr_in *sinptr; struct sockaddr_in6 *sin6ptr; struct ifi_info *ifi, *ifihead, **ifipnext; sockfd = socket(family, SOCK_DGRAM, 0); lastlen = 0; len = 100 * sizeof(struct ifreq); /* initial buffer size guess */ for ( ; ; ) { buf = malloc(len); ifc.ifc_len = len; ifc.ifc_buf = buf; if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { if (errno != EINVAL || lastlen != 0) { perror("ioctl"); exit(-1); } } else { if (ifc.ifc_len == lastlen) { break; /* success, len has not changed */ } lastlen = ifc.ifc_len; } len += 10 * sizeof(struct ifreq); /* increment */ free(buf); } ifihead = NULL; ifipnext = &ifihead; lastname[0] = 0; sdlname = NULL; for (ptr = buf; ptr < buf + ifc.ifc_len; ) { ifr = (struct ifreq *) ptr; #ifdef HAVE_SOCKADDR_SA_LEN len = max(sizeof(struct sockaddr), ifr->ifr_addr.sa_len); #else switch (ifr->ifr_addr.sa_family) { #ifdef IPV6 case AF_INET6: len = sizeof(struct sockaddr_in6); break; #endif case AF_INET: default: len = sizeof(struct sockaddr); break; } #endif /* HAVE_SOCKADDR_SA_LEN */ ptr += sizeof(ifr->ifr_name) + len + 8; /* for next one in buffer */ #ifdef HAVE_SOCKADDR_DL_STRUCT /* assumes that AF_LINK precedes AF_INET or AF_INET6 */ if (ifr->ifr_addr.sa_family == AF_LINK) { struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr; sdlname = ifr->ifr_name; idx = sdl->sdl_index; haddr = sdl->sdl_data + sdl->sdl_nlen; hlen = sdl->sdl_alen; } #endif if (ifr->ifr_addr.sa_family != family) { continue; /* ignore if not desired address family */ } myflags = 0; if ( (cptr = strchr(ifr->ifr_name, ':')) != NULL) { *cptr = 0; /* replace colon with null */ } if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) { if (doaliases == 0) continue; /* already processed this interface */ myflags = IFI_ALIAS; } memcpy(lastname, ifr->ifr_name, IFNAMSIZ); ifrcopy = *ifr; ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy); flags = ifrcopy.ifr_flags; if ((flags & IFF_UP) == 0) { continue; /* ignore if interface not up */ } ifi = calloc(1, sizeof(struct ifi_info)); *ifipnext = ifi; /* prev points to this new one */ ifipnext = &ifi->ifi_next; /* pointer to next one goes here */ ifi->ifi_flags = flags; /* IFF_xxx values */ ifi->ifi_myflags = myflags; /* IFI_xxx values */ #if defined(SIOCGIFMTU) && defined(HAVE_STRUCT_IFREQ_IFR_MTU) ioctl(sockfd, SIOCGIFMTU, &ifrcopy); ifi->ifi_mtu = ifrcopy.ifr_mtu; #else ifi->ifi_mtu = 0; #endif memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME); ifi->ifi_name[IFI_NAME-1] = '