laforge has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-hlr/+/33097 )

Change subject: Port to new libosmogsm 'struct osmo_sub_auth_data2'
......................................................................

Port to new libosmogsm 'struct osmo_sub_auth_data2'

libosmogsm has recently introdcued a 'struct osmo_sub_auth_data2' as
successor to 'struct osmo_sub_auth_data', together with updated
osmo_auth_gen_vec2/osmo_auth_gen_vec_auts2 API.

The rationale of this new API is to enable
* support for AKA algorithms which use K and/or OP[c] values of 256bit
  (instead of the classic 128bit)
* support for RES length sizes of 4 and 16 bytes (instead of the classic
  8 bytes)

This commit just jumps over to the new API without adding any related
functionality to osmo-hlr.  The latter is left for subsequent commits.

Change-Id: I3207c7bfb73e9ff5471e5c26b66639549e4d48a2
Depends: libosmocore.git Ie775fedba4a3fa12314c0f7c8a369662ef6a40df
---
M TODO-RELEASE
M include/osmocom/hlr/auc.h
M include/osmocom/hlr/db.h
M src/auc.c
M src/ctrl.c
M src/db_auc.c
M src/hlr.c
M src/hlr_vty_subscr.c
M tests/auc/auc_test.c
M tests/auc/gen_ts_55_205_test_sets/func_template.c
M tests/db/db_test.c
M tests/db/db_test.err
12 files changed, 191 insertions(+), 134 deletions(-)

Approvals:
  Jenkins Builder: Verified
  pespin: Looks good to me, but someone else must approve
  fixeria: Looks good to me, but someone else must approve
  laforge: Looks good to me, approved




diff --git a/TODO-RELEASE b/TODO-RELEASE
index 62fe828..4c445eb 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -7,4 +7,4 @@
 # If any interfaces have been added since the last public release: c:r:a + 1.
 # If any interfaces have been removed or changed since the last public 
release: c:r:0.
 #library        what            description / commit summary line
-libosmogsm     UPDATE_DEP_VER  update libosmogsm version dependency after 
I0ee0565382c1e4515d44ff9b1752685c0a66ae39 is released
+libosmogsm     UPDATE_DEP_VER  update libosmogsm version dependency after 
Ie775fedba4a3fa12314c0f7c8a369662ef6a40df is released
diff --git a/include/osmocom/hlr/auc.h b/include/osmocom/hlr/auc.h
index f5b6765..1d86398 100644
--- a/include/osmocom/hlr/auc.h
+++ b/include/osmocom/hlr/auc.h
@@ -3,6 +3,6 @@
 #include <osmocom/crypt/auth.h>

 int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
-                       struct osmo_sub_auth_data *aud2g,
-                       struct osmo_sub_auth_data *aud3g,
+                       struct osmo_sub_auth_data2 *aud2g,
+                       struct osmo_sub_auth_data2 *aud3g,
                        const uint8_t *rand_auts, const uint8_t *auts);
diff --git a/include/osmocom/hlr/db.h b/include/osmocom/hlr/db.h
index c43aa4f..588a96d 100644
--- a/include/osmocom/hlr/db.h
+++ b/include/osmocom/hlr/db.h
@@ -70,8 +70,8 @@

 /* obtain the authentication data for a given imsi */
 int db_get_auth_data(struct db_context *dbc, const char *imsi,
-                    struct osmo_sub_auth_data *aud2g,
-                    struct osmo_sub_auth_data *aud3g,
+                    struct osmo_sub_auth_data2 *aud2g,
+                    struct osmo_sub_auth_data2 *aud3g,
                     int64_t *subscr_id);

 int db_update_sqn(struct db_context *dbc, int64_t id,
@@ -121,7 +121,7 @@
  * See https://sqlite.org/lang_datefunc.html, function datetime(). */
 #define DB_LAST_LU_SEEN_FMT "%Y-%m-%d %H:%M:%S"

-/* Like struct osmo_sub_auth_data, but the keys are in hexdump representation.
+/* Like struct osmo_sub_auth_data2, but the keys are in hexdump representation.
  * This is useful because SQLite requires them in hexdump format, and callers
  * like the VTY and CTRL interface also have them available as hexdump to begin
  * with. In the binary format, a VTY command would first need to hexparse,
diff --git a/src/auc.c b/src/auc.c
index 28c441f..3ec0893 100644
--- a/src/auc.c
+++ b/src/auc.c
@@ -1,4 +1,4 @@
-/* (C) 2015 by Harald Welte <[email protected]>
+/* (C) 2015-2023 by Harald Welte <[email protected]>
  *
  * All Rights Reserved
  *
@@ -32,8 +32,8 @@
 /* compute given number of vectors using either aud2g or aud2g or a combination
  * of both.  Handles re-synchronization if rand_auts and auts are set */
 int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
-                       struct osmo_sub_auth_data *aud2g,
-                       struct osmo_sub_auth_data *aud3g,
+                       struct osmo_sub_auth_data2 *aud2g,
+                       struct osmo_sub_auth_data2 *aud3g,
                        const uint8_t *rand_auts, const uint8_t *auts)
 {
        unsigned int i;
@@ -93,10 +93,10 @@
             : "2G only",
             auts? ", with AUTS resync" : "");
        if (aud3g) {
-               DBGP("3G: k = %s\n", hexb(aud3g->u.umts.k));
+               DBGP("3G: k = %s\n", hex(aud3g->u.umts.k, aud3g->u.umts.k_len));
                DBGP("3G: %s = %s\n",
                     aud3g->u.umts.opc_is_op? "OP" : "opc",
-                    hexb(aud3g->u.umts.opc));
+                    hex(aud3g->u.umts.opc, aud3g->u.umts.opc_len));
                DBGP("3G: for sqn ind %u, previous sqn was %" PRIu64 "\n",
                     aud3g->u.umts.ind, aud3g->u.umts.sqn);
        }
@@ -115,6 +115,9 @@
                if (aud3g) {
                        /* 3G or 3G + 2G case */

+                       /* backwards-compatibiliy: We assume all RES are 8 
bytes long */
+                       vec[i].res_len = 8;
+
                        /* Do AUTS only for the first vector or we would use
                         * the same SQN for each following key. */
                        if ((i == 0) && auts) {
@@ -123,10 +126,10 @@
                                DBGP("vector [%u]: resync: rand_auts = %s\n",
                                     i, hex(rand_auts, 16));

-                               rc = osmo_auth_gen_vec_auts(vec+i, aud3g, auts,
+                               rc = osmo_auth_gen_vec_auts2(vec+i, aud3g, auts,
                                                            rand_auts, rand);
                        } else {
-                               rc = osmo_auth_gen_vec(vec+i, aud3g, rand);
+                               rc = osmo_auth_gen_vec2(vec+i, aud3g, rand);
                        }
                        if (rc < 0) {
                                LOGP(DAUC, LOGL_ERROR, "Error in 3G vector "
@@ -154,7 +157,7 @@

                        DBGP("vector [%u]: calculating 2G separately\n", i);

-                       rc = osmo_auth_gen_vec(&vtmp, aud2g, rand);
+                       rc = osmo_auth_gen_vec2(&vtmp, aud2g, rand);
                        if (rc < 0) {
                                LOGP(DAUC, LOGL_ERROR, "Error in 2G vector"
                                     "generation: [%u]: rc = %d\n", i, rc);
@@ -165,7 +168,7 @@
                        vec[i].auth_types |= OSMO_AUTH_TYPE_GSM;
                } else {
                        /* 2G only case */
-                       rc = osmo_auth_gen_vec(vec+i, aud2g, rand);
+                       rc = osmo_auth_gen_vec2(vec+i, aud2g, rand);
                        if (rc < 0) {
                                LOGP(DAUC, LOGL_ERROR, "Error in 2G vector "
                                     "generation: [%u]: rc = %d\n", i, rc);
diff --git a/src/ctrl.c b/src/ctrl.c
index 4e4afeb..f0f2ee6 100644
--- a/src/ctrl.c
+++ b/src/ctrl.c
@@ -1,6 +1,6 @@
 /* OsmoHLR Control Interface implementation */

-/* (C) 2017 sysmocom s.f.m.c. GmbH <[email protected]>
+/* (C) 2017-2023 sysmocom s.f.m.c. GmbH <[email protected]>
  * All Rights Reserved
  *
  * Author: Max Suraev <[email protected]>
@@ -166,7 +166,7 @@
                );
 }

-static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct 
osmo_sub_auth_data *aud)
+static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct 
osmo_sub_auth_data2 *aud)
 {
        if (aud->algo == OSMO_AUTH_ALG_NONE)
                return;
@@ -178,7 +178,7 @@
                hexdump_buf(aud->u.gsm.ki));
 }

-static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct 
osmo_sub_auth_data *aud)
+static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct 
osmo_sub_auth_data2 *aud)
 {
        if (aud->algo == OSMO_AUTH_ALG_NONE)
                return;
@@ -187,7 +187,7 @@
                "\naud3g.k\t%s"
                ,
                osmo_auth_alg_name(aud->algo),
-               hexdump_buf(aud->u.umts.k));
+               osmo_hexdump_nospc(aud->u.umts.k, aud->u.umts.k_len));
        /* hexdump uses a static string buffer, hence only one hexdump per
         * printf(). */
        ctrl_cmd_reply_printf(cmd,
@@ -196,7 +196,7 @@
                "\naud3g.sqn\t%" PRIu64
                ,
                aud->u.umts.opc_is_op? "op" : "opc",
-               hexdump_buf(aud->u.umts.opc),
+               osmo_hexdump_nospc(aud->u.umts.opc, aud->u.umts.opc_len),
                aud->u.umts.ind_bitlen,
                aud->u.umts.sqn);
 }
@@ -291,8 +291,8 @@
 static int get_subscr_info_aud(struct ctrl_cmd *cmd, void *data)
 {
        const char *imsi;
-       struct osmo_sub_auth_data aud2g;
-       struct osmo_sub_auth_data aud3g;
+       struct osmo_sub_auth_data2 aud2g;
+       struct osmo_sub_auth_data2 aud3g;
        struct hlr *hlr = data;
        const char *by_selector = cmd->node;
        int rc;
@@ -327,8 +327,8 @@
 static int get_subscr_info_all(struct ctrl_cmd *cmd, void *data)
 {
        struct hlr_subscriber subscr;
-       struct osmo_sub_auth_data aud2g;
-       struct osmo_sub_auth_data aud3g;
+       struct osmo_sub_auth_data2 aud2g;
+       struct osmo_sub_auth_data2 aud3g;
        struct hlr *hlr = data;
        const char *by_selector = cmd->node;
        int rc;
@@ -492,8 +492,8 @@
        struct hlr_subscriber subscr;
        struct hlr *hlr = data;
        const char *by_selector = cmd->node;
-       struct osmo_sub_auth_data aud2g;
-       struct osmo_sub_auth_data aud3g_unused;
+       struct osmo_sub_auth_data2 aud2g;
+       struct osmo_sub_auth_data2 aud3g_unused;
        int rc;

        if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
@@ -592,8 +592,8 @@
        struct hlr_subscriber subscr;
        struct hlr *hlr = data;
        const char *by_selector = cmd->node;
-       struct osmo_sub_auth_data aud2g_unused;
-       struct osmo_sub_auth_data aud3g;
+       struct osmo_sub_auth_data2 aud2g_unused;
+       struct osmo_sub_auth_data2 aud3g;
        int rc;

        if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
@@ -618,9 +618,9 @@
        }

        cmd->reply = talloc_asprintf(cmd, "%s,%s,%s,%s,%u", 
osmo_auth_alg_name(aud3g.algo),
-                                    osmo_hexdump_nospc_c(cmd, aud3g.u.umts.k, 
sizeof(aud3g.u.umts.k)),
+                                    osmo_hexdump_nospc_c(cmd, aud3g.u.umts.k, 
aud3g.u.umts.k_len),
                                     aud3g.u.umts.opc_is_op ? "OP" : "OPC",
-                                    osmo_hexdump_nospc_c(cmd, 
aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc)),
+                                    osmo_hexdump_nospc_c(cmd, 
aud3g.u.umts.opc, aud3g.u.umts.opc_len),
                                     aud3g.u.umts.ind_bitlen);
        return CTRL_CMD_REPLY;
 }
diff --git a/src/db_auc.c b/src/db_auc.c
index 11f282b..c72c127 100644
--- a/src/db_auc.c
+++ b/src/db_auc.c
@@ -1,4 +1,4 @@
-/* (C) 2015 by Harald Welte <[email protected]>
+/* (C) 2015-2023 by Harald Welte <[email protected]>
  *
  * All Rights Reserved
  *
@@ -74,9 +74,9 @@
 }

 /* hexparse a specific column of a sqlite prepared statement into dst (with 
length check)
- * returns 0 for success, -EIO on error */
-static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int 
col, const char *col_name,
-                        const char *imsi)
+ * returns byte length in case of success, -EIO on error */
+static int hexparse_stmt(uint8_t *dst, size_t dst_len_min, size_t dst_len_max, 
sqlite3_stmt *stmt,
+                        int col, const char *col_name, const char *imsi)
 {
        const uint8_t *text;
        size_t col_len;
@@ -84,9 +84,15 @@
        /* Bytes are stored as hex strings in database, hence divide length by 
two */
        col_len = sqlite3_column_bytes(stmt, col) / 2;

-       if (col_len != dst_len) {
-               LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected length %lu 
but has length %lu\n", col_name,
-                      dst_len, col_len);
+       if (col_len < dst_len_min) {
+               LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected min length 
%lu but has length %lu\n", col_name,
+                      dst_len_min, col_len);
+               return -EIO;
+       }
+
+       if (col_len > dst_len_max) {
+               LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected max length 
%lu but has length %lu\n", col_name,
+                      dst_len_max, col_len);
                return -EIO;
        }

@@ -96,10 +102,10 @@
                return -EIO;
        }

-       if (osmo_hexparse((void *)text, dst, dst_len) != col_len)
+       if (osmo_hexparse((void *)text, dst, dst_len_max) != col_len)
                return -EINVAL;

-       return 0;
+       return col_len;
 }

 /* obtain the authentication data for a given imsi
@@ -107,8 +113,8 @@
  * -ENOENT if the IMSI is not known, -ENOKEY if the IMSI is known but has no 
auth data,
  * -EIO on db failure */
 int db_get_auth_data(struct db_context *dbc, const char *imsi,
-                    struct osmo_sub_auth_data *aud2g,
-                    struct osmo_sub_auth_data *aud3g,
+                    struct osmo_sub_auth_data2 *aud2g,
+                    struct osmo_sub_auth_data2 *aud3g,
                     int64_t *subscr_id)
 {
        sqlite3_stmt *stmt = dbc->stmt[DB_STMT_AUC_BY_IMSI];
@@ -142,7 +148,8 @@
        /* obtain result values using sqlite3_column_*() */
        if (sqlite3_column_type(stmt, 1) == SQLITE_INTEGER) {
                /* we do have some 2G authentication data */
-               if (hexparse_stmt(aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki), 
stmt, 2, "Ki", imsi))
+               if (hexparse_stmt(aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki), 
sizeof(aud2g->u.gsm.ki),
+                                 stmt, 2, "Ki", imsi) < 0)
                        goto end_2g;
                aud2g->algo = sqlite3_column_int(stmt, 1);
                aud2g->type = OSMO_AUTH_TYPE_GSM;
@@ -151,24 +158,30 @@
 end_2g:
        if (sqlite3_column_type(stmt, 3) == SQLITE_INTEGER) {
                /* we do have some 3G authentication data */
-               if (hexparse_stmt(aud3g->u.umts.k, sizeof(aud3g->u.umts.k), 
stmt, 4, "K", imsi)) {
+               rc = hexparse_stmt(aud3g->u.umts.k, 16, 
sizeof(aud3g->u.umts.k), stmt, 4, "K", imsi);
+               if (rc < 0) {
                        ret = -EIO;
                        goto out;
                }
+               aud3g->u.umts.k_len = rc;
                aud3g->algo = sqlite3_column_int(stmt, 3);

                /* UMTS Subscribers can have either OP or OPC */
                if (sqlite3_column_text(stmt, 5)) {
-                       if (hexparse_stmt(aud3g->u.umts.opc, 
sizeof(aud3g->u.umts.opc), stmt, 5, "OP", imsi)) {
+                       rc = hexparse_stmt(aud3g->u.umts.opc, 16, 
sizeof(aud3g->u.umts.opc), stmt, 5, "OP", imsi);
+                       if (rc < 0) {
                                ret = -EIO;
                                goto out;
                        }
+                       aud3g->u.umts.opc_len = rc;
                        aud3g->u.umts.opc_is_op = 1;
                } else {
-                       if (hexparse_stmt(aud3g->u.umts.opc, 
sizeof(aud3g->u.umts.opc), stmt, 6, "OPC", imsi)) {
+                       rc = hexparse_stmt(aud3g->u.umts.opc, 16, 
sizeof(aud3g->u.umts.opc), stmt, 6, "OPC", imsi);
+                       if (rc < 0) {
                                ret = -EIO;
                                goto out;
                        }
+                       aud3g->u.umts.opc_len = rc;
                        aud3g->u.umts.opc_is_op = 0;
                }
                aud3g->u.umts.sqn = sqlite3_column_int64(stmt, 7);
@@ -194,7 +207,7 @@
               unsigned int num_vec, const uint8_t *rand_auts,
               const uint8_t *auts, bool separation_bit)
 {
-       struct osmo_sub_auth_data aud2g, aud3g;
+       struct osmo_sub_auth_data2 aud2g, aud3g;
        int64_t subscr_id;
        int ret = 0;
        int rc;
diff --git a/src/hlr.c b/src/hlr.c
index e3b54ac..457850e 100644
--- a/src/hlr.c
+++ b/src/hlr.c
@@ -724,7 +724,7 @@
 }

 static const char vlr_copyright[] =
-       "Copyright (C) 2016, 2017 by Harald Welte, sysmocom s.f.m.c. GmbH\r\n"
+       "Copyright (C) 2016-2023 by Harald Welte, sysmocom s.f.m.c. GmbH\r\n"
        "License AGPLv3+: GNU AGPL version 3 or later 
<http://gnu.org/licenses/agpl-3.0.html>\r\n"
        "This is free software: you are free to change and redistribute it.\r\n"
         "There is NO WARRANTY, to the extent permitted by law.\r\n";
diff --git a/src/hlr_vty_subscr.c b/src/hlr_vty_subscr.c
index 60a25bf..191a87d 100644
--- a/src/hlr_vty_subscr.c
+++ b/src/hlr_vty_subscr.c
@@ -1,5 +1,5 @@
 /* OsmoHLR subscriber management VTY implementation */
-/* (C) 2017 by sysmocom s.f.m.c. GmbH <[email protected]>
+/* (C) 2017-2023 by sysmocom s.f.m.c. GmbH <[email protected]>
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -77,8 +77,8 @@
 static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber 
*subscr)
 {
        int rc;
-       struct osmo_sub_auth_data aud2g;
-       struct osmo_sub_auth_data aud3g;
+       struct osmo_sub_auth_data2 aud2g;
+       struct osmo_sub_auth_data2 aud3g;

        vty_out(vty, "    ID: %"PRIu64"%s", subscr->id, VTY_NEWLINE);

@@ -137,12 +137,12 @@

        if (aud2g.type != OSMO_AUTH_TYPE_NONE && aud2g.type != 
OSMO_AUTH_TYPE_GSM) {
                vty_out(vty, "%% Error: 2G auth data is not of type 'GSM'%s", 
VTY_NEWLINE);
-               aud2g = (struct osmo_sub_auth_data){};
+               aud2g = (struct osmo_sub_auth_data2){};
        }
 
        if (aud3g.type != OSMO_AUTH_TYPE_NONE && aud3g.type != 
OSMO_AUTH_TYPE_UMTS) {
                vty_out(vty, "%% Error: 3G auth data is not of type 'UMTS'%s", 
VTY_NEWLINE);
-               aud3g = (struct osmo_sub_auth_data){};
+               aud3g = (struct osmo_sub_auth_data2){};
        }

        if (aud2g.algo != OSMO_AUTH_ALG_NONE && aud2g.type != 
OSMO_AUTH_TYPE_NONE) {
@@ -154,9 +154,10 @@

        if (aud3g.algo != OSMO_AUTH_ALG_NONE && aud3g.type != 
OSMO_AUTH_TYPE_NONE) {
                vty_out(vty, "    3G auth: %s%s", 
osmo_auth_alg_name(aud3g.algo), VTY_NEWLINE);
-               vty_out(vty, "             K=%s%s", 
hexdump_buf(aud3g.u.umts.k), VTY_NEWLINE);
+               vty_out(vty, "             K=%s%s",
+                       osmo_hexdump_nospc(aud3g.u.umts.k, aud3g.u.umts.k_len), 
VTY_NEWLINE);
                vty_out(vty, "             %s=%s%s", aud3g.u.umts.opc_is_op? 
"OP" : "OPC",
-                       hexdump_buf(aud3g.u.umts.opc), VTY_NEWLINE);
+                       osmo_hexdump_nospc(aud3g.u.umts.opc, 
aud3g.u.umts.opc_len), VTY_NEWLINE);
                vty_out(vty, "             IND-bitlen=%u", 
aud3g.u.umts.ind_bitlen);
                if (aud3g.u.umts.sqn)
                        vty_out(vty, " last-SQN=%"PRIu64, aud3g.u.umts.sqn);
diff --git a/tests/auc/auc_test.c b/tests/auc/auc_test.c
index f39a5ad..5906720 100644
--- a/tests/auc/auc_test.c
+++ b/tests/auc/auc_test.c
@@ -116,14 +116,14 @@
 /* Subscriber with 2G-only (COMP128v1) authentication data */
 static void test_gen_vectors_2g_only(void)
 {
-       struct osmo_sub_auth_data aud2g;
-       struct osmo_sub_auth_data aud3g;
+       struct osmo_sub_auth_data2 aud2g;
+       struct osmo_sub_auth_data2 aud3g;
        struct osmo_auth_vector vec;
        int rc;

        comment_start();

-       aud2g = (struct osmo_sub_auth_data){
+       aud2g = (struct osmo_sub_auth_data2){
                .type = OSMO_AUTH_TYPE_GSM,
                .algo = OSMO_AUTH_ALG_COMP128v1,
        };
@@ -131,7 +131,7 @@
        osmo_hexparse("EB215756028D60E3275E613320AEC880",
                      aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));

-       aud3g = (struct osmo_sub_auth_data){ 0 };
+       aud3g = (struct osmo_sub_auth_data2){ 0 };

        next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);

@@ -179,14 +179,14 @@
  * reflects the default configuration of sysmoUSIM-SJS1 */
 static void test_gen_vectors_2g_plus_3g(void)
 {
-       struct osmo_sub_auth_data aud2g;
-       struct osmo_sub_auth_data aud3g;
+       struct osmo_sub_auth_data2 aud2g;
+       struct osmo_sub_auth_data2 aud3g;
        struct osmo_auth_vector vec;
        int rc;

        comment_start();

-       aud2g = (struct osmo_sub_auth_data){
+       aud2g = (struct osmo_sub_auth_data2){
                .type = OSMO_AUTH_TYPE_GSM,
                .algo = OSMO_AUTH_ALG_COMP128v1,
        };
@@ -194,9 +194,11 @@
        osmo_hexparse("EB215756028D60E3275E613320AEC880",
                      aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));

-       aud3g = (struct osmo_sub_auth_data){
+       aud3g = (struct osmo_sub_auth_data2){
                .type = OSMO_AUTH_TYPE_UMTS,
                .algo = OSMO_AUTH_ALG_MILENAGE,
+               .u.umts.k_len = 16,
+               .u.umts.opc_len = 16,
                .u.umts.sqn = 31,
        };

@@ -292,8 +294,8 @@
  * tuples are suitable for both 2G and 3G authentication */
 static void test_gen_vectors_3g_only(void)
 {
-       struct osmo_sub_auth_data aud2g;
-       struct osmo_sub_auth_data aud3g;
+       struct osmo_sub_auth_data2 aud2g;
+       struct osmo_sub_auth_data2 aud3g;
        struct osmo_auth_vector vec;
        struct osmo_auth_vector vecs[3];
        uint8_t auts[14];
@@ -302,11 +304,13 @@

        comment_start();

-       aud2g = (struct osmo_sub_auth_data){ 0 };
+       aud2g = (struct osmo_sub_auth_data2){ 0 };

-       aud3g = (struct osmo_sub_auth_data){
+       aud3g = (struct osmo_sub_auth_data2){
                .type = OSMO_AUTH_TYPE_UMTS,
                .algo = OSMO_AUTH_ALG_MILENAGE,
+               .u.umts.k_len = 16,
+               .u.umts.opc_len = 16,
                .u.umts.sqn = 31,
        };

@@ -466,18 +470,20 @@
  * 2G and 3G authentication */
 static void test_gen_vectors_3g_xor(void)
 {
-       struct osmo_sub_auth_data aud2g;
-       struct osmo_sub_auth_data aud3g;
+       struct osmo_sub_auth_data2 aud2g;
+       struct osmo_sub_auth_data2 aud3g;
        struct osmo_auth_vector vec;
        int rc;

        comment_start();

-       aud2g = (struct osmo_sub_auth_data){ 0 };
+       aud2g = (struct osmo_sub_auth_data2){ 0 };

-       aud3g = (struct osmo_sub_auth_data){
+       aud3g = (struct osmo_sub_auth_data2){
                .type = OSMO_AUTH_TYPE_UMTS,
                .algo = OSMO_AUTH_ALG_XOR_3G,
+               .u.umts.k_len = 16,
+               .u.umts.opc_len = 16,
                .u.umts.sqn = 0,
        };

@@ -517,39 +523,43 @@
        int rc;
        int i;

-       struct osmo_sub_auth_data aud2g = {
+       struct osmo_sub_auth_data2 aud2g = {
                .type = OSMO_AUTH_TYPE_GSM,
                .algo = OSMO_AUTH_ALG_COMP128v1,
        };

-       struct osmo_sub_auth_data aud3g = {
+       struct osmo_sub_auth_data2 aud3g = {
                .type = OSMO_AUTH_TYPE_UMTS,
                .algo = OSMO_AUTH_ALG_MILENAGE,
+               .u.umts.k_len = 16,
+               .u.umts.opc_len = 16,
        };

-       struct osmo_sub_auth_data aud2g_noalg = {
+       struct osmo_sub_auth_data2 aud2g_noalg = {
                .type = OSMO_AUTH_TYPE_GSM,
                .algo = OSMO_AUTH_ALG_NONE,
        };

-       struct osmo_sub_auth_data aud3g_noalg = {
+       struct osmo_sub_auth_data2 aud3g_noalg = {
                .type = OSMO_AUTH_TYPE_UMTS,
                .algo = OSMO_AUTH_ALG_NONE,
+               .u.umts.k_len = 16,
+               .u.umts.opc_len = 16,
        };

-       struct osmo_sub_auth_data aud_notype = {
+       struct osmo_sub_auth_data2 aud_notype = {
                .type = OSMO_AUTH_TYPE_NONE,
                .algo = OSMO_AUTH_ALG_MILENAGE,
        };

-       struct osmo_sub_auth_data no_aud = {
+       struct osmo_sub_auth_data2 no_aud = {
                .type = OSMO_AUTH_TYPE_NONE,
                .algo = OSMO_AUTH_ALG_NONE,
        };

        struct {
-               struct osmo_sub_auth_data *aud2g;
-               struct osmo_sub_auth_data *aud3g;
+               struct osmo_sub_auth_data2 *aud2g;
+               struct osmo_sub_auth_data2 *aud3g;
                uint8_t *rand_auts;
                uint8_t *auts;
                const char *label;
diff --git a/tests/auc/gen_ts_55_205_test_sets/func_template.c 
b/tests/auc/gen_ts_55_205_test_sets/func_template.c
index c244dd8..f8b4097 100644
--- a/tests/auc/gen_ts_55_205_test_sets/func_template.c
+++ b/tests/auc/gen_ts_55_205_test_sets/func_template.c
@@ -24,18 +24,20 @@

 static void {func_name}(void)
 {{
-       struct osmo_sub_auth_data aud2g;
-       struct osmo_sub_auth_data aud3g;
+       struct osmo_sub_auth_data2 aud2g;
+       struct osmo_sub_auth_data2 aud3g;
        struct osmo_auth_vector vec;
        int rc;

        comment_start();

-       aud2g = (struct osmo_sub_auth_data){{ 0 }};
+       aud2g = (struct osmo_sub_auth_data2){{ 0 }};
 
-       aud3g = (struct osmo_sub_auth_data){{
+       aud3g = (struct osmo_sub_auth_data2){{
                .type = OSMO_AUTH_TYPE_UMTS,
                .algo = OSMO_AUTH_ALG_MILENAGE,
+               .u.umts.k_len = 16,
+               .u.umts.opc_len = 16,
                .u.umts.sqn = 31,
        }};

@@ -48,6 +50,7 @@
                      fake_rand, sizeof(fake_rand));

        vec = (struct osmo_auth_vector){{ {{0}} }};
+       vec.res_len = 8;
        VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64);
        rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
        VERBOSE_ASSERT(rc, == 1, "%d");
diff --git a/tests/db/db_test.c b/tests/db/db_test.c
index 6727812..bdf1393 100644
--- a/tests/db/db_test.c
+++ b/tests/db/db_test.c
@@ -122,16 +122,16 @@
 /* Not linking the real auc_compute_vectors(), just returning num_vec.
  * This gets called by db_get_auc(), but we're only interested in its rc. */
 int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
-                       struct osmo_sub_auth_data *aud2g,
-                       struct osmo_sub_auth_data *aud3g,
+                       struct osmo_sub_auth_data2 *aud2g,
+                       struct osmo_sub_auth_data2 *aud3g,
                        const uint8_t *rand_auts, const uint8_t *auts)
 { return num_vec; }

 static struct db_context *dbc = NULL;
 static void *ctx = NULL;
 static struct hlr_subscriber g_subscr;
-static struct osmo_sub_auth_data g_aud2g;
-static struct osmo_sub_auth_data g_aud3g;
+static struct osmo_sub_auth_data2 g_aud2g;
+static struct osmo_sub_auth_data2 g_aud3g;
 static int g_rc;
 static int64_t g_id;

@@ -180,18 +180,21 @@
 #undef Pb
 }

-void dump_aud(const char *label, struct osmo_sub_auth_data *aud)
+void dump_aud(const char *label, struct osmo_sub_auth_data2 *aud)
 {
        if (aud->type == OSMO_AUTH_TYPE_NONE) {
                fprintf(stderr, "%s: none\n", label);
                return;
        }

-       fprintf(stderr, "%s: struct osmo_sub_auth_data {\n", label);
+       fprintf(stderr, "%s: struct osmo_sub_auth_data2 {\n", label);
 #define Pf(name, fmt) \
        Pfo(name, fmt, aud)
 #define Phex(name) \
        Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, sizeof(aud->name)))
+#define Phexl(name, len) \
+       Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, aud->len))
+

        Pfv(type, "%s", osmo_sub_auth_type_name(aud->type));
        Pfv(algo, "%s", osmo_auth_alg_name(aud->algo));
@@ -200,9 +203,9 @@
                Phex(u.gsm.ki);
                break;
        case OSMO_AUTH_TYPE_UMTS:
-               Phex(u.umts.opc);
+               Phexl(u.umts.opc, u.umts.opc_len);
                Pf(u.umts.opc_is_op, "%u");
-               Phex(u.umts.k);
+               Phexl(u.umts.k, u.umts.k_len);
                Phex(u.umts.amf);
                if (aud->u.umts.sqn) {
                        Pf(u.umts.sqn, "%"PRIu64);
@@ -219,6 +222,7 @@

 #undef Pf
 #undef Phex
+#undef Phexl
 }

 void db_raw_sql(struct db_context *dbc, const char *sql)
diff --git a/tests/db/db_test.err b/tests/db/db_test.err
index 222d3a1..dee85e0 100644
--- a/tests/db/db_test.err
+++ b/tests/db/db_test.err
@@ -824,7 +824,7 @@
 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
 DAUC IMSI='123456789000000': No 3G Auth Data

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v1,
   .u.gsm.ki = '0123456789abcdef0123456789abcdef',
@@ -841,7 +841,7 @@
 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
 DAUC IMSI='123456789000000': No 3G Auth Data

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v1,
   .u.gsm.ki = '0123456789abcdef0123456789abcdef',
@@ -853,7 +853,7 @@
 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
 DAUC IMSI='123456789000000': No 3G Auth Data

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v2,
   .u.gsm.ki = 'beadedbeeaced1ebbeddefacedfacade',
@@ -865,7 +865,7 @@
 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
 DAUC IMSI='123456789000000': No 3G Auth Data

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v3,
   .u.gsm.ki = 'deafbeddedbabeacceededfadeddecaf',
@@ -877,7 +877,7 @@
 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
 DAUC IMSI='123456789000000': No 3G Auth Data

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = XOR-2G,
   .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
@@ -905,7 +905,7 @@
 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
 DAUC IMSI='123456789000000': No 3G Auth Data

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = XOR-2G,
   .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
@@ -932,7 +932,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -954,7 +954,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -970,7 +970,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'deaf0ff1ced0d0dabbedd1ced1cef00d',
@@ -985,7 +985,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1001,7 +1001,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'cededeffacedacefacedbadfadedbeef',
@@ -1033,7 +1033,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'cededeffacedacefacedbadfadedbeef',
@@ -1069,12 +1069,12 @@

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v3,
   .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
 }
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1097,12 +1097,12 @@

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v3,
   .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
 }
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1117,12 +1117,12 @@

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v3,
   .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
 }
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1137,12 +1137,12 @@

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v3,
   .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
 }
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1157,12 +1157,12 @@

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v3,
   .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
 }
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1177,12 +1177,12 @@

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v3,
   .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
 }
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1197,12 +1197,12 @@

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v3,
   .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
 }
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1217,12 +1217,12 @@

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v3,
   .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
 }
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1237,12 +1237,12 @@

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v3,
   .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
 }
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1257,12 +1257,12 @@

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0

-2G: struct osmo_sub_auth_data {
+2G: struct osmo_sub_auth_data2 {
   .type = GSM,
   .algo = COMP128v3,
   .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
 }
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1338,7 +1338,7 @@
 sqlite3_step(stmt) --> SQLITE_DONE

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -ENOKEY
-DAUC IMSI='123456789000000': Error reading Ki, expected length 16 but has 
length 15
+DAUC IMSI='123456789000000': Error reading Ki, expected min length 16 but has 
length 15
 DAUC IMSI='123456789000000': No 3G Auth Data


@@ -1359,7 +1359,7 @@

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
 DAUC IMSI='123456789000000': No 2G Auth Data
-DAUC IMSI='123456789000000': Error reading K, expected length 16 but has 
length 15
+DAUC IMSI='123456789000000': Error reading K, expected min length 16 but has 
length 15



@@ -1374,7 +1374,7 @@

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
 DAUC IMSI='123456789000000': No 2G Auth Data
-DAUC IMSI='123456789000000': Error reading OP, expected length 16 but has 
length 15
+DAUC IMSI='123456789000000': Error reading OP, expected min length 16 but has 
length 15



@@ -1389,7 +1389,7 @@

 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
 DAUC IMSI='123456789000000': No 2G Auth Data
-DAUC IMSI='123456789000000': Error reading OPC, expected length 16 but has 
length 15
+DAUC IMSI='123456789000000': Error reading OPC, expected min length 16 but has 
length 15



@@ -1458,7 +1458,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1477,7 +1477,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1495,7 +1495,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1513,7 +1513,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1534,7 +1534,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1550,7 +1550,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1568,7 +1568,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1586,7 +1586,7 @@
 DAUC IMSI='123456789000000': No 2G Auth Data

 2G: none
-3G: struct osmo_sub_auth_data {
+3G: struct osmo_sub_auth_data2 {
   .type = UMTS,
   .algo = MILENAGE,
   .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',

--
To view, visit https://gerrit.osmocom.org/c/osmo-hlr/+/33097
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-hlr
Gerrit-Branch: master
Gerrit-Change-Id: I3207c7bfb73e9ff5471e5c26b66639549e4d48a2
Gerrit-Change-Number: 33097
Gerrit-PatchSet: 3
Gerrit-Owner: laforge <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <[email protected]>
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: neels <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>
Gerrit-MessageType: merged

Reply via email to