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 int listen_all_nsid; 38 39 static void usage(void) 40 { 41 fprintf(stderr, "Usage: ip xfrm monitor [all-nsid] [ all | OBJECTS | help ]\n"); 42 fprintf(stderr, "OBJECTS := { acquire | expire | SA | aevent | policy | report }\n"); 43 exit(-1); 44 } 45 46 static int xfrm_acquire_print(const struct sockaddr_nl *who, 47 struct nlmsghdr *n, void *arg) 48 { 49 FILE *fp = (FILE*)arg; 50 struct xfrm_user_acquire *xacq = NLMSG_DATA(n); 51 int len = n->nlmsg_len; 52 struct rtattr * tb[XFRMA_MAX+1]; 53 __u16 family; 54 55 len -= NLMSG_LENGTH(sizeof(*xacq)); 56 if (len < 0) { 57 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 58 return -1; 59 } 60 61 parse_rtattr(tb, XFRMA_MAX, XFRMACQ_RTA(xacq), len); 62 63 family = xacq->sel.family; 64 if (family == AF_UNSPEC) 65 family = xacq->policy.sel.family; 66 if (family == AF_UNSPEC) 67 family = preferred_family; 68 69 fprintf(fp, "acquire "); 70 71 fprintf(fp, "proto %s ", strxf_xfrmproto(xacq->id.proto)); 72 if (show_stats > 0 || xacq->id.spi) { 73 __u32 spi = ntohl(xacq->id.spi); 74 fprintf(fp, "spi 0x%08x", spi); 75 if (show_stats > 0) 76 fprintf(fp, "(%u)", spi); 77 fprintf(fp, " "); 78 } 79 fprintf(fp, "%s", _SL_); 80 81 xfrm_selector_print(&xacq->sel, family, fp, " sel "); 82 83 xfrm_policy_info_print(&xacq->policy, tb, fp, " ", " policy "); 84 85 if (show_stats > 0) 86 fprintf(fp, " seq 0x%08u ", xacq->seq); 87 if (show_stats > 0) { 88 fprintf(fp, "%s-mask %s ", 89 strxf_algotype(XFRMA_ALG_CRYPT), 90 strxf_mask32(xacq->ealgos)); 91 fprintf(fp, "%s-mask %s ", 92 strxf_algotype(XFRMA_ALG_AUTH), 93 strxf_mask32(xacq->aalgos)); 94 fprintf(fp, "%s-mask %s", 95 strxf_algotype(XFRMA_ALG_COMP), 96 strxf_mask32(xacq->calgos)); 97 } 98 fprintf(fp, "%s", _SL_); 99 100 if (oneline) 101 fprintf(fp, "\n"); 102 fflush(fp); 103 104 return 0; 105 } 106 107 static int xfrm_state_flush_print(const struct sockaddr_nl *who, 108 struct nlmsghdr *n, void *arg) 109 { 110 FILE *fp = (FILE*)arg; 111 struct xfrm_usersa_flush *xsf = NLMSG_DATA(n); 112 int len = n->nlmsg_len; 113 const char *str; 114 115 len -= NLMSG_SPACE(sizeof(*xsf)); 116 if (len < 0) { 117 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 118 return -1; 119 } 120 121 fprintf(fp, "Flushed state "); 122 123 str = strxf_xfrmproto(xsf->proto); 124 if (str) 125 fprintf(fp, "proto %s", str); 126 else 127 fprintf(fp, "proto %u", xsf->proto); 128 fprintf(fp, "%s", _SL_); 129 130 if (oneline) 131 fprintf(fp, "\n"); 132 fflush(fp); 133 134 return 0; 135 } 136 137 static int xfrm_policy_flush_print(const struct sockaddr_nl *who, 138 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 = (struct xfrm_userpolicy_type *)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(const struct sockaddr_nl *who, 176 struct nlmsghdr *n, void *arg) 177 { 178 FILE *fp = (FILE*)arg; 179 struct xfrm_user_report *xrep = NLMSG_DATA(n); 180 int len = n->nlmsg_len; 181 struct rtattr * tb[XFRMA_MAX+1]; 182 __u16 family; 183 184 len -= NLMSG_LENGTH(sizeof(*xrep)); 185 if (len < 0) { 186 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 187 return -1; 188 } 189 190 family = xrep->sel.family; 191 if (family == AF_UNSPEC) 192 family = preferred_family; 193 194 fprintf(fp, "report "); 195 196 fprintf(fp, "proto %s ", strxf_xfrmproto(xrep->proto)); 197 fprintf(fp, "%s", _SL_); 198 199 xfrm_selector_print(&xrep->sel, family, fp, " sel "); 200 201 parse_rtattr(tb, XFRMA_MAX, XFRMREP_RTA(xrep), len); 202 203 xfrm_xfrma_print(tb, family, fp, " "); 204 205 if (oneline) 206 fprintf(fp, "\n"); 207 208 return 0; 209 } 210 211 static void xfrm_ae_flags_print(__u32 flags, void *arg) 212 { 213 FILE *fp = (FILE*)arg; 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 char buf[256]; 229 230 buf[0] = 0; 231 fprintf(fp, "dst %s ", 232 rt_addr_n2a(sa_id->family, sizeof(sa_id->daddr), &sa_id->daddr, 233 buf, sizeof(buf))); 234 235 fprintf(fp, " reqid 0x%x", reqid); 236 237 fprintf(fp, " protocol %s ", strxf_proto(sa_id->proto)); 238 fprintf(fp, " SPI 0x%x", ntohl(sa_id->spi)); 239 } 240 241 static int xfrm_ae_print(const struct sockaddr_nl *who, 242 struct nlmsghdr *n, void *arg) 243 { 244 FILE *fp = (FILE*)arg; 245 struct xfrm_aevent_id *id = NLMSG_DATA(n); 246 char abuf[256]; 247 248 fprintf(fp, "Async event "); 249 xfrm_ae_flags_print(id->flags, arg); 250 fprintf(fp,"\n\t"); 251 memset(abuf, '\0', sizeof(abuf)); 252 fprintf(fp, "src %s ", rt_addr_n2a(id->sa_id.family, 253 sizeof(id->saddr), &id->saddr, 254 abuf, sizeof(abuf))); 255 256 xfrm_usersa_print(&id->sa_id, id->reqid, fp); 257 258 fprintf(fp, "\n"); 259 fflush(fp); 260 261 return 0; 262 } 263 264 static void xfrm_print_addr(FILE *fp, int family, xfrm_address_t *a) 265 { 266 char buf[256]; 267 268 buf[0] = 0; 269 fprintf(fp, "%s", rt_addr_n2a(family, sizeof(*a), a, buf, sizeof(buf))); 270 } 271 272 static int xfrm_mapping_print(const struct sockaddr_nl *who, 273 struct nlmsghdr *n, void *arg) 274 { 275 FILE *fp = (FILE*)arg; 276 struct xfrm_user_mapping *map = NLMSG_DATA(n); 277 278 fprintf(fp, "Mapping change "); 279 xfrm_print_addr(fp, map->id.family, &map->old_saddr); 280 281 fprintf(fp, ":%d -> ", ntohs(map->old_sport)); 282 xfrm_print_addr(fp, map->id.family, &map->new_saddr); 283 fprintf(fp, ":%d\n\t", ntohs(map->new_sport)); 284 285 xfrm_usersa_print(&map->id, map->reqid, fp); 286 287 fprintf(fp, "\n"); 288 fflush(fp); 289 return 0; 290 } 291 292 static int xfrm_accept_msg(const struct sockaddr_nl *who, 293 struct rtnl_ctrl_data *ctrl, 294 struct nlmsghdr *n, void *arg) 295 { 296 FILE *fp = (FILE*)arg; 297 298 if (timestamp) 299 print_timestamp(fp); 300 301 if (listen_all_nsid) { 302 if (ctrl == NULL || ctrl->nsid < 0) 303 fprintf(fp, "[nsid current]"); 304 else 305 fprintf(fp, "[nsid %d]", ctrl->nsid); 306 } 307 308 switch (n->nlmsg_type) { 309 case XFRM_MSG_NEWSA: 310 case XFRM_MSG_DELSA: 311 case XFRM_MSG_UPDSA: 312 case XFRM_MSG_EXPIRE: 313 xfrm_state_print(who, n, arg); 314 return 0; 315 case XFRM_MSG_NEWPOLICY: 316 case XFRM_MSG_DELPOLICY: 317 case XFRM_MSG_UPDPOLICY: 318 case XFRM_MSG_POLEXPIRE: 319 xfrm_policy_print(who, n, arg); 320 return 0; 321 case XFRM_MSG_ACQUIRE: 322 xfrm_acquire_print(who, n, arg); 323 return 0; 324 case XFRM_MSG_FLUSHSA: 325 xfrm_state_flush_print(who, n, arg); 326 return 0; 327 case XFRM_MSG_FLUSHPOLICY: 328 xfrm_policy_flush_print(who, n, arg); 329 return 0; 330 case XFRM_MSG_REPORT: 331 xfrm_report_print(who, n, arg); 332 return 0; 333 case XFRM_MSG_NEWAE: 334 xfrm_ae_print(who, n, arg); 335 return 0; 336 case XFRM_MSG_MAPPING: 337 xfrm_mapping_print(who, n, arg); 338 return 0; 339 default: 340 break; 341 } 342 343 if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP && 344 n->nlmsg_type != NLMSG_DONE) { 345 fprintf(fp, "Unknown message: %08d 0x%08x 0x%08x\n", 346 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); 347 } 348 return 0; 349 } 350 351 extern struct rtnl_handle rth; 352 353 int do_xfrm_monitor(int argc, char **argv) 354 { 355 char *file = NULL; 356 unsigned groups = ~((unsigned)0); /* XXX */ 357 int lacquire=0; 358 int lexpire=0; 359 int laevent=0; 360 int lpolicy=0; 361 int lsa=0; 362 int lreport=0; 363 364 rtnl_close(&rth); 365 366 while (argc > 0) { 367 if (matches(*argv, "file") == 0) { 368 NEXT_ARG(); 369 file = *argv; 370 } else if (matches(*argv, "all-nsid") == 0) { 371 listen_all_nsid = 1; 372 } else if (matches(*argv, "acquire") == 0) { 373 lacquire=1; 374 groups = 0; 375 } else if (matches(*argv, "expire") == 0) { 376 lexpire=1; 377 groups = 0; 378 } else if (matches(*argv, "SA") == 0) { 379 lsa=1; 380 groups = 0; 381 } else if (matches(*argv, "aevent") == 0) { 382 laevent=1; 383 groups = 0; 384 } else if (matches(*argv, "policy") == 0) { 385 lpolicy=1; 386 groups = 0; 387 } else if (matches(*argv, "report") == 0) { 388 lreport=1; 389 groups = 0; 390 } else if (matches(*argv, "help") == 0) { 391 usage(); 392 } else if (strcmp(*argv, "all")) { 393 fprintf(stderr, "Argument \"%s\" is unknown, try \"ip xfrm monitor help\".\n", *argv); 394 exit(-1); 395 } 396 argc--; argv++; 397 } 398 399 if (lacquire) 400 groups |= nl_mgrp(XFRMNLGRP_ACQUIRE); 401 if (lexpire) 402 groups |= nl_mgrp(XFRMNLGRP_EXPIRE); 403 if (lsa) 404 groups |= nl_mgrp(XFRMNLGRP_SA); 405 if (lpolicy) 406 groups |= nl_mgrp(XFRMNLGRP_POLICY); 407 if (laevent) 408 groups |= nl_mgrp(XFRMNLGRP_AEVENTS); 409 if (lreport) 410 groups |= nl_mgrp(XFRMNLGRP_REPORT); 411 412 if (file) { 413 FILE *fp; 414 int err; 415 416 fp = fopen(file, "r"); 417 if (fp == NULL) { 418 perror("Cannot fopen"); 419 exit(-1); 420 } 421 err = rtnl_from_file(fp, xfrm_accept_msg, stdout); 422 fclose(fp); 423 return err; 424 } 425 426 if (rtnl_open_byproto(&rth, groups, NETLINK_XFRM) < 0) 427 exit(1); 428 if (listen_all_nsid && rtnl_listen_all_nsid(&rth) < 0) 429 exit(1); 430 431 if (rtnl_listen(&rth, xfrm_accept_msg, (void*)stdout) < 0) 432 exit(2); 433 434 return 0; 435 } 436