libosmocore/src/sim/core.c

173 lines
3.6 KiB
C

#include <stdlib.h>
#include <stdint.h>
#include <osmocom/core/talloc.h>
#include <osmocom/sim/sim.h>
static struct osim_decoded_element *
__element_alloc(void *ctx, const char *name, enum osim_element_type type,
enum osim_element_repr repr)
{
struct osim_decoded_element *elem;
elem = talloc_zero(ctx, struct osim_decoded_element);
if (!elem)
return NULL;
elem->name = name;
elem->type = type;
elem->representation = repr;
if (elem->type == ELEM_T_GROUP)
INIT_LLIST_HEAD(&elem->u.siblings);
return elem;
}
struct osim_decoded_element *
element_alloc(struct osim_decoded_data *dd, const char *name,
enum osim_element_type type, enum osim_element_repr repr)
{
struct osim_decoded_element *elem;
elem = __element_alloc(dd, name, type, repr);
if (!elem)
return NULL;
llist_add_tail(&elem->list, &dd->decoded_elements);
return elem;
}
struct osim_decoded_element *
element_alloc_sub(struct osim_decoded_element *ee, const char *name,
enum osim_element_type type, enum osim_element_repr repr)
{
struct osim_decoded_element *elem;
elem = __element_alloc(ee, name, type, repr);
if (!elem)
return NULL;
llist_add(&elem->list, &ee->u.siblings);
return elem;
}
void add_filedesc(struct osim_file_desc *root, const struct osim_file_desc *in, int num)
{
int i;
for (i = 0; i < num; i++) {
struct osim_file_desc *ofd = talloc_memdup(root, &in[i], sizeof(*in));
llist_add_tail(&ofd->list, &root->child_list);
}
}
struct osim_file_desc *alloc_df(void *ctx, uint16_t fid, const char *name)
{
struct osim_file_desc *mf;
mf = talloc_zero(ctx, struct osim_file_desc);
mf->type = TYPE_DF;
mf->fid = fid;
mf->short_name = name;
INIT_LLIST_HEAD(&mf->child_list);
return mf;
}
struct osim_file_desc *
add_df_with_ef(struct osim_file_desc *parent,
uint16_t fid, const char *name,
const struct osim_file_desc *in, int num)
{
struct osim_file_desc *df;
df = alloc_df(parent, fid, name);
df->parent = parent;
llist_add_tail(&df->list, &parent->child_list);
add_filedesc(df, in, num);
return df;
}
struct osim_file_desc *
add_adf_with_ef(struct osim_file_desc *parent,
const uint8_t *adf_name, uint8_t adf_name_len,
const char *name, const struct osim_file_desc *in,
int num)
{
struct osim_file_desc *df;
df = alloc_df(parent, 0xffff, name);
df->type = TYPE_ADF;
df->df_name = adf_name;
df->df_name_len = adf_name_len;
df->parent = parent;
llist_add_tail(&df->list, &parent->child_list);
add_filedesc(df, in, num);
return df;
}
struct osim_file_desc *
osim_file_find_name(struct osim_file_desc *parent, const char *name)
{
struct osim_file_desc *ofd;
llist_for_each_entry(ofd, &parent->child_list, list) {
if (!strcmp(ofd->short_name, name)) {
return ofd;
}
}
return NULL;
}
struct msgb *osim_new_apdumsg(uint8_t cla, uint8_t ins, uint8_t p1,
uint8_t p2, uint16_t lc, uint16_t le)
{
struct osim_apdu_cmd_hdr *ch;
struct msgb *msg = msgb_alloc(lc+le+sizeof(*ch)+2, "APDU");
if (!msg)
return NULL;
ch = (struct osim_apdu_cmd_hdr *) msgb_put(msg, sizeof(*ch));
msg->l2h = (char *) ch;
ch->cla = cla;
ch->ins = ins;
ch->p1 = p1;
ch->p2 = p2;
msgb_apdu_lc(msg) = lc;
msgb_apdu_le(msg) = le;
if (lc == 0 && le == 0)
msgb_apdu_case(msg) = APDU_CASE_1;
else if (lc == 0 && le >= 1) {
if (le <= 256)
msgb_apdu_case(msg) = APDU_CASE_2;
else
msgb_apdu_case(msg) = APDU_CASE_2_EXT;
} else if (le == 0 && lc >= 1) {
if (lc <= 255)
msgb_apdu_case(msg) = APDU_CASE_3;
else
msgb_apdu_case(msg) = APDU_CASE_3_EXT;
} else if (lc >= 1 && le >= 1) {
if (lc <= 255 & le <= 256)
msgb_apdu_case(msg) = APDU_CASE_4;
else
msgb_apdu_case(msg) = APDU_CASE_4_EXT;
}
return msg;
}