source: rtems-libbsd/freebsd/contrib/tcpdump/print-ip.c @ 8440506

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 8440506 was 8440506, checked in by Chris Johns <chrisj@…>, on 06/15/15 at 07:42:23

Add tcpdump and libpcap.

  • Update the file builder generator to handle generator specific cflags and includes. The tcpdump and libpcap have localised headers and need specific headers paths to see them. There are also module specific flags and these need to be passed to the lex and yacc generators.
  • Add the tcpdump support.
  • Property mode set to 100644
File size: 16.3 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
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 * $FreeBSD$
24 */
25
26#ifndef lint
27static const char rcsid[] _U_ =
28    "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.159 2007-09-14 01:29:28 guy Exp $ (LBL)";
29#endif
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
35#include <tcpdump-stdinc.h>
36
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40
41#include "addrtoname.h"
42#include "interface.h"
43#include "extract.h"                    /* must come after interface.h */
44
45#include "ip.h"
46#include "ipproto.h"
47
48struct tok ip_option_values[] = {
49    { IPOPT_EOL, "EOL" },
50    { IPOPT_NOP, "NOP" },
51    { IPOPT_TS, "timestamp" },
52    { IPOPT_SECURITY, "security" },
53    { IPOPT_RR, "RR" },
54    { IPOPT_SSRR, "SSRR" },
55    { IPOPT_LSRR, "LSRR" },
56    { IPOPT_RA, "RA" },
57    { IPOPT_RFC1393, "traceroute" },
58    { 0, NULL }
59};
60
61/*
62 * print the recorded route in an IP RR, LSRR or SSRR option.
63 */
64static void
65ip_printroute(register const u_char *cp, u_int length)
66{
67        register u_int ptr;
68        register u_int len;
69
70        if (length < 3) {
71                printf(" [bad length %u]", length);
72                return;
73        }
74        if ((length + 1) & 3)
75                printf(" [bad length %u]", length);
76        ptr = cp[2] - 1;
77        if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
78                printf(" [bad ptr %u]", cp[2]);
79
80        for (len = 3; len < length; len += 4) {
81                printf(" %s", ipaddr_string(&cp[len]));
82                if (ptr > len)
83                        printf(",");
84        }
85}
86
87/*
88 * If source-routing is present and valid, return the final destination.
89 * Otherwise, return IP destination.
90 *
91 * This is used for UDP and TCP pseudo-header in the checksum
92 * calculation.
93 */
94static u_int32_t
95ip_finddst(const struct ip *ip)
96{
97        int length;
98        int len;
99        const u_char *cp;
100        u_int32_t retval;
101
102        cp = (const u_char *)(ip + 1);
103        length = (IP_HL(ip) << 2) - sizeof(struct ip);
104
105        for (; length > 0; cp += len, length -= len) {
106                int tt;
107
108                TCHECK(*cp);
109                tt = *cp;
110                if (tt == IPOPT_EOL)
111                        break;
112                else if (tt == IPOPT_NOP)
113                        len = 1;
114                else {
115                        TCHECK(cp[1]);
116                        len = cp[1];
117                        if (len < 2)
118                                break;
119                }
120                TCHECK2(*cp, len);
121                switch (tt) {
122
123                case IPOPT_SSRR:
124                case IPOPT_LSRR:
125                        if (len < 7)
126                                break;
127                        memcpy(&retval, cp + len - 4, 4);
128                        return retval;
129                }
130        }
131trunc:
132        memcpy(&retval, &ip->ip_dst.s_addr, sizeof(u_int32_t));
133        return retval;
134}
135
136/*
137 * Compute a V4-style checksum by building a pseudoheader.
138 */
139int
140nextproto4_cksum(const struct ip *ip, const u_int8_t *data,
141                 u_int len, u_int next_proto)
142{
143        struct phdr {
144                u_int32_t src;
145                u_int32_t dst;
146                u_char mbz;
147                u_char proto;
148                u_int16_t len;
149        } ph;
150        struct cksum_vec vec[2];
151
152        /* pseudo-header.. */
153        ph.len = htons((u_int16_t)len);
154        ph.mbz = 0;
155        ph.proto = next_proto;
156        memcpy(&ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
157        if (IP_HL(ip) == 5)
158                memcpy(&ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));
159        else
160                ph.dst = ip_finddst(ip);
161
162        vec[0].ptr = (const u_int8_t *)(void *)&ph;
163        vec[0].len = sizeof(ph);
164        vec[1].ptr = data;
165        vec[1].len = len;
166        return (in_cksum(vec, 2));
167}
168
169static void
170ip_printts(register const u_char *cp, u_int length)
171{
172        register u_int ptr;
173        register u_int len;
174        int hoplen;
175        const char *type;
176
177        if (length < 4) {
178                printf("[bad length %u]", length);
179                return;
180        }
181        printf(" TS{");
182        hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
183        if ((length - 4) & (hoplen-1))
184                printf("[bad length %u]", length);
185        ptr = cp[2] - 1;
186        len = 0;
187        if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
188                printf("[bad ptr %u]", cp[2]);
189        switch (cp[3]&0xF) {
190        case IPOPT_TS_TSONLY:
191                printf("TSONLY");
192                break;
193        case IPOPT_TS_TSANDADDR:
194                printf("TS+ADDR");
195                break;
196        /*
197         * prespecified should really be 3, but some ones might send 2
198         * instead, and the IPOPT_TS_PRESPEC constant can apparently
199         * have both values, so we have to hard-code it here.
200         */
201
202        case 2:
203                printf("PRESPEC2.0");
204                break;
205        case 3:                 /* IPOPT_TS_PRESPEC */
206                printf("PRESPEC");
207                break;
208        default:
209                printf("[bad ts type %d]", cp[3]&0xF);
210                goto done;
211        }
212
213        type = " ";
214        for (len = 4; len < length; len += hoplen) {
215                if (ptr == len)
216                        type = " ^ ";
217                printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
218                       hoplen!=8 ? "" : ipaddr_string(&cp[len]));
219                type = " ";
220        }
221
222done:
223        printf("%s", ptr == len ? " ^ " : "");
224
225        if (cp[3]>>4)
226                printf(" [%d hops not recorded]} ", cp[3]>>4);
227        else
228                printf("}");
229}
230
231/*
232 * print IP options.
233 */
234static void
235ip_optprint(register const u_char *cp, u_int length)
236{
237        register u_int option_len;
238        const char *sep = "";
239
240        for (; length > 0; cp += option_len, length -= option_len) {
241                u_int option_code;
242
243                printf("%s", sep);
244                sep = ",";
245
246                TCHECK(*cp);
247                option_code = *cp;
248
249                printf("%s",
250                        tok2str(ip_option_values,"unknown %u",option_code));
251
252                if (option_code == IPOPT_NOP ||
253                    option_code == IPOPT_EOL)
254                        option_len = 1;
255
256                else {
257                        TCHECK(cp[1]);
258                        option_len = cp[1];
259                        if (option_len < 2) {
260                                printf(" [bad length %u]", option_len);
261                                return;
262                        }
263                }
264
265                if (option_len > length) {
266                        printf(" [bad length %u]", option_len);
267                        return;
268                }
269
270                TCHECK2(*cp, option_len);
271
272                switch (option_code) {
273                case IPOPT_EOL:
274                        return;
275
276                case IPOPT_TS:
277                        ip_printts(cp, option_len);
278                        break;
279
280                case IPOPT_RR:       /* fall through */
281                case IPOPT_SSRR:
282                case IPOPT_LSRR:
283                        ip_printroute(cp, option_len);
284                        break;
285
286                case IPOPT_RA:
287                        if (option_len < 4) {
288                                printf(" [bad length %u]", option_len);
289                                break;
290                        }
291                        TCHECK(cp[3]);
292                        if (EXTRACT_16BITS(&cp[2]) != 0)
293                            printf(" value %u", EXTRACT_16BITS(&cp[2]));
294                        break;
295
296                case IPOPT_NOP:       /* nothing to print - fall through */
297                case IPOPT_SECURITY:
298                default:
299                        break;
300                }
301        }
302        return;
303
304trunc:
305        printf("[|ip]");
306}
307
308#define IP_RES 0x8000
309
310static struct tok ip_frag_values[] = {
311        { IP_MF,        "+" },
312        { IP_DF,        "DF" },
313        { IP_RES,       "rsvd" }, /* The RFC3514 evil ;-) bit */
314        { 0,            NULL }
315};
316
317struct ip_print_demux_state {
318        const struct ip *ip;
319        const u_char *cp;
320        u_int   len, off;
321        u_char  nh;
322        int     advance;
323};
324
325static void
326ip_print_demux(netdissect_options *ndo,
327               struct ip_print_demux_state *ipds)
328{
329        struct protoent *proto;
330        struct cksum_vec vec[1];
331
332again:
333        switch (ipds->nh) {
334
335        case IPPROTO_AH:
336                ipds->nh = *ipds->cp;
337                ipds->advance = ah_print(ipds->cp);
338                if (ipds->advance <= 0)
339                        break;
340                ipds->cp += ipds->advance;
341                ipds->len -= ipds->advance;
342                goto again;
343
344        case IPPROTO_ESP:
345        {
346                int enh, padlen;
347                ipds->advance = esp_print(ndo, ipds->cp, ipds->len,
348                                    (const u_char *)ipds->ip,
349                                    &enh, &padlen);
350                if (ipds->advance <= 0)
351                        break;
352                ipds->cp += ipds->advance;
353                ipds->len -= ipds->advance + padlen;
354                ipds->nh = enh & 0xff;
355                goto again;
356        }
357
358        case IPPROTO_IPCOMP:
359        {
360                int enh;
361                ipds->advance = ipcomp_print(ipds->cp, &enh);
362                if (ipds->advance <= 0)
363                        break;
364                ipds->cp += ipds->advance;
365                ipds->len -= ipds->advance;
366                ipds->nh = enh & 0xff;
367                goto again;
368        }
369
370        case IPPROTO_SCTP:
371                sctp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len);
372                break;
373
374        case IPPROTO_DCCP:
375                dccp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len);
376                break;
377
378        case IPPROTO_TCP:
379                /* pass on the MF bit plus the offset to detect fragments */
380                tcp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
381                          ipds->off & (IP_MF|IP_OFFMASK));
382                break;
383
384        case IPPROTO_UDP:
385                /* pass on the MF bit plus the offset to detect fragments */
386                udp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
387                          ipds->off & (IP_MF|IP_OFFMASK));
388                break;
389
390        case IPPROTO_ICMP:
391                /* pass on the MF bit plus the offset to detect fragments */
392                icmp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
393                           ipds->off & (IP_MF|IP_OFFMASK));
394                break;
395
396        case IPPROTO_PIGP:
397                /*
398                 * XXX - the current IANA protocol number assignments
399                 * page lists 9 as "any private interior gateway
400                 * (used by Cisco for their IGRP)" and 88 as
401                 * "EIGRP" from Cisco.
402                 *
403                 * Recent BSD <netinet/in.h> headers define
404                 * IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88.
405                 * We define IP_PROTO_PIGP as 9 and
406                 * IP_PROTO_EIGRP as 88; those names better
407                 * match was the current protocol number
408                 * assignments say.
409                 */
410                igrp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
411                break;
412
413        case IPPROTO_EIGRP:
414                eigrp_print(ipds->cp, ipds->len);
415                break;
416
417        case IPPROTO_ND:
418                ND_PRINT((ndo, " nd %d", ipds->len));
419                break;
420
421        case IPPROTO_EGP:
422                egp_print(ipds->cp, ipds->len);
423                break;
424
425        case IPPROTO_OSPF:
426                ospf_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
427                break;
428
429        case IPPROTO_IGMP:
430                igmp_print(ipds->cp, ipds->len);
431                break;
432
433        case IPPROTO_IPV4:
434                /* DVMRP multicast tunnel (ip-in-ip encapsulation) */
435                ip_print(ndo, ipds->cp, ipds->len);
436                if (! vflag) {
437                        ND_PRINT((ndo, " (ipip-proto-4)"));
438                        return;
439                }
440                break;
441
442#ifdef INET6
443        case IPPROTO_IPV6:
444                /* ip6-in-ip encapsulation */
445                ip6_print(ndo, ipds->cp, ipds->len);
446                break;
447#endif /*INET6*/
448
449        case IPPROTO_RSVP:
450                rsvp_print(ipds->cp, ipds->len);
451                break;
452
453        case IPPROTO_GRE:
454                /* do it */
455                gre_print(ipds->cp, ipds->len);
456                break;
457
458        case IPPROTO_MOBILE:
459                mobile_print(ipds->cp, ipds->len);
460                break;
461
462        case IPPROTO_PIM:
463                vec[0].ptr = ipds->cp;
464                vec[0].len = ipds->len;
465                pim_print(ipds->cp, ipds->len, in_cksum(vec, 1));
466                break;
467
468        case IPPROTO_VRRP:
469                if (packettype == PT_CARP) {
470                        if (vflag)
471                                (void)printf("carp %s > %s: ",
472                                             ipaddr_string(&ipds->ip->ip_src),
473                                             ipaddr_string(&ipds->ip->ip_dst));
474                        carp_print(ipds->cp, ipds->len, ipds->ip->ip_ttl);
475                } else {
476                        if (vflag)
477                                (void)printf("vrrp %s > %s: ",
478                                             ipaddr_string(&ipds->ip->ip_src),
479                                             ipaddr_string(&ipds->ip->ip_dst));
480                        vrrp_print(ipds->cp, ipds->len, ipds->ip->ip_ttl);
481                }
482                break;
483
484        case IPPROTO_PGM:
485                pgm_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
486                break;
487
488        case IPPROTO_PFSYNC:
489                pfsync_ip_print(ipds->cp, ipds->len);
490                break;
491
492        default:
493                if (ndo->ndo_nflag==0 && (proto = getprotobynumber(ipds->nh)) != NULL)
494                        ND_PRINT((ndo, " %s", proto->p_name));
495                else
496                        ND_PRINT((ndo, " ip-proto-%d", ipds->nh));
497                ND_PRINT((ndo, " %d", ipds->len));
498                break;
499        }
500}
501
502void
503ip_print_inner(netdissect_options *ndo,
504               const u_char *bp,
505               u_int length, u_int nh,
506               const u_char *bp2)
507{
508        struct ip_print_demux_state  ipd;
509
510        ipd.ip = (const struct ip *)bp2;
511        ipd.cp = bp;
512        ipd.len  = length;
513        ipd.off  = 0;
514        ipd.nh   = nh;
515        ipd.advance = 0;
516
517        ip_print_demux(ndo, &ipd);
518}
519
520
521/*
522 * print an IP datagram.
523 */
524void
525ip_print(netdissect_options *ndo,
526         const u_char *bp,
527         u_int length)
528{
529        struct ip_print_demux_state  ipd;
530        struct ip_print_demux_state *ipds=&ipd;
531        const u_char *ipend;
532        u_int hlen;
533        struct cksum_vec vec[1];
534        u_int16_t sum, ip_sum;
535        struct protoent *proto;
536
537        ipds->ip = (const struct ip *)bp;
538        if (IP_V(ipds->ip) != 4) { /* print version if != 4 */
539            printf("IP%u ", IP_V(ipds->ip));
540            if (IP_V(ipds->ip) == 6)
541                printf(", wrong link-layer encapsulation");
542        }
543        else if (!eflag)
544            printf("IP ");
545
546        if ((u_char *)(ipds->ip + 1) > ndo->ndo_snapend) {
547                printf("[|ip]");
548                return;
549        }
550        if (length < sizeof (struct ip)) {
551                (void)printf("truncated-ip %u", length);
552                return;
553        }
554        hlen = IP_HL(ipds->ip) * 4;
555        if (hlen < sizeof (struct ip)) {
556                (void)printf("bad-hlen %u", hlen);
557                return;
558        }
559
560        ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len);
561        if (length < ipds->len)
562                (void)printf("truncated-ip - %u bytes missing! ",
563                        ipds->len - length);
564        if (ipds->len < hlen) {
565#ifdef GUESS_TSO
566            if (ipds->len) {
567                (void)printf("bad-len %u", ipds->len);
568                return;
569            }
570            else {
571                /* we guess that it is a TSO send */
572                ipds->len = length;
573            }
574#else
575            (void)printf("bad-len %u", ipds->len);
576            return;
577#endif /* GUESS_TSO */
578        }
579
580        /*
581         * Cut off the snapshot length to the end of the IP payload.
582         */
583        ipend = bp + ipds->len;
584        if (ipend < ndo->ndo_snapend)
585                ndo->ndo_snapend = ipend;
586
587        ipds->len -= hlen;
588
589        ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off);
590
591        if (vflag) {
592            (void)printf("(tos 0x%x", (int)ipds->ip->ip_tos);
593            /* ECN bits */
594            if (ipds->ip->ip_tos & 0x03) {
595                switch (ipds->ip->ip_tos & 0x03) {
596                case 1:
597                    (void)printf(",ECT(1)");
598                    break;
599                case 2:
600                    (void)printf(",ECT(0)");
601                    break;
602                case 3:
603                    (void)printf(",CE");
604                }
605            }
606
607            if (ipds->ip->ip_ttl >= 1)
608                (void)printf(", ttl %u", ipds->ip->ip_ttl);
609
610            /*
611             * for the firewall guys, print id, offset.
612             * On all but the last stick a "+" in the flags portion.
613             * For unfragmented datagrams, note the don't fragment flag.
614             */
615
616            (void)printf(", id %u, offset %u, flags [%s], proto %s (%u)",
617                         EXTRACT_16BITS(&ipds->ip->ip_id),
618                         (ipds->off & 0x1fff) * 8,
619                         bittok2str(ip_frag_values, "none", ipds->off&0xe000),
620                         tok2str(ipproto_values,"unknown",ipds->ip->ip_p),
621                         ipds->ip->ip_p);
622
623            (void)printf(", length %u", EXTRACT_16BITS(&ipds->ip->ip_len));
624
625            if ((hlen - sizeof(struct ip)) > 0) {
626                printf(", options (");
627                ip_optprint((u_char *)(ipds->ip + 1), hlen - sizeof(struct ip));
628                printf(")");
629            }
630
631            if (!Kflag && (u_char *)ipds->ip + hlen <= ndo->ndo_snapend) {
632                vec[0].ptr = (const u_int8_t *)(void *)ipds->ip;
633                vec[0].len = hlen;
634                sum = in_cksum(vec, 1);
635                if (sum != 0) {
636                    ip_sum = EXTRACT_16BITS(&ipds->ip->ip_sum);
637                    (void)printf(", bad cksum %x (->%x)!", ip_sum,
638                             in_cksum_shouldbe(ip_sum, sum));
639                }
640            }
641
642            printf(")\n    ");
643        }
644
645        /*
646         * If this is fragment zero, hand it to the next higher
647         * level protocol.
648         */
649        if ((ipds->off & 0x1fff) == 0) {
650                ipds->cp = (const u_char *)ipds->ip + hlen;
651                ipds->nh = ipds->ip->ip_p;
652
653                if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP &&
654                    ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) {
655                        (void)printf("%s > %s: ",
656                                     ipaddr_string(&ipds->ip->ip_src),
657                                     ipaddr_string(&ipds->ip->ip_dst));
658                }
659                ip_print_demux(ndo, ipds);
660        } else {
661            /* Ultra quiet now means that all this stuff should be suppressed */
662            if (qflag > 1) return;
663
664            /*
665             * if this isn't the first frag, we're missing the
666             * next level protocol header.  print the ip addr
667             * and the protocol.
668             */
669            if (ipds->off & 0x1fff) {
670                (void)printf("%s > %s:", ipaddr_string(&ipds->ip->ip_src),
671                             ipaddr_string(&ipds->ip->ip_dst));
672                if (!ndo->ndo_nflag && (proto = getprotobynumber(ipds->ip->ip_p)) != NULL)
673                    (void)printf(" %s", proto->p_name);
674                else
675                    (void)printf(" ip-proto-%d", ipds->ip->ip_p);
676            }
677        }
678}
679
680void
681ipN_print(register const u_char *bp, register u_int length)
682{
683        struct ip *ip, hdr;
684
685        ip = (struct ip *)bp;
686        if (length < 4) {
687                (void)printf("truncated-ip %d", length);
688                return;
689        }
690        memcpy (&hdr, (char *)ip, 4);
691        switch (IP_V(&hdr)) {
692        case 4:
693                ip_print (gndo, bp, length);
694                return;
695#ifdef INET6
696        case 6:
697                ip6_print (gndo, bp, length);
698                return;
699#endif
700        default:
701                (void)printf("unknown ip %d", IP_V(&hdr));
702                return;
703        }
704}
705
706/*
707 * Local Variables:
708 * c-style: whitesmith
709 * c-basic-offset: 8
710 * End:
711 */
712
713
Note: See TracBrowser for help on using the repository browser.