]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-ip.c
This commit was generated by cvs2svn to compensate for changes in r98005,
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-ip.c
1 /*
2  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
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  * $FreeBSD$
22  */
23
24 #ifndef lint
25 static const char rcsid[] =
26     "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.92 2001/01/02 23:00:01 guy Exp $ (LBL)";
27 #endif
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <sys/param.h>
34 #include <sys/time.h>
35 #include <sys/socket.h>
36
37 #include <netinet/in.h>
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43
44 #include "addrtoname.h"
45 #include "interface.h"
46 #include "extract.h"                    /* must come after interface.h */
47
48 #include "ip.h"
49
50 /* Compatibility */
51 #ifndef IPPROTO_ND
52 #define IPPROTO_ND      77
53 #endif
54
55 /*
56  * print the recorded route in an IP RR, LSRR or SSRR option.
57  */
58 static void
59 ip_printroute(const char *type, register const u_char *cp, u_int length)
60 {
61         register u_int ptr = cp[2] - 1;
62         register u_int len;
63
64         printf(" %s{", type);
65         if ((length + 1) & 3)
66                 printf(" [bad length %d]", length);
67         if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
68                 printf(" [bad ptr %d]", cp[2]);
69
70         type = "";
71         for (len = 3; len < length; len += 4) {
72                 if (ptr == len)
73                         type = "#";
74                 printf("%s%s", type, ipaddr_string(&cp[len]));
75                 type = " ";
76         }
77         printf("%s}", ptr == len? "#" : "");
78 }
79
80 static void
81 ip_printts(register const u_char *cp, u_int length)
82 {
83         register u_int ptr = cp[2] - 1;
84         register u_int len = 0;
85         int hoplen;
86         char *type;
87
88         printf(" TS{");
89         hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
90         if ((length - 4) & (hoplen-1))
91                 printf("[bad length %d]", length);
92         if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
93                 printf("[bad ptr %d]", cp[2]);
94         switch (cp[3]&0xF) {
95         case IPOPT_TS_TSONLY:
96                 printf("TSONLY");
97                 break;
98         case IPOPT_TS_TSANDADDR:
99                 printf("TS+ADDR");
100                 break;
101         /*
102          * prespecified should really be 3, but some ones might send 2
103          * instead, and the IPOPT_TS_PRESPEC constant can apparently
104          * have both values, so we have to hard-code it here.
105          */
106
107         case 2:
108                 printf("PRESPEC2.0");
109                 break;
110         case 3:                 /* IPOPT_TS_PRESPEC */
111                 printf("PRESPEC");
112                 break;
113         default:        
114                 printf("[bad ts type %d]", cp[3]&0xF);
115                 goto done;
116         }
117
118         type = " ";
119         for (len = 4; len < length; len += hoplen) {
120                 if (ptr == len)
121                         type = " ^ ";
122                 printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
123                        hoplen!=8 ? "" : ipaddr_string(&cp[len]));
124                 type = " ";
125         }
126
127 done:
128         printf("%s", ptr == len ? " ^ " : "");
129
130         if (cp[3]>>4)
131                 printf(" [%d hops not recorded]} ", cp[3]>>4);
132         else
133                 printf("}");
134 }
135
136 /*
137  * print IP options.
138  */
139 static void
140 ip_optprint(register const u_char *cp, u_int length)
141 {
142         register u_int len;
143
144         for (; length > 0; cp += len, length -= len) {
145                 int tt = *cp;
146
147                 if (tt == IPOPT_NOP || tt == IPOPT_EOL)
148                         len = 1;
149                 else {
150                         if (&cp[1] >= snapend) {
151                                 printf("[|ip]");
152                                 return;
153                         }
154                         len = cp[1];
155                 }
156                 if (len <= 0) {
157                         printf("[|ip op len %d]", len);
158                         return;
159                 }
160                 if (&cp[1] >= snapend || cp + len > snapend) {
161                         printf("[|ip]");
162                         return;
163                 }
164                 switch (tt) {
165
166                 case IPOPT_EOL:
167                         printf(" EOL");
168                         if (length > 1)
169                                 printf("-%d", length - 1);
170                         return;
171
172                 case IPOPT_NOP:
173                         printf(" NOP");
174                         break;
175
176                 case IPOPT_TS:
177                         ip_printts(cp, len);
178                         break;
179
180 #ifndef IPOPT_SECURITY
181 #define IPOPT_SECURITY 130
182 #endif /* IPOPT_SECURITY */
183                 case IPOPT_SECURITY:
184                         printf(" SECURITY{%d}", len);
185                         break;
186
187                 case IPOPT_RR:
188                         ip_printroute("RR", cp, len);
189                         break;
190
191                 case IPOPT_SSRR:
192                         ip_printroute("SSRR", cp, len);
193                         break;
194
195                 case IPOPT_LSRR:
196                         ip_printroute("LSRR", cp, len);
197                         break;
198
199 #ifndef IPOPT_RA
200 #define IPOPT_RA 148            /* router alert */
201 #endif
202                 case IPOPT_RA:
203                         printf(" RA");
204                         if (len != 4)
205                                 printf("{%d}", len);
206                         else if (cp[2] || cp[3])
207                                 printf("%d.%d", cp[2], cp[3]);
208                         break;
209
210                 default:
211                         printf(" IPOPT-%d{%d}", cp[0], len);
212                         break;
213                 }
214         }
215 }
216
217 /*
218  * compute an IP header checksum.
219  * don't modifiy the packet.
220  */
221 u_short
222 in_cksum(const u_short *addr, register int len, u_short csum)
223 {
224         int nleft = len;
225         const u_short *w = addr;
226         u_short answer;
227         int sum = csum;
228
229         /*
230          *  Our algorithm is simple, using a 32 bit accumulator (sum),
231          *  we add sequential 16 bit words to it, and at the end, fold
232          *  back all the carry bits from the top 16 bits into the lower
233          *  16 bits.
234          */
235         while (nleft > 1)  {
236                 sum += *w++;
237                 nleft -= 2;
238         }
239         if (nleft == 1)
240                 sum += htons(*(u_char *)w<<8);
241
242         /*
243          * add back carry outs from top 16 bits to low 16 bits
244          */
245         sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
246         sum += (sum >> 16);                     /* add carry */
247         answer = ~sum;                          /* truncate to 16 bits */
248         return (answer);
249 }
250
251 /*
252  * print an IP datagram.
253  */
254 void
255 ip_print(register const u_char *bp, register u_int length)
256 {
257         register const struct ip *ip;
258         register u_int hlen, len, len0, off;
259         register const u_char *cp;
260         u_char nh;
261         int advance;
262
263         ip = (const struct ip *)bp;
264 #ifdef LBL_ALIGN
265         /*
266          * If the IP header is not aligned, copy into abuf.
267          * This will never happen with BPF.  It does happen raw packet
268          * dumps from -r.
269          */
270         if ((long)ip & 3) {
271                 static u_char *abuf = NULL;
272                 static int didwarn = 0;
273
274                 if (abuf == NULL) {
275                         abuf = (u_char *)malloc(snaplen);
276                         if (abuf == NULL)
277                                 error("ip_print: malloc");
278                 }
279                 memcpy((char *)abuf, (char *)ip, min(length, snaplen));
280                 snapend += abuf - (u_char *)ip;
281                 packetp = abuf;
282                 ip = (struct ip *)abuf;
283                 /* We really want libpcap to give us aligned packets */
284                 if (!didwarn) {
285                         warning("compensating for unaligned libpcap packets");
286                         ++didwarn;
287                 }
288         }
289 #endif
290         if ((u_char *)(ip + 1) > snapend) {
291                 printf("[|ip]");
292                 return;
293         }
294         if (length < sizeof (struct ip)) {
295                 (void)printf("truncated-ip %d", length);
296                 return;
297         }
298         hlen = IP_HL(ip) * 4;
299         if (hlen < sizeof (struct ip)) {
300                 (void)printf("bad-hlen %d", hlen);
301                 return;
302         }
303
304         len = ntohs(ip->ip_len);
305         if (length < len)
306                 (void)printf("truncated-ip - %d bytes missing!",
307                         len - length);
308         len -= hlen;
309         len0 = len;
310
311         /*
312          * If this is fragment zero, hand it to the next higher
313          * level protocol.
314          */
315         off = ntohs(ip->ip_off);
316         if ((off & 0x1fff) == 0) {
317                 cp = (const u_char *)ip + hlen;
318                 nh = ip->ip_p;
319
320                 if (nh != IPPROTO_TCP && nh != IPPROTO_UDP) {
321                         (void)printf("%s > %s: ", ipaddr_string(&ip->ip_src),
322                                 ipaddr_string(&ip->ip_dst));
323                 }
324 again:
325                 switch (nh) {
326
327 #ifndef IPPROTO_AH
328 #define IPPROTO_AH      51
329 #endif
330                 case IPPROTO_AH:
331                         nh = *cp;
332                         advance = ah_print(cp, (const u_char *)ip);
333                         cp += advance;
334                         len -= advance;
335                         goto again;
336
337 #ifndef IPPROTO_ESP
338 #define IPPROTO_ESP     50
339 #endif
340                 case IPPROTO_ESP:
341                     {
342                         int enh;
343                         advance = esp_print(cp, (const u_char *)ip, &enh);
344                         cp += advance;
345                         len -= advance;
346                         if (enh < 0)
347                                 break;
348                         nh = enh & 0xff;
349                         goto again;
350                     }
351
352 #ifndef IPPROTO_IPCOMP
353 #define IPPROTO_IPCOMP  108
354 #endif
355                 case IPPROTO_IPCOMP:
356                     {
357                         int enh;
358                         advance = ipcomp_print(cp, (const u_char *)ip, &enh);
359                         cp += advance;
360                         len -= advance;
361                         if (enh < 0)
362                                 break;
363                         nh = enh & 0xff;
364                         goto again;
365                     }
366
367                 case IPPROTO_TCP:
368                         tcp_print(cp, len, (const u_char *)ip, (off &~ 0x6000));
369                         break;
370
371                 case IPPROTO_UDP:
372                         udp_print(cp, len, (const u_char *)ip, (off &~ 0x6000));
373                         break;
374
375                 case IPPROTO_ICMP:
376                         icmp_print(cp, len, (const u_char *)ip);
377                         break;
378
379 #ifndef IPPROTO_IGRP
380 #define IPPROTO_IGRP 9
381 #endif
382                 case IPPROTO_IGRP:
383                         igrp_print(cp, len, (const u_char *)ip);
384                         break;
385
386                 case IPPROTO_ND:
387 #if 0
388                         (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
389                                 ipaddr_string(&ip->ip_dst));
390 #endif
391                         (void)printf(" nd %d", len);
392                         break;
393
394                 case IPPROTO_EGP:
395                         egp_print(cp, len, (const u_char *)ip);
396                         break;
397
398 #ifndef IPPROTO_OSPF
399 #define IPPROTO_OSPF 89
400 #endif
401                 case IPPROTO_OSPF:
402                         ospf_print(cp, len, (const u_char *)ip);
403                         break;
404
405 #ifndef IPPROTO_IGMP
406 #define IPPROTO_IGMP 2
407 #endif
408                 case IPPROTO_IGMP:
409                         igmp_print(cp, len, (const u_char *)ip);
410                         break;
411
412                 case 4:
413                         /* DVMRP multicast tunnel (ip-in-ip encapsulation) */
414 #if 0
415                         if (vflag)
416                                 (void)printf("%s > %s: ",
417                                              ipaddr_string(&ip->ip_src),
418                                              ipaddr_string(&ip->ip_dst));
419 #endif
420                         ip_print(cp, len);
421                         if (! vflag) {
422                                 printf(" (ipip)");
423                                 return;
424                         }
425                         break;
426
427 #ifdef INET6
428 #ifndef IP6PROTO_ENCAP
429 #define IP6PROTO_ENCAP 41
430 #endif
431                 case IP6PROTO_ENCAP:
432                         /* ip6-in-ip encapsulation */
433 #if 0
434                         if (vflag)
435                                 (void)printf("%s > %s: ",
436                                              ipaddr_string(&ip->ip_src),
437                                              ipaddr_string(&ip->ip_dst));
438 #endif
439                         ip6_print(cp, len);
440                         if (! vflag) {
441                                 printf(" (encap)");
442                                 return;
443                         }
444                         break;
445 #endif /*INET6*/
446
447
448 #ifndef IPPROTO_GRE
449 #define IPPROTO_GRE 47
450 #endif
451                 case IPPROTO_GRE:
452                         if (vflag)
453                                 (void)printf("gre %s > %s: ",
454                                              ipaddr_string(&ip->ip_src),
455                                              ipaddr_string(&ip->ip_dst));
456                         /* do it */
457                         gre_print(cp, len);
458                         if (! vflag) {
459                                 printf(" (gre encap)");
460                                 return;
461                         }
462                         break;
463
464 #ifndef IPPROTO_MOBILE
465 #define IPPROTO_MOBILE 55
466 #endif
467                 case IPPROTO_MOBILE:
468                         if (vflag)
469                                 (void)printf("mobile %s > %s: ",
470                                              ipaddr_string(&ip->ip_src),
471                                              ipaddr_string(&ip->ip_dst));
472                         mobile_print(cp, len);
473                         if (! vflag) {
474                                 printf(" (mobile encap)");
475                                 return;
476                         }
477                         break;
478
479 #ifndef IPPROTO_PIM
480 #define IPPROTO_PIM     103
481 #endif
482                 case IPPROTO_PIM:
483                         pim_print(cp, len);
484                         break;
485
486 #ifndef IPPROTO_VRRP
487 #define IPPROTO_VRRP    112
488 #endif
489                 case IPPROTO_VRRP:
490                         if (vflag)
491                                 (void)printf("vrrp %s > %s: ",
492                                              ipaddr_string(&ip->ip_src),
493                                              ipaddr_string(&ip->ip_dst));
494                         vrrp_print(cp, len, ip->ip_ttl);
495                         break;
496
497                 default:
498 #if 0
499                         (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
500                                 ipaddr_string(&ip->ip_dst));
501 #endif
502                         (void)printf(" ip-proto-%d %d", nh, len);
503                         break;
504                 }
505         }
506
507         /* Ultra quiet now means that all this stuff should be suppressed */
508         /* res 3-Nov-98 */
509         if (qflag > 1) return;
510
511
512         /*
513          * for fragmented datagrams, print id:size@offset.  On all
514          * but the last stick a "+".  For unfragmented datagrams, note
515          * the don't fragment flag.
516          */
517         len = len0;     /* get the original length */
518         if (off & 0x3fff) {
519                 /*
520                  * if this isn't the first frag, we're missing the
521                  * next level protocol header.  print the ip addr.
522                  */
523                 if (off & 0x1fff)
524                         (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
525                                       ipaddr_string(&ip->ip_dst));
526 #ifndef IP_MF
527 #define IP_MF 0x2000
528 #endif /* IP_MF */
529 #ifndef IP_DF
530 #define IP_DF 0x4000
531 #endif /* IP_DF */
532                 (void)printf(" (frag %d:%u@%d%s)", ntohs(ip->ip_id), len,
533                         (off & 0x1fff) * 8,
534                         (off & IP_MF)? "+" : "");
535
536         } else if (off & IP_DF)
537                 (void)printf(" (DF)");
538
539         if (ip->ip_tos) {
540                 (void)printf(" [tos 0x%x", (int)ip->ip_tos);
541                 /* ECN bits */
542                 if (ip->ip_tos&0x02) {
543                         (void)printf(",ECT");
544                         if (ip->ip_tos&0x01)
545                                 (void)printf(",CE");
546                 }
547                 (void)printf("] ");
548         }
549
550         if (ip->ip_ttl <= 1)
551                 (void)printf(" [ttl %d]", (int)ip->ip_ttl);
552
553         if (vflag) {
554                 int sum;
555                 char *sep = "";
556
557                 printf(" (");
558                 if (ip->ip_ttl > 1) {
559                         (void)printf("%sttl %d", sep, (int)ip->ip_ttl);
560                         sep = ", ";
561                 }
562                 if ((off & 0x3fff) == 0) {
563                         (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
564                         sep = ", ";
565                 }
566                 (void)printf("%slen %d", sep, (int)ntohs(ip->ip_len));
567                 sep = ", ";
568                 if ((u_char *)ip + hlen <= snapend) {
569                         sum = in_cksum((const u_short *)ip, hlen, 0);
570                         if (sum != 0) {
571                                 (void)printf("%sbad cksum %x!", sep,
572                                              ntohs(ip->ip_sum));
573                                 sep = ", ";
574                         }
575                 }
576                 if ((hlen -= sizeof(struct ip)) > 0) {
577                         (void)printf("%soptlen=%d", sep, hlen);
578                         ip_optprint((u_char *)(ip + 1), hlen);
579                 }
580                 printf(")");
581         }
582 }
583
584 void
585 ipN_print(register const u_char *bp, register u_int length)
586 {
587         struct ip *ip, hdr;
588
589         ip = (struct ip *)bp;
590         if (length < 4) {
591                 (void)printf("truncated-ip %d", length);
592                 return;
593         }
594         memcpy (&hdr, (char *)ip, 4);
595         switch (IP_V(&hdr)) {
596         case 4:
597             ip_print (bp, length);
598             return;
599 #ifdef INET6
600         case 6:
601             ip6_print (bp, length);
602             return;
603 #endif
604         default:
605             (void)printf("unknown ip %d", IP_V(&hdr));
606             return;
607         }
608 }