在第1课中, (获取设备列表) 我们展示了如何获取适配器的基本信息 (如设备的名称和描述)。 事实上,WinPcap提供了其他更高级的信息。 特别需要指出的是, 由 pcap_findalldevs_ex() 返回的每一个 pcap_if 结构体,都包含一个 pcap_addr 结构体,这个结构体由如下元素组成:
另外,函数 pcap_findalldevs_ex() 还能返回远程适配器信息和一个位于所给的本地文件夹的pcap文件列表。
下面的范例使用了ifprint()函数来打印出 pcap_if 结构体中所有的内容。程序对每一个由 pcap_findalldevs_ex() 函数返回的pcap_if,都调用ifprint()函数来实现打印。
/*
* Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
* Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino, CACE Technologies
* nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include " pcap.h "
#ifndef WIN32
#include < sys / socket.h >
#include < netinet / in .h >
#else
#include < winsock.h >
#endif
// 函数原型
void ifprint(pcap_if_t * d);
char * iptos(u_long in );
char * ip6tos( struct sockaddr * sockaddr, char * address, int addrlen);
int main()
{
pcap_if_t * alldevs;
pcap_if_t * d;
char errbuf[PCAP_ERRBUF_SIZE + 1 ];
char source[PCAP_ERRBUF_SIZE + 1 ];
printf( " Enter the device you want to list:\n "
" rpcap:// ==> lists interfaces in the local machine\n "
" rpcap://hostname:port ==> lists interfaces in a remote machine\n "
" (rpcapd daemon must be up and running\n "
" and it must accept 'null' authentication)\n "
" file://foldername ==> lists all pcap files in the give folder\n\n "
" Enter your choice: " );
fgets(source, PCAP_ERRBUF_SIZE, stdin);
source[PCAP_ERRBUF_SIZE] = ' \0 ' ;
/* 获得接口列表 */
if (pcap_findalldevs_ex(source, NULL, & alldevs, errbuf) == - 1 )
{
fprintf(stderr, " Error in pcap_findalldevs: %s\n " ,errbuf);
exit( 1 );
}
/* 扫描列表并打印每一项 */
for (d = alldevs;d;d = d -> next)
{
ifprint(d);
}
pcap_freealldevs(alldevs);
return 1 ;
}
/* 打印所有可用信息 */
void ifprint(pcap_if_t * d)
{
pcap_addr_t * a;
char ip6str[ 128 ];
/* 设备名(Name) */
printf( " %s\n " ,d -> name);
/* 设备描述(Description) */
if (d -> description)
printf( " \tDescription: %s\n " ,d -> description);
/* Loopback Address */
printf( " \tLoopback: %s\n " ,(d -> flags & PCAP_IF_LOOPBACK) ? " yes " : " no " );
/* IP addresses */
for (a = d -> addresses;a;a = a -> next) {
printf( " \tAddress Family: #%d\n " ,a -> addr -> sa_family);
switch (a -> addr -> sa_family)
{
case AF_INET:
printf( " \tAddress Family Name: AF_INET\n " );
if (a -> addr)
printf( " \tAddress: %s\n " ,iptos((( struct sockaddr_in * )a -> addr) -> sin_addr.s_addr));
if (a -> netmask)
printf( " \tNetmask: %s\n " ,iptos((( struct sockaddr_in * )a -> netmask) -> sin_addr.s_addr));
if (a -> broadaddr)
printf( " \tBroadcast Address: %s\n " ,iptos((( struct sockaddr_in * )a -> broadaddr) -> sin_addr.s_addr));
if (a -> dstaddr)
printf( " \tDestination Address: %s\n " ,iptos((( struct sockaddr_in * )a -> dstaddr) -> sin_addr.s_addr));
break ;
case AF_INET6:
printf( " \tAddress Family Name: AF_INET6\n " );
if (a -> addr)
printf( " \tAddress: %s\n " , ip6tos(a -> addr, ip6str, sizeof (ip6str)));
break ;
default :
printf( " \tAddress Family Name: Unknown\n " );
break ;
}
}
printf( " \n " );
}
/* 将数字类型的IP地址转换成字符串类型的 */
#define IPTOSBUFFERS 12
char * iptos(u_long in )
{
static char output[IPTOSBUFFERS][ 3 * 4 + 3 + 1 ];
static short which;
u_char * p;
p = (u_char * ) & in ;
which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1 );
sprintf(output[which], " %d.%d.%d.%d " , p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ]);
return output[which];
}
char * ip6tos( struct sockaddr * sockaddr, char * address, int addrlen)
{
socklen_t sockaddrlen;
#ifdef WIN32
sockaddrlen = sizeof ( struct sockaddr_in6);
#else
sockaddrlen = sizeof ( struct sockaddr_storage);
#endif
if (getnameinfo(sockaddr,
sockaddrlen,
address,
addrlen,
NULL,
0 ,
NI_NUMERICHOST) != 0 ) address = NULL;
return address;
}
原作者:The WinPcap Team 主页: http://www.winpcap.org