xref: /freebsd/lib/libipsec/pfkey_dump.c (revision b601c69bdbe8755d26570261d7fd4c02ee4eff74)
1 /*	$FreeBSD$	*/
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) \
56 do { \
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 
66 static char *str_ipaddr __P((struct sockaddr *));
67 static char *str_prefport __P((u_int, u_int, u_int));
68 static char *str_time __P((time_t));
69 static void str_lifetime_byte __P((struct sadb_lifetime *, char *));
70 
71 /*
72  * Must to be re-written about following strings.
73  */
74 static 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 
87 static char *_str_mode[] = {
88 	"any",
89 	"transport",
90 	"tunnel",
91 };
92 
93 static 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 
109 static char *_str_state[] = {
110 	"larval",
111 	"mature",
112 	"dying",
113 	"dead",
114 };
115 
116 static char *_str_alg_auth[] = {
117 	"none",
118 	"hmac-md5",
119 	"hmac-sha1",
120 	"md5",
121 	"sha",
122 	"null",
123 };
124 
125 static 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 
135 static 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  */
145 void
146 pfkey_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 
302 void
303 pfkey_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  */
412 static char *
413 str_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  */
434 static char *
435 str_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  */
472 static char *
473 str_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 
492 static void
493 str_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