이 소스는 ifconfig 의 간략한 구현예제 입니다.
하지만 다양한 플랫폼을 지원하기 위해서 범용적인 코드를 원한다면
아래의 예제처럼 구현하기 보다는 pcap library 를 사용하기를 권합니다.

코드:

/*
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>
#include <netinet/ether.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 0   
   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 %s", ether_ntoa((struct ether_addr *)s_ifrequest->ifr_hwaddr.sa_data));
   }
   else strcpy(s_StringBuffer, "HWAddr <ERROR>");
#else
   if(ioctl(s_SocketHandle, SIOCGIFHWADDR, s_ifrequest) == 0)
   {
    sprintf(s_StringBuffer, "HWAddr %s", ether_ntoa((struct ether_addr *)s_ifrequest->ifr_hwaddr.sa_data));
   }
   else strcpy(s_StringBuffer, "HWAddr <ERROR>");
#endif
   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 */


위의 예제를 조금더 응용하여
현재 내가 보유한 여러개의 IP중에서 어떤 IP가 route를 통하는지
검출하는 간략한 예제입니다.
즉, 이것은 여러개의 IP를 가지고 있을때 이중에서 어떤것이
인터넷으로 패킷이 탈수 있는지 검출하는 것입니다.
물론 이것은 너무 간략하게 구현하려고 약간의 case 에 대해서 버그가 존재합니다. 그것은 적절히 코드를 보강하면 됩니다.
코드:

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

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

- Simple is best

*/

#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>
#include <unistd.h>
#include <fcntl.h>

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

int main(int s_Argc, char **s_Argv)
{
const char *c_Proc_Route = "/proc/net/route";
int s_SocketHandle, s_Handle, s_ReadBytes, s_RequestCount = 10;
struct ifconf s_ifconfig;
struct ifreq *s_ifrequest;
struct sockaddr_in *s_SockAddr_In;
char *s_MyDevice;
char *s_MyIP, *s_MyBroadcastIP, *s_MyNetmaskIP, *s_RouteIP, *s_RouteName;
char s_Buffer[ 32 << 10 ];

s_RouteIP = s_RouteName = (char *)0;
s_Handle = open(c_Proc_Route, O_RDONLY);
if(s_Handle >= 0)
{
  s_ReadBytes = read(s_Handle, &s_Buffer[0], sizeof(s_Buffer) - 1);
  close(s_Handle);
  if(s_ReadBytes > 0)
  {
   unsigned long s_Destination, s_Gateway, s_Flags, s_RefCnt, s_Use, s_Metric, s_Mask;
   char *s_TraceBuffer;
   int s_Index;
   s_Buffer[ s_ReadBytes ] = '\0';
   s_Index = 0;
   s_TraceBuffer = (char *)(&s_Buffer[s_Index]);
   do
   {
    s_RouteName = (char *)0;
    if(s_Buffer[s_Index] == '\0' || s_Buffer[s_Index] == '\n')
    {
     s_Buffer[s_Index] = '\0';
     s_RouteName = s_TraceBuffer;
     while((*s_TraceBuffer) != ' ' && (*s_TraceBuffer) != '\t' && (*s_TraceBuffer) != '\0')s_TraceBuffer++;
     *(s_TraceBuffer++) = '\0';
     while(((*s_TraceBuffer) == ' ' || (*s_TraceBuffer) == '\t') && (*s_TraceBuffer) != '\0')s_TraceBuffer++;
     if(sscanf(s_TraceBuffer, "%lx%lx%lX%lu%lu%lu%lx", &s_Destination, &s_Gateway, &s_Flags, &s_RefCnt, &s_Use, &s_Metric, &s_Mask) == 7)   
     {
      if(s_Destination == 0lu)
      {
       /* fprintf(stdout, "Default route [%s:%s]\n", s_RouteName, s_TraceBuffer); */
       break;
      }
      /* else fprintf(stdout, "Normal route [%s:%s]\n", s_RouteName, s_TraceBuffer); */
     }
     /* else fprintf(stdout, "Non line [%s:%s]\n", s_RouteName, s_TraceBuffer);  */
     s_Index++;
     s_TraceBuffer = (char *)(&s_Buffer[s_Index]);
    }
    else if(s_Buffer[s_Index] == '\r')s_Buffer[s_Index++] = ' ';
    else s_Index++;
   }while(s_Index < s_ReadBytes);
  }
}
else fprintf(stderr, "Can not open \"%s\"\n", c_Proc_Route);

if(s_RouteName == (char *)0)
{
  return(-1);
}

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(strcmp(s_MyDevice, "lo") != 0 && strcmp(s_RouteName, s_MyDevice) == 0)fprintf(stdout, "%s %s\n", s_MyDevice, s_MyIP);
   
   if(s_MyDevice     )free(s_MyDevice);
   if(s_MyIP         )free(s_MyIP);
   if(s_MyBroadcastIP)free(s_MyBroadcastIP);
   if(s_MyNetmaskIP  )free(s_MyNetmaskIP);
       }
      }
      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);
}

/* End of source */
2007/05/08 12:16 2007/05/08 12:16
트랙백은 하나, 댓글이 없습니다.

댓글+트랙백 RSS :: http://blog.minzkn.com/rss/response/67

댓글+트랙백 ATOM :: http://blog.minzkn.com/atom/response/67

트랙백 주소 :: http://blog.minzkn.com/trackback/67

트랙백 RSS :: http://blog.minzkn.com/rss/trackback/67

트랙백 ATOM :: http://blog.minzkn.com/atom/trackback/67

  1. Subject: 서버의 Local IP 가져오기, 단상

    Tracked from 엘레노아의 작업로그 2007/08/16 11:50  삭제

    결국 바랬던 것은 이런 모양이였다. 참고 사이트 : MINZKN의 블로그 :: 간단히 구현한 ifconfig 예제 (여기의 두번째 예제를 말하는 것이다.) 그러니까 Local Machine에 여러개의 IP가 있을 경우, 외부로 나가는 특정 IP를 알고 싶은 것이다. 가장 간단히 이것을 하려면, Local Machine의 Default Router가 어떤 NIC과 연결되어 있는지 체크한 후에, 그 NIC의 IP를 가져오면 된다. 이 동작은 이전 포스트..

댓글을 달아 주세요

댓글 RSS 주소 : http://blog.minzkn.com/rss/comment/67
댓글 ATOM 주소 : http://blog.minzkn.com/atom/comment/67