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 <linux/xfrm.h> 32 #include "utils.h" 33 #include "xfrm.h" 34 #include "ip_common.h" 35 36 static void usage(void) __attribute__((noreturn)); 37 38 static void usage(void) 39 { 40 fprintf(stderr, "Usage: ip xfrm monitor [ all | LISTofOBJECTS ]\n"); 41 exit(-1); 42 } 43 44 static int xfrm_acquire_print(const struct sockaddr_nl *who, 45 struct nlmsghdr *n, void *arg) 46 { 47 FILE *fp = (FILE*)arg; 48 struct xfrm_user_acquire *xacq = NLMSG_DATA(n); 49 int len = n->nlmsg_len; 50 struct rtattr * tb[XFRMA_MAX+1]; 51 __u16 family; 52 53 len -= NLMSG_LENGTH(sizeof(*xacq)); 54 if (len < 0) { 55 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 56 return -1; 57 } 58 59 parse_rtattr(tb, XFRMA_MAX, XFRMACQ_RTA(xacq), len); 60 61 family = xacq->sel.family; 62 if (family == AF_UNSPEC) 63 family = xacq->policy.sel.family; 64 if (family == AF_UNSPEC) 65 family = preferred_family; 66 67 fprintf(fp, "acquire "); 68 69 fprintf(fp, "proto %s ", strxf_xfrmproto(xacq->id.proto)); 70 if (show_stats > 0 || xacq->id.spi) { 71 __u32 spi = ntohl(xacq->id.spi); 72 fprintf(fp, "spi 0x%08x", spi); 73 if (show_stats > 0) 74 fprintf(fp, "(%u)", spi); 75 fprintf(fp, " "); 76 } 77 fprintf(fp, "%s", _SL_); 78 79 xfrm_selector_print(&xacq->sel, family, fp, " sel "); 80 81 xfrm_policy_info_print(&xacq->policy, tb, fp, " ", " policy "); 82 83 if (show_stats > 0) 84 fprintf(fp, " seq 0x%08u ", xacq->seq); 85 if (show_stats > 0) { 86 fprintf(fp, "%s-mask %s ", 87 strxf_algotype(XFRMA_ALG_CRYPT), 88 strxf_mask32(xacq->ealgos)); 89 fprintf(fp, "%s-mask %s ", 90 strxf_algotype(XFRMA_ALG_AUTH), 91 strxf_mask32(xacq->aalgos)); 92 fprintf(fp, "%s-mask %s", 93 strxf_algotype(XFRMA_ALG_COMP), 94 strxf_mask32(xacq->calgos)); 95 } 96 fprintf(fp, "%s", _SL_); 97 98 if (oneline) 99 fprintf(fp, "\n"); 100 fflush(fp); 101 102 return 0; 103 } 104 105 static int xfrm_state_flush_print(const struct sockaddr_nl *who, 106 struct nlmsghdr *n, void *arg) 107 { 108 FILE *fp = (FILE*)arg; 109 struct xfrm_usersa_flush *xsf = NLMSG_DATA(n); 110 int len = n->nlmsg_len; 111 const char *str; 112 113 len -= NLMSG_SPACE(sizeof(*xsf)); 114 if (len < 0) { 115 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 116 return -1; 117 } 118 119 fprintf(fp, "Flushed state "); 120 121 str = strxf_xfrmproto(xsf->proto); 122 if (str) 123 fprintf(fp, "proto %s", str); 124 else 125 fprintf(fp, "proto %u", xsf->proto); 126 fprintf(fp, "%s", _SL_); 127 128 if (oneline) 129 fprintf(fp, "\n"); 130 fflush(fp); 131 132 return 0; 133 } 134 135 static int xfrm_policy_flush_print(const struct sockaddr_nl *who, 136 struct nlmsghdr *n, void *arg) 137 { 138 struct rtattr * tb[XFRMA_MAX+1]; 139 FILE *fp = (FILE*)arg; 140 int len = n->nlmsg_len; 141 142 len -= NLMSG_SPACE(0); 143 if (len < 0) { 144 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 145 return -1; 146 } 147 148 fprintf(fp, "Flushed policy "); 149 150 parse_rtattr(tb, XFRMA_MAX, NLMSG_DATA(n), len); 151 152 if (tb[XFRMA_POLICY_TYPE]) { 153 struct xfrm_userpolicy_type *upt; 154 155 fprintf(fp, "ptype "); 156 157 if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt)) 158 fprintf(fp, "(ERROR truncated)"); 159 160 upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]); 161 fprintf(fp, "%s ", strxf_ptype(upt->type)); 162 } 163 164 fprintf(fp, "%s", _SL_); 165 166 if (oneline) 167 fprintf(fp, "\n"); 168 fflush(fp); 169 170 return 0; 171 } 172 173 static int xfrm_report_print(const struct sockaddr_nl *who, 174 struct nlmsghdr *n, void *arg) 175 { 176 FILE *fp = (FILE*)arg; 177 struct xfrm_user_report *xrep = NLMSG_DATA(n); 178 int len = n->nlmsg_len; 179 struct rtattr * tb[XFRMA_MAX+1]; 180 __u16 family; 181 182 len -= NLMSG_LENGTH(sizeof(*xrep)); 183 if (len < 0) { 184 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 185 return -1; 186 } 187 188 family = xrep->sel.family; 189 if (family == AF_UNSPEC) 190 family = preferred_family; 191 192 fprintf(fp, "report "); 193 194 fprintf(fp, "proto %s ", strxf_xfrmproto(xrep->proto)); 195 fprintf(fp, "%s", _SL_); 196 197 xfrm_selector_print(&xrep->sel, family, fp, " sel "); 198 199 parse_rtattr(tb, XFRMA_MAX, XFRMREP_RTA(xrep), len); 200 201 xfrm_xfrma_print(tb, family, fp, " "); 202 203 if (oneline) 204 fprintf(fp, "\n"); 205 206 return 0; 207 } 208 209 void xfrm_ae_flags_print(__u32 flags, void *arg) 210 { 211 FILE *fp = (FILE*)arg; 212 fprintf(fp, " (0x%x) ", flags); 213 if (!flags) 214 return; 215 if (flags & XFRM_AE_CR) 216 fprintf(fp, " replay update "); 217 if (flags & XFRM_AE_CE) 218 fprintf(fp, " timer expired "); 219 if (flags & XFRM_AE_CU) 220 fprintf(fp, " policy updated "); 221 222 } 223 224 static int xfrm_ae_print(const struct sockaddr_nl *who, 225 struct nlmsghdr *n, void *arg) 226 { 227 FILE *fp = (FILE*)arg; 228 struct xfrm_aevent_id *id = NLMSG_DATA(n); 229 char abuf[256]; 230 231 fprintf(fp, "Async event "); 232 xfrm_ae_flags_print(id->flags, arg); 233 fprintf(fp,"\n\t"); 234 memset(abuf, '\0', sizeof(abuf)); 235 fprintf(fp, "src %s ", rt_addr_n2a(id->sa_id.family, 236 sizeof(id->saddr), &id->saddr, 237 abuf, sizeof(abuf))); 238 memset(abuf, '\0', sizeof(abuf)); 239 fprintf(fp, "dst %s ", rt_addr_n2a(id->sa_id.family, 240 sizeof(id->sa_id.daddr), &id->sa_id.daddr, 241 abuf, sizeof(abuf))); 242 fprintf(fp, " reqid 0x%x", id->reqid); 243 fprintf(fp, " protocol %s ", strxf_proto(id->sa_id.proto)); 244 fprintf(fp, " SPI 0x%x", ntohl(id->sa_id.spi)); 245 246 fprintf(fp, "\n"); 247 fflush(fp); 248 249 return 0; 250 } 251 252 static int xfrm_accept_msg(const struct sockaddr_nl *who, 253 struct nlmsghdr *n, void *arg) 254 { 255 FILE *fp = (FILE*)arg; 256 257 if (timestamp) 258 print_timestamp(fp); 259 260 switch (n->nlmsg_type) { 261 case XFRM_MSG_NEWSA: 262 case XFRM_MSG_DELSA: 263 case XFRM_MSG_UPDSA: 264 case XFRM_MSG_EXPIRE: 265 xfrm_state_print(who, n, arg); 266 return 0; 267 case XFRM_MSG_NEWPOLICY: 268 case XFRM_MSG_DELPOLICY: 269 case XFRM_MSG_UPDPOLICY: 270 case XFRM_MSG_POLEXPIRE: 271 xfrm_policy_print(who, n, arg); 272 return 0; 273 case XFRM_MSG_ACQUIRE: 274 xfrm_acquire_print(who, n, arg); 275 return 0; 276 case XFRM_MSG_FLUSHSA: 277 xfrm_state_flush_print(who, n, arg); 278 return 0; 279 case XFRM_MSG_FLUSHPOLICY: 280 xfrm_policy_flush_print(who, n, arg); 281 return 0; 282 case XFRM_MSG_REPORT: 283 xfrm_report_print(who, n, arg); 284 return 0; 285 case XFRM_MSG_NEWAE: 286 xfrm_ae_print(who, n, arg); 287 return 0; 288 default: 289 break; 290 } 291 292 if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP && 293 n->nlmsg_type != NLMSG_DONE) { 294 fprintf(fp, "Unknown message: %08d 0x%08x 0x%08x\n", 295 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); 296 } 297 return 0; 298 } 299 300 extern struct rtnl_handle rth; 301 302 int do_xfrm_monitor(int argc, char **argv) 303 { 304 char *file = NULL; 305 unsigned groups = ~((unsigned)0); /* XXX */ 306 int lacquire=0; 307 int lexpire=0; 308 int laevent=0; 309 int lpolicy=0; 310 int lsa=0; 311 int lreport=0; 312 313 rtnl_close(&rth); 314 315 while (argc > 0) { 316 if (matches(*argv, "file") == 0) { 317 NEXT_ARG(); 318 file = *argv; 319 } else if (matches(*argv, "acquire") == 0) { 320 lacquire=1; 321 groups = 0; 322 } else if (matches(*argv, "expire") == 0) { 323 lexpire=1; 324 groups = 0; 325 } else if (matches(*argv, "SA") == 0) { 326 lsa=1; 327 groups = 0; 328 } else if (matches(*argv, "aevent") == 0) { 329 laevent=1; 330 groups = 0; 331 } else if (matches(*argv, "policy") == 0) { 332 lpolicy=1; 333 groups = 0; 334 } else if (matches(*argv, "report") == 0) { 335 lreport=1; 336 groups = 0; 337 } else if (matches(*argv, "help") == 0) { 338 usage(); 339 } else { 340 fprintf(stderr, "Argument \"%s\" is unknown, try \"ip xfrm monitor help\".\n", *argv); 341 exit(-1); 342 } 343 argc--; argv++; 344 } 345 346 if (lacquire) 347 groups |= nl_mgrp(XFRMNLGRP_ACQUIRE); 348 if (lexpire) 349 groups |= nl_mgrp(XFRMNLGRP_EXPIRE); 350 if (lsa) 351 groups |= nl_mgrp(XFRMNLGRP_SA); 352 if (lpolicy) 353 groups |= nl_mgrp(XFRMNLGRP_POLICY); 354 if (laevent) 355 groups |= nl_mgrp(XFRMNLGRP_AEVENTS); 356 if (lreport) 357 groups |= nl_mgrp(XFRMNLGRP_REPORT); 358 359 if (file) { 360 FILE *fp; 361 fp = fopen(file, "r"); 362 if (fp == NULL) { 363 perror("Cannot fopen"); 364 exit(-1); 365 } 366 return rtnl_from_file(fp, xfrm_accept_msg, (void*)stdout); 367 } 368 369 //ll_init_map(&rth); 370 371 if (rtnl_open_byproto(&rth, groups, NETLINK_XFRM) < 0) 372 exit(1); 373 374 if (rtnl_listen(&rth, xfrm_accept_msg, (void*)stdout) < 0) 375 exit(2); 376 377 return 0; 378 } 379