套接字 ioctl 命令

套 接字 ioctl 命令
了解更多关于套接字 I/O 控制 (ioctl) 命令的内容,以及如何使用它们完成各种网络相关的操作.操作系统为套接字、路由表、ARP 表、全局网络参数和接口提供了相应的控制操作方式。本文适用于对 Internet Protocol Version 4 (IPv4) 和 Internet Protocol Version 6 (IPv6) 堆栈网络级操作感兴趣的 AIX® Version 5.3 开发人员。

引言

文件描述符是低层的输入和输出接口。描述符可以表示到设备、管道或套接字的连接,这些连接用于与另一个进程或普通文件进行通信。I/O 控制 (ioctl) 函数调用可以用来对特殊文件的基础设备参数进行操作。它们可以完成与打开的文件描述符相关联的控制功能。这些命令涉及文件、流、普通数据链路控制以及其他 各种设备。

本文将讨论 AIX® Version 5.3 中提供的与网络操作和套接字相关的命令。在下列文件中列出了与套接字相关的命令和结构:

  • sys/ioctl.h
  • net/if_arp.h
  • net/if.h
  • net/netopt.h
  • netinet/in.h
应用程序开发人员可以使用这些命令,并且在 AIX Version 5.3 的文档中对这些命令进行了详细的描述。本文说明了有关 Internet Protocol Version 6 (IPv6) 地址和 Internet Protocol Version 4 (IPv4) 堆栈的常用命令的典型用法。

 

使用 ioctl 套接字控制选项

通常,网络程序需要了解系统中所有有关网络接口和 IP 地址的可用信息。现在,未来的应用程序可以支持 IPv4 和 IPv6 双协议栈。ioctl 结构需要对指针进行遍历和操作,以处理 IPv4 和 IPv6 地址在长度上的差别(除了使用合适的套接字结构 sockaddr_in6 或 sockaddr_storage 之外)。

AIX Version 5.3 提供了很多 ioctl 套接字控制选项,以提取各种有关网络接口的信息。这些 ioctl 命令用于查询接口的状态并对其属性进行操作。下面的部分中包含了一些有用的命令的代码段。有关 ioctl 命令的完整列表,请参见参考资料 部分。

ioctl 命令所使用的结构

下面的清单介绍了一些最重要的结构,使用 ioctl 套接字命令时常常用到这些结构。
清单 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 */
};


清单 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 */
};





回页首


代码示例

下面的表 1 介绍了一些接口检索命令。该信息来源于 IBM System p™ 和 AIX。
表 1. 接口检索命令

ioctl 命令 描述
SIOCGSIZIFCONF 获得获取 SIOCGIFCONF 返回的所有接口的配置信息所需的内存。
		
ioctl(fd, SIOCGSIZIFCONF, (caddr_t)&ifconfsize);

int ifconfsize;

SIOCGIFADDR

SIOCSIFADDR
SIOCGIFADDR 获取接口地址,而 SIOCSIFADDR 设置接口地址。ifr.ifr_addr 字段返回地址。
ioctl(fd, SIOCGIFADDR, (caddr_t)&ifr, sizeof(struct ifreq));

ioctl(fd, SIOCSIFADDR, (caddr_t)&ifr, sizeof(struct ifreq));

struct ifreq ifr;

SIOCGIFCONF 返回系统中配置的所有接口的配置信息。
ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc);

struct ifconf ifconf;

SIOCGSIZIFCONF

下面的代码段可以获取用来填充所有配置接口的信息所需的缓冲区大小。
清单 3. 使用 SIOCGSIZIFCONF 获得所需的缓冲区大小

				
/*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));
}


上面代码的输出是:

$> ./myprog
Size of memory needed = 628

SIOCGIFCONF 和 SIOCGIFADDR

SIOCGIFCONF 和 SIOCGIFADDR 命令可以用来检索接口的地址。SIOCGIFCONF 可以用来获取所有配置接口的信息,SIOCGIFADDR 可以用来检索特定接口的地址。


清单 4. 使用 SIOCGIFCONF 获取配置信息

					
/*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;
}


在使用 ifreq 结构中的配置信息填充了列表之后,可以对其进行遍历以检索所需的数据。根据调用之后该结构中填充的套接字地址的长度,可以对这个指针进行移动。下面的清单 5 显示了上面代码的列表中获得的系统中可用的 IP。
清 单 5. 从配置列表中检索信息

					
#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);
}

上面代码的输出是:

$> ./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


清单 6. 使用 SIOCGIFADDR 获取接口地址
					
/* 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);
}

上面代码的输出是:

$./myprog
9.182.192.35

下面的表 2 介绍了接口标志和一些属性检索命令。
表 2. 接口标志和属性检索命令

ioctl 命令 描述
SIOCGIFFLAGS

SIOCSIFFLAGS
SIOCGIFFLAGS 可以获取接口标志。

SIOCSIFFLAGS 可以设置接口标志。

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

SIOCGIFFLAGS

在使用 SIOCGIFCONF 获取了接口列表之后,您可以使用 SIOCGIFFLAGS-SIOCSIFFLAGS 对来获取和设置接口的属性。接口标志表示为 IFF_XXX。有关完整的列表,请参阅文件 /usr/include/net/if.h。

下面的示例使用一对接口标志来检索其当前状态,并检查环回。也可以使用其他选项。
清单 7. 验证接口的状态和类型

				
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");
}

上面代码的输出是:

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


清单 8. 设置接口标志
				
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");
}

上面代码的输出是:

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
.............
.............

表 3 介绍了一些用于网络优化的命令。
表 3. 用于网络优化的命令

ioctl 命令 描述
SIOCGIFMTU SIOCGIFMTU 可以获取接口的最大传输单元 (MTU)。

 

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

struct ifreq ifr;

这个 MTU 值存储在 ifr.ifr_mtu 字段中。
SIOCGNETOPT
SIOCGNETOPT1
SIOCGNETOPT 可以获取一个网络选项的值。

 

ioctl(fd, cmd, (caddr_t)&oreq);
struct optreq oreq;

SIOCGNETOPT1 可以获取当前值、缺省值和网络选项的范围。

 

ioctl(fd, SIOCGNETOPT1, (caddr_t)&oreq);
struct optreq1 oreq;

SIOCGIFMTU


清 单 9. 从 ifreq 结构获取 MTU

				
ret=ioctl(sd,SIOCGIFMTU,ifr);
if(ret==-1){
perror("Error getting mtu for interface :");
return ;
}
printf(" %d/n",ifr->ifr_mtu);

SIOCGNETOPT1

SIOCGNETOPT1 给出当前值、缺省值和网络选项的范围。


清单 10. 从 optreq1 结构获取网络选项

				
/*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;
}

上面代码的输出是:

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

在 AIX 中,您还可以使用 no 命令来管理各种网络优化参数。有关更详细的信息,请参阅相应的 man 页面。
清单 11. AIX 计算机上“no”命令的输出

				
$> 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
........
........





回页首


总结

ioctl 命令的功能非常强大,您可以使用它们来访问或修改网络(或其他)设备的可配置参数。它们使用了各种各样的数据结构,应该使用正确的数据来填充这些数据结 构,以便实现预期的结果。您将发现在使用 AF_INET 和 AF_INET6 系列时存在的区别。本文提供了一小部分常用命令子集的代码示例。要获得 AIX Version 5.3 中完整的命令清单,请转到参考资料 部分。我们希望这些关于 ioctl 的信息对您有用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
其中包含 AccessChk 为了确保创建安全的环境,Windows 管理员通常需要了解特定用户或用户组对文件、目录、注册表项和 Windows 服务等资源具有哪种访问权限。AccessChk 能够通过直观的界面和输出快速回答这些问题。 AccessEnum 这一简单但强大的安全工具可以向您显示,谁可以用何种访问权限访问您系统中的目录、文件和注册表项。使用此工具可查找权限漏洞。 AdExplorer Active Directory Explorer 是一个高级的 Active Directory (AD) 查看器和编辑器。 AdInsight 一种 LDAP(轻型目录访问协议)实时监视工具,旨在对 Active Directory 客户端应用程序进行故障排除。 AdRestore 恢复已删除的 Server 2003 Active Directory 对象。 Autologon 登录过程中跳过密码屏幕。 Autoruns 查看哪些程序被配置为在系统启动和您登录时自动启动。Autoruns 还能够完整列出应用程序可以配置自动启动设置的注册表和文件位置。 BgInfo 此完全可配置程序会自动生成桌面背景,其中包含有关系统的 IP 地址、计算机名称、网络适配器及更多内容的重要信息。 BlueScreen 此屏幕保护程序不仅精确模拟“蓝屏”,而且也模拟重新启动(完成 CHKDSK),并可在 Windows NT 4、Windows 2000、Windows XP、Server 2003 和 Windows 9x 上工作。 CacheSet CacheSet 是一个允许您利用 NT 提供的功能来控制缓存管理器的工作集大小的程序。它与 NT 的所有版本都兼容。 ClockRes 查看系统时钟的分辨率,亦即计时器最大分辨率。 Contig 您是否希望迅速对您频繁使用的文件进行碎片整理?使用 Contig 优化单个的文件,或者创建连续的新文件。 Coreinfo Coreinfo 是一个新的命令行实用工具,可向您显示逻辑处理器与物理处理器之间的映射、NUMA 节点和它们所处的插槽,以及分配给每个逻辑处理器的缓存。 Ctrl2cap 这是一个内核模式的驱动程序,可在键盘类驱动程序上演示键盘输入过滤,以便将 Caps-Lock 转变为控制键。在此级别过滤允许在 NT 刚好要“看到”键之前变换和隐藏键。Ctrl2cap 还显示如何使用 NtDisplayString() 打印初始化蓝屏的消息。 DebugView Sysinternals 的另一个优先程序:此程序截取设备驱动程序对 DbgPrint 的调用和 Win32 程序生成的 OutputDebugString。它允许在不使用活动的调试器的情况下,在本地计算机上或通过 Internet 查看和记录调试会话输出。 Desktops 使用这一新的实用工具可以创建最多四个虚拟桌面,使用任务栏界面或热键预览每个桌面上的内容并在这些桌面之间轻松地进行切换。 Disk2vhd Disk2vhd 可简化从物理系统到虚拟机 (p2v) 的迁移。 DiskExt 显示卷磁盘映射。 Diskmon 此实用工具会捕捉所有硬盘活动,或者在您的系统任务栏中象软件磁盘活动灯一样工作。 DiskView 图形磁盘扇区实用工具。 Disk Usage (DU) 按目录查看磁盘使用情况。 EFSDump 查看加密文件的信息。 Handle 此易用命令行实用工具将显示哪些进程打开了哪些文件,以及更多其他信息。 Hex2dec 将十六进制数字转换为十进制及反向转换。 接合点 创建 Win2K NTFS 符号链接。 LDMDump 转储逻辑磁盘管理器在磁盘上的数据库内容,其中说明了 Windows 2000 动态磁盘的分区情况。 ListDLLs 列出所有当前加载的 DLL,包括加载位置及其版本号。2.0 版将打印已加载模块的完整路径名。 LiveKd 使用 Microsoft 内核调试程序检查真实系统。 LoadOrder 查看设备加载到 WinNT/2K 系统中的顺序。 LogonSessions 列出系统中的活动登录会话。 MoveFile 使您可以安排在系统下一次重新启动时执行移动和删除命令。 NTFSInfo 用 NTFSInfo 可以查看有关 NTFS 卷的详细信息,包括主文件表 (MFT) 和 MFT 区的大小和位置,以及 NTFS 元数据文件的大小。 PageDefrag 对您的分页文件和注册表配置单元进行碎片整理。 PendMoves 枚举在系统下一次启动时所要执行的文件重命名和删除命令的列表。 PipeList 显示系统上的命名管道,包括每个管道的最大实例数和活动实例数。 PortMon 通过高级监视工具监视串行端口和并行端口的活动。它能识别所有的标准串行和并行 IOCTL,甚至可以显示部分正在发送和接收的数据。3.x 版具有强大的新 UI 增强功能和高级筛选功能。 ProcDump 这一新的命令行实用工具旨在捕获其他方式难以隔离和重现 CPU 峰值的进程转储。该工具还可用作用于创建进程转储的一般实用工具,并可以在进程具有挂起的窗口或未处理的异常时监视和生成进程转储。 Process Explorer 找出进程打开了哪些文件、注册表项和其他对象以及已加载哪些 DLL 等信息。这个功能异常强大的实用工具甚至可以显示每个进程的所有者。 Process Monitor 实时监视文件系统、注册表、进程、线程和 DLL 活动。 ProcFeatures 这一小程序会报告处理器和 Windows 对“物理地址扩展”和“无执行”缓冲区溢出保护的支持情况。 PsExec 在远程系统上执行进程。 PsFile 查看远程打开的文件。 PsGetSid 显示计算机或用户的 SID。 PsInfo 获取有关系统的信息。 PsKill v1.13(2009 年 12 月 1 日) 终止本地或远程进程。 PsList 显示有关进程和线程的信息。 PsLoggedOn 显示登录到某个系统的用户。 PsLogList 转储事件日志记录。 PsPasswd 更改帐户密码。 PsService 查看和控制服务。 PsShutdown 关闭并重新启动(可选)计算机。 PsSuspend 挂起和继续进程。 PsTools PsTools 套件包括一些命令行程序,可列出本地或远程计算机上运行的进程、远程运行进程、重新启动计算机、转储事件日志,以及执行其他任务。 RegDelNull 扫描并删除包含嵌入空字符的注册表项,标准注册表编辑工具不能删除这种注册表项。 RegJump 跳至 Regedit 中指定的注册表路径。 RootkitRevealer 扫描系统以找出基于 Rootkit 的恶意软件。 SDelete 安全地覆盖敏感文件,并使用此符合 DoD 的安全删除程序清理先前删除文件所在的可用空间。 ShareEnum 扫描网络上的文件共享并查看其安全设置,以关闭安全漏洞。 ShellRunas 通过方便的 shell 上下文菜单项,作为另一个用户启动程序。 Sigcheck 转储文件版本信息并检查系统中的映像是否已进行数字签名。 Streams 显示 NTFS 备用数据流。 Strings 在二进制映像中搜索 ANSI 和 UNICODE 字符串。 Sync 将缓存数据刷新到磁盘。 TCPView 活动套接字命令行查看器。 VMMap VMMap 是进程虚拟和物理内存分析实用工具。 VolumeId 设置 FAT 或 NTFS 驱动器的卷 ID。 Whois 查看 Internet 地址的所有者。 WinObj 基本对象管理器命名空间查看器。 ZoomIt 在屏幕上进行缩放和绘图的演示实用工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值