void ikev2_msg_retransmit_timeout(struct iked *env, void *arg) { struct iked_message *msg = arg; struct iked_sa *sa = msg->msg_sa; if (msg->msg_tries < IKED_RETRANSMIT_TRIES) { if (sendtofrom(msg->msg_fd, ibuf_data(msg->msg_data), ibuf_size(msg->msg_data), 0, (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen, (struct sockaddr *)&msg->msg_local, msg->msg_locallen) == -1) { log_warn("%s: sendtofrom", __func__); sa_free(env, sa); return; } /* Exponential timeout */ timer_add(env, &msg->msg_timer, IKED_RETRANSMIT_TIMEOUT * (2 << (msg->msg_tries++))); } else { log_debug("%s: retransmit limit reached for msgid %u", __func__, msg->msg_msgid); sa_free(env, sa); } }
int ikev2_msg_retransmit_response(struct iked *env, struct iked_sa *sa, struct iked_message *msg) { if (sendtofrom(msg->msg_fd, ibuf_data(msg->msg_data), ibuf_size(msg->msg_data), 0, (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen, (struct sockaddr *)&msg->msg_local, msg->msg_locallen) == -1) { log_warn("%s: sendtofrom", __func__); return (-1); } timer_add(env, &msg->msg_timer, IKED_RESPONSE_TIMEOUT); return (0); }
int ikev2_msg_send(struct iked *env, struct iked_message *msg) { struct iked_sa *sa = msg->msg_sa; struct ibuf *buf = msg->msg_data; uint32_t natt = 0x00000000; int isnatt = 0; uint8_t exchange, flags; struct ike_header *hdr; struct iked_message *m; if (buf == NULL || (hdr = ibuf_seek(msg->msg_data, msg->msg_offset, sizeof(*hdr))) == NULL) return (-1); isnatt = (msg->msg_natt || (msg->msg_sa && msg->msg_sa->sa_natt)); exchange = hdr->ike_exchange; flags = hdr->ike_flags; log_info("%s: %s %s from %s to %s msgid %u, %ld bytes%s", __func__, print_map(exchange, ikev2_exchange_map), (flags & IKEV2_FLAG_RESPONSE) ? "response" : "request", print_host((struct sockaddr *)&msg->msg_local, NULL, 0), print_host((struct sockaddr *)&msg->msg_peer, NULL, 0), betoh32(hdr->ike_msgid), ibuf_length(buf), isnatt ? ", NAT-T" : ""); if (isnatt) { if (ibuf_prepend(buf, &natt, sizeof(natt)) == -1) { log_debug("%s: failed to set NAT-T", __func__); return (-1); } msg->msg_offset += sizeof(natt); } if (sendtofrom(msg->msg_fd, ibuf_data(buf), ibuf_size(buf), 0, (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen, (struct sockaddr *)&msg->msg_local, msg->msg_locallen) == -1) { log_warn("%s: sendtofrom", __func__); return (-1); } if (!sa) return (0); if ((m = ikev2_msg_copy(env, msg)) == NULL) { log_debug("%s: failed to copy a message", __func__); return (-1); } m->msg_exchange = exchange; if (flags & IKEV2_FLAG_RESPONSE) { TAILQ_INSERT_TAIL(&sa->sa_responses, m, msg_entry); timer_set(env, &m->msg_timer, ikev2_msg_response_timeout, m); timer_add(env, &m->msg_timer, IKED_RESPONSE_TIMEOUT); } else { TAILQ_INSERT_TAIL(&sa->sa_requests, m, msg_entry); timer_set(env, &m->msg_timer, ikev2_msg_retransmit_timeout, m); timer_add(env, &m->msg_timer, IKED_RETRANSMIT_TIMEOUT); } return (0); }
smcp_status_t smcp_plat_outbound_finish(smcp_t self,const uint8_t* data_ptr, coap_size_t data_len, int flags) { SMCP_EMBEDDED_SELF_HOOK; smcp_status_t ret = SMCP_STATUS_FAILURE; ssize_t sent_bytes = -1; int fd; #if SMCP_DTLS if (smcp_plat_get_session_type() == SMCP_SESSION_TYPE_DTLS) { ret = smcp_plat_ssl_outbound_packet_process(self, data_ptr, data_len); } else #endif if (smcp_plat_get_session_type() == SMCP_SESSION_TYPE_UDP) { fd = smcp_get_current_instance()->plat.fd_udp; assert(fd >= 0); require(data_len > 0, bail); #if VERBOSE_DEBUG { char addr_str[50] = "???"; uint16_t port = ntohs(smcp_plat_get_remote_sockaddr()->smcp_port); SMCP_ADDR_NTOP(addr_str,sizeof(addr_str),&smcp_plat_get_remote_sockaddr()->smcp_addr); DEBUG_PRINTF("smcp(%p): Outbound packet to [%s]:%d", self,addr_str,(int)port); coap_dump_header( SMCP_DEBUG_OUT_FILE, "Outbound:\t", (struct coap_header_s*)data_ptr, (coap_size_t)data_len ); } #endif sent_bytes = sendtofrom( fd, data_ptr, data_len, 0, (struct sockaddr *)smcp_plat_get_remote_sockaddr(), sizeof(smcp_sockaddr_t), (struct sockaddr *)smcp_plat_get_local_sockaddr(), sizeof(smcp_sockaddr_t) ); require_action_string( (sent_bytes >= 0), bail, ret = SMCP_STATUS_ERRNO, strerror(errno) ); require_action_string( (sent_bytes == data_len), bail, ret = SMCP_STATUS_FAILURE, "sendto() returned less than len" ); ret = SMCP_STATUS_OK; } else { ret = SMCP_STATUS_NOT_IMPLEMENTED; } bail: return ret; }