home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / tcpdumpb.zip / print-ip.c < prev    next >
C/C++ Source or Header  |  1997-02-25  |  17KB  |  511 lines

  1. /*
  2.  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
  3.  *      The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] =
  24.     "@(#) $Header: print-ip.c,v 1.56 96/07/23 14:17:24 leres Exp $ (LBL)";
  25. #endif
  26.  
  27. #include <sys/param.h>
  28. #include <sys/time.h>
  29. #include <sys/socket.h>
  30.  
  31. #include <netinet/in.h>
  32. #include <netinet/in_systm.h>
  33. #include <netinet/ip.h>
  34. #ifndef __EMX__
  35. #include <netinet/ip_var.h>
  36. #endif
  37. #include <netinet/udp.h>
  38. #include <netinet/udp_var.h>
  39. #include <netinet/tcp.h>
  40. #ifndef __EMX__
  41. #include <netinet/tcpip.h>
  42. #endif
  43.  
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <unistd.h>
  48.  
  49. #include "addrtoname.h"
  50. #include "interface.h"
  51. #include "extract.h"                    /* must come after interface.h */
  52.  
  53. /* Compatibility */
  54. #ifndef IPPROTO_ND
  55. #define IPPROTO_ND      77
  56. #endif
  57.  
  58. #ifndef IN_CLASSD
  59. #define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000)
  60. #endif
  61.  
  62. /* (following from ipmulti/mrouted/prune.h) */
  63.  
  64. /*
  65.  * The packet format for a traceroute request.
  66.  */
  67. struct tr_query {
  68.         u_int  tr_src;                  /* traceroute source */
  69.         u_int  tr_dst;                  /* traceroute destination */
  70.         u_int  tr_raddr;                /* traceroute response address */
  71. #if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
  72.         struct {
  73.                 u_int   qid : 24;       /* traceroute query id */
  74.                 u_int   ttl : 8;        /* traceroute response ttl */
  75.         } q;
  76. #else
  77.         struct {
  78.                 u_int   ttl : 8;        /* traceroute response ttl */
  79.                 u_int   qid : 24;       /* traceroute query id */
  80.         } q;
  81. #endif /* BYTE_ORDER */
  82. };
  83.  
  84. #define tr_rttl q.ttl
  85. #define tr_qid  q.qid
  86.  
  87. /*
  88.  * Traceroute response format.  A traceroute response has a tr_query at the
  89.  * beginning, followed by one tr_resp for each hop taken.
  90.  */
  91. struct tr_resp {
  92.         u_int tr_qarr;                  /* query arrival time */
  93.         u_int tr_inaddr;                /* incoming interface address */
  94.         u_int tr_outaddr;               /* outgoing interface address */
  95.         u_int tr_rmtaddr;               /* parent address in source tree */
  96.         u_int tr_vifin;                 /* input packet count on interface */
  97.         u_int tr_vifout;                /* output packet count on interface */
  98.         u_int tr_pktcnt;                /* total incoming packets for src-grp */
  99.         u_char  tr_rproto;              /* routing proto deployed on router */
  100.         u_char  tr_fttl;                /* ttl required to forward on outvif */
  101.         u_char  tr_smask;               /* subnet mask for src addr */
  102.         u_char  tr_rflags;              /* forwarding error codes */
  103. };
  104.  
  105. /* defs within mtrace */
  106. #define TR_QUERY 1
  107. #define TR_RESP 2
  108.  
  109. /* fields for tr_rflags (forwarding error codes) */
  110. #define TR_NO_ERR       0
  111. #define TR_WRONG_IF     1
  112. #define TR_PRUNED       2
  113. #define TR_OPRUNED      3
  114. #define TR_SCOPED       4
  115. #define TR_NO_RTE       5
  116. #define TR_NO_FWD       7
  117. #define TR_NO_SPACE     0x81
  118. #define TR_OLD_ROUTER   0x82
  119.  
  120. /* fields for tr_rproto (routing protocol) */
  121. #define TR_PROTO_DVMRP  1
  122. #define TR_PROTO_MOSPF  2
  123. #define TR_PROTO_PIM    3
  124. #define TR_PROTO_CBT    4
  125.  
  126. static void print_mtrace(register const u_char *bp, register u_int len)
  127. {
  128.         register struct tr_query* tr = (struct tr_query*)(bp + 8);
  129.  
  130.         printf("mtrace %d: %s to %s reply-to %s", tr->tr_qid,
  131.                 ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
  132.                 ipaddr_string(&tr->tr_raddr));
  133.         if (IN_CLASSD(ntohl(tr->tr_raddr)))
  134.                 printf(" with-ttl %d", tr->tr_rttl);
  135. }
  136.  
  137. static void print_mresp(register const u_char *bp, register u_int len)
  138. {
  139.         register struct tr_query* tr = (struct tr_query*)(bp + 8);
  140.  
  141.         printf("mresp %d: %s to %s reply-to %s", tr->tr_qid,
  142.                 ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
  143.                 ipaddr_string(&tr->tr_raddr));
  144.         if (IN_CLASSD(ntohl(tr->tr_raddr)))
  145.                 printf(" with-ttl %d", tr->tr_rttl);
  146. }
  147.  
  148. static void
  149. igmp_print(register const u_char *bp, register u_int len,
  150.            register const u_char *bp2)
  151. {
  152.         register const struct ip *ip;
  153.  
  154.         ip = (const struct ip *)bp2;
  155.         (void)printf("%s > %s: ",
  156.                 ipaddr_string(&ip->ip_src),
  157.                 ipaddr_string(&ip->ip_dst));
  158.  
  159.         TCHECK2(bp[0], 8);
  160.         switch (bp[0]) {
  161.         case 0x11:
  162.                 (void)printf("igmp query");
  163.                 if (*(int *)&bp[4])
  164.                         (void)printf(" [gaddr %s]", ipaddr_string(&bp[4]));
  165.                 if (len != 8)
  166.                         (void)printf(" [len %d]", len);
  167.                 break;
  168.         case 0x12:
  169.                 (void)printf("igmp report %s", ipaddr_string(&bp[4]));
  170.                 if (len != 8)
  171.                         (void)printf(" [len %d]", len);
  172.                 break;
  173.         case 0x16:
  174.                 (void)printf("igmp nreport %s", ipaddr_string(&bp[4]));
  175.                 break;
  176.         case 0x17:
  177.                 (void)printf("igmp leave %s", ipaddr_string(&bp[4]));
  178.                 break;
  179.         case 0x13:
  180.                 (void)printf("igmp dvmrp");
  181.                 if (len < 8)
  182.                         (void)printf(" [len %d]", len);
  183.                 else
  184.                         dvmrp_print(bp, len);
  185.                 break;
  186.         case 0x14:
  187.                 (void)printf("igmp pim");
  188.                 pim_print(bp, len);
  189.                 break;
  190.         case 0x1e:
  191.                 print_mresp(bp, len);
  192.                 break;
  193.         case 0x1f:
  194.                 print_mtrace(bp, len);
  195.                 break;
  196.         default:
  197.                 (void)printf("igmp-%d", bp[0] & 0xf);
  198.                 break;
  199.         }
  200.         if ((bp[0] >> 4) != 1)
  201.                 (void)printf(" [v%d]", bp[0] >> 4);
  202.  
  203.         TCHECK2(bp[0], len);
  204.         if (vflag) {
  205.                 /* Check the IGMP checksum */
  206.                 u_int32_t sum = 0;
  207.                 int count;
  208.                 const u_short *sp = (u_short*)bp;
  209.  
  210.                 for (count = len / 2; --count >= 0; )
  211.                         sum += *sp++;
  212.                 if (len & 1)
  213.                         sum += ntohs(*(unsigned char*) sp << 8);
  214.                 while (sum >> 16)
  215.                         sum = (sum & 0xffff) + (sum >> 16);
  216.                 sum = 0xffff & ~sum;
  217.                 if (sum != 0)
  218.                         printf(" bad igmp cksum %x!", EXTRACT_16BITS(&bp[2]));
  219.         }
  220.         return;
  221. trunc:
  222.         fputs("[|igmp]", stdout);
  223. }
  224.  
  225. /*
  226.  * print the recorded route in an IP RR, LSRR or SSRR option.
  227.  */
  228. static void
  229. ip_printroute(const char *type, register const u_char *cp, u_int length)
  230. {
  231.         register u_int ptr = cp[2] - 1;
  232.         register u_int len;
  233.  
  234.         printf(" %s{", type);
  235.         if ((length + 1) & 3)
  236.                 printf(" [bad length %d]", length);
  237.         if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
  238.                 printf(" [bad ptr %d]", cp[2]);
  239.  
  240.         type = "";
  241.         for (len = 3; len < length; len += 4) {
  242.                 if (ptr == len)
  243.                         type = "#";
  244.                 printf("%s%s", type, ipaddr_string(&cp[len]));
  245.                 type = " ";
  246.         }
  247.         printf("%s}", ptr == len? "#" : "");
  248. }
  249.  
  250. /*
  251.  * print IP options.
  252.  */
  253. static void
  254. ip_optprint(register const u_char *cp, u_int length)
  255. {
  256.         register u_int len;
  257.  
  258.         for (; length > 0; cp += len, length -= len) {
  259.                 int tt = *cp;
  260.  
  261.                 len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1];
  262.                 if (len <= 0) {
  263.                         printf("[|ip op len %d]", len);
  264.                         return;
  265.                 }
  266.                 if (&cp[1] >= snapend || cp + len > snapend) {
  267.                         printf("[|ip]");
  268.                         return;
  269.                 }
  270.                 switch (tt) {
  271.  
  272.                 case IPOPT_EOL:
  273.                         printf(" EOL");
  274.                         if (length > 1)
  275.                                 printf("-%d", length - 1);
  276.                         return;
  277.  
  278.                 case IPOPT_NOP:
  279.                         printf(" NOP");
  280.                         break;
  281.  
  282.                 case IPOPT_TS:
  283.                         printf(" TS{%d}", len);
  284.                         break;
  285.  
  286.                 case IPOPT_SECURITY:
  287.                         printf(" SECURITY{%d}", len);
  288.                         break;
  289.  
  290.                 case IPOPT_RR:
  291.                         printf(" RR{%d}=", len);
  292.                         ip_printroute("RR", cp, len);
  293.                         break;
  294.  
  295.                 case IPOPT_SSRR:
  296.                         ip_printroute("SSRR", cp, len);
  297.                         break;
  298.  
  299.                 case IPOPT_LSRR:
  300.                         ip_printroute("LSRR", cp, len);
  301.                         break;
  302.  
  303.                 default:
  304.                         printf(" IPOPT-%d{%d}", cp[0], len);
  305.                         break;
  306.                 }
  307.         }
  308. }
  309.  
  310. /*
  311.  * compute an IP header checksum.
  312.  * don't modifiy the packet.
  313.  */
  314. static int
  315. in_cksum(const struct ip *ip)
  316. {
  317.         register const u_short *sp = (u_short *)ip;
  318.         register u_int32_t sum = 0;
  319.         register int count;
  320.  
  321.         /*
  322.          * No need for endian conversions.
  323.          */
  324.         for (count = ip->ip_hl * 2; --count >= 0; )
  325.                 sum += *sp++;
  326.         while (sum > 0xffff)
  327.                 sum = (sum & 0xffff) + (sum >> 16);
  328.         sum = ~sum & 0xffff;
  329.  
  330.         return (sum);
  331. }
  332.  
  333. /*
  334.  * print an IP datagram.
  335.  */
  336. void
  337. ip_print(register const u_char *bp, register u_int length)
  338. {
  339.         register const struct ip *ip;
  340.         register u_int hlen, len, off;
  341.         register const u_char *cp;
  342.  
  343.         ip = (const struct ip *)bp;
  344. #ifdef LBL_ALIGN
  345.         /*
  346.          * If the IP header is not aligned, copy into abuf.
  347.          * This will never happen with BPF.  It does happen raw packet
  348.          * dumps from -r.
  349.          */
  350.         if ((long)ip & 3) {
  351.                 static u_char *abuf = NULL;
  352.                 static int didwarn = 0;
  353.  
  354.                 if (abuf == NULL) {
  355.                         abuf = (u_char *)malloc(snaplen);
  356.                         if (abuf == NULL)
  357.                                 error("ip_print: malloc");
  358.                 }
  359.                 memcpy((char *)abuf, (char *)ip, min(length, snaplen));
  360.                 snapend += abuf - (u_char *)ip;
  361.                 packetp = abuf;
  362.                 ip = (struct ip *)abuf;
  363.                 /* We really want libpcap to give us aligned packets */
  364.                 if (!didwarn) {
  365.                         warning("compensating for unaligned libpcap packets");
  366.                         ++didwarn;
  367.                 }
  368.         }
  369. #endif
  370.         if ((u_char *)(ip + 1) > snapend) {
  371.                 printf("[|ip]");
  372.                 return;
  373.         }
  374.         if (length < sizeof (struct ip)) {
  375.                 (void)printf("truncated-ip %d", length);
  376.                 return;
  377.         }
  378.         hlen = ip->ip_hl * 4;
  379.  
  380.         len = ntohs(ip->ip_len);
  381.         if (length < len)
  382.                 (void)printf("truncated-ip - %d bytes missing!",
  383.                         len - length);
  384.         len -= hlen;
  385.  
  386.         /*
  387.          * If this is fragment zero, hand it to the next higher
  388.          * level protocol.
  389.          */
  390.         off = ntohs(ip->ip_off);
  391.         if ((off & 0x1fff) == 0) {
  392.                 cp = (const u_char *)ip + hlen;
  393.                 switch (ip->ip_p) {
  394.  
  395.                 case IPPROTO_TCP:
  396.                         tcp_print(cp, len, (const u_char *)ip);
  397.                         break;
  398.                 case IPPROTO_UDP:
  399.                         udp_print(cp, len, (const u_char *)ip);
  400.                         break;
  401.                 case IPPROTO_ICMP:
  402.                         icmp_print(cp, (const u_char *)ip);
  403.                         break;
  404.  
  405. #ifndef IPPROTO_IGRP
  406. #define IPPROTO_IGRP 9
  407. #endif
  408.                 case IPPROTO_IGRP:
  409.                         igrp_print(cp, len, (const u_char *)ip);
  410.                         break;
  411.  
  412.                 case IPPROTO_ND:
  413.                         (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
  414.                                 ipaddr_string(&ip->ip_dst));
  415.                         (void)printf(" nd %d", len);
  416.                         break;
  417.  
  418.                 case IPPROTO_EGP:
  419.                         egp_print(cp, len, (const u_char *)ip);
  420.                         break;
  421.  
  422. #ifndef IPPROTO_OSPF
  423. #define IPPROTO_OSPF 89
  424. #endif
  425.                 case IPPROTO_OSPF:
  426.                         ospf_print(cp, len, (const u_char *)ip);
  427.                         break;
  428.  
  429. #ifndef IPPROTO_IGMP
  430. #define IPPROTO_IGMP 2
  431. #endif
  432.                 case IPPROTO_IGMP:
  433.                         igmp_print(cp, len, (const u_char *)ip);
  434.                         break;
  435.  
  436. #ifndef IPPROTO_ENCAP
  437. #define IPPROTO_ENCAP 4
  438. #endif
  439.                 case IPPROTO_ENCAP:
  440.                         /* ip-in-ip encapsulation */
  441.                         if (vflag)
  442.                                 (void)printf("%s > %s: ",
  443.                                              ipaddr_string(&ip->ip_src),
  444.                                              ipaddr_string(&ip->ip_dst));
  445.                         ip_print(cp, len);
  446.                         if (! vflag) {
  447.                                 printf(" (encap)");
  448.                                 return;
  449.                         }
  450.                         break;
  451.  
  452.                 default:
  453.                         (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
  454.                                 ipaddr_string(&ip->ip_dst));
  455.                         (void)printf(" ip-proto-%d %d", ip->ip_p, len);
  456.                         break;
  457.                 }
  458.         }
  459.         /*
  460.          * for fragmented datagrams, print id:size@offset.  On all
  461.          * but the last stick a "+".  For unfragmented datagrams, note
  462.          * the don't fragment flag.
  463.          */
  464.         if (off & 0x3fff) {
  465.                 /*
  466.                  * if this isn't the first frag, we're missing the
  467.                  * next level protocol header.  print the ip addr.
  468.                  */
  469.                 if (off & 0x1fff)
  470.                         (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
  471.                                       ipaddr_string(&ip->ip_dst));
  472.                 (void)printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), len,
  473.                         (off & 0x1fff) * 8,
  474.                         (off & IP_MF)? "+" : "");
  475.         } else if (off & IP_DF)
  476.                 (void)printf(" (DF)");
  477.  
  478.         if (ip->ip_tos)
  479.                 (void)printf(" [tos 0x%x]", (int)ip->ip_tos);
  480.         if (ip->ip_ttl <= 1)
  481.                 (void)printf(" [ttl %d]", (int)ip->ip_ttl);
  482.  
  483.         if (vflag) {
  484.                 int sum;
  485.                 char *sep = "";
  486.  
  487.                 printf(" (");
  488.                 if (ip->ip_ttl > 1) {
  489.                         (void)printf("%sttl %d", sep, (int)ip->ip_ttl);
  490.                         sep = ", ";
  491.                 }
  492.                 if ((off & 0x3fff) == 0) {
  493.                         (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
  494.                         sep = ", ";
  495.                 }
  496.                 if ((u_char *)ip + hlen <= snapend) {
  497.                         sum = in_cksum(ip);
  498.                         if (sum != 0) {
  499.                                 (void)printf("%sbad cksum %x!", sep,
  500.                                              ntohs(ip->ip_sum));
  501.                                 sep = ", ";
  502.                         }
  503.                 }
  504.                 if ((hlen -= sizeof(struct ip)) > 0) {
  505.                         (void)printf("%soptlen=%d", sep, hlen);
  506.                         ip_optprint((u_char *)(ip + 1), hlen);
  507.                 }
  508.                 printf(")");
  509.         }
  510. }
  511.