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