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