QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 3323|回复: 14

请教读网卡MAC地址,不要ifconfig

[复制链接]
发表于 2003-6-16 11:52:43 | 显示全部楼层 |阅读模式
请问如何在LINUX C中读一下本机的网卡 MAC地址?

ifconfig是控制台命令

我是想问有没有相关的函数或例程可以在程序中直接用
发表于 2003-6-16 12:31:49 | 显示全部楼层
ifconfig
回复

使用道具 举报

 楼主| 发表于 2003-6-16 12:45:05 | 显示全部楼层
ifconfig是控制台命令

我是想问有没有相关的函数或例程可以在程序中直接用
回复

使用道具 举报

发表于 2003-6-16 13:55:52 | 显示全部楼层
我的办法是创建一个sock_packet类型的套接口
然后用ioctl从中读到hwaddr再分离出mac地址
回复

使用道具 举报

发表于 2003-6-16 14:04:50 | 显示全部楼层
a small program I've written up, so that hopefully other people won't have to go through the same learning curve I did with SNMP. I will also attach a file, snmpapi.cpp, that was written by Stas Khirman and distributed on his web page.

[code:1]snmpmac.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()
{
    WSADATA WinsockData;
    if (WSAStartup(MAKEWORD(2, 0), &WinsockData) != 0) {
        fprintf(stderr, "This program requires Winsock 2.x!\n");
        return;
    }

    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
    };                          //, 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 : %i\n",
           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 : %i\n", 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 adapter\n", 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 address\n", 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: %s\n", 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();

    /* Free the bindings */
    SNMP_FreeVarBind(&varBind[0]);
    SNMP_FreeVarBind(&varBind[1]);
}
[/code:1]

[code:1]snmpapi.cpp
/******************************************************************
*
*      Copyright (C) Stas Khirman 1998.  All rights reserved.         
*                                                                     
*       This program is distributed WITHOUT ANY WARRANTY
*
*******************************************************************/

/*************************************************
*     
*       Reproduction of SNMP.LIB and SNMPAPI.LIB base
*           functions
*
* Author: Stas Khirman ([email protected])
*
*
* Free software: no warranty; use anywhere is ok; spread the      
* sources; note any modifications; share variations and           
* derivatives (including sending to [email protected]).      
*                                                                     
*
*************************************************/
#include <snmp.h>

SNMPAPI
SNMP_FUNC_TYPE
SnmpUtilOidCpy(
    OUT AsnObjectIdentifier *DstObjId,
    IN  AsnObjectIdentifier *SrcObjId
    )
{
  DstObjId->ids = (UINT *)GlobalAlloc(GMEM_ZEROINIT,SrcObjId->idLength *
          sizeof(UINT));
  if(!DstObjId->ids){
    SetLastError(1);
    return 0;
  }

  memcpy(DstObjId->ids,SrcObjId->ids,SrcObjId->idLength*sizeof(UINT));
  DstObjId->idLength = SrcObjId->idLength;

  return 1;
}


VOID
SNMP_FUNC_TYPE
SnmpUtilOidFree(
    IN OUT AsnObjectIdentifier *ObjId
    )
{
  GlobalFree(ObjId->ids);
  ObjId->ids = 0;
  ObjId->idLength = 0;
}

SNMPAPI
SNMP_FUNC_TYPE
SnmpUtilOidNCmp(
    IN AsnObjectIdentifier *ObjIdA,
    IN AsnObjectIdentifier *ObjIdB,
    IN UINT                 Len
    )
{
  UINT CmpLen;
  UINT i;
  int  res;

  CmpLen = Len;
  if(ObjIdA->idLength < CmpLen)
    CmpLen = ObjIdA->idLength;
  if(ObjIdB->idLength < CmpLen)
    CmpLen = ObjIdB->idLength;

  for(i=0;i<CmpLen;i++){
    res = ObjIdA->ids[i] - ObjIdB->ids[i];
    if(res!=0)
      return res;
  }
  return 0;
}

VOID
SNMP_FUNC_TYPE
SnmpUtilVarBindFree(
    IN OUT RFC1157VarBind *VarBind
    )
{
  BYTE asnType;
  // free object name
  SnmpUtilOidFree(&VarBind->name);

  asnType = VarBind->value.asnType;

  if(asnType==ASN_OBJECTIDENTIFIER){
    SnmpUtilOidFree(&VarBind->value.asnValue.object);
  }
  else if(
        (asnType==ASN_OCTETSTRING) ||
        (asnType==ASN_RFC1155_IPADDRESS) ||
        (asnType==ASN_RFC1155_OPAQUE) ||
        (asnType==ASN_SEQUENCE)){
    if(VarBind->value.asnValue.string.dynamic){
      GlobalFree(VarBind->value.asnValue.string.stream);
    }
  }

  VarBind->value.asnType = ASN_NULL;

}
[/code:1]
回复

使用道具 举报

 楼主| 发表于 2003-6-16 16:21:19 | 显示全部楼层
To:CNOOC
这个是windows程序
在LINUX上可以运行吗?
回复

使用道具 举报

发表于 2003-6-16 17:58:54 | 显示全部楼层
#define MAC_ADDR_LEN 6

int get_macaddr(char * eth, unsigned char * buf)
{
    struct ifreq ifr;
    int fd;

    bzero(&ifr, sizeof(ifr));
    strcpy(ifr.ifr_name, eth);
    fd = socket(PF_INET, SOCK_DGRAM, 0);
       
    if (fd < 0)
    {
        printf("socket error\n");
        return -1;
    }
    if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0)
    {
        printf("ioctl get hardware address error\n");
        close(fd);
        return -1;
    }
    else
    {
        int i;
        for(i=0; i<MAC_ADDR_LEN; i++){
                sprintf(&(buf[i*2]),"%02x",(unsigned char)(ifr.ifr_hwaddr.sa_data));
        }
        buf[i*2]='\0';
//printf("hw addr: %s\n",buf);
        close(fd);
        return i*2;
    }
}
回复

使用道具 举报

发表于 2003-6-16 18:02:14 | 显示全部楼层
cnooc那个是...snmp的程序啊
回复

使用道具 举报

 楼主| 发表于 2003-6-16 19:36:00 | 显示全部楼层
感谢各位的帮助!!

最后按windychen的方法搞定了。

再次感谢windychen
回复

使用道具 举报

发表于 2003-6-17 13:22:03 | 显示全部楼层
好说好说,呵呵
回复

使用道具 举报

发表于 2003-6-17 22:27:40 | 显示全部楼层
关于硬件的很多信息读取和设定都可以使用ioctl函数来实现,因为绝大部分的设备都会提供ioctl接口,要正确使用它,读相应的设备描述头文件。里面会定义很多的IOCTL命令,还有相应的使用到的数据结构,多半是些结构体,它做为ioctl函数的第三个参数,可以作为传入数据使用,也可以作为传出数据使用。
ioctl是一把瑞士军刀,请大家多多使用。可惜我有很长时间没有用了,快生锈了。
;)
回复

使用道具 举报

发表于 2003-6-18 09:23:37 | 显示全部楼层
好东西,加精华,
windyche和caveman是否可以详细的讲解一下ioctl的用法?
授人以鱼不如授人以渔   
回复

使用道具 举报

发表于 2003-6-18 20:21:45 | 显示全部楼层
偷学中...
回复

使用道具 举报

发表于 2003-7-6 11:10:05 | 显示全部楼层
windychen说的没有错。。。

我以前写过一个程序,,需要设置MAC地址,,,通过IOCTL来完成。。

其实,MAC地址是存放在结构中的(具体哪个的我想不起来),是一个数据。各种网卡虽然都有一个EEPROM存放MAC,但是系统可以对网卡寄存器操作来把MAC读进我说的那个结构中,所以我们只要改变结构中的这个数组也就改变了MAC地址。
回复

使用道具 举报

发表于 2003-7-8 10:41:37 | 显示全部楼层
/* 分别读出MAC、NETMASK、IP ADDRESS:*/
#include<stdio.h>
#include<string.h>
#include<netdb.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/ioctl.h>
#include<net/if.h>
#include<net/if_arp.h>
#include<net/ethernet.h>
#include<signal.h>
#include<netinet/ip.h>

struct in_addr myip,mymask;
int fd_arp;        /* socket fd for receive packets */
struct ifreq ifr;  /* ifr structure */
main(int argc,char *argv[])
{
    char device[32];   /* ethernet device name */
    struct sockaddr from,to;
    int fromlen;
    struct sockaddr_in *sin_ptr;
    u_char *ptr;
    int n;
    strcpy(device,"eth0");
    if((fd_arp = socket(AF_INET,SOCK_PACKET,htons(0x0806)))<0)
        exit(-1);
    }
    strcpy(ifr.ifr_name,device);
    /* ifr.ifr_addr.sa_family = AF_INET; */
    /* get ip address of my interface */
    if(ioctl(fd_arp,SIOCGIFADDR,&ifr)<0)
    {
        perror("ioctr SIOCGIFADDR error");
        exit(-1);
    }
    sin_ptr = (struct sockaddr_in *)&ifr.ifr_addr;
    myip = sin_ptr->sin_addr;
    /* get network mask of my interface */
    if(ioctl(fd_arp,SIOCGIFNETMASK,&ifr)<0)
        {
            perror("ioctr SIOCGIFNETMASK error");
            exit(-1);
        }
    sin_ptr = (struct sockaddr_in *)&ifr.ifr_addr;
    mymask = sin_ptr->sin_addr;
    /* get mac address of the interface */
    if(ioctl(fd_arp,SIOCGIFHWADDR,&ifr)<0)
        {
            perror("ioctr SIOCGIFHWADDR error");
            exit(-1);
        }
    ptr = (u_char *)&ifr.ifr_ifru.ifru_hwaddr.sa_data[0];
    printf("request mac: %02x:%02x:%02x:%02x:%02x:%02x\n",*ptr,*(ptr+1),*(ptr+2),*(ptr+3),*(ptr+4),
*(ptr+5));
    printf("request netmask: %s\n",inet_ntoa(mymask));
    printf("request IP: %s\n",inet_ntoa(myip));
}
/* end of main */
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-15 13:52 , Processed in 0.086478 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表