免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1245 | 回复: 0
打印 上一主题 下一主题

learn more about TCP/IP [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-08-24 13:14 |只看该作者 |倒序浏览
learn IEEE802.3 TCP/IP UDP protocol format
compile method:
$gcc -Wall -o sniffer sniffer.c
run with root user for test:
$./sinffer
Test environment:
$gcc -v
gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
code filename: sniffer.c
----------
#include stdio.h>
#include unistd.h>
#include stdlib.h>
#include ctype.h>
#include stdint.h>
#include sys/types.h>
#include signal.h>
#include string.h>
#include errno.h>
#include sys/socket.h>
#include netinet/if_ether.h>
#include netinet/in.h>
#include netinet/ip.h>
#include netinet/udp.h>
#include netinet/tcp.h>
#include sys/ioctl.h>
#include net/if.h>
#include arpa/inet.h>
#define    SNIF_BUFFER_SIZE    8192
struct recv_packet
{
  struct ether_header    *ethdr;        /* IEEE802.3 Ethernet header */
  struct iphdr        *iphdr;        /* IP packet header */
  struct udphdr        *udphdr;    /* UDP packet header */
  struct tcphdr        *tcphdr;    /* TCP packet header */
  uint8_t        *data;        /* pointer to data */
  uint32_t        len;        /* data length */
};
/**
* print ip packet information
*/
static void print_eth_header(struct ether_header *etp);
static void print_ip_header(struct iphdr *ip);
static void print_udp_header(struct udphdr *up);
static void print_tcp_header(struct tcphdr *up);
static void print_data(uint8_t *p, uint32_t len);
static int is_filter(struct recv_packet *rcv);
/**
* CTRL + C for exit
*/
static int isc;
static void exit_while(int signo)
{
  isc = 0;
}
int main(int argc, char **argv)
{
  int            sd, rlen;
  unsigned char        buf[SNIF_BUFFER_SIZE], *p, *pe;
  struct ifreq        ethreq;
  struct recv_packet    rcv;
  /* Ctrl+C */
  signal(SIGINT, exit_while);
  if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)))  0)
  {
    fprintf(stderr, "socket create error: %s\n", strerror(errno));
    goto err_1;
  }
  strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ);
  ioctl(sd, SIOCGIFFLAGS, &ethreq);
  ethreq.ifr_flags |= IFF_PROMISC;
  ioctl(sd, SIOCSIFFLAGS, &ethreq);
  p = buf;
  rcv.ethdr = (struct ether_header *)p;
  p += sizeof(struct ether_header);
  rcv.iphdr = (struct iphdr *)p;
  p += sizeof(struct iphdr);
  rcv.udphdr = (struct udphdr *)p;
  rcv.tcphdr = (struct tcphdr *)p;
  isc = 1;
  while (isc)
  {
    rlen = recvfrom(sd, buf, SNIF_BUFFER_SIZE, 0, NULL, NULL);
    if (rlen  42)
    {
      fprintf(stderr, "Recv incomplete header information. \n");
      continue;
    }
    /* pointer to data end */
    pe = buf + rlen;
  
    if (is_filter(&rcv) == 1)
      continue;
    print_eth_header(rcv.ethdr);
    print_ip_header(rcv.iphdr);
    switch (rcv.iphdr->protocol)
    {
      case IPPROTO_UDP:
        print_udp_header(rcv.udphdr);
        rcv.data = (uint8_t *)rcv.udphdr + sizeof(struct udphdr);
        break;
      case IPPROTO_TCP:
        print_tcp_header(rcv.tcphdr);
        rcv.data = (uint8_t *)rcv.tcphdr + sizeof(struct tcphdr);
        break;
    }
    rcv.len = pe - rcv.data;
    print_data(rcv.data, rcv.len);
    printf("\n");
  }
  close(sd);
  return (0);
err_1:
  return (-1);
}
static int is_filter(struct recv_packet *rcv)
{
  uint32_t    saddr, daddr;
#if 0
  uint32_t    spip;
#endif
  saddr = ntohl(rcv->iphdr->saddr);
  daddr = ntohl(rcv->iphdr->daddr);
#if 0
  /* set your sniffer IP */
  spip    = ntohl(inet_addr("192.168.1.84"));
#endif
  /* filter the loopback packet */
  if (saddr == INADDR_LOOPBACK || daddr == INADDR_LOOPBACK)
    return (1);
#if 0
  if (saddr == spip || daddr == spip)
    return (0);
  else
    return (1);
#endif
  return (0);
}
/**
* IEEE 802.3
*/
static void print_eth_header(struct ether_header *etp)
{
#define    _XFF(t)            ((t)&0xFF)
#define    SNIF_ADDR_MAC(p)     \
    _XFF((p)[0]),_XFF((p)[1]),_XFF((p)[2]),_XFF((p)[3]),_XFF((p)[4]),_XFF((p)[5])
    /* dest mac addr [6] | src mac addr [6] | type [2]
     * | ip data packet
     */
   printf("MAC: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X ==> %.2X:%.2X:%.2X:%.2X:%.2X:%.2X "
    , SNIF_ADDR_MAC(etp->ether_shost)
    , SNIF_ADDR_MAC(etp->ether_dhost));
   printf("type.");
   switch (ntohs(etp->ether_type))
   {
     case ETHERTYPE_PUP:     printf("Xerox PUP ");     break;
     case ETHERTYPE_IP:     printf("IP ");         break;
     case ETHERTYPE_ARP:     printf("ARP ");     break;
     case ETHERTYPE_REVARP:     printf("RARP ");     break;
     default:            printf("Unkown type ");    break;
   }
   printf("\n");
}
/**
* IP data packet header
*/
static void print_ip_header(struct iphdr *ip)
{
  struct in_addr    saddr, daddr;
  char            sip[24], dip[24];
    /* ver 4bit | header length 4bits | TOS 8bits | total length 16 bits
     * flags identification 16bits | flags 3bits | offset 13bits
     * TTL 8 bits | protocol type 8bits | checksum 16bits
     * src ip address 32bits
     * dest ip address 32bits
     * options values
     *
     * tcp/udp data packet
     */
  saddr.s_addr = ip->saddr;
  strcpy(sip, inet_ntoa(saddr));
  daddr.s_addr = ip->daddr;
  strcpy(dip, inet_ntoa(daddr));
  printf("IP %s ==> %s \n", sip, dip);
  printf("IP Packet: ver.%d header-length.%d TOS.%04X total-len.%d TTL.%d \n"
    "id.%d offset.%d checksum.%d "
    , ip->version, ip->ihl, ip->tos, ntohs(ip->tot_len), ip->ttl
    , ntohs(ip->id), ntohs(ip->frag_off), ntohs(ip->check)
    );
  printf("protocol.");
  switch (ip->protocol)
  {
    case IPPROTO_ICMP: printf("ICMP "); break;
    case IPPROTO_IGMP: printf("IGMP "); break;
    case IPPROTO_IPIP: printf("IPIP "); break;
    case IPPROTO_RAW: printf("RAW "); break;
    case IPPROTO_TCP: printf("TCP "); break;
    case IPPROTO_UDP: printf("UDP "); break;
    default:
      printf("Unkown protocol type.%d ", ip->protocol);
  }
  printf("\n");
}
/**
* UDP data packet header
*/
static void print_udp_header(struct udphdr *up)
{
  printf("UDP src-port.%d dest-port.%d len.%d checksum.%d "
    , ntohs(up->source), ntohs(up->dest)
    , ntohs(up->len), ntohs(up->check));
  printf("\n");
}
/**
* TCP data packet header
*/
static void print_tcp_header(struct tcphdr *tp)
{
  printf("TCP src-port.%d dest-port.%d seq.%u ack_seq.%u \n"
    "windows.%d checksum.%d pointer.%d "
    , ntohs(tp->source), ntohs(tp->dest)
    , ntohl(tp->seq), ntohl(tp->ack_seq)
    , ntohs(tp->window), ntohs(tp->check), ntohs(tp->urg_ptr));
  if (tp->syn)    printf("syn ");
  if (tp->rst)    printf("rst ");
  if (tp->ack)    printf("ack ");
  if (tp->psh)    printf("psh ");
  if (tp->fin)    printf("fin ");
  if (tp->urg)    printf("urg ");
  printf("\n");
}
/**
* dump data information
*/
static void print_data(uint8_t *p, uint32_t len)
{
  int    i, nlen, j;
  int    flg, ll;
  char    cch[62];
  printf("data.%p data-len.%d \n", p, len);
  nlen = ll = 20;
  for (i = j = 0; i  len; i++, j++)
  {
    printf("%02X", p);
    if ((i+1) % 4 == 0)
    {
      flg = 1;
      printf(" ");
    }
    else
      flg = 0;
    cch[j] = (isprint(p)) ? p : '.';   
    if (j >= nlen && flg == 1)
    {
      ll = j;
      cch[j+1] = '\0';
      printf(" %s\n", cch);
      j = -1;
    }
  }
  cch[j] = '\0';
  for (; j = ll; j++)
  {
    printf(" ");
    if ((j+1) % 4 == 0) printf(" ");
  }
  printf(" %s\n", cch);
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/9205/showart_366752.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP