xref: /freebsd/contrib/tcpdump/print-ip-demux.c (revision ba3c1f5972d7b90feb6e6da47905ff2757e0fe57)
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 /* \summary: IPv4/IPv6 payload printer */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include "netdissect-stdinc.h"
29 
30 #include "netdissect.h"
31 #include "addrtoname.h"
32 #include "extract.h"
33 
34 #include "ip.h"
35 #include "ipproto.h"
36 
37 void
38 ip_demux_print(netdissect_options *ndo,
39 	       const u_char *bp,
40 	       u_int length, u_int ver, int fragmented, u_int ttl_hl,
41 	       uint8_t nh, const u_char *iph)
42 {
43 	int advance;
44 	const char *p_name;
45 
46 	advance = 0;
47 
48 again:
49 	switch (nh) {
50 
51 	case IPPROTO_AH:
52 		if (!ND_TTEST_1(bp)) {
53 			ndo->ndo_protocol = "ah";
54 			nd_print_trunc(ndo);
55 			break;
56 		}
57 		nh = GET_U_1(bp);
58 		advance = ah_print(ndo, bp);
59 		if (advance <= 0)
60 			break;
61 		bp += advance;
62 		length -= advance;
63 		goto again;
64 
65 	case IPPROTO_ESP:
66 	{
67 		esp_print(ndo, bp, length, iph, ver, fragmented, ttl_hl);
68 		/*
69 		 * Either this has decrypted the payload and
70 		 * printed it, in which case there's nothing more
71 		 * to do, or it hasn't, in which case there's
72 		 * nothing more to do.
73 		 */
74 		break;
75 	}
76 
77 	case IPPROTO_IPCOMP:
78 	{
79 		ipcomp_print(ndo, bp);
80 		/*
81 		 * Either this has decompressed the payload and
82 		 * printed it, in which case there's nothing more
83 		 * to do, or it hasn't, in which case there's
84 		 * nothing more to do.
85 		 */
86 		break;
87 	}
88 
89 	case IPPROTO_SCTP:
90 		sctp_print(ndo, bp, iph, length);
91 		break;
92 
93 	case IPPROTO_DCCP:
94 		dccp_print(ndo, bp, iph, length);
95 		break;
96 
97 	case IPPROTO_TCP:
98 		tcp_print(ndo, bp, length, iph, fragmented);
99 		break;
100 
101 	case IPPROTO_UDP:
102 		udp_print(ndo, bp, length, iph, fragmented, ttl_hl);
103 		break;
104 
105 	case IPPROTO_ICMP:
106 		if (ver == 4)
107 			icmp_print(ndo, bp, length, iph, fragmented);
108 		else {
109 			ND_PRINT("[%s requires IPv4]",
110 				 tok2str(ipproto_values,"unknown",nh));
111 			nd_print_invalid(ndo);
112 		}
113 		break;
114 
115 	case IPPROTO_ICMPV6:
116 		if (ver == 6)
117 			icmp6_print(ndo, bp, length, iph, fragmented);
118 		else {
119 			ND_PRINT("[%s requires IPv6]",
120 				 tok2str(ipproto_values,"unknown",nh));
121 			nd_print_invalid(ndo);
122 		}
123 		break;
124 
125 	case IPPROTO_PIGP:
126 		/*
127 		 * XXX - the current IANA protocol number assignments
128 		 * page lists 9 as "any private interior gateway
129 		 * (used by Cisco for their IGRP)" and 88 as
130 		 * "EIGRP" from Cisco.
131 		 *
132 		 * Recent BSD <netinet/in.h> headers define
133 		 * IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88.
134 		 * We define IP_PROTO_PIGP as 9 and
135 		 * IP_PROTO_EIGRP as 88; those names better
136 		 * match was the current protocol number
137 		 * assignments say.
138 		 */
139 		igrp_print(ndo, bp, length);
140 		break;
141 
142 	case IPPROTO_EIGRP:
143 		eigrp_print(ndo, bp, length);
144 		break;
145 
146 	case IPPROTO_ND:
147 		ND_PRINT(" nd %u", length);
148 		break;
149 
150 	case IPPROTO_EGP:
151 		egp_print(ndo, bp, length);
152 		break;
153 
154 	case IPPROTO_OSPF:
155 		if (ver == 6)
156 			ospf6_print(ndo, bp, length);
157 		else
158 			ospf_print(ndo, bp, length, iph);
159 		break;
160 
161 	case IPPROTO_IGMP:
162 		if (ver == 4)
163 			igmp_print(ndo, bp, length);
164 		else {
165 			ND_PRINT("[%s requires IPv4]",
166 				 tok2str(ipproto_values,"unknown",nh));
167 			nd_print_invalid(ndo);
168 		}
169 		break;
170 
171 	case IPPROTO_IPV4:
172 		/* ipv4-in-ip encapsulation */
173 		ip_print(ndo, bp, length);
174 		break;
175 
176 	case IPPROTO_IPV6:
177 		/* ip6-in-ip encapsulation */
178 		ip6_print(ndo, bp, length);
179 		break;
180 
181 	case IPPROTO_RSVP:
182 		rsvp_print(ndo, bp, length);
183 		break;
184 
185 	case IPPROTO_GRE:
186 		gre_print(ndo, bp, length);
187 		break;
188 
189 	case IPPROTO_MOBILE:
190 		mobile_print(ndo, bp, length);
191 		break;
192 
193 	case IPPROTO_PIM:
194 		pim_print(ndo, bp, length, iph);
195 		break;
196 
197 	case IPPROTO_VRRP:
198 		if (ndo->ndo_packettype == PT_CARP) {
199 			carp_print(ndo, bp, length, ttl_hl);
200 		} else {
201 			vrrp_print(ndo, bp, length, iph, ttl_hl, ver);
202 		}
203 		break;
204 
205 	case IPPROTO_PGM:
206 		pgm_print(ndo, bp, length, iph);
207 		break;
208 
209 	case IPPROTO_ETHERNET:
210 		if (ver == 6)
211 			ether_print(ndo, bp, length, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
212 		else {
213 			ND_PRINT("[%s requires IPv6]",
214 				 tok2str(ipproto_values,"unknown",nh));
215 			nd_print_invalid(ndo);
216 		}
217 		break;
218 
219 	case IPPROTO_NONE:
220 		ND_PRINT("no next header");
221 		break;
222 
223 	default:
224 		if (ndo->ndo_nflag==0 && (p_name = netdb_protoname(nh)) != NULL)
225 			ND_PRINT(" %s", p_name);
226 		else
227 			ND_PRINT(" ip-proto-%u", nh);
228 		ND_PRINT(" %u", length);
229 		break;
230 	}
231 }
232