Author: tjansen Date: Thu Nov 19 13:18:42 2009 New Revision: 1703 Log: Split NAT mapping creation into two steps. In the preliminary state, a mapping contains only the virtual local IPv4 address. The preliminary entry can be upgraded to its final state by filling the empty parts of the struct. This is a preparation for creating new mappings at runtime via DNS. Modified: trunk/libpisa/nat.c trunk/libpisa/nat.h trunk/pisacd/cdservers.c trunk/pisacd/cdservers.h Modified: trunk/libpisa/nat.c ============================================================================== --- trunk/libpisa/nat.c Thu Nov 19 03:12:27 2009 (r1702) +++ trunk/libpisa/nat.c Thu Nov 19 13:18:42 2009 (r1703) @@ -134,17 +134,56 @@ } /** - * Add a NAT mapping to the list. + * Add a NAT mapping to the list. Convenience function wrapping the two step + * process of creating and upgrading a preliminary NAT mapping. + * + * @param natlist NAT list containing the heads of the hashes. * @param local_private the local private IPv4 address * @param remote_private the remote private IPv4 address * @param entry associated connection manager entry + * @param mac MAC address, may be NULL if irrelevant * @return the new NAT mapping */ pisa_nat_mapping *pisa_nat_add_mapping(pisa_nat_list *natlist, struct in_addr *local_private, struct in_addr *remote_private, pisa_conmgr_entry *entry, pisa_mac *mac) { + pisa_nat_mapping *map = pisa_nat_add_preliminary(natlist, local_private); + pisa_nat_upgrade_preliminary(natlist, map, remote_private, entry, mac); + return map; +} + +/** + * Add a preliminary NAT mapping to the list. + * + * @param natlist NAT list containing the heads of the hashes. + * @param local_private the local private IPv4 address + * @return the new NAT mapping + */ +pisa_nat_mapping *pisa_nat_add_preliminary(pisa_nat_list *natlist, struct in_addr *local_private) +{ pisa_nat_mapping *map = malloc(sizeof(pisa_nat_mapping)); + memset(map, 0, sizeof(pisa_nat_mapping)); + map->state = PISA_NAT_STATE_PRELIMINARY; pisa_ipv4_copy(&map->local_private, local_private); + + HASH_ADD(hh_local_private, natlist->hash_local_private, local_private, sizeof(struct in_addr), map); + + return map; +} + +/** + * Fill in the remaining blank fields in a preliminary NAT mapping, thus + * upgrading it to the final state. + * + * @param natlist NAT list containing the heads of the hashes. + * @param map NAT mapping + * @param remove_private remote IPv4 address + * @param entry conmgr entry to the service gateway + * @param mac MAC address, may be NULL if irrelevant + */ +void pisa_nat_upgrade_preliminary(pisa_nat_list *natlist, pisa_nat_mapping *map, struct in_addr *remote_private, pisa_conmgr_entry *entry, pisa_mac *mac) +{ + map->state = PISA_NAT_STATE_FINAL; pisa_ipv4_copy(&map->remote.ipv4, remote_private); pisa_ipv6_copy(&map->remote.hit, &entry->hit); if (mac == NULL) @@ -154,10 +193,7 @@ map->connection = entry; HASH_ADD(hh_remote, natlist->hash_remote, remote, sizeof(map->remote), map); - HASH_ADD(hh_local_private, natlist->hash_local_private, local_private, sizeof(struct in_addr), map); HASH_ADD(hh_mac, natlist->hash_mac, mac, sizeof(pisa_mac), map); - - return map; } /** @@ -171,9 +207,11 @@ while (cur) { next = cur->hh_remote.next; if (!memcmp(remote_hit, &cur->remote.hit, sizeof(struct in6_addr))) { - HASH_DELETE(hh_remote, natlist->hash_remote, cur); + if (cur->state == PISA_NAT_STATE_FINAL) { + HASH_DELETE(hh_remote, natlist->hash_remote, cur); + HASH_DELETE(hh_mac, natlist->hash_mac, cur); + } HASH_DELETE(hh_local_private, natlist->hash_local_private, cur); - HASH_DELETE(hh_mac, natlist->hash_mac, cur); free(cur); } cur = next; Modified: trunk/libpisa/nat.h ============================================================================== --- trunk/libpisa/nat.h Thu Nov 19 03:12:27 2009 (r1702) +++ trunk/libpisa/nat.h Thu Nov 19 13:18:42 2009 (r1703) @@ -19,6 +19,11 @@ #include "conmgr.h" #include "arp.h" +typedef enum { + PISA_NAT_STATE_PRELIMINARY = 1, + PISA_NAT_STATE_FINAL = 2 +} pisa_nat_state; + typedef struct pisa_nat_mapping { struct in_addr local_private; pisa_mac mac; @@ -27,6 +32,7 @@ struct in6_addr hit; } remote; pisa_conmgr_entry *connection; + pisa_nat_state state; UT_hash_handle hh_local_private; UT_hash_handle hh_mac; @@ -43,6 +49,8 @@ void pisa_nat_destroy(pisa_nat_list *natlist); pisa_nat_mapping *pisa_nat_add_mapping(pisa_nat_list *natlist, struct in_addr *local_private, struct in_addr *remote_private, pisa_conmgr_entry *entry, pisa_mac *mac); +pisa_nat_mapping *pisa_nat_add_preliminary(pisa_nat_list *natlist, struct in_addr *local_private); +void pisa_nat_upgrade_preliminary(pisa_nat_list *natlist, pisa_nat_mapping *map, struct in_addr *remote_private, pisa_conmgr_entry *entry, pisa_mac *mac); void pisa_nat_del_mapping(pisa_nat_list *natlist, struct in6_addr *remote_hit); pisa_nat_mapping *pisa_nat_mapping_find_by_remote(pisa_nat_list *natlist, struct in6_addr *remote_hit, struct in_addr *remote_ipv4); pisa_nat_mapping *pisa_nat_mapping_find_by_local_private(pisa_nat_list *natlist, struct in_addr *local_private); Modified: trunk/pisacd/cdservers.c ============================================================================== --- trunk/pisacd/cdservers.c Thu Nov 19 03:12:27 2009 (r1702) +++ trunk/pisacd/cdservers.c Thu Nov 19 13:18:42 2009 (r1703) @@ -209,3 +209,24 @@ pisa_servers_add_mapping(config_setting_get_elem(mappings, i), entry); PISA_DEBUG(PL_CONFIG, "\n"); } + +/** + * Retrieve the conmgr entry for a given local IP address. If the entry + * already exists we return it. Otherwise we create a preliminary entry and + * schedule a DNS query. + * + * @param local_ip virtual local IP address of the service + * @return nat mappin, either full or preliminary + */ +pisa_nat_mapping *pisa_servers_add_via_dns(struct in_addr *local_ip) +{ + pisa_nat_mapping *nat; + + if ((nat = pisa_nat_mapping_find_by_local_private(cd_ctx.natlist, local_ip))) + return nat; + + nat = pisa_nat_add_preliminary(cd_ctx.natlist, local_ip); + /* Todo: schedule DNS query */ + + return nat; +} Modified: trunk/pisacd/cdservers.h ============================================================================== --- trunk/pisacd/cdservers.h Thu Nov 19 03:12:27 2009 (r1702) +++ trunk/pisacd/cdservers.h Thu Nov 19 13:18:42 2009 (r1703) @@ -12,4 +12,6 @@ void pisa_servers_add_services(pisa_conmgr_entry *entry); pisa_conmgr_entry *pisa_server_add(struct in6_addr *hit, int port, pisa_contype type); +pisa_nat_mapping *pisa_servers_add_via_dns(struct in_addr *local_ip); + #endif /* PISA_CDSERVERS_H */