]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-ip.c
This commit was generated by cvs2svn to compensate for changes in r55289,
[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
22 #ifndef lint
23 static const char rcsid[] =
24     "@(#) $Header: print-ip.c,v 1.66 97/05/28 12:51:43 leres Exp $ (LBL)";
25 #endif
26
27 #include <sys/param.h>
28 #include <sys/time.h>
29 #include <sys/socket.h>
30
31 #include <netinet/in.h>
32 #include <netinet/in_systm.h>
33 #include <netinet/ip.h>
34 #include <netinet/ip_var.h>
35 #include <netinet/udp.h>
36 #include <netinet/udp_var.h>
37 #include <netinet/tcp.h>
38 #include <netinet/tcpip.h>
39
40 #ifdef HAVE_MALLOC_H
41 #include <malloc.h>
42 #endif
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47
48 #include "addrtoname.h"
49 #include "interface.h"
50 #include "extract.h"                    /* must come after interface.h */
51
52 /* Compatibility */
53 #ifndef IPPROTO_ND
54 #define IPPROTO_ND      77
55 #endif
56
57 #ifndef IN_CLASSD
58 #define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000)
59 #endif
60
61 /* (following from ipmulti/mrouted/prune.h) */
62
63 /*
64  * The packet format for a traceroute request.
65  */
66 struct tr_query {
67         u_int  tr_src;                  /* traceroute source */
68         u_int  tr_dst;                  /* traceroute destination */
69         u_int  tr_raddr;                /* traceroute response address */
70 #ifdef WORDS_BIGENDIAN
71         struct {
72                 u_int   ttl : 8;        /* traceroute response ttl */
73                 u_int   qid : 24;       /* traceroute query id */
74         } q;
75 #else
76         struct {
77                 u_int   qid : 24;       /* traceroute query id */
78                 u_int   ttl : 8;        /* traceroute response ttl */
79         } q;
80 #endif
81 };
82
83 #define tr_rttl q.ttl
84 #define tr_qid  q.qid
85
86 /*
87  * Traceroute response format.  A traceroute response has a tr_query at the
88  * beginning, followed by one tr_resp for each hop taken.
89  */
90 struct tr_resp {
91         u_int tr_qarr;                  /* query arrival time */
92         u_int tr_inaddr;                /* incoming interface address */
93         u_int tr_outaddr;               /* outgoing interface address */
94         u_int tr_rmtaddr;               /* parent address in source tree */
95         u_int tr_vifin;                 /* input packet count on interface */
96         u_int tr_vifout;                /* output packet count on interface */
97         u_int tr_pktcnt;                /* total incoming packets for src-grp */
98         u_char  tr_rproto;              /* routing proto deployed on router */
99         u_char  tr_fttl;                /* ttl required to forward on outvif */
100         u_char  tr_smask;               /* subnet mask for src addr */
101         u_char  tr_rflags;              /* forwarding error codes */
102 };
103
104 /* defs within mtrace */
105 #define TR_QUERY 1
106 #define TR_RESP 2
107
108 /* fields for tr_rflags (forwarding error codes) */
109 #define TR_NO_ERR       0
110 #define TR_WRONG_IF     1
111 #define TR_PRUNED       2
112 #define TR_OPRUNED      3
113 #define TR_SCOPED       4
114 #define TR_NO_RTE       5
115 #define TR_NO_FWD       7
116 #define TR_NO_SPACE     0x81
117 #define TR_OLD_ROUTER   0x82
118
119 /* fields for tr_rproto (routing protocol) */
120 #define TR_PROTO_DVMRP  1
121 #define TR_PROTO_MOSPF  2
122 #define TR_PROTO_PIM    3
123 #define TR_PROTO_CBT    4
124
125 static void print_mtrace(register const u_char *bp, register u_int len)
126 {
127         register struct tr_query *tr = (struct tr_query *)(bp + 8);
128
129         printf("mtrace %d: %s to %s reply-to %s", tr->tr_qid,
130                 ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
131                 ipaddr_string(&tr->tr_raddr));
132         if (IN_CLASSD(ntohl(tr->tr_raddr)))
133                 printf(" with-ttl %d", tr->tr_rttl);
134 }
135
136 static void print_mresp(register const u_char *bp, register u_int len)
137 {
138         register struct tr_query *tr = (struct tr_query *)(bp + 8);
139
140         printf("mresp %d: %s to %s reply-to %s", tr->tr_qid,
141                 ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
142                 ipaddr_string(&tr->tr_raddr));
143         if (IN_CLASSD(ntohl(tr->tr_raddr)))
144                 printf(" with-ttl %d", tr->tr_rttl);
145 }
146
147 static void
148 igmp_print(register const u_char *bp, register u_int len,
149            register const u_char *bp2)
150 {
151         register const struct ip *ip;
152
153         ip = (const struct ip *)bp2;
154         (void)printf("%s > %s: ",
155                 ipaddr_string(&ip->ip_src),
156                 ipaddr_string(&ip->ip_dst));
157
158         TCHECK2(bp[0], 8);
159         switch (bp[0]) {
160         case 0x11:
161                 (void)printf("igmp %s query", bp[1] ? "v2" : "v1");
162                 if (bp[1] && bp[1] != 100)
163                         (void)printf(" [intvl %d]", bp[1]);
164                 if (*(int *)&bp[4])
165                         (void)printf(" [gaddr %s]", ipaddr_string(&bp[4]));
166                 if (len != 8)
167                         (void)printf(" [len %d]", len);
168                 break;
169         case 0x12:
170         case 0x16:
171                 (void)printf("igmp %s report %s",
172                              (bp[0] & 0x0f) == 6 ? "v2" : "v1",
173                              ipaddr_string(&bp[4]));
174                 if (len != 8)
175                         (void)printf(" [len %d]", len);
176                 if (bp[1])
177                         (void)printf(" [b1=0x%x]", bp[1]);
178                 break;
179         case 0x17:
180                 (void)printf("igmp leave %s", ipaddr_string(&bp[4]));
181                 if (len != 8)
182                         (void)printf(" [len %d]", len);
183                 if (bp[1])
184                         (void)printf(" [b1=0x%x]", bp[1]);
185                 break;
186         case 0x13:
187                 (void)printf("igmp dvmrp");
188                 if (len < 8)
189                         (void)printf(" [len %d]", len);
190                 else
191                         dvmrp_print(bp, len);
192                 break;
193         case 0x14:
194                 (void)printf("igmp pim");
195                 pim_print(bp, len);
196                 break;
197         case 0x1e:
198                 print_mresp(bp, len);
199                 break;
200         case 0x1f:
201                 print_mtrace(bp, len);
202                 break;
203         default:
204                 (void)printf("igmp-%d", bp[0] & 0xf);
205                 if (bp[1])
206                         (void)printf(" [b1=0x%02x]", bp[1]);
207                 break;
208         }
209
210         TCHECK2(bp[0], len);
211         if (vflag) {
212                 /* Check the IGMP checksum */
213                 u_int32_t sum = 0;
214                 int count;
215                 const u_short *sp = (u_short *)bp;
216                 
217                 for (count = len / 2; --count >= 0; )
218                         sum += *sp++;
219                 if (len & 1)
220                         sum += ntohs(*(u_char *) sp << 8);
221                 while (sum >> 16)
222                         sum = (sum & 0xffff) + (sum >> 16);
223                 sum = 0xffff & ~sum;
224                 if (sum != 0)
225                         printf(" bad igmp cksum %x!", EXTRACT_16BITS(&bp[2]));
226         }
227         return;
228 trunc:
229         fputs("[|igmp]", stdout);
230 }
231
232 /*
233  * print the recorded route in an IP RR, LSRR or SSRR option.
234  */
235 static void
236 ip_printroute(const char *type, register const u_char *cp, u_int length)
237 {
238         register u_int ptr = cp[2] - 1;
239         register u_int len;
240
241         printf(" %s{", type);
242         if ((length + 1) & 3)
243                 printf(" [bad length %d]", length);
244         if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
245                 printf(" [bad ptr %d]", cp[2]);
246
247         type = "";
248         for (len = 3; len < length; len += 4) {
249                 if (ptr == len)
250                         type = "#";
251                 printf("%s%s", type, ipaddr_string(&cp[len]));
252                 type = " ";
253         }
254         printf("%s}", ptr == len? "#" : "");
255 }
256
257 /*
258  * print IP options.
259  */
260 static void
261 ip_optprint(register const u_char *cp, u_int length)
262 {
263         register u_int len;
264
265         for (; length > 0; cp += len, length -= len) {
266                 int tt = *cp;
267
268                 len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1];
269                 if (len <= 0) {
270                         printf("[|ip op len %d]", len);
271                         return;
272                 }
273                 if (&cp[1] >= snapend || cp + len > snapend) {
274                         printf("[|ip]");
275                         return;
276                 }
277                 switch (tt) {
278
279                 case IPOPT_EOL:
280                         printf(" EOL");
281                         if (length > 1)
282                                 printf("-%d", length - 1);
283                         return;
284
285                 case IPOPT_NOP:
286                         printf(" NOP");
287                         break;
288
289                 case IPOPT_TS:
290                         printf(" TS{%d}", len);
291                         break;
292
293                 case IPOPT_SECURITY:
294                         printf(" SECURITY{%d}", len);
295                         break;
296
297                 case IPOPT_RR:
298                         printf(" RR{%d}=", len);
299                         ip_printroute("RR", cp, len);
300                         break;
301
302                 case IPOPT_SSRR:
303                         ip_printroute("SSRR", cp, len);
304                         break;
305
306                 case IPOPT_LSRR:
307                         ip_printroute("LSRR", cp, len);
308                         break;
309
310                 case IPOPT_RA:
311                         printf(" RA{%d}", len);
312                         if (cp[2] != 0 || cp[3] != 0)
313                                 printf(" [b23=0x04%x]", cp[2] << 8 | cp[3]);
314                         break;
315
316                 default:
317                         printf(" IPOPT-%d{%d}", cp[0], len);
318                         break;
319                 }
320         }
321 }
322
323 /*
324  * compute an IP header checksum.
325  * don't modifiy the packet.
326  */
327 static int
328 in_cksum(const struct ip *ip)
329 {
330         register const u_short *sp = (u_short *)ip;
331         register u_int32_t sum = 0;
332         register int count;
333
334         /*
335          * No need for endian conversions.
336          */
337         for (count = ip->ip_hl * 2; --count >= 0; )
338                 sum += *sp++;
339         while (sum > 0xffff)
340                 sum = (sum & 0xffff) + (sum >> 16);
341         sum = ~sum & 0xffff;
342
343         return (sum);
344 }
345
346 /*
347  * print an IP datagram.
348  */
349 void
350 ip_print(register const u_char *bp, register u_int length)
351 {
352         register const struct ip *ip;
353         register u_int hlen, len, off;
354         register const u_char *cp;
355
356         ip = (const struct ip *)bp;
357 #ifdef LBL_ALIGN
358         /*
359          * If the IP header is not aligned, copy into abuf.
360          * This will never happen with BPF.  It does happen raw packet
361          * dumps from -r.
362          */
363         if ((long)ip & 3) {
364                 static u_char *abuf = NULL;
365                 static int didwarn = 0;
366
367                 if (abuf == NULL) {
368                         abuf = (u_char *)malloc(snaplen);
369                         if (abuf == NULL)
370                                 error("ip_print: malloc");
371                 }
372                 memcpy((char *)abuf, (char *)ip, min(length, snaplen));
373                 snapend += abuf - (u_char *)ip;
374                 packetp = abuf;
375                 ip = (struct ip *)abuf;
376                 /* We really want libpcap to give us aligned packets */
377                 if (!didwarn) {
378                         warning("compensating for unaligned libpcap packets");
379                         ++didwarn;
380                 }
381         }
382 #endif
383         if ((u_char *)(ip + 1) > snapend) {
384                 printf("[|ip]");
385                 return;
386         }
387         if (length < sizeof (struct ip)) {
388                 (void)printf("truncated-ip %d", length);
389                 return;
390         }
391         hlen = ip->ip_hl * 4;
392
393         len = ntohs(ip->ip_len);
394         if (length < len)
395                 (void)printf("truncated-ip - %d bytes missing!",
396                         len - length);
397         len -= hlen;
398
399         /*
400          * If this is fragment zero, hand it to the next higher
401          * level protocol.
402          */
403         off = ntohs(ip->ip_off);
404         if ((off & 0x1fff) == 0) {
405                 cp = (const u_char *)ip + hlen;
406                 switch (ip->ip_p) {
407
408                 case IPPROTO_TCP:
409                         tcp_print(cp, len, (const u_char *)ip);
410                         break;
411
412                 case IPPROTO_UDP:
413                         udp_print(cp, len, (const u_char *)ip);
414                         break;
415
416                 case IPPROTO_ICMP:
417                         icmp_print(cp, (const u_char *)ip);
418                         break;
419
420 #ifndef IPPROTO_IGRP
421 #define IPPROTO_IGRP 9
422 #endif
423                 case IPPROTO_IGRP:
424                         igrp_print(cp, len, (const u_char *)ip);
425                         break;
426
427                 case IPPROTO_ND:
428                         (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
429                                 ipaddr_string(&ip->ip_dst));
430                         (void)printf(" nd %d", len);
431                         break;
432
433                 case IPPROTO_EGP:
434                         egp_print(cp, len, (const u_char *)ip);
435                         break;
436
437 #ifndef IPPROTO_OSPF
438 #define IPPROTO_OSPF 89
439 #endif
440                 case IPPROTO_OSPF:
441                         ospf_print(cp, len, (const u_char *)ip);
442                         break;
443
444 #ifndef IPPROTO_IGMP
445 #define IPPROTO_IGMP 2
446 #endif
447                 case IPPROTO_IGMP:
448                         igmp_print(cp, len, (const u_char *)ip);
449                         break;
450
451                 case 4:
452                         /* DVMRP multicast tunnel (ip-in-ip encapsulation) */
453                         if (vflag)
454                                 (void)printf("%s > %s: ",
455                                              ipaddr_string(&ip->ip_src),
456                                              ipaddr_string(&ip->ip_dst));
457                         ip_print(cp, len);
458                         if (! vflag) {
459                                 printf(" (ipip)");
460                                 return;
461                         }
462                         break;
463
464 #ifndef IPPROTO_GRE
465 #define IPPROTO_GRE 47
466 #endif
467                 case IPPROTO_GRE:
468                         if (vflag)
469                                 (void)printf("gre %s > %s: ",
470                                              ipaddr_string(&ip->ip_src),
471                                              ipaddr_string(&ip->ip_dst));
472                         /* do it */
473                         gre_print(cp, len);
474                         if (! vflag) {
475                                 printf(" (gre encap)");
476                                 return;
477                         }
478                         break;
479
480                 default:
481                         (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
482                                 ipaddr_string(&ip->ip_dst));
483                         (void)printf(" ip-proto-%d %d", ip->ip_p, len);
484                         break;
485                 }
486         }
487         /*
488          * for fragmented datagrams, print id:size@offset.  On all
489          * but the last stick a "+".  For unfragmented datagrams, note
490          * the don't fragment flag.
491          */
492         if (off & 0x3fff) {
493                 /*
494                  * if this isn't the first frag, we're missing the
495                  * next level protocol header.  print the ip addr.
496                  */
497                 if (off & 0x1fff)
498                         (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
499                                       ipaddr_string(&ip->ip_dst));
500                 (void)printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), len,
501                         (off & 0x1fff) * 8,
502                         (off & IP_MF)? "+" : "");
503         } else if (off & IP_DF)
504                 (void)printf(" (DF)");
505
506         if (ip->ip_tos)
507                 (void)printf(" [tos 0x%x]", (int)ip->ip_tos);
508         if (ip->ip_ttl <= 1)
509                 (void)printf(" [ttl %d]", (int)ip->ip_ttl);
510
511         if (vflag) {
512                 int sum;
513                 char *sep = "";
514
515                 printf(" (");
516                 if (ip->ip_ttl > 1) {
517                         (void)printf("%sttl %d", sep, (int)ip->ip_ttl);
518                         sep = ", ";
519                 }
520                 if ((off & 0x3fff) == 0) {
521                         (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
522                         sep = ", ";
523                 }
524                 if ((u_char *)ip + hlen <= snapend) {
525                         sum = in_cksum(ip);
526                         if (sum != 0) {
527                                 (void)printf("%sbad cksum %x!", sep,
528                                              ntohs(ip->ip_sum));
529                                 sep = ", ";
530                         }
531                 }
532                 if ((hlen -= sizeof(struct ip)) > 0) {
533                         (void)printf("%soptlen=%d", sep, hlen);
534                         ip_optprint((u_char *)(ip + 1), hlen);
535                 }
536                 printf(")");
537         }
538 }