pfkey_dump.c revision 121021
1/*	$KAME: pfkey_dump.c,v 1.28 2001/06/27 10:46:51 sakane Exp $	*/
2
3/*
4 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/lib/libipsec/pfkey_dump.c 121021 2003-10-12 09:41:42Z ume $");
34
35#include <sys/types.h>
36#include <sys/param.h>
37#include <sys/socket.h>
38#include <netinet6/ipsec.h>
39#include <net/pfkeyv2.h>
40#include <netkey/key_var.h>
41#include <netkey/key_debug.h>
42
43#include <netinet/in.h>
44#include <netinet6/ipsec.h>
45#include <arpa/inet.h>
46
47#include <stdlib.h>
48#include <unistd.h>
49#include <stdio.h>
50#include <string.h>
51#include <time.h>
52#include <netdb.h>
53
54#include "ipsec_strerror.h"
55#include "libpfkey.h"
56
57/* cope with old kame headers - ugly */
58#ifndef SADB_X_AALG_MD5
59#define SADB_X_AALG_MD5		SADB_AALG_MD5
60#endif
61#ifndef SADB_X_AALG_SHA
62#define SADB_X_AALG_SHA		SADB_AALG_SHA
63#endif
64#ifndef SADB_X_AALG_NULL
65#define SADB_X_AALG_NULL	SADB_AALG_NULL
66#endif
67
68#ifndef SADB_X_EALG_BLOWFISHCBC
69#define SADB_X_EALG_BLOWFISHCBC	SADB_EALG_BLOWFISHCBC
70#endif
71#ifndef SADB_X_EALG_CAST128CBC
72#define SADB_X_EALG_CAST128CBC	SADB_EALG_CAST128CBC
73#endif
74#ifndef SADB_X_EALG_RC5CBC
75#ifdef SADB_EALG_RC5CBC
76#define SADB_X_EALG_RC5CBC	SADB_EALG_RC5CBC
77#endif
78#endif
79
80#define GETMSGSTR(str, num) \
81do { \
82	if (sizeof((str)[0]) == 0 \
83	 || num >= sizeof(str)/sizeof((str)[0])) \
84		printf("%d ", (num)); \
85	else if (strlen((str)[(num)]) == 0) \
86		printf("%d ", (num)); \
87	else \
88		printf("%s ", (str)[(num)]); \
89} while (0)
90
91#define GETMSGV2S(v2s, num) \
92do { \
93	struct val2str *p;  \
94	for (p = (v2s); p && p->str; p++) { \
95		if (p->val == (num)) \
96			break; \
97	} \
98	if (p && p->str) \
99		printf("%s ", p->str); \
100	else \
101		printf("%d ", (num)); \
102} while (0)
103
104static char *str_ipaddr(struct sockaddr *);
105static char *str_prefport(u_int, u_int, u_int);
106static char *str_time(time_t);
107static void str_lifetime_byte(struct sadb_lifetime *, char *);
108
109struct val2str {
110	int val;
111	const char *str;
112};
113
114/*
115 * Must to be re-written about following strings.
116 */
117static char *str_satype[] = {
118	"unspec",
119	"unknown",
120	"ah",
121	"esp",
122	"unknown",
123	"rsvp",
124	"ospfv2",
125	"ripv2",
126	"mip",
127	"ipcomp",
128};
129
130static char *str_mode[] = {
131	"any",
132	"transport",
133	"tunnel",
134};
135
136static char *str_upper[] = {
137/*0*/	"ip", "icmp", "igmp", "ggp", "ip4",
138	"", "tcp", "", "egp", "",
139/*10*/	"", "", "", "", "",
140	"", "", "udp", "", "",
141/*20*/	"", "", "idp", "", "",
142	"", "", "", "", "tp",
143/*30*/	"", "", "", "", "",
144	"", "", "", "", "",
145/*40*/	"", "ip6", "", "rt6", "frag6",
146	"", "rsvp", "gre", "", "",
147/*50*/	"esp", "ah", "", "", "",
148	"", "", "", "icmp6", "none",
149/*60*/	"dst6",
150};
151
152static char *str_state[] = {
153	"larval",
154	"mature",
155	"dying",
156	"dead",
157};
158
159static struct val2str str_alg_auth[] = {
160	{ SADB_AALG_NONE, "none", },
161	{ SADB_AALG_MD5HMAC, "hmac-md5", },
162	{ SADB_AALG_SHA1HMAC, "hmac-sha1", },
163	{ SADB_X_AALG_MD5, "md5", },
164	{ SADB_X_AALG_SHA, "sha", },
165	{ SADB_X_AALG_NULL, "null", },
166#ifdef SADB_X_AALG_SHA2_256
167	{ SADB_X_AALG_SHA2_256, "hmac-sha2-256", },
168#endif
169#ifdef SADB_X_AALG_SHA2_384
170	{ SADB_X_AALG_SHA2_384, "hmac-sha2-384", },
171#endif
172#ifdef SADB_X_AALG_SHA2_512
173	{ SADB_X_AALG_SHA2_512, "hmac-sha2-512", },
174#endif
175#ifdef SADB_X_AALG_RIPEMD160HMAC
176	{ SADB_X_AALG_RIPEMD160HMAC, "hmac-ripemd160", },
177#endif
178	{ -1, NULL, },
179};
180
181static struct val2str str_alg_enc[] = {
182	{ SADB_EALG_NONE, "none", },
183	{ SADB_EALG_DESCBC, "des-cbc", },
184	{ SADB_EALG_3DESCBC, "3des-cbc", },
185	{ SADB_EALG_NULL, "null", },
186#ifdef SADB_X_EALG_RC5CBC
187	{ SADB_X_EALG_RC5CBC, "rc5-cbc", },
188#endif
189	{ SADB_X_EALG_CAST128CBC, "cast128-cbc", },
190	{ SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", },
191#ifdef SADB_X_EALG_RIJNDAELCBC
192	{ SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", },
193#endif
194#ifdef SADB_X_EALG_TWOFISHCBC
195	{ SADB_X_EALG_TWOFISHCBC, "twofish-cbc", },
196#endif
197	{ -1, NULL, },
198};
199
200static struct val2str str_alg_comp[] = {
201	{ SADB_X_CALG_NONE, "none", },
202	{ SADB_X_CALG_OUI, "oui", },
203	{ SADB_X_CALG_DEFLATE, "deflate", },
204	{ SADB_X_CALG_LZS, "lzs", },
205	{ -1, NULL, },
206};
207
208/*
209 * dump SADB_MSG formated.  For debugging, you should use kdebug_sadb().
210 */
211void
212pfkey_sadump(m)
213	struct sadb_msg *m;
214{
215	caddr_t mhp[SADB_EXT_MAX + 1];
216	struct sadb_sa *m_sa;
217	struct sadb_x_sa2 *m_sa2;
218	struct sadb_lifetime *m_lftc, *m_lfth, *m_lfts;
219	struct sadb_address *m_saddr, *m_daddr, *m_paddr;
220	struct sadb_key *m_auth, *m_enc;
221	struct sadb_ident *m_sid, *m_did;
222	struct sadb_sens *m_sens;
223
224	/* check pfkey message. */
225	if (pfkey_align(m, mhp)) {
226		printf("%s\n", ipsec_strerror());
227		return;
228	}
229	if (pfkey_check(mhp)) {
230		printf("%s\n", ipsec_strerror());
231		return;
232	}
233
234	m_sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
235	m_sa2 = (struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2];
236	m_lftc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT];
237	m_lfth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
238	m_lfts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT];
239	m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
240	m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
241	m_paddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_PROXY];
242	m_auth = (struct sadb_key *)mhp[SADB_EXT_KEY_AUTH];
243	m_enc = (struct sadb_key *)mhp[SADB_EXT_KEY_ENCRYPT];
244	m_sid = (struct sadb_ident *)mhp[SADB_EXT_IDENTITY_SRC];
245	m_did = (struct sadb_ident *)mhp[SADB_EXT_IDENTITY_DST];
246	m_sens = (struct sadb_sens *)mhp[SADB_EXT_SENSITIVITY];
247
248	/* source address */
249	if (m_saddr == NULL) {
250		printf("no ADDRESS_SRC extension.\n");
251		return;
252	}
253	printf("%s ", str_ipaddr((struct sockaddr *)(m_saddr + 1)));
254
255	/* destination address */
256	if (m_daddr == NULL) {
257		printf("no ADDRESS_DST extension.\n");
258		return;
259	}
260	printf("%s ", str_ipaddr((struct sockaddr *)(m_daddr + 1)));
261
262	/* SA type */
263	if (m_sa == NULL) {
264		printf("no SA extension.\n");
265		return;
266	}
267	if (m_sa2 == NULL) {
268		printf("no SA2 extension.\n");
269		return;
270	}
271	printf("\n\t");
272
273	GETMSGSTR(str_satype, m->sadb_msg_satype);
274
275	printf("mode=");
276	GETMSGSTR(str_mode, m_sa2->sadb_x_sa2_mode);
277
278	printf("spi=%u(0x%08x) reqid=%u(0x%08x)\n",
279		(u_int32_t)ntohl(m_sa->sadb_sa_spi),
280		(u_int32_t)ntohl(m_sa->sadb_sa_spi),
281		(u_int32_t)m_sa2->sadb_x_sa2_reqid,
282		(u_int32_t)m_sa2->sadb_x_sa2_reqid);
283
284	/* encryption key */
285	if (m->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) {
286		printf("\tC: ");
287		GETMSGV2S(str_alg_comp, m_sa->sadb_sa_encrypt);
288	} else if (m->sadb_msg_satype == SADB_SATYPE_ESP) {
289		if (m_enc != NULL) {
290			printf("\tE: ");
291			GETMSGV2S(str_alg_enc, m_sa->sadb_sa_encrypt);
292			ipsec_hexdump((caddr_t)m_enc + sizeof(*m_enc),
293				      m_enc->sadb_key_bits / 8);
294			printf("\n");
295		}
296	}
297
298	/* authentication key */
299	if (m_auth != NULL) {
300		printf("\tA: ");
301		GETMSGV2S(str_alg_auth, m_sa->sadb_sa_auth);
302		ipsec_hexdump((caddr_t)m_auth + sizeof(*m_auth),
303		              m_auth->sadb_key_bits / 8);
304		printf("\n");
305	}
306
307	/* replay windoe size & flags */
308	printf("\tseq=0x%08x replay=%u flags=0x%08x ",
309		m_sa2->sadb_x_sa2_sequence,
310		m_sa->sadb_sa_replay,
311		m_sa->sadb_sa_flags);
312
313	/* state */
314	printf("state=");
315	GETMSGSTR(str_state, m_sa->sadb_sa_state);
316	printf("\n");
317
318	/* lifetime */
319	if (m_lftc != NULL) {
320		time_t tmp_time = time(0);
321
322		printf("\tcreated: %s",
323			str_time(m_lftc->sadb_lifetime_addtime));
324		printf("\tcurrent: %s\n", str_time(tmp_time));
325		printf("\tdiff: %lu(s)",
326			(u_long)(m_lftc->sadb_lifetime_addtime == 0 ?
327			0 : (tmp_time - m_lftc->sadb_lifetime_addtime)));
328
329		printf("\thard: %lu(s)",
330			(u_long)(m_lfth == NULL ?
331			0 : m_lfth->sadb_lifetime_addtime));
332		printf("\tsoft: %lu(s)\n",
333			(u_long)(m_lfts == NULL ?
334			0 : m_lfts->sadb_lifetime_addtime));
335
336		printf("\tlast: %s",
337			str_time(m_lftc->sadb_lifetime_usetime));
338		printf("\thard: %lu(s)",
339			(u_long)(m_lfth == NULL ?
340			0 : m_lfth->sadb_lifetime_usetime));
341		printf("\tsoft: %lu(s)\n",
342			(u_long)(m_lfts == NULL ?
343			0 : m_lfts->sadb_lifetime_usetime));
344
345		str_lifetime_byte(m_lftc, "current");
346		str_lifetime_byte(m_lfth, "hard");
347		str_lifetime_byte(m_lfts, "soft");
348		printf("\n");
349
350		printf("\tallocated: %lu",
351			(unsigned long)m_lftc->sadb_lifetime_allocations);
352		printf("\thard: %lu",
353			(u_long)(m_lfth == NULL ?
354			0 : m_lfth->sadb_lifetime_allocations));
355		printf("\tsoft: %lu\n",
356			(u_long)(m_lfts == NULL ?
357			0 : m_lfts->sadb_lifetime_allocations));
358	}
359
360	printf("\tsadb_seq=%lu pid=%lu ",
361		(u_long)m->sadb_msg_seq,
362		(u_long)m->sadb_msg_pid);
363
364	/* XXX DEBUG */
365	printf("refcnt=%u\n", m->sadb_msg_reserved);
366
367	return;
368}
369
370void
371pfkey_spdump(m)
372	struct sadb_msg *m;
373{
374	char pbuf[NI_MAXSERV];
375	caddr_t mhp[SADB_EXT_MAX + 1];
376	struct sadb_address *m_saddr, *m_daddr;
377	struct sadb_x_policy *m_xpl;
378	struct sadb_lifetime *m_lft = NULL;
379	struct sockaddr *sa;
380	u_int16_t port;
381
382	/* check pfkey message. */
383	if (pfkey_align(m, mhp)) {
384		printf("%s\n", ipsec_strerror());
385		return;
386	}
387	if (pfkey_check(mhp)) {
388		printf("%s\n", ipsec_strerror());
389		return;
390	}
391
392	m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
393	m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
394	m_xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
395	m_lft = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
396
397	/* source address */
398	if (m_saddr == NULL) {
399		printf("no ADDRESS_SRC extension.\n");
400		return;
401	}
402	sa = (struct sockaddr *)(m_saddr + 1);
403	switch (sa->sa_family) {
404	case AF_INET:
405	case AF_INET6:
406		if (getnameinfo(sa, sa->sa_len, NULL, 0, pbuf, sizeof(pbuf),
407		    NI_NUMERICSERV) != 0)
408			port = 0;	/*XXX*/
409		else
410			port = atoi(pbuf);
411		printf("%s%s ", str_ipaddr(sa),
412			str_prefport(sa->sa_family,
413			    m_saddr->sadb_address_prefixlen, port));
414		break;
415	default:
416		printf("unknown-af ");
417		break;
418	}
419
420	/* destination address */
421	if (m_daddr == NULL) {
422		printf("no ADDRESS_DST extension.\n");
423		return;
424	}
425	sa = (struct sockaddr *)(m_daddr + 1);
426	switch (sa->sa_family) {
427	case AF_INET:
428	case AF_INET6:
429		if (getnameinfo(sa, sa->sa_len, NULL, 0, pbuf, sizeof(pbuf),
430		    NI_NUMERICSERV) != 0)
431			port = 0;	/*XXX*/
432		else
433			port = atoi(pbuf);
434		printf("%s%s ", str_ipaddr(sa),
435			str_prefport(sa->sa_family,
436			    m_daddr->sadb_address_prefixlen, port));
437		break;
438	default:
439		printf("unknown-af ");
440		break;
441	}
442
443	/* upper layer protocol */
444	if (m_saddr->sadb_address_proto != m_daddr->sadb_address_proto) {
445		printf("upper layer protocol mismatched.\n");
446		return;
447	}
448	if (m_saddr->sadb_address_proto == IPSEC_ULPROTO_ANY)
449		printf("any");
450	else
451		GETMSGSTR(str_upper, m_saddr->sadb_address_proto);
452
453	/* policy */
454    {
455	char *d_xpl;
456
457	if (m_xpl == NULL) {
458		printf("no X_POLICY extension.\n");
459		return;
460	}
461	d_xpl = ipsec_dump_policy((char *)m_xpl, "\n\t");
462
463	/* dump SPD */
464	printf("\n\t%s\n", d_xpl);
465	free(d_xpl);
466    }
467
468	/* lifetime */
469	if (m_lft) {
470		printf("\tlifetime:%lu validtime:%lu\n",
471			(u_long)m_lft->sadb_lifetime_addtime,
472			(u_long)m_lft->sadb_lifetime_usetime);
473	}
474
475	printf("\tspid=%ld seq=%ld pid=%ld\n",
476		(u_long)m_xpl->sadb_x_policy_id,
477		(u_long)m->sadb_msg_seq,
478		(u_long)m->sadb_msg_pid);
479
480	/* XXX TEST */
481	printf("\trefcnt=%u\n", m->sadb_msg_reserved);
482
483	return;
484}
485
486/*
487 * set "ipaddress" to buffer.
488 */
489static char *
490str_ipaddr(sa)
491	struct sockaddr *sa;
492{
493	static char buf[NI_MAXHOST];
494#ifdef NI_WITHSCOPEID
495	const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID;
496#else
497	const int niflag = NI_NUMERICHOST;
498#endif
499
500	if (sa == NULL)
501		return "";
502
503	if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0, niflag) == 0)
504		return buf;
505	return NULL;
506}
507
508/*
509 * set "/prefix[port number]" to buffer.
510 */
511static char *
512str_prefport(family, pref, port)
513	u_int family, pref, port;
514{
515	static char buf[128];
516	char prefbuf[128];
517	char portbuf[128];
518	int plen;
519
520	switch (family) {
521	case AF_INET:
522		plen = sizeof(struct in_addr) << 3;
523		break;
524	case AF_INET6:
525		plen = sizeof(struct in6_addr) << 3;
526		break;
527	default:
528		return "?";
529	}
530
531	if (pref == plen)
532		prefbuf[0] = '\0';
533	else
534		snprintf(prefbuf, sizeof(prefbuf), "/%u", pref);
535
536	if (port == IPSEC_PORT_ANY)
537		snprintf(portbuf, sizeof(portbuf), "[%s]", "any");
538	else
539		snprintf(portbuf, sizeof(portbuf), "[%u]", port);
540
541	snprintf(buf, sizeof(buf), "%s%s", prefbuf, portbuf);
542
543	return buf;
544}
545
546/*
547 * set "Mon Day Time Year" to buffer
548 */
549static char *
550str_time(t)
551	time_t t;
552{
553	static char buf[128];
554
555	if (t == 0) {
556		int i = 0;
557		for (;i < 20;) buf[i++] = ' ';
558	} else {
559		char *t0;
560		t0 = ctime(&t);
561		memcpy(buf, t0 + 4, 20);
562	}
563
564	buf[20] = '\0';
565
566	return(buf);
567}
568
569static void
570str_lifetime_byte(x, str)
571	struct sadb_lifetime *x;
572	char *str;
573{
574	double y;
575	char *unit;
576	int w;
577
578	if (x == NULL) {
579		printf("\t%s: 0(bytes)", str);
580		return;
581	}
582
583#if 0
584	if ((x->sadb_lifetime_bytes) / 1024 / 1024) {
585		y = (x->sadb_lifetime_bytes) * 1.0 / 1024 / 1024;
586		unit = "M";
587		w = 1;
588	} else if ((x->sadb_lifetime_bytes) / 1024) {
589		y = (x->sadb_lifetime_bytes) * 1.0 / 1024;
590		unit = "K";
591		w = 1;
592	} else {
593		y = (x->sadb_lifetime_bytes) * 1.0;
594		unit = "";
595		w = 0;
596	}
597#else
598	y = (x->sadb_lifetime_bytes) * 1.0;
599	unit = "";
600	w = 0;
601#endif
602	printf("\t%s: %.*f(%sbytes)", str, w, y, unit);
603}
604