File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / libipsec / ipsec_dump_policy.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, 6 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: ipsec_dump_policy.c,v 1.9 2010/12/03 15:01:11 tteras Exp $	*/
    2: 
    3: /* Id: ipsec_dump_policy.c,v 1.10 2005/06/29 09:12:37 manubsd 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: 
   42: #include <netinet/in.h>
   43: #include PATH_IPSEC_H
   44: 
   45: #include <arpa/inet.h>
   46: 
   47: #include <stdio.h>
   48: #include <stdlib.h>
   49: #include <string.h>
   50: #include <netdb.h>
   51: 
   52: #include "ipsec_strerror.h"
   53: #include "libpfkey.h"
   54: 
   55: static const char *ipsp_dir_strs[] = {
   56: 	"any", "in", "out", "fwd",
   57: #ifdef __linux__
   58: 	"in(socket)", "out(socket)"
   59: #endif
   60: };
   61: 
   62: static const char *ipsp_policy_strs[] = {
   63: 	"discard", "none", "ipsec", "entrust", "bypass",
   64: };
   65: 
   66: static char *ipsec_dump_ipsecrequest __P((char *, size_t,
   67: 	struct sadb_x_ipsecrequest *, size_t, int));
   68: static char *ipsec_dump_policy1 __P((void *, const char *, int));
   69: static int set_addresses __P((char *, size_t, struct sockaddr *,
   70: 	struct sockaddr *, int));
   71: static char *set_address __P((char *, size_t, struct sockaddr *, int));
   72: 
   73: /*
   74:  * policy is sadb_x_policy buffer.
   75:  * Must call free() later.
   76:  * When delimiter == NULL, alternatively ' '(space) is applied.
   77:  */
   78: char *
   79: ipsec_dump_policy(policy, delimiter)
   80: 	ipsec_policy_t policy;
   81: 	__ipsec_const char *delimiter;
   82: {
   83: 	return ipsec_dump_policy1(policy, delimiter, 0);
   84: }
   85: 
   86: char *
   87: ipsec_dump_policy_withports(policy, delimiter)
   88: 	void *policy;
   89: 	const char *delimiter;
   90: {
   91: 	return ipsec_dump_policy1(policy, delimiter, 1);
   92: }
   93: 
   94: static char *
   95: ipsec_dump_policy1(policy, delimiter, withports)
   96: 	void *policy;
   97: 	const char *delimiter;
   98: 	int withports;
   99: {
  100: 	struct sadb_x_policy *xpl = policy;
  101: 	struct sadb_x_ipsecrequest *xisr;
  102: 	size_t off, buflen;
  103: 	char *buf;
  104: 	char isrbuf[1024];
  105: 	char *newbuf;
  106: 
  107: #ifdef HAVE_PFKEY_POLICY_PRIORITY
  108: 	int32_t priority_offset;
  109: 	char *priority_str;
  110: 	char operator;
  111: #endif
  112: 
  113: 	/* sanity check */
  114: 	if (policy == NULL)
  115: 		return NULL;
  116: 	if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) {
  117: 		__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
  118: 		return NULL;
  119: 	}
  120: 
  121: 	/* set delimiter */
  122: 	if (delimiter == NULL)
  123: 		delimiter = " ";
  124: 
  125: #ifdef HAVE_PFKEY_POLICY_PRIORITY
  126: 	if (xpl->sadb_x_policy_priority == 0)
  127: 	{
  128: 		priority_offset = 0;
  129: 		priority_str = "";
  130: 	}
  131: 	/* find which constant the priority is closest to */
  132: 	else if (xpl->sadb_x_policy_priority < 
  133: 	         (u_int32_t) (PRIORITY_DEFAULT / 4) * 3)
  134: 	{
  135: 		priority_offset = xpl->sadb_x_policy_priority - PRIORITY_HIGH;
  136: 		priority_str = "prio high";
  137: 	}
  138: 	else if (xpl->sadb_x_policy_priority >= 
  139: 	         (u_int32_t) (PRIORITY_DEFAULT / 4) * 3 &&
  140: 	         xpl->sadb_x_policy_priority < 
  141: 	         (u_int32_t) (PRIORITY_DEFAULT / 4) * 5)
  142: 	{
  143: 		priority_offset = xpl->sadb_x_policy_priority - PRIORITY_DEFAULT;
  144: 		priority_str = "prio def";
  145: 	}
  146: 	else
  147: 	{
  148: 		priority_offset = xpl->sadb_x_policy_priority - PRIORITY_LOW;
  149: 		priority_str = "prio low";
  150: 	}
  151: 
  152: 	/* fix sign to match the way it is input */
  153: 	priority_offset *= -1;
  154: 	if (priority_offset < 0)
  155: 	{
  156: 		operator = '-';
  157: 		priority_offset *= -1;
  158: 	}
  159: 	else
  160: 	{
  161: 		operator = '+';
  162: 	}
  163: #endif
  164: 	
  165: 	switch (xpl->sadb_x_policy_dir) {
  166: 	case IPSEC_DIR_ANY:
  167: 	case IPSEC_DIR_INBOUND:
  168: 	case IPSEC_DIR_OUTBOUND:
  169: #ifdef HAVE_POLICY_FWD
  170: 	case IPSEC_DIR_FWD:
  171: 	case IPSEC_DIR_FWD + 1:
  172: 	case IPSEC_DIR_FWD + 2:
  173: #endif
  174: 		break;
  175: 	default:
  176: 		__ipsec_errcode = EIPSEC_INVAL_DIR;
  177: 		return NULL;
  178: 	}
  179: 
  180: 	switch (xpl->sadb_x_policy_type) {
  181: 	case IPSEC_POLICY_DISCARD:
  182: 	case IPSEC_POLICY_NONE:
  183: 	case IPSEC_POLICY_IPSEC:
  184: 	case IPSEC_POLICY_BYPASS:
  185: 	case IPSEC_POLICY_ENTRUST:
  186: 		break;
  187: 	default:
  188: 		__ipsec_errcode = EIPSEC_INVAL_POLICY;
  189: 		return NULL;
  190: 	}
  191: 
  192: 	buflen = strlen(ipsp_dir_strs[xpl->sadb_x_policy_dir])
  193: 		+ 1	/* space */
  194: #ifdef HAVE_PFKEY_POLICY_PRIORITY
  195: 		+ strlen(priority_str)
  196: 		+ ((priority_offset != 0) ? 13 : 0) /* [space operator space int] */
  197: 		+ ((strlen(priority_str) != 0) ? 1 : 0) /* space */
  198: #endif
  199: 		+ strlen(ipsp_policy_strs[xpl->sadb_x_policy_type])
  200: 		+ 1;	/* NUL */
  201: 
  202: 	if ((buf = malloc(buflen)) == NULL) {
  203: 		__ipsec_errcode = EIPSEC_NO_BUFS;
  204: 		return NULL;
  205: 	}
  206: #ifdef HAVE_PFKEY_POLICY_PRIORITY
  207: 	if (priority_offset != 0)
  208: 	{
  209: 		snprintf(buf, buflen, "%s %s %c %u %s", 
  210: 	    	ipsp_dir_strs[xpl->sadb_x_policy_dir], priority_str, operator, 
  211: 			priority_offset, ipsp_policy_strs[xpl->sadb_x_policy_type]);
  212: 	}
  213: 	else if (strlen (priority_str) != 0)
  214: 	{
  215: 		snprintf(buf, buflen, "%s %s %s", 
  216: 	    	ipsp_dir_strs[xpl->sadb_x_policy_dir], priority_str, 
  217: 			ipsp_policy_strs[xpl->sadb_x_policy_type]);
  218: 	}
  219: 	else
  220: 	{
  221: 		snprintf(buf, buflen, "%s %s", 
  222: 	    	ipsp_dir_strs[xpl->sadb_x_policy_dir],
  223: 			ipsp_policy_strs[xpl->sadb_x_policy_type]);
  224: 	}
  225: #else
  226: 	snprintf(buf, buflen, "%s %s", ipsp_dir_strs[xpl->sadb_x_policy_dir],
  227: 	    ipsp_policy_strs[xpl->sadb_x_policy_type]);
  228: #endif
  229: 
  230: 	if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
  231: 		__ipsec_errcode = EIPSEC_NO_ERROR;
  232: 		return buf;
  233: 	}
  234: 
  235: 	/* count length of buffer for use */
  236: 	off = sizeof(*xpl);
  237: 	while (off < PFKEY_EXTLEN(xpl)) {
  238: 		xisr = (void *)((caddr_t)(void *)xpl + off);
  239: 		off += xisr->sadb_x_ipsecrequest_len;
  240: 	}
  241: 
  242: 	/* validity check */
  243: 	if (off != PFKEY_EXTLEN(xpl)) {
  244: 		__ipsec_errcode = EIPSEC_INVAL_SADBMSG;
  245: 		free(buf);
  246: 		return NULL;
  247: 	}
  248: 
  249: 	off = sizeof(*xpl);
  250: 	while (off < PFKEY_EXTLEN(xpl)) {
  251: 		int offset;
  252: 		xisr = (void *)((caddr_t)(void *)xpl + off);
  253: 
  254: 		if (ipsec_dump_ipsecrequest(isrbuf, sizeof(isrbuf), xisr,
  255: 		    PFKEY_EXTLEN(xpl) - off, withports) == NULL) {
  256: 			free(buf);
  257: 			return NULL;
  258: 		}
  259: 
  260: 		offset = strlen(buf);
  261: 		buflen = offset + strlen(delimiter) + strlen(isrbuf) + 1;
  262: 		newbuf = (char *)realloc(buf, buflen);
  263: 		if (newbuf == NULL) {
  264: 			__ipsec_errcode = EIPSEC_NO_BUFS;
  265: 			free(buf);
  266: 			return NULL;
  267: 		}
  268: 		buf = newbuf;
  269: 		snprintf(buf+offset, buflen-offset, "%s%s", delimiter, isrbuf);
  270: 
  271: 		off += xisr->sadb_x_ipsecrequest_len;
  272: 	}
  273: 
  274: 	__ipsec_errcode = EIPSEC_NO_ERROR;
  275: 	return buf;
  276: }
  277: 
  278: static char *
  279: ipsec_dump_ipsecrequest(buf, len, xisr, bound, withports)
  280: 	char *buf;
  281: 	size_t len;
  282: 	struct sadb_x_ipsecrequest *xisr;
  283: 	size_t bound;	/* boundary */
  284: 	int withports;
  285: {
  286: 	const char *proto, *mode, *level;
  287: 	char abuf[NI_MAXHOST * 2 + 2];
  288: 
  289: 	if (xisr->sadb_x_ipsecrequest_len > bound) {
  290: 		__ipsec_errcode = EIPSEC_INVAL_PROTO;
  291: 		return NULL;
  292: 	}
  293: 
  294: 	switch (xisr->sadb_x_ipsecrequest_proto) {
  295: 	case IPPROTO_ESP:
  296: 		proto = "esp";
  297: 		break;
  298: 	case IPPROTO_AH:
  299: 		proto = "ah";
  300: 		break;
  301: 	case IPPROTO_IPCOMP:
  302: 		proto = "ipcomp";
  303: 		break;
  304: 	default:
  305: 		__ipsec_errcode = EIPSEC_INVAL_PROTO;
  306: 		return NULL;
  307: 	}
  308: 
  309: 	switch (xisr->sadb_x_ipsecrequest_mode) {
  310: 	case IPSEC_MODE_ANY:
  311: 		mode = "any";
  312: 		break;
  313: 	case IPSEC_MODE_TRANSPORT:
  314: 		mode = "transport";
  315: 		break;
  316: 	case IPSEC_MODE_TUNNEL:
  317: 		mode = "tunnel";
  318: 		break;
  319: 	default:
  320: 		__ipsec_errcode = EIPSEC_INVAL_MODE;
  321: 		return NULL;
  322: 	}
  323: 
  324: 	abuf[0] = '\0';
  325: 	if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
  326: 		struct sockaddr *sa1, *sa2;
  327: 		caddr_t p;
  328: 
  329: 		p = (void *)(xisr + 1);
  330: 		sa1 = (void *)p;
  331: 		sa2 = (void *)(p + sysdep_sa_len(sa1));
  332: 		if (sizeof(*xisr) + sysdep_sa_len(sa1) + sysdep_sa_len(sa2) !=
  333: 		    xisr->sadb_x_ipsecrequest_len) {
  334: 			__ipsec_errcode = EIPSEC_INVAL_ADDRESS;
  335: 			return NULL;
  336: 		}
  337: 		if (set_addresses(abuf, sizeof(abuf), 
  338: 		    sa1, sa2, withports) != 0) {
  339: 			__ipsec_errcode = EIPSEC_INVAL_ADDRESS;
  340: 			return NULL;
  341: 		}
  342: 	}
  343: 
  344: 	switch (xisr->sadb_x_ipsecrequest_level) {
  345: 	case IPSEC_LEVEL_DEFAULT:
  346: 		level = "default";
  347: 		break;
  348: 	case IPSEC_LEVEL_USE:
  349: 		level = "use";
  350: 		break;
  351: 	case IPSEC_LEVEL_REQUIRE:
  352: 		level = "require";
  353: 		break;
  354: 	case IPSEC_LEVEL_UNIQUE:
  355: 		level = "unique";
  356: 		break;
  357: 	default:
  358: 		__ipsec_errcode = EIPSEC_INVAL_LEVEL;
  359: 		return NULL;
  360: 	}
  361: 
  362: 	if (xisr->sadb_x_ipsecrequest_reqid == 0)
  363: 		snprintf(buf, len, "%s/%s/%s/%s", proto, mode, abuf, level);
  364: 	else {
  365: 		int ch;
  366: 
  367: 		if (xisr->sadb_x_ipsecrequest_reqid > IPSEC_MANUAL_REQID_MAX)
  368: 			ch = '#';
  369: 		else
  370: 			ch = ':';
  371: 		snprintf(buf, len, "%s/%s/%s/%s%c%u", proto, mode, abuf, level,
  372: 		    ch, xisr->sadb_x_ipsecrequest_reqid);
  373: 	}
  374: 
  375: 	return buf;
  376: }
  377: 
  378: static int
  379: set_addresses(buf, len, sa1, sa2, withports)
  380: 	char *buf;
  381: 	size_t len;
  382: 	struct sockaddr *sa1;
  383: 	struct sockaddr *sa2;
  384: 	int withports;
  385: {
  386: 	char tmp1[NI_MAXHOST], tmp2[NI_MAXHOST];
  387: 
  388: 	if (set_address(tmp1, sizeof(tmp1), sa1, withports) == NULL ||
  389: 	    set_address(tmp2, sizeof(tmp2), sa2, withports) == NULL)
  390: 		return -1;
  391: 	if (strlen(tmp1) + 1 + strlen(tmp2) + 1 > len)
  392: 		return -1;
  393: 	snprintf(buf, len, "%s-%s", tmp1, tmp2);
  394: 	return 0;
  395: }
  396: 
  397: static char *
  398: set_address(buf, len, sa, withports)
  399: 	char *buf;
  400: 	size_t len;
  401: 	struct sockaddr *sa;
  402: 	int withports;
  403: {
  404: 	const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
  405: 	char host[NI_MAXHOST];
  406: 	char serv[NI_MAXSERV];
  407: 
  408: 	if (len < 1)
  409: 		return NULL;
  410: 	buf[0] = '\0';
  411: 	if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), host, sizeof(host), 
  412: 	    serv, sizeof(serv), niflags) != 0)
  413: 		return NULL;
  414: 
  415: 	if (withports)
  416: 		snprintf(buf, len, "%s[%s]", host, serv);
  417: 	else
  418: 		snprintf(buf, len, "%s", host);
  419: 
  420: 	return buf;
  421: }

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