Lan card에서 mac address 읽는 방법

은영신랑의 이미지

이건 제 생각인데요.
PCI Configuration 중에서 Expasion ROM Base Address에 Lan card의
정보가 들어있는 EEPROM의 base address가 들어있고,
운영체제나 그런데서는 그 어드레스를 이용해서 MAC address를 읽어들이는것이라고 생각되는데요.

제 RTL8029를 보면 그 부분이 00000000 으로 되어 있거든요.
제가 틀린것인가요?

답변좀 부탁드리겠습니다.

mach의 이미지

1) Memory Mapped
특정 주소를 매핑하여 그 주소에 읽고 쓰는 일반연산( move 연산자)을 이용하여 IO를 수행하는 경우
모토롤라칩이나, RISC계열 프로세서
2) Programmed
IO를 위한 별도의 명령어를 사용하는 경우로 별도의 명령은 In, out등의 니모닉이나 유사한 형태를 가짐.(일반 메모리와 IO를 별도로 분리하여 취급)
인텔계열 프로세서, IBM기종
3) DMA
대량의 데이터를 IO하는 경우에 IO장치에 있는 주프로세서가(IO장치에서는 CPU) 메인보드의 버스를 사용할 수 있도록 하드웨어가 제작되어있는경우에도 사용가능하며, IO장치에 있는 메모리를 주 기억장치와 맵핑시켜주거나, 주기억장치의 메모리를 IO장치가 직접액세스하게 맵핑시켜서 사용하게된다.
하드디스크, 기가비트랜카드등

* 님이 생각하시는 것은 1)번 유형인듯한데요. 이 경우에도 IO주소가 일정하지 않습니다. 같은 종류의 IO장치일찌라도 IO주소는 다소 틀려질 수 있습니다. 대부분 인텔계열이라면 in, out명령을 사용하여 특정주소(IO프로세서의 레지스터)에 값을 쓰면 특정주소(IO프로세서의 레지스터)에 IO프로세서가 그 결과값을 세팅하고 주프로그램에서는 나중에 다시 그 값을 읽어보는(in) 형태가 되는 경우가 많습니다.
이러한 IO장치들은 매 장치마다 그 핸들링 방식이 차이가 있고, 기능에서도 다소간 차이를 가집니다. 그래서, IO장치들의 처리루틴은 운영체제제작자가 제작한다기 보다는 하드웨어제작자가 레퍼런스를 제공하는 유형이 되는 경우가 많습니다. 하드웨어 제작자는 자신의 스펙을 제시한다기 보다는 메이저운영체제의 디바이스드라이버를 제작해서 제공하는 유형이 많이 있습니다. 디바이스 드라이버는 하드웨어 제작자의 의도대로 되는 경우보다는 운영체제 제작자의 의도대로 되는 경우가 많습니다. 특정 운영체제를 지원하기 위한 wrapping이라도 제공하는게 보통입니다.

*여담
하드웨어 제작자와 별도로, 많은 훌륭한(?) 해커들이 디바이스 드라이버를 직접제작해서 제공해주기도 합니다. 몇몇 실제사례에서는 하드웨어 제작자보다 더욱 훌륭한(고성능) 디바이스 드라이버를 제작해서 보급한 사례는 많이 있습니다. 또한가지, 그러한 디바이스 드라이버를 하드웨어 업체가 겸허하게 수용하고 이를 오히려 자랑스럽게 홈페이지에 게제한 경우는 귀감이 되기도 합니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

mach의 이미지

에고 질문에는 답변을 못하고 헛소리를 한듯합니다.
참고로, 랜카드의 MAC주소는 ioctl()을 사용하여 읽어 보심이 좋을 듯합니다.
유닉스/리눅스는 공히 디바이스드라이버를 제작할때, 몇몇개의 특정 루틴을 제작하게 되어있는데, 그 특정루틴중 ioctl()은 장치에 의존적인 루틴이 내제되게 되어있습니다. ioctl()을 호출하여 그 장치의 특정 기능을 수행할 수 있습니다.
특히, 랜카드의 경우에는 mac주소를 가지게 되는데, 이또한 그 루틴을 사용해서 읽을 수 있습니다. ioctl()을 사용하여 mac주소를 읽는 법은 스티븐스의 unix network programming 2nd edition을 보면 잘 나와있습니다.

또한가지는, 유닉스/리눅스/윈도우등의 운영체제에 걸쳐 포괄적으로 네트워크장치에 대한 제어를 수행하는 루틴을 wrapping한 라이브러를 사용할 수도 있겠습니다. http://www.packetfactory.net/Projects/Libnet/은 libnet에 대한 링크인데, 이를 참조하셔도 좋을듯합니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

은영신랑의 이미지

우선 답변 감사드리고요.

쉽게 생각했었는데 그런것 같지만은 않네요.
우선 책이나 다른 소스좀 더 보고 공부좀 해야겠네요.

익명 사용자의 이미지

이것은 제가 예전에 공개했던 소스입니다.
그런데 x86 linux에서는 이것이 잘 동작합니다.
하지만 어떤 분께서 조언하신 내용중에서
이것에 대하여 지적해주신 분이 있었습니다.
이것이 모든 시스템에 이식되는 코드는 아니라는 겁니다.
저로서도 100% 이식되는 코드를 만들어 공개하고픈 마음은
굴뚝같으나 방법을 모르겠군요.

/*
 Copyright (c) 2002 Information Equipment co.,LTD.
 All Right Reserved.

 Code by JaeHyuk Cho <minzkn@infoeq.co.kr>

 - Simple is best
 
*/

#if !defined(DEF_ifconfig_c)
#define DEF_ifconfig_c "ifconfig.c"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <netdb.h>

int main(int s_Argc, char **s_Argv);

int main(int s_Argc, char **s_Argv)
{
 int s_SocketHandle;	
 int s_RequestCount = 10;
 struct ifconf s_ifconfig;
 struct ifreq *s_ifrequest;
 struct sockaddr_in *s_SockAddr_In;
 
 char s_StringBuffer[1 << 10];
 char *s_MyTitle;
 char *s_MyDevice;
 char *s_MyIP, *s_MyBroadcastIP, *s_MyNetmaskIP;
 char *s_MyHWAddr;
 char *s_MyFlagString;
 int  s_MyFlags, s_MyMTU, s_MyMetric;
 fprintf(stdout, "MZ_ifconfig v0.0.1b - Copyright(c)InfoEQ co.,LTD - %s %s\n", __DATE__, __TIME__);
 fprintf(stdout, "Code by JaeHyuk Cho - <minzkn@infoeq.co.kr>\n\n");
 s_SocketHandle = socket(AF_INET, SOCK_DGRAM, 0);
 if(s_SocketHandle >= 0)
 {
  memset((void *)&s_ifconfig, 0, sizeof(struct ifconf));
  do
  {
   if(s_ifconfig.ifc_buf)free(s_ifconfig.ifc_buf);
   s_ifconfig.ifc_len = sizeof(struct ifreq) * s_RequestCount;
   s_ifconfig.ifc_buf = malloc(s_ifconfig.ifc_len);
   if(s_ifconfig.ifc_buf)
   {
    if(ioctl(s_SocketHandle, SIOCGIFCONF, &s_ifconfig) == 0)
    {
     if(s_ifconfig.ifc_len < (sizeof(struct ifreq) * s_RequestCount))
     {
      s_ifrequest = s_ifconfig.ifc_req;
      if(s_ifrequest)
      {
       for(s_RequestCount = 0;s_RequestCount < s_ifconfig.ifc_len;s_RequestCount += sizeof(struct ifreq), s_ifrequest++)
       {
        /* ------------------------------------------------------------------------ */	       
	s_MyDevice = strdup(s_ifrequest->ifr_name);
	
	ioctl(s_SocketHandle, SIOCGIFADDR, s_ifrequest);        
	s_SockAddr_In       = (struct sockaddr_in *)(&s_ifrequest->ifr_addr);
        s_MyIP              = strdup(inet_ntoa(s_SockAddr_In->sin_addr));	
	ioctl(s_SocketHandle, SIOCGIFBRDADDR, s_ifrequest);        
	s_SockAddr_In       = (struct sockaddr_in *)&s_ifrequest->ifr_broadaddr;
        s_MyBroadcastIP     = strdup(inet_ntoa(s_SockAddr_In->sin_addr));	
	ioctl(s_SocketHandle, SIOCGIFNETMASK, s_ifrequest);        
	s_SockAddr_In       = (struct sockaddr_in *)&s_ifrequest->ifr_netmask;
        s_MyNetmaskIP       = strdup(inet_ntoa(s_SockAddr_In->sin_addr));	
	
	if(ioctl(s_SocketHandle, SIOCGIFHWADDR, s_ifrequest) == 0)
	{
	 unsigned char s_NullHWAddr[] = {0, 0, 0, 0, 0, 0};
         if(memcmp(&s_ifrequest->ifr_hwaddr.sa_data[0], &s_NullHWAddr[0], sizeof(s_NullHWAddr)) == 0)
	 {
          strcpy(s_StringBuffer, "");
	 }
	 else
	 {
	  sprintf(s_StringBuffer, "HWAddr %02x:%02x:%02x:%02x:%02x:%02x",
		 s_ifrequest->ifr_hwaddr.sa_data[0] & 0xff,
		 s_ifrequest->ifr_hwaddr.sa_data[1] & 0xff,
		 s_ifrequest->ifr_hwaddr.sa_data[2] & 0xff,
		 s_ifrequest->ifr_hwaddr.sa_data[3] & 0xff,
		 s_ifrequest->ifr_hwaddr.sa_data[4] & 0xff,
		 s_ifrequest->ifr_hwaddr.sa_data[5] & 0xff
	        );
	 }
	}
	else strcpy(s_StringBuffer, "HWAddr <ERROR>");
	s_MyHWAddr = strdup(s_StringBuffer);
	
	if(ioctl(s_SocketHandle, SIOCGIFFLAGS, s_ifrequest) == 0)s_MyFlags = s_ifrequest->ifr_flags;
	else s_MyFlags = 0;
       	strcpy(s_StringBuffer, "");
	if(s_MyFlags == 0)strcpy(s_StringBuffer, "[NO FLAGS]");
	else
	{
	 if(s_MyFlags & IFF_UP          )strcat(s_StringBuffer, "UP ");	
	 if(s_MyFlags & IFF_BROADCAST   )strcat(s_StringBuffer, "BROADCAST ");	
	 if(s_MyFlags & IFF_DEBUG       )strcat(s_StringBuffer, "DEBUG ");	
	 if(s_MyFlags & IFF_LOOPBACK    )strcat(s_StringBuffer, "LOOPBACK ");	
	 if(s_MyFlags & IFF_POINTOPOINT )strcat(s_StringBuffer, "POINTOPOINT ");	
	 if(s_MyFlags & IFF_NOTRAILERS  )strcat(s_StringBuffer, "NOTRAILERS ");	
	 if(s_MyFlags & IFF_RUNNING     )strcat(s_StringBuffer, "RUNNING ");	
	 if(s_MyFlags & IFF_NOARP       )strcat(s_StringBuffer, "NOARP ");	
	 if(s_MyFlags & IFF_PROMISC     )strcat(s_StringBuffer, "PROMISC ");	
	 if(s_MyFlags & IFF_ALLMULTI    )strcat(s_StringBuffer, "ALLMULTI ");	
	 if(s_MyFlags & IFF_SLAVE       )strcat(s_StringBuffer, "SLAVE ");	
	 if(s_MyFlags & IFF_MASTER      )strcat(s_StringBuffer, "MASTER ");	
	 if(s_MyFlags & IFF_MULTICAST   )strcat(s_StringBuffer, "MULTICAST ");	
	}
	s_MyFlagString = strdup(s_StringBuffer);

        s_MyTitle = strdup("Unknown"); /* Not support */ 
	
	if(ioctl(s_SocketHandle, SIOCGIFMTU, s_ifrequest) == 0)s_MyMTU = s_ifrequest->ifr_mtu;
	else s_MyMTU = 0;
	
	if(ioctl(s_SocketHandle, SIOCGIFMETRIC, s_ifrequest) == 0)s_MyMetric = s_ifrequest->ifr_metric;
	else s_MyMetric = 0;
        
	/* Print. */
	fprintf(stdout, 
		"%-8s Link encap:%s  %s\n"
		"%-8s inet addr %-15s  Broadcast %-15s  Netmask %-15s\n"
		"%-8s %s MTU:%d Metric:%d\n"
		"\n", 
	        s_MyDevice, s_MyTitle, s_MyHWAddr,
		"", s_MyIP, s_MyBroadcastIP, s_MyNetmaskIP,
		"", s_MyFlagString, s_MyMTU, s_MyMetric ? s_MyMetric : 1
	       );
	
	/* Free. */
	if(s_MyTitle      )free(s_MyTitle);
	if(s_MyDevice     )free(s_MyDevice);
	if(s_MyIP         )free(s_MyIP);
	if(s_MyBroadcastIP)free(s_MyBroadcastIP);
	if(s_MyNetmaskIP  )free(s_MyNetmaskIP);
	if(s_MyHWAddr     )free(s_MyHWAddr);
	if(s_MyFlagString )free(s_MyFlagString);
        /* ------------------------------------------------------------------------ */	       
       }
      }
      break; 
     }
     else s_RequestCount += 10; 
    }
    else break;
   }
   else break;
  }while(1);  
  if(s_ifconfig.ifc_buf)free(s_ifconfig.ifc_buf);
  close(s_SocketHandle);	  
 }
 else fprintf(stderr, "Can not open socket !!!\n");
 return(0);
}

#endif 

/* End of source */ 

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.