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 39 static void usage(void) 40 { 41 fprintf(stderr, "Usage: ip xfrm monitor [ all | LISTofOBJECTS ]\n"); 42 exit(-1); 43 } 44 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 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 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 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 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 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 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 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