예제 #1
0
int
pfkey_x_satype_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
{
	int error = 0;
	struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext;

	KLIPS_PRINT(debug_pfkey,
		    "klips_debug:pfkey_x_satype_process: .\n");

	if(!extr || !extr->ips) {
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_x_satype_process: "
			    "extr or extr->ips is NULL, fatal\n");
		SENDERR(EINVAL);
	}

	if(extr->ips2 == NULL) {
		extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */
	}
	if(extr->ips2 == NULL) {
		SENDERR(-error);
	}
	if(!(extr->ips2->ips_said.proto = satype2proto(pfkey_x_satype->sadb_x_satype_satype))) {
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_x_satype_process: "
			    "proto lookup from satype=%d failed.\n",
			    pfkey_x_satype->sadb_x_satype_satype);
		SENDERR(EINVAL);
	}
	KLIPS_PRINT(debug_pfkey,
		    "klips_debug:pfkey_x_satype_process: "
		    "protocol==%d decoded from satype==%d(%s).\n",
		    extr->ips2->ips_said.proto,
		    pfkey_x_satype->sadb_x_satype_satype,
		    satype2name(pfkey_x_satype->sadb_x_satype_satype));

errlab:
	return error;
}
예제 #2
0
int main(char *argv[], int argc)
{
  int error;
  struct sockaddr_in saddr,daddr;
  struct sockaddr_in saddr2,daddr2;

  void *main_talloc = NULL;
  struct ipsec_sa *sa, *sa1;
  char auth1[]={0x87, 0x65, 0x87, 0x65,
	       0x87, 0x65, 0x87, 0x65,
	       0x87, 0x65, 0x87, 0x65,
	       0x87, 0x65, 0x87, 0x65};
  char enc[] ={0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, 0x49,
	       0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f, 0x51,
	       0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, 0x58};

  debug_xform = 1;
  init_kmalloc();
  debug_tunnel=0xffffffff;
  debug_xmit=0xffffffff;
  sysctl_ipsec_debug_verbose = 1;
  prng_init(&ipsec_prng, seed, sizeof(seed));
  ipsec_sadb_init();
  ipsec_alg_init();

  {
    sa1 = ipsec_sa_alloc(&error);
    assert(error == 0);

    ipsec_sa_intern(sa1);

    sa1->ips_seq = 1;
    sa1->ips_pid = 10;
    
    sa1->ips_said.spi = htonl(0x12345678);
    sa1->ips_said.proto = IPPROTO_IPIP;
    sa1->ips_said.dst.u.v4.sin_addr.s_addr = htonl(0xc001022D);

    sa1->ips_state = SADB_SASTATE_MATURE;
    daddr2.sin_addr.s_addr = htonl(0xc001022D);
    saddr2.sin_addr.s_addr = htonl(0xc0010217);
    sa1->ips_addr_s = (struct sockaddr *)&saddr2;
    sa1->ips_addr_d = (struct sockaddr *)&daddr2;
  }
    
  {
    sa = ipsec_sa_alloc(&error);
    assert(error == 0);

    ipsec_sa_intern(sa);

    sa->ips_said.spi = htonl(0x12345678);
    sa->ips_said.proto = IPPROTO_ESP;
    sa->ips_said.dst.u.v4.sin_addr.s_addr = htonl(0xc001022D);
    sa->ips_said.dst.u.v4.sin_family      = AF_INET;

    sa->ips_seq = 1;
    sa->ips_pid = 10;
    sa->ips_inext = sa1;

    {
      /* make a copy so that ipsec_sa_init() can zero it out */
      char *auth = talloc_size(main_talloc, AHMD596_KLEN);

      memcpy(auth, auth1, AHMD596_KLEN);
      sa->ips_authalg = AH_MD5;
      sa->ips_key_bits_a = AHMD596_KLEN * 8;
      sa->ips_key_a = auth;
    }

    sa->ips_encalg = ESP_3DES;
    sa->ips_key_bits_e = 192;
    sa->ips_iv_bits = 128;
    sa->ips_key_e_size = 0;
    
    sa->ips_key_e = talloc_memdup(main_talloc, enc, sa->ips_key_bits_e);
    sa->ips_state = SADB_SASTATE_MATURE;
    daddr.sin_addr.s_addr = htonl(0xc001022D);
    saddr.sin_addr.s_addr = htonl(0xc0010217);
    sa->ips_addr_s = (struct sockaddr *)&saddr;
    sa->ips_addr_d = (struct sockaddr *)&daddr;

    ipsec_sa_add(sa);
    assert(ipsec_sa_init(sa) == 0);
    ipsec_sa_put(sa);
  }
    
  {
    struct ipsec_xmit_state ixs_mem;
    struct ipsec_xmit_state *ixs = &ixs_mem;
    enum ipsec_xmit_value stat;
    struct net_device_stats stats;
    int iphlen;

    struct sk_buff *skb = skbFromArray(packet2, packet2_len);

    skb->nh.raw = skb_pull(skb, skb->mac_len);
    iphlen = (skb->nh.iph->ihl<<2);

    /* do not use skb_pull, since data should stay at IP header */
    skb->h.raw = skb->nh.raw + iphlen;

    memset((caddr_t)ixs, 0, sizeof(*ixs));
    memset(&stats, 0, sizeof(stats));
    ixs->stats = &stats;
    ixs->oskb = NULL;
    ixs->saved_header = NULL;	/* saved copy of the hard header */
    ixs->route = NULL;
    memset((caddr_t)&(ixs->ips), 0, sizeof(ixs->ips));
    ixs->dev = NULL;
    ixs->skb = skb;
    ixs->physmtu = 1500;
    ixs->cur_mtu = 1500;
    ixs->outgoing_said.spi   = htonl(0x12345678);
    ixs->outgoing_said.proto = IPPROTO_ESP;
    ixs->outgoing_said.dst.u.v4.sin_family = AF_INET;
    ixs->outgoing_said.dst.u.v4.sin_addr.s_addr = htonl(0xc001022D);
    
    stat = ipsec_xmit_sanity_check_skb(ixs);
    assert(stat == IPSEC_XMIT_OK);

#if 0    
    stat = ipsec_tunnel_strip_hard_header(ixs);
    assert(stat == IPSEC_XMIT_OK);
    
    stat = ipsec_tunnel_SAlookup(ixs);
    assert(stat == IPSEC_XMIT_OK);
#endif
    
    stat = ipsec_xmit_encap_bundle(ixs);
    assert(stat == IPSEC_XMIT_OK);

#if 0
    stat = ipsec_tunnel_restore_hard_header(ixs);
#endif

    ipsec_print_ip(ixs->iph);
  }
  
  return 0;
}
예제 #3
0
int main(char *argv[], int argc)
{
	int ret;
	int error;
	struct sockaddr_in saddr, daddr;
	struct sockaddr_in saddr2, daddr2;
	void *rcv02_talloc = NULL;

	struct ipsec_sa *sa, *sa1;
	char auth1[] = { 0x87, 0x65, 0x87, 0x65,
			 0x87, 0x65, 0x87, 0x65,
			 0x87, 0x65, 0x87, 0x65,
			 0x87, 0x65, 0x87, 0x65 };
	char enc[] = { 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, 0x49,
		       0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f, 0x51,
		       0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, 0x58 };

	debug_xform = 1;
	init_kmalloc();
	debug_rcv = 0xffffffff;
	sysctl_ipsec_debug_verbose = 1;
	prng_init(&ipsec_prng, seed, sizeof(seed));
	ipsec_sadb_init();
	ipsec_alg_init();

	{
		sa1 = ipsec_sa_alloc(&error);
		assert(error == 0);

		ipsec_sa_intern(sa1);

		sa1->ips_said.spi = htonl(0x12345678);
		sa1->ips_said.proto = IPPROTO_IPIP;
		sa1->ips_said.dst.u.v4.sin_addr.s_addr = htonl(0xc001022D);

		sa1->ips_seq = 1;
		sa1->ips_pid = 10;

		sa1->ips_state = SADB_SASTATE_MATURE;
		daddr2.sin_addr.s_addr = htonl(0xc001022D);
		saddr2.sin_addr.s_addr = htonl(0xc0010217);
		sa1->ips_addr_s = (struct sockaddr *)&saddr2;
		sa1->ips_addr_d = (struct sockaddr *)&daddr2;
	}

	{
		sa = ipsec_sa_alloc(&error);
		assert(error == 0);

		ipsec_sa_intern(sa);

		sa->ips_said.spi = htonl(0x12345678);
		sa->ips_said.proto = IPPROTO_ESP;
		sa->ips_said.dst.u.v4.sin_addr.s_addr = htonl(0xc001022D);

		sa->ips_seq = 1;
		sa->ips_pid = 10;
		sa->ips_inext = sa1;

		{
			/* make a copy so that ipsec_sa_init() can zero it out */
			char *auth = talloc_size(rcv02_talloc, AHMD596_KLEN);

			memcpy(auth, auth1, AHMD596_KLEN);
			sa->ips_authalg = AH_MD5;
			sa->ips_key_bits_a = AHMD596_KLEN * 8;
			sa->ips_key_a = auth;
		}

		sa->ips_natt_type = ESPINUDP_WITH_NON_ESP;
		sa->ips_encalg = ESP_3DES;
		sa->ips_key_bits_e = 192;
		sa->ips_iv_bits = 128;
		sa->ips_key_e_size = 0;
		sa->ips_key_e = talloc_memdup(rcv02_talloc, enc,
					      sa->ips_key_bits_e);

		sa->ips_state = SADB_SASTATE_MATURE;
		daddr.sin_addr.s_addr = htonl(0xc001022D);
		saddr.sin_addr.s_addr = htonl(0xc0010217);
		sa->ips_addr_s = (struct sockaddr *)&saddr;
		sa->ips_addr_d = (struct sockaddr *)&daddr;

		ipsec_sa_init(sa);
		ipsec_sa_add(sa);
		//ipsec_sa_put(sa);
	}

	{
		int iphlen, len;
		struct iphdr *iph;
		struct sk_buff *skb = skbFromArray(packet1, packet1_len);
		skb_ethernet_ip_setup(skb);

		/* now simulate action of udp_encap_rcv */

		len = sizeof(struct udphdr);

		iph = skb->nh.iph;
		iphlen = iph->ihl << 2;
		iph->tot_len = htons(ntohs(iph->tot_len) - len);
		if (skb->len < iphlen + len) {
			/* packet is too small!?! */
			return 0;
		}

		/* pull the data buffer up to the ESP header and set the
		 * transport header to point to ESP.  Keep UDP on the stack
		 * for later.
		 */
		skb->h.raw = skb_pull(skb, len);

		/* modify the protocol (it's ESP!) */
		iph->protocol = IPPROTO_ESP;

		printf("SA natt: %d\n", sa->ips_natt_type);
		ret = klips26_rcv_encap(skb, UDP_ENCAP_ESPINUDP);
	}

	return 0;
}
예제 #4
0
int main(char *argv[], int argc)
{
  int ret;
  int error;
  struct sockaddr_in saddr,daddr;
  struct sockaddr_in saddr2,daddr2;
  void *rcv01_talloc = NULL;

  struct ipsec_sa *sa, *sa1;
  char auth1[]={0x87, 0x65, 0x87, 0x65,
	       0x87, 0x65, 0x87, 0x65,
	       0x87, 0x65, 0x87, 0x65,
	       0x87, 0x65, 0x87, 0x65};
  char enc[] ={0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, 0x49,
	       0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f, 0x51,
	       0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, 0x58};

  debug_xform = 1;
  init_kmalloc();
  debug_rcv=0xffffffff;
  sysctl_ipsec_debug_verbose = 1;
  prng_init(&ipsec_prng, seed, sizeof(seed));
  ipsec_sadb_init();
  ipsec_alg_init();

  {
    sa1 = ipsec_sa_alloc(&error);
    assert(error == 0);

    ipsec_sa_intern(sa1);

    sa1->ips_said.spi = htonl(0x12345678);
    sa1->ips_said.proto = IPPROTO_IPIP;
    sa1->ips_said.dst.u.v4.sin_addr.s_addr = htonl(0xc001022D);

    sa1->ips_seq = 1;
    sa1->ips_pid = 10;
    
    sa1->ips_state = SADB_SASTATE_MATURE;
    daddr2.sin_addr.s_addr = htonl(0xc001022D);
    saddr2.sin_addr.s_addr = htonl(0xc0010217);
    sa1->ips_addr_s = (struct sockaddr *)&saddr2;
    sa1->ips_addr_d = (struct sockaddr *)&daddr2;
  }
    
  {
    sa = ipsec_sa_alloc(&error);

    ipsec_sa_intern(sa);

    assert(error == 0);
    sa->ips_said.spi = htonl(0x12345678);
    sa->ips_said.proto = IPPROTO_ESP;
    sa->ips_said.dst.u.v4.sin_addr.s_addr = htonl(0xc001022D);

    sa->ips_seq = 1;
    sa->ips_pid = 10;
    sa->ips_inext = sa1;

    {
      /* make a copy so that ipsec_sa_init() can zero it out */
      char *auth = talloc_size(rcv01_talloc, AHMD596_KLEN);

      memcpy(auth, auth1, AHMD596_KLEN);
      sa->ips_authalg = AH_MD5;
      sa->ips_key_bits_a = AHMD596_KLEN * 8;
      sa->ips_key_a = auth;
    }

    sa->ips_encalg = ESP_3DES;
    sa->ips_key_bits_e = 192;
    sa->ips_iv_bits = 128;
    sa->ips_key_e_size = 0;
    sa->ips_key_e = talloc_memdup(rcv01_talloc, enc, sa->ips_key_bits_e);

    sa->ips_state = SADB_SASTATE_MATURE;
    daddr.sin_addr.s_addr = htonl(0xc001022D);
    saddr.sin_addr.s_addr = htonl(0xc0010217);
    sa->ips_addr_s = (struct sockaddr *)&saddr;
    sa->ips_addr_d = (struct sockaddr *)&daddr;

    ipsec_sa_add(sa);
    assert(ipsec_sa_init(sa) == 0);
    //ipsec_sa_put(sa);
  }
    
  {
    struct sk_buff *skb = skbFromArray(packet1, packet1_len);
    skb_ethernet_ip_setup(skb);

    ret = ipsec_rcv(skb);
    assert(netif_rx_count == 1);
  }
  
  ipsec_sadb_cleanup(0);  /* 0 = all protocols */

  exit(0);
}
예제 #5
0
int
pfkey_sa_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
{
	struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext;
	int error = 0;
	struct ipsec_sa* ipsp;
	
	KLIPS_PRINT(debug_pfkey,
		    "klips_debug:pfkey_sa_process: .\n");

	if(!extr || !extr->ips) {
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_sa_process: "
			    "extr or extr->ips is NULL, fatal\n");
		SENDERR(EINVAL);
	}

	switch(pfkey_ext->sadb_ext_type) {
	case SADB_EXT_SA:
		ipsp = extr->ips;
		break;
	case SADB_X_EXT_SA2:
		if(extr->ips2 == NULL) {
			extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */
		}
		if(extr->ips2 == NULL) {
			SENDERR(-error);
		}
		ipsp = extr->ips2;
		break;
	default:
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_sa_process: "
			    "invalid exttype=%d.\n",
			    pfkey_ext->sadb_ext_type);
		SENDERR(EINVAL);
	}

	ipsp->ips_said.spi = pfkey_sa->sadb_sa_spi;
	ipsp->ips_replaywin = pfkey_sa->sadb_sa_replay;
	ipsp->ips_state = pfkey_sa->sadb_sa_state;
	ipsp->ips_flags = pfkey_sa->sadb_sa_flags;
	ipsp->ips_replaywin_lastseq = ipsp->ips_replaywin_bitmap = 0;
	ipsp->ips_ref_rel = pfkey_sa->sadb_x_sa_ref;
	
	switch(ipsp->ips_said.proto) {
	case IPPROTO_AH:
		ipsp->ips_authalg = pfkey_sa->sadb_sa_auth;
		ipsp->ips_encalg = SADB_EALG_NONE;
		break;
	case IPPROTO_ESP:
		ipsp->ips_authalg = pfkey_sa->sadb_sa_auth;
		ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt;
#ifdef CONFIG_KLIPS_ALG
		ipsec_alg_sa_init(ipsp);
#endif /* CONFIG_KLIPS_ALG */
		break;
	case IPPROTO_IPIP:
		ipsp->ips_authalg = AH_NONE;
		ipsp->ips_encalg = ESP_NONE;
		break;
#ifdef CONFIG_KLIPS_IPCOMP
	case IPPROTO_COMP:
		ipsp->ips_authalg = AH_NONE;
		ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt;
		break;
#endif /* CONFIG_KLIPS_IPCOMP */
	case IPPROTO_INT:
		ipsp->ips_authalg = AH_NONE;
		ipsp->ips_encalg = ESP_NONE;
		break;
	case 0:
		break;
	default:
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_sa_process: "
			    "unknown proto=%d.\n",
			    ipsp->ips_said.proto);
		SENDERR(EINVAL);
	}

errlab:
	return error;
}
예제 #6
0
int
pfkey_address_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
{
	int error = 0;
	int saddr_len = 0;
	char ipaddr_txt[ADDRTOA_BUF];
	unsigned char **sap;
	unsigned short * portp = 0;
	struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext;
	struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address));
	struct ipsec_sa* ipsp;
	
	KLIPS_PRINT(debug_pfkey,
		    "klips_debug:pfkey_address_process:\n");
	
	if(!extr || !extr->ips) {
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "extr or extr->ips is NULL, fatal\n");
		SENDERR(EINVAL);
	}

	switch(s->sa_family) {
	case AF_INET:
		saddr_len = sizeof(struct sockaddr_in);
		addrtoa(((struct sockaddr_in*)s)->sin_addr, 0, ipaddr_txt, sizeof(ipaddr_txt));
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "found address family=%d, AF_INET, %s.\n",
			    s->sa_family,
			    ipaddr_txt);
		break;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
	case AF_INET6:
		saddr_len = sizeof(struct sockaddr_in6);
		break;
#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
	default:
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "s->sa_family=%d not supported.\n",
			    s->sa_family);
		SENDERR(EPFNOSUPPORT);
	}
	
	switch(pfkey_address->sadb_address_exttype) {
	case SADB_EXT_ADDRESS_SRC:
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "found src address.\n");
		sap = (unsigned char **)&(extr->ips->ips_addr_s);
		extr->ips->ips_addr_s_size = saddr_len;
		break;
	case SADB_EXT_ADDRESS_DST:
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "found dst address.\n");
		sap = (unsigned char **)&(extr->ips->ips_addr_d);
		extr->ips->ips_addr_d_size = saddr_len;
		break;
	case SADB_EXT_ADDRESS_PROXY:
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "found proxy address.\n");
		sap = (unsigned char **)&(extr->ips->ips_addr_p);
		extr->ips->ips_addr_p_size = saddr_len;
		break;
	case SADB_X_EXT_ADDRESS_DST2:
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "found 2nd dst address.\n");
		if(extr->ips2 == NULL) {
			extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */
		}
		if(extr->ips2 == NULL) {
			SENDERR(-error);
		}
		sap = (unsigned char **)&(extr->ips2->ips_addr_d);
		extr->ips2->ips_addr_d_size = saddr_len;
		break;
	case SADB_X_EXT_ADDRESS_SRC_FLOW:
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "found src flow address.\n");
		if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
			SENDERR(ENOMEM);
		}
		sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_src);
		portp = &(extr->eroute->er_eaddr.sen_sport);
		break;
	case SADB_X_EXT_ADDRESS_DST_FLOW:
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "found dst flow address.\n");
		if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
			SENDERR(ENOMEM);
		}
		sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_dst);
		portp = &(extr->eroute->er_eaddr.sen_dport);
		break;
	case SADB_X_EXT_ADDRESS_SRC_MASK:
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "found src mask address.\n");
		if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
			SENDERR(ENOMEM);
		}
		sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_src);
		portp = &(extr->eroute->er_emask.sen_sport);
		break;
	case SADB_X_EXT_ADDRESS_DST_MASK:
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "found dst mask address.\n");
		if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
			SENDERR(ENOMEM);
		}
		sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_dst);
		portp = &(extr->eroute->er_emask.sen_dport);
		break;
#ifdef NAT_TRAVERSAL
	case SADB_X_EXT_NAT_T_OA:
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "found NAT-OA address.\n");
		sap = (unsigned char **)&(extr->ips->ips_natt_oa);
		extr->ips->ips_natt_oa_size = saddr_len;
		break;
#endif
	default:
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "unrecognised ext_type=%d.\n",
			    pfkey_address->sadb_address_exttype);
		SENDERR(EINVAL);
	}
	
	switch(pfkey_address->sadb_address_exttype) {
	case SADB_EXT_ADDRESS_SRC:
	case SADB_EXT_ADDRESS_DST:
	case SADB_EXT_ADDRESS_PROXY:
	case SADB_X_EXT_ADDRESS_DST2:
#ifdef NAT_TRAVERSAL
	case SADB_X_EXT_NAT_T_OA:
#endif
		KLIPS_PRINT(debug_pfkey,
			    "klips_debug:pfkey_address_process: "
			    "allocating %d bytes for saddr.\n",
			    saddr_len);
		if(!(*sap = kmalloc(saddr_len, GFP_KERNEL))) {
			SENDERR(ENOMEM);
		}
		memcpy(*sap, s, saddr_len);
		break;
	default:
		if(s->sa_family	!= AF_INET) {
			KLIPS_PRINT(debug_pfkey,
				    "klips_debug:pfkey_address_process: "
				    "s->sa_family=%d not supported.\n",
				    s->sa_family);
			SENDERR(EPFNOSUPPORT);
		}
		{
			unsigned long *ulsap = (unsigned long *)sap;
			*ulsap = ((struct sockaddr_in*)s)->sin_addr.s_addr;
		}

		if (portp != 0)
			*portp = ((struct sockaddr_in*)s)->sin_port;
#ifdef CONFIG_KLIPS_DEBUG
		if(extr->eroute) {
			char buf1[64], buf2[64];
			if (debug_pfkey) {
				subnettoa(extr->eroute->er_eaddr.sen_ip_src,
					  extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1));
				subnettoa(extr->eroute->er_eaddr.sen_ip_dst,
					  extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2));
				KLIPS_PRINT(debug_pfkey,
					    "klips_debug:pfkey_address_parse: "
					    "extr->eroute set to %s:%d->%s:%d\n",
					    buf1,
					    ntohs(extr->eroute->er_eaddr.sen_sport),
					    buf2,
					    ntohs(extr->eroute->er_eaddr.sen_dport));
			}
		}
#endif /* CONFIG_KLIPS_DEBUG */
	}

	ipsp = extr->ips;
	switch(pfkey_address->sadb_address_exttype) {
	case SADB_X_EXT_ADDRESS_DST2:
		ipsp = extr->ips2;
	case SADB_EXT_ADDRESS_DST:
		if(s->sa_family == AF_INET) {
			ipsp->ips_said.dst.u.v4.sin_addr.s_addr = ((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr.s_addr;
			ipsp->ips_said.dst.u.v4.sin_family      = AF_INET;
			addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr,
				0,
				ipaddr_txt,
				sizeof(ipaddr_txt));
			KLIPS_PRINT(debug_pfkey,
				    "klips_debug:pfkey_address_process: "
				    "ips_said.dst set to %s.\n",
				    ipaddr_txt);
		} else {
			KLIPS_PRINT(debug_pfkey,
				    "klips_debug:pfkey_address_process: "
				    "uh, ips_said.dst doesn't do address family=%d yet, said will be invalid.\n",
				    s->sa_family);
		}
	default:
		break;
	}
	
	/* XXX check if port!=0 */
	
	KLIPS_PRINT(debug_pfkey,
		    "klips_debug:pfkey_address_process: successful.\n");
 errlab:
	return error;
}