Annotation of embedaddon/ipsec-tools/src/libipsec/ipsec_dump_policy.c, revision 1.1
1.1 ! misho 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>