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 36static void usage(void) __attribute__((noreturn)); 37 38static void usage(void) 39{ 40 fprintf(stderr, "Usage: ip xfrm monitor [ all | LISTofOBJECTS ]\n"); 41 exit(-1); 42} 43 44static 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 if (n->nlmsg_type != XFRM_MSG_ACQUIRE) { 54 fprintf(stderr, "Not an acquire: %08x %08x %08x\n", 55 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); 56 return 0; 57 } 58 59 len -= NLMSG_LENGTH(sizeof(*xacq)); 60 if (len < 0) { 61 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 62 return -1; 63 } 64 65 parse_rtattr(tb, XFRMA_MAX, XFRMACQ_RTA(xacq), len); 66 67 family = xacq->sel.family; 68 if (family == AF_UNSPEC) 69 family = xacq->policy.sel.family; 70 if (family == AF_UNSPEC) 71 family = preferred_family; 72 73 fprintf(fp, "acquire "); 74 75 fprintf(fp, "proto %s ", strxf_xfrmproto(xacq->id.proto)); 76 if (show_stats > 0 || xacq->id.spi) { 77 __u32 spi = ntohl(xacq->id.spi); 78 fprintf(fp, "spi 0x%08x", spi); 79 if (show_stats > 0) 80 fprintf(fp, "(%u)", spi); 81 fprintf(fp, " "); 82 } 83 fprintf(fp, "%s", _SL_); 84 85 xfrm_selector_print(&xacq->sel, family, fp, " sel "); 86 87 xfrm_policy_info_print(&xacq->policy, tb, fp, " ", " policy "); 88 89 if (show_stats > 0) 90 fprintf(fp, " seq 0x%08u ", xacq->seq); 91 if (show_stats > 0) { 92 fprintf(fp, "%s-mask %s ", 93 strxf_algotype(XFRMA_ALG_CRYPT), 94 strxf_mask32(xacq->ealgos)); 95 fprintf(fp, "%s-mask %s ", 96 strxf_algotype(XFRMA_ALG_AUTH), 97 strxf_mask32(xacq->aalgos)); 98 fprintf(fp, "%s-mask %s", 99 strxf_algotype(XFRMA_ALG_COMP), 100 strxf_mask32(xacq->calgos)); 101 } 102 fprintf(fp, "%s", _SL_); 103 104 if (oneline) 105 fprintf(fp, "\n"); 106 107 return 0; 108} 109 110static int xfrm_accept_msg(const struct sockaddr_nl *who, 111 struct nlmsghdr *n, void *arg) 112{ 113 FILE *fp = (FILE*)arg; 114 115 if (timestamp) 116 print_timestamp(fp); 117 118 if (n->nlmsg_type == XFRM_MSG_ACQUIRE) { 119 xfrm_acquire_print(who, n, arg); 120 return 0; 121 } 122 if (n->nlmsg_type == XFRM_MSG_EXPIRE) { 123 xfrm_state_print(who, n, arg); 124 return 0; 125 } 126 if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) { 127 xfrm_policy_print(who, n, arg); 128 return 0; 129 } 130 if (n->nlmsg_type == XFRM_MSG_FLUSHSA) { 131 /* XXX: Todo: show proto in xfrm_usersa_flush */ 132 fprintf(fp, "Flushed state\n"); 133 return 0; 134 } 135 if (n->nlmsg_type == XFRM_MSG_FLUSHPOLICY) { 136 fprintf(fp, "Flushed policy\n"); 137 return 0; 138 } 139 if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP && 140 n->nlmsg_type != NLMSG_DONE) { 141 fprintf(fp, "Unknown message: %08x %08x %08x\n", 142 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); 143 } 144 return 0; 145} 146 147int do_xfrm_monitor(int argc, char **argv) 148{ 149 struct rtnl_handle rth; 150 char *file = NULL; 151 unsigned groups = ~((unsigned)0); /* XXX */ 152 int lacquire=0; 153 int lexpire=0; 154 155 while (argc > 0) { 156 if (matches(*argv, "file") == 0) { 157 NEXT_ARG(); 158 file = *argv; 159 } else if (matches(*argv, "acquire") == 0) { 160 lacquire=1; 161 groups = 0; 162 } else if (matches(*argv, "expire") == 0) { 163 lexpire=1; 164 groups = 0; 165 } else if (matches(*argv, "help") == 0) { 166 usage(); 167 } else { 168 fprintf(stderr, "Argument \"%s\" is unknown, try \"ip xfrm monitor help\".\n", *argv); 169 exit(-1); 170 } 171 argc--; argv++; 172 } 173 174 if (lacquire) 175 groups |= XFRMGRP_ACQUIRE; 176 if (lexpire) 177 groups |= XFRMGRP_EXPIRE; 178 179 if (file) { 180 FILE *fp; 181 fp = fopen(file, "r"); 182 if (fp == NULL) { 183 perror("Cannot fopen"); 184 exit(-1); 185 } 186 return rtnl_from_file(fp, xfrm_accept_msg, (void*)stdout); 187 } 188 189 //ll_init_map(&rth); 190 191 if (rtnl_listen(&rth, xfrm_accept_msg, (void*)stdout) < 0) 192 exit(2); 193 194 return 0; 195} 196