'개발/Network Driver'에 해당되는 글 10건

  1. 2008.08.28 인터넷에 연결된 IP 주소 찾기
  2. 2008.08.26 자신의 IP 얻어오는 소스!! ㅋ
  3. 2008.08.01 NDIS 란?
  4. 2008.07.25 WDF 드라이버 개발하면서 Visual Studio 2008 intellisense 사용하기
  5. 2008.07.25 WDK(Windows Driver Kit) VisualStudio2005에서 컴파일하기
2008. 8. 28. 21:42

인터넷에 연결된 IP 주소 찾기

인터넷에 연결된 IP 주소 찾기

호스트에 2개 이상의 랜카드가 설치되어 있거나 하나의 랜카드이어도 여러 개의 IP 를 가지고 있는 경우, 인터넷에 연결된 IP 주소를 찾기는 방법으로 제가 추천하는 방법은 2가지가 있어요.


첫번째, 가장 쉬운 방법으로 아주 유명한 웹사이트에 TCP 연결을 한 후, 연결된 TCP 소켓에서 자신의 IP 주소를 가져오는 것입니다. 일부 FTP 클라이언트 프로그램에서 데이타 소켓의 주소를 처리할 때에 애용되는 방법이죠.


두번째, 오늘 생각해 낸 방법으로 호스트의 랜카드 및 IP 주소 리스트를 검색하여서 인터넷에 연결된 IP 주소를 찾는 방법입니다. 동작 원리를 간단히 설명하면 아래와 같아요.


(1) 호스트에서 사용하는 모든 랜카드를 검색하여 Default GW 주소가 설정된 랜카드를 찾는다.
(2) Default GW 주소가 설정된 랜카드의 모든 IP 주소를 검색하여 Default GW 의 Network 주소와 동일한 IP 주소를 찾는다.
(3) 위에서 찾은 IP 주소를 로컬 IP 주소로 리턴한다.

두번째 방법에 대한 소스코드는 아래와 같아요.


================================= 소스코드 =====================================


#include "stdafx.h"
#include <winsock.h>

#include <ntddndis.h>

#include "iptypes.h"
#include "ipifcons.h"


typedef DWORD (WINAPI *ADDIPADDRESS)( IPAddr, IPMask, DWORD, PULONG, PULONG );
typedef DWORD (WINAPI *DELETEIPADDRESS)( ULONG );
typedef DWORD (WINAPI *GETADAPTERSINFO)( PIP_ADAPTER_INFO, PULONG );

ADDIPADDRESS AddIPAddress = NULL;
DELETEIPADDRESS DeleteIPAddress = NULL;
GETADAPTERSINFO GetAdaptersInfo = NULL;


/** 호스트에서 인터넷에 연결되어 있는 IP 주소를 가져온다. */

void PrintIP2()
{
// 호스트에 연결된 IP 주소 중에서 default gw 와 동일한 네트워크에 존재하는 IP 주소를 찾아낸다.
static HINSTANCE hDll;   // ICMP library handle

 if( hDll == NULL )
{
 hDll = LoadLibrary( "iphlpapi.dll" );
}

 if( hDll )
{
 DWORD dwErr, dwAdapterInfoSize = 0;
 PIP_ADAPTER_INFO pAdapterInfo, pAdapt;
 PIP_ADDR_STRING  pAddrStr;

  if( AddIPAddress == NULL )
 {
  AddIPAddress = (ADDIPADDRESS) GetProcAddress( hDll, "AddIPAddress" );
  if( AddIPAddress == NULL ) goto NORMAL_CASE;
 }

  if( DeleteIPAddress == NULL )
 {
  DeleteIPAddress = (DELETEIPADDRESS) GetProcAddress( hDll, "DeleteIPAddress" );
  if( DeleteIPAddress == NULL ) goto NORMAL_CASE;
 }

  if( GetAdaptersInfo == NULL )
 {
  GetAdaptersInfo = (GETADAPTERSINFO) GetProcAddress( hDll, "GetAdaptersInfo" );
  if( GetAdaptersInfo == NULL ) goto NORMAL_CASE;
 }

  if( ( dwErr = GetAdaptersInfo( NULL, &dwAdapterInfoSize ) ) != 0 )
 {
  if( dwErr != ERROR_BUFFER_OVERFLOW )
  {
   goto NORMAL_CASE;
  }
  // QQQ: ERROR_BUFFER_OVERFLOW 인 경우에는 어떻게 처리하지??
 }

  // Allocate memory from sizing information
 if( ( pAdapterInfo = (PIP_ADAPTER_INFO) GlobalAlloc( GPTR, dwAdapterInfoSize )) == NULL )
 {
  goto NORMAL_CASE;
 }

  // Get actual adapter information
 if( ( dwErr = GetAdaptersInfo( pAdapterInfo, &dwAdapterInfoSize ) ) != 0 )
 {
  goto NORMAL_CASE;
 }

  for( pAdapt = pAdapterInfo; pAdapt; pAdapt = pAdapt->Next )
 {
  switch ( pAdapt->Type )
  {
  case MIB_IF_TYPE_ETHERNET:
   // QQQ: 여러개의 default GW 가 나올 수 있으나, 현재는 첫번째 default GW 만 생각한다.
   if( strlen( pAdapt->GatewayList.IpAddress.String ) > 0 )
   {
    DWORD dwGwIp, dwMask, dwIp, dwGwNetwork, dwNetwork;

     dwGwIp = inet_addr( pAdapt->GatewayList.IpAddress.String );

     //printf( "Gateway address = [%s] ", pAdapt->GatewayList.IpAddress.String );
    //printf( "Gateway mask = [%s] ", pAdapt->GatewayList.IpMask.String );

     for( pAddrStr = &(pAdapt->IpAddressList); pAddrStr; pAddrStr = pAddrStr->Next )
    {
     if( strlen(pAddrStr->IpAddress.String) > 0 )
     {
      dwIp = inet_addr( pAddrStr->IpAddress.String );
      dwMask = inet_addr( pAddrStr->IpMask.String );
      dwNetwork = dwIp & dwMask;
      dwGwNetwork = dwGwIp & dwMask;

       //printf( "IP address = [%s], network = %08x ", pAddrStr->IpAddress.String, dwNetwork );
     
      if( dwGwNetwork == dwNetwork )
      {
       printf( "ip address = %s ", pAddrStr->IpAddress.String );
       break;
      }
     }
    }
   }
   break;
  default:
   break;
  }
 }
}

}


int _tmain(int argc, _TCHAR* argv[])
{
PrintIP2();

 return 0;
}

2008. 8. 26. 23:32

자신의 IP 얻어오는 소스!! ㅋ

//------------------------------------------------------------------------------
//
// Get machine ip addresses by sockaddr for sockaddr_in/sockaddr_in6.
//
// AUTHOR  : Yubin Lim
// DATE    : 2004-11-05
// EMAIL   : purewell at purewell dot biz
// REQUIRE : MICROSOFT PLATFORM SDK(IPHLPAPI.LIB),
//           WINDOWS XP,
//           Visual C/C++ Compiler
//
//------------------------------------------------------------------------------


#include <cstdio>
#include <cstdlib>
#include <iostream>

using namespace std;

#include <winsock2.h>
#include <ws2tcpip.h>
#include <iptypes.h>
#include <iphlpapi.h>

#pragma comment(lib, "iphlpapi")
#pragma comment(lib, "ws2_32")

static bool win32_getMyIP(int nFamily)
{
  DWORD dwRet;
  PIP_ADAPTER_ADDRESSES pAdpAddrs;
  PIP_ADAPTER_ADDRESSES pThis;
  PIP_ADAPTER_UNICAST_ADDRESS pThisAddrs;
  unsigned long ulBufLen = sizeof(IP_ADAPTER_ADDRESSES);

  pAdpAddrs = (PIP_ADAPTER_ADDRESSES)malloc( ulBufLen );
  if ( !pAdpAddrs ) return false;

  dwRet = GetAdaptersAddresses(nFamily, 0, NULL, pAdpAddrs, &ulBufLen);
  if (dwRet == ERROR_BUFFER_OVERFLOW)
  {
    free ( pAdpAddrs );
    pAdpAddrs = (PIP_ADAPTER_ADDRESSES)malloc( ulBufLen );

    if ( !pAdpAddrs ) return false;
  }

  dwRet = GetAdaptersAddresses(nFamily, 0, NULL, pAdpAddrs, &ulBufLen);
  if ( dwRet != NO_ERROR )
  {
    free ( pAdpAddrs );
    return false;
  }

  for ( pThis = pAdpAddrs; NULL != pThis; pThis = pThis->Next)
  {
    fprintf(stderr," FN: %Sn", pThis->FriendlyName);
    fprintf(stderr," DS: %Sn", pThis->Description);
    fprintf(stderr," AN: %Sn", pThis->AdapterName);
    for ( pThisAddrs = pThis->FirstUnicastAddress;
          NULL != pThisAddrs;
          pThisAddrs = pThisAddrs->Next )
    {
      if ( nFamily == AF_INET )
      {
        struct sockaddr_in* pAddr
          = (struct sockaddr_in*)pThisAddrs->Address.lpSockaddr;

        cerr << "  IP v4: " << inet_ntoa(pAddr->sin_addr) << endl;
      }
      else if ( nFamily == AF_INET6 )
      {
        struct sockaddr_in6* pAddr
          = (sockaddr_in6*)pThisAddrs->Address.lpSockaddr;

        //! @todo convert binary address type to string type
        cerr << "  IP v6" << endl;
      }
    }//for
  }//for

  free ( pAdpAddrs );

  return true;
}


int main(void)
{
  win32_getMyIP(AF_INET);
  win32_getMyIP(AF_INET6);
  return 0;
}
2008. 8. 1. 17:06

NDIS 란?

        NDIS 란?

             NDIS는 "Network Driver Interface Specification"의 약자이다. NDIS의 목적은 Network

             Interface Cards를 위한 표준 API를 정의 하고, 또한 상위 레벨(TCP/IP)프로토콜 드라이

             버 뿐만 아니라 MAC driver들에 의해 사용될 수 있는 함수들의 라이브러리를 제공한다.

             Wrapper function은 platform dependency들을 숨길 뿐만 아니라 MAC과 프로토콜 드라

             이버를 쉽게 개발할 수 있도록 한다.

             현재 최신 버젼은 Windows Vista용으로 나온 NDIS 6.0이고, 우리가 사용 할 버젼은 XP

             용으로 나온 NDIS 5.1 버젼을 사용할 것이다.


             NDIS는 다음과 같은 기능을 제공한다.

              - Registering Driver

              - Registering Network Interface Cards

              - Opening a Network Interface Card

              - Sending Data

              - Receiving Data

              - Indicating Status

              - Querying an Setting Network Interface Card Driver Capabilities

              - Querying Global Statistics

              - Closing a Network Interface Card

              - Resetting a Network Interface Card

              - Removing a Network Interface Card

              - Uploading and Deregistering Drivers, and so on



사용자 삽입 이미지

                                         - NDIS Drivers 아키텍쳐 -



             그림이 보여주듯, NDIS는 다음과 같은 타입들의 네트워크 드라이버들을 제공한다.

              - Miniport Drivers

              - Intermediate Drivers

              - Protocol Drivers



            (1) Miniport NIC Drivers

               ① NIC을 통해 데이터를 보내고 받는 것을 포함해, 네트워크 인터페이스 카드를

                  관리한다.

               ② intermediate driver들과 전송 계층 드라이버들과 같은 상위 레벨 드라이버들과 인터

                 페이스를 제공한다.

                 Packet sending : 전송 계층 드라이버가 전송하는 패킷을 가지고 있을 때, NDIS

                 라이브러리에 의해 export 되어지는 NdisXxx 함수를 호출한다. 후에 NDIS는

                 미니포트에 의해 export 된 적당한 MiniportXxx 함수를 호출함으로써 미니포트에게

                 패킷을 전달한다. 미니포트 드라이버는 그리고 나서 적당한 NdisXxx 함수들을

                 호출함으로써 전송을 위해 NIC에게 패킷을 포워드한다.

                 Packet receiving : NIC가 NIC에게 주소화된 패킷을 수신할 때, NDIS 혹은 NIC의

                 미니포트에 의해 처리될 수 있는 하드웨어 인터럽트를 포스트할 수 있다. NDIS는

                 적당한 MiniportXxx 함수를 호출함으로써 NIC의 미니포트에게 알린다. 미니포트는

                 NIC으로부터 데이터 전송을 설정하고 그리고 나서 적당한 NdisXxx 함수를

                 호출함으로써 바인드된 상위레벨 드라이버들에게 수신된 패킷의 존재를

                 인디케이트한다.

사용자 삽입 이미지


            (2) Intermediate Drivers

               위의 그림에서처럼 intermediate driver들은 일반적으로 미니포트 드라이버들과 전송 계

               층 프로토콜 드라이버들 사이에서 계층화 된다.

               lower edge에서, intermediate driver는 NDIS가 아래 미니포트들로부터 요구들을 통신

               하기 위해 호출하는 프로토콜 엔트리 포인트들(ProtocolXxx 함수들)을 노출한다. 아래

               미니포트 드라이버에 대해, intermediate driver는 프로토콜 드라이버가 되는 것으로 나

               타난다.

               upper edge에서, intermediate driver는 하나나 혹은 그 이상의 위의 프로토콜

               드라이버들의 요구들과 통신하기 위해 NDIS가 호출하는 미니포트 엔트리 포인트들

               (MiniportXxx 함수들)을 노출한다. 위의 프로토콜 드라이버에 대해서, intermediate

               driver는 미니포트로 나타난다.

               다음과 같은 기능에 intermediate driver를 사용할 수 있다.


               ① 다른 네트워크 미디어 사이를 변환하기 위해

               - 예를 들어, Ethernet 또는 Token Ring 전송계층들과 ATM 미니포트 사이에

                 intermediate driver의 함수는 Ethernet 과 Token Ring 패킷들을 ATM 패킷들로

                 mapping하거나 그 반대로 mapping한다.

               ② 패킷들을 필터하기

               - 패킷 스케줄러는 필터 드라이버로서 사용된 intermediate driver의 예이다. 패킷

                 스케줄러는 전송을 위해 전송 계층에 의해 아래로 전달된 각 보내기 패킷들 내에

                 우선권 정보를 읽고, 미니포트 드라이버에 의해 위로 인디케이트된 각 수신 패킷에

                 대한 우선권 정보를 읽는다. 패킷 스케줄러는 그리고 나서 우선권을 토대로 전송  

                 혹은 수신을 위해 각 패킷을 스케줄한다.

               ③ 하나 이상의 NIC과 관련해서 패킷 전송을 balance한다.

                - load balancing. 드라이버는 하나의 가상 어댑터를 위의 전송 계층 프로토콜들에게

                 노출하지만 하나 이상의 NIC들로 전송 할 패킷들을 분산한다.(distributes)


사용자 삽입 이미지




            (3) Protocol Drivers

               드라이버들의 NDIS 계층도에서 가장 위에 있는 네트워크 프로토콜은 TCP/IP 혹은

               IPX/SPX 스택과 같은 전송 프로토콜 스택을 실행하는 전송 계층 드라이버내에서 가장

               낮은 레벨 드라이버로서 사용되어진다. 전송 계층 드라이버는 패킷들을 할당하고,

               보내는 어플리케이션으로부터 데이터를 패킷에 복사하고, 이러한 패킷들을 NDIS

               함수들을 호출함으로써 낮은 레벨 드라이버에 보낸다. 프로토콜 드라이버는 또한 다음

               낮은 레벨 드라이버로부터 들어오는 패킷들을 수신하기 위해 프로토콜 인터페이스를

               제공한다. 전송 계층 드라이버는 수신된 데이터를 적당한 클라이언트 어플리케이션에게

               전송한다.

               lower edge에서, 프로토콜 드라이버는 intermediate 네트워크 드라이버들과 미니포트

               NIC 드라이버들과 인터페이스한다. 프로토콜 드라이버는 패킷들을 보내기 위해 NdisXxx

               함수들을 호출하고, lower 레벨 드라이버들에 의해 유지된 정보를 읽고 설정하고 운영

               체제 서비스들을 사용한다. 프로토콜 드라이버는 NDIS가 수신된 패킷들을 위로 인디케

               이트하기 위해 그리고 lower-level 드라이버들의 상태를 인디케이트하고 프로토콜 드라

               이버와 통신하기 위해 lower-level 드라이버들을 위해 혹은 자신의 목적을 위해 호출하

               는 엔트리 포인트들(ProtocolXxx 함수들)의 집합을 export한다.

               upper edge에서, 전송 계층 프로토콜 드라이버는 프로토콜 스택에서 상위 레벨 드라이

               버에 대한 private 인터페이스를 가진다.

사용자 삽입 이미지

2008. 7. 25. 06:10

WDF 드라이버 개발하면서 Visual Studio 2008 intellisense 사용하기

WDK를 visual studio 2005에서 컴파일 하는 방법은 아래 URL을 참조해 주세요

http://refreeme.tistory.com/6


만약에 위 방법대로 했는데 컴파일이 되지 않는 경우가 있습니다. 그럴경우에는 아래 화면 같은 환경설정 화면에서 아래와 같이 수정하면됩니다.

사용자 삽입 이미지



Build Command Line : c:\winddk\ddkbuild -wxp chk E:\Workspace\WDK\osrusbfx2\sys\step1

(컴파일 해야하는 소스 파일위치를 절대경로를 입력해주면 됩니다.)


그럼 오늘 블로그 포스트 주제인 Visual Studio 2008에서 WDK를 개발하면서 Intellisense를 사용하는 방법에 대해서 알아보겠습니다.


아래 화면 처럼 개발할때 Intellisense가 지원되면 정말 편하죠

사용자 삽입 이미지



설정 방법은 의외로 간단합니다.

아래 화면 처럼 설정해 주면 됩니다.

사용자 삽입 이미지


즉, 위 화면 처럼 Intellisense가 참조할 경로를 입력만 해주면 됩니다.

Include Search Path : C:\WinDDK\6000\inc\ddk;C:\WinDDK\6000\inc\wdf\kmdf\10


출처 : 다년간의 프로그램밍 경험 및 http://blogs.msdn.com/888_umdf_4_you/

2008. 7. 25. 05:44

WDK(Windows Driver Kit) VisualStudio2005에서 컴파일하기

참고로 WDK는 VisualStudio 6.0에서는 컴파일 되지 않습니다

*아래 단계를 통해서 WDK 예제 NDIS 샘플중에 하나인 passthru를 컴파일 해보겠습니다.^^


1. osronline.com 에서 ddkbuild.cmd를 다운 받습니다. 편의를 위해서 제블로그에 올려 놓았습니다.

다운 받은 파일은 WinDDK가 설치된 경로에 압축해제해 놓습니다.

저는 아래경로에 파일을 압축해제해 두었습니다.

C:\WinDDK\ddkbuild.cmd


2. 아래 그림과 같이 vs2005에서 메이크 파일 프로젝트를 생성합니다.



사용자 삽입 이미지
 
 
2. 프로젝트가 생성된 후에 passthru 파일을아래 그림과 같은 메뉴를 통해서 추가 합니다.
 

사용자 삽입 이미지


3. 파일을 추가 할때 주의할 점은 makefile과 sources 파일은 꼭 추가해야 합니다.




사용자 삽입 이미지
 
4. 프로젝트 환경 속성 페이지에서 빌드 명령줄을 아래와 같이 추가합니다
c:\winddk\ddkbuild -wxp chk .
 
or
 
c:\winddk\ddkbuild -wxp fre .
 
 
사용자 삽입 이미지
 
 
5.운영 체제 환경변수를 아래 화면처럼 추가하고 재부팅 합니다.

사용자 삽입 이미지

사용자 삽입 이미지

 
 
 
7. 위 과정을 다한 후에는 F7을 눌러서 컴파일 되는 것을 확인하면 됩니다.
 
도움이 되시라고 위와 같이 설정한 visualstudio2005 프로젝트 파일을 소스코드 포함해서 올려 놓았습니다.
필요하신 분들은 다운받아 사용하세요
 
출처: 다년간의 프로그램밍 경험
        http://blog.naver.com/process3/20035804966