This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Max gerrit-no-reply at lists.osmocom.orgHello Harald Welte, Jenkins Builder, I'd like you to reexamine a change. Please visit https://gerrit.osmocom.org/1821 to look at the new patch set (#3). Move lu_operation into separate file Create luop.(c|h) and move lu_operation and corresponding TX functions there to facilitate re-use in upcoming control interface. Change-Id: Ic55a45d56b37be2ba43d96f7da2af43b46af9813 Related: OS#1645 --- M src/Makefile.am M src/hlr.c A src/luop.c A src/luop.h 4 files changed, 322 insertions(+), 242 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-hlr refs/changes/21/1821/3 diff --git a/src/Makefile.am b/src/Makefile.am index 9bbc13e..56a5670 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,6 +14,7 @@ noinst_HEADERS = \ auc.h \ db.h \ + luop.h \ gsup_router.h \ gsup_server.h \ logging.h \ @@ -32,6 +33,7 @@ osmo_hlr_SOURCES = \ auc.c \ db.c \ + luop.c \ db_auc.c \ db_hlr.c \ gsup_router.c \ diff --git a/src/hlr.c b/src/hlr.c index 206ddc1..8c9eeb8 100644 --- a/src/hlr.c +++ b/src/hlr.c @@ -38,6 +38,7 @@ #include "gsup_server.h" #include "gsup_router.h" #include "rand.h" +#include "luop.h" #include "hlr_vty.h" static struct db_context *g_dbc; @@ -83,187 +84,9 @@ static LLIST_HEAD(g_lu_ops); -#define CANCEL_TIMEOUT_SECS 30 -#define ISD_TIMEOUT_SECS 30 - -enum lu_state { - LU_S_NULL, - LU_S_LU_RECEIVED, - LU_S_CANCEL_SENT, - LU_S_CANCEL_ACK_RECEIVED, - LU_S_ISD_SENT, - LU_S_ISD_ACK_RECEIVED, - LU_S_COMPLETE, -}; - -static const struct value_string lu_state_names[] = { - { LU_S_NULL, "NULL" }, - { LU_S_LU_RECEIVED, "LU RECEIVED" }, - { LU_S_CANCEL_SENT, "CANCEL SENT" }, - { LU_S_CANCEL_ACK_RECEIVED, "CANCEL-ACK RECEIVED" }, - { LU_S_ISD_SENT, "ISD SENT" }, - { LU_S_ISD_ACK_RECEIVED, "ISD-ACK RECEIVED" }, - { LU_S_COMPLETE, "COMPLETE" }, - { 0, NULL } -}; - -struct lu_operation { - /*! entry in global list of location update operations */ - struct llist_head list; - /*! to which gsup_server do we belong */ - struct osmo_gsup_server *gsup_server; - /*! state of the location update */ - enum lu_state state; - /*! CS (false) or PS (true) Location Update? */ - bool is_ps; - /*! currently running timer */ - struct osmo_timer_list timer; - - /*! subscriber related to this operation */ - struct hlr_subscriber subscr; - /*! peer VLR/SGSN starting the request */ - uint8_t *peer; -}; - -void lu_op_tx_insert_subscr_data(struct lu_operation *luop); - -void lu_op_statechg(struct lu_operation *luop, enum lu_state new_state) -{ - enum lu_state old_state = luop->state; - - DEBUGP(DMAIN, "LU OP state change: %s -> ", - get_value_string(lu_state_names, old_state)); - DEBUGPC(DMAIN, "%s\n", - get_value_string(lu_state_names, new_state)); - - luop->state = new_state; -} - -struct lu_operation *lu_op_by_imsi(const char *imsi) -{ - struct lu_operation *luop; - - llist_for_each_entry(luop, &g_lu_ops, list) { - if (!strcmp(imsi, luop->subscr.imsi)) - return luop; - } - return NULL; -} - -/* Send a msgb to a given address using routing */ -int osmo_gsup_addr_send(struct osmo_gsup_server *gs, - const uint8_t *addr, size_t addrlen, - struct msgb *msg) -{ - struct osmo_gsup_conn *conn; - - conn = gsup_route_find(gs, addr, addrlen); - if (!conn) { - DEBUGP(DMAIN, "Cannot find route for addr %s\n", addr); - msgb_free(msg); - return -ENODEV; - } - - return osmo_gsup_conn_send(conn, msg); -} - -/* Transmit a given GSUP message for the given LU operation */ -static void _luop_tx_gsup(struct lu_operation *luop, - const struct osmo_gsup_message *gsup) -{ - struct msgb *msg_out; - - msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP LUOP"); - osmo_gsup_encode(msg_out, gsup); - - osmo_gsup_addr_send(luop->gsup_server, luop->peer, - talloc_total_size(luop->peer), - msg_out); -} - -static inline void fill_gsup_msg(struct osmo_gsup_message *out, - const struct lu_operation *lu, - enum osmo_gsup_message_type mt) -{ - memset(out, 0, sizeof(struct osmo_gsup_message)); - if (lu) - osmo_strlcpy(out->imsi, lu->subscr.imsi, - GSM23003_IMSI_MAX_DIGITS + 1); - out->message_type = mt; -} - -/*! Transmit UPD_LOC_ERROR and destroy lu_operation */ -void lu_op_tx_error(struct lu_operation *luop, enum gsm48_gmm_cause cause) -{ - struct osmo_gsup_message gsup; - - DEBUGP(DMAIN, "%s: LU OP Tx Error (cause %s)\n", - luop->subscr.imsi, get_value_string(gsm48_gmm_cause_names, - cause)); - - fill_gsup_msg(&gsup, luop, OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR); - gsup.cause = cause; - - _luop_tx_gsup(luop, &gsup); - - llist_del(&luop->list); - talloc_free(luop); -} - -/* timer call-back in case LU operation doesn't receive an response */ -static void lu_op_timer_cb(void *data) -{ - struct lu_operation *luop = data; - - DEBUGP(DMAIN, "LU OP timer expired in state %s\n", - get_value_string(lu_state_names, luop->state)); - - switch (luop->state) { - case LU_S_CANCEL_SENT: - break; - case LU_S_ISD_SENT: - break; - default: - break; - } - - lu_op_tx_error(luop, GMM_CAUSE_NET_FAIL); -} - -/*! Transmit UPD_LOC_RESULT and destroy lu_operation */ -void lu_op_tx_ack(struct lu_operation *luop) -{ - struct osmo_gsup_message gsup; - - fill_gsup_msg(&gsup, luop, OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT); - //FIXME gsup.hlr_enc; - - _luop_tx_gsup(luop, &gsup); - - llist_del(&luop->list); - talloc_free(luop); -} - -/*! Send Cancel Location to old VLR/SGSN */ -void lu_op_tx_cancel_old(struct lu_operation *luop) -{ - struct osmo_gsup_message gsup; - - OSMO_ASSERT(luop->state == LU_S_LU_RECEIVED); - - fill_gsup_msg(&gsup, NULL, OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST); - //gsup.cause = FIXME; - //gsup.cancel_type = FIXME; - - _luop_tx_gsup(luop, &gsup); - - lu_op_statechg(luop, LU_S_CANCEL_SENT); - osmo_timer_schedule(&luop->timer, CANCEL_TIMEOUT_SECS, 0); -} - /*! Receive Cancel Location Result from old VLR/SGSN */ void lu_op_rx_cancel_old_ack(struct lu_operation *luop, - const struct osmo_gsup_message *gsup) + const struct osmo_gsup_message *gsup) { OSMO_ASSERT(luop->state == LU_S_CANCEL_SENT); /* FIXME: Check for spoofing */ @@ -273,55 +96,6 @@ /* FIXME */ lu_op_tx_insert_subscr_data(luop); -} - -/*! Transmit Insert Subscriber Data to new VLR/SGSN */ -void lu_op_tx_insert_subscr_data(struct lu_operation *luop) -{ - struct osmo_gsup_message gsup; - uint8_t apn[APN_MAXLEN]; - uint8_t msisdn_enc[43]; /* TODO use constant; TS 24.008 10.5.4.7 */ - int l; - - OSMO_ASSERT(luop->state == LU_S_LU_RECEIVED || - luop->state == LU_S_CANCEL_ACK_RECEIVED); - - fill_gsup_msg(&gsup, luop, OSMO_GSUP_MSGT_INSERT_DATA_REQUEST); - - l = gsm48_encode_bcd_number(msisdn_enc, sizeof(msisdn_enc), 0, - luop->subscr.msisdn); - if (l < 1) { - LOGP(DMAIN, LOGL_ERROR, - "%s: Error: cannot encode MSISDN '%s'\n", - luop->subscr.imsi, luop->subscr.msisdn); - lu_op_tx_error(luop, GMM_CAUSE_PROTO_ERR_UNSPEC); - return; - } - gsup.msisdn_enc = msisdn_enc; - gsup.msisdn_enc_len = l; - - /* FIXME: deal with encoding the following data */ - gsup.hlr_enc; - - if (luop->is_ps) { - /* FIXME: PDP infos - use more fine-grained access control - instead of wildcard APN */ - l = osmo_apn_from_str(apn, sizeof(apn), "*"); - if (l > 0) { - gsup.pdp_infos[0].apn_enc = apn; - gsup.pdp_infos[0].apn_enc_len = l; - gsup.pdp_infos[0].have_info = 1; - gsup.num_pdp_infos = 1; - /* FIXME: use real value: */ - gsup.pdp_infos[0].context_id = 1; - } - } - - /* Send ISD to new VLR/SGSN */ - _luop_tx_gsup(luop, &gsup); - - lu_op_statechg(luop, LU_S_ISD_SENT); - osmo_timer_schedule(&luop->timer, ISD_TIMEOUT_SECS, 0); } /*! Receive Insert Subscriber Data Result from new VLR/SGSN */ @@ -362,19 +136,6 @@ gsup->message_type); break; } -} - -static struct lu_operation *lu_op_alloc(struct osmo_gsup_server *srv) -{ - struct lu_operation *luop; - - luop = talloc_zero(srv, struct lu_operation); - OSMO_ASSERT(luop); - luop->gsup_server = srv; - luop->timer.cb = lu_op_timer_cb; - luop->timer.data = luop; - - return luop; } /*! Receive Update Location Request, creates new \ref lu_operation */ @@ -508,7 +269,8 @@ case OSMO_GSUP_MSGT_LOCATION_CANCEL_ERROR: case OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT: { - struct lu_operation *luop = lu_op_by_imsi(gsup.imsi); + struct lu_operation *luop = lu_op_by_imsi(gsup.imsi, + &g_lu_ops); if (!luop) { LOGP(DMAIN, LOGL_ERROR, "GSUP message %u for " "unknown IMSI %s\n", gsup.message_type, diff --git a/src/luop.c b/src/luop.c new file mode 100644 index 0000000..ef845d0 --- /dev/null +++ b/src/luop.c @@ -0,0 +1,242 @@ +/* OsmoHLR TX/RX lu operations */ + +/* (C) 2017 sysmocom s.f.m.c. GmbH <info at sysmocom.de> + * All Rights Reserved + * + * Author: Harald Welte <laforge at gnumonks.org> + * + * 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 <http://www.gnu.org/licenses/>. + * + */ + +#include <string.h> +#include <errno.h> + +#include <osmocom/core/logging.h> +#include <osmocom/gsm/gsm48_ie.h> +#include <osmocom/gsm/gsup.h> +#include <osmocom/gsm/apn.h> + +#include "gsup_server.h" +#include "gsup_router.h" +#include "logging.h" +#include "luop.h" + +const struct value_string lu_state_names[] = { + { LU_S_NULL, "NULL" }, + { LU_S_LU_RECEIVED, "LU RECEIVED" }, + { LU_S_CANCEL_SENT, "CANCEL SENT" }, + { LU_S_CANCEL_ACK_RECEIVED, "CANCEL-ACK RECEIVED" }, + { LU_S_ISD_SENT, "ISD SENT" }, + { LU_S_ISD_ACK_RECEIVED, "ISD-ACK RECEIVED" }, + { LU_S_COMPLETE, "COMPLETE" }, + { 0, NULL } +}; + +/* Transmit a given GSUP message for the given LU operation */ +static void _luop_tx_gsup(struct lu_operation *luop, + const struct osmo_gsup_message *gsup) +{ + struct msgb *msg_out; + + msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP LUOP"); + osmo_gsup_encode(msg_out, gsup); + + osmo_gsup_addr_send(luop->gsup_server, luop->peer, + talloc_total_size(luop->peer), + msg_out); +} + +static inline void fill_gsup_msg(struct osmo_gsup_message *out, + const struct lu_operation *lu, + enum osmo_gsup_message_type mt) +{ + memset(out, 0, sizeof(struct osmo_gsup_message)); + if (lu) + osmo_strlcpy(out->imsi, lu->subscr.imsi, + GSM23003_IMSI_MAX_DIGITS + 1); + out->message_type = mt; +} + +/* timer call-back in case LU operation doesn't receive an response */ +static void lu_op_timer_cb(void *data) +{ + struct lu_operation *luop = data; + + DEBUGP(DMAIN, "LU OP timer expired in state %s\n", + get_value_string(lu_state_names, luop->state)); + + switch (luop->state) { + case LU_S_CANCEL_SENT: + break; + case LU_S_ISD_SENT: + break; + default: + break; + } + + lu_op_tx_error(luop, GMM_CAUSE_NET_FAIL); +} + +struct lu_operation *lu_op_alloc(struct osmo_gsup_server *srv) +{ + struct lu_operation *luop; + + luop = talloc_zero(srv, struct lu_operation); + OSMO_ASSERT(luop); + luop->gsup_server = srv; + luop->timer.cb = lu_op_timer_cb; + luop->timer.data = luop; + + return luop; +} + +struct lu_operation *lu_op_by_imsi(const char *imsi, + const struct llist_head *lst) +{ + struct lu_operation *luop; + + llist_for_each_entry(luop, lst, list) { + if (!strcmp(imsi, luop->subscr.imsi)) + return luop; + } + return NULL; +} + +void lu_op_statechg(struct lu_operation *luop, enum lu_state new_state) +{ + enum lu_state old_state = luop->state; + + DEBUGP(DMAIN, "LU OP state change: %s -> ", + get_value_string(lu_state_names, old_state)); + DEBUGPC(DMAIN, "%s\n", + get_value_string(lu_state_names, new_state)); + + luop->state = new_state; +} + +/* Send a msgb to a given address using routing */ +int osmo_gsup_addr_send(struct osmo_gsup_server *gs, + const uint8_t *addr, size_t addrlen, + struct msgb *msg) +{ + struct osmo_gsup_conn *conn; + + conn = gsup_route_find(gs, addr, addrlen); + if (!conn) { + DEBUGP(DMAIN, "Cannot find route for addr %s\n", addr); + msgb_free(msg); + return -ENODEV; + } + + return osmo_gsup_conn_send(conn, msg); +} + +/*! Transmit UPD_LOC_ERROR and destroy lu_operation */ +void lu_op_tx_error(struct lu_operation *luop, enum gsm48_gmm_cause cause) +{ + struct osmo_gsup_message gsup; + + DEBUGP(DMAIN, "%s: LU OP Tx Error (cause %s)\n", + luop->subscr.imsi, get_value_string(gsm48_gmm_cause_names, + cause)); + + fill_gsup_msg(&gsup, luop, OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR); + gsup.cause = cause; + + _luop_tx_gsup(luop, &gsup); + + llist_del(&luop->list); + talloc_free(luop); +} + +/*! Transmit UPD_LOC_RESULT and destroy lu_operation */ +void lu_op_tx_ack(struct lu_operation *luop) +{ + struct osmo_gsup_message gsup; + + fill_gsup_msg(&gsup, luop, OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT); + //FIXME gsup.hlr_enc; + + _luop_tx_gsup(luop, &gsup); + + llist_del(&luop->list); + talloc_free(luop); +} + +/*! Send Cancel Location to old VLR/SGSN */ +void lu_op_tx_cancel_old(struct lu_operation *luop) +{ + struct osmo_gsup_message gsup; + + OSMO_ASSERT(luop->state == LU_S_LU_RECEIVED); + + fill_gsup_msg(&gsup, NULL, OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST); + //gsup.cause = FIXME; + //gsup.cancel_type = FIXME; + + _luop_tx_gsup(luop, &gsup); + + lu_op_statechg(luop, LU_S_CANCEL_SENT); + osmo_timer_schedule(&luop->timer, CANCEL_TIMEOUT_SECS, 0); +} + +/*! Transmit Insert Subscriber Data to new VLR/SGSN */ +void lu_op_tx_insert_subscr_data(struct lu_operation *luop) +{ + struct osmo_gsup_message gsup; + uint8_t apn[APN_MAXLEN]; + uint8_t msisdn_enc[43]; /* TODO use constant; TS 24.008 10.5.4.7 */ + int l; + + OSMO_ASSERT(luop->state == LU_S_LU_RECEIVED || + luop->state == LU_S_CANCEL_ACK_RECEIVED); + + fill_gsup_msg(&gsup, luop, OSMO_GSUP_MSGT_INSERT_DATA_REQUEST); + + l = gsm48_encode_bcd_number(msisdn_enc, sizeof(msisdn_enc), 0, + luop->subscr.msisdn); + if (l < 1) { + LOGP(DMAIN, LOGL_ERROR, + "%s: Error: cannot encode MSISDN '%s'\n", + luop->subscr.imsi, luop->subscr.msisdn); + lu_op_tx_error(luop, GMM_CAUSE_PROTO_ERR_UNSPEC); + return; + } + gsup.msisdn_enc = msisdn_enc; + gsup.msisdn_enc_len = l; + + /* FIXME: deal with encoding the following data */ + gsup.hlr_enc; + + if (luop->is_ps) { + /* FIXME: PDP infos - use more fine-grained access control + instead of wildcard APN */ + l = osmo_apn_from_str(apn, sizeof(apn), "*"); + if (l > 0) { + gsup.pdp_infos[0].apn_enc = apn; + gsup.pdp_infos[0].apn_enc_len = l; + gsup.pdp_infos[0].have_info = 1; + gsup.num_pdp_infos = 1; + /* FIXME: use real value: */ + gsup.pdp_infos[0].context_id = 1; + } + } + + /* Send ISD to new VLR/SGSN */ + _luop_tx_gsup(luop, &gsup); + + lu_op_statechg(luop, LU_S_ISD_SENT); + osmo_timer_schedule(&luop->timer, ISD_TIMEOUT_SECS, 0); +} diff --git a/src/luop.h b/src/luop.h new file mode 100644 index 0000000..fea6e2f --- /dev/null +++ b/src/luop.h @@ -0,0 +1,74 @@ +/* OsmoHLR TX/RX lu operations */ + +/* (C) 2017 sysmocom s.f.m.c. GmbH <info at sysmocom.de> + * All Rights Reserved + * + * Author: Harald Welte <laforge at gnumonks.org> + * + * 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 <http://www.gnu.org/licenses/>. + * + */ + +#pragma once + +#include <osmocom/core/timer.h> + +#include "db.h" + +#define CANCEL_TIMEOUT_SECS 30 +#define ISD_TIMEOUT_SECS 30 + +enum lu_state { + LU_S_NULL, + LU_S_LU_RECEIVED, + LU_S_CANCEL_SENT, + LU_S_CANCEL_ACK_RECEIVED, + LU_S_ISD_SENT, + LU_S_ISD_ACK_RECEIVED, + LU_S_COMPLETE, +}; + +extern const struct value_string lu_state_names[]; + +struct lu_operation { + /*! entry in global list of location update operations */ + struct llist_head list; + /*! to which gsup_server do we belong */ + struct osmo_gsup_server *gsup_server; + /*! state of the location update */ + enum lu_state state; + /*! CS (false) or PS (true) Location Update? */ + bool is_ps; + /*! currently running timer */ + struct osmo_timer_list timer; + + /*! subscriber related to this operation */ + struct hlr_subscriber subscr; + /*! peer VLR/SGSN starting the request */ + uint8_t *peer; +}; + +int osmo_gsup_addr_send(struct osmo_gsup_server *gs, + const uint8_t *addr, size_t addrlen, + struct msgb *msg); + +struct lu_operation *lu_op_alloc(struct osmo_gsup_server *srv); +void lu_op_statechg(struct lu_operation *luop, enum lu_state new_state); +struct lu_operation *lu_op_by_imsi(const char *imsi, + const struct llist_head *lst); + +void lu_op_tx_error(struct lu_operation *luop, enum gsm48_gmm_cause cause); +void lu_op_tx_ack(struct lu_operation *luop); +void lu_op_tx_cancel_old(struct lu_operation *luop); +void lu_op_tx_insert_subscr_data(struct lu_operation *luop); -- To view, visit https://gerrit.osmocom.org/1821 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newpatchset Gerrit-Change-Id: Ic55a45d56b37be2ba43d96f7da2af43b46af9813 Gerrit-PatchSet: 3 Gerrit-Project: osmo-hlr Gerrit-Branch: master Gerrit-Owner: Max <msuraev at sysmocom.de> Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de>