osmo-hlr/src/gsupclient/cni_peer_id.c

194 lines
4.9 KiB
C

/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <string.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsupclient/cni_peer_id.h>
bool osmo_ipa_name_is_empty(const struct osmo_ipa_name *ipa_name)
{
return (!ipa_name) || (!ipa_name->len);
}
int osmo_ipa_name_set(struct osmo_ipa_name *ipa_name, const uint8_t *val, size_t len)
{
if (!val || !len) {
*ipa_name = (struct osmo_ipa_name){};
return 0;
}
if (len > sizeof(ipa_name->val))
return -ENOSPC;
ipa_name->len = len;
memcpy(ipa_name->val, val, len);
return 0;
}
static int osmo_ipa_name_set_str_va(struct osmo_ipa_name *ipa_name, const char *str_fmt, va_list ap)
{
if (!str_fmt)
return osmo_ipa_name_set(ipa_name, NULL, 0);
vsnprintf((char*)(ipa_name->val), sizeof(ipa_name->val), str_fmt, ap);
ipa_name->len = strlen((char*)(ipa_name->val))+1;
return 0;
}
int osmo_ipa_name_set_str(struct osmo_ipa_name *ipa_name, const char *str_fmt, ...)
{
va_list ap;
int rc;
va_start(ap, str_fmt);
rc = osmo_ipa_name_set_str_va(ipa_name, str_fmt, ap);
va_end(ap);
return rc;
}
int osmo_ipa_name_cmp(const struct osmo_ipa_name *a, const struct osmo_ipa_name *b)
{
int cmp;
if (a == b)
return 0;
if (!a)
return -1;
if (!b)
return 1;
if (!a->len && !b->len)
return 0;
if (!a->len && b->len)
return -1;
if (!b->len && a->len)
return 1;
if (a->len == b->len)
return memcmp(a->val, b->val, a->len);
else if (a->len < b->len) {
cmp = memcmp(a->val, b->val, a->len);
if (!cmp)
cmp = -1;
return cmp;
} else {
/* a->len > b->len */
cmp = memcmp(a->val, b->val, b->len);
if (!cmp)
cmp = 1;
return cmp;
}
}
/* Call osmo_ipa_name_to_str_c with OTC_SELECT. */
const char *osmo_ipa_name_to_str(const struct osmo_ipa_name *ipa_name)
{
return osmo_ipa_name_to_str_c(OTC_SELECT, ipa_name);
}
/* Return an unquoted string, not including the terminating zero. Used for writing VTY config. */
const char *osmo_ipa_name_to_str_c(void *ctx, const struct osmo_ipa_name *ipa_name)
{
size_t len = ipa_name->len;
if (!len)
return talloc_strdup(ctx, "");
if (ipa_name->val[len-1] == '\0')
len--;
return osmo_escape_str_c(ctx, (char*)ipa_name->val, len);
}
bool osmo_cni_peer_id_is_empty(const struct osmo_cni_peer_id *cni_peer_id)
{
if (!cni_peer_id)
return true;
switch (cni_peer_id->type) {
case OSMO_CNI_PEER_ID_EMPTY:
return true;
case OSMO_CNI_PEER_ID_IPA_NAME:
return osmo_ipa_name_is_empty(&cni_peer_id->ipa_name);
default:
return false;
}
}
int osmo_cni_peer_id_set(struct osmo_cni_peer_id *cni_peer_id, enum osmo_cni_peer_id_type type,
const uint8_t *val, size_t len)
{
cni_peer_id->type = type;
switch (type) {
case OSMO_CNI_PEER_ID_IPA_NAME:
return osmo_ipa_name_set(&cni_peer_id->ipa_name, val, len);
default:
return -EINVAL;
}
}
int osmo_cni_peer_id_set_str(struct osmo_cni_peer_id *cni_peer_id, enum osmo_cni_peer_id_type type,
const char *str_fmt, ...)
{
va_list ap;
int rc;
*cni_peer_id = (struct osmo_cni_peer_id){};
switch (type) {
case OSMO_CNI_PEER_ID_IPA_NAME:
cni_peer_id->type = OSMO_CNI_PEER_ID_IPA_NAME;
va_start(ap, str_fmt);
rc = osmo_ipa_name_set_str_va(&cni_peer_id->ipa_name, str_fmt, ap);
va_end(ap);
return rc;
default:
return -EINVAL;
}
}
int osmo_cni_peer_id_cmp(const struct osmo_cni_peer_id *a, const struct osmo_cni_peer_id *b)
{
if (a == b)
return 0;
if (!a)
return -1;
if (!b)
return 1;
if (a->type != b->type)
return OSMO_CMP(a->type, b->type);
switch (a->type) {
case OSMO_CNI_PEER_ID_IPA_NAME:
return osmo_ipa_name_cmp(&a->ipa_name, &b->ipa_name);
default:
return -EINVAL;
}
}
const struct value_string osmo_cni_peer_id_type_names[] = {
{ OSMO_CNI_PEER_ID_IPA_NAME, "IPA-name" },
{}
};
/* Call osmo_cni_peer_id_to_str_c with OTC_SELECT */
const char *osmo_cni_peer_id_to_str(const struct osmo_cni_peer_id *cpi)
{
return osmo_cni_peer_id_to_str_c(OTC_SELECT, cpi);
}
/* Return an unquoted string, not including the terminating zero. Used for writing VTY config. */
const char *osmo_cni_peer_id_to_str_c(void *ctx, const struct osmo_cni_peer_id *cpi)
{
switch (cpi->type) {
case OSMO_CNI_PEER_ID_IPA_NAME:
return osmo_ipa_name_to_str_c(ctx, &cpi->ipa_name);
default:
return talloc_strdup(ctx, osmo_cni_peer_id_type_name(cpi->type));
}
}