1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <netinet/in.h>
31
32#include "utils.h"
33#include "xfrm.h"
34#include "ip_common.h"
35
36static void usage(void) __attribute__((noreturn));
37static int listen_all_nsid;
38static bool nokeys;
39
40static void usage(void)
41{
42 fprintf(stderr,
43 "Usage: ip xfrm monitor [ nokeys ] [ all-nsid ] [ all | OBJECTS | help ]\n"
44 "OBJECTS := { acquire | expire | SA | aevent | policy | report }\n");
45 exit(-1);
46}
47
48static int xfrm_acquire_print(struct nlmsghdr *n, void *arg)
49{
50 FILE *fp = (FILE *)arg;
51 struct xfrm_user_acquire *xacq = NLMSG_DATA(n);
52 int len = n->nlmsg_len;
53 struct rtattr *tb[XFRMA_MAX+1];
54 __u16 family;
55
56 len -= NLMSG_LENGTH(sizeof(*xacq));
57 if (len < 0) {
58 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
59 return -1;
60 }
61
62 parse_rtattr(tb, XFRMA_MAX, XFRMACQ_RTA(xacq), len);
63
64 family = xacq->sel.family;
65 if (family == AF_UNSPEC)
66 family = xacq->policy.sel.family;
67 if (family == AF_UNSPEC)
68 family = preferred_family;
69
70 fprintf(fp, "acquire ");
71
72 fprintf(fp, "proto %s ", strxf_xfrmproto(xacq->id.proto));
73 if (show_stats > 0 || xacq->id.spi) {
74 __u32 spi = ntohl(xacq->id.spi);
75
76 fprintf(fp, "spi 0x%08x", spi);
77 if (show_stats > 0)
78 fprintf(fp, "(%u)", spi);
79 fprintf(fp, " ");
80 }
81 fprintf(fp, "%s", _SL_);
82
83 xfrm_selector_print(&xacq->sel, family, fp, " sel ");
84
85 xfrm_policy_info_print(&xacq->policy, tb, fp, " ", " policy ");
86
87 if (show_stats > 0)
88 fprintf(fp, " seq 0x%08u ", xacq->seq);
89 if (show_stats > 0) {
90 fprintf(fp, "%s-mask %s ",
91 strxf_algotype(XFRMA_ALG_CRYPT),
92 strxf_mask32(xacq->ealgos));
93 fprintf(fp, "%s-mask %s ",
94 strxf_algotype(XFRMA_ALG_AUTH),
95 strxf_mask32(xacq->aalgos));
96 fprintf(fp, "%s-mask %s",
97 strxf_algotype(XFRMA_ALG_COMP),
98 strxf_mask32(xacq->calgos));
99 }
100 fprintf(fp, "%s", _SL_);
101
102 if (oneline)
103 fprintf(fp, "\n");
104 fflush(fp);
105
106 return 0;
107}
108
109static int xfrm_state_flush_print(struct nlmsghdr *n, void *arg)
110{
111 FILE *fp = (FILE *)arg;
112 struct xfrm_usersa_flush *xsf = NLMSG_DATA(n);
113 int len = n->nlmsg_len;
114 const char *str;
115
116 len -= NLMSG_SPACE(sizeof(*xsf));
117 if (len < 0) {
118 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
119 return -1;
120 }
121
122 fprintf(fp, "Flushed state ");
123
124 str = strxf_xfrmproto(xsf->proto);
125 if (str)
126 fprintf(fp, "proto %s", str);
127 else
128 fprintf(fp, "proto %u", xsf->proto);
129 fprintf(fp, "%s", _SL_);
130
131 if (oneline)
132 fprintf(fp, "\n");
133 fflush(fp);
134
135 return 0;
136}
137
138static int xfrm_policy_flush_print(struct nlmsghdr *n, void *arg)
139{
140 struct rtattr *tb[XFRMA_MAX+1];
141 FILE *fp = (FILE *)arg;
142 int len = n->nlmsg_len;
143
144 len -= NLMSG_SPACE(0);
145 if (len < 0) {
146 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
147 return -1;
148 }
149
150 fprintf(fp, "Flushed policy ");
151
152 parse_rtattr(tb, XFRMA_MAX, NLMSG_DATA(n), len);
153
154 if (tb[XFRMA_POLICY_TYPE]) {
155 struct xfrm_userpolicy_type *upt;
156
157 fprintf(fp, "ptype ");
158
159 if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt))
160 fprintf(fp, "(ERROR truncated)");
161
162 upt = RTA_DATA(tb[XFRMA_POLICY_TYPE]);
163 fprintf(fp, "%s ", strxf_ptype(upt->type));
164 }
165
166 fprintf(fp, "%s", _SL_);
167
168 if (oneline)
169 fprintf(fp, "\n");
170 fflush(fp);
171
172 return 0;
173}
174
175static int xfrm_report_print(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, " ", nokeys);
203
204 if (oneline)
205 fprintf(fp, "\n");
206
207 return 0;
208}
209
210static void xfrm_ae_flags_print(__u32 flags, void *arg)
211{
212 FILE *fp = (FILE *)arg;
213
214 fprintf(fp, " (0x%x) ", flags);
215 if (!flags)
216 return;
217 if (flags & XFRM_AE_CR)
218 fprintf(fp, " replay update ");
219 if (flags & XFRM_AE_CE)
220 fprintf(fp, " timer expired ");
221 if (flags & XFRM_AE_CU)
222 fprintf(fp, " policy updated ");
223
224}
225
226static void xfrm_usersa_print(const struct xfrm_usersa_id *sa_id, __u32 reqid, FILE *fp)
227{
228 fprintf(fp, "dst %s ",
229 rt_addr_n2a(sa_id->family, sizeof(sa_id->daddr), &sa_id->daddr));
230
231 fprintf(fp, " reqid 0x%x", reqid);
232
233 fprintf(fp, " protocol %s ", strxf_proto(sa_id->proto));
234 fprintf(fp, " SPI 0x%x", ntohl(sa_id->spi));
235}
236
237static int xfrm_ae_print(struct nlmsghdr *n, void *arg)
238{
239 FILE *fp = (FILE *)arg;
240 struct xfrm_aevent_id *id = NLMSG_DATA(n);
241
242 fprintf(fp, "Async event ");
243 xfrm_ae_flags_print(id->flags, arg);
244 fprintf(fp, "\n\t");
245 fprintf(fp, "src %s ", rt_addr_n2a(id->sa_id.family,
246 sizeof(id->saddr), &id->saddr));
247
248 xfrm_usersa_print(&id->sa_id, id->reqid, fp);
249
250 fprintf(fp, "\n");
251 fflush(fp);
252
253 return 0;
254}
255
256static void xfrm_print_addr(FILE *fp, int family, xfrm_address_t *a)
257{
258 fprintf(fp, "%s", rt_addr_n2a(family, sizeof(*a), a));
259}
260
261static int xfrm_mapping_print(struct nlmsghdr *n, void *arg)
262{
263 FILE *fp = (FILE *)arg;
264 struct xfrm_user_mapping *map = NLMSG_DATA(n);
265
266 fprintf(fp, "Mapping change ");
267 xfrm_print_addr(fp, map->id.family, &map->old_saddr);
268
269 fprintf(fp, ":%d -> ", ntohs(map->old_sport));
270 xfrm_print_addr(fp, map->id.family, &map->new_saddr);
271 fprintf(fp, ":%d\n\t", ntohs(map->new_sport));
272
273 xfrm_usersa_print(&map->id, map->reqid, fp);
274
275 fprintf(fp, "\n");
276 fflush(fp);
277 return 0;
278}
279
280static int xfrm_accept_msg(struct rtnl_ctrl_data *ctrl,
281 struct nlmsghdr *n, void *arg)
282{
283 FILE *fp = (FILE *)arg;
284
285 if (timestamp)
286 print_timestamp(fp);
287
288 if (listen_all_nsid) {
289 if (ctrl == NULL || ctrl->nsid < 0)
290 fprintf(fp, "[nsid current]");
291 else
292 fprintf(fp, "[nsid %d]", ctrl->nsid);
293 }
294
295 switch (n->nlmsg_type) {
296 case XFRM_MSG_NEWSA:
297 case XFRM_MSG_DELSA:
298 case XFRM_MSG_UPDSA:
299 case XFRM_MSG_EXPIRE:
300 xfrm_state_print(n, arg);
301 return 0;
302 case XFRM_MSG_NEWPOLICY:
303 case XFRM_MSG_DELPOLICY:
304 case XFRM_MSG_UPDPOLICY:
305 case XFRM_MSG_POLEXPIRE:
306 xfrm_policy_print(n, arg);
307 return 0;
308 case XFRM_MSG_ACQUIRE:
309 xfrm_acquire_print(n, arg);
310 return 0;
311 case XFRM_MSG_FLUSHSA:
312 xfrm_state_flush_print(n, arg);
313 return 0;
314 case XFRM_MSG_FLUSHPOLICY:
315 xfrm_policy_flush_print(n, arg);
316 return 0;
317 case XFRM_MSG_REPORT:
318 xfrm_report_print(n, arg);
319 return 0;
320 case XFRM_MSG_NEWAE:
321 xfrm_ae_print(n, arg);
322 return 0;
323 case XFRM_MSG_MAPPING:
324 xfrm_mapping_print(n, arg);
325 return 0;
326 default:
327 break;
328 }
329
330 if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP &&
331 n->nlmsg_type != NLMSG_DONE) {
332 fprintf(fp, "Unknown message: %08d 0x%08x 0x%08x\n",
333 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
334 }
335 return 0;
336}
337
338extern struct rtnl_handle rth;
339
340int do_xfrm_monitor(int argc, char **argv)
341{
342 char *file = NULL;
343 unsigned int groups = ~((unsigned)0);
344 int lacquire = 0;
345 int lexpire = 0;
346 int laevent = 0;
347 int lpolicy = 0;
348 int lsa = 0;
349 int lreport = 0;
350
351 rtnl_close(&rth);
352
353 while (argc > 0) {
354 if (matches(*argv, "file") == 0) {
355 NEXT_ARG();
356 file = *argv;
357 } else if (strcmp(*argv, "nokeys") == 0) {
358 nokeys = true;
359 } else if (strcmp(*argv, "all") == 0) {
360
361 } else if (matches(*argv, "all-nsid") == 0) {
362 listen_all_nsid = 1;
363 } else if (matches(*argv, "acquire") == 0) {
364 lacquire = 1;
365 groups = 0;
366 } else if (matches(*argv, "expire") == 0) {
367 lexpire = 1;
368 groups = 0;
369 } else if (matches(*argv, "SA") == 0) {
370 lsa = 1;
371 groups = 0;
372 } else if (matches(*argv, "aevent") == 0) {
373 laevent = 1;
374 groups = 0;
375 } else if (matches(*argv, "policy") == 0) {
376 lpolicy = 1;
377 groups = 0;
378 } else if (matches(*argv, "report") == 0) {
379 lreport = 1;
380 groups = 0;
381 } else if (matches(*argv, "help") == 0) {
382 usage();
383 } else {
384 fprintf(stderr, "Argument \"%s\" is unknown, try \"ip xfrm monitor help\".\n", *argv);
385 exit(-1);
386 }
387 argc--; argv++;
388 }
389
390 if (lacquire)
391 groups |= nl_mgrp(XFRMNLGRP_ACQUIRE);
392 if (lexpire)
393 groups |= nl_mgrp(XFRMNLGRP_EXPIRE);
394 if (lsa)
395 groups |= nl_mgrp(XFRMNLGRP_SA);
396 if (lpolicy)
397 groups |= nl_mgrp(XFRMNLGRP_POLICY);
398 if (laevent)
399 groups |= nl_mgrp(XFRMNLGRP_AEVENTS);
400 if (lreport)
401 groups |= nl_mgrp(XFRMNLGRP_REPORT);
402
403 if (file) {
404 FILE *fp;
405 int err;
406
407 fp = fopen(file, "r");
408 if (fp == NULL) {
409 perror("Cannot fopen");
410 exit(-1);
411 }
412 err = rtnl_from_file(fp, xfrm_accept_msg, stdout);
413 fclose(fp);
414 return err;
415 }
416
417 if (rtnl_open_byproto(&rth, groups, NETLINK_XFRM) < 0)
418 exit(1);
419 if (listen_all_nsid && rtnl_listen_all_nsid(&rth) < 0)
420 exit(1);
421
422 if (rtnl_listen(&rth, xfrm_accept_msg, (void *)stdout) < 0)
423 exit(2);
424
425 return 0;
426}
427