diff --git a/src/libcharon/plugins/osmo_epdg/osmo_epdg_provider.c b/src/libcharon/plugins/osmo_epdg/osmo_epdg_provider.c index 25dfbd2be..e7a16940b 100644 --- a/src/libcharon/plugins/osmo_epdg/osmo_epdg_provider.c +++ b/src/libcharon/plugins/osmo_epdg/osmo_epdg_provider.c @@ -23,6 +23,7 @@ #include "osmo_epdg_ue.h" #include +#include #include #include #include @@ -199,13 +200,55 @@ METHOD(attribute_provider_t, release_address, bool, return found; } +/* see attr_provider for similar usage */ +CALLBACK(attribute_enum_filter, bool, + void *data, enumerator_t *orig, va_list args) +{ + osmo_epdg_attribute_t *entry; + configuration_attribute_type_t *type; + chunk_t *value; + + VA_ARGS_VGET(args, type, value); + while (orig->enumerate(orig, &entry)) + { + if (entry->valid) + { + *type = entry->type; + *value = entry->value; + return TRUE; + } + } + + return FALSE; +} + METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, private_osmo_epdg_provider_t *this, linked_list_t *pools, ike_sa_t *ike_sa, linked_list_t *vips) { - /* don't forget fixing the this point if needed */ - /* no additional attributes for this ike_sa */ - return enumerator_create_empty(); + this = container_of((void *) this, private_osmo_epdg_provider_t, public.attribute); + enumerator_t *enumerator = NULL; + linked_list_t *attributes = NULL; + osmo_epdg_ue_t *ue = this->db->get_subscriber_ike(this->db, ike_sa); + + /* create an iterator based on the llist */ + if (!ue) + { + return enumerator_create_empty(); + } + + /* this ref is giving into the enumerator */ + ue->get(ue); + attributes = ue->get_attributes(ue); + enumerator = enumerator_create_cleaner( + enumerator_create_filter( + attributes->create_enumerator(attributes), + attribute_enum_filter, NULL, NULL), + (void *)ue->put, ue); + + /* this ref was taken by get_subscriber */ + ue->put(ue); + return enumerator; } METHOD(osmo_epdg_provider_t, destroy, void, diff --git a/src/libcharon/plugins/osmo_epdg/osmo_epdg_ue.c b/src/libcharon/plugins/osmo_epdg/osmo_epdg_ue.c index 7bde312aa..1766bc630 100644 --- a/src/libcharon/plugins/osmo_epdg/osmo_epdg_ue.c +++ b/src/libcharon/plugins/osmo_epdg/osmo_epdg_ue.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -59,6 +60,13 @@ struct private_osmo_epdg_ue_t { */ host_t *address; + /** + * The requested attributes/PCO options on GTP + * e.g. P-CSCF requests, DNS, .. + * holds attribute_entry_t + */ + linked_list_t *attributes; + /** * Refcount to track this object. * It will call destroy() when refcount reaches 0 @@ -145,6 +153,13 @@ METHOD(osmo_epdg_ue_t, get_state, enum osmo_epdg_ue_state, return state; } +METHOD(osmo_epdg_ue_t, get_attributes, linked_list_t *, + private_osmo_epdg_ue_t *this) +{ + /* TODO: check if we need to also take locking .. also refcounting would be great here */ + return this->attributes; +} + METHOD(osmo_epdg_ue_t, get, void, private_osmo_epdg_ue_t *this) { @@ -160,10 +175,23 @@ METHOD(osmo_epdg_ue_t, put, void, } } + +CALLBACK(destroy_attribute, void, + osmo_epdg_attribute_t *attr) +{ + if (attr->valid) + { + chunk_free(&attr->value); + } + free(attr); +} + METHOD(osmo_epdg_ue_t, destroy, void, private_osmo_epdg_ue_t *this) { this->lock->destroy(this->lock); + this->attributes->destroy_function(this->attributes, destroy_attribute); + free(this->apn); free(this->imsi); free(this); @@ -191,6 +219,7 @@ osmo_epdg_ue_t *osmo_epdg_ue_create(uint32_t id, const char *imsi, const char *a .set_address = _set_address, .get_state = _get_state, .set_state = _set_state, + .get_attributes = _get_attributes, .destroy = _destroy, }, .apn = strdup(apn), @@ -198,8 +227,27 @@ osmo_epdg_ue_t *osmo_epdg_ue_create(uint32_t id, const char *imsi, const char *a .id = id, .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), .state = UE_WAIT_LOCATION_UPDATE, + .attributes = linked_list_create(), .refcount = 1, ); + /* hardcode P-CSCF and DNS entry */ + osmo_epdg_attribute_t *entry; + host_t *host = host_create_from_string_and_family("10.74.0.31", AF_INET, 0); + INIT(entry, + .type = INTERNAL_IP4_DNS, + .value = chunk_clone(host->get_address(host)), + .valid = TRUE, + ); + this->attributes->insert_last(this->attributes, entry); + + INIT(entry, + .type = P_CSCF_IP4_ADDRESS, + .value = chunk_clone(host->get_address(host)), + .valid = TRUE, + ); + this->attributes->insert_last(this->attributes, entry); + host->destroy(host); + return &this->public; } diff --git a/src/libcharon/plugins/osmo_epdg/osmo_epdg_ue.h b/src/libcharon/plugins/osmo_epdg/osmo_epdg_ue.h index 7061fcfe3..bed0984f3 100644 --- a/src/libcharon/plugins/osmo_epdg/osmo_epdg_ue.h +++ b/src/libcharon/plugins/osmo_epdg/osmo_epdg_ue.h @@ -79,6 +79,11 @@ struct osmo_epdg_ue_t { */ void (*set_id)(osmo_epdg_ue_t *this, uint32_t unique_id); + /** + * Get Linked list of osmo_epdg_attribute_t + */ + linked_list_t *(*get_attributes)(osmo_epdg_ue_t *this); + /** * Get address. Returns NULL or a cloned' host_t object */ @@ -117,6 +122,13 @@ struct osmo_epdg_ue_t { void (*destroy)(osmo_epdg_ue_t *this); }; +struct osmo_epdg_attribute_t { + configuration_attribute_type_t type; + chunk_t value; + bool valid; +}; +typedef struct osmo_epdg_attribute_t osmo_epdg_attribute_t; + /** * Create a osmo_epdg_ue instance. * A newly created object will come with refcount = 1. Use put() to destroy it.