블로그 이미지
송시혁

calendar

1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

Notice

Tag

Recent Post

Recent Comment

Recent Trackback

Archive

2013. 7. 12. 19:29 네트워크/vmware 실습



#include "ethernet.h"
#include "hexaview.h"

//  write (1, "\033[1;1H\033[2J", 10);//화면 지우는 것. 

void hexaview(unsigned char *ucP, unsigned int isize);

typedef struct _L1_map
{
  unsigned int uiType;
  int (*L1func)(void *);
  
}L1_map;
//전역변수로 typedef struct 구조체 정의.

L1_map L1list[]={
                          {ETHERTYPE_PUP,     0},
                          {ETHERTYPE_IP,      L2_IP},
                          {ETHERTYPE_ARP,     0},
                          {ETHERTYPE_REVARP,  0},
                          {0xFFFFFFFF      ,  0}              
      
                      };
// 전역변수로 구조체 L1list선언.


int main()
{
  int iSock;
  int iRet;
  struct ifreq stIF;  //
  unsigned char ucBuff[1500];
  struct sockaddr_in stPkat_Info;
  unsigned int uiLen=sizeof(stPkat_Info);
  L1_map *stpL1;
  int ipProto;
  
  iSock=socket(AF_INET, SOCK_PACKET, ntohs(ETH_P_ALL));//소켓 생성. 
  if(0>iSock)
  {
    fprintf(stderr, "error");
    return 0;
  }
//위 if문은 에러시 화면에 error를 찍고 프로그램 종료.

  strcpy(stIF.ifr_name, "eth0" );//문자열 eth0를 stIF.ifr_name에 대입.(랜카드, 랜번호)
  
  iRet=ioctl(iSock, SIOCGIFFLAGS, &stIF);  //ioctl()함수 사용.
//첫 번째 인자는 소켓번호, 두번재 인자는 , 3번째 인자는 크기.
  
  if(0>iRet)//에러처리
  {
    fprintf(stderr, "error");
    close(iSock);
    return 0;
  }
  stIF.ifr_flags= stIF.ifr_flags|IFF_PROMISC;//IFF_PROMISC는 랜카드를 PROMISC모드로 설정한다.

  iRet=ioctl(iSock, SIOCSIFFLAGS, &stIF);  //소켓을 설정한다.

  if(0>iRet)
  {
    fprintf(stderr, "error");
    close(iSock);
    return 0;
  }

  iRet=recvfrom(iSock, ucBuff, 15000, (struct sockaddr *)&stPkat_Info , &uiLen);
 /*   
데이터를 수신하는 함수
1.소켓
2.데이터를 저장하는 버퍼
3.데이터를 저장하는 버퍼의 크기를 지정.
4.제어 플래그, 대부분의 경우 0으로 설정한다.
5.송신자의 주소, 구조체. 이 구조체의 반환영에 따라 struct sockaddr형으로 캐스팅한다. 포인터이기 때문에 인자에
  주소를 넣어야 한다.
6. 자료형이 포인터이기 때문에 주소로 받아야하며, 송신자 주소의 크기가 되겠다.
*/

  ipProto=L1_ethernet(ucBuff);//L1_ethernet(ucBuff)함수를 호출한다. 반환형은 int형. ipProto에 넣는다.
                                      //함수의 설명은 아래 소스를 참조. 인자는 void형 포인터. 송신된 데이터가 들어있는
                                     // ucBuff를 인자로 넣는다.


  stpL1=L1list;         //전역변수 구조체형 L1list배열을 구조체형 포인터에 대입. 배열이름은 주소이기때문에 
                           //포인터에 대입이 가능한다.
//아래 while문이 실행됨으로서 L1list안에 내용들이 출력이 된다. 

  while(1)
  {
    if(iProto==(stpL1->uiType)) //iProto와 stpL1->uiType과 같으면, 정지. uiType은 전역변수 unsigned int형 구조체의 멤버.
    {                                    
      break;
    }
    if(0xFFFFFFFF==(stpL1->uiType))//L1list의 배열의 끝으로 마찬가지로 while문에 종료조건이다.
    {
      break;  

    }
    ++stpL1;   //포인터를 한 칸 이동시키면, 가르키는 주소도 한 칸 이동된다. 처음에는 L1list[0]을  가르키다
                  // 1증가하면 다음주소인 L1list[1]을 가르킨다.

  }

  if(0!=stpL1->L1func)
  {
    (stpL1->L1func)(ucBuff+14);//

  }


  hexaview(ucBuff,iRet);  //헥사뷰 함수 호출.

  close(iSock);  
  return 0;
}


void hexaview(unsigned char *ucP, unsigned int isize)
{
  int iCnt;
  int iLoop;

  printf("---------------------------------------"
      "----------------------------------\n");
  printf("address                     Hexa                              ASCII\n");
  printf("         ");
  for(iCnt=0; iCnt<=15; iCnt= iCnt +1)
  {
    printf("%02X ", iCnt);
  }


  putchar('\n');


  printf("---------------------------------------"
      "----------------------------------\n");

  if(0==isize%16)
  {
    isize = isize/16;
  }
  else
  {
    isize = (isize/16)+1;
  }
  for(iLoop=0;iLoop< isize;iLoop= iLoop+1)  
  {
    printf("%08X ", ucP);

    for(iCnt=0;iCnt<=15;iCnt=iCnt +1)
    {  
      printf("%02X ", *(ucP+iCnt));
    }  

    for(iCnt=0; iCnt<=15; iCnt= iCnt +1)
    {


      if(0==*(ucP+iCnt))
      {  
        printf(".");
      }
      else if(*(ucP+iCnt)<32)
      {
        printf(".");
      }
      else if(*(ucP+iCnt)>127)
      {
        printf(".");
      }
      else
      {
        printf("%c",  *(ucP+iCnt));
      }  
    }
    putchar('\n');
    ucP= ucP+16;
  }

  return;

}







L1_ethernet.c 함수

//패킷을 건져올리는 함수.

#include "ethernet.h"

int L1_ethernet(void *vp)
{
  struct ether_header *stEth=(struct ether_header *)vp;
    
  //printf("-----%02s\n", ether_ntoa ((struct ether_addr *)stEth->ether_shost));
  //
  printf("mac address: [%02X %02X %02X %02X %02X %02X]->"stEth->ether_shost[0], stEth->ether_shost[1],stEth->ether_shost[2],
  stEth->ether_shost[3],stEth->ether_shost[4],stEth->ether_shost[5]);


  printf("[%02X %02X %02X %02X %02X %02X]\n", stEth->ether_dhost[0],stEth->ether_dhost[1],stEth->ether_dhost[2],
  stEth->ether_dhost[3],stEth->ether_dhost[4],stEth->ether_dhost[5]);

  printf("packet type : ");
   
  switch(ntohs(stEth->ether_type))//big endian으로 바꾸는 함수를 스위치문 인자.
 {
    case ETHERTYPE_IP:
                          printf("IP\n");
                        //L2_IP(ucdata+14);
                          break;
    case ETHERTYPE_ARP:
                              printf("Address resolution\n");
                              break;
    case ETHERTYPE_REVARP:
                                  printf("Reverse ARP\n");
                                  break;
      
    default:
            printf("unknown: %04X\n", ntohs(stEth->ether_type));
            break;  


  }
//스위치문에서 해당패킷이 선택되어 지면, 해당 printf()문을 출력한다.  
  
  return (ntohs(stEth->ether_type));스위치문에서 선택된 ether타입을 반환한다.
}















L2ip.c 함수
각종 ip, tcp와 같은 패키지를 화면에 출력하는 함수. ip헤더부분을 나타낸다.


#include "ethernet.h"


int L2_IP(void *vp)
{
  struct ip * stIp=vp;
  unsigned short usChecksum;
  
  printf("ipversion              : IPv%d\n", stIp->ip_v);
  //0~4 4bit version

  printf("ipheader size          : %dbytes\n", (stIp->ip_hl)*4);
  //
0~4 4bit header length

  printf("type of service        : low delay  %s\n", (0==((stIp->ip_tos)&IPTOS_LOWDELAY))? "NO""yes");
  //8bit 
type of service

  printf("                         throughput %s\n", (0==((stIp->ip_tos)&IPTOS_THROUGHPUT))? "NO""yes");
  //total packet length

  printf("                         relability %s\n", (0==((stIp->ip_tos)&IPTOS_RELIABILITY))? "NO""yes");
  //
  printf("                         lowcost    %s\n", (0==((stIp->ip_tos)&IPTOS_LOWCOST))? "NO""yes");

  printf("total length           : %d\n", ntohs(stIp->ip_len));

  printf("identification         : %d\n", ntohs(stIp->ip_id));

  printf("flag                   : More  Fragment %s\n", (0==(ntohs(stIp->ip_off)&IP_MF))? "NO""yes");     

  printf("flag                   : Don't Fragment %s\n", (0==(ntohs(stIp->ip_off)&IP_DF))? "NO""yes");    
 

  printf("flagmentation off_set  : %d\n", ntohs(stIp->ip_off)&IP_OFFMASK);

  printf("time to live           : %d\n", stIp->ip_ttl);

  printf("프로토콜               : ");
                                     
  switch(stIp->ip_p)
  {
    case IPPROTO_IP:
      printf(" Dummy protocol for TCP\n");
      break;
      
    /*case IPTOS_THROUGHPUT:
      printf(" IPv6 Hop-by-Hop options\n");      
      break;*/

      
    case IPPROTO_ICMP :
      printf("Internet Control Message Protocol\n");
      break;
      
    case IPPROTO_IGMP:
      printf("Internet Group Management Protocol\n");
      break;
      
    case IPPROTO_IPIP:
      printf("IPIP tunnels (older KA9Q tunnels use 94)\n");
      break;
      
    case IPPROTO_TCP :
      printf("Transmission Control Protocol\n");      
      break;

    case IPPROTO_EGP  :
      printf("Exterior Gateway Protocol\n");
      break;
      
    case IPPROTO_PUP:
      printf("PUP protocol\n");
      break;
      
    case IPPROTO_UDP:
      printf("User Datagram Protocol\n");      
      break;
      
    case IPPROTO_IDP :
      printf("XNS IDP protocol\n");
      break;
      
    case IPPROTO_TP :
      printf("SO Transport Protocol Class 4\n");
      break;  
      
    case IPPROTO_IPV6:
      printf("IPv6 header\n");
      break;
      
    case IPPROTO_ROUTING:
      printf("IPv6 routing header\n");
      break;
      
    case IPPROTO_FRAGMENT:
      printf("IPv6 fragmentation header\n");
      break;
      
    default:
      break;

  }

  printf("%04x\n",stIp->ip_sum);
  stIp->ip_sum=0x0000;
  
  printf("check sum :%04x\n", smart_cksum(stIp,20));
  usChecksum=stIp->ip_sum;
  stIp->ip_sum=0x0000;
  printf("checksum check         : %s\n", (usChecksum==smart_cksum(stIp,(stIp->ip_hl)*4))?"ok":"fail");
  printf("IP Address             : [%s]->",inet_ntoa(stIp->ip_src));
  printf("[%s]\n", inet_ntoa(stIp->ip_dst));
  printf("IP Address             : [%s]->[%s]\n",inet_ntoa(stIp->ip_src),inet_ntoa(stIp->ip_dst)); 
  

  return stIp->ip_p;//stIp->ip_p 스위치문조건을 만족하는 해당 타입을 반환한다.
}





//체크 섬 함수.
unsigned short smart_cksum(void *vpData, unsigned int uiLen)
{
  unsigned long ulSum;
  for(ulSum =0;uiLen > 0;uiLen=uiLen-2)
  {
    ulSum = ulSum + *((unsigned short  *)vpData);
    vpData= (unsigned short *)vpData +1;
  }
  ulSum = (ulSum>>16) + (ulSum&0xffff);
  ulSum = ulSum + (ulSum>>16);
  return ~ulSum;
}
                              

ethernet.h 헤더파일

#ifndef _ETHERNET_H_
#define _ETHERNET_H_

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <pcap/pcap.h>
#include <netinet/ether.h>
#include <netinet/ip.h>
#include <netinet/in.h>

int L1_ethernet(void *vp);
int L2_IP(void *vp);
unsigned short smart_cksum(void *vpData, unsigned int uiLen);

#endif//_ETHERNET_H_ 


posted by 송시혁