]> The Tcpdump Group git mirrors - tcpdump/blob - print-ip.c
ASCII patches for tcpdump.
[tcpdump] / print-ip.c
1 /* $NetBSD: print-ip.c,v 1.4 1995/04/24 13:27:43 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that: (1) source code distributions
9 * retain the above copyright notice and this paragraph in its entirety, (2)
10 * distributions including binary code include the above copyright notice and
11 * this paragraph in its entirety in the documentation or other materials
12 * provided with the distribution, and (3) all advertising materials mentioning
13 * features or use of this software display the following acknowledgement:
14 * ``This product includes software developed by the University of California,
15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16 * the University nor the names of its contributors may be used to endorse
17 * or promote products derived from this software without specific prior
18 * written permission.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 */
23
24 #ifndef lint
25 static const char rcsid[] =
26 "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.68 1999-10-17 21:56:54 mcr Exp $ (LBL)";
27 #endif
28
29 #include <sys/param.h>
30 #include <sys/time.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33
34 #include <netinet/in.h>
35 #include <netinet/in_systm.h>
36 #include <netinet/ip.h>
37 #include <netinet/udp.h>
38 #include <netinet/tcp.h>
39
40 #include <stdio.h>
41 #ifdef __STDC__
42 #include <stdlib.h>
43 #endif
44 #include <unistd.h>
45
46 #include "interface.h"
47 #include "addrtoname.h"
48
49 static void
50 igmp_print(register const u_char *bp, register int len,
51 register const u_char *bp2)
52 {
53 register const struct ip *ip;
54 register const u_char *ep;
55
56 ip = (const struct ip *)bp2;
57 ep = (const u_char *)snapend;
58 (void)printf("%s > %s: ",
59 ipaddr_string(&ip->ip_src),
60 ipaddr_string(&ip->ip_dst));
61
62 if (bp + 7 > ep) {
63 (void)printf("[|igmp]");
64 return;
65 }
66 switch (bp[0] & 0xf) {
67 case 1:
68 (void)printf("igmp query");
69 if (*(int *)&bp[4])
70 (void)printf(" [gaddr %s]", ipaddr_string(&bp[4]));
71 if (len != 8)
72 (void)printf(" [len %d]", len);
73 break;
74 case 2:
75 (void)printf("igmp report %s", ipaddr_string(&bp[4]));
76 if (len != 8)
77 (void)printf(" [len %d]", len);
78 break;
79 case 3:
80 (void)printf("igmp dvmrp %s", ipaddr_string(&bp[4]));
81 if (len < 8)
82 (void)printf(" [len %d]", len);
83 break;
84 default:
85 (void)printf("igmp-%d", bp[0] & 0xf);
86 break;
87 }
88 if ((bp[0] >> 4) != 1)
89 (void)printf(" [v%d]", bp[0] >> 4);
90 if (bp[1])
91 (void)printf(" [b1=0x%x]", bp[1]);
92 }
93
94 /*
95 * print the recorded route in an IP RR, LSRR or SSRR option.
96 */
97 static void
98 ip_printroute(const char *type, register const u_char *cp, int length)
99 {
100 int ptr = cp[2] - 1;
101 int len;
102
103 printf(" %s{", type);
104 if ((length + 1) & 3)
105 printf(" [bad length %d]", length);
106 if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
107 printf(" [bad ptr %d]", cp[2]);
108
109 type = "";
110 for (len = 3; len < length; len += 4) {
111 if (ptr == len)
112 type = "#";
113 #ifdef TCPDUMP_ALIGN
114 {
115 struct in_addr addr;
116 bcopy((char *)&cp[len], (char *)&addr, sizeof(addr));
117 printf("%s%s", type, ipaddr_string(&addr));
118 }
119 #else
120 printf("%s%s", type, ipaddr_string(&cp[len]));
121 #endif
122 type = " ";
123 }
124 printf("%s}", ptr == len? "#" : "");
125 }
126
127 /*
128 * print IP options.
129 */
130 static void
131 ip_optprint(register const u_char *cp, int length)
132 {
133 int len;
134
135 for (; length > 0; cp += len, length -= len) {
136 int tt = *cp;
137
138 len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1];
139 if (&cp[1] >= snapend || cp + len > snapend) {
140 printf("[|ip]");
141 return;
142 }
143 switch (tt) {
144
145 case IPOPT_EOL:
146 printf(" EOL");
147 if (length > 1)
148 printf("-%d", length - 1);
149 return;
150
151 case IPOPT_NOP:
152 printf(" NOP");
153 break;
154
155 case IPOPT_TS:
156 printf(" TS{%d}", len);
157 break;
158
159 case IPOPT_SECURITY:
160 printf(" SECURITY{%d}", len);
161 break;
162
163 case IPOPT_RR:
164 printf(" RR{%d}=", len);
165 ip_printroute("RR", cp, len);
166 break;
167
168 case IPOPT_SSRR:
169 ip_printroute("SSRR", cp, len);
170 break;
171
172 case IPOPT_LSRR:
173 ip_printroute("LSRR", cp, len);
174 break;
175
176 default:
177 printf(" IPOPT-%d{%d}", cp[0], len);
178 break;
179 }
180 }
181 }
182
183 /*
184 * compute an IP header checksum.
185 * don't modifiy the packet.
186 */
187 static int
188 in_cksum(const struct ip *ip)
189 {
190 register const u_short *sp = (u_short *)ip;
191 register u_int32 sum = 0;
192 register int count;
193
194 /*
195 * No need for endian conversions.
196 */
197 for (count = ip->ip_hl * 2; --count >= 0; )
198 sum += *sp++;
199 while (sum > 0xffff)
200 sum = (sum & 0xffff) + (sum >> 16);
201 sum = ~sum & 0xffff;
202
203 return (sum);
204 }
205
206
207 void
208 print_ipproto(u_int proto, const struct ip *ip,
209 const u_char *cp, int len)
210 {
211 switch (proto) {
212 case IPPROTO_TCP:
213 tcp_print(cp, len, (const u_char *)ip);
214 break;
215 case IPPROTO_UDP:
216 udp_print(cp, len, (const u_char *)ip);
217 break;
218 case IPPROTO_ICMP:
219 icmp_print(cp, (const u_char *)ip);
220 break;
221 case IPPROTO_ND:
222 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
223 ipaddr_string(&ip->ip_dst));
224 (void)printf(" nd %d", len);
225 break;
226 case IPPROTO_EGP:
227 egp_print(cp, len, (const u_char *)ip);
228 break;
229 #ifndef IPPROTO_OSPF
230 #define IPPROTO_OSPF 89
231 #endif
232 case IPPROTO_OSPF:
233 ospf_print(cp, len, (const u_char *)ip);
234 break;
235 #ifndef IPPROTO_IGMP
236 #define IPPROTO_IGMP 2
237 #endif
238 case IPPROTO_IGMP:
239 igmp_print(cp, len, (const u_char *)ip);
240 break;
241 #ifndef IPPROTO_ENCAP
242 #define IPPROTO_ENCAP 4
243 #endif
244 case IPPROTO_ENCAP:
245 /* ip-in-ip encapsulation */
246 if (vflag)
247 (void)printf("%s > %s: ",
248 ipaddr_string(&ip->ip_src),
249 ipaddr_string(&ip->ip_dst));
250 ip_print(cp, len);
251 if (! vflag) {
252 printf(" (encap)");
253 return;
254 }
255 break;
256
257 #ifndef IPPROTO_ESP
258 #define IPPROTO_ESP 50
259 #endif
260 case IPPROTO_ESP:
261 esp_print(cp, len, (const u_char *)ip);
262 break;
263
264 #ifndef IPPROTO_AH
265 #define IPPROTO_AH 51
266 #endif
267 case IPPROTO_AH:
268 ah_print(cp, len, (const u_char *)ip);
269 break;
270
271 default:
272 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
273 ipaddr_string(&ip->ip_dst));
274 (void)printf(" ip-proto-%d %d", proto, len);
275 break;
276 }
277 }
278
279 /*
280 * print an IP datagram.
281 */
282 void
283 ip_print(register const u_char *bp, register int length)
284 {
285 register const struct ip *ip;
286 register int hlen;
287 register int len;
288 register int off;
289 register const u_char *cp;
290
291 ip = (const struct ip *)bp;
292 #ifdef TCPDUMP_ALIGN
293 /*
294 * The IP header is not word aligned, so copy into abuf.
295 * This will never happen with BPF. It does happen raw packet
296 * dumps from -r.
297 */
298 if ((long)ip & (sizeof(long)-1)) {
299 static u_char *abuf;
300
301 if (abuf == 0)
302 abuf = (u_char *)malloc(snaplen);
303 bcopy((char *)ip, (char *)abuf, min(length, snaplen));
304 snapend += abuf - (u_char *)ip;
305 packetp = abuf;
306 ip = (struct ip *)abuf;
307 }
308 #endif
309 if ((u_char *)(ip + 1) > snapend) {
310 printf("[|ip]");
311 return;
312 }
313 if (length < sizeof (struct ip)) {
314 (void)printf("truncated-ip %d", length);
315 return;
316 }
317 hlen = ip->ip_hl * 4;
318
319 len = ntohs(ip->ip_len);
320 if (length < len)
321 (void)printf("truncated-ip - %d bytes missing!",
322 len - length);
323 len -= hlen;
324
325 /*
326 * If this is fragment zero, hand it to the next higher
327 * level protocol.
328 */
329 off = ntohs(ip->ip_off);
330 if ((off & 0x1fff) == 0) {
331 cp = (const u_char *)ip + hlen;
332 print_ipproto(ip->ip_p, ip, cp, len);
333 }
334 /*
335 * for fragmented datagrams, print id:size@offset. On all
336 * but the last stick a "+". For unfragmented datagrams, note
337 * the don't fragment flag.
338 */
339 if (off & 0x3fff) {
340 /*
341 * if this isn't the first frag, we're missing the
342 * next level protocol header. print the ip addr.
343 */
344 if (off & 0x1fff)
345 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
346 ipaddr_string(&ip->ip_dst));
347 (void)printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), len,
348 (off & 0x1fff) * 8,
349 (off & IP_MF)? "+" : "");
350 } else if (off & IP_DF)
351 (void)printf(" (DF)");
352
353 if (ip->ip_tos)
354 (void)printf(" [tos 0x%x]", (int)ip->ip_tos);
355 if (ip->ip_ttl <= 1)
356 (void)printf(" [ttl %d]", (int)ip->ip_ttl);
357
358 if (vflag) {
359 int sum;
360 char *sep = "";
361
362 printf(" (");
363 if (ip->ip_ttl > 1) {
364 (void)printf("%sttl %d", sep, (int)ip->ip_ttl);
365 sep = ", ";
366 }
367 if ((off & 0x3fff) == 0) {
368 (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
369 sep = ", ";
370 }
371 sum = in_cksum(ip);
372 if (sum != 0) {
373 (void)printf("%sbad cksum %x!", sep,
374 ntohs(ip->ip_sum));
375 sep = ", ";
376 }
377 if ((hlen -= sizeof(struct ip)) > 0) {
378 (void)printf("%soptlen=%d", sep, hlen);
379 ip_optprint((u_char *)(ip + 1), hlen);
380 }
381 printf(")");
382 }
383 }