/* * @(#) RFC2367 PF_KEYv2 Key management API message parser * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * RCSID $Id: pfkey_v2_parser.c,v 1.4 2004/09/29 22:27:41 as Exp $ */ /* * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. */ char pfkey_v2_parser_c_version[] = "$Id: pfkey_v2_parser.c,v 1.4 2004/09/29 22:27:41 as Exp $"; #include #include #include /* printk() */ #include "freeswan/ipsec_param.h" #ifdef MALLOC_SLAB # include /* kmalloc() */ #else /* MALLOC_SLAB */ # include /* kmalloc() */ #endif /* MALLOC_SLAB */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #include #include #ifdef SPINLOCK # ifdef SPINLOCK_23 # include /* *lock* */ # else /* SPINLOCK_23 */ # include /* *lock* */ # endif /* SPINLOCK_23 */ #endif /* SPINLOCK */ #ifdef NET_21 # include # include # define ip_chk_addr inet_addr_type # define IS_MYADDR RTN_LOCAL #endif #include #include #ifdef NETLINK_SOCK # include #else # include #endif #include /* get_random_bytes() */ #include "freeswan/radij.h" #include "freeswan/ipsec_encap.h" #include "freeswan/ipsec_sa.h" #include "freeswan/ipsec_radij.h" #include "freeswan/ipsec_xform.h" #include "freeswan/ipsec_ah.h" #include "freeswan/ipsec_esp.h" #include "freeswan/ipsec_tunnel.h" #include "freeswan/ipsec_rcv.h" #include "freeswan/ipcomp.h" #include #include #include "freeswan/ipsec_proto.h" #include "freeswan/ipsec_alg.h" #define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) struct sklist_t { struct socket *sk; struct sklist_t* next; } pfkey_sklist_head, *pfkey_sklist, *pfkey_sklist_prev; __u32 pfkey_msg_seq = 0; int pfkey_alloc_eroute(struct eroute** eroute) { int error = 0; if(*eroute) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_alloc_eroute: " "eroute struct already allocated\n"); SENDERR(EEXIST); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_alloc_eroute: " "allocating %lu bytes for an eroute.\n", (unsigned long) sizeof(**eroute)); if((*eroute = kmalloc(sizeof(**eroute), GFP_ATOMIC) ) == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_alloc_eroute: " "memory allocation error\n"); SENDERR(ENOMEM); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_alloc_eroute: " "allocated eroute struct=0p%p.\n", eroute); memset((caddr_t)*eroute, 0, sizeof(**eroute)); (*eroute)->er_eaddr.sen_len = (*eroute)->er_emask.sen_len = sizeof(struct sockaddr_encap); (*eroute)->er_eaddr.sen_family = (*eroute)->er_emask.sen_family = AF_ENCAP; (*eroute)->er_eaddr.sen_type = SENT_IP4; (*eroute)->er_emask.sen_type = 255; (*eroute)->er_pid = 0; (*eroute)->er_count = 0; (*eroute)->er_lasttime = jiffies/HZ; errlab: return(error); } DEBUG_NO_STATIC int pfkey_x_protocol_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; struct sadb_protocol * p = (struct sadb_protocol *)pfkey_ext; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process: %p\n", extr); if (extr == 0) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process:" "extr is NULL, fatal\n"); SENDERR(EINVAL); } if (extr->eroute == 0) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process:" "extr->eroute is NULL, fatal\n"); SENDERR(EINVAL); } extr->eroute->er_eaddr.sen_proto = p->sadb_protocol_proto; extr->eroute->er_emask.sen_proto = p->sadb_protocol_proto ? ~0:0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process: protocol = %d.\n", p->sadb_protocol_proto); errlab: return error; } DEBUG_NO_STATIC int pfkey_ipsec_sa_init(struct ipsec_sa *ipsp, struct sadb_ext **extensions) { int error = 0; char sa[SATOA_BUF]; size_t sa_len; char ipaddr_txt[ADDRTOA_BUF]; char ipaddr2_txt[ADDRTOA_BUF]; #if defined (CONFIG_IPSEC_AUTH_HMAC_MD5) || defined (CONFIG_IPSEC_AUTH_HMAC_SHA1) int i; unsigned char kb[AHMD596_BLKLEN]; #endif #ifdef CONFIG_IPSEC_ALG struct ipsec_alg_enc *ixt_e = NULL; struct ipsec_alg_auth *ixt_a = NULL; #endif /* CONFIG_IPSEC_ALG */ if(ipsp == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "ipsp is NULL, fatal\n"); SENDERR(EINVAL); } sa_len = satoa(ipsp->ips_said, 0, sa, SATOA_BUF); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "(pfkey defined) called for SA:%s\n", sa_len ? sa : " (error)"); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "calling init routine of %s%s%s\n", IPS_XFORM_NAME(ipsp)); switch(ipsp->ips_said.proto) { #ifdef CONFIG_IPSEC_IPIP case IPPROTO_IPIP: { addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_s))->sin_addr, 0, ipaddr_txt, sizeof(ipaddr_txt)); addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr, 0, ipaddr2_txt, sizeof(ipaddr_txt)); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "(pfkey defined) IPIP ipsec_sa set for %s->%s.\n", ipaddr_txt, ipaddr2_txt); } break; #endif /* !CONFIG_IPSEC_IPIP */ #ifdef CONFIG_IPSEC_AH case IPPROTO_AH: switch(ipsp->ips_authalg) { # ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 case AH_MD5: { unsigned char *akp; unsigned int aks; MD5_CTX *ictx; MD5_CTX *octx; if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHMD596_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "hmac md5-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHMD596_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "allocating %lu bytes for md5_ctx.\n", (unsigned long) sizeof(struct md5_ctx)); if((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct md5_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { kb[i] = akp[i] ^ HMAC_IPAD; } for (; i < AHMD596_BLKLEN; i++) { kb[i] = HMAC_IPAD; } ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); MD5Init(ictx); MD5Update(ictx, kb, AHMD596_BLKLEN); for (i = 0; i < AHMD596_BLKLEN; i++) { kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); } octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); MD5Init(octx); MD5Update(octx, kb, AHMD596_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* zero key buffer -- paranoid */ memset(akp, 0, aks); kfree(akp); } break; # endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ # ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 case AH_SHA: { unsigned char *akp; unsigned int aks; SHA1_CTX *ictx; SHA1_CTX *octx; if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHSHA196_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "allocating %lu bytes for sha1_ctx.\n", (unsigned long) sizeof(struct sha1_ctx)); if((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct sha1_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { kb[i] = akp[i] ^ HMAC_IPAD; } for (; i < AHMD596_BLKLEN; i++) { kb[i] = HMAC_IPAD; } ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); SHA1Init(ictx); SHA1Update(ictx, kb, AHSHA196_BLKLEN); for (i = 0; i < AHSHA196_BLKLEN; i++) { kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); } octx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->octx); SHA1Init(octx); SHA1Update(octx, kb, AHSHA196_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* zero key buffer -- paranoid */ memset(akp, 0, aks); kfree(akp); } break; # endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "authalg=%d support not available in the kernel", ipsp->ips_authalg); SENDERR(EINVAL); } break; #endif /* CONFIG_IPSEC_AH */ #ifdef CONFIG_IPSEC_ESP case IPPROTO_ESP: { #if defined (CONFIG_IPSEC_AUTH_HMAC_MD5) || defined (CONFIG_IPSEC_AUTH_HMAC_SHA1) unsigned char *akp; unsigned int aks; #endif #if defined (CONFIG_IPSEC_ENC_3DES) unsigned char *ekp; unsigned int eks; #endif ipsp->ips_iv_size = 0; #ifdef CONFIG_IPSEC_ALG if ((ixt_e=ipsp->ips_alg_enc)) { ipsp->ips_iv_size = ixt_e->ixt_ivlen/8; } else #endif /* CONFIG_IPSEC_ALG */ switch(ipsp->ips_encalg) { # ifdef CONFIG_IPSEC_ENC_3DES case ESP_3DES: # endif /* CONFIG_IPSEC_ENC_3DES */ # if defined(CONFIG_IPSEC_ENC_3DES) KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "allocating %u bytes for iv.\n", EMT_ESPDES_IV_SZ); if((ipsp->ips_iv = (caddr_t) kmalloc((ipsp->ips_iv_size = EMT_ESPDES_IV_SZ), GFP_ATOMIC)) == NULL) { SENDERR(ENOMEM); } prng_bytes(&ipsec_prng, (char *)ipsp->ips_iv, EMT_ESPDES_IV_SZ); ipsp->ips_iv_bits = ipsp->ips_iv_size * 8; ipsp->ips_iv_size = EMT_ESPDES_IV_SZ; break; # endif /* defined(CONFIG_IPSEC_ENC_3DES) */ case ESP_NONE: break; default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "encalg=%d support not available in the kernel", ipsp->ips_encalg); SENDERR(EINVAL); } /* Create IV */ if (ipsp->ips_iv_size) { if((ipsp->ips_iv = (caddr_t) kmalloc(ipsp->ips_iv_size, GFP_ATOMIC)) == NULL) { SENDERR(ENOMEM); } prng_bytes(&ipsec_prng, (char *)ipsp->ips_iv, ipsp->ips_iv_size); ipsp->ips_iv_bits = ipsp->ips_iv_size * 8; } #ifdef CONFIG_IPSEC_ALG if (ixt_e) { if ((error=ipsec_alg_enc_key_create(ipsp)) < 0) SENDERR(-error); } else #endif /* CONFIG_IPSEC_ALG */ switch(ipsp->ips_encalg) { # ifdef CONFIG_IPSEC_ENC_3DES case ESP_3DES: if(ipsp->ips_key_bits_e != (EMT_ESP3DES_KEY_SZ * 8)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "incorrect encryption key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ipsp->ips_key_bits_e, EMT_ESP3DES_KEY_SZ * 8); SENDERR(EINVAL); } /* save encryption key pointer */ ekp = ipsp->ips_key_e; eks = ipsp->ips_key_e_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "allocating %lu bytes for 3des.\n", (unsigned long) (3 * sizeof(struct des_eks))); if((ipsp->ips_key_e = (caddr_t) kmalloc(3 * sizeof(struct des_eks), GFP_ATOMIC)) == NULL) { ipsp->ips_key_e = ekp; SENDERR(ENOMEM); } ipsp->ips_key_e_size = 3 * sizeof(struct des_eks); for(i = 0; i < 3; i++) { #if KLIPS_DIVULGE_CYPHER_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "3des key %d/3 is 0x%08x%08x\n", i + 1, ntohl(*((__u32 *)ekp + i * 2)), ntohl(*((__u32 *)ekp + i * 2 + 1))); # endif #if KLIPS_FIXES_DES_PARITY /* force parity */ des_set_odd_parity((des_cblock *)(ekp + EMT_ESPDES_KEY_SZ * i)); #endif error = des_set_key((des_cblock *)(ekp + EMT_ESPDES_KEY_SZ * i), ((struct des_eks *)(ipsp->ips_key_e))[i].ks); if (error == -1) printk("klips_debug:pfkey_ipsec_sa_init: " "parity error in des key %d/3\n", i + 1); else if (error == -2) printk("klips_debug:pfkey_ipsec_sa_init: " "illegal weak des key %d/3\n", i + 1); if (error) { memset(ekp, 0, eks); kfree(ekp); SENDERR(EINVAL); } } /* paranoid */ memset(ekp, 0, eks); kfree(ekp); break; # endif /* CONFIG_IPSEC_ENC_3DES */ case ESP_NONE: break; default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "encalg=%d support not available in the kernel", ipsp->ips_encalg); SENDERR(EINVAL); } #ifdef CONFIG_IPSEC_ALG if ((ixt_a=ipsp->ips_alg_auth)) { if ((error=ipsec_alg_auth_key_create(ipsp)) < 0) SENDERR(-error); } else #endif /* CONFIG_IPSEC_ALG */ switch(ipsp->ips_authalg) { # ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 case AH_MD5: { MD5_CTX *ictx; MD5_CTX *octx; if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHMD596_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "hmac md5-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)(ipsp->ips_key_a))+0)), ntohl(*(((__u32 *)(ipsp->ips_key_a))+1)), ntohl(*(((__u32 *)(ipsp->ips_key_a))+2)), ntohl(*(((__u32 *)(ipsp->ips_key_a))+3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHMD596_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "allocating %lu bytes for md5_ctx.\n", (unsigned long) sizeof(struct md5_ctx)); if((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct md5_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { kb[i] = akp[i] ^ HMAC_IPAD; } for (; i < AHMD596_BLKLEN; i++) { kb[i] = HMAC_IPAD; } ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); MD5Init(ictx); MD5Update(ictx, kb, AHMD596_BLKLEN); for (i = 0; i < AHMD596_BLKLEN; i++) { kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); } octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); MD5Init(octx); MD5Update(octx, kb, AHMD596_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* paranoid */ memset(akp, 0, aks); kfree(akp); break; } # endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */ # ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 case AH_SHA: { SHA1_CTX *ictx; SHA1_CTX *octx; if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHSHA196_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "allocating %lu bytes for sha1_ctx.\n", (unsigned long) sizeof(struct sha1_ctx)); if((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct sha1_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { kb[i] = akp[i] ^ HMAC_IPAD; } for (; i < AHMD596_BLKLEN; i++) { kb[i] = HMAC_IPAD; } ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); SHA1Init(ictx); SHA1Update(ictx, kb, AHSHA196_BLKLEN); for (i = 0; i < AHSHA196_BLKLEN; i++) { kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); } octx = &((struct sha1_ctx*)(ipsp->ips_key_a))->octx; SHA1Init(octx); SHA1Update(octx, kb, AHSHA196_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_ipsec_sa_init: " "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ memset(akp, 0, aks); kfree(akp); break; } # endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ case AH_NONE: break; default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "authalg=%d support not available in the kernel.\n", ipsp->ips_authalg); SENDERR(EINVAL); } } break; #endif /* !CONFIG_IPSEC_ESP */ #ifdef CONFIG_IPSEC_IPCOMP case IPPROTO_COMP: ipsp->ips_comp_adapt_tries = 0; ipsp->ips_comp_adapt_skip = 0; ipsp->ips_comp_ratio_cbytes = 0; ipsp->ips_comp_ratio_dbytes = 0; break; #endif /* CONFIG_IPSEC_IPCOMP */ default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ipsec_sa_init: " "proto=%d unknown.\n", ipsp->ips_said.proto); SENDERR(EINVAL); } errlab: return(error); } int pfkey_safe_build(int error, struct sadb_ext *extensions[SADB_MAX+1]) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build: " "error=%d\n", error); if (!error) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:" "success.\n"); return 1; } else { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:" "caught error %d\n", error); pfkey_extensions_free(extensions); return 0; } } DEBUG_NO_STATIC int pfkey_getspi_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; ipsec_spi_t minspi = htonl(256), maxspi = htonl(-1L); int found_avail = 0; struct ipsec_sa *ipsq; char sa[SATOA_BUF]; size_t sa_len; struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: .\n"); pfkey_extensions_init(extensions_reply); if(extr == NULL || extr->ips == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "error, extr or extr->ipsec_sa pointer NULL\n"); SENDERR(EINVAL); } if(extensions[SADB_EXT_SPIRANGE]) { minspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_min; maxspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_max; } if(maxspi == minspi) { extr->ips->ips_said.spi = maxspi; ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); if(ipsq != NULL) { sa_len = satoa(extr->ips->ips_said, 0, sa, SATOA_BUF); ipsec_sa_put(ipsq); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "EMT_GETSPI found an old ipsec_sa for SA: %s, delete it first.\n", sa_len ? sa : " (error)"); SENDERR(EEXIST); } else { found_avail = 1; } } else { int i = 0; __u32 rand_val; __u32 spi_diff; while( ( i < (spi_diff = (ntohl(maxspi) - ntohl(minspi)))) && !found_avail ) { prng_bytes(&ipsec_prng, (char *) &(rand_val), ( (spi_diff < (2^8)) ? 1 : ( (spi_diff < (2^16)) ? 2 : ( (spi_diff < (2^24)) ? 3 : 4 ) ) ) ); extr->ips->ips_said.spi = htonl(ntohl(minspi) + (rand_val % (spi_diff + 1))); i++; ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); if(ipsq == NULL) { found_avail = 1; } else { ipsec_sa_put(ipsq); } } } sa_len = satoa(extr->ips->ips_said, 0, sa, SATOA_BUF); if (!found_avail) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "found an old ipsec_sa for SA: %s, delete it first.\n", sa_len ? sa : " (error)"); SENDERR(EEXIST); } if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.s_addr) == IS_MYADDR) { extr->ips->ips_flags |= EMT_INBOUND; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "existing ipsec_sa not found (this is good) for SA: %s, %s-bound, allocating.\n", sa_len ? sa : " (error)", extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ extr->ips->ips_rcvif = NULL; extr->ips->ips_life.ipl_addtime.ipl_count = jiffies/HZ; extr->ips->ips_state = SADB_SASTATE_LARVAL; if(!extr->ips->ips_life.ipl_allocations.ipl_count) { extr->ips->ips_life.ipl_allocations.ipl_count += 1; } if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], SADB_GETSPI, satype, 0, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], SADB_EXT_SA, extr->ips->ips_said.spi, 0, SADB_SASTATE_LARVAL, 0, 0, 0, extr->ips->ips_ref), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_s), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "failed to build the getspi reply message extensions\n"); goto errlab; } if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "failed to build the getspi reply message\n"); SENDERR(-error); } for(pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "sending up getspi reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "sending up getspi reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } if((error = ipsec_sa_add(extr->ips))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "failed to add the larval SA=%s with error=%d.\n", sa_len ? sa : " (error)", error); SENDERR(-error); } extr->ips = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "successful for SA: %s\n", sa_len ? sa : " (error)"); errlab: if (pfkey_reply) { pfkey_msg_free(&pfkey_reply); } pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_update_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; struct ipsec_sa* ipsq; char sa[SATOA_BUF]; size_t sa_len; struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; #ifdef CONFIG_IPSEC_NAT_TRAVERSAL struct ipsec_sa *nat_t_ips_saved = NULL; #endif KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: .\n"); pfkey_extensions_init(extensions_reply); if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "error, sa_state=%d must be MATURE=%d\n", ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, SADB_SASTATE_MATURE); SENDERR(EINVAL); } if(extr == NULL || extr->ips == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "error, extr or extr->ips pointer NULL\n"); SENDERR(EINVAL); } sa_len = satoa(extr->ips->ips_said, 0, sa, SATOA_BUF); spin_lock_bh(&tdb_lock); ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); if (ipsq == NULL) { spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "reserved ipsec_sa for SA: %s not found. Call SADB_GETSPI first or call SADB_ADD instead.\n", sa_len ? sa : " (error)"); SENDERR(ENOENT); } if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.s_addr) == IS_MYADDR) { extr->ips->ips_flags |= EMT_INBOUND; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "existing ipsec_sa found (this is good) for SA: %s, %s-bound, updating.\n", sa_len ? sa : " (error)", extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); #ifdef CONFIG_IPSEC_NAT_TRAVERSAL if (extr->ips->ips_natt_sport || extr->ips->ips_natt_dport) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: only updating NAT-T ports " "(%u:%u -> %u:%u)\n", ipsq->ips_natt_sport, ipsq->ips_natt_dport, extr->ips->ips_natt_sport, extr->ips->ips_natt_dport); if (extr->ips->ips_natt_sport) { ipsq->ips_natt_sport = extr->ips->ips_natt_sport; if (ipsq->ips_addr_s->sa_family == AF_INET) { ((struct sockaddr_in *)(ipsq->ips_addr_s))->sin_port = htons(extr->ips->ips_natt_sport); } } if (extr->ips->ips_natt_dport) { ipsq->ips_natt_dport = extr->ips->ips_natt_dport; if (ipsq->ips_addr_d->sa_family == AF_INET) { ((struct sockaddr_in *)(ipsq->ips_addr_d))->sin_port = htons(extr->ips->ips_natt_dport); } } nat_t_ips_saved = extr->ips; extr->ips = ipsq; } else { #endif /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ extr->ips->ips_rcvif = NULL; if ((error = pfkey_ipsec_sa_init(extr->ips, extensions))) { ipsec_sa_put(ipsq); spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "not successful for SA: %s, deleting.\n", sa_len ? sa : " (error)"); SENDERR(-error); } extr->ips->ips_life.ipl_addtime.ipl_count = ipsq->ips_life.ipl_addtime.ipl_count; ipsec_sa_put(ipsq); if((error = ipsec_sa_delchain(ipsq))) { spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "error=%d, trouble deleting intermediate ipsec_sa for SA=%s.\n", error, sa_len ? sa : " (error)"); SENDERR(-error); } #ifdef CONFIG_IPSEC_NAT_TRAVERSAL } #endif spin_unlock_bh(&tdb_lock); if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], SADB_UPDATE, satype, 0, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags, extr->ips->ips_ref), extensions_reply) /* The 3 lifetime extentions should only be sent if non-zero. */ && (extensions[SADB_EXT_LIFETIME_HARD] ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD], SADB_EXT_LIFETIME_HARD, extr->ips->ips_life.ipl_allocations.ipl_hard, extr->ips->ips_life.ipl_bytes.ipl_hard, extr->ips->ips_life.ipl_addtime.ipl_hard, extr->ips->ips_life.ipl_usetime.ipl_hard, extr->ips->ips_life.ipl_packets.ipl_hard), extensions_reply) : 1) && (extensions[SADB_EXT_LIFETIME_SOFT] ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT], SADB_EXT_LIFETIME_SOFT, extr->ips->ips_life.ipl_allocations.ipl_count, extr->ips->ips_life.ipl_bytes.ipl_count, extr->ips->ips_life.ipl_addtime.ipl_count, extr->ips->ips_life.ipl_usetime.ipl_count, extr->ips->ips_life.ipl_packets.ipl_count), extensions_reply) : 1) && (extr->ips->ips_life.ipl_allocations.ipl_count || extr->ips->ips_life.ipl_bytes.ipl_count || extr->ips->ips_life.ipl_addtime.ipl_count || extr->ips->ips_life.ipl_usetime.ipl_count || extr->ips->ips_life.ipl_packets.ipl_count ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_CURRENT], SADB_EXT_LIFETIME_CURRENT, extr->ips->ips_life.ipl_allocations.ipl_count, extr->ips->ips_life.ipl_bytes.ipl_count, extr->ips->ips_life.ipl_addtime.ipl_count, extr->ips->ips_life.ipl_usetime.ipl_count, extr->ips->ips_life.ipl_packets.ipl_count), extensions_reply) : 1) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_s), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) && (extr->ips->ips_ident_s.data ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC], SADB_EXT_IDENTITY_SRC, extr->ips->ips_ident_s.type, extr->ips->ips_ident_s.id, extr->ips->ips_ident_s.len, extr->ips->ips_ident_s.data), extensions_reply) : 1) && (extr->ips->ips_ident_d.data ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST], SADB_EXT_IDENTITY_DST, extr->ips->ips_ident_d.type, extr->ips->ips_ident_d.id, extr->ips->ips_ident_d.len, extr->ips->ips_ident_d.data), extensions_reply) : 1) #if 0 /* FIXME: This won't work yet because I have not finished it. */ && (extr->ips->ips_sens_ ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY], extr->ips->ips_sens_dpd, extr->ips->ips_sens_sens_level, extr->ips->ips_sens_sens_len, extr->ips->ips_sens_sens_bitmap, extr->ips->ips_sens_integ_level, extr->ips->ips_sens_integ_len, extr->ips->ips_sens_integ_bitmap), extensions_reply) : 1) #endif )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "failed to build the update reply message extensions\n"); SENDERR(-error); } if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "failed to build the update reply message\n"); SENDERR(-error); } for(pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "sending up update reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "sending up update reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } #ifdef CONFIG_IPSEC_NAT_TRAVERSAL if (nat_t_ips_saved) { /** * As we _really_ update existing SA, we keep tdbq and need to delete * parsed ips (nat_t_ips_saved, was extr->ips). * * goto errlab with extr->ips = nat_t_ips_saved will free it. */ extr->ips = nat_t_ips_saved; error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse (NAT-T ports): " "successful for SA: %s\n", sa_len ? sa : " (error)"); goto errlab; } #endif if((error = ipsec_sa_add(extr->ips))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "failed to update the mature SA=%s with error=%d.\n", sa_len ? sa : " (error)", error); SENDERR(-error); } extr->ips = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "successful for SA: %s\n", sa_len ? sa : " (error)"); errlab: if (pfkey_reply) { pfkey_msg_free(&pfkey_reply); } pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_add_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; struct ipsec_sa* ipsq; char sa[SATOA_BUF]; size_t sa_len; struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: .\n"); pfkey_extensions_init(extensions_reply); if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "error, sa_state=%d must be MATURE=%d\n", ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, SADB_SASTATE_MATURE); SENDERR(EINVAL); } if(!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "extr or extr->ips pointer NULL\n"); SENDERR(EINVAL); } sa_len = satoa(extr->ips->ips_said, 0, sa, SATOA_BUF); ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); if(ipsq != NULL) { ipsec_sa_put(ipsq); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "found an old ipsec_sa for SA%s, delete it first.\n", sa_len ? sa : " (error)"); SENDERR(EEXIST); } if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.s_addr) == IS_MYADDR) { extr->ips->ips_flags |= EMT_INBOUND; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "existing ipsec_sa not found (this is good) for SA%s, %s-bound, allocating.\n", sa_len ? sa : " (error)", extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ extr->ips->ips_rcvif = NULL; if ((error = pfkey_ipsec_sa_init(extr->ips, extensions))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "not successful for SA: %s, deleting.\n", sa_len ? sa : " (error)"); SENDERR(-error); } extr->ips->ips_life.ipl_addtime.ipl_count = jiffies / HZ; if(!extr->ips->ips_life.ipl_allocations.ipl_count) { extr->ips->ips_life.ipl_allocations.ipl_count += 1; } if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], SADB_ADD, satype, 0, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags, extr->ips->ips_ref), extensions_reply) /* The 3 lifetime extentions should only be sent if non-zero. */ && (extensions[SADB_EXT_LIFETIME_HARD] ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD], SADB_EXT_LIFETIME_HARD, extr->ips->ips_life.ipl_allocations.ipl_hard, extr->ips->ips_life.ipl_bytes.ipl_hard, extr->ips->ips_life.ipl_addtime.ipl_hard, extr->ips->ips_life.ipl_usetime.ipl_hard, extr->ips->ips_life.ipl_packets.ipl_hard), extensions_reply) : 1) && (extensions[SADB_EXT_LIFETIME_SOFT] ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT], SADB_EXT_LIFETIME_SOFT, extr->ips->ips_life.ipl_allocations.ipl_soft, extr->ips->ips_life.ipl_bytes.ipl_soft, extr->ips->ips_life.ipl_addtime.ipl_soft, extr->ips->ips_life.ipl_usetime.ipl_soft, extr->ips->ips_life.ipl_packets.ipl_soft), extensions_reply) : 1) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_s), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) && (extr->ips->ips_ident_s.data ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC], SADB_EXT_IDENTITY_SRC, extr->ips->ips_ident_s.type, extr->ips->ips_ident_s.id, extr->ips->ips_ident_s.len, extr->ips->ips_ident_s.data), extensions_reply) : 1) && (extr->ips->ips_ident_d.data ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST], SADB_EXT_IDENTITY_DST, extr->ips->ips_ident_d.type, extr->ips->ips_ident_d.id, extr->ips->ips_ident_d.len, extr->ips->ips_ident_d.data), extensions_reply) : 1) #if 0 /* FIXME: This won't work yet because I have not finished it. */ && (extr->ips->ips_sens_ ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY], extr->ips->ips_sens_dpd, extr->ips->ips_sens_sens_level, extr->ips->ips_sens_sens_len, extr->ips->ips_sens_sens_bitmap, extr->ips->ips_sens_integ_level, extr->ips->ips_sens_integ_len, extr->ips->ips_sens_integ_bitmap), extensions_reply) : 1) #endif )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "failed to build the add reply message extensions\n"); SENDERR(-error); } if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "failed to build the add reply message\n"); SENDERR(-error); } for(pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "sending up add reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "sending up add reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } if((error = ipsec_sa_add(extr->ips))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "failed to add the mature SA=%s with error=%d.\n", sa_len ? sa : " (error)", error); SENDERR(-error); } extr->ips = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "successful for SA: %s\n", sa_len ? sa : " (error)"); errlab: if (pfkey_reply) { pfkey_msg_free(&pfkey_reply); } pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_delete_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { struct ipsec_sa *ipsp; char sa[SATOA_BUF]; size_t sa_len; int error = 0; struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: .\n"); pfkey_extensions_init(extensions_reply); if(!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " "extr or extr->ips pointer NULL, fatal\n"); SENDERR(EINVAL); } sa_len = satoa(extr->ips->ips_said, 0, sa, SATOA_BUF); spin_lock_bh(&tdb_lock); ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said)); if (ipsp == NULL) { spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " "ipsec_sa not found for SA:%s, could not delete.\n", sa_len ? sa : " (error)"); SENDERR(ESRCH); } ipsec_sa_put(ipsp); if((error = ipsec_sa_delchain(ipsp))) { spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " "error=%d returned trying to delete ipsec_sa for SA:%s.\n", error, sa_len ? sa : " (error)"); SENDERR(-error); } spin_unlock_bh(&tdb_lock); if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], SADB_DELETE, satype, 0, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], SADB_EXT_SA, extr->ips->ips_said.spi, 0, 0, 0, 0, 0, extr->ips->ips_ref), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_s), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " "failed to build the delete reply message extensions\n"); SENDERR(-error); } if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " "failed to build the delete reply message\n"); SENDERR(-error); } for(pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " "sending up delete reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " "sending up delete reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } errlab: if (pfkey_reply) { pfkey_msg_free(&pfkey_reply); } pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_get_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; struct ipsec_sa *ipsp; char sa[SATOA_BUF]; size_t sa_len; struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_reply = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: .\n"); pfkey_extensions_init(extensions_reply); if(!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " "extr or extr->ips pointer NULL, fatal\n"); SENDERR(EINVAL); } sa_len = satoa(extr->ips->ips_said, 0, sa, SATOA_BUF); spin_lock_bh(&tdb_lock); ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said)); if (ipsp == NULL) { spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " "ipsec_sa not found for SA=%s, could not get.\n", sa_len ? sa : " (error)"); SENDERR(ESRCH); } if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], SADB_GET, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype, 0, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags, extr->ips->ips_ref), extensions_reply) /* The 3 lifetime extentions should only be sent if non-zero. */ && (ipsp->ips_life.ipl_allocations.ipl_count || ipsp->ips_life.ipl_bytes.ipl_count || ipsp->ips_life.ipl_addtime.ipl_count || ipsp->ips_life.ipl_usetime.ipl_count || ipsp->ips_life.ipl_packets.ipl_count ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_CURRENT], SADB_EXT_LIFETIME_CURRENT, ipsp->ips_life.ipl_allocations.ipl_count, ipsp->ips_life.ipl_bytes.ipl_count, ipsp->ips_life.ipl_addtime.ipl_count, ipsp->ips_life.ipl_usetime.ipl_count, ipsp->ips_life.ipl_packets.ipl_count), extensions_reply) : 1) && (ipsp->ips_life.ipl_allocations.ipl_hard || ipsp->ips_life.ipl_bytes.ipl_hard || ipsp->ips_life.ipl_addtime.ipl_hard || ipsp->ips_life.ipl_usetime.ipl_hard || ipsp->ips_life.ipl_packets.ipl_hard ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD], SADB_EXT_LIFETIME_HARD, ipsp->ips_life.ipl_allocations.ipl_hard, ipsp->ips_life.ipl_bytes.ipl_hard, ipsp->ips_life.ipl_addtime.ipl_hard, ipsp->ips_life.ipl_usetime.ipl_hard, ipsp->ips_life.ipl_packets.ipl_hard), extensions_reply) : 1) && (ipsp->ips_life.ipl_allocations.ipl_soft || ipsp->ips_life.ipl_bytes.ipl_soft || ipsp->ips_life.ipl_addtime.ipl_soft || ipsp->ips_life.ipl_usetime.ipl_soft || ipsp->ips_life.ipl_packets.ipl_soft ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT], SADB_EXT_LIFETIME_SOFT, ipsp->ips_life.ipl_allocations.ipl_soft, ipsp->ips_life.ipl_bytes.ipl_soft, ipsp->ips_life.ipl_addtime.ipl_soft, ipsp->ips_life.ipl_usetime.ipl_soft, ipsp->ips_life.ipl_packets.ipl_soft), extensions_reply) : 1) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_s), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) && (extr->ips->ips_addr_p ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_PROXY], SADB_EXT_ADDRESS_PROXY, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_p), extensions_reply) : 1) #if 0 /* FIXME: This won't work yet because the keys are not stored directly in the ipsec_sa. They are stored as contexts. */ && (extr->ips->ips_key_a_size ? pfkey_safe_build(error = pfkey_key_build(&extensions_reply[SADB_EXT_KEY_AUTH], SADB_EXT_KEY_AUTH, extr->ips->ips_key_a_size * 8, extr->ips->ips_key_a), extensions_reply) : 1) /* FIXME: This won't work yet because the keys are not stored directly in the ipsec_sa. They are stored as key schedules. */ && (extr->ips->ips_key_e_size ? pfkey_safe_build(error = pfkey_key_build(&extensions_reply[SADB_EXT_KEY_ENCRYPT], SADB_EXT_KEY_ENCRYPT, extr->ips->ips_key_e_size * 8, extr->ips->ips_key_e), extensions_reply) : 1) #endif && (extr->ips->ips_ident_s.data ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC], SADB_EXT_IDENTITY_SRC, extr->ips->ips_ident_s.type, extr->ips->ips_ident_s.id, extr->ips->ips_ident_s.len, extr->ips->ips_ident_s.data), extensions_reply) : 1) && (extr->ips->ips_ident_d.data ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST], SADB_EXT_IDENTITY_DST, extr->ips->ips_ident_d.type, extr->ips->ips_ident_d.id, extr->ips->ips_ident_d.len, extr->ips->ips_ident_d.data), extensions_reply) : 1) #if 0 /* FIXME: This won't work yet because I have not finished it. */ && (extr->ips->ips_sens_ ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY], extr->ips->ips_sens_dpd, extr->ips->ips_sens_sens_level, extr->ips->ips_sens_sens_len, extr->ips->ips_sens_sens_bitmap, extr->ips->ips_sens_integ_level, extr->ips->ips_sens_integ_len, extr->ips->ips_sens_integ_bitmap), extensions_reply) : 1) #endif )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " "failed to build the get reply message extensions\n"); ipsec_sa_put(ipsp); spin_unlock_bh(&tdb_lock); SENDERR(-error); } ipsec_sa_put(ipsp); spin_unlock_bh(&tdb_lock); if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " "failed to build the get reply message\n"); SENDERR(-error); } if((error = pfkey_upmsg(sk->socket, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " "failed to send the get reply message\n"); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " "succeeded in sending get reply message.\n"); errlab: if (pfkey_reply) { pfkey_msg_free(&pfkey_reply); } pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_acquire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: .\n"); /* XXX I don't know if we want an upper bound, since userspace may want to register itself for an satype > SADB_SATYPE_MAX. */ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " "SATYPE=%d invalid.\n", satype); SENDERR(EINVAL); } if(!(pfkey_registered_sockets[satype])) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " "no sockets registered for SAtype=%d(%s).\n", satype, satype2name(satype)); SENDERR(EPROTONOSUPPORT); } for(pfkey_socketsp = pfkey_registered_sockets[satype]; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " "sending up acquire reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " "sending up acquire reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } errlab: return error; } DEBUG_NO_STATIC int pfkey_register_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_parse: .\n"); /* XXX I don't know if we want an upper bound, since userspace may want to register itself for an satype > SADB_SATYPE_MAX. */ if((satype == 0) || (satype > SADB_SATYPE_MAX)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_parse: " "SATYPE=%d invalid.\n", satype); SENDERR(EINVAL); } if(!pfkey_list_insert_socket(sk->socket, &(pfkey_registered_sockets[satype]))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_parse: " "SATYPE=%02d(%s) successfully registered by KMd (pid=%d).\n", satype, satype2name(satype), key_pid(sk)); }; /* send up register msg with supported SATYPE algos */ error=pfkey_register_reply(satype, (struct sadb_msg*)extensions[SADB_EXT_RESERVED]); errlab: return error; } int pfkey_register_reply(int satype, struct sadb_msg *sadb_msg) { struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; struct supported_list *pfkey_supported_listp; unsigned int alg_num_a = 0, alg_num_e = 0; struct sadb_alg *alg_a = NULL, *alg_e = NULL, *alg_ap = NULL, *alg_ep = NULL; int error = 0; pfkey_extensions_init(extensions_reply); if((satype == 0) || (satype > SADB_SATYPE_MAX)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "SAtype=%d unspecified or unknown.\n", satype); SENDERR(EINVAL); } if(!(pfkey_registered_sockets[satype])) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "no sockets registered for SAtype=%d(%s).\n", satype, satype2name(satype)); SENDERR(EPROTONOSUPPORT); } /* send up register msg with supported SATYPE algos */ pfkey_supported_listp = pfkey_supported_list[satype]; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "pfkey_supported_list[%d]=0p%p\n", satype, pfkey_supported_list[satype]); while(pfkey_supported_listp) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "checking supported=0p%p\n", pfkey_supported_listp); if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_AUTH) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "adding auth alg.\n"); alg_num_a++; } if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_ENCRYPT) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "adding encrypt alg.\n"); alg_num_e++; } pfkey_supported_listp = pfkey_supported_listp->next; } if(alg_num_a) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "allocating %lu bytes for auth algs.\n", (unsigned long) (alg_num_a * sizeof(struct sadb_alg))); if((alg_a = kmalloc(alg_num_a * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "auth alg memory allocation error\n"); SENDERR(ENOMEM); } alg_ap = alg_a; } if(alg_num_e) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "allocating %lu bytes for enc algs.\n", (unsigned long) (alg_num_e * sizeof(struct sadb_alg))); if((alg_e = kmalloc(alg_num_e * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "enc alg memory allocation error\n"); SENDERR(ENOMEM); } alg_ep = alg_e; } pfkey_supported_listp = pfkey_supported_list[satype]; while(pfkey_supported_listp) { if(alg_num_a) { if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_AUTH) { alg_ap->sadb_alg_id = pfkey_supported_listp->supportedp->supported_alg_id; alg_ap->sadb_alg_ivlen = pfkey_supported_listp->supportedp->supported_alg_ivlen; alg_ap->sadb_alg_minbits = pfkey_supported_listp->supportedp->supported_alg_minbits; alg_ap->sadb_alg_maxbits = pfkey_supported_listp->supportedp->supported_alg_maxbits; alg_ap->sadb_alg_reserved = 0; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_register_reply: " "adding auth=0p%p\n", alg_ap); alg_ap++; } } if(alg_num_e) { if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_ENCRYPT) { alg_ep->sadb_alg_id = pfkey_supported_listp->supportedp->supported_alg_id; alg_ep->sadb_alg_ivlen = pfkey_supported_listp->supportedp->supported_alg_ivlen; alg_ep->sadb_alg_minbits = pfkey_supported_listp->supportedp->supported_alg_minbits; alg_ep->sadb_alg_maxbits = pfkey_supported_listp->supportedp->supported_alg_maxbits; alg_ep->sadb_alg_reserved = 0; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_register_reply: " "adding encrypt=0p%p\n", alg_ep); alg_ep++; } } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "found satype=%d(%s) exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n", satype, satype2name(satype), pfkey_supported_listp->supportedp->supported_alg_exttype, pfkey_supported_listp->supportedp->supported_alg_id, pfkey_supported_listp->supportedp->supported_alg_ivlen, pfkey_supported_listp->supportedp->supported_alg_minbits, pfkey_supported_listp->supportedp->supported_alg_maxbits); pfkey_supported_listp = pfkey_supported_listp->next; } if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], SADB_REGISTER, satype, 0, sadb_msg? sadb_msg->sadb_msg_seq : ++pfkey_msg_seq, sadb_msg? sadb_msg->sadb_msg_pid: current->pid), extensions_reply) && (alg_num_a ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[SADB_EXT_SUPPORTED_AUTH], SADB_EXT_SUPPORTED_AUTH, alg_num_a, alg_a), extensions_reply) : 1) && (alg_num_e ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[SADB_EXT_SUPPORTED_ENCRYPT], SADB_EXT_SUPPORTED_ENCRYPT, alg_num_e, alg_e), extensions_reply) : 1))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "failed to build the register message extensions_reply\n"); SENDERR(-error); } if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "failed to build the register message\n"); SENDERR(-error); } /* this should go to all registered sockets for that satype only */ for(pfkey_socketsp = pfkey_registered_sockets[satype]; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "sending up acquire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "sending up register message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } errlab: if(alg_a) { kfree(alg_a); } if(alg_e) { kfree(alg_e); } if (pfkey_reply) { pfkey_msg_free(&pfkey_reply); } pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_expire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; struct socket_list *pfkey_socketsp; #ifdef CONFIG_IPSEC_DEBUG uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; #endif /* CONFIG_IPSEC_DEBUG */ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: .\n"); if(pfkey_open_sockets) { for(pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: " "sending up expire reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: " "sending up expire reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } } errlab: return error; } DEBUG_NO_STATIC int pfkey_flush_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; uint8_t proto = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " "flushing type %d SAs\n", satype); if(satype && !(proto = satype2proto(satype))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " "satype %d lookup failed.\n", ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype); SENDERR(EINVAL); } if ((error = ipsec_sadb_cleanup(proto))) { SENDERR(-error); } if(pfkey_open_sockets) { for(pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " "sending up flush reply message for satype=%d(%s) (proto=%d) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), proto, pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " "sending up flush reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } } errlab: return error; } DEBUG_NO_STATIC int pfkey_dump_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_dump_parse: .\n"); SENDERR(ENOSYS); errlab: return error; } DEBUG_NO_STATIC int pfkey_x_promisc_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_promisc_parse: .\n"); SENDERR(ENOSYS); errlab: return error; } DEBUG_NO_STATIC int pfkey_x_pchange_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_pchange_parse: .\n"); SENDERR(ENOSYS); errlab: return error; } DEBUG_NO_STATIC int pfkey_x_grpsa_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { struct ipsec_sa *ips1p, *ips2p, *ipsp; struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; char sa1[SATOA_BUF], sa2[SATOA_BUF]; size_t sa_len1, sa_len2 = 0; int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: .\n"); pfkey_extensions_init(extensions_reply); if(extr == NULL || extr->ips == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "extr or extr->ips is NULL, fatal.\n"); SENDERR(EINVAL); } sa_len1 = satoa(extr->ips->ips_said, 0, sa1, SATOA_BUF); if(extr->ips2 != NULL) { sa_len2 = satoa(extr->ips2->ips_said, 0, sa2, SATOA_BUF); } spin_lock_bh(&tdb_lock); ips1p = ipsec_sa_getbyid(&(extr->ips->ips_said)); if(ips1p == NULL) { spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "reserved ipsec_sa for SA1: %s not found. Call SADB_ADD/UPDATE first.\n", sa_len1 ? sa1 : " (error)"); SENDERR(ENOENT); } if(extr->ips2) { /* GRPSA */ ips2p = ipsec_sa_getbyid(&(extr->ips2->ips_said)); if(ips2p == NULL) { ipsec_sa_put(ips1p); spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "reserved ipsec_sa for SA2: %s not found. Call SADB_ADD/UPDATE first.\n", sa_len2 ? sa2 : " (error)"); SENDERR(ENOENT); } /* Is either one already linked? */ if(ips1p->ips_onext) { ipsec_sa_put(ips1p); ipsec_sa_put(ips2p); spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "ipsec_sa for SA: %s is already linked.\n", sa_len1 ? sa1 : " (error)"); SENDERR(EEXIST); } if(ips2p->ips_inext) { ipsec_sa_put(ips1p); ipsec_sa_put(ips2p); spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "ipsec_sa for SA: %s is already linked.\n", sa_len2 ? sa2 : " (error)"); SENDERR(EEXIST); } /* Is extr->ips already linked to extr->ips2? */ ipsp = ips2p; while(ipsp) { if(ipsp == ips1p) { ipsec_sa_put(ips1p); ipsec_sa_put(ips2p); spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "ipsec_sa for SA: %s is already linked to %s.\n", sa_len1 ? sa1 : " (error)", sa_len2 ? sa2 : " (error)"); SENDERR(EEXIST); } ipsp = ipsp->ips_onext; } /* link 'em */ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "linking ipsec_sa SA: %s with %s.\n", sa_len1 ? sa1 : " (error)", sa_len2 ? sa2 : " (error)"); ips1p->ips_onext = ips2p; ips2p->ips_inext = ips1p; } else { /* UNGRPSA */ ipsec_sa_put(ips1p); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "unlinking ipsec_sa SA: %s.\n", sa_len1 ? sa1 : " (error)"); while(ips1p->ips_onext) { ips1p = ips1p->ips_onext; } while(ips1p->ips_inext) { ipsp = ips1p; ips1p = ips1p->ips_inext; ipsec_sa_put(ips1p); ipsp->ips_inext = NULL; ipsec_sa_put(ipsp); ips1p->ips_onext = NULL; } } spin_unlock_bh(&tdb_lock); if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], SADB_X_GRPSA, satype, 0, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags, extr->ips->ips_ref), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) && (extr->ips2 ? (pfkey_safe_build(error = pfkey_x_satype_build(&extensions_reply[SADB_X_EXT_SATYPE2], ((struct sadb_x_satype*)extensions[SADB_X_EXT_SATYPE2])->sadb_x_satype_satype /* proto2satype(extr->ips2->ips_said.proto) */), extensions_reply) && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_X_EXT_SA2], SADB_X_EXT_SA2, extr->ips2->ips_said.spi, extr->ips2->ips_replaywin, extr->ips2->ips_state, extr->ips2->ips_authalg, extr->ips2->ips_encalg, extr->ips2->ips_flags, extr->ips2->ips_ref), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST2], SADB_X_EXT_ADDRESS_DST2, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips2->ips_addr_d), extensions_reply) ) : 1 ) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "failed to build the x_grpsa reply message extensions\n"); SENDERR(-error); } if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "failed to build the x_grpsa reply message\n"); SENDERR(-error); } for(pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "sending up x_grpsa reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "sending up x_grpsa reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "succeeded in sending x_grpsa reply message.\n"); errlab: if (pfkey_reply) { pfkey_msg_free(&pfkey_reply); } pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_x_addflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; #ifdef CONFIG_IPSEC_DEBUG char buf1[64], buf2[64]; #endif /* CONFIG_IPSEC_DEBUG */ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; ip_address srcflow, dstflow, srcmask, dstmask; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: .\n"); pfkey_extensions_init(extensions_reply); memset((caddr_t)&srcflow, 0, sizeof(srcflow)); memset((caddr_t)&dstflow, 0, sizeof(dstflow)); memset((caddr_t)&srcmask, 0, sizeof(srcmask)); memset((caddr_t)&dstmask, 0, sizeof(dstmask)); if(!extr || !(extr->ips) || !(extr->eroute)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "missing extr, ipsec_sa or eroute data.\n"); SENDERR(EINVAL); } srcflow.u.v4.sin_family = AF_INET; dstflow.u.v4.sin_family = AF_INET; srcmask.u.v4.sin_family = AF_INET; dstmask.u.v4.sin_family = AF_INET; srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src; dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst; srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src; dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst; #ifdef CONFIG_IPSEC_DEBUG 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_x_addflow_parse: " "calling breakeroute and/or makeroute for %s->%s\n", buf1, buf2); } #endif /* CONFIG_IPSEC_DEBUG */ if(extr->ips->ips_flags & SADB_X_SAFLAGS_INFLOW) { /* if(ip_chk_addr((unsigned long)extr->ips->ips_said.dst.s_addr) == IS_MYADDR) */ struct ipsec_sa *ipsp, *ipsq; char sa[SATOA_BUF]; size_t sa_len; ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); if(ipsq == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "ipsec_sa not found, cannot set incoming policy.\n"); SENDERR(ENOENT); } ipsp = ipsq; while(ipsp && ipsp->ips_said.proto != IPPROTO_IPIP) { ipsp = ipsp->ips_inext; } if(ipsp == NULL) { ipsec_sa_put(ipsq); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "SA chain does not have an IPIP SA, cannot set incoming policy.\n"); SENDERR(ENOENT); } sa_len = satoa(extr->ips->ips_said, 0, sa, SATOA_BUF); ipsp->ips_flags |= SADB_X_SAFLAGS_INFLOW; ipsp->ips_flow_s = srcflow; ipsp->ips_flow_d = dstflow; ipsp->ips_mask_s = srcmask; ipsp->ips_mask_d = dstmask; ipsec_sa_put(ipsq); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "inbound eroute, setting incoming policy information in IPIP ipsec_sa for SA: %s.\n", sa_len ? sa : " (error)"); } else { struct sk_buff *first = NULL, *last = NULL; if(extr->ips->ips_flags & SADB_X_SAFLAGS_REPLACEFLOW) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "REPLACEFLOW flag set, calling breakeroute.\n"); if ((error = ipsec_breakroute(&(extr->eroute->er_eaddr), &(extr->eroute->er_emask), &first, &last))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "breakeroute returned %d. first=0p%p, last=0p%p\n", error, first, last); if(first != NULL) { ipsec_kfree_skb(first); } if(last != NULL) { ipsec_kfree_skb(last); } SENDERR(-error); } } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "calling makeroute.\n"); if ((error = ipsec_makeroute(&(extr->eroute->er_eaddr), &(extr->eroute->er_emask), extr->ips->ips_said, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid, NULL, &(extr->ips->ips_ident_s), &(extr->ips->ips_ident_d)))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "makeroute returned %d.\n", error); SENDERR(-error); } if(first != NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "first=0p%p HOLD packet re-injected.\n", first); DEV_QUEUE_XMIT(first, first->dev, SOPRI_NORMAL); } if(last != NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "last=0p%p HOLD packet re-injected.\n", last); DEV_QUEUE_XMIT(last, last->dev, SOPRI_NORMAL); } } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "makeroute call successful.\n"); if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], SADB_X_ADDFLOW, satype, 0, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags, extr->ips->ips_ref), extensions_reply) && (extensions[SADB_EXT_ADDRESS_SRC] ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_s), extensions_reply) : 1) && (extensions[SADB_EXT_ADDRESS_DST] ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) : 1) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_FLOW], SADB_X_EXT_ADDRESS_SRC_FLOW, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&srcflow), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_FLOW], SADB_X_EXT_ADDRESS_DST_FLOW, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&dstflow), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_MASK], SADB_X_EXT_ADDRESS_SRC_MASK, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&srcmask), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_MASK], SADB_X_EXT_ADDRESS_DST_MASK, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&dstmask), extensions_reply) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "failed to build the x_addflow reply message extensions\n"); SENDERR(-error); } if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "failed to build the x_addflow reply message\n"); SENDERR(-error); } for(pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "sending up x_addflow reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "sending up x_addflow reply message for satype=%d(%s) (proto=%d) to socket=0p%p succeeded.\n", satype, satype2name(satype), extr->ips->ips_said.proto, pfkey_socketsp->socketp); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "extr->ips cleaned up and freed.\n"); errlab: if (pfkey_reply) { pfkey_msg_free(&pfkey_reply); } pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_x_delflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; #ifdef CONFIG_IPSEC_DEBUG char buf1[64], buf2[64]; #endif /* CONFIG_IPSEC_DEBUG */ struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; ip_address srcflow, dstflow, srcmask, dstmask; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: .\n"); pfkey_extensions_init(extensions_reply); memset((caddr_t)&srcflow, 0, sizeof(srcflow)); memset((caddr_t)&dstflow, 0, sizeof(dstflow)); memset((caddr_t)&srcmask, 0, sizeof(srcmask)); memset((caddr_t)&dstmask, 0, sizeof(dstmask)); if(!extr || !(extr->ips)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "extr, or extr->ips is NULL, fatal\n"); SENDERR(EINVAL); } if(extr->ips->ips_flags & SADB_X_SAFLAGS_CLEARFLOW) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "CLEARFLOW flag set, calling cleareroutes.\n"); if ((error = ipsec_cleareroutes())) KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "cleareroutes returned %d.\n", error); SENDERR(-error); } else { struct sk_buff *first = NULL, *last = NULL; if(!(extr->eroute)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "extr->eroute is NULL, fatal.\n"); SENDERR(EINVAL); } srcflow.u.v4.sin_family = AF_INET; dstflow.u.v4.sin_family = AF_INET; srcmask.u.v4.sin_family = AF_INET; dstmask.u.v4.sin_family = AF_INET; srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src; dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst; srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src; dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst; #ifdef CONFIG_IPSEC_DEBUG 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_x_delflow_parse: " "calling breakeroute for %s->%s\n", buf1, buf2); } #endif /* CONFIG_IPSEC_DEBUG */ error = ipsec_breakroute(&(extr->eroute->er_eaddr), &(extr->eroute->er_emask), &first, &last); if(error) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "breakeroute returned %d. first=0p%p, last=0p%p\n", error, first, last); } if(first != NULL) { ipsec_kfree_skb(first); } if(last != NULL) { ipsec_kfree_skb(last); } if(error) { SENDERR(-error); } } if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], SADB_X_DELFLOW, satype, 0, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags, extr->ips->ips_ref), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_FLOW], SADB_X_EXT_ADDRESS_SRC_FLOW, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&srcflow), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_FLOW], SADB_X_EXT_ADDRESS_DST_FLOW, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&dstflow), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_MASK], SADB_X_EXT_ADDRESS_SRC_MASK, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&srcmask), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_MASK], SADB_X_EXT_ADDRESS_DST_MASK, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&dstmask), extensions_reply) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "failed to build the x_delflow reply message extensions\n"); SENDERR(-error); } if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "failed to build the x_delflow reply message\n"); SENDERR(-error); } for(pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "sending up x_delflow reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "sending up x_delflow reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "extr->ips cleaned up and freed.\n"); errlab: if (pfkey_reply) { pfkey_msg_free(&pfkey_reply); } pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_x_msg_debug_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_msg_debug_parse: .\n"); /* errlab:*/ return error; } /* pfkey_expire expects the ipsec_sa table to be locked before being called. */ int pfkey_expire(struct ipsec_sa *ipsp, int hard) { struct sadb_ext *extensions[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_msg = NULL; struct socket_list *pfkey_socketsp; int error = 0; uint8_t satype; pfkey_extensions_init(extensions); if(!(satype = proto2satype(ipsp->ips_said.proto))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " "satype lookup for protocol %d lookup failed.\n", ipsp->ips_said.proto); SENDERR(EINVAL); } if(!pfkey_open_sockets) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " "no sockets listening.\n"); SENDERR(EPROTONOSUPPORT); } if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0], SADB_EXPIRE, satype, 0, ++pfkey_msg_seq, 0), extensions) && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions[SADB_EXT_SA], SADB_EXT_SA, ipsp->ips_said.spi, ipsp->ips_replaywin, ipsp->ips_state, ipsp->ips_authalg, ipsp->ips_encalg, ipsp->ips_flags, ipsp->ips_ref), extensions) && pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_CURRENT], SADB_EXT_LIFETIME_CURRENT, ipsp->ips_life.ipl_allocations.ipl_count, ipsp->ips_life.ipl_bytes.ipl_count, ipsp->ips_life.ipl_addtime.ipl_count, ipsp->ips_life.ipl_usetime.ipl_count, ipsp->ips_life.ipl_packets.ipl_count), extensions) && (hard ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_HARD], SADB_EXT_LIFETIME_HARD, ipsp->ips_life.ipl_allocations.ipl_hard, ipsp->ips_life.ipl_bytes.ipl_hard, ipsp->ips_life.ipl_addtime.ipl_hard, ipsp->ips_life.ipl_usetime.ipl_hard, ipsp->ips_life.ipl_packets.ipl_hard), extensions) : pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_SOFT], SADB_EXT_LIFETIME_SOFT, ipsp->ips_life.ipl_allocations.ipl_soft, ipsp->ips_life.ipl_bytes.ipl_soft, ipsp->ips_life.ipl_addtime.ipl_soft, ipsp->ips_life.ipl_usetime.ipl_soft, ipsp->ips_life.ipl_packets.ipl_soft), extensions)) && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, 0, /* ipsp->ips_said.proto, */ 0, ipsp->ips_addr_s), extensions) && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, 0, /* ipsp->ips_said.proto, */ 0, ipsp->ips_addr_d), extensions))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " "failed to build the expire message extensions\n"); spin_unlock(&tdb_lock); goto errlab; } if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " "failed to build the expire message\n"); SENDERR(-error); } for(pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " "sending up expire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " "sending up expire message for satype=%d(%s) (proto=%d) to socket=0p%p succeeded.\n", satype, satype2name(satype), ipsp->ips_said.proto, pfkey_socketsp->socketp); } errlab: if (pfkey_msg) { pfkey_msg_free(&pfkey_msg); } pfkey_extensions_free(extensions); return error; } int pfkey_acquire(struct ipsec_sa *ipsp) { struct sadb_ext *extensions[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_msg = NULL; struct socket_list *pfkey_socketsp; int error = 0; struct sadb_comb comb[] = { /* auth; encrypt; flags; */ /* auth_minbits; auth_maxbits; encrypt_minbits; encrypt_maxbits; */ /* reserved; soft_allocations; hard_allocations; soft_bytes; hard_bytes; */ /* soft_addtime; hard_addtime; soft_usetime; hard_usetime; */ /* soft_packets; hard_packets; */ { SADB_AALG_MD5_HMAC, SADB_EALG_3DES_CBC, SADB_SAFLAGS_PFS, 128, 128, 168, 168, 0, 0, 0, 0, 0, 57600, 86400, 57600, 86400, 0, 0 }, { SADB_AALG_SHA1_HMAC, SADB_EALG_3DES_CBC, SADB_SAFLAGS_PFS, 160, 160, 168, 168, 0, 0, 0, 0, 0, 57600, 86400, 57600, 86400, 0, 0 } }; /* XXX This should not be hard-coded. It should be taken from the spdb */ uint8_t satype = SADB_SATYPE_ESP; pfkey_extensions_init(extensions); if((satype == 0) || (satype > SADB_SATYPE_MAX)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: " "SAtype=%d unspecified or unknown.\n", satype); SENDERR(EINVAL); } if(!(pfkey_registered_sockets[satype])) { KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " "no sockets registered for SAtype=%d(%s).\n", satype, satype2name(satype)); SENDERR(EPROTONOSUPPORT); } if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0], SADB_ACQUIRE, satype, 0, ++pfkey_msg_seq, 0), extensions) && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, ipsp->ips_said.proto, 0, ipsp->ips_addr_s), extensions) && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, ipsp->ips_said.proto, 0, ipsp->ips_addr_d), extensions) #if 0 && (ipsp->ips_addr_p ? pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_PROXY], SADB_EXT_ADDRESS_PROXY, ipsp->ips_said.proto, 0, ipsp->ips_addr_p), extensions) : 1) #endif && (ipsp->ips_ident_s.type != SADB_IDENTTYPE_RESERVED ? pfkey_safe_build(error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_SRC], SADB_EXT_IDENTITY_SRC, ipsp->ips_ident_s.type, ipsp->ips_ident_s.id, ipsp->ips_ident_s.len, ipsp->ips_ident_s.data), extensions) : 1) && (ipsp->ips_ident_d.type != SADB_IDENTTYPE_RESERVED ? pfkey_safe_build(error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_DST], SADB_EXT_IDENTITY_DST, ipsp->ips_ident_d.type, ipsp->ips_ident_d.id, ipsp->ips_ident_d.len, ipsp->ips_ident_d.data), extensions) : 1) #if 0 /* FIXME: This won't work yet because I have not finished it. */ && (ipsp->ips_sens_ ? pfkey_safe_build(error = pfkey_sens_build(&extensions[SADB_EXT_SENSITIVITY], ipsp->ips_sens_dpd, ipsp->ips_sens_sens_level, ipsp->ips_sens_sens_len, ipsp->ips_sens_sens_bitmap, ipsp->ips_sens_integ_level, ipsp->ips_sens_integ_len, ipsp->ips_sens_integ_bitmap), extensions) : 1) #endif && pfkey_safe_build(error = pfkey_prop_build(&extensions[SADB_EXT_PROPOSAL], 64, /* replay */ sizeof(comb)/sizeof(struct sadb_comb), &(comb[0])), extensions) )) { KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " "failed to build the acquire message extensions\n"); SENDERR(-error); } if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " "failed to build the acquire message\n"); SENDERR(-error); } #if KLIPS_PFKEY_ACQUIRE_LOSSAGE > 0 if(sysctl_ipsec_regress_pfkey_lossage) { return(0); } #endif /* this should go to all registered sockets for that satype only */ for(pfkey_socketsp = pfkey_registered_sockets[satype]; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: " "sending up acquire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: " "sending up acquire message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } errlab: if (pfkey_msg) { pfkey_msg_free(&pfkey_msg); } pfkey_extensions_free(extensions); return error; } #ifdef CONFIG_IPSEC_NAT_TRAVERSAL int pfkey_nat_t_new_mapping(struct ipsec_sa *ipsp, struct sockaddr *ipaddr, __u16 sport) { struct sadb_ext *extensions[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_msg = NULL; struct socket_list *pfkey_socketsp; int error = 0; uint8_t satype = (ipsp->ips_said.proto==IPPROTO_ESP) ? SADB_SATYPE_ESP : 0; /* Construct SADB_X_NAT_T_NEW_MAPPING message */ pfkey_extensions_init(extensions); if((satype == 0) || (satype > SADB_SATYPE_MAX)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " "SAtype=%d unspecified or unknown.\n", satype); SENDERR(EINVAL); } if(!(pfkey_registered_sockets[satype])) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " "no sockets registered for SAtype=%d(%s).\n", satype, satype2name(satype)); SENDERR(EPROTONOSUPPORT); } if (!(pfkey_safe_build (error = pfkey_msg_hdr_build(&extensions[0], SADB_X_NAT_T_NEW_MAPPING, satype, 0, ++pfkey_msg_seq, 0), extensions) /* SA */ && pfkey_safe_build (error = pfkey_sa_build(&extensions[SADB_EXT_SA], SADB_EXT_SA, ipsp->ips_said.spi, 0, 0, 0, 0, 0), extensions) /* ADDRESS_SRC = old addr */ && pfkey_safe_build (error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, ipsp->ips_said.proto, 0, ipsp->ips_addr_s), extensions) /* NAT_T_SPORT = old port */ && pfkey_safe_build (error = pfkey_x_nat_t_port_build(&extensions[SADB_X_EXT_NAT_T_SPORT], SADB_X_EXT_NAT_T_SPORT, ipsp->ips_natt_sport), extensions) /* ADDRESS_DST = new addr */ && pfkey_safe_build (error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, ipsp->ips_said.proto, 0, ipaddr), extensions) /* NAT_T_DPORT = new port */ && pfkey_safe_build (error = pfkey_x_nat_t_port_build(&extensions[SADB_X_EXT_NAT_T_DPORT], SADB_X_EXT_NAT_T_DPORT, sport), extensions) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " "failed to build the nat_t_new_mapping message extensions\n"); SENDERR(-error); } if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " "failed to build the nat_t_new_mapping message\n"); SENDERR(-error); } /* this should go to all registered sockets for that satype only */ for(pfkey_socketsp = pfkey_registered_sockets[satype]; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } errlab: if (pfkey_msg) { pfkey_msg_free(&pfkey_msg); } pfkey_extensions_free(extensions); return error; } DEBUG_NO_STATIC int pfkey_x_nat_t_new_mapping_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr) { /* SADB_X_NAT_T_NEW_MAPPING not used in kernel */ return -EINVAL; } #endif DEBUG_NO_STATIC int (*ext_processors[SADB_EXT_MAX+1])(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) = { NULL, /* pfkey_msg_process, */ pfkey_sa_process, pfkey_lifetime_process, pfkey_lifetime_process, pfkey_lifetime_process, pfkey_address_process, pfkey_address_process, pfkey_address_process, pfkey_key_process, pfkey_key_process, pfkey_ident_process, pfkey_ident_process, pfkey_sens_process, pfkey_prop_process, pfkey_supported_process, pfkey_supported_process, pfkey_spirange_process, pfkey_x_kmprivate_process, pfkey_x_satype_process, pfkey_sa_process, pfkey_address_process, pfkey_address_process, pfkey_address_process, pfkey_address_process, pfkey_address_process, pfkey_x_debug_process, pfkey_x_protocol_process #ifdef CONFIG_IPSEC_NAT_TRAVERSAL , pfkey_x_nat_t_type_process, pfkey_x_nat_t_port_process, pfkey_x_nat_t_port_process, pfkey_address_process #endif }; DEBUG_NO_STATIC int (*msg_parsers[SADB_MAX +1])(struct sock *sk, struct sadb_ext *extensions[], struct pfkey_extracted_data* extr) = { NULL, /* RESERVED */ pfkey_getspi_parse, pfkey_update_parse, pfkey_add_parse, pfkey_delete_parse, pfkey_get_parse, pfkey_acquire_parse, pfkey_register_parse, pfkey_expire_parse, pfkey_flush_parse, pfkey_dump_parse, pfkey_x_promisc_parse, pfkey_x_pchange_parse, pfkey_x_grpsa_parse, pfkey_x_addflow_parse, pfkey_x_delflow_parse, pfkey_x_msg_debug_parse #ifdef CONFIG_IPSEC_NAT_TRAVERSAL , pfkey_x_nat_t_new_mapping_parse #endif }; int pfkey_build_reply(struct sadb_msg *pfkey_msg, struct pfkey_extracted_data *extr, struct sadb_msg **pfkey_reply) { struct sadb_ext *extensions[SADB_EXT_MAX+1]; int error = 0; int msg_type = pfkey_msg->sadb_msg_type; int seq = pfkey_msg->sadb_msg_seq; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " "building reply with type: %d\n", msg_type); pfkey_extensions_init(extensions); if (!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " "bad ipsec_sa passed\n"); return EINVAL; } error = pfkey_safe_build(pfkey_msg_hdr_build(&extensions[0], msg_type, proto2satype(extr->ips->ips_said.proto), 0, seq, pfkey_msg->sadb_msg_pid), extensions) && (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & 1 << SADB_EXT_SA) || pfkey_safe_build(pfkey_sa_ref_build(&extensions[SADB_EXT_SA], SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags, extr->ips->ips_ref), extensions)) && (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & 1 << SADB_EXT_LIFETIME_CURRENT) || pfkey_safe_build(pfkey_lifetime_build(&extensions [SADB_EXT_LIFETIME_CURRENT], SADB_EXT_LIFETIME_CURRENT, extr->ips->ips_life.ipl_allocations.ipl_count, extr->ips->ips_life.ipl_bytes.ipl_count, extr->ips->ips_life.ipl_addtime.ipl_count, extr->ips->ips_life.ipl_usetime.ipl_count, extr->ips->ips_life.ipl_packets.ipl_count), extensions)) && (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & 1 << SADB_EXT_ADDRESS_SRC) || pfkey_safe_build(pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, extr->ips->ips_said.proto, 0, extr->ips->ips_addr_s), extensions)) && (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] & 1 << SADB_EXT_ADDRESS_DST) || pfkey_safe_build(pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, extr->ips->ips_said.proto, 0, extr->ips->ips_addr_d), extensions)); if (error == 0) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " "building extensions failed\n"); return EINVAL; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " "built extensions, proceed to build the message\n"); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " "extensions[1]=0p%p\n", extensions[1]); error = pfkey_msg_build(pfkey_reply, extensions, EXT_BITS_OUT); pfkey_extensions_free(extensions); return error; } int pfkey_msg_interp(struct sock *sk, struct sadb_msg *pfkey_msg, struct sadb_msg **pfkey_reply) { int error = 0; int i; struct sadb_ext *extensions[SADB_EXT_MAX+1]; struct pfkey_extracted_data extr = {NULL, NULL, NULL}; pfkey_extensions_init(extensions); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "parsing message ver=%d, type=%d, errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", pfkey_msg->sadb_msg_version, pfkey_msg->sadb_msg_type, pfkey_msg->sadb_msg_errno, pfkey_msg->sadb_msg_satype, satype2name(pfkey_msg->sadb_msg_satype), pfkey_msg->sadb_msg_len, pfkey_msg->sadb_msg_reserved, pfkey_msg->sadb_msg_seq, pfkey_msg->sadb_msg_pid); extr.ips = ipsec_sa_alloc(&error); /* pass in error var by pointer */ if(extr.ips == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "memory allocation error.\n"); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "allocated extr->ips=0p%p.\n", extr.ips); if(pfkey_msg->sadb_msg_satype > SADB_SATYPE_MAX) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "satype %d > max %d\n", pfkey_msg->sadb_msg_satype, SADB_SATYPE_MAX); SENDERR(EINVAL); } switch(pfkey_msg->sadb_msg_type) { case SADB_GETSPI: case SADB_UPDATE: case SADB_ADD: case SADB_DELETE: case SADB_X_GRPSA: case SADB_X_ADDFLOW: if(!(extr.ips->ips_said.proto = satype2proto(pfkey_msg->sadb_msg_satype))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "satype %d lookup failed.\n", pfkey_msg->sadb_msg_satype); SENDERR(EINVAL); } else { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "satype %d lookups to proto=%d.\n", pfkey_msg->sadb_msg_satype, extr.ips->ips_said.proto); } break; default: break; } /* The NULL below causes the default extension parsers to be used */ /* Parse the extensions */ if((error = pfkey_msg_parse(pfkey_msg, NULL, extensions, EXT_BITS_IN))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "message parsing failed with error %d.\n", error); SENDERR(-error); } /* Process the extensions */ for(i=1; i <= SADB_EXT_MAX;i++) { if(extensions[i] != NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "processing ext %d 0p%p with processor 0p%p.\n", i, extensions[i], ext_processors[i]); if((error = ext_processors[i](extensions[i], &extr))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "extension processing for type %d failed with error %d.\n", i, error); SENDERR(-error); } } } /* Parse the message types */ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "parsing message type %d(%s) with msg_parser 0p%p.\n", pfkey_msg->sadb_msg_type, pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type), msg_parsers[pfkey_msg->sadb_msg_type]); if((error = msg_parsers[pfkey_msg->sadb_msg_type](sk, extensions, &extr))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "message parsing failed with error %d.\n", error); SENDERR(-error); } #if 0 error = pfkey_build_reply(pfkey_msg, &extr, pfkey_reply); if (error) { *pfkey_reply = NULL; } #endif errlab: if(extr.ips != NULL) { ipsec_sa_wipe(extr.ips); } if(extr.ips2 != NULL) { ipsec_sa_wipe(extr.ips2); } if (extr.eroute != NULL) { kfree(extr.eroute); } return(error); }