请问winpcap中如果获取本机网卡地址?

解决方案 »

  1.   

    http://community.csdn.net/Expert/FAQ/FAQ_Index.asp?id=204183
      

  2.   

    winpcap官方网站:winpcap.polito.it
    winpcap的源代码中带了很多例子,从很简单的例子到比较复杂的例子都有
      

  3.   

    不好意思,可能我没有说清楚,是网卡的MAC地址
      

  4.   

    winpcap自带的TestApp例子中,获得的MAC头中源MAC就是本机网卡地址.
    基本上每个winpcap程序都可以得到
      

  5.   

    数据链路层mac头,以太网帧类型(2字节)+源MAC(6字节)+目的MAC(6字节)
      

  6.   

    wincap不是有源代码嘛,很好找到。
      

  7.   

    /*
     * Copyright (c) 1999 - 2004
     * NetGroup, Politecnico di Torino (Italy)
     * 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 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 <stdio.h>
    #include <conio.h>
    #include "..\..\..\Include\packet32.h"
    #include "..\..\..\Include\ntddndis.h"#define Max_Num_Adapter 10
    char AdapterList[Max_Num_Adapter][1024];int main()
    {
    LPADAPTER lpAdapter = 0;
    int i;
    DWORD dwErrorCode;
    char AdapterName[8192];
    char *temp,*temp1;
    int AdapterNum=0,Open;
    ULONG AdapterLength;
    PPACKET_OID_DATA  OidData;
    BOOLEAN Status;

    //
    // Obtain the name of the adapters installed on this machine
    // printf("Packet.dll test application. Library version:%s\n", PacketGetVersion());

    printf("Adapters installed:\n");
    i=0;

    AdapterLength = sizeof(AdapterName);

    if(PacketGetAdapterNames(AdapterName,&AdapterLength)==FALSE){
    printf("Unable to retrieve the list of the adapters!\n");
    return -1;
    }
    temp=AdapterName;
    temp1=AdapterName; while ((*temp!='\0')||(*(temp-1)!='\0'))
    {
    if (*temp=='\0') 
    {
    memcpy(AdapterList[i],temp1,temp-temp1);
    temp1=temp+1;
    i++;
    }
    temp++;
    }
      
    AdapterNum=i;
    for (i=0;i<AdapterNum;i++)
    printf("\n%d- %s\n",i+1,AdapterList[i]);
    printf("\n");
    do 
    {
    printf("Select the number of the adapter to open : ");
    scanf("%d",&Open);
    if (Open>AdapterNum) printf("\nThe number must be smaller than %d",AdapterNum); 
    } while (Open>AdapterNum);
    //
    // Open the selected adapter
    // lpAdapter =   PacketOpenAdapter(AdapterList[Open-1]);

    if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE))
    {
    dwErrorCode=GetLastError();
    printf("Unable to open the adapter, Error Code : %lx\n",dwErrorCode);  return -1;
    } // 
    // Allocate a buffer to get the MAC adress
    // OidData = malloc(6 + sizeof(PACKET_OID_DATA));
    if (OidData == NULL) 
    {
    printf("error allocating memory!\n");
    PacketCloseAdapter(lpAdapter);
    return -1;
    } // 
    // Retrieve the adapter MAC querying the NIC driver
    // OidData->Oid = OID_802_3_CURRENT_ADDRESS; OidData->Length = 6;
    ZeroMemory(OidData->Data, 6);

    Status = PacketRequest(lpAdapter, FALSE, OidData);
    if(Status)
    {
    printf("The MAC address of the adapter is %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
    (PCHAR)(OidData->Data)[0],
    (PCHAR)(OidData->Data)[1],
    (PCHAR)(OidData->Data)[2],
    (PCHAR)(OidData->Data)[3],
    (PCHAR)(OidData->Data)[4],
    (PCHAR)(OidData->Data)[5]);
    }
    else
    {
    printf("error retrieving the MAC address of the adapter!\n");
    } free(OidData);
    PacketCloseAdapter(lpAdapter);
    return (0);
    }
      

  8.   

    看来我还是说得不够清楚,我现在通过Winpcap捕获数据包,我要判断捕获的数据包是本机发出去的、还是本机收到的,我想通过比较MAC地址来判断,所以我首先要获取本机的MAC地址,获取方法必须也能在Win 95/NT上运行
      

  9.   

    winpcap本身就有提供win98下的接口.
    获取本机mac地址可以使用netbios,也可以使用iphelper api获取.
    http://www.teacherli.com/info11/ask280122.htm
      

  10.   

    最后想确定一下winpcap有没有直接的方式,然后就要结贴了
      

  11.   

    不用winpcap 就有直接的方法 我记得有个贴 讲了很多种得到mac的方法 搜一下吧
      

  12.   

    老兄,我现在主要是要用winpcap,又不是专门用它来取得mac,我早就搜过了
      

  13.   

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

  14.   

    使用TCP/IP协议
    用iphlpapi.h中的
    DWOR GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo,
                         PULONG pOutBufLen)如果用NetBEUI协议就要用别的方法获得MAC地址了,
    获得MAC地址方法很多,主要和协议有关
      

  15.   

    用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;
    }
      

  16.   

    typedef struct tagASTAT 

        ADAPTER_STATUS adapt; 
        NAME_BUFFER    NameBuff [30]; 
    }ASTAT,*LPASTAT;ASTAT Adapter接上面的
      

  17.   

    http://support.microsoft.com/default.aspx?scid=kb;en-us;118623
      

  18.   

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

  19.   

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

  20.   

    从捕获的IP头就可以看出来了.用不着MAC头
      

  21.   

    非IP包也好办,winpcap抓包是每次都能抓到mac头的,源MAC也就是你本机的MAC地址肯定是每次都相同的,而目的MAC可能都不一样.
      

  22.   

    源MAC也就是你本机的MAC地址?(谁说的?)现在放宽要求了,获取网卡5D24AE04-C486-4A96-83FB-8B5EC6C7F430对应的MAC地址