int ikev2_pld_payloads(struct iked *env, struct iked_message *msg, off_t offset, size_t length, u_int payload, int quick) { struct ikev2_payload pld; u_int e; int ret; u_int8_t *msgbuf = ibuf_data(msg->msg_data); /* Check if message was decrypted in an E payload */ e = msg->msg_e ? IKED_E : 0; if (quick) print_debug("%s: %spayloads", __func__, e ? "decrypted " : ""); else ikev2_pld_payloads(env, msg, offset, length, payload, 1); while (payload != 0 && offset < (off_t)length) { memcpy(&pld, msgbuf + offset, sizeof(pld)); if (quick) print_debug(" %s", print_map(payload, ikev2_payload_map)); else log_debug("%s: %spayload %s" " nextpayload %s critical 0x%02x length %d", __func__, e ? "decrypted " : "", print_map(payload, ikev2_payload_map), print_map(pld.pld_nextpayload, ikev2_payload_map), pld.pld_reserved & IKEV2_CRITICAL_PAYLOAD, betoh16(pld.pld_length)); offset += sizeof(pld); ret = 0; if (quick) goto next; switch (payload | e) { case IKEV2_PAYLOAD_SA: case IKEV2_PAYLOAD_SA | IKED_E: ret = ikev2_pld_sa(env, &pld, msg, offset); break; case IKEV2_PAYLOAD_KE: case IKEV2_PAYLOAD_KE | IKED_E: ret = ikev2_pld_ke(env, &pld, msg, offset); break; case IKEV2_PAYLOAD_IDi | IKED_E: case IKEV2_PAYLOAD_IDr | IKED_E: ret = ikev2_pld_id(env, &pld, msg, offset, payload); break; case IKEV2_PAYLOAD_CERT | IKED_E: ret = ikev2_pld_cert(env, &pld, msg, offset); break; case IKEV2_PAYLOAD_CERTREQ: case IKEV2_PAYLOAD_CERTREQ | IKED_E: ret = ikev2_pld_certreq(env, &pld, msg, offset); break; case IKEV2_PAYLOAD_AUTH | IKED_E: ret = ikev2_pld_auth(env, &pld, msg, offset); break; case IKEV2_PAYLOAD_NONCE: case IKEV2_PAYLOAD_NONCE | IKED_E: ret = ikev2_pld_nonce(env, &pld, msg, offset); break; case IKEV2_PAYLOAD_NOTIFY: case IKEV2_PAYLOAD_NOTIFY | IKED_E: ret = ikev2_pld_notify(env, &pld, msg, offset); break; case IKEV2_PAYLOAD_DELETE | IKED_E: ret = ikev2_pld_delete(env, &pld, msg, offset); break; case IKEV2_PAYLOAD_TSi | IKED_E: case IKEV2_PAYLOAD_TSr | IKED_E: ret = ikev2_pld_ts(env, &pld, msg, offset, payload); break; case IKEV2_PAYLOAD_SK: ret = ikev2_pld_e(env, &pld, msg, offset); break; case IKEV2_PAYLOAD_CP | IKED_E: ret = ikev2_pld_cp(env, &pld, msg, offset); break; case IKEV2_PAYLOAD_EAP | IKED_E: ret = ikev2_pld_eap(env, &pld, msg, offset); break; default: print_hex(msgbuf, offset, betoh16(pld.pld_length) - sizeof(pld)); break; } if (ret != 0 && ikev2_msg_frompeer(msg)) { (void)ikev2_send_informational(env, msg); return (-1); } /* Encrypted payload must appear last */ if (payload == IKEV2_PAYLOAD_SK) return (0); next: payload = pld.pld_nextpayload; offset += betoh16(pld.pld_length) - sizeof(pld); } if (quick) print_debug("\n"); return (0); }
int ikev2_pld_payloads(struct iked *env, struct iked_message *msg, size_t offset, size_t length, u_int payload) { struct ikev2_payload pld; u_int e; int ret; u_int8_t *msgbuf = ibuf_data(msg->msg_data); size_t left; /* Check if message was decrypted in an E payload */ e = msg->msg_e ? IKED_E : 0; while (payload != 0 && offset < length) { /* Bytes left in datagram. */ left = length - offset; if (ikev2_validate_pld(msg, offset, left, &pld)) return (-1); log_debug("%s: %spayload %s" " nextpayload %s critical 0x%02x length %d", __func__, e ? "decrypted " : "", print_map(payload, ikev2_payload_map), print_map(pld.pld_nextpayload, ikev2_payload_map), pld.pld_reserved & IKEV2_CRITICAL_PAYLOAD, betoh16(pld.pld_length)); /* Skip over generic payload header. */ offset += sizeof(pld); left -= sizeof(pld); ret = 0; switch (payload | e) { case IKEV2_PAYLOAD_SA: case IKEV2_PAYLOAD_SA | IKED_E: ret = ikev2_pld_sa(env, &pld, msg, offset, left); break; case IKEV2_PAYLOAD_KE: case IKEV2_PAYLOAD_KE | IKED_E: ret = ikev2_pld_ke(env, &pld, msg, offset, left); break; case IKEV2_PAYLOAD_IDi | IKED_E: case IKEV2_PAYLOAD_IDr | IKED_E: ret = ikev2_pld_id(env, &pld, msg, offset, left, payload); break; case IKEV2_PAYLOAD_CERT | IKED_E: ret = ikev2_pld_cert(env, &pld, msg, offset, left); break; case IKEV2_PAYLOAD_CERTREQ: case IKEV2_PAYLOAD_CERTREQ | IKED_E: ret = ikev2_pld_certreq(env, &pld, msg, offset, left); break; case IKEV2_PAYLOAD_AUTH | IKED_E: ret = ikev2_pld_auth(env, &pld, msg, offset, left); break; case IKEV2_PAYLOAD_NONCE: case IKEV2_PAYLOAD_NONCE | IKED_E: ret = ikev2_pld_nonce(env, &pld, msg, offset, left); break; case IKEV2_PAYLOAD_NOTIFY: case IKEV2_PAYLOAD_NOTIFY | IKED_E: ret = ikev2_pld_notify(env, &pld, msg, offset, left); break; case IKEV2_PAYLOAD_DELETE | IKED_E: ret = ikev2_pld_delete(env, &pld, msg, offset, left); break; case IKEV2_PAYLOAD_TSi | IKED_E: case IKEV2_PAYLOAD_TSr | IKED_E: ret = ikev2_pld_ts(env, &pld, msg, offset, left, payload); break; case IKEV2_PAYLOAD_SK: ret = ikev2_pld_e(env, &pld, msg, offset); break; case IKEV2_PAYLOAD_CP | IKED_E: ret = ikev2_pld_cp(env, &pld, msg, offset, left); break; case IKEV2_PAYLOAD_EAP | IKED_E: ret = ikev2_pld_eap(env, &pld, msg, offset, left); break; default: print_hex(msgbuf, offset, betoh16(pld.pld_length) - sizeof(pld)); break; } if (ret != 0 && ikev2_msg_frompeer(msg)) { (void)ikev2_send_informational(env, msg); return (-1); } /* Encrypted payload must appear last */ if (payload == IKEV2_PAYLOAD_SK) return (0); payload = pld.pld_nextpayload; offset += betoh16(pld.pld_length) - sizeof(pld); } return (0); }