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