]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-ip.c
Catch up with "base" telnet.
[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.100 2001/09/17 21:58:03 fenner 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 u_int len, int 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 #ifndef IPPROTO_SCTP
321 #define IPPROTO_SCTP 132
322 #endif
323                 if (nh != IPPROTO_TCP && nh != IPPROTO_UDP &&
324                     nh != IPPROTO_SCTP) {
325                         (void)printf("%s > %s: ", ipaddr_string(&ip->ip_src),
326                                 ipaddr_string(&ip->ip_dst));
327                 }
328 again:
329                 switch (nh) {
330
331 #ifndef IPPROTO_AH
332 #define IPPROTO_AH      51
333 #endif
334                 case IPPROTO_AH:
335                         nh = *cp;
336                         advance = ah_print(cp, (const u_char *)ip);
337                         cp += advance;
338                         len -= advance;
339                         goto again;
340
341 #ifndef IPPROTO_ESP
342 #define IPPROTO_ESP     50
343 #endif
344                 case IPPROTO_ESP:
345                     {
346                         int enh, padlen;
347                         advance = esp_print(cp, (const u_char *)ip, &enh, &padlen);
348                         cp += advance;
349                         len -= advance + padlen;
350                         if (enh < 0)
351                                 break;
352                         nh = enh & 0xff;
353                         goto again;
354                     }
355
356 #ifndef IPPROTO_IPCOMP
357 #define IPPROTO_IPCOMP  108
358 #endif
359                 case IPPROTO_IPCOMP:
360                     {
361                         int enh;
362                         advance = ipcomp_print(cp, (const u_char *)ip, &enh);
363                         cp += advance;
364                         len -= advance;
365                         if (enh < 0)
366                                 break;
367                         nh = enh & 0xff;
368                         goto again;
369                     }
370
371                 case IPPROTO_SCTP:
372                         sctp_print(cp, (const u_char *)ip, len);
373                         break;
374
375                 case IPPROTO_TCP:
376                         tcp_print(cp, len, (const u_char *)ip, (off &~ 0x6000));
377                         break;
378
379                 case IPPROTO_UDP:
380                         udp_print(cp, len, (const u_char *)ip, (off &~ 0x6000));
381                         break;
382
383                 case IPPROTO_ICMP:
384                         icmp_print(cp, len, (const u_char *)ip);
385                         break;
386
387 #ifndef IPPROTO_IGRP
388 #define IPPROTO_IGRP 9
389 #endif
390                 case IPPROTO_IGRP:
391                         igrp_print(cp, len, (const u_char *)ip);
392                         break;
393
394                 case IPPROTO_ND:
395                         (void)printf(" nd %d", len);
396                         break;
397
398                 case IPPROTO_EGP:
399                         egp_print(cp, len, (const u_char *)ip);
400                         break;
401
402 #ifndef IPPROTO_OSPF
403 #define IPPROTO_OSPF 89
404 #endif
405                 case IPPROTO_OSPF:
406                         ospf_print(cp, len, (const u_char *)ip);
407                         break;
408
409 #ifndef IPPROTO_IGMP
410 #define IPPROTO_IGMP 2
411 #endif
412                 case IPPROTO_IGMP:
413                         igmp_print(cp, len);
414                         break;
415
416                 case 4:
417                         /* DVMRP multicast tunnel (ip-in-ip encapsulation) */
418                         ip_print(cp, len);
419                         if (! vflag) {
420                                 printf(" (ipip-proto-4)");
421                                 return;
422                         }
423                         break;
424
425 #ifdef INET6
426 #ifndef IP6PROTO_ENCAP
427 #define IP6PROTO_ENCAP 41
428 #endif
429                 case IP6PROTO_ENCAP:
430                         /* ip6-in-ip encapsulation */
431                         ip6_print(cp, len);
432                         break;
433 #endif /*INET6*/
434
435
436 #ifndef IPPROTO_GRE
437 #define IPPROTO_GRE 47
438 #endif
439                 case IPPROTO_GRE:
440                         /* do it */
441                         gre_print(cp, len);
442                         break;
443
444 #ifndef IPPROTO_MOBILE
445 #define IPPROTO_MOBILE 55
446 #endif
447                 case IPPROTO_MOBILE:
448                         mobile_print(cp, len);
449                         break;
450
451 #ifndef IPPROTO_PIM
452 #define IPPROTO_PIM     103
453 #endif
454                 case IPPROTO_PIM:
455                         pim_print(cp, len);
456                         break;
457
458 #ifndef IPPROTO_VRRP
459 #define IPPROTO_VRRP    112
460 #endif
461                 case IPPROTO_VRRP:
462                         vrrp_print(cp, len, ip->ip_ttl);
463                         break;
464
465                 default:
466                         (void)printf(" ip-proto-%d %d", nh, len);
467                         break;
468                 }
469         }
470
471         /* Ultra quiet now means that all this stuff should be suppressed */
472         /* res 3-Nov-98 */
473         if (qflag > 1) return;
474
475
476         /*
477          * for fragmented datagrams, print id:size@offset.  On all
478          * but the last stick a "+".  For unfragmented datagrams, note
479          * the don't fragment flag.
480          */
481         len = len0;     /* get the original length */
482         if (off & 0x3fff) {
483                 /*
484                  * if this isn't the first frag, we're missing the
485                  * next level protocol header.  print the ip addr.
486                  */
487                 if (off & 0x1fff)
488                         (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
489                                       ipaddr_string(&ip->ip_dst));
490 #ifndef IP_MF
491 #define IP_MF 0x2000
492 #endif /* IP_MF */
493 #ifndef IP_DF
494 #define IP_DF 0x4000
495 #endif /* IP_DF */
496                 (void)printf(" (frag %d:%u@%d%s)", ntohs(ip->ip_id), len,
497                         (off & 0x1fff) * 8,
498                         (off & IP_MF)? "+" : "");
499
500         } else if (off & IP_DF)
501                 (void)printf(" (DF)");
502
503         if (ip->ip_tos) {
504                 (void)printf(" [tos 0x%x", (int)ip->ip_tos);
505                 /* ECN bits */
506                 if (ip->ip_tos & 0x03) {
507                         switch (ip->ip_tos & 0x03) {
508                         case 1:
509                                 (void)printf(",ECT(1)");
510                                 break;
511                         case 2:
512                                 (void)printf(",ECT(0)");
513                                 break;
514                         case 3:
515                                 (void)printf(",CE");
516                         }
517                 }
518                 (void)printf("] ");
519         }
520
521         if (ip->ip_ttl <= 1)
522                 (void)printf(" [ttl %d]", (int)ip->ip_ttl);
523
524         if (vflag) {
525                 int sum;
526                 char *sep = "";
527
528                 printf(" (");
529                 if (ip->ip_ttl > 1) {
530                         (void)printf("%sttl %d", sep, (int)ip->ip_ttl);
531                         sep = ", ";
532                 }
533                 if ((off & 0x3fff) == 0) {
534                         (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
535                         sep = ", ";
536                 }
537                 (void)printf("%slen %d", sep, (int)ntohs(ip->ip_len));
538                 sep = ", ";
539                 if ((u_char *)ip + hlen <= snapend) {
540                         sum = in_cksum((const u_short *)ip, hlen, 0);
541                         if (sum != 0) {
542                                 (void)printf("%sbad cksum %x!", sep,
543                                              ntohs(ip->ip_sum));
544                                 sep = ", ";
545                         }
546                 }
547                 if ((hlen -= sizeof(struct ip)) > 0) {
548                         (void)printf("%soptlen=%d", sep, hlen);
549                         ip_optprint((u_char *)(ip + 1), hlen);
550                 }
551                 printf(")");
552         }
553 }
554
555 void
556 ipN_print(register const u_char *bp, register u_int length)
557 {
558         struct ip *ip, hdr;
559
560         ip = (struct ip *)bp;
561         if (length < 4) {
562                 (void)printf("truncated-ip %d", length);
563                 return;
564         }
565         memcpy (&hdr, (char *)ip, 4);
566         switch (IP_V(&hdr)) {
567         case 4:
568                 ip_print (bp, length);
569                 return;
570 #ifdef INET6
571         case 6:
572                 ip6_print (bp, length);
573                 return;
574 #endif
575         default:
576                 (void)printf("unknown ip %d", IP_V(&hdr));
577                 return;
578         }
579 }