int hip_setup_hit_sp_pair(hip_hit_t *src_hit, hip_hit_t *dst_hit, struct in6_addr *src_addr, struct in6_addr *dst_addr, u8 proto, int use_full_prefix, int update) { int so, len, err = 0; u_int prefs, prefd; u8 prefix = (use_full_prefix) ? 128 : HIP_HIT_PREFIX_LEN; int cmd = update ? SADB_X_SPDUPDATE : SADB_X_SPDADD; HIP_DEBUG("\n"); HIP_IFEL(((so = pfkey_open()) < 0), -1, "ERROR in opening pfkey socket: %s\n", ipsec_strerror()); HIP_DEBUG("Adding a pair of SP\n"); HIP_IFEBL((hip_pfkey_policy_modify(so, dst_hit, prefix, src_hit, prefix, src_addr, dst_addr, proto, cmd, IPSEC_DIR_INBOUND)<0), -1, pfkey_close(so), "ERROR in %s the inbound policy\n", update ? "updating" : "adding"); HIP_IFEL(((so = pfkey_open()) < 0), -1, "ERROR in opening pfkey socket: %s\n", ipsec_strerror()); HIP_IFEBL((hip_pfkey_policy_modify(so, src_hit, prefix, dst_hit, prefix, dst_addr, src_addr, proto, cmd, IPSEC_DIR_OUTBOUND)<0), -1, pfkey_close(so), "ERROR in %s the outbound policy\n", update ? "updating" : "adding"); return 0; out_err: return err; }
/** linux_pfkey_register - Register via PFKEY our capabilities * */ static void linux_pfkey_register(void) { pfkey_register_proto(SADB_SATYPE_AH, "AH"); pfkey_register_proto(SADB_SATYPE_ESP, "ESP"); pfkey_register_proto(SADB_X_SATYPE_IPCOMP, "IPCOMP"); pfkey_close(); }
void hip_delete_sa(u32 spi, struct in6_addr *peer_addr, struct in6_addr *dst_addr, int direction, hip_ha_t *entry) { int so, len, err = 0; struct sockaddr_storage ss_addr, dd_addr; struct sockaddr *saddr; struct sockaddr *daddr; in_port_t sport, dport; /* @todo: sport and dport should be used! */ if (direction == HIP_SPI_DIRECTION_OUT) { sport = entry->local_udp_port; dport = entry->peer_udp_port; entry->outbound_sa_count--; if (entry->outbound_sa_count < 0) { HIP_ERROR("Warning: out sa count negative\n"); entry->outbound_sa_count = 0; } } else { sport = entry->peer_udp_port; dport = entry->local_udp_port; entry->inbound_sa_count--; if (entry->inbound_sa_count < 0) { HIP_ERROR("Warning: in sa count negative\n"); entry->inbound_sa_count = 0; } } saddr = (struct sockaddr*) &ss_addr; daddr = (struct sockaddr*) &dd_addr; HIP_DEBUG("\n"); HIP_DEBUG("spi=0x%x\n", spi); HIP_DEBUG_IN6ADDR("peer_addr", peer_addr); HIP_DEBUG_IN6ADDR("dst_addr", dst_addr); // Sanity check HIP_IFEL((!peer_addr || !dst_addr), -1, "Addresses not valid when deleting SA's\n"); HIP_IFEL(((so = pfkey_open()) < 0), -1, "ERROR in opening pfkey socket: %s\n", ipsec_strerror()); get_sock_addr_from_in6(saddr, peer_addr); get_sock_addr_from_in6(daddr, dst_addr); HIP_IFEBL(((len = pfkey_send_delete(so, SADB_SATYPE_ESP, HIP_IPSEC_DEFAULT_MODE, saddr, daddr, spi))<0), -1, pfkey_close(so), "ERROR in deleting sa %s", ipsec_strerror()); out_err: return; }
int hip_flush_all_sa() { int so, len, err = 0; HIP_DEBUG("\n"); HIP_IFEL(((so = pfkey_open()) < 0), -1, "ERROR in opening pfkey socket: %s\n", ipsec_strerror()); HIP_DEBUG("Flushing all SA's\n"); HIP_IFEBL(((len = pfkey_send_flush(so, SADB_SATYPE_ESP))<0), -1, pfkey_close(so), "ERROR in flushing policies %s\n", ipsec_strerror()); return len; out_err: return err; }
void hip_delete_hit_sp_pair(hip_hit_t *src_hit, hip_hit_t *dst_hit, u8 proto, int use_full_prefix) { int so, len, err = 0; u8 prefix = (use_full_prefix) ? 128 : HIP_HIT_PREFIX_LEN; HIP_DEBUG("\n"); HIP_IFEL(((so = pfkey_open()) < 0), -1, "ERROR in opening pfkey socket: %s\n", ipsec_strerror()); HIP_IFEBL((hip_pfkey_policy_modify(so, dst_hit, prefix, src_hit, prefix, NULL, NULL, proto, SADB_X_SPDDELETE, IPSEC_DIR_INBOUND)<0), -1, pfkey_close(so), "ERROR in deleting the inbound policy\n"); HIP_IFEL(((so = pfkey_open()) < 0), -1, "ERROR in opening pfkey socket: %s\n", ipsec_strerror()); HIP_IFEBL((hip_pfkey_policy_modify(so, src_hit, prefix, dst_hit, prefix, NULL, NULL, proto, SADB_X_SPDDELETE, IPSEC_DIR_OUTBOUND)<0), -1, pfkey_close(so), "ERROR in deleting the outbound policy\n"); out_err: return; }
int hip_flush_all_policy() { int so, len, err = 0; HIP_DEBUG("\n"); HIP_IFEL(((so = pfkey_open()) < 0), -1, "ERROR in opening pfkey socket: %s\n", ipsec_strerror()); HIP_DEBUG("FLushing all SP's\n"); HIP_IFEBL(((len = pfkey_send_spdflush(so))<0), -1, pfkey_close(so), "ERROR in flushing policies %s\n", ipsec_strerror()); HIP_DEBUG("FLushing all SP's was successful\n"); return len; out_err: HIP_ERROR("FLushing all SP's\n"); return err; }
/* Security associations in the kernel with BEET are bounded to the outer * address, meaning IP addresses. As a result the parameters to be given * should be such an addresses and not the HITs. */ uint32_t hip_add_sa(struct in6_addr *saddr, struct in6_addr *daddr, struct in6_addr *src_hit, struct in6_addr *dst_hit, uint32_t spi, int ealg, struct hip_crypto_key *enckey, struct hip_crypto_key *authkey, int already_acquired, int direction, int update, hip_ha_t *entry) { int so, len, err = 0, e_keylen, a_keylen; int aalg = ealg; u_int wsize = 4; /* XXX static size of window */ struct sockaddr_storage ss_addr, dd_addr; struct sockaddr *s_saddr; struct sockaddr *d_saddr; uint32_t reqid = 0; u_int32_t seq = 0; u_int flags = 0; // always zero u_int64_t lifebyte = 0, lifetime = 0; //u_int8_t l_natt_type = HIP_UDP_ENCAP_ESPINUDP_NON_IKE; u_int8_t l_natt_type = HIP_UDP_ENCAP_ESPINUDP; // FIXME: this parameter maybe should be related to some esp parameters (according to racoon source code) u_int16_t l_natt_frag = 0; /* Mappings from HIP to PFKEY algo names */ u_int e_types[] = {SADB_EALG_NULL, SADB_X_EALG_AESCBC, SADB_EALG_3DESCBC, SADB_EALG_3DESCBC, SADB_X_EALG_BLOWFISHCBC, SADB_EALG_NULL, SADB_EALG_NULL}; u_int a_algos[] = {SADB_AALG_NONE, SADB_AALG_SHA1HMAC, SADB_AALG_SHA1HMAC, SADB_AALG_MD5HMAC, SADB_AALG_SHA1HMAC, SADB_AALG_SHA1HMAC, SADB_AALG_MD5HMAC}; u_int e_type = e_types[ealg]; u_int a_type = a_algos[aalg]; in_port_t sport = entry->local_udp_port; in_port_t dport = entry->peer_udp_port; a_keylen = hip_auth_key_length_esp(ealg); e_keylen = hip_enc_key_length(ealg); get_random_bytes(&reqid, sizeof(uint32_t)); get_random_bytes(&seq, sizeof(uint32_t)); HIP_DEBUG("\n"); HIP_DEBUG_HIT("src_hit", src_hit); HIP_DEBUG_HIT("dst_hit", dst_hit); HIP_DEBUG_IN6ADDR("saddr", saddr); HIP_DEBUG_IN6ADDR("daddr", daddr); HIP_IFEL((!saddr || !daddr), 1, "Addresses not valid when adding SA's\n"); HIP_IFEL(((so = pfkey_open()) < 0), 1, "ERROR in opening pfkey socket: %s\n", ipsec_strerror()); s_saddr = (struct sockaddr*) &ss_addr; d_saddr = (struct sockaddr*) &dd_addr; get_sock_addr_from_in6(s_saddr, saddr); get_sock_addr_from_in6(d_saddr, daddr); if (direction == HIP_SPI_DIRECTION_OUT) { entry->outbound_sa_count++; } else { entry->inbound_sa_count++; } // NOTE: port numbers remains in host representation if (update) { if (sport) { // pfkey_send_update_nat when update = 1 and sport != 0 HIP_IFEBL(((len = pfkey_send_update_nat(so, SADB_SATYPE_ESP, HIP_IPSEC_DEFAULT_MODE, s_saddr, d_saddr, spi, reqid, wsize, (void*) enckey, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, lifetime, 0, seq, l_natt_type, sport, dport, NULL, l_natt_frag)) < 0), 1, pfkey_close(so), "ERROR in updating sa for nat: %s\n", ipsec_strerror()); } else { // pfkey_send_update when update = 1 and sport == 0 HIP_IFEBL(((len = pfkey_send_update(so, SADB_SATYPE_ESP, HIP_IPSEC_DEFAULT_MODE, s_saddr, d_saddr, spi, reqid, wsize, (void*) enckey, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, lifetime, 0, seq)) < 0), 1, pfkey_close(so), "ERROR in updating sa: %s\n", ipsec_strerror()); } } else { if (sport) { // pfkey_send_add_nat when update = 0 and sport != 0 HIP_IFEBL(((len = pfkey_send_add_nat(so, SADB_SATYPE_ESP, HIP_IPSEC_DEFAULT_MODE, s_saddr, d_saddr, spi, reqid, wsize, (void*) enckey, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, lifetime, 0, seq, l_natt_type, sport, dport, NULL, l_natt_frag)) < 0), 1, pfkey_close(so), "ERROR in adding sa for nat: %s\n", ipsec_strerror()); } else { // pfkey_send_add when update = 0 and sport == 0 HIP_IFEBL(((len = pfkey_send_add(so, SADB_SATYPE_ESP, HIP_IPSEC_DEFAULT_MODE, s_saddr, d_saddr, spi, reqid, wsize, (void*) enckey, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, lifetime, 0, seq)) < 0), 1, pfkey_close(so), "ERROR in adding sa: %s\n", ipsec_strerror()); } } return 0; out_err: return err; }