Annotation of embedaddon/strongswan/src/libcharon/encoding/payloads/id_payload.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2005-2011 Martin Willi
! 3: * Copyright (C) 2010 revosec AG
! 4: * Copyright (C) 2007-2011 Tobias Brunner
! 5: * Copyright (C) 2005 Jan Hutter
! 6: * HSR Hochschule fuer Technik Rapperswil
! 7: *
! 8: * This program is free software; you can redistribute it and/or modify it
! 9: * under the terms of the GNU General Public License as published by the
! 10: * Free Software Foundation; either version 2 of the License, or (at your
! 11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 12: *
! 13: * This program is distributed in the hope that it will be useful, but
! 14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 16: * for more details.
! 17: */
! 18:
! 19: #include <stddef.h>
! 20:
! 21: #include "id_payload.h"
! 22:
! 23: #include <daemon.h>
! 24: #include <encoding/payloads/encodings.h>
! 25:
! 26: typedef struct private_id_payload_t private_id_payload_t;
! 27:
! 28: /**
! 29: * Private data of an id_payload_t object.
! 30: */
! 31: struct private_id_payload_t {
! 32:
! 33: /**
! 34: * Public id_payload_t interface.
! 35: */
! 36: id_payload_t public;
! 37:
! 38: /**
! 39: * Next payload type.
! 40: */
! 41: uint8_t next_payload;
! 42:
! 43: /**
! 44: * Critical flag.
! 45: */
! 46: bool critical;
! 47:
! 48: /**
! 49: * Reserved bits
! 50: */
! 51: bool reserved_bit[7];
! 52:
! 53: /**
! 54: * Reserved bytes
! 55: */
! 56: uint8_t reserved_byte[3];
! 57:
! 58: /**
! 59: * Length of this payload.
! 60: */
! 61: uint16_t payload_length;
! 62:
! 63: /**
! 64: * Type of the ID Data.
! 65: */
! 66: uint8_t id_type;
! 67:
! 68: /**
! 69: * The contained id data value.
! 70: */
! 71: chunk_t id_data;
! 72:
! 73: /**
! 74: * Tunneled protocol ID for IKEv1 quick modes.
! 75: */
! 76: uint8_t protocol_id;
! 77:
! 78: /**
! 79: * Tunneled port for IKEv1 quick modes.
! 80: */
! 81: uint16_t port;
! 82:
! 83: /**
! 84: * one of PLV2_ID_INITIATOR, PLV2_ID_RESPONDER, IDv1 and PLV1_NAT_OA
! 85: */
! 86: payload_type_t type;
! 87: };
! 88:
! 89: /**
! 90: * Encoding rules for an IKEv2 ID payload
! 91: */
! 92: static encoding_rule_t encodings_v2[] = {
! 93: /* 1 Byte next payload type, stored in the field next_payload */
! 94: { U_INT_8, offsetof(private_id_payload_t, next_payload) },
! 95: /* the critical bit */
! 96: { FLAG, offsetof(private_id_payload_t, critical) },
! 97: /* 7 Bit reserved bits */
! 98: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[0]) },
! 99: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[1]) },
! 100: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[2]) },
! 101: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[3]) },
! 102: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[4]) },
! 103: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[5]) },
! 104: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[6]) },
! 105: /* Length of the whole payload*/
! 106: { PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
! 107: /* 1 Byte ID type*/
! 108: { U_INT_8, offsetof(private_id_payload_t, id_type) },
! 109: /* 3 reserved bytes */
! 110: { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[0])},
! 111: { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[1])},
! 112: { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[2])},
! 113: /* some id data bytes, length is defined in PAYLOAD_LENGTH */
! 114: { CHUNK_DATA, offsetof(private_id_payload_t, id_data) },
! 115: };
! 116:
! 117: /*
! 118: 1 2 3
! 119: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
! 120: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 121: ! Next Payload !C! RESERVED ! Payload Length !
! 122: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 123: ! ID Type ! RESERVED |
! 124: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 125: ! !
! 126: ~ Identification Data ~
! 127: ! !
! 128: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 129: */
! 130:
! 131: /**
! 132: * Encoding rules for an IKEv1 ID payload
! 133: */
! 134: static encoding_rule_t encodings_v1[] = {
! 135: /* 1 Byte next payload type, stored in the field next_payload */
! 136: { U_INT_8, offsetof(private_id_payload_t, next_payload) },
! 137: /* Reserved Byte is skipped */
! 138: { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[0])},
! 139: /* Length of the whole payload*/
! 140: { PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
! 141: /* 1 Byte ID type*/
! 142: { U_INT_8, offsetof(private_id_payload_t, id_type) },
! 143: { U_INT_8, offsetof(private_id_payload_t, protocol_id) },
! 144: { U_INT_16, offsetof(private_id_payload_t, port) },
! 145: /* some id data bytes, length is defined in PAYLOAD_LENGTH */
! 146: { CHUNK_DATA, offsetof(private_id_payload_t, id_data) },
! 147: };
! 148:
! 149: /*
! 150: 1 2 3
! 151: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
! 152: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 153: ! Next Payload ! RESERVED ! Payload Length !
! 154: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 155: ! ID Type ! Protocol ID ! Port |
! 156: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 157: ! !
! 158: ~ Identification Data ~
! 159: ! !
! 160: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 161: */
! 162:
! 163: METHOD(payload_t, verify, status_t,
! 164: private_id_payload_t *this)
! 165: {
! 166: bool bad_length = FALSE;
! 167:
! 168: if ((this->type == PLV1_NAT_OA || this->type == PLV1_NAT_OA_DRAFT_00_03) &&
! 169: this->id_type != ID_IPV4_ADDR && this->id_type != ID_IPV6_ADDR)
! 170: {
! 171: DBG1(DBG_ENC, "invalid ID type %N for %N payload", id_type_names,
! 172: this->id_type, payload_type_short_names, this->type);
! 173: return FAILED;
! 174: }
! 175: switch (this->id_type)
! 176: {
! 177: case ID_IPV4_ADDR_RANGE:
! 178: case ID_IPV4_ADDR_SUBNET:
! 179: bad_length = this->id_data.len != 8;
! 180: break;
! 181: case ID_IPV6_ADDR_RANGE:
! 182: case ID_IPV6_ADDR_SUBNET:
! 183: bad_length = this->id_data.len != 32;
! 184: break;
! 185: }
! 186: if (bad_length)
! 187: {
! 188: DBG1(DBG_ENC, "invalid %N length (%d bytes)",
! 189: id_type_names, this->id_type, this->id_data.len);
! 190: return FAILED;
! 191: }
! 192: return SUCCESS;
! 193: }
! 194:
! 195: METHOD(payload_t, get_encoding_rules, int,
! 196: private_id_payload_t *this, encoding_rule_t **rules)
! 197: {
! 198: if (this->type == PLV1_ID ||
! 199: this->type == PLV1_NAT_OA || this->type == PLV1_NAT_OA_DRAFT_00_03)
! 200: {
! 201: *rules = encodings_v1;
! 202: return countof(encodings_v1);
! 203: }
! 204: *rules = encodings_v2;
! 205: return countof(encodings_v2);
! 206: }
! 207:
! 208: METHOD(payload_t, get_header_length, int,
! 209: private_id_payload_t *this)
! 210: {
! 211: return 8;
! 212: }
! 213:
! 214: METHOD(payload_t, get_type, payload_type_t,
! 215: private_id_payload_t *this)
! 216: {
! 217: return this->type;
! 218: }
! 219:
! 220: METHOD(payload_t, get_next_type, payload_type_t,
! 221: private_id_payload_t *this)
! 222: {
! 223: return this->next_payload;
! 224: }
! 225:
! 226: METHOD(payload_t, set_next_type, void,
! 227: private_id_payload_t *this, payload_type_t type)
! 228: {
! 229: this->next_payload = type;
! 230: }
! 231:
! 232: METHOD(payload_t, get_length, size_t,
! 233: private_id_payload_t *this)
! 234: {
! 235: return this->payload_length;
! 236: }
! 237:
! 238: METHOD(id_payload_t, get_identification, identification_t*,
! 239: private_id_payload_t *this)
! 240: {
! 241: return identification_create_from_encoding(this->id_type, this->id_data);
! 242: }
! 243:
! 244: /**
! 245: * Create a traffic selector from an range ID
! 246: */
! 247: static traffic_selector_t *get_ts_from_range(private_id_payload_t *this,
! 248: ts_type_t type)
! 249: {
! 250: return traffic_selector_create_from_bytes(this->protocol_id, type,
! 251: chunk_create(this->id_data.ptr, this->id_data.len / 2), this->port,
! 252: chunk_skip(this->id_data, this->id_data.len / 2), this->port ?: 65535);
! 253: }
! 254:
! 255: /**
! 256: * Create a traffic selector from an subnet ID
! 257: */
! 258: static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this,
! 259: ts_type_t type)
! 260: {
! 261: traffic_selector_t *ts;
! 262: chunk_t net, netmask;
! 263: int i;
! 264:
! 265: net = chunk_create(this->id_data.ptr, this->id_data.len / 2);
! 266: netmask = chunk_clone(chunk_skip(this->id_data, this->id_data.len / 2));
! 267: for (i = 0; i < net.len; i++)
! 268: {
! 269: netmask.ptr[i] = (netmask.ptr[i] ^ 0xFF) | net.ptr[i];
! 270: }
! 271: ts = traffic_selector_create_from_bytes(this->protocol_id, type,
! 272: net, this->port, netmask, this->port ?: 65535);
! 273: chunk_free(&netmask);
! 274: return ts;
! 275: }
! 276:
! 277: /**
! 278: * Create a traffic selector from an IP ID
! 279: */
! 280: static traffic_selector_t *get_ts_from_ip(private_id_payload_t *this,
! 281: ts_type_t type)
! 282: {
! 283: return traffic_selector_create_from_bytes(this->protocol_id, type,
! 284: this->id_data, this->port, this->id_data, this->port ?: 65535);
! 285: }
! 286:
! 287: METHOD(id_payload_t, get_ts, traffic_selector_t*,
! 288: private_id_payload_t *this)
! 289: {
! 290: switch (this->id_type)
! 291: {
! 292: case ID_IPV4_ADDR_SUBNET:
! 293: if (this->id_data.len == 8)
! 294: {
! 295: return get_ts_from_subnet(this, TS_IPV4_ADDR_RANGE);
! 296: }
! 297: break;
! 298: case ID_IPV6_ADDR_SUBNET:
! 299: if (this->id_data.len == 32)
! 300: {
! 301: return get_ts_from_subnet(this, TS_IPV6_ADDR_RANGE);
! 302: }
! 303: break;
! 304: case ID_IPV4_ADDR_RANGE:
! 305: if (this->id_data.len == 8)
! 306: {
! 307: return get_ts_from_range(this, TS_IPV4_ADDR_RANGE);
! 308: }
! 309: break;
! 310: case ID_IPV6_ADDR_RANGE:
! 311: if (this->id_data.len == 32)
! 312: {
! 313: return get_ts_from_range(this, TS_IPV6_ADDR_RANGE);
! 314: }
! 315: break;
! 316: case ID_IPV4_ADDR:
! 317: if (this->id_data.len == 4)
! 318: {
! 319: return get_ts_from_ip(this, TS_IPV4_ADDR_RANGE);
! 320: }
! 321: break;
! 322: case ID_IPV6_ADDR:
! 323: if (this->id_data.len == 16)
! 324: {
! 325: return get_ts_from_ip(this, TS_IPV6_ADDR_RANGE);
! 326: }
! 327: break;
! 328: default:
! 329: break;
! 330: }
! 331: return NULL;
! 332: }
! 333:
! 334: METHOD(id_payload_t, get_encoded, chunk_t,
! 335: private_id_payload_t *this)
! 336: {
! 337: uint16_t port = htons(this->port);
! 338: return chunk_cat("cccc", chunk_from_thing(this->id_type),
! 339: chunk_from_thing(this->protocol_id),
! 340: chunk_from_thing(port), this->id_data);
! 341: }
! 342:
! 343: METHOD2(payload_t, id_payload_t, destroy, void,
! 344: private_id_payload_t *this)
! 345: {
! 346: free(this->id_data.ptr);
! 347: free(this);
! 348: }
! 349:
! 350: /*
! 351: * Described in header.
! 352: */
! 353: id_payload_t *id_payload_create(payload_type_t type)
! 354: {
! 355: private_id_payload_t *this;
! 356:
! 357: INIT(this,
! 358: .public = {
! 359: .payload_interface = {
! 360: .verify = _verify,
! 361: .get_encoding_rules = _get_encoding_rules,
! 362: .get_header_length = _get_header_length,
! 363: .get_length = _get_length,
! 364: .get_next_type = _get_next_type,
! 365: .set_next_type = _set_next_type,
! 366: .get_type = _get_type,
! 367: .destroy = _destroy,
! 368: },
! 369: .get_identification = _get_identification,
! 370: .get_encoded = _get_encoded,
! 371: .get_ts = _get_ts,
! 372: .destroy = _destroy,
! 373: },
! 374: .next_payload = PL_NONE,
! 375: .payload_length = get_header_length(this),
! 376: .type = type,
! 377: );
! 378: return &this->public;
! 379: }
! 380:
! 381: /*
! 382: * Described in header.
! 383: */
! 384: id_payload_t *id_payload_create_from_identification(payload_type_t type,
! 385: identification_t *id)
! 386: {
! 387: private_id_payload_t *this;
! 388:
! 389: this = (private_id_payload_t*)id_payload_create(type);
! 390: this->id_data = chunk_clone(id->get_encoding(id));
! 391: this->id_type = id->get_type(id);
! 392: this->payload_length += this->id_data.len;
! 393:
! 394: return &this->public;
! 395: }
! 396:
! 397: /*
! 398: * Described in header.
! 399: */
! 400: id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts)
! 401: {
! 402: private_id_payload_t *this;
! 403: uint8_t mask;
! 404: host_t *net;
! 405:
! 406: this = (private_id_payload_t*)id_payload_create(PLV1_ID);
! 407:
! 408: if (ts->is_host(ts, NULL))
! 409: {
! 410: if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
! 411: {
! 412: this->id_type = ID_IPV4_ADDR;
! 413: }
! 414: else
! 415: {
! 416: this->id_type = ID_IPV6_ADDR;
! 417: }
! 418: this->id_data = chunk_clone(ts->get_from_address(ts));
! 419: }
! 420: else if (ts->to_subnet(ts, &net, &mask))
! 421: {
! 422: uint8_t netmask[16], len, byte;
! 423:
! 424: if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
! 425: {
! 426: this->id_type = ID_IPV4_ADDR_SUBNET;
! 427: len = 4;
! 428: }
! 429: else
! 430: {
! 431: this->id_type = ID_IPV6_ADDR_SUBNET;
! 432: len = 16;
! 433: }
! 434: memset(netmask, 0, sizeof(netmask));
! 435: for (byte = 0; byte < sizeof(netmask); byte++)
! 436: {
! 437: if (mask < 8)
! 438: {
! 439: netmask[byte] = 0xFF << (8 - mask);
! 440: break;
! 441: }
! 442: netmask[byte] = 0xFF;
! 443: mask -= 8;
! 444: }
! 445: this->id_data = chunk_cat("cc", net->get_address(net),
! 446: chunk_create(netmask, len));
! 447: net->destroy(net);
! 448: }
! 449: else
! 450: {
! 451: if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
! 452: {
! 453: this->id_type = ID_IPV4_ADDR_RANGE;
! 454: }
! 455: else
! 456: {
! 457: this->id_type = ID_IPV6_ADDR_RANGE;
! 458: }
! 459: this->id_data = chunk_cat("cc",
! 460: ts->get_from_address(ts), ts->get_to_address(ts));
! 461: net->destroy(net);
! 462: }
! 463: this->port = ts->get_from_port(ts);
! 464: this->protocol_id = ts->get_protocol(ts);
! 465: this->payload_length += this->id_data.len;
! 466:
! 467: return &this->public;
! 468: }
! 469:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>