1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <netinet/in.h>
4 #include <netinet/in_systm.h>
5 #include <netinet/ip.h>
6 #include <netinet/ip_var.h>
7 #include <netinet/udp.h>
8 #include <netinet/udp_var.h>
9 #include <netinet/tcp.h>
10 #include <netinet/tcpip.h>
11 
12 #include "tcpview.h"
13 #include "addrtoname.h"
14 
15 #ifdef __STDC__
16 static void ip_printroute(u_char *, int);
17 static void ip_optprint(u_char *, int);
18 static void do_addr(int, int, u_char *);
19 #else
20 static void ip_printroute();
21 static void ip_optprint();
22 static void do_addr();
23 #endif
24 
25 char *Precedence[] = { "", "Priority", "Immediate", "Flash", "Flash Override",
26 			 "CRITIC/ECP", "Internetwork Control", "Network Control" };
27 
28 extern char D_Src_Host[64], D_Dst_Host[64], D_Proto[8];
29 extern u_short D_Src_Port, D_Dst_Port;
30 
detail_ip(ip)31 void detail_ip(ip)
32      register struct ip *ip;
33 {
34   u_short hlen;
35   register unsigned char *cp;
36   u_short off, id, len;
37   char buf[64];
38 
39 #ifdef TCPDUMP_ALIGN
40   static u_char *abuf=NULL;
41   /*
42    * The IP header is not word aligned, so copy into abuf.
43    * This will never happen with BPF.  It does happen raw packet
44    * dumps from -r.
45    */
46   if ((int)ip & (sizeof(long)-1)) {
47     if (abuf == NULL)
48       abuf = (u_char *)malloc(MAX_SNAPLEN);
49     bcopy((char *)ip, (char *)abuf, Phdr->caplen-Offset);
50     ip = (struct ip *)abuf;
51   }
52 #endif
53 
54   len = Phdr->caplen - Offset;
55   if (len < sizeof (struct ip)) {
56     printf("***** IP (truncated) *****");
57     hex(0,Phdr->caplen - Offset - 1);
58     return;
59   }
60 
61   hlen = ip->ip_hl * 4;  /* header length */
62 
63   off = ntohs(ip->ip_off);  /* fragment offset */
64   id = ntohs(ip->ip_id);
65   len = ntohs(ip->ip_len) - hlen;   /* total size of datagram minus header */
66 
67   printf("----- IP Header -----\n\n");
68   hex( 0, hlen - 1 );    /* header */
69   hex( -1, -1 );       /* blank line */
70   printf("Version = %d, header length = %d\n",ip->ip_v,hlen);
71   hex( 0, 0 );         /* Version and Header Length */
72   if( ip->ip_tos ) {
73     u_char prec = (ip->ip_tos & 0xe0)>>5;
74     strcpy(buf,Precedence[prec]);
75     if( ip->ip_tos & 0x10) {
76       if( *buf ) strcat(buf,", ");
77       strcat(buf,"Low Delay");
78     }
79     if( ip->ip_tos & 0x08) {
80       if( *buf ) strcat(buf,", ");
81       strcat(buf,"High Throughput");
82     }
83     if( ip->ip_tos & 0x04) {
84       if( *buf ) strcat(buf,", ");
85       strcat(buf,"High Relibility");
86     }
87     printf("Type of service = 0x%02x ( %s )\n",ip->ip_tos,buf);
88   } else
89     printf("Type of service = 0\n");
90   printf("Total length = %d bytes\n",ntohs(ip->ip_len));
91   printf("Identification = %d\n",id);
92   hex( 1, 1 );         /* TOS */
93   hex( 2, 3 );         /* Total Length */
94   hex( 4, 5 );         /* ID */
95 
96   buf[0]='\0';
97   if( off & IP_DF)
98     strcat(buf,"Don't Fragment  ");
99   if( off & IP_MF)
100     strcat(buf,"More Fragments");
101   printf("Flags = 0x%02x ( %s )\n",(off&(IP_MF|IP_DF))>>13,buf);
102   hex( 6, 6 );         /* Flags */
103   printf("Fragment offset = %d bytes\n",off&0x1fff);
104   hex( 6, 7 );         /* Fragment offset */
105   printf("Time to live = %d hops or seconds\n",ip->ip_ttl);
106   hex( 8, 8 );         /* TTL */
107 
108   strcpy(D_Proto,ipproto_string(ip->ip_p));
109   printf("Protocol = %d ( %s )\n",ip->ip_p,D_Proto);
110   hex( 9, 9 );         /* protocol */
111 
112   printf("Header checksum = 0x%x\n",ntohs(ip->ip_sum));
113   hex( 10, 11 );       /* header checksum */
114 
115   strcpy(D_Src_Host,ipaddr_str(&ip->ip_src,ADDR_NUMERICAL));
116   printf("Source address = [%s], %s\n",
117 	 D_Src_Host,ipaddr_str(&ip->ip_src,ADDR_DOMAIN));
118   strcpy(D_Dst_Host,ipaddr_str(&ip->ip_dst,ADDR_NUMERICAL));
119   printf("Destination address = [%s], %s\n",
120 	 D_Dst_Host,ipaddr_str(&ip->ip_dst,ADDR_DOMAIN));
121 
122   hex( 12, 15 );       /* source */
123   hex( 16, 19 );       /* destination */
124 
125   if( hlen > sizeof(struct ip) ) {  /* must be options here */
126     u_short old_offset = Offset;
127     printf("IP OPTIONS\n");
128     hex(20,hlen-1);
129     Offset += sizeof(struct ip);
130     ip_optprint((u_char *)(ip+1),hlen-sizeof(struct ip));
131     Offset = old_offset;
132   }
133 
134   /* if this is a fragment, there is no higher layer so just return now */
135   if( off & 0x1fff )
136     return;
137 
138   putchar('\n');
139   hex( -1, -1 );       /* blank line */
140 
141   cp = (unsigned char *)ip + hlen;  /* pointer to next protocol header */
142   Offset += hlen;
143 
144   switch (ip->ip_p) {
145   case IPPROTO_TCP:
146     detail_tcp((struct tcphdr *)cp, len);
147     break;
148   case IPPROTO_UDP:
149     detail_udp((struct udphdr *)cp, len);
150     break;
151 /***
152   case IPPROTO_EGP:
153     detail_egp((u_char *)cp);
154     break;
155 ***/
156   case IPPROTO_ICMP:
157     detail_icmp((struct icmp *)cp, len);
158     break;
159   default:
160     break;
161   }
162 }
163 
164 /*
165  * print IP options.
166  */
ip_optprint(cp,length)167 static void ip_optprint(cp, length)
168      u_char *cp;
169      int length;
170 {
171   u_short len;
172 
173   for (; length > 0; cp += len, length -= len) {
174     u_char tt = *cp;
175 
176     len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1];
177     /* check to see if there is space for code, len, and all data */
178     if( Phdr->caplen - Offset - 2 < len ) {
179       printf("*** truncated ***");
180       hex(0,Phdr->caplen-Offset-1);
181       return;
182     }
183     switch (tt) {
184 
185     case IPOPT_EOL:
186       printf("  End Of List\n");
187       hex(0,0);
188       if (length > 1) {
189 	printf("  %d bytes remaining", length - 1);
190 	hex(-1,-1);
191       }
192       return;
193 
194     case IPOPT_NOP:
195       printf("  NOP\n");
196       hex(0,0);
197       Offset++;
198       break;
199 
200     case IPOPT_TS:
201       printf("  Timestamp\n");
202       hex(0,len+1);
203       Offset += len+2;
204       break;
205 
206     case IPOPT_SECURITY:
207       printf("  Security{%d}\n", len);
208       hex(0,len+1);
209       Offset += len+2;
210       break;
211 
212     case IPOPT_RR:
213       printf("  Record Route\n");
214       hex(0,len);
215       ip_printroute(cp, len);
216       Offset += len;
217       break;
218 
219     case IPOPT_SSRR:
220       printf("  Strict Source Route\n");
221       hex(0,len);
222       ip_printroute(cp, len);
223       Offset += len;
224       break;
225 
226     case IPOPT_LSRR:
227       printf("  Loose Source Route\n");
228       hex(0,len);
229       ip_printroute(cp, len);
230       Offset += len;
231       break;
232 
233     default:
234       printf("  Unknown IP option %d\n", cp[0]);
235       hex(0,len);
236       Offset += len;
237       break;
238     }
239   }
240 }
241 
242 
243 /*
244  * print the recorded route in an IP RR, LSRR or SSRR option.
245  */
ip_printroute(cp,length)246 static void ip_printroute(cp, length)
247      u_char *cp;
248      int length;
249 {
250   int ptr = cp[2] - 1;
251   int len;
252 
253   if ((length + 1) & 3)
254     printf("    [bad length %d]\n", length);
255   else
256     printf("    length %d\n",length);
257   hex(1,1);
258 
259   if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
260     printf("    [bad ptr %d]\n", cp[2]);
261   else
262     printf("    ptr %d\n",cp[2]);
263   hex(2,2);
264 
265   for (len = 3; len < length; len += 4) {
266 #ifdef TCPDUMP_ALIGN
267     {
268       struct in_addr addr;
269       bcopy((char *)&cp[len], (char *)&addr, sizeof(addr));
270       do_addr(ptr,len,(u_char *)&addr);
271     }
272 #else
273     do_addr(ptr,len,&cp[len]);
274 #endif
275     hex(len,len+3);
276   }
277 }
278 
do_addr(ptr,len,addr)279 static void do_addr( ptr, len, addr)
280      int ptr,len;
281      u_char *addr;
282 {
283   char *str1, *str2;
284 
285   if( len >= ptr )
286     printf("      # %s\n",ipaddr_str(addr,ADDR_NUMERICAL));
287   else {
288     str1 = ipaddr_str(addr,ADDR_NUMERICAL);
289     str2 = ipaddr_str(addr,0);
290     if( strcmp(str1,str2) )
291       printf("      %s [%s]\n", str2, str1);
292     else
293       printf("      %s\n",str2);
294   }
295 }
296 
297 
298 
299 
300 
301