xfrm_monitor.c revision 9107d119df662ac57d36b8a5a25deed2afb13278
1/* $USAGI: $ */
2
3/*
4 * Copyright (C)2005 USAGI/WIDE Project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20/*
21 * based on ipmonitor.c
22 */
23/*
24 * Authors:
25 *	Masahide NAKAMURA @USAGI
26 */
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <endian.h>
32#include <linux/xfrm.h>
33#include "utils.h"
34#include "xfrm.h"
35#include "ip_common.h"
36
37static void usage(void) __attribute__((noreturn));
38
39static void usage(void)
40{
41	fprintf(stderr, "Usage: ip xfrm monitor [ all | LISTofOBJECTS ]\n");
42	exit(-1);
43}
44
45static int xfrm_acquire_print(const struct sockaddr_nl *who,
46			      struct nlmsghdr *n, void *arg)
47{
48	FILE *fp = (FILE*)arg;
49	struct xfrm_user_acquire *xacq = NLMSG_DATA(n);
50	int len = n->nlmsg_len;
51	struct rtattr * tb[XFRMA_MAX+1];
52	__u16 family;
53
54	len -= NLMSG_LENGTH(sizeof(*xacq));
55	if (len < 0) {
56		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
57		return -1;
58	}
59
60	parse_rtattr(tb, XFRMA_MAX, XFRMACQ_RTA(xacq), len);
61
62	family = xacq->sel.family;
63	if (family == AF_UNSPEC)
64		family = xacq->policy.sel.family;
65	if (family == AF_UNSPEC)
66		family = preferred_family;
67
68	fprintf(fp, "acquire ");
69
70	fprintf(fp, "proto %s ", strxf_xfrmproto(xacq->id.proto));
71	if (show_stats > 0 || xacq->id.spi) {
72		__u32 spi = ntohl(xacq->id.spi);
73		fprintf(fp, "spi 0x%08x", spi);
74		if (show_stats > 0)
75			fprintf(fp, "(%u)", spi);
76		fprintf(fp, " ");
77	}
78	fprintf(fp, "%s", _SL_);
79
80	xfrm_selector_print(&xacq->sel, family, fp, "  sel ");
81
82	xfrm_policy_info_print(&xacq->policy, tb, fp, "    ", "  policy ");
83
84	if (show_stats > 0)
85		fprintf(fp, "  seq 0x%08u ", xacq->seq);
86	if (show_stats > 0) {
87		fprintf(fp, "%s-mask %s ",
88			strxf_algotype(XFRMA_ALG_CRYPT),
89			strxf_mask32(xacq->ealgos));
90		fprintf(fp, "%s-mask %s ",
91			strxf_algotype(XFRMA_ALG_AUTH),
92			strxf_mask32(xacq->aalgos));
93		fprintf(fp, "%s-mask %s",
94			strxf_algotype(XFRMA_ALG_COMP),
95			strxf_mask32(xacq->calgos));
96	}
97	fprintf(fp, "%s", _SL_);
98
99	if (oneline)
100		fprintf(fp, "\n");
101	fflush(fp);
102
103	return 0;
104}
105
106static int xfrm_state_flush_print(const struct sockaddr_nl *who,
107				  struct nlmsghdr *n, void *arg)
108{
109	FILE *fp = (FILE*)arg;
110	struct xfrm_usersa_flush *xsf = NLMSG_DATA(n);
111	int len = n->nlmsg_len;
112	const char *str;
113
114	len -= NLMSG_SPACE(sizeof(*xsf));
115	if (len < 0) {
116		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
117		return -1;
118	}
119
120	fprintf(fp, "Flushed state ");
121
122	str = strxf_xfrmproto(xsf->proto);
123	if (str)
124		fprintf(fp, "proto %s", str);
125	else
126		fprintf(fp, "proto %u", xsf->proto);
127	fprintf(fp, "%s", _SL_);
128
129	if (oneline)
130		fprintf(fp, "\n");
131	fflush(fp);
132
133	return 0;
134}
135
136static int xfrm_policy_flush_print(const struct sockaddr_nl *who,
137				   struct nlmsghdr *n, void *arg)
138{
139	struct rtattr * tb[XFRMA_MAX+1];
140	FILE *fp = (FILE*)arg;
141	int len = n->nlmsg_len;
142
143	len -= NLMSG_SPACE(0);
144	if (len < 0) {
145		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
146		return -1;
147	}
148
149	fprintf(fp, "Flushed policy ");
150
151	parse_rtattr(tb, XFRMA_MAX, NLMSG_DATA(n), len);
152
153	if (tb[XFRMA_POLICY_TYPE]) {
154		struct xfrm_userpolicy_type *upt;
155
156		fprintf(fp, "ptype ");
157
158		if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt))
159			fprintf(fp, "(ERROR truncated)");
160
161		upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]);
162		fprintf(fp, "%s ", strxf_ptype(upt->type));
163	}
164
165	fprintf(fp, "%s", _SL_);
166
167	if (oneline)
168		fprintf(fp, "\n");
169	fflush(fp);
170
171	return 0;
172}
173
174static int xfrm_report_print(const struct sockaddr_nl *who,
175			     struct nlmsghdr *n, void *arg)
176{
177	FILE *fp = (FILE*)arg;
178	struct xfrm_user_report *xrep = NLMSG_DATA(n);
179	int len = n->nlmsg_len;
180	struct rtattr * tb[XFRMA_MAX+1];
181	__u16 family;
182
183	len -= NLMSG_LENGTH(sizeof(*xrep));
184	if (len < 0) {
185		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
186		return -1;
187	}
188
189	family = xrep->sel.family;
190	if (family == AF_UNSPEC)
191		family = preferred_family;
192
193	fprintf(fp, "report ");
194
195	fprintf(fp, "proto %s ", strxf_xfrmproto(xrep->proto));
196	fprintf(fp, "%s", _SL_);
197
198	xfrm_selector_print(&xrep->sel, family, fp, "  sel ");
199
200	parse_rtattr(tb, XFRMA_MAX, XFRMREP_RTA(xrep), len);
201
202	xfrm_xfrma_print(tb, family, fp, "  ");
203
204	if (oneline)
205		fprintf(fp, "\n");
206
207	return 0;
208}
209
210void xfrm_ae_flags_print(__u32 flags, void *arg)
211{
212	FILE *fp = (FILE*)arg;
213	fprintf(fp, " (0x%x) ", flags);
214	if (!flags)
215		return;
216	if (flags & XFRM_AE_CR)
217		fprintf(fp, " replay update ");
218	if (flags & XFRM_AE_CE)
219		fprintf(fp, " timer expired ");
220	if (flags & XFRM_AE_CU)
221		fprintf(fp, " policy updated ");
222
223}
224
225static int xfrm_ae_print(const struct sockaddr_nl *who,
226			     struct nlmsghdr *n, void *arg)
227{
228	FILE *fp = (FILE*)arg;
229	struct xfrm_aevent_id *id = NLMSG_DATA(n);
230	char abuf[256];
231
232	fprintf(fp, "Async event ");
233	xfrm_ae_flags_print(id->flags, arg);
234	fprintf(fp,"\n\t");
235	memset(abuf, '\0', sizeof(abuf));
236	fprintf(fp, "src %s ", rt_addr_n2a(id->sa_id.family,
237		sizeof(id->saddr), &id->saddr,
238		abuf, sizeof(abuf)));
239	memset(abuf, '\0', sizeof(abuf));
240	fprintf(fp, "dst %s ", rt_addr_n2a(id->sa_id.family,
241		sizeof(id->sa_id.daddr), &id->sa_id.daddr,
242		abuf, sizeof(abuf)));
243	fprintf(fp, " reqid 0x%x", id->reqid);
244	fprintf(fp, " protocol %s ", strxf_proto(id->sa_id.proto));
245	fprintf(fp, " SPI 0x%x", ntohl(id->sa_id.spi));
246
247	fprintf(fp, "\n");
248	fflush(fp);
249
250	return 0;
251}
252
253static int xfrm_accept_msg(const struct sockaddr_nl *who,
254			   struct nlmsghdr *n, void *arg)
255{
256	FILE *fp = (FILE*)arg;
257
258	if (timestamp)
259		print_timestamp(fp);
260
261	switch (n->nlmsg_type) {
262	case XFRM_MSG_NEWSA:
263	case XFRM_MSG_DELSA:
264	case XFRM_MSG_UPDSA:
265	case XFRM_MSG_EXPIRE:
266		xfrm_state_print(who, n, arg);
267		return 0;
268	case XFRM_MSG_NEWPOLICY:
269	case XFRM_MSG_DELPOLICY:
270	case XFRM_MSG_UPDPOLICY:
271	case XFRM_MSG_POLEXPIRE:
272		xfrm_policy_print(who, n, arg);
273		return 0;
274	case XFRM_MSG_ACQUIRE:
275		xfrm_acquire_print(who, n, arg);
276		return 0;
277	case XFRM_MSG_FLUSHSA:
278		xfrm_state_flush_print(who, n, arg);
279		return 0;
280	case XFRM_MSG_FLUSHPOLICY:
281		xfrm_policy_flush_print(who, n, arg);
282		return 0;
283	case XFRM_MSG_REPORT:
284		xfrm_report_print(who, n, arg);
285		return 0;
286	case XFRM_MSG_NEWAE:
287		xfrm_ae_print(who, n, arg);
288		return 0;
289	default:
290		break;
291	}
292
293	if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP &&
294	    n->nlmsg_type != NLMSG_DONE) {
295		fprintf(fp, "Unknown message: %08d 0x%08x 0x%08x\n",
296			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
297	}
298	return 0;
299}
300
301extern struct rtnl_handle rth;
302
303int do_xfrm_monitor(int argc, char **argv)
304{
305	char *file = NULL;
306	unsigned groups = ~((unsigned)0); /* XXX */
307	int lacquire=0;
308	int lexpire=0;
309	int laevent=0;
310	int lpolicy=0;
311	int lsa=0;
312	int lreport=0;
313
314	rtnl_close(&rth);
315
316	while (argc > 0) {
317		if (matches(*argv, "file") == 0) {
318			NEXT_ARG();
319			file = *argv;
320		} else if (matches(*argv, "acquire") == 0) {
321			lacquire=1;
322			groups = 0;
323		} else if (matches(*argv, "expire") == 0) {
324			lexpire=1;
325			groups = 0;
326		} else if (matches(*argv, "SA") == 0) {
327			lsa=1;
328			groups = 0;
329		} else if (matches(*argv, "aevent") == 0) {
330			laevent=1;
331			groups = 0;
332		} else if (matches(*argv, "policy") == 0) {
333			lpolicy=1;
334			groups = 0;
335		} else if (matches(*argv, "report") == 0) {
336			lreport=1;
337			groups = 0;
338		} else if (matches(*argv, "help") == 0) {
339			usage();
340		} else {
341			fprintf(stderr, "Argument \"%s\" is unknown, try \"ip xfrm monitor help\".\n", *argv);
342			exit(-1);
343		}
344		argc--;	argv++;
345	}
346
347	if (lacquire)
348		groups |= nl_mgrp(XFRMNLGRP_ACQUIRE);
349	if (lexpire)
350		groups |= nl_mgrp(XFRMNLGRP_EXPIRE);
351	if (lsa)
352		groups |= nl_mgrp(XFRMNLGRP_SA);
353	if (lpolicy)
354		groups |= nl_mgrp(XFRMNLGRP_POLICY);
355	if (laevent)
356		groups |= nl_mgrp(XFRMNLGRP_AEVENTS);
357	if (lreport)
358		groups |= nl_mgrp(XFRMNLGRP_REPORT);
359
360	if (file) {
361		FILE *fp;
362		fp = fopen(file, "r");
363		if (fp == NULL) {
364			perror("Cannot fopen");
365			exit(-1);
366		}
367		return rtnl_from_file(fp, xfrm_accept_msg, (void*)stdout);
368	}
369
370	//ll_init_map(&rth);
371
372	if (rtnl_open_byproto(&rth, groups, NETLINK_XFRM) < 0)
373		exit(1);
374
375	if (rtnl_listen(&rth, xfrm_accept_msg, (void*)stdout) < 0)
376		exit(2);
377
378	return 0;
379}
380