최상단

컨텐츠

[C] Socket를 이용한 Snooper의 구현//

글 정보

Category
컴퓨터 이야기
2006. 6. 7. 22:08

본문

덜덜덜.......오랫만에 남이 짜 놓은 소스를 봐서 그런지;;

자극 만점+_+;;;

이정도는 해야지 C프로그램인가ㅡㅡ;;하하;;
아직 멀었다.ㅡㅜ

/* snooper.c
*
* Copyright (c) 2000 Sean Walton and Macmillan Publishers.  Use may be in
* whole or in part in accordance to the General Public License (GPL).
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

/*****************************************************************************/
/*** snooper.c                                                             ***/
/***                                                                       ***/
/*** This program captures *all* packets that the network interface sees.  ***/
/*** Be very careful with this tool, because you may see all lot of info.  ***/
/*** Also, it uses the deprecated SOCK_PACKET socket type.  The newer and  ***/
/*** preferred method is with PF_PACKET.                                   ***/
/*****************************************************************************/

#include <stdio.h>
#include <sys/socket.h>
#include <resolv.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/types.h>
#include <linux/if_ether.h>

#define IP_SIZE  4
#define ETH_SIZE 6

typedef enum { eETH_ADDR, eIP_ADDR } EAddress;

typedef unsigned char uchar;

/*--------------------------------------------------------------------*/
/* Ethernet Frame                                                     */
/*                                                                    */
/* This structure defines the fields within the ethernet frame. Since */
/* this programs gets the lowest-level packet, fragmented packets are */
/* not reassembled.  The first few fields contain the MAC addresses   */
/* of the source and destination. Note that this structure is set for */
/* little-endian format.                                              */
/*--------------------------------------------------------------------*/
struct ip_packet {
struct {
uchar dst_eth[ETH_SIZE];
uchar src_eth[ETH_SIZE];
uchar __unknwn[2];
} hw_header;             /* hardware header */
  uint header_len:4;       /* header length in words in 32bit words */
  uint version:4;          /* 4-bit version */
  uint serve_type:8;       /* how to service packet */
  uint packet_len:16;      /* total size of packet in bytes */
  uint ID:16;              /* fragment ID */
  uint frag_offset:13;     /* to help reassembly */
  uint more_frags:1;       /* flag for "more frags to follow" */
  uint dont_frag:1;        /* flag to permit fragmentation */
  uint __reserved:1;       /* always zero */
  uint time_to_live:8;     /* maximum router hop count */
  uint protocol:8;         /* ICMP, UDP, TCP */
  uint hdr_chksum:16;      /* ones-comp. checksum of header */
  uchar IPv4_src[IP_SIZE]; /* IP address of originator */
  uchar IPv4_dst[IP_SIZE]; /* IP address of destination */
  uchar options[0];        /* up to 40 bytes */
  uchar data[0];           /* message data up to 64KB */
};

/*--------------------------------------------------------------------*/
/* dump                                                               */
/*                                                                    */
/* Dump a block of data in hex & ascii.                               */
/*--------------------------------------------------------------------*/
void dump(void* b, int len)
{   unsigned char *buf = b;
  int i, cnt=0;
  char str[17];
  memset(str, 0, 17);

  for ( i = 0; i < len; i++ )
  {
       if ( cnt % 16 == 0 && i != 0 )
       {
           printf(" : %s : %d \n", str, cnt);
           memset(str, 0, 17);
  cnt=0;
       }
       if ( buf[i] < ' '  ||  buf[i] >= 127 )
           str[cnt] = '.';
       else
           str[cnt] = buf[i];
       printf(" %02X", buf[i]);
       cnt++;
  }

  printf("%*s : %-16s : %d\n\n",(16-(len%16))*3, "", str,len%16); // 잘안되는 부분이 있어서
수정을 조금 하기는 했지만.. %*s라는 형식을 처음봤음-0-;;;

}

/*--------------------------------------------------------------------*/
/* PrintAddr                                                          */
/*                                                                    */
/* Print the different types of address (MAC or IP).                  */
/*--------------------------------------------------------------------*/
void PrintAddr(char* msg, uchar *addr, EAddress is_ip)
{ int i;
static struct {
int len;
char *fmt;
char delim;
} addr_fmt[] = {{ETH_SIZE, "%x", ':'}, {IP_SIZE, "%d", '.'}};

printf("%s", msg);
for ( i = 0; i < addr_fmt[is_ip].len; i++ )
{
printf(addr_fmt[is_ip].fmt, addr[i]);
if ( i < addr_fmt[is_ip].len-1 )
  putchar(addr_fmt[is_ip].delim);
}

}

/*--------------------------------------------------------------------*/
/* GetProtocol                                                        */
/*                                                                    */
/* Convert the protocol value into the alphabetic representation.     */
/*--------------------------------------------------------------------*/
char* GetProtocol(int value)
{
switch (value)
{
case IPPROTO_IP: return "IP";
case IPPROTO_ICMP: return "ICMP";
case IPPROTO_IGMP: return "IGMP";
case IPPROTO_IPIP: return "IPIP";
case IPPROTO_TCP: return "TCP";
case IPPROTO_EGP: return "EGP";
case IPPROTO_PUP: return "PUP";
case IPPROTO_UDP: return "UDP";
case IPPROTO_IDP: return "IDP";
case IPPROTO_RSVP: return "RSVP";
case IPPROTO_GRE: return "GRE";
case IPPROTO_IPV6: return "IPV6/4";
case IPPROTO_PIM: return "PIM";
case IPPROTO_RAW: return "RAW";
default: return "???";
}
}

/*--------------------------------------------------------------------*/
/* DumpPacket                                                         */
/*                                                                    */
/* Display the read packet with data and fields.                      */
/*--------------------------------------------------------------------*/
void DumpPacket(char *buffer, int len)
{ struct ip_packet *ip=(void*)buffer;

printf("-------------------------------------------------\n");
dump(buffer, len);
PrintAddr("Destination EtherID=", ip->hw_header.dst_eth, eETH_ADDR);
PrintAddr(", Source EtherID=", ip->hw_header.src_eth, eETH_ADDR);
printf("\nIPv%d: header-len=%d, type=%d, packet-size=%d, ID=%d\n",
ip->version, ip->header_len*4, ip->serve_type,
ntohs(ip->packet_len), ntohs(ip->ID));
printf("frag=%c, more=%c, offset=%d, TTL=%d, protocol=%s\n",
(ip->dont_frag? 'N': 'Y'),
(ip->more_frags? 'N': 'Y'),
ip->frag_offset,
ip->time_to_live, GetProtocol(ip->protocol));
printf("checksum=%d, ", ntohs(ip->hdr_chksum));
PrintAddr("source=", ip->IPv4_src, eIP_ADDR);
PrintAddr(", destination=", ip->IPv4_dst, eIP_ADDR);
printf("\n");
fflush(stdout);
}

void PANIC(char *msg);
#define PANIC(msg) {perror(msg);exit(0);}

/*--------------------------------------------------------------------*/
/* main                                                               */
/*                                                                    */
/* Open socket.  Repeatedly read and display records.                 */
/*--------------------------------------------------------------------*/
int main()
{   int sd, bytes_read;
  char data[1024];

  sd  = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
  if ( sd < 0 )
PANIC("Snooper socket");
  do
{
   bytes_read = recvfrom(sd, data, sizeof(data), 0, 0, 0);
       if ( bytes_read > 0 )
  DumpPacket(data, bytes_read);
  }
while ( bytes_read > 0 );
  return 0;
}


소스 전체적인 부분은
http://www.cs.utah.edu/~swalton/listings/sockets/programs/
에서 가져왔고..
출력하는 부분에 문제가 있어 조금 수정을 했습니다//
파란색으로 해놓은 부분 완전 감동-_-;;;
씨언어의 또다른 세계가 보인다ㅡㅡ;;

소스 첨부

트랙백과 댓글 여닫기

TOP