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 | LISTofXFRM-OBJECTS ]\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 void xfrm_usersa_print(const struct xfrm_usersa_id *sa_id, __u32 reqid, FILE *fp)
    226 {
    227 	char buf[256];
    228 
    229 	buf[0] = 0;
    230 	fprintf(fp, "dst %s ", rt_addr_n2a(sa_id->family,
    231 		sizeof(sa_id->daddr), &sa_id->daddr, buf, sizeof(buf)));
    232 
    233 	fprintf(fp, " reqid 0x%x", reqid);
    234 
    235 	fprintf(fp, " protocol %s ", strxf_proto(sa_id->proto));
    236 	fprintf(fp, " SPI 0x%x", ntohl(sa_id->spi));
    237 }
    238 
    239 static int xfrm_ae_print(const struct sockaddr_nl *who,
    240 			     struct nlmsghdr *n, void *arg)
    241 {
    242 	FILE *fp = (FILE*)arg;
    243 	struct xfrm_aevent_id *id = NLMSG_DATA(n);
    244 	char abuf[256];
    245 
    246 	fprintf(fp, "Async event ");
    247 	xfrm_ae_flags_print(id->flags, arg);
    248 	fprintf(fp,"\n\t");
    249 	memset(abuf, '\0', sizeof(abuf));
    250 	fprintf(fp, "src %s ", rt_addr_n2a(id->sa_id.family,
    251 		sizeof(id->saddr), &id->saddr,
    252 		abuf, sizeof(abuf)));
    253 
    254 	xfrm_usersa_print(&id->sa_id, id->reqid, fp);
    255 
    256 	fprintf(fp, "\n");
    257 	fflush(fp);
    258 
    259 	return 0;
    260 }
    261 
    262 static void xfrm_print_addr(FILE *fp, int family, xfrm_address_t *a, size_t s)
    263 {
    264 	char buf[256];
    265 
    266 	buf[0] = 0;
    267 	fprintf(fp, "%s", rt_addr_n2a(family, s, a, buf, sizeof(buf)));
    268 }
    269 
    270 static int xfrm_mapping_print(const struct sockaddr_nl *who,
    271 			     struct nlmsghdr *n, void *arg)
    272 {
    273 	FILE *fp = (FILE*)arg;
    274 	struct xfrm_user_mapping *map = NLMSG_DATA(n);
    275 
    276 	fprintf(fp, "Mapping change ");
    277 	xfrm_print_addr(fp, map->id.family, &map->old_saddr,
    278 			sizeof(map->old_saddr));
    279 
    280 	fprintf(fp, ":%d -> ", ntohs(map->old_sport));
    281 	xfrm_print_addr(fp, map->id.family, &map->new_saddr,
    282 			sizeof(map->new_saddr));
    283 	fprintf(fp, ":%d\n\t", ntohs(map->new_sport));
    284 
    285 	xfrm_usersa_print(&map->id, map->reqid, fp);
    286 
    287 	fprintf(fp, "\n");
    288 	fflush(fp);
    289 	return 0;
    290 }
    291 
    292 static int xfrm_accept_msg(const struct sockaddr_nl *who,
    293 			   struct nlmsghdr *n, void *arg)
    294 {
    295 	FILE *fp = (FILE*)arg;
    296 
    297 	if (timestamp)
    298 		print_timestamp(fp);
    299 
    300 	switch (n->nlmsg_type) {
    301 	case XFRM_MSG_NEWSA:
    302 	case XFRM_MSG_DELSA:
    303 	case XFRM_MSG_UPDSA:
    304 	case XFRM_MSG_EXPIRE:
    305 		xfrm_state_print(who, n, arg);
    306 		return 0;
    307 	case XFRM_MSG_NEWPOLICY:
    308 	case XFRM_MSG_DELPOLICY:
    309 	case XFRM_MSG_UPDPOLICY:
    310 	case XFRM_MSG_POLEXPIRE:
    311 		xfrm_policy_print(who, n, arg);
    312 		return 0;
    313 	case XFRM_MSG_ACQUIRE:
    314 		xfrm_acquire_print(who, n, arg);
    315 		return 0;
    316 	case XFRM_MSG_FLUSHSA:
    317 		xfrm_state_flush_print(who, n, arg);
    318 		return 0;
    319 	case XFRM_MSG_FLUSHPOLICY:
    320 		xfrm_policy_flush_print(who, n, arg);
    321 		return 0;
    322 	case XFRM_MSG_REPORT:
    323 		xfrm_report_print(who, n, arg);
    324 		return 0;
    325 	case XFRM_MSG_NEWAE:
    326 		xfrm_ae_print(who, n, arg);
    327 		return 0;
    328 	case XFRM_MSG_MAPPING:
    329 		xfrm_mapping_print(who, n, arg);
    330 		return 0;
    331 	default:
    332 		break;
    333 	}
    334 
    335 	if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP &&
    336 	    n->nlmsg_type != NLMSG_DONE) {
    337 		fprintf(fp, "Unknown message: %08d 0x%08x 0x%08x\n",
    338 			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
    339 	}
    340 	return 0;
    341 }
    342 
    343 extern struct rtnl_handle rth;
    344 
    345 int do_xfrm_monitor(int argc, char **argv)
    346 {
    347 	char *file = NULL;
    348 	unsigned groups = ~((unsigned)0); /* XXX */
    349 	int lacquire=0;
    350 	int lexpire=0;
    351 	int laevent=0;
    352 	int lpolicy=0;
    353 	int lsa=0;
    354 	int lreport=0;
    355 
    356 	rtnl_close(&rth);
    357 
    358 	while (argc > 0) {
    359 		if (matches(*argv, "file") == 0) {
    360 			NEXT_ARG();
    361 			file = *argv;
    362 		} else if (matches(*argv, "acquire") == 0) {
    363 			lacquire=1;
    364 			groups = 0;
    365 		} else if (matches(*argv, "expire") == 0) {
    366 			lexpire=1;
    367 			groups = 0;
    368 		} else if (matches(*argv, "SA") == 0) {
    369 			lsa=1;
    370 			groups = 0;
    371 		} else if (matches(*argv, "aevent") == 0) {
    372 			laevent=1;
    373 			groups = 0;
    374 		} else if (matches(*argv, "policy") == 0) {
    375 			lpolicy=1;
    376 			groups = 0;
    377 		} else if (matches(*argv, "report") == 0) {
    378 			lreport=1;
    379 			groups = 0;
    380 		} else if (matches(*argv, "help") == 0) {
    381 			usage();
    382 		} else {
    383 			fprintf(stderr, "Argument \"%s\" is unknown, try \"ip xfrm monitor help\".\n", *argv);
    384 			exit(-1);
    385 		}
    386 		argc--;	argv++;
    387 	}
    388 
    389 	if (lacquire)
    390 		groups |= nl_mgrp(XFRMNLGRP_ACQUIRE);
    391 	if (lexpire)
    392 		groups |= nl_mgrp(XFRMNLGRP_EXPIRE);
    393 	if (lsa)
    394 		groups |= nl_mgrp(XFRMNLGRP_SA);
    395 	if (lpolicy)
    396 		groups |= nl_mgrp(XFRMNLGRP_POLICY);
    397 	if (laevent)
    398 		groups |= nl_mgrp(XFRMNLGRP_AEVENTS);
    399 	if (lreport)
    400 		groups |= nl_mgrp(XFRMNLGRP_REPORT);
    401 
    402 	if (file) {
    403 		FILE *fp;
    404 		fp = fopen(file, "r");
    405 		if (fp == NULL) {
    406 			perror("Cannot fopen");
    407 			exit(-1);
    408 		}
    409 		return rtnl_from_file(fp, xfrm_accept_msg, (void*)stdout);
    410 	}
    411 
    412 	//ll_init_map(&rth);
    413 
    414 	if (rtnl_open_byproto(&rth, groups, NETLINK_XFRM) < 0)
    415 		exit(1);
    416 
    417 	if (rtnl_listen(&rth, xfrm_accept_msg, (void*)stdout) < 0)
    418 		exit(2);
    419 
    420 	return 0;
    421 }
    422