Three methods for obtaining MAC addresses

Source: Internet
Author: User
Tags snmp
The first method is to use Microsoft's NetBIOS API. This is a set of commands that provide underlying network support through Winsock. The biggest disadvantage of using NetBIOS is that you must install NetBIOS in the system (if file sharing is enabled in windows, this is not a problem ). In addition, this method is fast and accurate.

The NetBIOS API contains only one function, called NetBIOS. This function uses the network control block structure as a parameter, which tells the function what 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_rj_cplt;
# Ifdef _ win64
Uchar ncb_reserve [18];
# Else
Uchar ncb_reserve [10];
# Endif
Handle ncb_event;
} NCB, * PNCB;

The focus is on ncb_command members. This member tells NetBIOS what to do. We use three commands to detect MAC addresses. Their definitions on msdn are as follows:

Command description:

Ncbenum Windows NT/2000: lists the number of NICs in the system. With this command, the ncb_buffer Member points to the buffer filled by the lana_enum structure.

Ncbenum is not a standard NetBIOS 3.0 command.

Ncbreset resets the NIC. The NIC must be reset before accepting the new NCB command.

Ncbastat accepts the status of the local or remote interface card. With this command, the ncb_buffer Member points to the buffer filled by the adapter_status structure, followed by an array of the name_buffer structure.

To obtain the MAC address of your system, follow these steps:

1. List all interface cards.

2. Reset each card to obtain the correct information.

3. query the interface card, obtain the MAC address, and generate a standard colon separation format.

The following is the source program of the instance.

# Include <windows. h>
# Include <stdlib. h>
# Include <stdio. h>
# Include <iostream>
# Include <string>
# Pragma comment (Lib, "netapi32.lib ")

Using namespace STD;
# Define bzero (thing, SZ) memset (thing, 0, SZ)

Bool getadapterinfo (INT adapter_num, string & mac_addr)
{
// Reset the NIC so that we can query
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 ):";
Const char retcode = NCB. ncb_retcode;
Mac_addr + = string (& retcode );
Return false;
}

// Prepare to obtain the status block of the Interface Card
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 );

// Obtain the information of the NIC. If the NIC works normally, the standard colon separation format is returned.
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 ):";
Const char retcode = NCB. ncb_retcode;
Mac_addr + = string (& retcode );
Return false;
}
}

Int main ()
{
// Obtain the NIC list
Lana_enum adapterlist;
NCB;
Memset (& NCB, 0, sizeof (NCB ));
NCB. ncb_command = ncbenum;
NCB. ncb_buffer = (unsigned char *) & adapterlist;
NCB. ncb_length = sizeof (adapterlist );
NetBIOS (& NCB );

// Obtain the address of the local Ethernet Card
String mac_addr;
Int nlen = adapterlist. length;
For (INT I = 0; I <nlen-1; ++ I)
{
If (getadapterinfo (adapterlist. Lana [I], mac_addr ))
{
Cout <"adapter" <int (adapterlist. Lana [I]) <
"''' 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;
}

 

Method 2-Use the com guid API

This method uses the com api to create a guid (globally unique identifier) and inherit the MAC address from it. GUID is usually used to identify COM components and other objects in the system. They are calculated from MAC addresses (combined with other things). On the surface, MAC addresses are included in them. On the surface, it is because it is not actually included.

I provide this method to serve as a negative textbook. You may use this method to obtain the MAC address, but sometimes you will only get a random hexadecimal value.

The example below is very simple and does not need to be discussed. We use cocreateguid to create a guid and put the last six bytes into the string. They may be MAC addresses, but they are not necessary.

UUID. cpp

# Include <windows. h>
# Include <iostream>
# Include <conio. h>
Using namespace STD;
Int main ()
{
Cout <"MAC address is :";
// Request a uuid from Com. If the machine has an Ethernet card,
// The last six bytes of UUID (2-7 bytes of data4) should be the MAC address of the local ethernet card.
Guid UUID;
Cocreateguid (& UUID );
// Spit the address out
Char mac_addr [18];
Sprintf (mac_addr, "% 02x: % 02x: % 02x: % 02x: % 02x: % 02x ",
UUID. data4 [2], UUID. data4 [3], UUID. data4 [4],
UUID. data4 [5], UUID. data4 [6], UUID. data4 [7]);
Cout <mac_addr <Endl;
Getch ();
Return 0;
}

Method 3-use SNMP to expand the API

The third method I want to discuss is to use the SNMP (Simple Network Management Protocol) Extension of windows to obtain the MAC address. In my experience, this protocol is very simple. The Code is also checked forward. The basic steps are the same as those of NETBIOS:

1. Obtain the NIC list

2. query the type and MAC address of each card

3. I personally do not know much about SNMP when saving the current Nic, but the code is very clear as I said just now.

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 ASNO

{
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 obtain the instance handle */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 used to receive m_query query results */
Varbindlist. List = varbind;
Varbind [0]. Name = mib_null;
Varbind [1]. Name = mib_null;
/* Copy and search for the number of entries in the interface table in the oId */
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 the iftype of the oId-interface type */
Snmp_oidcpy (& varbind [0]. Name, & mib_ifentrytype );
/* Copy the oId ifphysaddress-physical address */
Snmp_oidcpy (& varbind [1]. Name, & mib_ifmacentaddr );
Do
{
/* Submit the query and the result is loaded into varbindlist.
It is expected that the number of calls in this loop is equal to the number of interface cards in the system */
Ret =
M_query (asn_rfc1157_getnextrequest, & varbindlist, & errorstatus,
& Errorindex );
If (! RET)
Ret = 1;
Else
/* Confirm the correct return type */
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 obtained the 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 network interface cards */
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 the null address returned by other network interface cards */
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);/* termination due to an error. */
Getch ();
Freelibrary (m_hinst );
/* Unbind */
Snmp_freevarbind (& varbind [0]);
Snmp_freevarbind (& varbind [1]);
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.