Projet

Général

Profil

Télécharger (15,6 ko) Statistiques
| Branche: | Révision:

univnautes-tools / pfPorts / filterlog / files / print-icmp.c @ 8135339c

1
/*
2
 * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996
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
#include <sys/sbuf.h>
27
#include <netinet/in.h>
28
#include <netinet/ip.h>
29
#include <netinet/tcp.h>
30
#include <netinet/udp.h>
31
#include <arpa/inet.h>
32

    
33
#include <stdio.h>
34
#include <stdlib.h>
35
#include <string.h>
36

    
37
#include "common.h"
38

    
39
/*
40
 * Interface Control Message Protocol Definitions.
41
 * Per RFC 792, September 1981.
42
 */
43

    
44
/*
45
 * Structure of an icmp header.
46
 */
47
struct icmp {
48
	u_int8_t  icmp_type;		/* type of message, see below */
49
	u_int8_t  icmp_code;		/* type sub code */
50
	u_int16_t icmp_cksum;		/* ones complement cksum of struct */
51
	union {
52
		u_int8_t ih_pptr;			/* ICMP_PARAMPROB */
53
		struct in_addr ih_gwaddr;	/* ICMP_REDIRECT */
54
		struct ih_idseq {
55
			u_int16_t icd_id;
56
			u_int16_t icd_seq;
57
		} ih_idseq;
58
		u_int32_t ih_void;
59
	} icmp_hun;
60
#define	icmp_pptr	icmp_hun.ih_pptr
61
#define	icmp_gwaddr	icmp_hun.ih_gwaddr
62
#define	icmp_id		icmp_hun.ih_idseq.icd_id
63
#define	icmp_seq	icmp_hun.ih_idseq.icd_seq
64
#define	icmp_void	icmp_hun.ih_void
65
	union {
66
		struct id_ts {
67
			u_int32_t its_otime;
68
			u_int32_t its_rtime;
69
			u_int32_t its_ttime;
70
		} id_ts;
71
		struct id_ip  {
72
			struct ip idi_ip;
73
			/* options and then 64 bits of data */
74
		} id_ip;
75
		u_int32_t id_mask;
76
		u_int8_t id_data[1];
77
	} icmp_dun;
78
#define	icmp_otime	icmp_dun.id_ts.its_otime
79
#define	icmp_rtime	icmp_dun.id_ts.its_rtime
80
#define	icmp_ttime	icmp_dun.id_ts.its_ttime
81
#define	icmp_ip		icmp_dun.id_ip.idi_ip
82
#define	icmp_mask	icmp_dun.id_mask
83
#define	icmp_data	icmp_dun.id_data
84
};
85

    
86
#define ICMP_MPLS_EXT_EXTRACT_VERSION(x) (((x)&0xf0)>>4) 
87
#define ICMP_MPLS_EXT_VERSION 2
88

    
89
/*
90
 * Lower bounds on packet lengths for various types.
91
 * For the error advice packets must first insure that the
92
 * packet is large enought to contain the returned ip header.
93
 * Only then can we do the check to see if 64 bits of packet
94
 * data have been returned, since we need to check the returned
95
 * ip header length.
96
 */
97
#define	ICMP_MINLEN	8				/* abs minimum */
98
#define ICMP_EXTD_MINLEN (156 - sizeof (struct ip))     /* draft-bonica-internet-icmp-08 */
99
#define	ICMP_TSLEN	(8 + 3 * sizeof (u_int32_t))	/* timestamp */
100
#define	ICMP_MASKLEN	12				/* address mask */
101
#define	ICMP_ADVLENMIN	(8 + sizeof (struct ip) + 8)	/* min */
102
#define	ICMP_ADVLEN(p)	(8 + (IP_HL(&(p)->icmp_ip) << 2) + 8)
103
	/* N.B.: must separately check that ip_hl >= 5 */
104

    
105
/*
106
 * Definition of type and code field values.
107
 */
108
#define	ICMP_ECHOREPLY		0		/* echo reply */
109
#define	ICMP_UNREACH		3		/* dest unreachable, codes: */
110
#define		ICMP_UNREACH_NET	0		/* bad net */
111
#define		ICMP_UNREACH_HOST	1		/* bad host */
112
#define		ICMP_UNREACH_PROTOCOL	2		/* bad protocol */
113
#define		ICMP_UNREACH_PORT	3		/* bad port */
114
#define		ICMP_UNREACH_NEEDFRAG	4		/* IP_DF caused drop */
115
#define		ICMP_UNREACH_SRCFAIL	5		/* src route failed */
116
#define		ICMP_UNREACH_NET_UNKNOWN 6		/* unknown net */
117
#define		ICMP_UNREACH_HOST_UNKNOWN 7		/* unknown host */
118
#define		ICMP_UNREACH_ISOLATED	8		/* src host isolated */
119
#define		ICMP_UNREACH_NET_PROHIB	9		/* prohibited access */
120
#define		ICMP_UNREACH_HOST_PROHIB 10		/* ditto */
121
#define		ICMP_UNREACH_TOSNET	11		/* bad tos for net */
122
#define		ICMP_UNREACH_TOSHOST	12		/* bad tos for host */
123
#define	ICMP_SOURCEQUENCH	4		/* packet lost, slow down */
124
#define	ICMP_REDIRECT		5		/* shorter route, codes: */
125
#define		ICMP_REDIRECT_NET	0		/* for network */
126
#define		ICMP_REDIRECT_HOST	1		/* for host */
127
#define		ICMP_REDIRECT_TOSNET	2		/* for tos and net */
128
#define		ICMP_REDIRECT_TOSHOST	3		/* for tos and host */
129
#define	ICMP_ECHO		8		/* echo service */
130
#define	ICMP_ROUTERADVERT	9		/* router advertisement */
131
#define	ICMP_ROUTERSOLICIT	10		/* router solicitation */
132
#define	ICMP_TIMXCEED		11		/* time exceeded, code: */
133
#define		ICMP_TIMXCEED_INTRANS	0		/* ttl==0 in transit */
134
#define		ICMP_TIMXCEED_REASS	1		/* ttl==0 in reass */
135
#define	ICMP_PARAMPROB		12		/* ip header bad */
136
#define		ICMP_PARAMPROB_OPTABSENT 1		/* req. opt. absent */
137
#define	ICMP_TSTAMP		13		/* timestamp request */
138
#define	ICMP_TSTAMPREPLY	14		/* timestamp reply */
139
#define	ICMP_IREQ		15		/* information request */
140
#define	ICMP_IREQREPLY		16		/* information reply */
141
#define	ICMP_MASKREQ		17		/* address mask request */
142
#define	ICMP_MASKREPLY		18		/* address mask reply */
143

    
144
#define	ICMP_MAXTYPE		18
145

    
146
#define	ICMP_INFOTYPE(type) \
147
	((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \
148
	(type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \
149
	(type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \
150
	(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
151
	(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
152
#define	ICMP_MPLS_EXT_TYPE(type) \
153
	((type) == ICMP_UNREACH || \
154
         (type) == ICMP_TIMXCEED || \
155
         (type) == ICMP_PARAMPROB)
156
/* rfc1700 */
157
#ifndef ICMP_UNREACH_NET_UNKNOWN
158
#define ICMP_UNREACH_NET_UNKNOWN	6	/* destination net unknown */
159
#endif
160
#ifndef ICMP_UNREACH_HOST_UNKNOWN
161
#define ICMP_UNREACH_HOST_UNKNOWN	7	/* destination host unknown */
162
#endif
163
#ifndef ICMP_UNREACH_ISOLATED
164
#define ICMP_UNREACH_ISOLATED		8	/* source host isolated */
165
#endif
166
#ifndef ICMP_UNREACH_NET_PROHIB
167
#define ICMP_UNREACH_NET_PROHIB		9	/* admin prohibited net */
168
#endif
169
#ifndef ICMP_UNREACH_HOST_PROHIB
170
#define ICMP_UNREACH_HOST_PROHIB	10	/* admin prohibited host */
171
#endif
172
#ifndef ICMP_UNREACH_TOSNET
173
#define ICMP_UNREACH_TOSNET		11	/* tos prohibited net */
174
#endif
175
#ifndef ICMP_UNREACH_TOSHOST
176
#define ICMP_UNREACH_TOSHOST		12	/* tos prohibited host */
177
#endif
178

    
179
/* rfc1716 */
180
#ifndef ICMP_UNREACH_FILTER_PROHIB
181
#define ICMP_UNREACH_FILTER_PROHIB	13	/* admin prohibited filter */
182
#endif
183
#ifndef ICMP_UNREACH_HOST_PRECEDENCE
184
#define ICMP_UNREACH_HOST_PRECEDENCE	14	/* host precedence violation */
185
#endif
186
#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
187
#define ICMP_UNREACH_PRECEDENCE_CUTOFF	15	/* precedence cutoff */
188
#endif
189

    
190
/* Most of the icmp types */
191
static struct tok icmp2str[] = {
192
	{ ICMP_ECHOREPLY,		"echo reply" },
193
	{ ICMP_SOURCEQUENCH,		"source quench" },
194
	{ ICMP_ECHO,			"echo request" },
195
	{ ICMP_ROUTERSOLICIT,		"router solicitation" },
196
	{ ICMP_TSTAMP,			"time stamp request" },
197
	{ ICMP_TSTAMPREPLY,		"time stamp reply" },
198
	{ ICMP_IREQ,			"information request" },
199
	{ ICMP_IREQREPLY,		"information reply" },
200
	{ ICMP_MASKREQ,			"address mask request" },
201
	{ 0,				NULL }
202
};
203

    
204
/* Formats for most of the ICMP_UNREACH codes */
205
static struct tok unreach2str[] = {
206
	{ ICMP_UNREACH_NET,		"net %s unreachable" },
207
	{ ICMP_UNREACH_HOST,		"host %s unreachable" },
208
	{ ICMP_UNREACH_SRCFAIL,
209
	    "%s unreachable - source route failed" },
210
	{ ICMP_UNREACH_NET_UNKNOWN,	"net %s unreachable - unknown" },
211
	{ ICMP_UNREACH_HOST_UNKNOWN,	"host %s unreachable - unknown" },
212
	{ ICMP_UNREACH_ISOLATED,
213
	    "%s unreachable - source host isolated" },
214
	{ ICMP_UNREACH_NET_PROHIB,
215
	    "net %s unreachable - admin prohibited" },
216
	{ ICMP_UNREACH_HOST_PROHIB,
217
	    "host %s unreachable - admin prohibited" },
218
	{ ICMP_UNREACH_TOSNET,
219
	    "net %s unreachable - tos prohibited" },
220
	{ ICMP_UNREACH_TOSHOST,
221
	    "host %s unreachable - tos prohibited" },
222
	{ ICMP_UNREACH_FILTER_PROHIB,
223
	    "host %s unreachable - admin prohibited filter" },
224
	{ ICMP_UNREACH_HOST_PRECEDENCE,
225
	    "host %s unreachable - host precedence violation" },
226
	{ ICMP_UNREACH_PRECEDENCE_CUTOFF,
227
	    "host %s unreachable - precedence cutoff" },
228
	{ 0,				NULL }
229
};
230

    
231
/* Formats for the ICMP_REDIRECT codes */
232
static struct tok type2str[] = {
233
	{ ICMP_REDIRECT_NET,		"redirect %s to net %s" },
234
	{ ICMP_REDIRECT_HOST,		"redirect %s to host %s" },
235
	{ ICMP_REDIRECT_TOSNET,		"redirect-tos %s to net %s" },
236
	{ ICMP_REDIRECT_TOSHOST,	"redirect-tos %s to host %s" },
237
	{ 0,				NULL }
238
};
239

    
240
/* rfc1191 */
241
struct mtu_discovery {
242
	u_int16_t unused;
243
	u_int16_t nexthopmtu;
244
};
245

    
246
/* rfc1256 */
247
struct ih_rdiscovery {
248
	u_int8_t ird_addrnum;
249
	u_int8_t ird_addrsiz;
250
	u_int16_t ird_lifetime;
251
};
252

    
253
struct id_rdiscovery {
254
	u_int32_t ird_addr;
255
	u_int32_t ird_pref;
256
};
257

    
258
/*
259
 * draft-bonica-internet-icmp-08
260
 *
261
 * The Destination Unreachable, Time Exceeded
262
 * and Parameter Problem messages are slighly changed as per
263
 * the above draft. A new Length field gets added to give
264
 * the caller an idea about the length of the piggypacked
265
 * IP packet before the MPLS extension header starts.
266
 *
267
 * The Length field represents length of the padded "original datagram"
268
 * field  measured in 32-bit words.
269
 *
270
 * 0                   1                   2                   3
271
 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
272
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
273
 * |     Type      |     Code      |          Checksum             |
274
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
275
 * |     unused    |    Length     |          unused               |
276
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
277
 * |      Internet Header + leading octets of original datagram    |
278
 * |                                                               |
279
 * |                           //                                  |
280
 * |                                                               |
281
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
282
 */
283

    
284
struct icmp_ext_t {
285
    u_int8_t icmp_type;
286
    u_int8_t icmp_code;
287
    u_int8_t icmp_checksum[2];
288
    u_int8_t icmp_reserved;
289
    u_int8_t icmp_length;
290
    u_int8_t icmp_reserved2[2];
291
    u_int8_t icmp_ext_legacy_header[128]; /* extension header starts 128 bytes after ICMP header */
292
    u_int8_t icmp_ext_version_res[2];
293
    u_int8_t icmp_ext_checksum[2];
294
    u_int8_t icmp_ext_data[1];
295
};
296

    
297
struct icmp_mpls_ext_object_header_t {
298
    u_int8_t length[2];
299
    u_int8_t class_num;
300
    u_int8_t ctype;
301
};
302

    
303
static const struct tok icmp_mpls_ext_obj_values[] = {
304
    { 1, "MPLS Stack Entry" },
305
    { 2, "Extended Payload" },
306
    { 0, NULL}
307
};
308

    
309
/* prototypes */
310
const char *icmp_tstamp_print(u_int);
311

    
312
/* print the milliseconds since midnight UTC */
313
const char *
314
icmp_tstamp_print(u_int tstamp) {
315
    u_int msec,sec,min,hrs;
316

    
317
    static char buf[64];
318

    
319
    msec = tstamp % 1000;
320
    sec = tstamp / 1000;
321
    min = sec / 60; sec -= min * 60;
322
    hrs = min / 60; min -= hrs * 60;
323
    snprintf(buf, sizeof(buf), "%02u:%02u:%02u.%03u",hrs,min,sec,msec);
324
    return buf;
325
}
326
 
327
void
328
icmp_print(struct sbuf *sbuf, const u_char *bp, u_int plen, const u_char *bp2, int fragmented __unused)
329
{
330
	const struct icmp *dp;
331
	const struct ip *ip;
332
	const struct ip *oip;
333
	const struct udphdr *ouh;
334
	u_int hlen, dport, mtu;
335

    
336
	dp = (const struct icmp *)bp;
337
	ip = (const struct ip *)bp2;
338

    
339
	switch (dp->icmp_type) {
340
	case ICMP_ECHO:
341
	case ICMP_ECHOREPLY:
342
		sbuf_printf(sbuf, "%s,%u,%u",
343
                               dp->icmp_type == ICMP_ECHO ?
344
                               "request" : "reply",
345
                               EXTRACT_16BITS(&dp->icmp_id),
346
                               EXTRACT_16BITS(&dp->icmp_seq));
347
		break;
348

    
349
	case ICMP_UNREACH:
350
		switch (dp->icmp_code) {
351
		case ICMP_UNREACH_PROTOCOL:
352
			sbuf_printf(sbuf,
353
			    "unreachproto,%s,%d",
354
			    inet_ntoa(dp->icmp_ip.ip_dst),
355
			    dp->icmp_ip.ip_p);
356
			break;
357

    
358
		case ICMP_UNREACH_PORT:
359
			oip = &dp->icmp_ip;
360
			hlen = IP_HL(oip) * 4;
361
			ouh = (const struct udphdr *)(((const u_char *)oip) + hlen);
362
			dport = EXTRACT_16BITS(&ouh->uh_dport);
363
			sbuf_printf(sbuf, "unreachport,");
364
			switch (oip->ip_p) {
365
			case IPPROTO_TCP:
366
				sbuf_printf(sbuf,
367
					"%s,TCP,%u",
368
					inet_ntoa(oip->ip_dst),
369
					dport);
370
				break;
371

    
372
			case IPPROTO_UDP:
373
				sbuf_printf(sbuf,
374
					"%s,UDP,%u",
375
					inet_ntoa(oip->ip_dst),
376
					dport);
377
				break;
378

    
379
			default:
380
				sbuf_printf(sbuf,
381
					"%s,%d,%d",
382
					inet_ntoa(oip->ip_dst),
383
					oip->ip_p, dport);
384
				break;
385
			}
386
			break;
387

    
388
		case ICMP_UNREACH_NEEDFRAG:
389
		    {
390
			register const struct mtu_discovery *mp;
391
			mp = (const struct mtu_discovery *)(const u_char *)&dp->icmp_void;
392
			mtu = EXTRACT_16BITS(&mp->nexthopmtu);
393
			if (mtu) {
394
				sbuf_printf(sbuf,
395
				    "needfrag,%s,%d",
396
				    inet_ntoa(dp->icmp_ip.ip_dst), mtu);
397
			} else {
398
				sbuf_printf(sbuf,
399
				    "needfrag,%s need to frag",
400
				    inet_ntoa(dp->icmp_ip.ip_dst));
401
			}
402
		    }
403
			break;
404

    
405
		default:
406
			sbuf_printf(sbuf, "unreach,");
407
			sbuf_printf(sbuf, code2str(unreach2str, "%s unreachable", dp->icmp_code),
408
			    inet_ntoa(dp->icmp_ip.ip_dst));
409
			break;
410
		}
411
		break;
412

    
413
	case ICMP_REDIRECT:
414
		sbuf_printf(sbuf, "redirect,");
415
		sbuf_printf(sbuf, code2str(type2str, "redirect-?? %s to net %s,", dp->icmp_code),
416
		    inet_ntoa(dp->icmp_ip.ip_dst),
417
		    inet_ntoa(dp->icmp_gwaddr));
418
		break;
419

    
420
	case ICMP_ROUTERADVERT:
421
	    {
422
		register const struct ih_rdiscovery *ihp;
423
		u_int lifetime, num, size;
424

    
425
		sbuf_printf(sbuf, "routeradv");
426

    
427
		ihp = (const struct ih_rdiscovery *)&dp->icmp_void;
428
		lifetime = EXTRACT_16BITS(&ihp->ird_lifetime);
429
		if (lifetime < 60) {
430
			sbuf_printf(sbuf, "%u,",
431
			    lifetime);
432
		} else if (lifetime < 60 * 60) {
433
			sbuf_printf(sbuf, "%u:%02u,",
434
			    lifetime / 60, lifetime % 60);
435
		} else {
436
			sbuf_printf(sbuf,
437
			    "%u:%02u:%02u,",
438
			    lifetime / 3600,
439
			    (lifetime % 3600) / 60,
440
			    lifetime % 60);
441
		}
442

    
443
		num = ihp->ird_addrnum;
444
		sbuf_printf(sbuf, "%d,", num);
445

    
446
		size = ihp->ird_addrsiz;
447
		if (size != 2) {
448
			sbuf_printf(sbuf,
449
			    "%d,", size);
450
			break;
451
		}
452
	    }
453
		break;
454

    
455
	case ICMP_TIMXCEED:
456
		sbuf_printf(sbuf, "timexceed,");
457
		switch (dp->icmp_code) {
458
		case ICMP_TIMXCEED_INTRANS:
459
			sbuf_printf(sbuf, "time exceeded in-transit");
460
			break;
461

    
462
		case ICMP_TIMXCEED_REASS:
463
			sbuf_printf(sbuf, "ip reassembly time exceeded");
464
			break;
465

    
466
		default:
467
			sbuf_printf(sbuf, "time exceeded-#%d",
468
			    dp->icmp_code);
469
			break;
470
		}
471
		break;
472

    
473
	case ICMP_PARAMPROB:
474
		if (dp->icmp_code)
475
			sbuf_printf(sbuf,
476
			    "paramprob, parameter problem - code %d", dp->icmp_code);
477
		else {
478
			sbuf_printf(sbuf,
479
			    "paramprob, parameter problem - octet %d", dp->icmp_pptr);
480
		}
481
		break;
482

    
483
	case ICMP_MASKREPLY:
484
		sbuf_printf(sbuf, "maskreply, address mask is 0x%08x",
485
		    EXTRACT_32BITS(&dp->icmp_mask));
486
		break;
487

    
488
	case ICMP_TSTAMP:
489
		sbuf_printf(sbuf,
490
		    "tstamp,%u,%u",
491
		    EXTRACT_16BITS(&dp->icmp_id),
492
		    EXTRACT_16BITS(&dp->icmp_seq));
493
		break;
494

    
495
	case ICMP_TSTAMPREPLY:
496
		sbuf_printf(sbuf,
497
		    "tstampreply, %u,%u,%s,",
498
                               EXTRACT_16BITS(&dp->icmp_id),
499
                               EXTRACT_16BITS(&dp->icmp_seq),
500
                               icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_otime)));
501

    
502
                sbuf_printf(sbuf, "%s,",
503
                         icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_rtime)));
504
                sbuf_printf(sbuf, "%s",
505
                         icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_ttime)));
506
                break;
507

    
508
	default:
509
		sbuf_printf(sbuf, code2str(icmp2str, "type-??", dp->icmp_type));
510
		break;
511
	}
512
	sbuf_printf(sbuf, "%u", plen);
513

    
514
	return;
515
}
(6-6/11)