Linux API/network2009. 6. 18. 21:19
아래의 소스에서 눈여겨 볼 부분은 다음과 같다.
    struct ifreq *ifr;
    struct ifconf ifcfg;

    ioctl(fd, SIOCGIFCONF, (char *)&ifcfg);

    // 네트워크 장치의 정보를 얻어온다. 
    // 보통 루프백과 하나의 이더넷 카드를 가지고 있을 것이므로
    // 2개의 정보를 출력할 것이다.

    ifr = ifcfg.ifc_req;
    for (n = 0; n < ifcfg.ifc_len; n+= sizeof(struct ifreq))
    {
        // 주소값을 출력하고 루프백 주소인지 확인한다.
        printf("[%s]\n", ifr->ifr_name);
        sin = (struct sockaddr_in *)&ifr->ifr_addr;
        printf("IP    %s %d\n", inet_ntoa(sin->sin_addr), sin->sin_addr.s_addr);
        if ( ntohl(sin->sin_addr.s_addr) == INADDR_LOOPBACK)
        {
            printf("Loop Back\n");
        }
        else
        {
            // 루프백장치가 아니라면 MAC을 출력한다.
        }
        ifr++;
    }

ifr은 struct ifreq인데, 여러개가 있을 수 있으니, 저런식으로 포인터로 증가를 시켜준다. (ifr++)
그리고 n개의 네트워크 장치가 있을 수 있으니, ifcfg.ifc_len의 값으로 전체 갯수를 알려준다.
그 다음에는 장치명(익숙한 eth0 라던가)은 ifr->ifr_name에 들어있다.

#include "sys/ioctl.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "sys/socket.h"
#include "unistd.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "net/if.h"
#include "arpa/inet.h"

int main()
{
    // 이더넷 데이터 구조체 
    struct ifreq *ifr;
    struct sockaddr_in *sin;
    struct sockaddr *sa;

    // 이더넷 설정 구조체
    struct ifconf ifcfg;
    int fd;
    int n;
    int numreqs = 30;
    fd = socket(AF_INET, SOCK_DGRAM, 0);

    // 이더넷 설정정보를 가지고오기 위해서 
    // 설정 구조체를 초기화하고  
    // ifreq데이터는 ifc_buf에 저장되며, 
    // 네트워크 장치가 여러개 있을 수 있으므로 크기를 충분히 잡아주어야 한다.  
    // 보통은 루프백주소와 하나의 이더넷카드, 2개의 장치를 가진다.
    memset(&ifcfg, 0, sizeof(ifcfg));
    ifcfg.ifc_buf = NULL;
    ifcfg.ifc_len = sizeof(struct ifreq) * numreqs;
    ifcfg.ifc_buf = malloc(ifcfg.ifc_len);

    for(;;)
    {
        ifcfg.ifc_len = sizeof(struct ifreq) * numreqs;
        ifcfg.ifc_buf = realloc(ifcfg.ifc_buf, ifcfg.ifc_len);
        if (ioctl(fd, SIOCGIFCONF, (char *)&ifcfg) < 0)
        {
            perror("SIOCGIFCONF ");
            exit;
        }
        // 디버깅 메시지 ifcfg.ifc_len/sizeof(struct ifreq)로 네트워크 
        // 장치의 수를 계산할 수 있다.  
        // 물론 ioctl을 통해서도 구할 수 있는데 그건 각자 해보기 바란다.
        printf("%d : %d \n", ifcfg.ifc_len, sizeof(struct ifreq));
        break;
    }

    // 주소를 비교해 보자.. ifcfg.if_req는 ifcfg.ifc_buf를 가리키고 있음을 
    // 알 수 있다. 
    printf("address %d\n", &ifcfg.ifc_req);
    printf("address %d\n", &ifcfg.ifc_buf);

    // 네트워크 장치의 정보를 얻어온다.  
    // 보통 루프백과 하나의 이더넷 카드를 가지고 있을 것이므로 
    // 2개의 정보를 출력할 것이다. 
    ifr = ifcfg.ifc_req;
    for (n = 0; n < ifcfg.ifc_len; n+= sizeof(struct ifreq))
    {
        // 주소값을 출력하고 루프백 주소인지 확인한다.
        printf("[%s]\n", ifr->ifr_name);
        sin = (struct sockaddr_in *)&ifr->ifr_addr;
        printf("IP    %s %d\n", inet_ntoa(sin->sin_addr), sin->sin_addr.s_addr);
        if ( ntohl(sin->sin_addr.s_addr) == INADDR_LOOPBACK)
        {
            printf("Loop Back\n");
        }
        else
        {
            // 루프백장치가 아니라면 MAC을 출력한다.
            ioctl(fd, SIOCGIFHWADDR, (char *)ifr);
            sa = &ifr->ifr_hwaddr;
            printf("%s\n", ether_ntoa((struct ether_addr *)sa->sa_data));
        }
        // 브로드 캐스팅 주소 
        ioctl(fd,  SIOCGIFBRDADDR, (char *)ifr);
        sin = (struct sockaddr_in *)&ifr->ifr_broadaddr;
        printf("BROD  %s\n", inet_ntoa(sin->sin_addr));
        // 네트워크 마스팅 주소
        ioctl(fd, SIOCGIFNETMASK, (char *)ifr);
        sin = (struct sockaddr_in *)&ifr->ifr_addr;
        printf("MASK  %s\n", inet_ntoa(sin->sin_addr));
        // MTU값
        ioctl(fd, SIOCGIFMTU, (char *)ifr);
        printf("MTU   %d\n", ifr->ifr_mtu);
        printf("\n");
        ifr++;
    }
}

[링크 : http://www.joinc.co.kr/modules.php?file=article&mode=nested&name=News&sid=148]
Posted by 구차니
Linux API/network2009. 6. 5. 19:33
$ more /proc/net/route
Iface   Destination     Gateway         Flags   RefCnt  Use     Metric  Mask            MTU     Window  IRTT
eth0    000AA8C0        00000000        0001    0       0       0       00FFFFFF        0       0       0
eth0    0000FEA9        00000000        0001    0       0       0       0000FFFF        0       0       0
eth0    00000000        010AA8C0        0003    0       0       0       00000000        0       0       0

$ netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
192.168.10.0    0.0.0.0         255.255.255.0   U         0 0          0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 eth0
0.0.0.0         192.168.10.1    0.0.0.0         UG        0 0          0 eth0


0x010AA8C0 이 gateway인데 숫자가 뒤집혀 있다.
0x01. 0x0A. 0xA8. 0xC0
1.      10.     168.   192
Posted by 구차니
Linux API/network2009. 6. 5. 18:01

'Linux API > network' 카테고리의 다른 글

네트워크 장치 갯수 얻기 (get amount of eth?)  (0) 2009.06.18
gateway 정보  (0) 2009.06.05
network 관련 include 할 파일 목록  (0) 2009.06.05
offsetof() - stddef.h  (0) 2009.06.05
SIOCGIF가 모야?  (0) 2009.06.05
Posted by 구차니
Linux API/network2009. 6. 5. 17:55
#include <net/if.h>
struct ifreq

#include <netinet/in.h>
struct sockaddr_in

#include <sys/socket.h>
struct sockaddr

#include <netpacket/packet.h>
struct packet_mreq

#include <net/route.h>
struct rtentry

#include <netdb.h>
struct hostent
struct addrinfo


sockaddr의 경우 원본은 bits/socket.h에 있으나
sys/socket.h 에서 include 함으로 굳이 bits/socket.h를 include 할 필요는 없다.

'Linux API > network' 카테고리의 다른 글

gateway 정보  (0) 2009.06.05
linux에서 ip/mac address 받아오기 관련 링크  (0) 2009.06.05
offsetof() - stddef.h  (0) 2009.06.05
SIOCGIF가 모야?  (0) 2009.06.05
C언어로 MAC 어드레스 받아오기 (Linux)  (1) 2009.06.04
Posted by 구차니
Linux API/network2009. 6. 5. 16:03
ifconfig.c를 들여다 보고 있자니 신기한 녀석들이 나타나시었다.

struct arg1opt {
    const char *name;
    unsigned short selector;
    unsigned short ifr_offset;
};

#define ifreq_offsetof(x)  offsetof(struct ifreq, x)

static const struct arg1opt Arg1Opt[] = {
    {"SIOCSIFMETRIC",  SIOCSIFMETRIC,  ifreq_offsetof(ifr_metric)},
    {"SIOCSIFMTU",     SIOCSIFMTU,     ifreq_offsetof(ifr_mtu)},
    {"SIOCSIFTXQLEN",  SIOCSIFTXQLEN,  ifreq_offsetof(ifr_qlen)},
    {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)},
    {"SIOCSIFNETMASK", SIOCSIFNETMASK, ifreq_offsetof(ifr_netmask)},
    {"SIOCSIFBRDADDR", SIOCSIFBRDADDR, ifreq_offsetof(ifr_broadaddr)},
#ifdef BB_FEATURE_IFCONFIG_HW
    {"SIOCSIFHWADDR",  SIOCSIFHWADDR,  ifreq_offsetof(ifr_hwaddr)},
#endif
    {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)},
#ifdef SIOCSKEEPALIVE
    {"SIOCSKEEPALIVE", SIOCSKEEPALIVE, ifreq_offsetof(ifr_data)},
#endif
#ifdef SIOCSOUTFILL
    {"SIOCSOUTFILL",   SIOCSOUTFILL,   ifreq_offsetof(ifr_data)},
#endif
#ifdef BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
    {"SIOCSIFMAP",     SIOCSIFMAP,     ifreq_offsetof(ifr_map.mem_start)},
    {"SIOCSIFMAP",     SIOCSIFMAP,     ifreq_offsetof(ifr_map.base_addr)},
    {"SIOCSIFMAP",     SIOCSIFMAP,     ifreq_offsetof(ifr_map.irq)},
#endif
    /* Last entry if for unmatched (possibly hostname) arg. */
    {"SIOCSIFADDR",    SIOCSIFADDR,    ifreq_offsetof(ifr_addr)},
};

$ man offsetof
#include <stddef.h>
size_t offsetof(type, member);

머. 매크로로 해도 될텐데 왜 굳이 함수형으로 했을까는 조금 의문이지만,
간단하게 표현하자면 . 연산자를 붙여주는 역활을 한다.

       #include <stddef.h>
       #include <stdio.h>
       #include <stdlib.h>

       int main()
       {
           struct s {
               int i;
               char c;
               double d;
               char a[];
           };

           /* Output is compiler dependent */

           printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n",
                   (long) offsetof(struct s, i),    // s.i ?
                   (long) offsetof(struct s, c),    // s.c ?
                   (long) offsetof(struct s, d),    // s.d ?
                   (long) offsetof(struct s, a));    // s.a ?
           printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s));

           exit(EXIT_SUCCESS);
       }


생각을 해보니..

$ vi /usr/inclue/net/if.h
152 # define ifr_name       ifr_ifrn.ifrn_name      /* interface name       */
153 # define ifr_hwaddr     ifr_ifru.ifru_hwaddr    /* MAC address          */
154 # define ifr_addr       ifr_ifru.ifru_addr      /* address              */
155 # define ifr_dstaddr    ifr_ifru.ifru_dstaddr   /* other end of p-p lnk */
156 # define ifr_broadaddr  ifr_ifru.ifru_broadaddr /* broadcast address    */
157 # define ifr_netmask    ifr_ifru.ifru_netmask   /* interface net mask   */
158 # define ifr_flags      ifr_ifru.ifru_flags     /* flags                */
159 # define ifr_metric     ifr_ifru.ifru_ivalue    /* metric               */
160 # define ifr_mtu        ifr_ifru.ifru_mtu       /* mtu                  */
161 # define ifr_map        ifr_ifru.ifru_map       /* device map           */
162 # define ifr_slave      ifr_ifru.ifru_slave     /* slave device         */
163 # define ifr_data       ifr_ifru.ifru_data      /* for use by interface */
164 # define ifr_ifindex    ifr_ifru.ifru_ivalue    /* interface index      */
165 # define ifr_bandwidth  ifr_ifru.ifru_ivalue    /* link bandwidth       */
166 # define ifr_qlen       ifr_ifru.ifru_ivalue    /* queue length         */
167 # define ifr_newname    ifr_ifru.ifru_newname   /* New name             */

이런식으로도 매크로 정의가 되어 있는데, 여러가지 방법으로 사용하는 이유가 있을까 라는 생각도 든다.

'Linux API > network' 카테고리의 다른 글

gateway 정보  (0) 2009.06.05
linux에서 ip/mac address 받아오기 관련 링크  (0) 2009.06.05
network 관련 include 할 파일 목록  (0) 2009.06.05
SIOCGIF가 모야?  (0) 2009.06.05
C언어로 MAC 어드레스 받아오기 (Linux)  (1) 2009.06.04
Posted by 구차니
Linux API/network2009. 6. 5. 09:47
netdevice 의 ioctl mark들의 이름을 보니

SIOCGIFNAME
SIOCGIFINDEX
SIOCGIFFLAGS, SIOCSIFFLAGS
SIOCGIFMETRIC, SIOCSIFMETRIC
SIOCGIFMTU, SIOCSIFMTU
SIOCGIFHWADDR, SIOCSIFHWADDR
SIOCSIFHWBROADCAST
SIOCGIFMAP, SIOCSIFMAP
SIOCADDMULTI, SIOCDELMULTI
SIOCGIFTXQLEN, SIOCSIFTXQLEN
SIOCSIFNAME
SIOCGIFCONF

SIOCGIF로 시작을 한다. 무슨 의미인가 곰곰히 생각해봤더니 IF는 GIF가 아니라 InterFace인거 같긴한데..
아무튼 검색을 해보니

Socket IO Config Interface 랜다

[링크 : http://www.acronymfinder.com/Socket-IO-Config-Interface-(SIOCGIF).html]



사족 : 개인적으로는 Socket Input Output(=IO) Computer Generic InterFace가 아닐까 생각을 -ㅁ-

'Linux API > network' 카테고리의 다른 글

gateway 정보  (0) 2009.06.05
linux에서 ip/mac address 받아오기 관련 링크  (0) 2009.06.05
network 관련 include 할 파일 목록  (0) 2009.06.05
offsetof() - stddef.h  (0) 2009.06.05
C언어로 MAC 어드레스 받아오기 (Linux)  (1) 2009.06.04
Posted by 구차니
Linux API/network2009. 6. 4. 18:31
#include "stdio.h"
#include "string.h"
#include "net/if.h"
#include "sys/ioctl.h"

//
// Global public data
//
unsigned char cMacAddr[8]; // Server's MAC address

static int GetSvrMacAddress( char *pIface )
{
int nSD; // Socket descriptor
struct ifreq sIfReq; // Interface request
struct if_nameindex *pIfList; // Ptr to interface name index
struct if_nameindex *pListSave; // Ptr to interface name index

//
// Initialize this function
//
pIfList = (struct if_nameindex *)NULL;
pListSave = (struct if_nameindex *)NULL;
#ifndef SIOCGIFADDR
// The kernel does not support the required ioctls
return( 0 );
#endif

//
// Create a socket that we can use for all of our ioctls
//
nSD = socket( PF_INET, SOCK_STREAM, 0 );
if ( nSD < 0 )
{
// Socket creation failed, this is a fatal error
printf( "File %s: line %d: Socket failed\n", __FILE__, __LINE__ );
return( 0 );
}

//
// Obtain a list of dynamically allocated structures
//
pIfList = pListSave = if_nameindex();

//
// Walk thru the array returned and query for each interface's
// address
//
for ( pIfList; *(char *)pIfList != 0; pIfList++ )
{
//
// Determine if we are processing the interface that we
// are interested in
//
if ( strcmp(pIfList->if_name, pIface) )
// Nope, check the next one in the list
continue;
strncpy( sIfReq.ifr_name, pIfList->if_name, IF_NAMESIZE );

//
// Get the MAC address for this interface
//
if ( ioctl(nSD, SIOCGIFHWADDR, &sIfReq) != 0 )
{
// We failed to get the MAC address for the interface
printf( "File %s: line %d: Ioctl failed\n", __FILE__, __LINE__ );
return( 0 );
}
memmove( (void *)&cMacAddr[0], (void *)&sIfReq.ifr_ifru.ifru_hwaddr.sa_data[0], 6 );
break;
}

//
// Clean up things and return
//
if_freenameindex( pListSave );
close( nSD );
return( 1 );
}

int main( int argc, char * argv[] )
{
//
// Initialize this program
//
bzero( (void *)&cMacAddr[0], sizeof(cMacAddr) );
if ( !GetSvrMacAddress("eth0") )
{
// We failed to get the local host's MAC address
printf( "Fatal error: Failed to get local host's MAC address\n" );
}
printf( "HWaddr %02X:%02X:%02X:%02X:%02X:%02X\n",
cMacAddr[0], cMacAddr[1], cMacAddr[2],
cMacAddr[3], cMacAddr[4], cMacAddr[5] );

//
// And exit
//
exit( 0 );
}
[링크 : http://www.linuxquestions.org/questions/programming-9/getting-mac-address-with-c-linux-325037/]

위의 소스 작동하는 것 확인함.
아무튼, struct ifreq 에 ioctl함수로 받아오는 식으로 구현되어 있음.

man 7 netdevice
struct ifreq {
       char ifr_name[IFNAMSIZ]; /* Interface name */
       union {
           struct sockaddr ifr_addr;
           struct sockaddr ifr_dstaddr;
           struct sockaddr ifr_broadaddr;
           struct sockaddr ifr_netmask;
           struct sockaddr ifr_hwaddr;
           short           ifr_flags;
           int           ifr_ifindex;
           int           ifr_metric;
           int           ifr_mtu;
           struct ifmap    ifr_map;
           char           ifr_slave[IFNAMSIZ];
           char           ifr_newname[IFNAMSIZ];
           char *           ifr_data;
       };
       };

[링크 : http://unixhelp.ed.ac.uk/CGI/man-cgi?netdevice+7]

$ vi /usr/inclue/bits/socket.h
161 /* Structure describing a generic socket address.  */
162 struct sockaddr
163   {
164     __SOCKADDR_COMMON (sa_);    /* Common data: address family and length.  */
165     char sa_data[14];           /* Address data.  */
166   };

[링크 : http://adywicaksono.wordpress.com/2007/11/08/detecting-mac-address-using-c-application/]
[링크 : http://www.joinc.co.kr/modules/moniwiki/wiki.php/Code/C/ifinfo]

'Linux API > network' 카테고리의 다른 글

gateway 정보  (0) 2009.06.05
linux에서 ip/mac address 받아오기 관련 링크  (0) 2009.06.05
network 관련 include 할 파일 목록  (0) 2009.06.05
offsetof() - stddef.h  (0) 2009.06.05
SIOCGIF가 모야?  (0) 2009.06.05
Posted by 구차니