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