/* create output HDR as replica of input HDR */ void echo_hdr(struct msg_digest *md, bool enc, u_int8_t np) { struct isakmp_hdr r_hdr = md->hdr; /* mostly same as incoming header */ r_hdr.isa_flags &= ~ISAKMP_FLAG_COMMIT; /* we won't ever turn on this bit */ if (enc) r_hdr.isa_flags |= ISAKMP_FLAG_ENCRYPTION; /* some day, we may have to set r_hdr.isa_version */ r_hdr.isa_np = np; if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody)) { impossible(); /* surely must have room and be well-formed */ } }
bool emit_redirect_notification_decoded_dest( v2_notification_t ntype, const ip_address *dest_ip, const char *dest_str, const chunk_t *nonce, /* optional */ pb_stream *pbs) { struct ikev2_redirect_part gwi; size_t id_len; const unsigned char *id_bytes; if (dest_ip == NULL) { id_len = strlen(dest_str); id_bytes = (const unsigned char *)dest_str; } else { passert(dest_str == NULL); switch (addrtypeof(dest_ip)) { case AF_INET: gwi.gw_identity_type = GW_IPV4; break; case AF_INET6: gwi.gw_identity_type = GW_IPV6; break; default: bad_case(addrtypeof(dest_ip)); } id_len = addrbytesptr_read(dest_ip, &id_bytes); } if (id_len > 0xFF) { /* ??? what should we do? */ loglog(RC_LOG_SERIOUS, "redirect destination longer than 255 octets; ignoring"); return false; } gwi.gw_identity_len = id_len; passert(nonce == NULL || (nonce->len >= IKEv2_MINIMUM_NONCE_SIZE && nonce->len <= IKEv2_MAXIMUM_NONCE_SIZE)); pb_stream gwid_pbs; return - emit_v2Npl(ntype, pbs, &gwid_pbs) && out_struct(&gwi, &ikev2_redirect_desc, &gwid_pbs, NULL) && out_raw(id_bytes, id_len , &gwid_pbs, "redirect ID") && (nonce == NULL || out_chunk(*nonce, &gwid_pbs, "redirect ID len")) && (close_output_pbs(&gwid_pbs), true); }
/* create output HDR as replica of input HDR */ void echo_hdr(struct msg_digest *md, bool enc, u_int8_t np) { struct isakmp_hdr r_hdr = md->hdr; /* mostly same as incoming header */ /* make sure we start with a clean buffer */ zero(reply_buffer); init_pbs(&reply_stream, reply_buffer, sizeof(reply_buffer), "reply packet"); r_hdr.isa_flags &= ~ISAKMP_FLAG_COMMIT; /* we won't ever turn on this bit */ if (enc) r_hdr.isa_flags |= ISAKMP_FLAG_ENCRYPTION; /* some day, we may have to set r_hdr.isa_version */ r_hdr.isa_np = np; if (!out_struct(&r_hdr, &isakmp_hdr_desc, &reply_stream, &md->rbody)) impossible(); /* surely must have room and be well-formed */ }
void send_v2_notification(struct state *p1st, u_int16_t type , struct state *encst , u_char *icookie , u_char *rcookie , chunk_t *n_data) { u_char buffer[1024]; pb_stream reply; pb_stream rbody; /* this function is not generic enough yet just enough for 6msg * TBD accept HDR FLAGS as arg. default ISAKMP_FLAGS_R * TBD when there is a child SA use that SPI in the notify paylod. * TBD support encrypted notifications payloads. * TBD accept Critical bit as an argument. default is set. * TBD accept exchange type as an arg, default is ISAKMP_v2_SA_INIT * do we need to send a notify with empty data? * do we need to support more Protocol ID? more than PROTO_ISAKMP */ IPSEC_dbg("sending %snotification %s to %s:%u" , encst ? "encrypted " : "" , enum_name(&ikev2_notify_names, type) , ip_str(&p1st->st_remoteaddr) , p1st->st_remoteport); if(n_data == NULL) { DBG(DBG_CONTROLMORE, DBG_log("don't send packet when notification data empty")); return; } memset(buffer, 0, sizeof(buffer)); init_pbs(&reply, buffer, sizeof(buffer), "notification msg"); /* HDR out */ { struct isakmp_hdr n_hdr ; zero(&n_hdr); /* default to 0 */ /* AAA should we copy from MD? */ n_hdr.isa_version = IKEv2_MAJOR_VERSION << ISA_MAJ_SHIFT | IKEv2_MINOR_VERSION; memcpy(n_hdr.isa_rcookie, rcookie, COOKIE_SIZE); memcpy(n_hdr.isa_icookie, icookie, COOKIE_SIZE); n_hdr.isa_xchg = ISAKMP_v2_SA_INIT; n_hdr.isa_np = ISAKMP_NEXT_v2N; n_hdr.isa_flags &= ~ISAKMP_FLAGS_I; n_hdr.isa_flags |= ISAKMP_FLAGS_R; if (!out_struct(&n_hdr, &isakmp_hdr_desc, &reply, &rbody)) { IPSEC_dbg("error initializing hdr for notify message"); return; } } chunk_t child_spi; child_spi.ptr = NULL; child_spi.len = 0; /* build and add v2N payload to the packet */ ship_v2N (ISAKMP_NEXT_NONE, ISAKMP_PAYLOAD_CRITICAL, PROTO_ISAKMP, &child_spi,type, n_data, &rbody); close_message(&rbody); close_output_pbs(&reply); clonetochunk(p1st->st_tpacket, reply.start, pbs_offset(&reply) , "notification packet"); ipsec_child_send_packet(p1st, "notification", TRUE); }