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
|
#include <sys/types.h>
|
25
|
#include <sys/socket.h>
|
26
|
|
27
|
#include <netinet/in.h>
|
28
|
#include <arpa/inet.h>
|
29
|
#include <netinet/ip.h>
|
30
|
|
31
|
#include <netinet/udp.h>
|
32
|
|
33
|
#include <stdio.h>
|
34
|
#include <stdlib.h>
|
35
|
#include <string.h>
|
36
|
#include <netdb.h>
|
37
|
|
38
|
#include <pcap/pcap.h>
|
39
|
|
40
|
#include "common.h"
|
41
|
|
42
|
#define IP_RES 0x8000
|
43
|
|
44
|
static struct tok ip_frag_values[] = {
|
45
|
{ IP_MF, "+" },
|
46
|
{ IP_DF, "DF" },
|
47
|
{ IP_RES, "rsvd" }, /* The RFC3514 evil ;-) bit */
|
48
|
{ 0, NULL }
|
49
|
};
|
50
|
|
51
|
struct ip_print_demux_state {
|
52
|
const struct ip *ip;
|
53
|
const u_char *cp;
|
54
|
u_int len, off;
|
55
|
u_char nh;
|
56
|
int advance;
|
57
|
};
|
58
|
|
59
|
static void
|
60
|
ip_print_demux(struct sbuf *sbuf,
|
61
|
struct ip_print_demux_state *ipds)
|
62
|
{
|
63
|
#if 0
|
64
|
struct protoent *proto;
|
65
|
struct cksum_vec vec[1];
|
66
|
|
67
|
again:
|
68
|
#endif
|
69
|
switch (ipds->nh) {
|
70
|
|
71
|
#if 0
|
72
|
case IPPROTO_AH:
|
73
|
ipds->nh = *ipds->cp;
|
74
|
ipds->advance = ah_print(ipds->cp);
|
75
|
if (ipds->advance <= 0)
|
76
|
break;
|
77
|
ipds->cp += ipds->advance;
|
78
|
ipds->len -= ipds->advance;
|
79
|
goto again;
|
80
|
|
81
|
case IPPROTO_ESP:
|
82
|
{
|
83
|
int enh, padlen;
|
84
|
ipds->advance = esp_print(ndo, ipds->cp, ipds->len,
|
85
|
(const u_char *)ipds->ip,
|
86
|
&enh, &padlen);
|
87
|
if (ipds->advance <= 0)
|
88
|
break;
|
89
|
ipds->cp += ipds->advance;
|
90
|
ipds->len -= ipds->advance + padlen;
|
91
|
ipds->nh = enh & 0xff;
|
92
|
goto again;
|
93
|
}
|
94
|
|
95
|
case IPPROTO_IPCOMP:
|
96
|
{
|
97
|
int enh;
|
98
|
ipds->advance = ipcomp_print(ipds->cp, &enh);
|
99
|
if (ipds->advance <= 0)
|
100
|
break;
|
101
|
ipds->cp += ipds->advance;
|
102
|
ipds->len -= ipds->advance;
|
103
|
ipds->nh = enh & 0xff;
|
104
|
goto again;
|
105
|
}
|
106
|
|
107
|
case IPPROTO_SCTP:
|
108
|
sctp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len);
|
109
|
break;
|
110
|
|
111
|
case IPPROTO_DCCP:
|
112
|
dccp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len);
|
113
|
break;
|
114
|
#endif
|
115
|
|
116
|
case IPPROTO_TCP:
|
117
|
/* pass on the MF bit plus the offset to detect fragments */
|
118
|
tcp_print(sbuf, ipds->cp, ipds->len, (const u_char *)ipds->ip);
|
119
|
break;
|
120
|
|
121
|
case IPPROTO_UDP:
|
122
|
{
|
123
|
const struct udphdr *up;
|
124
|
|
125
|
up = (const struct udphdr *)ipds->cp;
|
126
|
sbuf_printf(sbuf, "%d,%d,%d", EXTRACT_16BITS(&up->uh_sport), EXTRACT_16BITS(&up->uh_dport),
|
127
|
EXTRACT_16BITS(&up->uh_ulen));
|
128
|
|
129
|
}
|
130
|
break;
|
131
|
|
132
|
case IPPROTO_ICMP:
|
133
|
/* pass on the MF bit plus the offset to detect fragments */
|
134
|
icmp_print(sbuf, ipds->cp, ipds->len, (const u_char *)ipds->ip,
|
135
|
ipds->off & (IP_MF|IP_OFFMASK));
|
136
|
break;
|
137
|
|
138
|
#if 0
|
139
|
case IPPROTO_PIGP:
|
140
|
/*
|
141
|
* XXX - the current IANA protocol number assignments
|
142
|
* page lists 9 as "any private interior gateway
|
143
|
* (used by Cisco for their IGRP)" and 88 as
|
144
|
* "EIGRP" from Cisco.
|
145
|
*
|
146
|
* Recent BSD <netinet/in.h> headers define
|
147
|
* IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88.
|
148
|
* We define IP_PROTO_PIGP as 9 and
|
149
|
* IP_PROTO_EIGRP as 88; those names better
|
150
|
* match was the current protocol number
|
151
|
* assignments say.
|
152
|
*/
|
153
|
igrp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
|
154
|
break;
|
155
|
|
156
|
case IPPROTO_EIGRP:
|
157
|
eigrp_print(ipds->cp, ipds->len);
|
158
|
break;
|
159
|
|
160
|
case IPPROTO_ND:
|
161
|
ND_PRINT((ndo, " nd %d", ipds->len));
|
162
|
break;
|
163
|
|
164
|
case IPPROTO_EGP:
|
165
|
egp_print(ipds->cp, ipds->len);
|
166
|
break;
|
167
|
|
168
|
case IPPROTO_OSPF:
|
169
|
ospf_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
|
170
|
break;
|
171
|
case IPPROTO_IGMP:
|
172
|
igmp_print(ipds->cp, ipds->len);
|
173
|
break;
|
174
|
#endif
|
175
|
|
176
|
case IPPROTO_IPV4:
|
177
|
/* DVMRP multicast tunnel (ip-in-ip encapsulation) */
|
178
|
sbuf_printf(sbuf, "IPV4-IN-IPV4,");
|
179
|
//ip_print(sbuf, ipds->cp, ipds->len);
|
180
|
break;
|
181
|
|
182
|
case IPPROTO_IPV6:
|
183
|
/* ip6-in-ip encapsulation */
|
184
|
//ip6_print(sbuf, ipds->cp, ipds->len);
|
185
|
sbuf_printf(sbuf, "IPV6-IN-IPV4,");
|
186
|
break;
|
187
|
#if 0
|
188
|
case IPPROTO_RSVP:
|
189
|
rsvp_print(ipds->cp, ipds->len);
|
190
|
break;
|
191
|
|
192
|
case IPPROTO_GRE:
|
193
|
/* do it */
|
194
|
gre_print(ipds->cp, ipds->len);
|
195
|
break;
|
196
|
|
197
|
case IPPROTO_MOBILE:
|
198
|
mobile_print(ipds->cp, ipds->len);
|
199
|
break;
|
200
|
|
201
|
case IPPROTO_PIM:
|
202
|
vec[0].ptr = ipds->cp;
|
203
|
vec[0].len = ipds->len;
|
204
|
pim_print(ipds->cp, ipds->len, in_cksum(vec, 1));
|
205
|
break;
|
206
|
#endif
|
207
|
case IPPROTO_VRRP:
|
208
|
/* Type, ttl, vhid, version, adbskew, advbase */
|
209
|
sbuf_printf(sbuf, "%s,%d,%d,%d,%d,%d",
|
210
|
(ipds->cp[0] & 0x0f) == 1 ? "advertise" : "unkwn",
|
211
|
ipds->ip->ip_ttl, ipds->cp[1], (ipds->cp[0] & 0xf0) >> 4,
|
212
|
ipds->cp[2], ipds->cp[5]);
|
213
|
break;
|
214
|
|
215
|
#if 0
|
216
|
case IPPROTO_PGM:
|
217
|
pgm_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
|
218
|
break;
|
219
|
|
220
|
case IPPROTO_PFSYNC:
|
221
|
pfsync_ip_print(ipds->cp, ipds->len);
|
222
|
break;
|
223
|
#endif
|
224
|
default:
|
225
|
//sbuf_printf(sbuf, "ip-proto=%d ", ipds->nh);
|
226
|
sbuf_printf(sbuf, "datalength=%d ", ipds->len);
|
227
|
break;
|
228
|
}
|
229
|
}
|
230
|
|
231
|
/*
|
232
|
* print an IP datagram.
|
233
|
* it requires fixed length fields to be put as null always
|
234
|
*/
|
235
|
void
|
236
|
ip_print(struct sbuf *sbuf,
|
237
|
const u_char *bp,
|
238
|
u_int length)
|
239
|
{
|
240
|
struct ip_print_demux_state ipd;
|
241
|
struct ip_print_demux_state *ipds=&ipd;
|
242
|
const u_char *ipend;
|
243
|
u_int hlen;
|
244
|
|
245
|
ipds->ip = (const struct ip *)bp;
|
246
|
sbuf_printf(sbuf, "%u,", IP_V(ipds->ip));
|
247
|
|
248
|
if (ntohs(ipds->ip->ip_len) > MAXIMUM_SNAPLEN) {
|
249
|
sbuf_printf(sbuf, "[|ip]),");
|
250
|
return;
|
251
|
}
|
252
|
if (length < sizeof (struct ip)) {
|
253
|
sbuf_printf(sbuf, "truncated-ip= %u),", length);
|
254
|
return;
|
255
|
}
|
256
|
hlen = IP_HL(ipds->ip) * 4;
|
257
|
if (hlen < sizeof (struct ip)) {
|
258
|
sbuf_printf(sbuf, "bad-hlen=%u),", hlen);
|
259
|
return;
|
260
|
}
|
261
|
|
262
|
ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len);
|
263
|
if (length < ipds->len)
|
264
|
sbuf_printf(sbuf, "error='truncated-ip %u bytes missing!',",
|
265
|
ipds->len - length);
|
266
|
if (ipds->len < hlen) {
|
267
|
sbuf_printf(sbuf, "bad-len=%u,", ipds->len);
|
268
|
return;
|
269
|
}
|
270
|
|
271
|
/*
|
272
|
* Cut off the snapshot length to the end of the IP payload.
|
273
|
*/
|
274
|
ipend = bp + ipds->len;
|
275
|
ipds->len -= hlen;
|
276
|
ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off);
|
277
|
|
278
|
sbuf_printf(sbuf, "0x%x,", (int)ipds->ip->ip_tos);
|
279
|
/* ECN bits */
|
280
|
if (ipds->ip->ip_tos & 0x03) {
|
281
|
switch (ipds->ip->ip_tos & 0x03) {
|
282
|
case 1:
|
283
|
sbuf_printf(sbuf, "1");
|
284
|
break;
|
285
|
case 2:
|
286
|
sbuf_printf(sbuf, "0");
|
287
|
break;
|
288
|
case 3:
|
289
|
sbuf_printf(sbuf, "CE");
|
290
|
break;
|
291
|
}
|
292
|
}
|
293
|
sbuf_printf(sbuf, ",%u,", ipds->ip->ip_ttl);
|
294
|
|
295
|
/*
|
296
|
* for the firewall guys, print id, offset.
|
297
|
* On all but the last stick a "+" in the flags portion.
|
298
|
* For unfragmented datagrams, note the don't fragment flag.
|
299
|
*/
|
300
|
sbuf_printf(sbuf, "%u,%u,%s,%u,",
|
301
|
EXTRACT_16BITS(&ipds->ip->ip_id),
|
302
|
(ipds->off & 0x1fff) * 8,
|
303
|
code2str(ip_frag_values, "none", ipds->off & 0xe000),
|
304
|
ipds->ip->ip_p);
|
305
|
|
306
|
if (getprotobynumber(ipds->ip->ip_p) != NULL)
|
307
|
sbuf_printf(sbuf, "%s,", ((struct protoent *)getprotobynumber(ipds->ip->ip_p))->p_name);
|
308
|
else
|
309
|
sbuf_printf(sbuf, "%s,",
|
310
|
code2str(ipproto_values, "unknown", ipds->ip->ip_p));
|
311
|
sbuf_printf(sbuf, "%u,", EXTRACT_16BITS(&ipds->ip->ip_len));
|
312
|
|
313
|
sbuf_printf(sbuf, "%s,", inet_ntoa(ipds->ip->ip_src));
|
314
|
sbuf_printf(sbuf, "%s,", inet_ntoa(ipds->ip->ip_dst));
|
315
|
/*
|
316
|
* If this is fragment zero, hand it to the next higher
|
317
|
* level protocol.
|
318
|
*/
|
319
|
if ((ipds->off & 0x1fff) == 0) {
|
320
|
ipds->cp = (const u_char *)ipds->ip + hlen;
|
321
|
ipds->nh = ipds->ip->ip_p;
|
322
|
|
323
|
ip_print_demux(sbuf, ipds);
|
324
|
}
|
325
|
}
|