'dhcp probe'에 해당되는 글 1건

  1. 2014.11.29 DHCP Probe 소스 코드

이전에 작성했던 현재 네트워크에서 DHCP 서버를 확인하는 글을 참고하여

http://sound79.tistory.com/169


간단하게 DHCP Probe 코드를  작성해 보았습니다.

소스코드를 보면 간단합니다. DHCP 패킷을 하나 만들어서 전송한 후 DHCP Offer 메시지를 일정 시간 기다립니다.

DHCP Offer 메시지를 수신하면 현재 네트워크에 DHCP Server가 존재한다고 판단하도록 되어 있습니다.


DHCPProbe.h

/*
 * DhcpProbe.h
 *
 *  Created on: 2014. 8. 17.
 *      Author: sound79@gmail.com
 */
#ifndef DHCPPROBE_H_
#define DHCPPROBE_H_

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

#define MAX_DHCP_CHADDR_LEN        16
#define MAX_DHCP_SNAME_LEN        64
#define MAX_DHCP_FILE_LEN        128
#define MAX_DHCP_OPTIONS_LEN    312

#define SERVER_DHCP_PORT        67
#define CLIENT_DHCP_PORT        68

#define CHECK_WAITTING_DHCP_OFFER_TIME        2

typedef struct DHCPPacket_t
{
    unsigned char  op;
    unsigned char  htype;
    unsigned char  hlen;
    unsigned char  hops;
#if 0
    unsigned long xid;
    unsigned short secs;
    unsigned short flags;
#else
    u_int32_t xid;
    u_int16_t secs;
    u_int16_t flags;
#endif
    struct in_addr ciaddr;
    struct in_addr yiaddr;
    struct in_addr siaddr;
    struct in_addr giaddr;
    unsigned char chaddr [MAX_DHCP_CHADDR_LEN];
    char sname [MAX_DHCP_SNAME_LEN];
    char file [MAX_DHCP_FILE_LEN];
    char options[MAX_DHCP_OPTIONS_LEN];

    void clear()
    {
        op = 0, htype = 0, hlen = 0 , hops = 0;
        xid = 0, secs = 0, flags = 0;
        memset(&ciaddr, 0, sizeof(ciaddr));
        memset(&yiaddr, 0, sizeof(ciaddr));
        memset(&siaddr, 0, sizeof(ciaddr));
        memset(&giaddr, 0, sizeof(ciaddr));
        memset(chaddr, 0, MAX_DHCP_CHADDR_LEN);
        memset(sname, 0, MAX_DHCP_SNAME_LEN);
        memset(file, 0, MAX_DHCP_FILE_LEN);
        memset(options, 0, MAX_DHCP_OPTIONS_LEN);
    }
}DHCPPacket;

using namespace std;

class DHCPProbe
{
private:
    DHCPPacket mDHCPPacket;
    string mEthName;
    string mEthMacAddress;
    int    mDHCPSocket;
    unsigned long mPacketXID;

private:
    bool makeDHCPSocket();
    void closeDHCPSocket();
    bool getMacAddress();
    bool makeDHCPDiscoveryPacket();
    bool sendDHCPDiscovery();
    int recvDHCPOffer(char *buffer, int buffer_size, struct sockaddr_in *sourceAddress);
    int waitDHCPOfferPacket();

public:
    DHCPProbe(string ethName = "eth0");
    virtual ~DHCPProbe();
    int CheckDHCPServerExist();
};

#endif /* DHCPPROBE_H_ */



DhcpProbe.cpp

DhcpProbe.cpp


DhcpProbe.h


/*
 * DhcpProbe.cpp
 *
 *  Created on: 2014. 8. 17.
 *      Author: sound79@gmail.com
 */

#include "DhcpProbe.h"

DHCPProbe::DHCPProbe(string ethName) : mDHCPPacket(), mEthName(ethName), mDHCPSocket(0), mPacketXID(0)
{
    //초기화 mDHCPPacket
}

DHCPProbe::~DHCPProbe()
{
}

bool DHCPProbe::makeDHCPSocket()
{
    struct sockaddr_in dhcpAddress;
    struct ifreq interface;

    memset(&dhcpAddress, 0, sizeof(dhcpAddress));
    dhcpAddress.sin_family=AF_INET;
    dhcpAddress.sin_port=htons(CLIENT_DHCP_PORT);
    dhcpAddress.sin_addr.s_addr=INADDR_ANY;
    memset(&dhcpAddress.sin_zero, 0, sizeof(dhcpAddress.sin_zero));

    int sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    if(sock<0)
    {
        fprintf(stderr, "%s %s %d: create socket error!\n", __FILE__, __FUNCTION__, __LINE__);
        return false;
    }

    int flags = 1;
    if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&flags, sizeof(flags)) < 0)
    {
        fprintf(stderr, "%s %s %d: error=[%s]\n", __FILE__, __FUNCTION__, __LINE__, strerror(errno));
        return false;
    }

    if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&flags, sizeof flags) < 0)
    {
        fprintf(stderr, "%s %s %d: error=[%s]\n", __FILE__, __FUNCTION__, __LINE__, strerror(errno));
        return false;
    }

    memset(&interface.ifr_ifrn.ifrn_name, 0, IFNAMSIZ);
    if(mEthName.length() > IFNAMSIZ)
        strncpy(interface.ifr_ifrn.ifrn_name, mEthName.c_str(), IFNAMSIZ);
    else
        strncpy(interface.ifr_ifrn.ifrn_name, mEthName.c_str(), mEthName.length());

    if(setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (char *)&interface, sizeof(interface)) < 0)
    {
        fprintf(stderr, "%s %s %d: error=[%s]\n", __FILE__, __FUNCTION__, __LINE__, strerror(errno));
        return false;
    }


    if(bind(sock, (struct sockaddr *)&dhcpAddress, sizeof(dhcpAddress)) < 0)
    {
        fprintf(stderr, "%s %s %d: error=[%s]\n", __FILE__, __FUNCTION__, __LINE__, strerror(errno));
        return false;
    }

    mDHCPSocket = sock;

    getMacAddress();

    return true;
}

void DHCPProbe::closeDHCPSocket()
{
    if(mDHCPSocket > 0)
        close(mDHCPSocket);
    mDHCPSocket = 0;
}

bool DHCPProbe::getMacAddress()
{
    struct ifreq ifr;
    strncpy((char *)&ifr.ifr_name, mEthName.c_str(), sizeof(ifr.ifr_name));

    if(ioctl(mDHCPSocket,SIOCGIFHWADDR,&ifr)<0)
    {
        fprintf(stderr, "%s %s %d: couldn't get mac address!\n", __FILE__, __FUNCTION__, __LINE__);
        return false;
    }
    char mac_address[7] = {0,};
    memcpy(&mac_address, &ifr.ifr_hwaddr.sa_data, 6);
    mEthMacAddress = mac_address;

    return true;
}

bool DHCPProbe::makeDHCPDiscoveryPacket()
{
    mDHCPPacket.clear();

    mDHCPPacket.op = 0x01;        //boot request
    mDHCPPacket.htype = 0x01;    //ethernet hardware address
    mDHCPPacket.hlen = 6;
    mDHCPPacket.hops = 0;
    srand(time(NULL));
    mPacketXID = random();
    mDHCPPacket.xid = htonl(mPacketXID);
    mDHCPPacket.secs = 0xFF;
    mDHCPPacket.flags = htons(32768);    //DHCP Broadcast flag
    if(mEthMacAddress.length() > 6)
        memcpy(mDHCPPacket.chaddr, mEthMacAddress.c_str(), mEthMacAddress.length());
    else
        memcpy(mDHCPPacket.chaddr, mEthMacAddress.c_str(), 6);

    mDHCPPacket.options[0] = '\x63';
    mDHCPPacket.options[1] = '\x82';
    mDHCPPacket.options[2] = '\x53';
    mDHCPPacket.options[3] = '\x63';
    mDHCPPacket.options[4] = 53;
    mDHCPPacket.options[5] = '\x01';
    mDHCPPacket.options[6] = 1;

    return true;
}

bool DHCPProbe::sendDHCPDiscovery()
{
    makeDHCPDiscoveryPacket();

    struct sockaddr_in destAddress;

    destAddress.sin_family = AF_INET;
    destAddress.sin_port = htons(67);
    destAddress.sin_addr.s_addr = INADDR_BROADCAST;
    memset(&destAddress.sin_zero, 0, sizeof(destAddress.sin_zero));

    int result = sendto(mDHCPSocket, reinterpret_cast<char *>(&mDHCPPacket), sizeof(mDHCPPacket), 0, reinterpret_cast<struct sockaddr *>(&destAddress), sizeof(destAddress));
    if(result < 0)
        return false;
    else
        return true;
}

int DHCPProbe::recvDHCPOffer(char *buffer, int buffer_size, struct sockaddr_in *sourceAddress)
{
    struct timeval tv;
    fd_set readfds;

    tv.tv_sec = CHECK_WAITTING_DHCP_OFFER_TIME;
    tv.tv_usec = 0;
    FD_ZERO(&readfds);
    FD_SET(mDHCPSocket, &readfds);
    select(mDHCPSocket+1, &readfds, NULL, NULL, &tv);

    if(FD_ISSET(mDHCPSocket, &readfds))
    {
        struct sockaddr_in src_addr;
        memset(&src_addr, 0, sizeof(src_addr));
        socklen_t address_size = sizeof(src_addr);
        recvfrom(mDHCPSocket,(char *)buffer, buffer_size, MSG_PEEK, (struct sockaddr *)&src_addr, &address_size);
        recvfrom(mDHCPSocket,(char *)buffer, buffer_size, 0, (struct sockaddr *)&src_addr, &address_size);
        fprintf(stderr, "%s %s %d:\n", __FILE__, __FUNCTION__, __LINE__);
        memcpy(sourceAddress, &src_addr, sizeof(src_addr));
    }
    else
    {
        fprintf(stderr, "%s %s %d:\n", __FILE__, __FUNCTION__, __LINE__);
        return 0;
    }

    return 1;
}

int DHCPProbe::waitDHCPOfferPacket()
{
    struct sockaddr_in source;
    time_t start_time;
    time_t check_time;
    time(&start_time);

    DHCPPacket buffer;

    while(1)
    {
        time(&check_time);
        if((check_time - start_time) >= CHECK_WAITTING_DHCP_OFFER_TIME)
            break;
        memset(&source, 0, sizeof(source));
        if(recvDHCPOffer(reinterpret_cast<char *>(&buffer), sizeof(buffer), &source) > 0)
        {
            fprintf(stderr, "%s\n", inet_ntoa(source.sin_addr));
        }
    }

    return 1;
}

int DHCPProbe::CheckDHCPServerExist()
{
    if(makeDHCPSocket() == false)
        return 0;

    if(sendDHCPDiscovery() == false)
        return 0;

    waitDHCPOfferPacket();
    closeDHCPSocket();

    return 1;
}

int main()
{
    DHCPProbe dhcp("eth0");
    dhcp.CheckDHCPServerExist();

    return 0;
}


저작자 표시 비영리 동일 조건 변경 허락
신고

'Programming' 카테고리의 다른 글

cJSON Programming  (0) 2015.11.29
scons 개념 및 사용법  (0) 2015.04.08
DHCP Probe 소스 코드  (0) 2014.11.29
현재 네트워크에서 DHCP 서버가 동작되고 있는지 확인?  (0) 2014.08.18
gsoap (2)  (1) 2014.03.12
gsoap (1)  (0) 2014.03.11
Posted by sound79 사운드친구

댓글을 달아 주세요