case IPSEC_ESP_DES: case IPSEC_ESP_DES_IV32: case IPSEC_ESP_DES_IV64: emsg->em_alg = XF_ESPDES; break;
klips_set_spi (struct sa *sa, struct proto *proto, int incoming){  struct encap_msghdr *emsg = 0;  struct ipsec_proto *iproto = proto->data;  struct sockaddr *dst, *src;  int dstlen, srclen, keylen, hashlen;  size_t len;  struct ipe4_xdata *ip4x;  /* Actually works for all.  */  struct espblkrply_edata *edx;  /* Actually works for all.  */  struct ahhmacmd5_edata *amx;  switch (proto->proto)    {    case IPSEC_PROTO_IPSEC_ESP:      keylen = ipsec_esp_enckeylength (proto);      hashlen = ipsec_esp_authkeylength (proto);      len = EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN;      emsg = calloc (1, len);      if (!emsg)	return -1;      emsg->em_proto = IPPROTO_ESP;      edx = (struct espblkrply_edata *)emsg->em_dat;      /* Funny expression due to I just want one switch.  */      switch (proto->id | (iproto->auth << 8))	{	case IPSEC_ESP_DES:	case IPSEC_ESP_DES_IV32:	case IPSEC_ESP_DES_IV64:	  emsg->em_alg = XF_ESPDES;	  break;	case IPSEC_ESP_3DES:	  emsg->em_alg = XF_ESP3DES;	  break;	case IPSEC_ESP_DES | (IPSEC_AUTH_HMAC_MD5 << 8):	case IPSEC_ESP_DES_IV32 | (IPSEC_AUTH_HMAC_MD5 << 8):	case IPSEC_ESP_DES_IV64 | (IPSEC_AUTH_HMAC_MD5 << 8):	  emsg->em_alg = XF_ESPDESMD596;	  break;	case IPSEC_ESP_3DES | (IPSEC_AUTH_HMAC_MD5 << 8):	  emsg->em_alg = XF_ESP3DESMD596;	  break;	case IPSEC_ESP_DES | (IPSEC_AUTH_HMAC_SHA << 8):	case IPSEC_ESP_DES_IV32 | (IPSEC_AUTH_HMAC_SHA << 8):	case IPSEC_ESP_DES_IV64 | (IPSEC_AUTH_HMAC_SHA << 8):	  emsg->em_alg = XF_ESPDESSHA196;	  break;	case IPSEC_ESP_3DES | (IPSEC_AUTH_HMAC_SHA << 8):	  emsg->em_alg = XF_ESP3DESSHA196;	  break;	default:	  LOG_DBG ((LOG_SYSDEP, 10, 		    "klips_set_spi: Unsupported enc/auth alg negotiated"));	  return -1;	}      /* XXX What if we have a protocol requiring IV?  */      edx->eme_ivlen = EMT_ESPDES_IV_SZ;      edx->eme_klen = keylen;      edx->ame_klen = hashlen;#if 0      /* I have reason to believe Shared-SADB won't work at all in KLIPS.  */      edx->eme_ooowin	= conf_get_str ("General", "Shared-SADB") ? 0 : iproto->replay_window;#else      edx->eme_ooowin = iproto->replay_window;#endif      /*       * XXX Pluto sets the unused by KLIPS flag EME_INITIATOR in       * edx->eme_flags, if the party is the initiator.  Should we too?       */      edx->eme_flags = 0;      memcpy (edx->eme_key, iproto->keymat[incoming], keylen);      if (iproto->auth)	memcpy (edx->ame_key, iproto->keymat[incoming] + keylen, hashlen);      break;    case IPSEC_PROTO_IPSEC_AH:      hashlen = ipsec_ah_keylength (proto);      len = EMT_SETSPI_FLEN + AH_NEW_XENCAP_LEN + hashlen;      emsg = calloc (1, len);      if (!emsg)	return -1;      emsg->em_proto = IPPROTO_AH;      amx = (struct ahhmacmd5_edata *)emsg->em_dat;      switch (proto->id)	{	case IPSEC_AH_MD5:	  emsg->em_alg = XF_AHHMACMD5;	  break;	case IPSEC_AH_SHA:	  emsg->em_alg = XF_AHHMACSHA1;	  break;	default:	  /* XXX Log?  */	  goto cleanup;	}      /* XXX Should we be able to send in different lengths here?  */      amx->ame_alen = amx->ame_klen = hashlen;#if 0      /* I have reason to believe Shared-SADB won't work at all in KLIPS.  */      amx->ame_ooowin	= conf_get_str ("General", "Shared-SADB") ? 0 : iproto->replay_window;#else      amx->ame_ooowin = iproto->replay_window;#endif      amx->ame_replayp = amx->ame_ooowin > 0;      memcpy (amx->ame_key, iproto->keymat[incoming], hashlen);      break;    default:      /* XXX Log?  */      goto cleanup;    }  emsg->em_msglen = len;  emsg->em_type = EMT_SETSPI;  memcpy (&emsg->em_spi, proto->spi[incoming], sizeof emsg->em_spi);  emsg->em_flags = incoming ? EMT_INBOUND : 0;  /*   * XXX Addresses has to be thought through.  Assumes IPv4.   */  sa->transport->vtbl->get_dst (sa->transport, &dst, &dstlen);  sa->transport->vtbl->get_src (sa->transport, &src, &srclen);  emsg->em_dst    = ((struct sockaddr_in *)(incoming ? src : dst))->sin_addr;  /*   * Klips does not know about expirations, thus we need to do them inside   * isakmpd.   */  if (sa->seconds)    if (sa_setup_expirations (sa))      goto cleanup;  LOG_DBG ((LOG_SYSDEP, 10, "klips_set_spi: proto %d dst %s SPI 0x%x",	    emsg->em_proto, inet_ntoa (emsg->em_dst), htonl (emsg->em_spi)));  if (klips_write (emsg))    goto cleanup;  free (emsg);  /* If we are tunneling we have to setup an IP in IP tunnel too.  */  if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL)    {      len = EMT_SETSPI_FLEN + EMT_IPE4_ULEN;      emsg = calloc (1, len);      if (!emsg)	goto cleanup;      emsg->em_proto = IPPROTO_IPIP;      emsg->em_msglen = len;      emsg->em_type = EMT_SETSPI;      /*       * XXX Code in Pluto suggests this is not possible, but that we have       * to have a unique SPI for the IP4 SA.       */      memcpy (&emsg->em_spi, proto->spi[incoming], sizeof emsg->em_spi);      emsg->em_flags = 0;      emsg->em_alg = XF_IP4;      ip4x = (struct ipe4_xdata *)emsg->em_dat;      ip4x->i4_dst = emsg->em_dst	= ((struct sockaddr_in *)(incoming ? src : dst))->sin_addr;      ip4x->i4_src	= ((struct sockaddr_in *)(incoming ? dst : src))->sin_addr;      LOG_DBG ((LOG_SYSDEP, 10, "klips_set_spi: proto %d dst %s SPI 0x%x",		emsg->em_proto, inet_ntoa (emsg->em_dst),		htonl (emsg->em_spi)));      if (klips_write (emsg))	goto cleanup;      free (emsg);      /*       * Grouping the IP-in-IP SA with the IPSec one means we must be careful       * in klips_group_spis so that we'll remove duplicate IP-in-IP SAs       * and get everything grouped in the right order.       *       * XXX Could we not share code with klips_group_spis here?       */      emsg = calloc (1, EMT_GRPSPIS_FLEN + 2 * EMT_GRPSPIS_COMPLEN);      if (!emsg)	goto cleanup;      emsg->em_msglen = EMT_GRPSPIS_FLEN + 2 * EMT_GRPSPIS_COMPLEN;      emsg->em_type = EMT_GRPSPIS;      memcpy (&emsg->em_rel[0].emr_spi, proto->spi[incoming],	      sizeof emsg->em_rel[0].emr_spi);      memcpy (&emsg->em_rel[1].emr_spi, proto->spi[incoming],	      sizeof emsg->em_rel[1].emr_spi);      emsg->em_rel[0].emr_dst = emsg->em_rel[1].emr_dst	= ((struct sockaddr_in *)(incoming ? src : dst))->sin_addr;      emsg->em_rel[0].emr_proto = IPPROTO_IPIP;      /* XXX What if IPCOMP etc. comes along?  */      emsg->em_rel[1].emr_proto	= proto->proto == IPSEC_PROTO_IPSEC_ESP ? IPPROTO_ESP : IPPROTO_AH;      if (klips_write (emsg))	goto cleanup;      free (emsg);    }  LOG_DBG ((LOG_SYSDEP, 50, "klips_set_spi: done"));  return 0; cleanup:  /* XXX Cleanup the potential SAs we have setup.  */  if (emsg)    free (emsg);  return -1;}