]> git.proxmox.com Git - mirror_iproute2.git/blob - ip/xfrm_monitor.c
lwtunnel: add support for rpl segment routing
[mirror_iproute2.git] / ip / xfrm_monitor.c
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, see <http://www.gnu.org/licenses>.
18 */
19 /*
20 * based on ipmonitor.c
21 */
22 /*
23 * Authors:
24 * Masahide NAKAMURA @USAGI
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
36 static void usage(void) __attribute__((noreturn));
37 static int listen_all_nsid;
38 static bool nokeys;
39
40 static 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
48 static 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
109 static 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
138 static 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
175 static 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
210 static 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
226 static 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
237 static 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
256 static 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
261 static 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
280 static 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
338 extern struct rtnl_handle rth;
339
340 int do_xfrm_monitor(int argc, char **argv)
341 {
342 char *file = NULL;
343 unsigned int groups = ~((unsigned)0); /* XXX */
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 /* fall out */
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 }