if (msg->isakmp_sa == NULL)
if (!msg->isakmp_sa)
message_recv (struct message *msg){  u_int8_t *buf = msg->iov[0].iov_base;  size_t sz = msg->iov[0].iov_len;  u_int8_t exch_type;  int setup_isakmp_sa, msgid_is_zero;  u_int8_t flags;  struct keystate *ks = 0;  struct proto tmp_proto;  struct sa tmp_sa;  /* Possibly dump a raw hex image of the message to the log channel.  */  message_dump_raw ("message_recv", msg, LOG_MESSAGE);  /* Messages shorter than an ISAKMP header are bad.  */  if (sz < ISAKMP_HDR_SZ || sz != GET_ISAKMP_HDR_LENGTH (buf))    {      log_print ("message_recv: bad message length");      message_drop (msg, ISAKMP_NOTIFY_UNEQUAL_PAYLOAD_LENGTHS, 0, 1, 1);      return -1;    }  /*   * If the responder cookie is zero, this is a request to setup an ISAKMP SA.   * Otherwise the cookies should refer to an existing ISAKMP SA.   *   * XXX This is getting ugly, please reread later to see if it can be made   * nicer.   */  setup_isakmp_sa = zero_test (buf + ISAKMP_HDR_RCOOKIE_OFF,			       ISAKMP_HDR_RCOOKIE_LEN);  if (setup_isakmp_sa)    {      /*       * This might be a retransmission of a former ISAKMP SA setup message.       * If so, just drop it.       * XXX Must we really look in both the SA and exchange pools?       */      if (exchange_lookup_from_icookie (buf + ISAKMP_HDR_ICOOKIE_OFF)	  || sa_lookup_from_icookie (buf + ISAKMP_HDR_ICOOKIE_OFF))	{	  /*	   * XXX Later we should differentiate between retransmissions and	   * potential replay attacks.	   */	  LOG_DBG ((LOG_MESSAGE, 90,		    "message_recv: dropping setup for existing SA"));	  message_free (msg);	  return -1;	}    }  else    {      msg->isakmp_sa = sa_lookup_by_header (buf, 0);      if (msg->isakmp_sa)        sa_reference (msg->isakmp_sa);      /*       * If we cannot find an ISAKMP SA out of the cookies, this is either       * a responder's first reply, and we need to upgrade our exchange,       * or it's just plain invalid cookies.       */      if (!msg->isakmp_sa)	{	  msg->exchange	    = exchange_lookup_from_icookie (buf + ISAKMP_HDR_ICOOKIE_OFF);	  if (msg->exchange && msg->exchange->phase == 1	      && zero_test (msg->exchange->cookies + ISAKMP_HDR_RCOOKIE_OFF,			    ISAKMP_HDR_RCOOKIE_LEN))	    exchange_upgrade_p1 (msg);	  else	    {	      log_print ("message_recv: invalid cookie(s) %08x%08x %08x%08x",			 decode_32 (buf + ISAKMP_HDR_ICOOKIE_OFF),			 decode_32 (buf + ISAKMP_HDR_ICOOKIE_OFF + 4),			 decode_32 (buf + ISAKMP_HDR_RCOOKIE_OFF),			 decode_32 (buf + ISAKMP_HDR_RCOOKIE_OFF + 4));	      tmp_proto.sa = &tmp_sa;	      tmp_sa.doi = doi_lookup (ISAKMP_DOI_ISAKMP);	      tmp_proto.proto = ISAKMP_PROTO_ISAKMP;	      tmp_proto.spi_sz[1] = ISAKMP_HDR_COOKIES_LEN;	      tmp_proto.spi[1] = buf + ISAKMP_HDR_COOKIES_OFF;	      message_drop (msg, ISAKMP_NOTIFY_INVALID_COOKIE, &tmp_proto, 1,			    1);	      return -1;	    }#if 0	  msg->isakmp_sa	    = sa_lookup_from_icookie (buf + ISAKMP_HDR_ICOOKIE_OFF);	  if (msg->isakmp_sa)	    sa_isakmp_upgrade (msg);#endif	}      msg->exchange = exchange_lookup (buf, 1);    }  if (message_check_duplicate (msg))    return -1;  if (GET_ISAKMP_HDR_NEXT_PAYLOAD (buf) >= ISAKMP_PAYLOAD_RESERVED_MIN)    {      log_print ("message_recv: "		 "invalid payload type %d in ISAKMP header "		 "(check passphrases, if applicable and in Phase 1)",		 GET_ISAKMP_HDR_NEXT_PAYLOAD (buf));      message_drop (msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE, 0, 1, 1);      return -1;    }  /* Validate that the message is of version 1.0.  */  if (ISAKMP_VERSION_MAJOR (GET_ISAKMP_HDR_VERSION (buf)) != 1)    {      log_print ("message_recv: invalid version major %d",		 ISAKMP_VERSION_MAJOR (GET_ISAKMP_HDR_VERSION (buf)));      message_drop (msg, ISAKMP_NOTIFY_INVALID_MAJOR_VERSION, 0, 1, 1);      return -1;    }  if (ISAKMP_VERSION_MINOR (GET_ISAKMP_HDR_VERSION (buf)) != 0)    {      log_print ("message_recv: invalid version minor %d",		 ISAKMP_VERSION_MINOR (GET_ISAKMP_HDR_VERSION (buf)));      message_drop (msg, ISAKMP_NOTIFY_INVALID_MINOR_VERSION, 0, 1, 1);      return -1;    }  /*   * Validate the exchange type.  If it's a DOI-specified exchange wait until   * after all payloads have been seen for the validation as the SA payload   * might not yet have been parsed, thus the DOI might be unknown.   */  exch_type = GET_ISAKMP_HDR_EXCH_TYPE (buf);  if (exch_type == ISAKMP_EXCH_NONE      || (exch_type >= ISAKMP_EXCH_FUTURE_MIN &&	  exch_type <= ISAKMP_EXCH_FUTURE_MAX)      || (setup_isakmp_sa && exch_type >= ISAKMP_EXCH_DOI_MIN))    {      log_print ("message_recv: invalid exchange type %s",		 constant_name (isakmp_exch_cst, exch_type));      message_drop (msg, ISAKMP_NOTIFY_INVALID_EXCHANGE_TYPE, 0, 1, 1);      return -1;    }  /*   * Check for unrecognized flags, or the encryption flag when we don't   * have an ISAKMP SA to decrypt with.   */  flags = GET_ISAKMP_HDR_FLAGS (buf);  if (flags      & ~(ISAKMP_FLAGS_ENC | ISAKMP_FLAGS_COMMIT | ISAKMP_FLAGS_AUTH_ONLY))    {      log_print ("message_recv: invalid flags 0x%x",		 GET_ISAKMP_HDR_FLAGS (buf));      message_drop (msg, ISAKMP_NOTIFY_INVALID_FLAGS, 0, 1, 1);      return -1;    }  /* If we are about to setup an ISAKMP SA, the message ID must be zero.  */  msgid_is_zero = zero_test (buf + ISAKMP_HDR_MESSAGE_ID_OFF,			     ISAKMP_HDR_MESSAGE_ID_LEN);  if (setup_isakmp_sa && !msgid_is_zero)    {      log_print ("message_recv: invalid message id");      message_drop (msg, ISAKMP_NOTIFY_INVALID_MESSAGE_ID, 0, 1, 1);      return -1;    }  if (!setup_isakmp_sa && msgid_is_zero)    {      /*       * XXX Very likely redundant, look at the  else clause of the       * if (setup_isakmp_sa) statement above.       */      msg->exchange = exchange_lookup (buf, 0);      if (!msg->exchange)	{	  log_print ("message_recv: phase 1 message after ISAKMP SA is ready");	  message_free (msg);	  return -1;	}      else if (msg->exchange->last_sent)	{	  LOG_DBG ((LOG_MESSAGE, 80,		    "message_recv: resending last message from phase 1"));	  message_send (msg->exchange->last_sent);	}    }  if (flags & ISAKMP_FLAGS_ENC)    {      if (msg->isakmp_sa == NULL)	{	  LOG_DBG ((LOG_MISC, 10,		    "message_recv: no isakmp_sa for encrypted message"));	  return -1;	}      /* Decrypt rest of message using a DOI-specified IV.  */      ks = msg->isakmp_sa->doi->get_keystate (msg);      if (!ks)	{	  message_free (msg);	  return -1;	}      msg->orig = malloc (sz);      if (!msg->orig)	{	  message_free (msg);	  free (ks);	  return -1;	}      memcpy (msg->orig, buf, sz);      crypto_decrypt (ks, buf + ISAKMP_HDR_SZ, sz - ISAKMP_HDR_SZ);    }  else    msg->orig = buf;  msg->orig_sz = sz;  /* IKE packet capture */  message_packet_log (msg);  /*   * Check the overall payload structure at the same time as indexing them by   * type.   */  if (GET_ISAKMP_HDR_NEXT_PAYLOAD (buf) != ISAKMP_PAYLOAD_NONE      && message_sort_payloads (msg, GET_ISAKMP_HDR_NEXT_PAYLOAD (buf)))    {      if (ks)	free (ks);      return -1;    }  /*   * Run generic payload tests now.  If anything fails these checks, the   * message needs either to be retained for later duplicate checks or   * freed entirely.   * XXX Should SAs and even transports be cleaned up then too?   */  if (message_validate_payloads (msg))    {      if (ks)	free (ks);      return -1;    }  /* If we have not found an exchange by now something is definitely wrong.  */  if (!msg->exchange)    {      log_print ("message_recv: no exchange");      message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1);      if (ks)	free (ks);      return -1;    }  /*   * Now we can validate DOI-specific exchange types.  If we have no SA   * DOI-specific exchange types are definitely wrong.   */  if (exch_type >= ISAKMP_EXCH_DOI_MIN && exch_type <= ISAKMP_EXCH_DOI_MAX      && msg->exchange->doi->validate_exchange (exch_type))    {      log_print ("message_recv: invalid DOI exchange type %d", exch_type);      message_drop (msg, ISAKMP_NOTIFY_INVALID_EXCHANGE_TYPE, 0, 1, 1);      if (ks)	free (ks);      return -1;    }  /* Make sure the IV we used gets saved in the proper SA.  */  if (ks)    {      if (!msg->exchange->keystate)	{	  msg->exchange->keystate = ks;	  msg->exchange->crypto = ks->xf;	}      else	free (ks);    }  /* Handle the flags.  */  if (flags & ISAKMP_FLAGS_ENC)    msg->exchange->flags |= EXCHANGE_FLAG_ENCRYPT;  if ((msg->exchange->flags & EXCHANGE_FLAG_COMMITTED) == 0      && (flags & ISAKMP_FLAGS_COMMIT))    msg->exchange->flags |= EXCHANGE_FLAG_HE_COMMITTED;  /* OK let the exchange logic do the rest.  */  exchange_run (msg);  return 0;}