blob: c312e42cc4013e444f5bc59a54b8b16dd5446d23 [file] [log] [blame]
Harald Welte3aa901d2018-08-13 18:32:36 +02001
2
3#include <asn1c/asn_application.h>
4#include <asn1c/der_encoder.h>
5
6#include <osmocom/core/msgb.h>
7#include <osmocom/rspro/RsproPDU.h>
8
Harald Welte137c4402018-08-17 21:25:56 +02009#include "rspro_util.h"
10
Harald Welte57555aa2018-08-17 22:05:06 +020011#define ASN_ALLOC_COPY(out, in) \
12do { \
13 if (in) { \
14 out = CALLOC(1, sizeof(*in)); \
15 OSMO_ASSERT(out); \
16 memcpy(out, in, sizeof(*in)); \
17 } \
18} while (0)
19
20
Harald Welte3aa901d2018-08-13 18:32:36 +020021struct msgb *rspro_msgb_alloc(void)
22{
23 return msgb_alloc_headroom(1024, 8, "RSPRO");
24}
25
26/*! BER-Encode an RSPRO message into msgb.
27 * \param[in] pdu Structure describing RSPRO PDU. Is freed by this function on success
28 * \returns callee-allocated message buffer containing encoded RSPRO PDU; NULL on error.
29 */
30struct msgb *rspro_enc_msg(RsproPDU_t *pdu)
31{
32 struct msgb *msg = rspro_msgb_alloc();
33 asn_enc_rval_t rval;
34
35 if (!msg)
36 return NULL;
37
Harald Welte6b8d4f82018-08-17 22:06:24 +020038 rval = der_encode_to_buffer(&asn_DEF_RsproPDU, pdu, msgb_data(msg), msgb_tailroom(msg));
Harald Welte3aa901d2018-08-13 18:32:36 +020039 if (rval.encoded < 0) {
Harald Weltea2b23c32018-08-17 22:09:06 +020040 fprintf(stderr, "Failed to encode %s\n", rval.failed_type->name);
Harald Welte3aa901d2018-08-13 18:32:36 +020041 return NULL;
42 }
Harald Welted5c5c0b2018-08-17 22:04:01 +020043 msgb_put(msg, rval.encoded);
Harald Welte3aa901d2018-08-13 18:32:36 +020044
45 ASN_STRUCT_FREE(asn_DEF_RsproPDU, pdu);
46
47 return msg;
48}
49
50/* consumes 'msg' _if_ it is successful */
51RsproPDU_t *rspro_dec_msg(struct msgb *msg)
52{
53 RsproPDU_t *pdu;
54 asn_dec_rval_t rval;
55
56 rval = ber_decode(NULL, &asn_DEF_RsproPDU, (void **) &pdu, msgb_data(msg), msgb_length(msg));
57 if (rval.code != RC_OK) {
58 /* FIXME */
59 return NULL;
60 }
61
62 msgb_free(msg);
63
64 return pdu;
65}
66
Harald Welte3aa901d2018-08-13 18:32:36 +020067static void fill_comp_id(ComponentIdentity_t *out, const struct app_comp_id *in)
68{
Harald Welte137c4402018-08-17 21:25:56 +020069 out->type = in->type;
Harald Welte3aa901d2018-08-13 18:32:36 +020070 OCTET_STRING_fromString(&out->name, in->name);
71 OCTET_STRING_fromString(&out->software, in->software);
72 OCTET_STRING_fromString(&out->swVersion, in->sw_version);
73 if (strlen(in->hw_manufacturer))
74 out->hwManufacturer = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName,
75 in->hw_manufacturer, -1);
76 if (strlen(in->hw_model))
77 out->hwModel = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->hw_model, -1);
78 if (strlen(in->hw_serial_nr))
79 out->hwSerialNr = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->hw_serial_nr, -1);
80 if (strlen(in->hw_version))
81 out->hwVersion = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->hw_version, -1);
82 if (strlen(in->fw_version))
83 out->fwVersion = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->fw_version, -1);
84}
85
86static void fill_ip4_port(IpPort_t *out, uint32_t ip, uint16_t port)
87{
88 uint32_t ip_n = htonl(ip);
89 out->ip.present = IpAddress_PR_ipv4;
90 OCTET_STRING_fromBuf(&out->ip.choice.ipv4, (const char *) &ip_n, 4);
91 out->port = htons(port);
92}
93
94
95RsproPDU_t *rspro_gen_ConnectBankReq(const struct app_comp_id *a_cid,
96 uint16_t bank_id, uint16_t num_slots)
97{
98 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
99 if (!pdu)
100 return NULL;
101 pdu->msg.present = RsproPDUchoice_PR_connectBankReq;
102 fill_comp_id(&pdu->msg.choice.connectBankReq.identity, a_cid);
103 pdu->msg.choice.connectBankReq.bankId = bank_id;
104 pdu->msg.choice.connectBankReq.numberOfSlots = num_slots;
105
106 return pdu;
107}
108
Harald Welte57555aa2018-08-17 22:05:06 +0200109RsproPDU_t *rspro_gen_ConnectClientReq(const struct app_comp_id *a_cid, const ClientSlot_t *client)
Harald Welte3aa901d2018-08-13 18:32:36 +0200110{
111 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
112 if (!pdu)
113 return NULL;
114 pdu->msg.present = RsproPDUchoice_PR_connectClientReq;
115 fill_comp_id(&pdu->msg.choice.connectClientReq.identity, a_cid);
Harald Welte57555aa2018-08-17 22:05:06 +0200116 ASN_ALLOC_COPY(pdu->msg.choice.connectClientReq.clientSlot, client);
Harald Welte3aa901d2018-08-13 18:32:36 +0200117
118 return pdu;
119}
120
121RsproPDU_t *rspro_gen_CreateMappingReq(const ClientSlot_t *client, const BankSlot_t *bank)
122{
123 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
124 if (!pdu)
125 return NULL;
126 pdu->msg.present = RsproPDUchoice_PR_createMappingReq;
127 pdu->msg.choice.createMappingReq.client = *client;
128 pdu->msg.choice.createMappingReq.bank = *bank;
129
130 return pdu;
131}
132
Harald Welte371d0262018-08-16 15:23:58 +0200133RsproPDU_t *rspro_gen_ConfigClientReq(const ClientSlot_t *client, uint32_t ip, uint16_t port)
Harald Welte3aa901d2018-08-13 18:32:36 +0200134{
135 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
136 if (!pdu)
137 return NULL;
138 pdu->msg.present = RsproPDUchoice_PR_configClientReq;
Harald Welte371d0262018-08-16 15:23:58 +0200139 pdu->msg.choice.configClientReq.clientSlot = *client;
Harald Welte3aa901d2018-08-13 18:32:36 +0200140 fill_ip4_port(&pdu->msg.choice.configClientReq.bankd, ip, port);
141
142 return pdu;
143}
144
145RsproPDU_t *rspro_gen_SetAtrReq(uint16_t client_id, uint16_t slot_nr, const uint8_t *atr,
146 unsigned int atr_len)
147{
148 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
149 if (!pdu)
150 return NULL;
151 pdu->msg.present = RsproPDUchoice_PR_setAtrReq;
152 pdu->msg.choice.setAtrReq.slot.clientId = client_id;
153 pdu->msg.choice.setAtrReq.slot.slotNr = slot_nr;
154 OCTET_STRING_fromBuf(&pdu->msg.choice.setAtrReq.atr, (const char *)atr, atr_len);
155
156 return pdu;
157}