home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / dos_win / pcroute / analyzer / ip.c.Z / ip.c
Encoding:
C/C++ Source or Header  |  1992-02-09  |  9.4 KB  |  360 lines

  1. /*************************************************************************/
  2. /*                           ip.c     ip.c                               */
  3. /*************************************************************************/
  4.  
  5. /* ip.c prints out IP and ARP packets in human readable form */
  6.  
  7. /* AUTHOR: Vance Morrison
  8.    DATE:  6/5/90            */
  9.  
  10. static char copywrite[] = "Copywrite (c) 1990, Vance Morrison";
  11. /*************************************************************************/
  12.  
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #include <bios.h>
  16.  
  17. #define swap_word(n) ((((unsigned short) n) >> 8)+(((unsigned short) n) << 8))
  18.  
  19. #define ARP_REQUEST 1
  20. #define ARP_REPLY   2
  21. #define ARP_ETHER_TYPE 1
  22.  
  23. struct arp {
  24.     unsigned short arp_hdr;                /* header type 1 = ETHERNET */
  25.     unsigned short arp_proto;              /* protocol code */
  26.     unsigned char arp_hln;                 /* length of ethernet address */
  27.     unsigned char arp_pln;                 /* length of ethernet address */
  28.     unsigned short arp_op;                 /* operation (request reply) */
  29.     unsigned char arp_sha[6];              /* source hardware address */
  30.     unsigned char arp_spa[4];              /* source protocol address */
  31.     unsigned char arp_tha[6];              /* target hardware address */
  32.     unsigned char arp_tpa[4];              /* target protocol address */
  33.     };
  34.  
  35. #define IP_PROTO_ICMP 1
  36. #define IP_PROTO_TCP 6
  37. #define IP_PROTO_UDP 17
  38.  
  39. struct ip {
  40.     unsigned char ip_ver_size;
  41.     unsigned char ip_tos;
  42.     unsigned short ip_length;
  43.     unsigned short ip_id;
  44.     unsigned short ip_frag;
  45.     unsigned char  ip_ttl;
  46.     unsigned char  ip_proto;
  47.     unsigned short ip_check;
  48.     unsigned char ip_src[4];
  49.     unsigned char ip_dst[4];
  50.     unsigned char ip_data[1];
  51.     };
  52.  
  53. struct udp {
  54.     unsigned short udp_src;
  55.     unsigned short udp_dst;
  56.     unsigned short udp_length;
  57.     unsigned short udp_check;
  58.     unsigned char udp_data[1];
  59.     };
  60.  
  61.     /* values for type field */
  62. #define ICMP_ECHO_REPLY     0
  63. #define ICMP_ECHO_REQUEST   8
  64. #define ICMP_TIME           11
  65. #define ICMP_UNREACHABLE    3
  66. #define ICMP_REDIRECT       5
  67.  
  68.     /* values for the code field */
  69. #define ICMP_TIME_TTL       0
  70. #define ICMP_UNREACH_NET    0
  71. #define ICMP_UNREACH_HOST   1
  72. #define ICMP_UNREACH_PROTO  2
  73. #define ICMP_UNREACH_PORT   3
  74.  
  75. #define ICMP_REDIRECT_NET        0
  76. #define ICMP_REDIRECT_HOST       1
  77. #define ICMP_REDIRECT_TOS_NET    2
  78. #define ICMP_REDIRECT_TOS_HOST   3
  79.  
  80. struct icmp {
  81.     unsigned char icmp_type;
  82.     unsigned char icmp_code;
  83.     unsigned short icmp_check;
  84.     unsigned short icmp_id;
  85.     unsigned short icmp_seq;
  86.     };
  87.  
  88.    /* definition of RIP packet structure */
  89.  
  90. #define RIP_PORT               0x208
  91.  
  92. #define RIP_REPLY               2 
  93. #define IP_FAMILY               2
  94.  
  95. struct rip_route {
  96.     unsigned short rip_family;
  97.     unsigned short rip_zero1;
  98.     unsigned char rip_address[4];
  99.     unsigned char rip_zero2[4];
  100.     unsigned char rip_zero3[4];
  101.     unsigned char rip_metric[4];
  102.     };
  103.  
  104. struct rip {
  105.     unsigned char rip_command;
  106.     unsigned char rip_version;
  107.     unsigned short rip_zero;
  108.     struct rip_route rip_routes[1];         /* routing info */
  109.     };
  110.  
  111. struct tcp {
  112.     unsigned short tcp_src;
  113.     unsigned short tcp_dst;
  114.     unsigned long tcp_seq;
  115.     unsigned long tcp_ack;
  116.     unsigned char tcp_off;
  117.     unsigned char tcp_flags;
  118.     unsigned short tcp_window;
  119.     unsigned short tcp_check;
  120.     unsigned short tcp_urgent;
  121.     unsigned char tcp_data[1];
  122.     };
  123.  
  124.  
  125. /******************************************************************/
  126. print_IP_addr(ip_addr)
  127.     unsigned char *ip_addr;
  128. {
  129.     char buff[20];
  130.     sprintf(buff, "%d.%d.%d.%d",ip_addr[0],ip_addr[1],ip_addr[2],ip_addr[3]);
  131.     printf("%15s", buff);
  132. }
  133.  
  134.  
  135. /******************************************************************/
  136. print_arp(p)
  137.     struct arp *p;
  138. {
  139.     unsigned short op;
  140.  
  141.     printf("    ARP PACKET\n");
  142.     printf("    TYPE: %d ", swap_word(p->arp_hdr));
  143.     op = swap_word(p->arp_op);
  144.     printf("    OP:   %d ", op);
  145.     if (op == ARP_REQUEST)
  146.     printf("(REQUEST) ");
  147.     else if (op == ARP_REPLY)
  148.     printf("(REPLY)   ");
  149.     else
  150.     printf("(UNKNOWN) ");
  151.     printf("\n");
  152.  
  153.     printf("    SOURCE:  ETHER ");
  154.     print_ether_addr(p->arp_sha);
  155.     printf("    IP ");
  156.     print_IP_addr(p->arp_spa);
  157.     printf("\n");
  158.  
  159.     printf("    TARGET:  ETHER ");
  160.     print_ether_addr(p->arp_tha);
  161.     printf("    IP ");
  162.     print_IP_addr(p->arp_tpa);
  163.     printf("\n");
  164. }
  165.  
  166.  
  167. /******************************************************************/
  168. /* computes the ones complement some of a block of numbers  (assumes
  169.    a twos complement 16 bit short integer) */
  170.  
  171. ones_comp_sum(p, len)
  172.     unsigned short *p;
  173.     int len;
  174. {
  175.     register unsigned short sum;
  176.     register unsigned short new_sum;
  177.  
  178.     sum = 0;
  179.     while (len > 0) {
  180.        new_sum = sum + *p++;
  181.        if (new_sum < sum)       /* did we wrap around */
  182.            new_sum++;
  183.        sum = new_sum;
  184.        --len;
  185.        }
  186.     return(sum);
  187. }
  188.  
  189. /**************************************************************************/
  190. /* pseudo_head_sum, computes the checksum for the psuedo-header given a
  191.    IP packet.  This number is used for TCP and UDP checksumming */
  192.  
  193. unsigned short pseudo_head_sum(p)
  194.     struct ip *p;
  195. {
  196.     unsigned short data_len;
  197.     unsigned short check;
  198.     unsigned char ttl;
  199.     unsigned short ret;
  200.  
  201.     check = p->ip_check;
  202.     ttl = p->ip_ttl;
  203.  
  204.     p->ip_ttl = 0;
  205.     data_len = swap_word(p->ip_length) - 4*(p->ip_ver_size%16);
  206.     p->ip_check = swap_word(data_len);
  207.     ret = ones_comp_sum((unsigned short *) &p->ip_ttl, 6);
  208.  
  209.     p->ip_check = check;
  210.     p->ip_ttl = ttl;
  211.     return(ret);
  212. }
  213.  
  214.  
  215. /******************************************************************/
  216. print_ip(p)
  217.     struct ip *p;
  218. {
  219.     unsigned short check, my_check;
  220.  
  221.     printf("    IP PACKET   ");
  222.     print_IP_addr(p->ip_src);
  223.     printf("   -->   ");
  224.     print_IP_addr(p->ip_dst);
  225.     printf("\n");
  226.  
  227.     printf("    VER:%2d     SIZE:%2d   ID: %4xH   TOS:%3d    FRAG/FLAGS: %4xH\n"
  228.         ,(p->ip_ver_size / 16), (p->ip_ver_size % 16),  swap_word(p->ip_id),
  229.         p->ip_tos, swap_word(p->ip_frag));
  230.     printf("    LEN:%4d   TTL:%3d   PROTOCOL:%4d ", 
  231.     swap_word(p->ip_length), p->ip_ttl, p->ip_proto);
  232.     switch (p->ip_proto) {
  233.         case IP_PROTO_ICMP:
  234.             printf("(ICMP)");
  235.             break;
  236.         case IP_PROTO_TCP:
  237.             printf("(TCP) ");
  238.             break;
  239.         case IP_PROTO_UDP:
  240.             printf("(UDP) ");
  241.             break;
  242.         default:
  243.             printf("      ");
  244.             break;
  245.         }
  246.  
  247.     check = p->ip_check;
  248.     p->ip_check = 0;
  249.     my_check = ~ones_comp_sum((unsigned short *) p, 10);
  250.     p->ip_check = check;
  251.     printf("   CHECK: %4xH ", swap_word(check));
  252.     if (check == 0)
  253.         printf("(Ignored)       ");
  254.     else if (check == my_check)
  255.         printf("(Correct)       ");
  256.     else
  257.         printf("(Should be %4x)", swap_word(my_check));
  258.     printf("\n");
  259.  
  260.     switch (p->ip_proto) {
  261.         case IP_PROTO_ICMP:
  262.             print_icmp((struct icmp *) p->ip_data);
  263.             break;
  264.         case IP_PROTO_TCP:
  265.             print_tcp((struct tcp *) p->ip_data, 
  266.                 swap_word(p->ip_length)-4*(p->ip_ver_size%16));
  267.             break;
  268.         case IP_PROTO_UDP:
  269.             print_udp((struct udp *) p->ip_data);
  270.             break;
  271.         default:
  272.             break;
  273.         }
  274. }
  275.  
  276.  
  277. /******************************************************************/
  278.  
  279. print_udp(p)
  280.     struct udp *p;
  281. {
  282.  
  283.     printf("        UDP PACKET\n");
  284.     printf("        LEN:%4d   SOURCE: %3d    DEST %3d:   CHECK: %4xH\n",
  285.         swap_word(p->udp_length), swap_word(p->udp_src), 
  286.         swap_word(p->udp_dst), swap_word(p->udp_check));
  287.  
  288.     switch (swap_word(p->udp_dst)) {
  289.         case RIP_PORT:
  290.             print_rip((struct rip *) p->udp_data, swap_word(p->udp_length)-8);
  291.             break;
  292.         default:
  293.             break;
  294.         }
  295. }
  296.  
  297.  
  298. /******************************************************************/
  299. print_tcp(p, len)
  300.     struct tcp *p;
  301.     int len;
  302. {
  303.     printf("        TCP PACKET\n");
  304.     printf("        LEN:%4d   SOURCE: %3d    DEST %3d:   CHECK: %4xH\n",
  305.         len - 20, swap_word(p->tcp_src), swap_word(p->tcp_dst), 
  306.         swap_word(p->tcp_check));
  307. }
  308.  
  309.  
  310. /******************************************************************/
  311. print_icmp(p)
  312.     struct icmp *p;
  313. {
  314.     printf("        ICMP PACKET\n");
  315.     printf("        TYPE:%3d", p->icmp_type);
  316.     switch (p->icmp_type) {
  317.         case ICMP_ECHO_REPLY:
  318.             printf("(ECHO REPLY)   ");
  319.             break;
  320.         case ICMP_ECHO_REQUEST:
  321.             printf("(ECHO REQUEST) ");
  322.             break;
  323.         case ICMP_TIME:
  324.             printf("(TIME)         ");
  325.             break;
  326.         case ICMP_UNREACHABLE:
  327.             printf("(UNREACHABLE)  ");
  328.             break;
  329.         case ICMP_REDIRECT:
  330.             printf("(REDIRECT)     ");
  331.             break;
  332.         default:
  333.             printf("(UNKNOWN)      ");
  334.             break;
  335.         }
  336.     printf("   CODE:%3d", p->icmp_code);
  337. }
  338.  
  339.  
  340. /******************************************************************/
  341. print_rip(p, len)
  342.     struct rip *p;
  343.     int len;
  344. {
  345.     int i, num_routes;
  346.  
  347.     printf("            RIP PACKET\n");
  348.     printf("            COMMAND:%3d     VERSION:%3d\n", 
  349.         p->rip_command, p->rip_version);
  350.  
  351.     num_routes = (len - 4)/20;
  352.     for(i = 0; i < num_routes; i++) {
  353.         printf("                ROUTE: ");      
  354.         print_IP_addr(p->rip_routes[i].rip_address);
  355.         printf("   METRIC:%3d", p->rip_routes[i].rip_metric[3]);
  356.         printf("   FAMILY:%3d\n", swap_word(p->rip_routes[i].rip_family));
  357.         }
  358. }
  359.  
  360.