• 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 <endian.h>
32 #include <linux/xfrm.h>
33 #include "utils.h"
34 #include "xfrm.h"
35 #include "ip_common.h"
36 
37 static void usage(void) __attribute__((noreturn));
38 
usage(void)39 static void usage(void)
40 {
41 	fprintf(stderr, "Usage: ip xfrm monitor [ all | LISTofOBJECTS ]\n");
42 	exit(-1);
43 }
44 
xfrm_acquire_print(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)45 static 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 
xfrm_state_flush_print(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)106 static 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 
xfrm_policy_flush_print(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)136 static 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 
xfrm_report_print(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)174 static 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 
xfrm_ae_flags_print(__u32 flags,void * arg)210 void 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 
xfrm_ae_print(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)225 static 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 
xfrm_accept_msg(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)253 static 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 
301 extern struct rtnl_handle rth;
302 
do_xfrm_monitor(int argc,char ** argv)303 int 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