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 <linux/xfrm.h>
     32 #include "utils.h"
     33 #include "xfrm.h"
     34 #include "ip_common.h"
     35 
     36 static void usage(void) __attribute__((noreturn));
     37 
     38 static void usage(void)
     39 {
     40 	fprintf(stderr, "Usage: ip xfrm monitor [ all | LISTofOBJECTS ]\n");
     41 	exit(-1);
     42 }
     43 
     44 static 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 	len -= NLMSG_LENGTH(sizeof(*xacq));
     54 	if (len < 0) {
     55 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
     56 		return -1;
     57 	}
     58 
     59 	parse_rtattr(tb, XFRMA_MAX, XFRMACQ_RTA(xacq), len);
     60 
     61 	family = xacq->sel.family;
     62 	if (family == AF_UNSPEC)
     63 		family = xacq->policy.sel.family;
     64 	if (family == AF_UNSPEC)
     65 		family = preferred_family;
     66 
     67 	fprintf(fp, "acquire ");
     68 
     69 	fprintf(fp, "proto %s ", strxf_xfrmproto(xacq->id.proto));
     70 	if (show_stats > 0 || xacq->id.spi) {
     71 		__u32 spi = ntohl(xacq->id.spi);
     72 		fprintf(fp, "spi 0x%08x", spi);
     73 		if (show_stats > 0)
     74 			fprintf(fp, "(%u)", spi);
     75 		fprintf(fp, " ");
     76 	}
     77 	fprintf(fp, "%s", _SL_);
     78 
     79 	xfrm_selector_print(&xacq->sel, family, fp, "  sel ");
     80 
     81 	xfrm_policy_info_print(&xacq->policy, tb, fp, "    ", "  policy ");
     82 
     83 	if (show_stats > 0)
     84 		fprintf(fp, "  seq 0x%08u ", xacq->seq);
     85 	if (show_stats > 0) {
     86 		fprintf(fp, "%s-mask %s ",
     87 			strxf_algotype(XFRMA_ALG_CRYPT),
     88 			strxf_mask32(xacq->ealgos));
     89 		fprintf(fp, "%s-mask %s ",
     90 			strxf_algotype(XFRMA_ALG_AUTH),
     91 			strxf_mask32(xacq->aalgos));
     92 		fprintf(fp, "%s-mask %s",
     93 			strxf_algotype(XFRMA_ALG_COMP),
     94 			strxf_mask32(xacq->calgos));
     95 	}
     96 	fprintf(fp, "%s", _SL_);
     97 
     98 	if (oneline)
     99 		fprintf(fp, "\n");
    100 	fflush(fp);
    101 
    102 	return 0;
    103 }
    104 
    105 static int xfrm_state_flush_print(const struct sockaddr_nl *who,
    106 				  struct nlmsghdr *n, void *arg)
    107 {
    108 	FILE *fp = (FILE*)arg;
    109 	struct xfrm_usersa_flush *xsf = NLMSG_DATA(n);
    110 	int len = n->nlmsg_len;
    111 	const char *str;
    112 
    113 	len -= NLMSG_SPACE(sizeof(*xsf));
    114 	if (len < 0) {
    115 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
    116 		return -1;
    117 	}
    118 
    119 	fprintf(fp, "Flushed state ");
    120 
    121 	str = strxf_xfrmproto(xsf->proto);
    122 	if (str)
    123 		fprintf(fp, "proto %s", str);
    124 	else
    125 		fprintf(fp, "proto %u", xsf->proto);
    126 	fprintf(fp, "%s", _SL_);
    127 
    128 	if (oneline)
    129 		fprintf(fp, "\n");
    130 	fflush(fp);
    131 
    132 	return 0;
    133 }
    134 
    135 static int xfrm_policy_flush_print(const struct sockaddr_nl *who,
    136 				   struct nlmsghdr *n, void *arg)
    137 {
    138 	struct rtattr * tb[XFRMA_MAX+1];
    139 	FILE *fp = (FILE*)arg;
    140 	int len = n->nlmsg_len;
    141 
    142 	len -= NLMSG_SPACE(0);
    143 	if (len < 0) {
    144 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
    145 		return -1;
    146 	}
    147 
    148 	fprintf(fp, "Flushed policy ");
    149 
    150 	parse_rtattr(tb, XFRMA_MAX, NLMSG_DATA(n), len);
    151 
    152 	if (tb[XFRMA_POLICY_TYPE]) {
    153 		struct xfrm_userpolicy_type *upt;
    154 
    155 		fprintf(fp, "ptype ");
    156 
    157 		if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt))
    158 			fprintf(fp, "(ERROR truncated)");
    159 
    160 		upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]);
    161 		fprintf(fp, "%s ", strxf_ptype(upt->type));
    162 	}
    163 
    164 	fprintf(fp, "%s", _SL_);
    165 
    166 	if (oneline)
    167 		fprintf(fp, "\n");
    168 	fflush(fp);
    169 
    170 	return 0;
    171 }
    172 
    173 static int xfrm_report_print(const struct sockaddr_nl *who,
    174 			     struct nlmsghdr *n, void *arg)
    175 {
    176 	FILE *fp = (FILE*)arg;
    177 	struct xfrm_user_report *xrep = NLMSG_DATA(n);
    178 	int len = n->nlmsg_len;
    179 	struct rtattr * tb[XFRMA_MAX+1];
    180 	__u16 family;
    181 
    182 	len -= NLMSG_LENGTH(sizeof(*xrep));
    183 	if (len < 0) {
    184 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
    185 		return -1;
    186 	}
    187 
    188 	family = xrep->sel.family;
    189 	if (family == AF_UNSPEC)
    190 		family = preferred_family;
    191 
    192 	fprintf(fp, "report ");
    193 
    194 	fprintf(fp, "proto %s ", strxf_xfrmproto(xrep->proto));
    195 	fprintf(fp, "%s", _SL_);
    196 
    197 	xfrm_selector_print(&xrep->sel, family, fp, "  sel ");
    198 
    199 	parse_rtattr(tb, XFRMA_MAX, XFRMREP_RTA(xrep), len);
    200 
    201 	xfrm_xfrma_print(tb, family, fp, "  ");
    202 
    203 	if (oneline)
    204 		fprintf(fp, "\n");
    205 
    206 	return 0;
    207 }
    208 
    209 void xfrm_ae_flags_print(__u32 flags, void *arg)
    210 {
    211 	FILE *fp = (FILE*)arg;
    212 	fprintf(fp, " (0x%x) ", flags);
    213 	if (!flags)
    214 		return;
    215 	if (flags & XFRM_AE_CR)
    216 		fprintf(fp, " replay update ");
    217 	if (flags & XFRM_AE_CE)
    218 		fprintf(fp, " timer expired ");
    219 	if (flags & XFRM_AE_CU)
    220 		fprintf(fp, " policy updated ");
    221 
    222 }
    223 
    224 static int xfrm_ae_print(const struct sockaddr_nl *who,
    225 			     struct nlmsghdr *n, void *arg)
    226 {
    227 	FILE *fp = (FILE*)arg;
    228 	struct xfrm_aevent_id *id = NLMSG_DATA(n);
    229 	char abuf[256];
    230 
    231 	fprintf(fp, "Async event ");
    232 	xfrm_ae_flags_print(id->flags, arg);
    233 	fprintf(fp,"\n\t");
    234 	memset(abuf, '\0', sizeof(abuf));
    235 	fprintf(fp, "src %s ", rt_addr_n2a(id->sa_id.family,
    236 		sizeof(id->saddr), &id->saddr,
    237 		abuf, sizeof(abuf)));
    238 	memset(abuf, '\0', sizeof(abuf));
    239 	fprintf(fp, "dst %s ", rt_addr_n2a(id->sa_id.family,
    240 		sizeof(id->sa_id.daddr), &id->sa_id.daddr,
    241 		abuf, sizeof(abuf)));
    242 	fprintf(fp, " reqid 0x%x", id->reqid);
    243 	fprintf(fp, " protocol %s ", strxf_proto(id->sa_id.proto));
    244 	fprintf(fp, " SPI 0x%x", ntohl(id->sa_id.spi));
    245 
    246 	fprintf(fp, "\n");
    247 	fflush(fp);
    248 
    249 	return 0;
    250 }
    251 
    252 static int xfrm_accept_msg(const struct sockaddr_nl *who,
    253 			   struct nlmsghdr *n, void *arg)
    254 {
    255 	FILE *fp = (FILE*)arg;
    256 
    257 	if (timestamp)
    258 		print_timestamp(fp);
    259 
    260 	switch (n->nlmsg_type) {
    261 	case XFRM_MSG_NEWSA:
    262 	case XFRM_MSG_DELSA:
    263 	case XFRM_MSG_UPDSA:
    264 	case XFRM_MSG_EXPIRE:
    265 		xfrm_state_print(who, n, arg);
    266 		return 0;
    267 	case XFRM_MSG_NEWPOLICY:
    268 	case XFRM_MSG_DELPOLICY:
    269 	case XFRM_MSG_UPDPOLICY:
    270 	case XFRM_MSG_POLEXPIRE:
    271 		xfrm_policy_print(who, n, arg);
    272 		return 0;
    273 	case XFRM_MSG_ACQUIRE:
    274 		xfrm_acquire_print(who, n, arg);
    275 		return 0;
    276 	case XFRM_MSG_FLUSHSA:
    277 		xfrm_state_flush_print(who, n, arg);
    278 		return 0;
    279 	case XFRM_MSG_FLUSHPOLICY:
    280 		xfrm_policy_flush_print(who, n, arg);
    281 		return 0;
    282 	case XFRM_MSG_REPORT:
    283 		xfrm_report_print(who, n, arg);
    284 		return 0;
    285 	case XFRM_MSG_NEWAE:
    286 		xfrm_ae_print(who, n, arg);
    287 		return 0;
    288 	default:
    289 		break;
    290 	}
    291 
    292 	if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP &&
    293 	    n->nlmsg_type != NLMSG_DONE) {
    294 		fprintf(fp, "Unknown message: %08d 0x%08x 0x%08x\n",
    295 			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
    296 	}
    297 	return 0;
    298 }
    299 
    300 extern struct rtnl_handle rth;
    301 
    302 int do_xfrm_monitor(int argc, char **argv)
    303 {
    304 	char *file = NULL;
    305 	unsigned groups = ~((unsigned)0); /* XXX */
    306 	int lacquire=0;
    307 	int lexpire=0;
    308 	int laevent=0;
    309 	int lpolicy=0;
    310 	int lsa=0;
    311 	int lreport=0;
    312 
    313 	rtnl_close(&rth);
    314 
    315 	while (argc > 0) {
    316 		if (matches(*argv, "file") == 0) {
    317 			NEXT_ARG();
    318 			file = *argv;
    319 		} else if (matches(*argv, "acquire") == 0) {
    320 			lacquire=1;
    321 			groups = 0;
    322 		} else if (matches(*argv, "expire") == 0) {
    323 			lexpire=1;
    324 			groups = 0;
    325 		} else if (matches(*argv, "SA") == 0) {
    326 			lsa=1;
    327 			groups = 0;
    328 		} else if (matches(*argv, "aevent") == 0) {
    329 			laevent=1;
    330 			groups = 0;
    331 		} else if (matches(*argv, "policy") == 0) {
    332 			lpolicy=1;
    333 			groups = 0;
    334 		} else if (matches(*argv, "report") == 0) {
    335 			lreport=1;
    336 			groups = 0;
    337 		} else if (matches(*argv, "help") == 0) {
    338 			usage();
    339 		} else {
    340 			fprintf(stderr, "Argument \"%s\" is unknown, try \"ip xfrm monitor help\".\n", *argv);
    341 			exit(-1);
    342 		}
    343 		argc--;	argv++;
    344 	}
    345 
    346 	if (lacquire)
    347 		groups |= nl_mgrp(XFRMNLGRP_ACQUIRE);
    348 	if (lexpire)
    349 		groups |= nl_mgrp(XFRMNLGRP_EXPIRE);
    350 	if (lsa)
    351 		groups |= nl_mgrp(XFRMNLGRP_SA);
    352 	if (lpolicy)
    353 		groups |= nl_mgrp(XFRMNLGRP_POLICY);
    354 	if (laevent)
    355 		groups |= nl_mgrp(XFRMNLGRP_AEVENTS);
    356 	if (lreport)
    357 		groups |= nl_mgrp(XFRMNLGRP_REPORT);
    358 
    359 	if (file) {
    360 		FILE *fp;
    361 		fp = fopen(file, "r");
    362 		if (fp == NULL) {
    363 			perror("Cannot fopen");
    364 			exit(-1);
    365 		}
    366 		return rtnl_from_file(fp, xfrm_accept_msg, (void*)stdout);
    367 	}
    368 
    369 	//ll_init_map(&rth);
    370 
    371 	if (rtnl_open_byproto(&rth, groups, NETLINK_XFRM) < 0)
    372 		exit(1);
    373 
    374 	if (rtnl_listen(&rth, xfrm_accept_msg, (void*)stdout) < 0)
    375 		exit(2);
    376 
    377 	return 0;
    378 }
    379