대문 / 프로그래밍, 네트웍 / Wake on LAN (WOL)

Wake on LAN (WOL)

Magic packet의 생성

  • Wake on LAN (WOL)을 UDP상에서 구현 하는 경우 UDP packet의 첫 6 byte는 FFH로 채워지고 이후 대상 PC의 Ethenet MAC address 6 byte가 16회 반복시켜서 UDP Magic packet을 만들수 있습니다. 만약 MAC address가 "44:87:FC:8F:BB:B4" 라고 한다면 다음과 같은 UDP packet을 만들어 Broadcast나 Unicast로 송출하면 됩니다.
    00000000 FF FF FF FF FF FF 44 87 | FC 8F BB B4 44 87 FC 8F [......D.....D...]
    00000010 BB B4 44 87 FC 8F BB B4 | 44 87 FC 8F BB B4 44 87 [..D.....D.....D.]
    00000020 FC 8F BB B4 44 87 FC 8F | BB B4 44 87 FC 8F BB B4 [....D.....D.....]
    00000030 44 87 FC 8F BB B4 44 87 | FC 8F BB B4 44 87 FC 8F [D.....D.....D...]
    00000040 BB B4 44 87 FC 8F BB B4 | 44 87 FC 8F BB B4 44 87 [..D.....D.....D.]
    00000050 FC 8F BB B4 44 87 FC 8F | BB B4 44 87 FC 8F BB B4 [....D.....D.....]
    00000060 44 87 FC 8F BB B4                                 [D.....          ]
    

예제소스

  • 최근 예제 소스는 [http]http://source.hwport.com/viewvc/extra/wake_on_lan/[]에서 보실수 있습니다.
    /*
      Copyright (C) JAEHYUK CHO
      All rights reserved.
      Code by JaeHyuk Cho <mailto:minzkn@minzkn.com>
    */
    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    int main(int s_argc, char **s_argv);
    
    int main(int s_argc, char **s_argv)
    {
        static const unsigned char s_target_mac[6] = { /* 이 부분을 자신이 깨우고자 하는 PC의 Ethernet MAC address로 채워주면 되겠습니다. */
            0x44u, 0x87u, 0xfcu, 0x8fu, 0xbbu, 0xb4u
        };
    
        int s_socket;
        struct sockaddr_in s_sockaddr_in;
        unsigned char s_magic_packet[ 6 + (6 * 16) ];
        int s_repeat;
        ssize_t s_send_bytes;
        int s_value;
    
        /* UDP socket open */
        s_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if(s_socket == (-1)) {
            perror("socket");
            return(EXIT_FAILURE);
        }
    
        /* bind */
        (void)memset((void *)(&s_sockaddr_in), 0, sizeof(s_sockaddr_in));
        s_sockaddr_in.sin_family = AF_INET;
        s_sockaddr_in.sin_addr.s_addr = htonl(INADDR_ANY);
        s_sockaddr_in.sin_port = htons(0);
        if(bind(s_socket, (const struct sockaddr *)(&s_sockaddr_in), (socklen_t)sizeof(s_sockaddr_in)) == (-1)) {
            perror("bind");
    
            (void)close(s_socket);
    
            return(EXIT_FAILURE);
        }
    
        /* broadcast socket option enable (Broadcast를 위해서는 SO_BROADCAST가 설정되어야 합니다.) */
        s_value = 1;
        (void)setsockopt(s_socket, SOL_SOCKET, SO_BROADCAST, (const void *)(&s_value), (socklen_t)sizeof(s_value));
    
        /* WOL packet build (repeat 6) */
        (void)memset((void *)(&s_magic_packet[0]), 0xff, (size_t)6u); /* 첫 6byte는 FFH로 채웁니다. */
        for(s_repeat = 0;s_repeat < 16;s_repeat++) { /* 깨우고자 하는 MAC address를 16회 반복하여 채웁니다. */
            (void)memcpy((void *)(&s_magic_packet[6 + (s_repeat * 6)]), (const void *)(&s_target_mac[0]), sizeof(s_target_mac));
        }
    
        /* broadcast socket address structure set */
        (void)memset((void *)(&s_sockaddr_in), 0, sizeof(s_sockaddr_in));
        s_sockaddr_in.sin_family = AF_INET;
        (void)inet_pton(s_sockaddr_in.sin_family, "255.255.255.255", (void *)(&s_sockaddr_in.sin_addr));
        s_sockaddr_in.sin_port = htons(2304); /* any port ... (사실상 port는 아무거나 상관하지 않습니다. 다만 다른 응용프로그램들에게 방해가 되지 않는 포트를 선택하는것 뿐입니다.) */
    
        /* send */
        s_send_bytes = sendto(
            s_socket,
            (const void *)(&s_magic_packet[0]),
            sizeof(s_magic_packet),
            0,
            (const struct sockaddr *)(&s_sockaddr_in),
            (socklen_t)sizeof(s_sockaddr_in)
        );
        if(s_send_bytes == ((ssize_t)(-1))) {
            perror("sendto");
    
            (void)close(s_socket);
    
            return(EXIT_FAILURE);
        }
    
        (void)fprintf(stdout,
            "WOL packet : %ld bytes (Target %02X:%02X:%02X:%02X:%02X:%02X)\n",
            (long)s_send_bytes,
            (unsigned int)s_target_mac[0], (unsigned int)s_target_mac[1], (unsigned int)s_target_mac[2],
            (unsigned int)s_target_mac[3], (unsigned int)s_target_mac[4], (unsigned int)s_target_mac[5]
        );
    
        /* socket close */
        (void)close(s_socket);
    
        return(EXIT_SUCCESS);
    }
    
    /* vim: set expandtab: */
    /* End of source */
    

참고문헌


/*
End of page
(RemoteIP=38.107.179.244:54171)
Copyright © HWPORT.COM
All Rights Reserved.
*/