File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / setkey / setkey.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:39:10 2012 UTC (12 years, 5 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_2p2, v0_8_1p0, v0_8_1, v0_8_0p0, v0_8_0, HEAD
ipsec-tools

    1: /*	$NetBSD: setkey.c,v 1.14 2009/08/06 04:44:43 tteras Exp $	*/
    2: 
    3: /*	$KAME: setkey.c,v 1.36 2003/09/24 23:52:51 itojun Exp $	*/
    4: 
    5: /*
    6:  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
    7:  * All rights reserved.
    8:  *
    9:  * Redistribution and use in source and binary forms, with or without
   10:  * modification, are permitted provided that the following conditions
   11:  * are met:
   12:  * 1. Redistributions of source code must retain the above copyright
   13:  *    notice, this list of conditions and the following disclaimer.
   14:  * 2. Redistributions in binary form must reproduce the above copyright
   15:  *    notice, this list of conditions and the following disclaimer in the
   16:  *    documentation and/or other materials provided with the distribution.
   17:  * 3. Neither the name of the project nor the names of its contributors
   18:  *    may be used to endorse or promote products derived from this software
   19:  *    without specific prior written permission.
   20:  *
   21:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31:  * SUCH DAMAGE.
   32:  */
   33: 
   34: #ifdef HAVE_CONFIG_H
   35: #include "config.h"
   36: #endif
   37: 
   38: #include <sys/types.h>
   39: #include <sys/param.h>
   40: #include <sys/socket.h>
   41: #include <sys/time.h>
   42: #include <sys/stat.h>
   43: #include <sys/sysctl.h>
   44: #include <err.h>
   45: #include <netinet/in.h>
   46: #include <net/pfkeyv2.h>
   47: #include PATH_IPSEC_H
   48: 
   49: #include <stdio.h>
   50: #include <stdlib.h>
   51: #include <limits.h>
   52: #include <string.h>
   53: #include <ctype.h>
   54: #include <unistd.h>
   55: #include <errno.h>
   56: #include <netdb.h>
   57: #include <fcntl.h>
   58: #include <dirent.h>
   59: #include <time.h>
   60: 
   61: #ifdef HAVE_READLINE
   62: #include <readline/readline.h>
   63: #include <readline/history.h>
   64: #endif
   65: 
   66: #include "config.h"
   67: #include "libpfkey.h"
   68: #include "package_version.h"
   69: #define extern /* so that variables in extern.h are not extern... */
   70: #include "extern.h"
   71: 
   72: #define strlcpy(d,s,l) (strncpy(d,s,l), (d)[(l)-1] = '\0')
   73: 
   74: void usage __P((int));
   75: int main __P((int, char **));
   76: int get_supported __P((void));
   77: void sendkeyshort __P((u_int));
   78: void promisc __P((void));
   79: int postproc __P((struct sadb_msg *, int));
   80: int verifypriority __P((struct sadb_msg *m));
   81: int fileproc __P((const char *));
   82: const char *numstr __P((int));
   83: void shortdump_hdr __P((void));
   84: void shortdump __P((struct sadb_msg *));
   85: static void printdate __P((void));
   86: static int32_t gmt2local __P((time_t));
   87: void stdin_loop __P((void));
   88: 
   89: #define MODE_SCRIPT	1
   90: #define MODE_CMDDUMP	2
   91: #define MODE_CMDFLUSH	3
   92: #define MODE_PROMISC	4
   93: #define MODE_STDIN	5
   94: 
   95: int so;
   96: 
   97: int f_forever = 0;
   98: int f_all = 0;
   99: int f_verbose = 0;
  100: int f_mode = 0;
  101: int f_cmddump = 0;
  102: int f_policy = 0;
  103: int f_hexdump = 0;
  104: int f_tflag = 0;
  105: int f_notreally = 0;
  106: int f_withports = 0;
  107: #ifdef HAVE_POLICY_FWD
  108: int f_rfcmode = 1;
  109: #define RK_OPTS "rk"
  110: #else
  111: int f_rkwarn = 0;
  112: #define RK_OPTS ""
  113: static void rkwarn(void);
  114: static void
  115: rkwarn(void)
  116: {
  117: 	if (!f_rkwarn) {
  118: 		f_rkwarn = 1;
  119: 		printf("warning: -r and -k options are not supported in this environment\n");
  120: 	}
  121: }
  122: 
  123: #endif
  124: static time_t thiszone;
  125: 
  126: void
  127: usage(int only_version)
  128: {
  129: 	printf("setkey @(#) %s (%s)\n", TOP_PACKAGE_STRING, TOP_PACKAGE_URL); 
  130: 	if (! only_version) {
  131: 		printf("usage: setkey [-v" RK_OPTS "] file ...\n");
  132: 		printf("       setkey [-nv" RK_OPTS "] -c\n");
  133: 		printf("       setkey [-nv" RK_OPTS "] -f filename\n");
  134: 		printf("       setkey [-Palpv" RK_OPTS "] -D\n");
  135: 		printf("       setkey [-Pv] -F\n");
  136: 		printf("       setkey [-H] -x\n");
  137: 		printf("       setkey [-V] [-h]\n");
  138: 	}
  139: 	exit(1);
  140: }
  141: 
  142: int
  143: main(argc, argv)
  144: 	int argc;
  145: 	char **argv;
  146: {
  147: 	FILE *fp = stdin;
  148: 	int c;
  149: 
  150: 	if (argc == 1) {
  151: 		usage(0);
  152: 		/* NOTREACHED */
  153: 	}
  154: 
  155: 	thiszone = gmt2local(0);
  156: 
  157: 	while ((c = getopt(argc, argv, "acdf:HlnvxDFPphVrk?")) != -1) {
  158: 		switch (c) {
  159: 		case 'c':
  160: 			f_mode = MODE_STDIN;
  161: #ifdef HAVE_READLINE
  162: 			/* disable filename completion */
  163: 			rl_bind_key('\t', rl_insert);
  164: #endif
  165: 			break;
  166: 		case 'f':
  167: 			f_mode = MODE_SCRIPT;
  168: 			if ((fp = fopen(optarg, "r")) == NULL) {
  169: 				err(1, "fopen");
  170: 				/*NOTREACHED*/
  171: 			}
  172: 			break;
  173: 		case 'D':
  174: 			f_mode = MODE_CMDDUMP;
  175: 			break;
  176: 		case 'F':
  177: 			f_mode = MODE_CMDFLUSH;
  178: 			break;
  179: 		case 'a':
  180: 			f_all = 1;
  181: 			break;
  182: 		case 'l':
  183: 			f_forever = 1;
  184: 			break;
  185: 		case 'n':
  186: 			f_notreally = 1;
  187: 			break;
  188: #ifdef __NetBSD__
  189: 		case 'h':
  190: #endif
  191: 		case 'H':
  192: 			f_hexdump = 1;
  193: 			break;
  194: 		case 'x':
  195: 			f_mode = MODE_PROMISC;
  196: 			f_tflag++;
  197: 			break;
  198: 		case 'P':
  199: 			f_policy = 1;
  200: 			break;
  201: 		case 'p':
  202: 			f_withports = 1;
  203: 			break;
  204: 		case 'v':
  205: 			f_verbose = 1;
  206: 			break;
  207: 		case 'r':
  208: #ifdef HAVE_POLICY_FWD
  209: 			f_rfcmode = 1;
  210: #else
  211: 			rkwarn();
  212: #endif
  213: 			break;
  214: 		case 'k':
  215: #ifdef HAVE_POLICY_FWD
  216: 			f_rfcmode = 0;
  217: #else
  218: 			rkwarn();
  219: #endif
  220: 			break;
  221: 		case 'V':
  222: 			usage(1);
  223: 			break;
  224: 			/*NOTREACHED*/
  225: #ifndef __NetBSD__
  226: 		case 'h':
  227: #endif
  228: 		case '?':
  229: 		default:
  230: 			usage(0);
  231: 			/*NOTREACHED*/
  232: 		}
  233: 	}
  234: 
  235: 	argc -= optind;
  236: 	argv += optind;
  237: 
  238: 	if (argc > 0) {
  239: 		while (argc--)
  240: 			if (fileproc(*argv++) < 0) {
  241: 				err(1, "%s", argv[-1]);
  242: 				/*NOTREACHED*/
  243: 			}
  244: 		exit(0);
  245: 	}
  246: 
  247: 	so = pfkey_open();
  248: 	if (so < 0) {
  249: 		perror("pfkey_open");
  250: 		exit(1);
  251: 	}
  252: 
  253: 	switch (f_mode) {
  254: 	case MODE_CMDDUMP:
  255: 		sendkeyshort(f_policy ? SADB_X_SPDDUMP : SADB_DUMP);
  256: 		break;
  257: 	case MODE_CMDFLUSH:
  258: 		sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH);
  259: 		break;
  260: 	case MODE_SCRIPT:
  261: 		if (get_supported() < 0) {
  262: 			errx(1, "%s", ipsec_strerror());
  263: 			/*NOTREACHED*/
  264: 		}
  265: 		if (parse(&fp))
  266: 			exit (1);
  267: 		break;
  268: 	case MODE_STDIN:
  269: 		if (get_supported() < 0) {
  270: 			errx(1, "%s", ipsec_strerror());
  271: 			/*NOTREACHED*/
  272: 		}
  273: 		stdin_loop();
  274: 		break;
  275: 	case MODE_PROMISC:
  276: 		promisc();
  277: 		/*NOTREACHED*/
  278: 	default:
  279: 		usage(0);
  280: 		/*NOTREACHED*/
  281: 	}
  282: 
  283: 	exit(0);
  284: }
  285: 
  286: int
  287: get_supported()
  288: {
  289: 
  290: 	if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0)
  291: 		return -1;
  292: 
  293: 	if (pfkey_recv_register(so) < 0)
  294: 		return -1;
  295: 
  296: 	return (0);
  297: }
  298: 
  299: void
  300: stdin_loop()
  301: {
  302: 	char line[1024], *semicolon, *comment;
  303: 	size_t linelen = 0;
  304: 	
  305: 	memset (line, 0, sizeof(line));
  306: 
  307: 	parse_init();
  308: 	while (1) {
  309: #ifdef HAVE_READLINE
  310: 		char *rbuf;
  311: 		rbuf = readline ("");
  312: 		if (! rbuf)
  313: 			break;
  314: #else
  315: 		char rbuf[1024];
  316: 		rbuf[0] = '\0';
  317: 		if (fgets(rbuf, sizeof(rbuf), stdin) == NULL)
  318: 			break;
  319: 		if (rbuf[strlen(rbuf)-1] == '\n')
  320: 			rbuf[strlen(rbuf)-1] = '\0';
  321: #endif
  322: 		comment = strchr(rbuf, '#');
  323: 		if (comment)
  324: 			*comment = '\0';
  325: 
  326: 		if (!rbuf[0])
  327: 			continue;
  328: 
  329: 		linelen += snprintf (&line[linelen], sizeof(line) - linelen,
  330: 				     "%s%s", linelen > 0 ? " " : "", rbuf);
  331: 
  332: 		semicolon = strchr(line, ';');
  333: 		while (semicolon) {
  334: 			char saved_char = *++semicolon;
  335: 			*semicolon = '\0';
  336: #ifdef HAVE_READLINE
  337: 			add_history (line);
  338: #endif
  339: 
  340: #ifdef HAVE_PFKEY_POLICY_PRIORITY
  341: 			last_msg_type = -1;  /* invalid message type */
  342: #endif
  343: 
  344: 			parse_string (line);
  345: 			if (exit_now)
  346: 				return;
  347: 			if (saved_char) {
  348: 				*semicolon = saved_char;
  349: 				linelen = strlen (semicolon);
  350: 				memmove (line, semicolon, linelen + 1);
  351: 				semicolon = strchr(line, ';');
  352: 			}
  353: 			else {
  354: 				semicolon = NULL;
  355: 				linelen = 0;
  356: 			}
  357: 		}
  358: 	}
  359: }
  360: 
  361: void
  362: sendkeyshort(type)
  363:         u_int type;
  364: {
  365: 	struct sadb_msg msg;
  366: 
  367: 	msg.sadb_msg_version = PF_KEY_V2;
  368: 	msg.sadb_msg_type = type;
  369: 	msg.sadb_msg_errno = 0;
  370: 	msg.sadb_msg_satype = SADB_SATYPE_UNSPEC;
  371: 	msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
  372: 	msg.sadb_msg_reserved = 0;
  373: 	msg.sadb_msg_seq = 0;
  374: 	msg.sadb_msg_pid = getpid();
  375: 
  376: 	sendkeymsg((char *)&msg, sizeof(msg));
  377: 
  378: 	return;
  379: }
  380: 
  381: void
  382: promisc()
  383: {
  384: 	struct sadb_msg msg;
  385: 	u_char rbuf[1024 * 32];	/* XXX: Enough ? Should I do MSG_PEEK ? */
  386: 	ssize_t l;
  387: 
  388: 	msg.sadb_msg_version = PF_KEY_V2;
  389: 	msg.sadb_msg_type = SADB_X_PROMISC;
  390: 	msg.sadb_msg_errno = 0;
  391: 	msg.sadb_msg_satype = 1;
  392: 	msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
  393: 	msg.sadb_msg_reserved = 0;
  394: 	msg.sadb_msg_seq = 0;
  395: 	msg.sadb_msg_pid = getpid();
  396: 
  397: 	if ((l = send(so, &msg, sizeof(msg), 0)) < 0) {
  398: 		err(1, "send");
  399: 		/*NOTREACHED*/
  400: 	}
  401: 
  402: 	while (1) {
  403: 		struct sadb_msg *base;
  404: 
  405: 		if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) {
  406: 			err(1, "recv");
  407: 			/*NOTREACHED*/
  408: 		}
  409: 
  410: 		if (l != sizeof(*base))
  411: 			continue;
  412: 
  413: 		base = (struct sadb_msg *)rbuf;
  414: 		if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len),
  415: 				0)) < 0) {
  416: 			err(1, "recv");
  417: 			/*NOTREACHED*/
  418: 		}
  419: 		printdate();
  420: 		if (f_hexdump) {
  421: 			int i;
  422: 			for (i = 0; i < l; i++) {
  423: 				if (i % 16 == 0)
  424: 					printf("%08x: ", i);
  425: 				printf("%02x ", rbuf[i] & 0xff);
  426: 				if (i % 16 == 15)
  427: 					printf("\n");
  428: 			}
  429: 			if (l % 16)
  430: 				printf("\n");
  431: 		}
  432: 		/* adjust base pointer for promisc mode */
  433: 		if (base->sadb_msg_type == SADB_X_PROMISC) {
  434: 			if ((ssize_t)sizeof(*base) < l)
  435: 				base++;
  436: 			else
  437: 				base = NULL;
  438: 		}
  439: 		if (base) {
  440: 			kdebug_sadb(base);
  441: 			printf("\n");
  442: 			fflush(stdout);
  443: 		}
  444: 	}
  445: }
  446: 
  447: /* Generate 'spi' array with SPIs matching 'satype', 'srcs', and 'dsts'
  448:  * Return value is dynamically generated array of SPIs, also number of
  449:  * SPIs through num_spi pointer.
  450:  * On any error, set *num_spi to 0 and return NULL.
  451:  */
  452: u_int32_t *
  453: sendkeymsg_spigrep(satype, srcs, dsts, num_spi)
  454: 	unsigned int satype;
  455: 	struct addrinfo *srcs;
  456: 	struct addrinfo *dsts;
  457: 	int *num_spi;
  458: {
  459: 	struct sadb_msg msg, *m;
  460: 	char *buf;
  461: 	size_t len;
  462: 	ssize_t l;
  463: 	u_char rbuf[1024 * 32];
  464: 	caddr_t mhp[SADB_EXT_MAX + 1];
  465: 	struct sadb_address *saddr;
  466: 	struct sockaddr *s;
  467: 	struct addrinfo *a;
  468: 	struct sadb_sa *sa;
  469: 	u_int32_t *spi = NULL;
  470: 	int max_spi = 0, fail = 0;
  471: 
  472: 	*num_spi = 0;
  473: 
  474: 	if (f_notreally) {
  475: 		return NULL;
  476: 	}
  477: 
  478:     {
  479: 	struct timeval tv;
  480: 	tv.tv_sec = 1;
  481: 	tv.tv_usec = 0;
  482: 	if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
  483: 		perror("setsockopt");
  484: 		return NULL;
  485: 	}
  486:     }
  487: 
  488: 	msg.sadb_msg_version = PF_KEY_V2;
  489: 	msg.sadb_msg_type = SADB_DUMP;
  490: 	msg.sadb_msg_errno = 0;
  491: 	msg.sadb_msg_satype = satype;
  492: 	msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
  493: 	msg.sadb_msg_reserved = 0;
  494: 	msg.sadb_msg_seq = 0;
  495: 	msg.sadb_msg_pid = getpid();
  496: 	buf = (char *)&msg;
  497: 	len = sizeof(msg);
  498: 
  499: 	if (f_verbose) {
  500: 		kdebug_sadb(&msg);
  501: 		printf("\n");
  502: 	}
  503: 	if (f_hexdump) {
  504: 		int i;
  505: 		for (i = 0; i < len; i++) {
  506: 			if (i % 16 == 0)
  507: 				printf("%08x: ", i);
  508: 			printf("%02x ", buf[i] & 0xff);
  509: 			if (i % 16 == 15)
  510: 				printf("\n");
  511: 		}
  512: 		if (len % 16)
  513: 			printf("\n");
  514: 	}
  515: 
  516: 	if ((l = send(so, buf, len, 0)) < 0) {
  517: 		perror("send");
  518: 		return NULL;
  519: 	}
  520: 
  521: 	m = (struct sadb_msg *)rbuf;
  522: 	do {
  523: 		if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
  524: 			perror("recv");
  525: 			fail = 1;
  526: 			break;
  527: 		}
  528: 
  529: 		if (PFKEY_UNUNIT64(m->sadb_msg_len) != l) {
  530: 			warnx("invalid keymsg length");
  531: 			fail = 1;
  532: 			break;
  533: 		}
  534: 
  535: 		if (f_verbose) {
  536: 			kdebug_sadb(m);
  537: 			printf("\n");
  538: 		}
  539: 
  540: 		if (m->sadb_msg_type != SADB_DUMP) {
  541: 			warnx("unexpected message type");
  542: 			fail = 1;
  543: 			break;
  544: 		}
  545: 
  546: 		if (m->sadb_msg_errno != 0) {
  547: 			warnx("error encountered");
  548: 			fail = 1;
  549: 			break;
  550: 		}
  551: 
  552: 		/* match satype */
  553: 		if (m->sadb_msg_satype != satype)
  554: 			continue;
  555: 
  556: 		pfkey_align(m, mhp);
  557: 		pfkey_check(mhp);
  558: 
  559: 		/* match src */
  560: 		saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
  561: 		if (saddr == NULL)
  562: 			continue;
  563: 		s = (struct sockaddr *)(saddr + 1);
  564: 		for (a = srcs; a; a = a->ai_next)
  565: 			if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0)
  566: 				break;
  567: 		if (a == NULL)
  568: 			continue;
  569: 
  570: 		/* match dst */
  571: 		saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
  572: 		if (saddr == NULL)
  573: 			continue;
  574: 		s = (struct sockaddr *)(saddr + 1);
  575: 		for (a = dsts; a; a = a->ai_next)
  576: 			if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0)
  577: 				break;
  578: 		if (a == NULL)
  579: 			continue;
  580: 
  581: 		if (*num_spi >= max_spi) {
  582: 			max_spi += 512;
  583: 			spi = realloc(spi, max_spi * sizeof(u_int32_t));
  584: 		}
  585: 
  586: 		sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
  587: 		if (sa != NULL)
  588: 			spi[(*num_spi)++] = (u_int32_t)ntohl(sa->sadb_sa_spi);
  589: 
  590: 		m = (struct sadb_msg *)((caddr_t)m + PFKEY_UNUNIT64(m->sadb_msg_len));
  591: 
  592: 		if (f_verbose) {
  593: 			kdebug_sadb(m);
  594: 			printf("\n");
  595: 		}
  596: 
  597: 	} while (m->sadb_msg_seq);
  598: 
  599: 	if (fail) {
  600: 		free(spi);
  601: 		*num_spi = 0;
  602: 		return NULL;
  603: 	}
  604: 
  605: 	return spi;
  606: }
  607: 
  608: int
  609: sendkeymsg(buf, len)
  610: 	char *buf;
  611: 	size_t len;
  612: {
  613: 	u_char rbuf[1024 * 32];	/* XXX: Enough ? Should I do MSG_PEEK ? */
  614: 	ssize_t l;
  615: 	struct sadb_msg *msg;
  616: 
  617: 	if (f_notreally) {
  618: 		goto end;
  619: 	}
  620: 
  621:     {
  622: 	struct timeval tv;
  623: 	tv.tv_sec = 1;
  624: 	tv.tv_usec = 0;
  625: 	if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
  626: 		perror("setsockopt");
  627: 		goto end;
  628: 	}
  629:     }
  630: 
  631: 	if (f_forever)
  632: 		shortdump_hdr();
  633: again:
  634: 	if (f_verbose) {
  635: 		kdebug_sadb((struct sadb_msg *)buf);
  636: 		printf("\n");
  637: 	}
  638: 	if (f_hexdump) {
  639: 		int i;
  640: 		for (i = 0; i < len; i++) {
  641: 			if (i % 16 == 0)
  642: 				printf("%08x: ", i);
  643: 			printf("%02x ", buf[i] & 0xff);
  644: 			if (i % 16 == 15)
  645: 				printf("\n");
  646: 		}
  647: 		if (len % 16)
  648: 			printf("\n");
  649: 	}
  650: 
  651: 	if ((l = send(so, buf, len, 0)) < 0) {
  652: 		perror("send");
  653: 		goto end;
  654: 	}
  655: 
  656: 	msg = (struct sadb_msg *)rbuf;
  657: 	do {
  658: 		if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
  659: 			perror("recv");
  660: 			goto end;
  661: 		}
  662: 
  663: 		if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) {
  664: 			warnx("invalid keymsg length");
  665: 			break;
  666: 		}
  667: 
  668: 		if (f_verbose) {
  669: 			kdebug_sadb(msg);
  670: 			printf("\n");
  671: 		}
  672: 		if (postproc(msg, l) < 0)
  673: 			break;
  674: 	} while (msg->sadb_msg_errno || msg->sadb_msg_seq);
  675: 
  676: 	if (f_forever) {
  677: 		fflush(stdout);
  678: 		sleep(1);
  679: 		goto again;
  680: 	}
  681: 
  682: end:
  683: 	return (0);
  684: }
  685: 
  686: int
  687: postproc(msg, len)
  688: 	struct sadb_msg *msg;
  689: 	int len;
  690: {
  691: #ifdef HAVE_PFKEY_POLICY_PRIORITY
  692: 	static int priority_support_check = 0;
  693: #endif
  694: 
  695: 	if (msg->sadb_msg_errno != 0) {
  696: 		char inf[80];
  697: 		const char *errmsg = NULL;
  698: 
  699: 		if (f_mode == MODE_SCRIPT)
  700: 			snprintf(inf, sizeof(inf), "The result of line %d: ", lineno);
  701: 		else
  702: 			inf[0] = '\0';
  703: 
  704: 		switch (msg->sadb_msg_errno) {
  705: 		case ENOENT:
  706: 			switch (msg->sadb_msg_type) {
  707: 			case SADB_DELETE:
  708: 			case SADB_GET:
  709: 			case SADB_X_SPDDELETE:
  710: 				errmsg = "No entry";
  711: 				break;
  712: 			case SADB_DUMP:
  713: 				errmsg = "No SAD entries";
  714: 				break;
  715: 			case SADB_X_SPDDUMP:
  716: 				errmsg = "No SPD entries";
  717: 				break;
  718: 			}
  719: 			break;
  720: 		default:
  721: 			errmsg = strerror(msg->sadb_msg_errno);
  722: 		}
  723: 		printf("%s%s.\n", inf, errmsg);
  724: 		return (-1);
  725: 	}
  726: 
  727: 	switch (msg->sadb_msg_type) {
  728: 	case SADB_GET:
  729: 		if (f_withports)
  730: 			pfkey_sadump_withports(msg);
  731: 		else
  732: 			pfkey_sadump(msg);
  733: 		break;
  734: 
  735: 	case SADB_DUMP:
  736: 		/* filter out DEAD SAs */
  737: 		if (!f_all) {
  738: 			caddr_t mhp[SADB_EXT_MAX + 1];
  739: 			struct sadb_sa *sa;
  740: 			pfkey_align(msg, mhp);
  741: 			pfkey_check(mhp);
  742: 			if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
  743: 				if (sa->sadb_sa_state == SADB_SASTATE_DEAD)
  744: 					break;
  745: 			}
  746: 		}
  747: 		if (f_forever) {
  748: 			/* TODO: f_withports */
  749: 			shortdump(msg);
  750: 		} else {
  751: 			if (f_withports)
  752: 				pfkey_sadump_withports(msg);
  753: 			else
  754: 				pfkey_sadump(msg);
  755: 		}
  756: 		msg = (struct sadb_msg *)((caddr_t)msg +
  757: 				     PFKEY_UNUNIT64(msg->sadb_msg_len));
  758: 		if (f_verbose) {
  759: 			kdebug_sadb((struct sadb_msg *)msg);
  760: 			printf("\n");
  761: 		}
  762: 		break;
  763: 
  764: 	case SADB_X_SPDGET:
  765: 		if (f_withports) 
  766: 			pfkey_spdump_withports(msg);
  767: 		else
  768: 			pfkey_spdump(msg);
  769: 		break;
  770: 
  771: 	case SADB_X_SPDDUMP:
  772: 		if (f_withports) 
  773: 			pfkey_spdump_withports(msg);
  774: 		else
  775: 			pfkey_spdump(msg);
  776: 		if (msg->sadb_msg_seq == 0) break;
  777: 		msg = (struct sadb_msg *)((caddr_t)msg +
  778: 				     PFKEY_UNUNIT64(msg->sadb_msg_len));
  779: 		if (f_verbose) {
  780: 			kdebug_sadb((struct sadb_msg *)msg);
  781: 			printf("\n");
  782: 		}
  783: 		break;
  784: #ifdef HAVE_PFKEY_POLICY_PRIORITY
  785: 	case SADB_X_SPDADD:
  786: 		if (last_msg_type == SADB_X_SPDADD && last_priority != 0 && 
  787: 		    msg->sadb_msg_pid == getpid() && !priority_support_check) {
  788: 			priority_support_check = 1;	
  789: 			if (!verifypriority(msg))
  790: 				printf ("WARNING: Kernel does not support policy priorities\n");
  791: 		}
  792: 		break;
  793: #endif
  794: 	}
  795: 
  796: 	return (0);
  797: }
  798: 
  799: #ifdef HAVE_PFKEY_POLICY_PRIORITY
  800: int
  801: verifypriority(m)
  802: 	struct sadb_msg *m;
  803: {
  804: 	caddr_t mhp[SADB_EXT_MAX + 1];
  805: 	struct sadb_x_policy *xpl;
  806: 
  807: 	/* check pfkey message. */
  808: 	if (pfkey_align(m, mhp)) {
  809: 		printf("(%s\n", ipsec_strerror());
  810: 		return 0;
  811: 	}
  812: 	if (pfkey_check(mhp)) {
  813: 		printf("%s\n", ipsec_strerror());
  814: 		return 0;
  815: 	}
  816: 
  817: 	xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY];
  818: 
  819: 	if (xpl == NULL) {
  820: 		printf("no X_POLICY extension.\n");
  821: 		return 0;
  822: 	}
  823: 
  824: 	/* now make sure they match */
  825: 	if (last_priority != xpl->sadb_x_policy_priority)
  826: 		return 0;
  827: 
  828: 	return 1; 
  829: }
  830: #endif
  831: 
  832: int
  833: fileproc(filename)
  834: 	const char *filename;
  835: {
  836: 	int fd;
  837: 	ssize_t len, l;
  838: 	u_char *p, *ep;
  839: 	struct sadb_msg *msg;
  840: 	u_char rbuf[1024 * 32];	/* XXX: Enough ? Should I do MSG_PEEK ? */
  841: 
  842: 	fd = open(filename, O_RDONLY);
  843: 	if (fd < 0)
  844: 		return -1;
  845: 
  846: 	l = 0;
  847: 	while (1) {
  848: 		len = read(fd, rbuf + l, sizeof(rbuf) - l);
  849: 		if (len < 0) {
  850: 			close(fd);
  851: 			return -1;
  852: 		} else if (len == 0)
  853: 			break;
  854: 		l += len;
  855: 	}
  856: 
  857: 	if (l < sizeof(struct sadb_msg)) {
  858: 		close(fd);
  859: 		errno = EINVAL;
  860: 		return -1;
  861: 	}
  862: 	close(fd);
  863: 
  864: 	p = rbuf;
  865: 	ep = rbuf + l;
  866: 
  867: 	while (p < ep) {
  868: 		msg = (struct sadb_msg *)p;
  869: 		len = PFKEY_UNUNIT64(msg->sadb_msg_len);
  870: 		postproc(msg, len);
  871: 		p += len;
  872: 	}
  873: 
  874: 	return (0);
  875: }
  876: 
  877: 
  878: /*------------------------------------------------------------*/
  879: static const char *satype[] = {
  880: 	NULL, NULL, "ah", "esp"
  881: };
  882: static const char *sastate[] = {
  883: 	"L", "M", "D", "d"
  884: };
  885: static const char *ipproto[] = {
  886: /*0*/	"ip", "icmp", "igmp", "ggp", "ip4",
  887: 	NULL, "tcp", NULL, "egp", NULL,
  888: /*10*/	NULL, NULL, NULL, NULL, NULL,
  889: 	NULL, NULL, "udp", NULL, NULL,
  890: /*20*/	NULL, NULL, "idp", NULL, NULL,
  891: 	NULL, NULL, NULL, NULL, "tp",
  892: /*30*/	NULL, NULL, NULL, NULL, NULL,
  893: 	NULL, NULL, NULL, NULL, NULL,
  894: /*40*/	NULL, "ip6", NULL, "rt6", "frag6",
  895: 	NULL, "rsvp", "gre", NULL, NULL,
  896: /*50*/	"esp", "ah", NULL, NULL, NULL,
  897: 	NULL, NULL, NULL, "icmp6", "none",
  898: /*60*/	"dst6",
  899: };
  900: 
  901: #define STR_OR_ID(x, tab) \
  902: 	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)])	? tab[(x)] : numstr(x))
  903: 
  904: const char *
  905: numstr(x)
  906: 	int x;
  907: {
  908: 	static char buf[20];
  909: 	snprintf(buf, sizeof(buf), "#%d", x);
  910: 	return buf;
  911: }
  912: 
  913: void
  914: shortdump_hdr()
  915: {
  916: 	printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n",
  917: 		"time", "p", "s", "spi", "ltime", "src", "dst");
  918: }
  919: 
  920: void
  921: shortdump(msg)
  922: 	struct sadb_msg *msg;
  923: {
  924: 	caddr_t mhp[SADB_EXT_MAX + 1];
  925: 	char buf[NI_MAXHOST], pbuf[NI_MAXSERV];
  926: 	struct sadb_sa *sa;
  927: 	struct sadb_address *saddr;
  928: 	struct sadb_lifetime *lts, *lth, *ltc;
  929: 	struct sockaddr *s;
  930: 	u_int t;
  931: 	time_t cur = time(0);
  932: 
  933: 	pfkey_align(msg, mhp);
  934: 	pfkey_check(mhp);
  935: 
  936: 	printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60));
  937: 
  938: 	printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype));
  939: 
  940: 	if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
  941: 		printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate));
  942: 		printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi));
  943: 	} else
  944: 		printf("%-1s %-8s", "?", "?");
  945: 
  946: 	lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT];
  947: 	lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
  948: 	ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT];
  949: 	if (lts && lth && ltc) {
  950: 		if (ltc->sadb_lifetime_addtime == 0)
  951: 			t = (u_long)0;
  952: 		else
  953: 			t = (u_long)(cur - ltc->sadb_lifetime_addtime);
  954: 		if (t >= 1000)
  955: 			strlcpy(buf, " big/", sizeof(buf));
  956: 		else
  957: 			snprintf(buf, sizeof(buf), " %3lu/", (u_long)t);
  958: 		printf("%s", buf);
  959: 
  960: 		t = (u_long)lth->sadb_lifetime_addtime;
  961: 		if (t >= 1000)
  962: 			strlcpy(buf, "big", sizeof(buf));
  963: 		else
  964: 			snprintf(buf, sizeof(buf), "%-3lu", (u_long)t);
  965: 		printf("%s", buf);
  966: 	} else
  967: 		printf(" ??\?/???");	/* backslash to avoid trigraph ??/ */
  968: 
  969: 	printf(" ");
  970: 
  971: 	if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) {
  972: 		if (saddr->sadb_address_proto)
  973: 			printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
  974: 		s = (struct sockaddr *)(saddr + 1);
  975: 		getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf),
  976: 			pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
  977: 		if (strcmp(pbuf, "0") != 0)
  978: 			printf("%s[%s]", buf, pbuf);
  979: 		else
  980: 			printf("%s", buf);
  981: 	} else
  982: 		printf("?");
  983: 
  984: 	printf(" -> ");
  985: 
  986: 	if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) {
  987: 		if (saddr->sadb_address_proto)
  988: 			printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
  989: 
  990: 		s = (struct sockaddr *)(saddr + 1);
  991: 		getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf),
  992: 			pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
  993: 		if (strcmp(pbuf, "0") != 0)
  994: 			printf("%s[%s]", buf, pbuf);
  995: 		else
  996: 			printf("%s", buf);
  997: 	} else
  998: 		printf("?");
  999: 
 1000: 	printf("\n");
 1001: }
 1002: 
 1003: /* From: tcpdump(1):gmt2local.c and util.c */
 1004: /*
 1005:  * Print the timestamp
 1006:  */
 1007: static void
 1008: printdate()
 1009: {
 1010: 	struct timeval tp;
 1011: 	int s;
 1012: 
 1013: 	if (gettimeofday(&tp, NULL) == -1) {
 1014: 		perror("gettimeofday");
 1015: 		return;
 1016: 	}
 1017: 
 1018: 	if (f_tflag == 1) {
 1019: 		/* Default */
 1020: 		s = (tp.tv_sec + thiszone ) % 86400;
 1021: 		(void)printf("%02d:%02d:%02d.%06u ",
 1022: 		    s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec);
 1023: 	} else if (f_tflag > 1) {
 1024: 		/* Unix timeval style */
 1025: 		(void)printf("%u.%06u ",
 1026: 		    (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec);
 1027: 	}
 1028: 
 1029: 	printf("\n");
 1030: }
 1031: 
 1032: /*
 1033:  * Returns the difference between gmt and local time in seconds.
 1034:  * Use gmtime() and localtime() to keep things simple.
 1035:  */
 1036: int32_t
 1037: gmt2local(time_t t)
 1038: {
 1039: 	register int dt, dir;
 1040: 	register struct tm *gmt, *loc;
 1041: 	struct tm sgmt;
 1042: 
 1043: 	if (t == 0)
 1044: 		t = time(NULL);
 1045: 	gmt = &sgmt;
 1046: 	*gmt = *gmtime(&t);
 1047: 	loc = localtime(&t);
 1048: 	dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
 1049: 	    (loc->tm_min - gmt->tm_min) * 60;
 1050: 
 1051: 	/*
 1052: 	 * If the year or julian day is different, we span 00:00 GMT
 1053: 	 * and must add or subtract a day. Check the year first to
 1054: 	 * avoid problems when the julian day wraps.
 1055: 	 */
 1056: 	dir = loc->tm_year - gmt->tm_year;
 1057: 	if (dir == 0)
 1058: 		dir = loc->tm_yday - gmt->tm_yday;
 1059: 	dt += dir * 24 * 60 * 60;
 1060: 
 1061: 	return (dt);
 1062: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>