From 4960fab767084f9d5937960f68b84c801350f74c Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Wed, 18 Nov 2015 17:53:00 +0100 Subject: gtphub: cosmetic: rename a file. gtphub_ext.c's initial purpose was to wrap a specific function. The file then turned into everything related to DNS, which fits pretty well. Rename to gtphub_ares.c. Tweak the header comment to reflect the new file name. Sponsored-by: On-Waves ehi --- openbsc/src/gprs/Makefile.am | 2 +- openbsc/src/gprs/gtphub_ares.c | 218 +++++++++++++++++++++++++++++++++++++++++ openbsc/src/gprs/gtphub_ext.c | 216 ---------------------------------------- 3 files changed, 219 insertions(+), 217 deletions(-) create mode 100644 openbsc/src/gprs/gtphub_ares.c delete mode 100644 openbsc/src/gprs/gtphub_ext.c (limited to 'openbsc/src/gprs') diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index 5e115eb50..634948dfb 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -34,7 +34,7 @@ osmo_sgsn_LDADD = \ -lgtp $(OSMO_LIBS) $(LIBOSMOABIS_LIBS) $(LIBCARES_LIBS) \ $(LIBCRYPTO_LIBS) -lrt -osmo_gtphub_SOURCES = gtphub_main.c gtphub.c gtphub_ext.c gtphub_vty.c \ +osmo_gtphub_SOURCES = gtphub_main.c gtphub.c gtphub_ares.c gtphub_vty.c \ sgsn_ares.c gprs_utils.c osmo_gtphub_LDADD = \ $(top_builddir)/src/libcommon/libcommon.a \ diff --git a/openbsc/src/gprs/gtphub_ares.c b/openbsc/src/gprs/gtphub_ares.c new file mode 100644 index 000000000..4cacf88fd --- /dev/null +++ b/openbsc/src/gprs/gtphub_ares.c @@ -0,0 +1,218 @@ +/* GTP Hub Implementation */ + +/* (C) 2015 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * gtphub_ares.c. + * + * This file is kept separate so that these functions can be wrapped for + * gtphub_test.c. When a function and its callers are in the same compilational + * unit, the wrappability may be optimized away. + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include +#include + +#include +#include + +/* TODO split GRX ares from sgsn into a separate struct and allow use without + * globals. */ +#include +extern struct sgsn_instance *sgsn; + +struct sgsn_instance sgsn_inst = { 0 }; +struct sgsn_instance *sgsn = &sgsn_inst; + +extern void *osmo_gtphub_ctx; + +int gtphub_ares_init(struct gtphub *hub) +{ + return sgsn_ares_init(sgsn); +} + +struct ggsn_lookup { + struct llist_head entry; + struct expiring_item expiry_entry; + + struct gtphub *hub; + + char imsi_str[GSM_IMSI_LENGTH]; + char apn_ni_str[GSM_APN_LENGTH]; + char apn_oi_str[GSM_APN_LENGTH]; + int have_3dig_mnc; +}; + +static int start_ares_query(struct ggsn_lookup *lookup); + +static void ggsn_lookup_cb(void *arg, int status, int timeouts, + struct hostent *hostent) +{ + struct ggsn_lookup *lookup = arg; + LOGP(DGTPHUB, LOGL_NOTICE, "ggsn_lookup_cb(%p / %p)", lookup, + &lookup->expiry_entry); + + if (status != ARES_SUCCESS) { + LOGP(DGTPHUB, LOGL_ERROR, "DNS query failed.\n"); + + /* Need to try with three digits now */ + if (!lookup->have_3dig_mnc) { + lookup->have_3dig_mnc = 1; + if (start_ares_query(lookup) == 0) + return; + } + + LOGP(DGTPHUB, LOGL_ERROR, "Failed to resolve GGSN. (%p)\n", + lookup); + goto remove_from_queue; + } + + struct gsn_addr resolved_addr; + if (hostent->h_length > sizeof(resolved_addr.buf)) { + LOGP(DGTPHUB, LOGL_ERROR, "Addr size too large: %d > %d\n", + (int)hostent->h_length, (int)sizeof(resolved_addr.buf)); + goto remove_from_queue; + } + + /* Get the first addr from the list */ + char *addr0 = hostent->h_addr_list[0]; + if (!addr0) { + LOGP(DGTPHUB, LOGL_ERROR, "No host address.\n"); + goto remove_from_queue; + } + + memcpy(resolved_addr.buf, addr0, hostent->h_length); + resolved_addr.len = hostent->h_length; + + LOGP(DGTPHUB, LOGL_NOTICE, "resolved addr %s\n", + osmo_hexdump((unsigned char*)&resolved_addr, + sizeof(resolved_addr))); + + gtphub_resolved_ggsn(lookup->hub, lookup->apn_oi_str, &resolved_addr, + gtphub_now()); + +remove_from_queue: + LOGP(DGTPHUB, LOGL_ERROR, "Removing GGSN lookup. (%p / %p)\n", lookup, + &lookup->expiry_entry); + expiring_item_del(&lookup->expiry_entry); +} + +static void make_addr_str(struct ggsn_lookup *lookup) +{ + char *apn_oi_str; + apn_oi_str = osmo_apn_qualify_from_imsi(lookup->imsi_str, + lookup->apn_ni_str, + lookup->have_3dig_mnc); + strncpy(lookup->apn_oi_str, apn_oi_str, sizeof(lookup->apn_oi_str)); + lookup->apn_oi_str[sizeof(lookup->apn_oi_str)-1] = '\0'; +} + +static int start_ares_query(struct ggsn_lookup *lookup) +{ + LOGP(DGTPHUB, LOGL_DEBUG, "Going to query %s (%p / %p)\n", + lookup->apn_oi_str, lookup, &lookup->expiry_entry); + + int rc = sgsn_ares_query(sgsn, lookup->apn_oi_str, ggsn_lookup_cb, + lookup); + if (rc != 0) + LOGP(DGTPHUB, LOGL_ERROR, "Failed to start ares query.\n"); + return rc; +} + +static void ggsn_lookup_del_cb(struct expiring_item *expi) +{ + struct ggsn_lookup *lookup; + lookup = container_of(expi, struct ggsn_lookup, expiry_entry); + + LOGP(DGTPHUB, LOGL_NOTICE, "ggsn_lookup_del_cb(%p / %p)\n", lookup, + expi); + + lookup->expiry_entry.del_cb = 0; + expiring_item_del(expi); + + llist_del(&lookup->entry); + talloc_free(lookup); +} + +struct gtphub_peer_port *gtphub_resolve_ggsn_addr(struct gtphub *hub, + const char *imsi_str, + const char *apn_ni_str) +{ + OSMO_ASSERT(imsi_str); + OSMO_ASSERT(apn_ni_str); + + struct ggsn_lookup *lookup = talloc_zero(osmo_gtphub_ctx, + struct ggsn_lookup); + OSMO_ASSERT(lookup); + + LOGP(DGTPHUB, LOGL_NOTICE, "Request to resolve IMSI" + " '%s' with APN-NI '%s' (%p / %p)\n", + imsi_str, apn_ni_str, lookup, &lookup->expiry_entry); + + expiring_item_init(&lookup->expiry_entry); + lookup->hub = hub; + + strncpy(lookup->imsi_str, imsi_str, sizeof(lookup->imsi_str)); + lookup->imsi_str[sizeof(lookup->imsi_str)-1] = '\0'; + + strncpy(lookup->apn_ni_str, apn_ni_str, sizeof(lookup->apn_ni_str)); + lookup->apn_ni_str[sizeof(lookup->apn_ni_str)-1] = '\0'; + + make_addr_str(lookup); + + LOGP(DGTPHUB, LOGL_NOTICE, "looking for active queries...\n"); + struct ggsn_lookup *active; + llist_for_each_entry(active, &hub->ggsn_lookups, entry) { + if (strncmp(active->apn_oi_str, lookup->apn_oi_str, + sizeof(lookup->apn_oi_str)) == 0) { + /* A query already pending. Just tip our hat. */ + return NULL; + } + } + + LOGP(DGTPHUB, LOGL_NOTICE, "looking for already resolved GGSNs...\n"); + struct gtphub_resolved_ggsn *resolved; + llist_for_each_entry(resolved, &hub->resolved_ggsns, entry) { + if (strncmp(resolved->apn_oi_str, lookup->apn_oi_str, + sizeof(lookup->apn_oi_str)) == 0) { + /* Already resolved. */ + return resolved->peer; + } + } + + /* Kick off a resolution, but so far return nothing. The hope is that + * the peer will resend the request (a couple of times), and by then + * the GGSN will be resolved. */ + LOGP(DGTPHUB, LOGL_NOTICE, "kick off resolution.\n"); + + llist_add(&lookup->entry, &hub->ggsn_lookups); + + lookup->expiry_entry.del_cb = ggsn_lookup_del_cb; + expiry_add(&hub->expire_seq_maps, &lookup->expiry_entry, gtphub_now()); + + start_ares_query(lookup); + LOGP(DGTPHUB, LOGL_NOTICE, "Resolving %s %s ..." + " (Returning failure, hoping for a retry" + "once resolution has concluded)\n", + imsi_str, apn_ni_str); + + return NULL; +} diff --git a/openbsc/src/gprs/gtphub_ext.c b/openbsc/src/gprs/gtphub_ext.c deleted file mode 100644 index 5ed15fc26..000000000 --- a/openbsc/src/gprs/gtphub_ext.c +++ /dev/null @@ -1,216 +0,0 @@ -/* GTP Hub Implementation */ - -/* (C) 2015 by sysmocom s.f.m.c. GmbH - * All Rights Reserved - * - * gtphub_ext.c -- ext means extern. This file is kept separate so that these - * functions can be wrapped for gtphub_test.c. When a function and its callers - * are in the same compilational unit, the wrappability may be optimized away. - * - * Author: Neels Hofmeyr - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include -#include - -#include -#include - -#include -#include - -/* TODO split GRX ares from sgsn into a separate struct and allow use without - * globals. */ -#include -extern struct sgsn_instance *sgsn; - -struct sgsn_instance sgsn_inst = { 0 }; -struct sgsn_instance *sgsn = &sgsn_inst; - -extern void *osmo_gtphub_ctx; - -int gtphub_ares_init(struct gtphub *hub) -{ - return sgsn_ares_init(sgsn); -} - -struct ggsn_lookup { - struct llist_head entry; - struct expiring_item expiry_entry; - - struct gtphub *hub; - - char imsi_str[GSM_IMSI_LENGTH]; - char apn_ni_str[GSM_APN_LENGTH]; - char apn_oi_str[GSM_APN_LENGTH]; - int have_3dig_mnc; -}; - -static int start_ares_query(struct ggsn_lookup *lookup); - -static void ggsn_lookup_cb(void *arg, int status, int timeouts, - struct hostent *hostent) -{ - struct ggsn_lookup *lookup = arg; - LOGP(DGTPHUB, LOGL_NOTICE, "ggsn_lookup_cb(%p / %p)", lookup, - &lookup->expiry_entry); - - if (status != ARES_SUCCESS) { - LOGP(DGTPHUB, LOGL_ERROR, "DNS query failed.\n"); - - /* Need to try with three digits now */ - if (!lookup->have_3dig_mnc) { - lookup->have_3dig_mnc = 1; - if (start_ares_query(lookup) == 0) - return; - } - - LOGP(DGTPHUB, LOGL_ERROR, "Failed to resolve GGSN. (%p)\n", - lookup); - goto remove_from_queue; - } - - struct gsn_addr resolved_addr; - if (hostent->h_length > sizeof(resolved_addr.buf)) { - LOGP(DGTPHUB, LOGL_ERROR, "Addr size too large: %d > %d\n", - (int)hostent->h_length, (int)sizeof(resolved_addr.buf)); - goto remove_from_queue; - } - - /* Get the first addr from the list */ - char *addr0 = hostent->h_addr_list[0]; - if (!addr0) { - LOGP(DGTPHUB, LOGL_ERROR, "No host address.\n"); - goto remove_from_queue; - } - - memcpy(resolved_addr.buf, addr0, hostent->h_length); - resolved_addr.len = hostent->h_length; - - LOGP(DGTPHUB, LOGL_NOTICE, "resolved addr %s\n", - osmo_hexdump((unsigned char*)&resolved_addr, - sizeof(resolved_addr))); - - gtphub_resolved_ggsn(lookup->hub, lookup->apn_oi_str, &resolved_addr, - gtphub_now()); - -remove_from_queue: - LOGP(DGTPHUB, LOGL_ERROR, "Removing GGSN lookup. (%p / %p)\n", lookup, - &lookup->expiry_entry); - expiring_item_del(&lookup->expiry_entry); -} - -static void make_addr_str(struct ggsn_lookup *lookup) -{ - char *apn_oi_str; - apn_oi_str = osmo_apn_qualify_from_imsi(lookup->imsi_str, - lookup->apn_ni_str, - lookup->have_3dig_mnc); - strncpy(lookup->apn_oi_str, apn_oi_str, sizeof(lookup->apn_oi_str)); - lookup->apn_oi_str[sizeof(lookup->apn_oi_str)-1] = '\0'; -} - -static int start_ares_query(struct ggsn_lookup *lookup) -{ - LOGP(DGTPHUB, LOGL_DEBUG, "Going to query %s (%p / %p)\n", - lookup->apn_oi_str, lookup, &lookup->expiry_entry); - - int rc = sgsn_ares_query(sgsn, lookup->apn_oi_str, ggsn_lookup_cb, - lookup); - if (rc != 0) - LOGP(DGTPHUB, LOGL_ERROR, "Failed to start ares query.\n"); - return rc; -} - -static void ggsn_lookup_del_cb(struct expiring_item *expi) -{ - struct ggsn_lookup *lookup; - lookup = container_of(expi, struct ggsn_lookup, expiry_entry); - - LOGP(DGTPHUB, LOGL_NOTICE, "ggsn_lookup_del_cb(%p / %p)\n", lookup, - expi); - - lookup->expiry_entry.del_cb = 0; - expiring_item_del(expi); - - llist_del(&lookup->entry); - talloc_free(lookup); -} - -struct gtphub_peer_port *gtphub_resolve_ggsn_addr(struct gtphub *hub, - const char *imsi_str, - const char *apn_ni_str) -{ - OSMO_ASSERT(imsi_str); - OSMO_ASSERT(apn_ni_str); - - struct ggsn_lookup *lookup = talloc_zero(osmo_gtphub_ctx, - struct ggsn_lookup); - OSMO_ASSERT(lookup); - - LOGP(DGTPHUB, LOGL_NOTICE, "Request to resolve IMSI" - " '%s' with APN-NI '%s' (%p / %p)\n", - imsi_str, apn_ni_str, lookup, &lookup->expiry_entry); - - expiring_item_init(&lookup->expiry_entry); - lookup->hub = hub; - - strncpy(lookup->imsi_str, imsi_str, sizeof(lookup->imsi_str)); - lookup->imsi_str[sizeof(lookup->imsi_str)-1] = '\0'; - - strncpy(lookup->apn_ni_str, apn_ni_str, sizeof(lookup->apn_ni_str)); - lookup->apn_ni_str[sizeof(lookup->apn_ni_str)-1] = '\0'; - - make_addr_str(lookup); - - LOGP(DGTPHUB, LOGL_NOTICE, "looking for active queries...\n"); - struct ggsn_lookup *active; - llist_for_each_entry(active, &hub->ggsn_lookups, entry) { - if (strncmp(active->apn_oi_str, lookup->apn_oi_str, - sizeof(lookup->apn_oi_str)) == 0) { - /* A query already pending. Just tip our hat. */ - return NULL; - } - } - - LOGP(DGTPHUB, LOGL_NOTICE, "looking for already resolved GGSNs...\n"); - struct gtphub_resolved_ggsn *resolved; - llist_for_each_entry(resolved, &hub->resolved_ggsns, entry) { - if (strncmp(resolved->apn_oi_str, lookup->apn_oi_str, - sizeof(lookup->apn_oi_str)) == 0) { - /* Already resolved. */ - return resolved->peer; - } - } - - /* Kick off a resolution, but so far return nothing. The hope is that - * the peer will resend the request (a couple of times), and by then - * the GGSN will be resolved. */ - LOGP(DGTPHUB, LOGL_NOTICE, "kick off resolution.\n"); - - llist_add(&lookup->entry, &hub->ggsn_lookups); - - lookup->expiry_entry.del_cb = ggsn_lookup_del_cb; - expiry_add(&hub->expire_seq_maps, &lookup->expiry_entry, gtphub_now()); - - start_ares_query(lookup); - LOGP(DGTPHUB, LOGL_NOTICE, "Resolving %s %s ..." - " (Returning failure, hoping for a retry" - "once resolution has concluded)\n", - imsi_str, apn_ni_str); - - return NULL; -} -- cgit v1.2.3