Home | History | Annotate | Download | only in ip
      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