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