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