winpcap获取本机网卡地址

ypos 2005-01-31 05:10:00
请问winpcap中如果获取本机网卡地址?
...全文
602 点赞 收藏 31
写回复
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
roselu 2005-03-22
GZ
回复
ypos 2005-02-02
源MAC也就是你本机的MAC地址?(谁说的?)

现在放宽要求了,获取网卡5D24AE04-C486-4A96-83FB-8B5EC6C7F430对应的MAC地址
回复
SmallBigCat 2005-02-02
用UuidCreate也可以的
回复
kingzai 2005-02-02
非IP包也好办,winpcap抓包是每次都能抓到mac头的,源MAC也就是你本机的MAC地址肯定是每次都相同的,而目的MAC可能都不一样.
回复
ypos 2005-02-02
如果要判断非IP包呢?
回复
wangzhanlili 2005-02-01
不用winpcap 就有直接的方法 我记得有个贴 讲了很多种得到mac的方法 搜一下吧
回复
ypos 2005-02-01
最后想确定一下winpcap有没有直接的方式,然后就要结贴了
回复
kingzai 2005-02-01
winpcap本身就有提供win98下的接口.
获取本机mac地址可以使用netbios,也可以使用iphelper api获取.
http://www.teacherli.com/info11/ask280122.htm
回复
ypos 2005-02-01
看来我还是说得不够清楚,我现在通过Winpcap捕获数据包,我要判断捕获的数据包是本机发出去的、还是本机收到的,我想通过比较MAC地址来判断,所以我首先要获取本机的MAC地址,获取方法必须也能在Win 95/NT上运行
回复
kingzai 2005-02-01
从捕获的IP头就可以看出来了.用不着MAC头
回复
ypos 2005-02-01
我的目的是:判断捕获的数据包是本机发出去的、还是本机收到的(分别对单个网卡判断)
回复
chuanke 2005-02-01
Method 2 - Using the SNMP Extension API [code]
The third method I will talk about is using the SNMP (Simple Network Management Protocol) extension in Windows to get your system's address. The protocol in my experience is anything but simple, but the code should read pretty straight-forwardly. Basically the steps are the same as with Netbios:
Get a list of adapters
Query each adapter for type and MAC address
Save the adapters that are actual NICs
I don't personally know much about SNMP, but as I said before, the code is pretty clear. For more information, refer to the following URLs:

SNMP Functions
SNMP Variable Types and Request PDU Types
SNMP Structures

snmp.cpp
#include <snmp.h>
#include <conio.h>
#include <stdio.h>
typedef bool(WINAPI * pSnmpExtensionInit) (
IN DWORD dwTimeZeroReference,
OUT HANDLE * hPollForTrapEvent,
OUT AsnObjectIdentifier * supportedView);
typedef bool(WINAPI * pSnmpExtensionTrap) (
OUT AsnObjectIdentifier * enterprise,
OUT AsnInteger * genericTrap,
OUT AsnInteger * specificTrap,
OUT AsnTimeticks * timeStamp,
OUT RFC1157VarBindList * variableBindings);
typedef bool(WINAPI * pSnmpExtensionQuery) (
IN BYTE requestType,
IN OUT RFC1157VarBindList * variableBindings,
OUT AsnInteger * errorStatus,
OUT AsnInteger * errorIndex);
typedef bool(WINAPI * pSnmpExtensionInitEx) (
OUT AsnObjectIdentifier * supportedView);
void main()
{
HINSTANCE m_hInst;
pSnmpExtensionInit m_Init;
pSnmpExtensionInitEx m_InitEx;
pSnmpExtensionQuery m_Query;
pSnmpExtensionTrap m_Trap;
HANDLE PollForTrapEvent;
AsnObjectIdentifier SupportedView;
UINT OID_ifEntryType[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 3};
UINT OID_ifEntryNum[] = {1, 3, 6, 1, 2, 1, 2, 1};
UINT OID_ipMACEntAddr[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 6};
AsnObjectIdentifier MIB_ifMACEntAddr =
{ sizeof(OID_ipMACEntAddr) sizeof(UINT), OID_ipMACEntAddr };
AsnObjectIdentifier MIB_ifEntryType =
{sizeof(OID_ifEntryType) sizeof(UINT), OID_ifEntryType};
AsnObjectIdentifier MIB_ifEntryNum =
{sizeof(OID_ifEntryNum) sizeof(UINT), OID_ifEntryNum};
RFC1157VarBindList varBindList;
RFC1157VarBind varBind[2];
AsnInteger errorStatus;
AsnInteger errorIndex;
AsnObjectIdentifier MIB_NULL = {0, 0};
int ret;
int dtmp;
int i = 0, j = 0;
bool found = false;
char TempEthernet[13];
m_Init = NULL;
m_InitEx = NULL;
m_Query = NULL;
m_Trap = NULL;

/* Load the SNMP dll and get the addresses of the functions
necessary */
m_hInst = LoadLibrary("inetmib1.dll");
if (m_hInst < (HINSTANCE) HINSTANCE_ERROR)
{
m_hInst = NULL;
return;
}
m_Init =
(pSnmpExtensionInit) GetProcAddress(m_hInst, "SnmpExtensionInit");
m_InitEx =
(pSnmpExtensionInitEx) GetProcAddress(m_hInst,
"SnmpExtensionInitEx");
m_Query =
(pSnmpExtensionQuery) GetProcAddress(m_hInst,
"SnmpExtensionQuery");
m_Trap =
(pSnmpExtensionTrap) GetProcAddress(m_hInst, "SnmpExtensionTrap");
m_Init(GetTickCount(), &PollForTrapEvent, &SupportedView);

/* Initialize the variable list to be retrieved by m_Query */
varBindList.list = varBind;
varBind[0].name = MIB_NULL;
varBind[1].name = MIB_NULL;

/* Copy in the OID to find the number of entries in the
Inteface table */
varBindList.len = 1; /* Only retrieving one item */
SNMP_oidcpy(&varBind[0].name, &MIB_ifEntryNum);
ret =
m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus,
&errorIndex);
printf("# of adapters in this system : %in",
varBind[0].value.asnValue.number);
varBindList.len = 2;

/* Copy in the OID of ifType, the type of interface */
SNMP_oidcpy(&varBind[0].name, &MIB_ifEntryType);

/* Copy in the OID of ifPhysAddress, the address */
SNMP_oidcpy(&varBind[1].name, &MIB_ifMACEntAddr);
do
{
/* Submit the query. Responses will be loaded into varBindList.
We can expect this call to succeed a # of times corresponding
to the # of adapters reported to be in the system */
ret =
m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus,
&errorIndex);
if (!ret)
ret = 1;
else
/* Confirm that the proper type has been returned */
ret =
SNMP_oidncmp(&varBind[0].name, &MIB_ifEntryType,
MIB_ifEntryType.idLength); if (!ret) {
j++;
dtmp = varBind[0].value.asnValue.number;
printf("Interface #%i type : %in", j, dtmp);

/* Type 6 describes ethernet interfaces */
if (dtmp == 6)
{

/* Confirm that we have an address here */
ret =
SNMP_oidncmp(&varBind[1].name, &MIB_ifMACEntAddr,
MIB_ifMACEntAddr.idLength);
if ((!ret) && (varBind[1].value.asnValue.address.stream != NULL))
{
if((varBind[1].value.asnValue.address.stream[0] == 0x44)
&& (varBind[1].value.asnValue.address.stream[1] == 0x45)
&& (varBind[1].value.asnValue.address.stream[2] == 0x53)
&& (varBind[1].value.asnValue.address.stream[3] == 0x54)
&& (varBind[1].value.asnValue.address.stream[4] == 0x00))
{
/* Ignore all dial-up networking adapters */
printf("Interface #%i is a DUN adaptern", j);
continue;
}
if ((varBind[1].value.asnValue.address.stream[0] == 0x00)
&& (varBind[1].value.asnValue.address.stream[1] == 0x00)
&& (varBind[1].value.asnValue.address.stream[2] == 0x00)
&& (varBind[1].value.asnValue.address.stream[3] == 0x00)
&& (varBind[1].value.asnValue.address.stream[4] == 0x00)
&& (varBind[1].value.asnValue.address.stream[5] == 0x00))
{
/* Ignore NULL addresses returned by other network
interfaces */
printf("Interface #%i is a NULL addressn", j);
continue;
}
sprintf(TempEthernet, "%02x%02x%02x%02x%02x%02x",
varBind[1].value.asnValue.address.stream[0],
varBind[1].value.asnValue.address.stream[1],
varBind[1].value.asnValue.address.stream[2],
varBind[1].value.asnValue.address.stream[3],
varBind[1].value.asnValue.address.stream[4],
varBind[1].value.asnValue.address.stream[5]);
printf("MAC Address of interface #%i: %sn", j,
TempEthernet);}
}
}
} while (!ret); /* Stop only on an error. An error will occur
when we go exhaust the list of interfaces to
be examined */
getch();
FreeLibrary(m_hInst);
/* Free the bindings */
SNMP_FreeVarBind(&varBind[0]);
SNMP_FreeVarBind(&varBind[1]);
}
回复
chuanke 2005-02-01
Method 1 - Using the Netbios API
This method of getting your computer's MAC address uses Microsoft's Netbios API. This is a set of commands that enables lower-level network support than provided by say Winsock. The disadvantage to using Netbios to determine your address is that you must have Netbios installed (not really a problem if you are on a Windows network and use file sharing). Otherwise this method is quick and accurate.

The Netbios API includes only one function, called simply Netbios. This function takes a network control block structure as its parameter, which tells it what it needs to do. The structure is defined as follows:

typedef struct _NCB {
UCHAR ncb_command;
UCHAR ncb_retcode;
UCHAR ncb_lsn;
UCHAR ncb_num;
PUCHAR ncb_buffer;
WORD ncb_length;
UCHAR ncb_callname[NCBNAMSZ];
UCHAR ncb_name[NCBNAMSZ];
UCHAR ncb_rto;
UCHAR ncb_sto;
void (CALLBACK *ncb_post) (struct _NCB *);
UCHAR ncb_lana_num;
UCHAR ncb_cmd_cplt;
#ifdef _WIN64
UCHAR ncb_reserve[18];
#else
UCHAR ncb_reserve[10];
#endif
HANDLE ncb_event;
} NCB, *PNCB;



Focus especially on the ncb_command member. This is the member that tells Netbios what to do. We will use 3 commands in determining the MAC address. They are defined on MSDN as follows:

Command Description
NCBENUM Windows NT/2000: Enumerates LAN adapter (LANA) numbers. When this code is specified, the ncb_buffer member points to a buffer to be filled with a LANA_ENUM structure.

NCBENUM is not a standard NetBIOS 3.0 command.
NCBRESET Resets a LAN adapter. An adapter must be reset before it can accept any other NCB command that specifies the same number in the ncb_lana_num member.
NCBASTAT Retrieves the status of either a local or remote adapter. When this code is specified, the ncb_buffer member points to a buffer to be filled with an ADAPTER_STATUS structure, followed by an array of NAME_BUFFER structures.


Here are the steps to getting the MAC address(es) of your system:

Enumerate the adaptors
Reset each adaptor to get proper information from it
Query the adaptor to get the MAC address and put it in standard colon-separated format
The code below provides a simple illustration of these concepts. For more information on Netbios functions, refer to the Microsoft help files or MSDN.

netbios.cpp
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

using namespace std;
#define bzero(thing,sz) memset(thing,0,sz)

bool GetAdapterInfo(int adapter_num, string &mac_addr)
{
// Reset the LAN adapter so that we can begin querying it
NCB Ncb;
memset(&Ncb, 0, sizeof(Ncb));
Ncb.ncb_command = NCBRESET;
Ncb.ncb_lana_num = adapter_num;
if (Netbios(&Ncb) != NRC_GOODRET) {
mac_addr = "bad (NCBRESET): ";
mac_addr += string(Ncb.ncb_retcode);
return false;
}

// Prepare to get the adapter status block
bzero(&Ncb,sizeof(Ncb);
Ncb.ncb_command = NCBASTAT;
Ncb.ncb_lana_num = adapter_num;
strcpy((char *) Ncb.ncb_callname, "*");
struct ASTAT
{
ADAPTER_STATUS adapt;
NAME_BUFFER NameBuff[30];
} Adapter;
bzero(&Adapter,sizeof(Adapter));
Ncb.ncb_buffer = (unsigned char *)&Adapter;
Ncb.ncb_length = sizeof(Adapter);

// Get the adapter's info and, if this works, return it in standard,
// colon-delimited form.
if (Netbios(&Ncb) == 0)
{
char acMAC[18];
sprintf(acMAC, "%02X:%02X:%02X:%02X:%02X:%02X",
int (Adapter.adapt.adapter_address[0]),
int (Adapter.adapt.adapter_address[1]),
int (Adapter.adapt.adapter_address[2]),
int (Adapter.adapt.adapter_address[3]),
int (Adapter.adapt.adapter_address[4]),
int (Adapter.adapt.adapter_address[5]));
mac_addr = acMAC;
return true;
}
else
{
mac_addr = "bad (NCBASTAT): ";
mac_addr += string(Ncb.ncb_retcode);
return false;
}
}

int main()
{
// Get adapter list
LANA_ENUM AdapterList;
NCB Ncb;
memset(&Ncb, 0, sizeof(NCB));
Ncb.ncb_command = NCBENUM;
Ncb.ncb_buffer = (unsigned char *)&AdapterList;
Ncb.ncb_length = sizeof(AdapterList);
Netbios(&Ncb);

// Get all of the local ethernet addresses
string mac_addr;
for (int i = 0; i < AdapterList.length - 1; ++i)
{
if (GetAdapterInfo(AdapterList.lana[i], mac_addr))
{
cout << "Adapter " << int (AdapterList.lana[i]) <<
"'s MAC is " << mac_addr << endl;
}
else
{
cerr << "Failed to get MAC address! Do you" << endl;
cerr << "have the NetBIOS protocol installed?" << endl;
break;
}
}

return 0;
}

回复
chuanke 2005-02-01
http://support.microsoft.com/default.aspx?scid=kb;en-us;118623
回复
KeNan_Net 2005-02-01
typedef struct tagASTAT
{
ADAPTER_STATUS adapt;
NAME_BUFFER NameBuff [30];
}ASTAT,*LPASTAT;

ASTAT Adapter

接上面的
回复
KeNan_Net 2005-02-01
用NetBEUI协议获得MAC地址
GetMacAddress(LPMAC_ADDRESS pMacAddr)
{
NCB ncb;
UCHAR uRetCode;
int num = 0;
LANA_ENUM lana_enum;
memset(&ncb, 0, sizeof(ncb) );
ncb.ncb_command = NCBENUM;
ncb.ncb_buffer = (unsigned char *)&lana_enum;
ncb.ncb_length = sizeof(lana_enum);
//向网卡发送NCBENUM命令,以获取当前机器的网卡信息,如有多少个网卡
//每张网卡的编号等
uRetCode = Netbios(&ncb);
if (uRetCode == 0)
{
num = lana_enum.length;
//对每一张网卡,以其网卡编号为输入编号,获取其MAC地址
for (int i = 0; i < num; i++)
{
ASTAT Adapter;
if(GetAddressByIndex(lana_enum.lana[i],Adapter) == 0)
{
pMacAddr[i].b1 = Adapter.adapt.adapter_address[0];
pMacAddr[i].b2 = Adapter.adapt.adapter_address[1];
pMacAddr[i].b3 = Adapter.adapt.adapter_address[2];
pMacAddr[i].b4 = Adapter.adapt.adapter_address[3];
pMacAddr[i].b5 = Adapter.adapt.adapter_address[4];
pMacAddr[i].b6 = Adapter.adapt.adapter_address[5];
}
}
}
return num;
}
回复
KeNan_Net 2005-02-01
使用TCP/IP协议
用iphlpapi.h中的
DWOR GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo,
PULONG pOutBufLen)

如果用NetBEUI协议就要用别的方法获得MAC地址了,
获得MAC地址方法很多,主要和协议有关
回复
ypos 2005-02-01
大家请看清楚我的问题是什么
回复
kingzai 2005-02-01
#include "pcap.h"

main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int i=0;
char errbuf[PCAP_ERRBUF_SIZE];

/* Retrieve the device list *//*取得网卡列表*/
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}

/* Print the list */
for(d=alldevs;d;d=d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)\n", d->description);
else printf(" (No description available)\n");
}

if(i==0)
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return;
}

/* We don't need any more the device list. Free it */
pcap_freealldevs(alldevs);
}

在WIND2000下,输出结果如下:


1. {4E273621-5161-46C8-895A-48D0E52A0B83} (Realtek RTL8029(AS) Ethernet Adapter)
2. {5D24AE04-C486-4A96-83FB-8B5EC6C7F430} (3Com EtherLink PCI)
回复
ypos 2005-02-01
老兄,我现在主要是要用winpcap,又不是专门用它来取得mac,我早就搜过了
回复
发动态
发帖子
网络编程
创建于2007-09-28

1.8w+

社区成员

VC/MFC 网络编程
申请成为版主
社区公告
暂无公告