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 fflush(fp); 107 108 return 0; 109} 110 111static int xfrm_accept_msg(const struct sockaddr_nl *who, 112 struct nlmsghdr *n, void *arg) 113{ 114 FILE *fp = (FILE*)arg; 115 116 if (timestamp) 117 print_timestamp(fp); 118 119 if (n->nlmsg_type == XFRM_MSG_NEWSA || 120 n->nlmsg_type == XFRM_MSG_DELSA || 121 n->nlmsg_type == XFRM_MSG_UPDSA || 122 n->nlmsg_type == XFRM_MSG_EXPIRE) { 123 xfrm_state_print(who, n, arg); 124 return 0; 125 } 126 if (n->nlmsg_type == XFRM_MSG_NEWPOLICY || 127 n->nlmsg_type == XFRM_MSG_DELPOLICY || 128 n->nlmsg_type == XFRM_MSG_UPDPOLICY || 129 n->nlmsg_type == XFRM_MSG_POLEXPIRE) { 130 xfrm_policy_print(who, n, arg); 131 return 0; 132 } 133 134 if (n->nlmsg_type == XFRM_MSG_ACQUIRE) { 135 xfrm_acquire_print(who, n, arg); 136 return 0; 137 } 138 if (n->nlmsg_type == XFRM_MSG_FLUSHSA) { 139 /* XXX: Todo: show proto in xfrm_usersa_flush */ 140 fprintf(fp, "Flushed state\n"); 141 return 0; 142 } 143 if (n->nlmsg_type == XFRM_MSG_FLUSHPOLICY) { 144 fprintf(fp, "Flushed policy\n"); 145 return 0; 146 } 147 if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP && 148 n->nlmsg_type != NLMSG_DONE) { 149 fprintf(fp, "Unknown message: %08d 0x%08x 0x%08x\n", 150 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); 151 } 152 return 0; 153} 154 155int do_xfrm_monitor(int argc, char **argv) 156{ 157 struct rtnl_handle rth; 158 char *file = NULL; 159 unsigned groups = ~((unsigned)0); /* XXX */ 160 int lacquire=0; 161 int lexpire=0; 162 int lpolicy=0; 163 int lsa=0; 164 165 while (argc > 0) { 166 if (matches(*argv, "file") == 0) { 167 NEXT_ARG(); 168 file = *argv; 169 } else if (matches(*argv, "acquire") == 0) { 170 lacquire=1; 171 groups = 0; 172 } else if (matches(*argv, "expire") == 0) { 173 lexpire=1; 174 groups = 0; 175 } else if (matches(*argv, "SA") == 0) { 176 lsa=1; 177 groups = 0; 178 } else if (matches(*argv, "policy") == 0) { 179 lpolicy=1; 180 groups = 0; 181 } else if (matches(*argv, "help") == 0) { 182 usage(); 183 } else { 184 fprintf(stderr, "Argument \"%s\" is unknown, try \"ip xfrm monitor help\".\n", *argv); 185 exit(-1); 186 } 187 argc--; argv++; 188 } 189 190 if (lacquire) 191 groups |= XFRMGRP_ACQUIRE; 192 if (lexpire) 193 groups |= XFRMGRP_EXPIRE; 194 if (lsa) 195 groups |= XFRMGRP_SA; 196 if (lpolicy) 197 groups |= XFRMGRP_POLICY; 198 199 if (file) { 200 FILE *fp; 201 fp = fopen(file, "r"); 202 if (fp == NULL) { 203 perror("Cannot fopen"); 204 exit(-1); 205 } 206 return rtnl_from_file(fp, xfrm_accept_msg, (void*)stdout); 207 } 208 209 //ll_init_map(&rth); 210 211 if (rtnl_open_byproto(&rth, groups, NETLINK_XFRM) < 0) 212 exit(1); 213 214 if (rtnl_listen(&rth, xfrm_accept_msg, (void*)stdout) < 0) 215 exit(2); 216 217 return 0; 218} 219