blob: c8f45896374e2f86de09c4ae81338fad4736fcbd [file] [log] [blame]
Harald Welte3aa901d2018-08-13 18:32:36 +02001
2
Kévin Redonff5db6e2018-10-11 17:16:18 +02003#include <asn_application.h>
4#include <der_encoder.h>
Harald Welte3aa901d2018-08-13 18:32:36 +02005
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 Weltefd471192018-09-24 14:51:14 +020038 msg->l2h = msg->data;
Harald Welte6b8d4f82018-08-17 22:06:24 +020039 rval = der_encode_to_buffer(&asn_DEF_RsproPDU, pdu, msgb_data(msg), msgb_tailroom(msg));
Harald Welte3aa901d2018-08-13 18:32:36 +020040 if (rval.encoded < 0) {
Harald Weltea2b23c32018-08-17 22:09:06 +020041 fprintf(stderr, "Failed to encode %s\n", rval.failed_type->name);
Harald Welte703d6862018-09-24 17:44:50 +020042 msgb_free(msg);
Harald Welte3aa901d2018-08-13 18:32:36 +020043 return NULL;
44 }
Harald Welted5c5c0b2018-08-17 22:04:01 +020045 msgb_put(msg, rval.encoded);
Harald Welte3aa901d2018-08-13 18:32:36 +020046
47 ASN_STRUCT_FREE(asn_DEF_RsproPDU, pdu);
48
49 return msg;
50}
51
52/* consumes 'msg' _if_ it is successful */
53RsproPDU_t *rspro_dec_msg(struct msgb *msg)
54{
Harald Welte9ebbacc2018-09-24 17:43:39 +020055 RsproPDU_t *pdu = NULL;
Harald Welte3aa901d2018-08-13 18:32:36 +020056 asn_dec_rval_t rval;
57
Harald Welte75852862018-09-24 14:55:34 +020058 printf("decoding %s\n", msgb_hexdump(msg));
59 rval = ber_decode(NULL, &asn_DEF_RsproPDU, (void **) &pdu, msgb_l2(msg), msgb_l2len(msg));
Harald Welte3aa901d2018-08-13 18:32:36 +020060 if (rval.code != RC_OK) {
Harald Welte75852862018-09-24 14:55:34 +020061 fprintf(stderr, "Failed to decode: %d. Consumed %lu of %u bytes\n",
62 rval.code, rval.consumed, msgb_length(msg));
63 msgb_free(msg);
Harald Welte3aa901d2018-08-13 18:32:36 +020064 return NULL;
65 }
66
67 msgb_free(msg);
68
69 return pdu;
70}
71
Harald Welte3aa901d2018-08-13 18:32:36 +020072static void fill_comp_id(ComponentIdentity_t *out, const struct app_comp_id *in)
73{
Harald Welte137c4402018-08-17 21:25:56 +020074 out->type = in->type;
Harald Welte3aa901d2018-08-13 18:32:36 +020075 OCTET_STRING_fromString(&out->name, in->name);
76 OCTET_STRING_fromString(&out->software, in->software);
77 OCTET_STRING_fromString(&out->swVersion, in->sw_version);
78 if (strlen(in->hw_manufacturer))
79 out->hwManufacturer = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName,
80 in->hw_manufacturer, -1);
81 if (strlen(in->hw_model))
82 out->hwModel = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->hw_model, -1);
83 if (strlen(in->hw_serial_nr))
84 out->hwSerialNr = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->hw_serial_nr, -1);
85 if (strlen(in->hw_version))
86 out->hwVersion = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->hw_version, -1);
87 if (strlen(in->fw_version))
88 out->fwVersion = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->fw_version, -1);
89}
90
91static void fill_ip4_port(IpPort_t *out, uint32_t ip, uint16_t port)
92{
93 uint32_t ip_n = htonl(ip);
94 out->ip.present = IpAddress_PR_ipv4;
95 OCTET_STRING_fromBuf(&out->ip.choice.ipv4, (const char *) &ip_n, 4);
96 out->port = htons(port);
97}
98
99
100RsproPDU_t *rspro_gen_ConnectBankReq(const struct app_comp_id *a_cid,
101 uint16_t bank_id, uint16_t num_slots)
102{
103 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
104 if (!pdu)
105 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200106 pdu->version = 2;
Harald Welte3aa901d2018-08-13 18:32:36 +0200107 pdu->msg.present = RsproPDUchoice_PR_connectBankReq;
108 fill_comp_id(&pdu->msg.choice.connectBankReq.identity, a_cid);
109 pdu->msg.choice.connectBankReq.bankId = bank_id;
110 pdu->msg.choice.connectBankReq.numberOfSlots = num_slots;
111
112 return pdu;
113}
114
Harald Welte57555aa2018-08-17 22:05:06 +0200115RsproPDU_t *rspro_gen_ConnectClientReq(const struct app_comp_id *a_cid, const ClientSlot_t *client)
Harald Welte3aa901d2018-08-13 18:32:36 +0200116{
117 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
118 if (!pdu)
119 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200120 pdu->version = 2;
Harald Welte3aa901d2018-08-13 18:32:36 +0200121 pdu->msg.present = RsproPDUchoice_PR_connectClientReq;
122 fill_comp_id(&pdu->msg.choice.connectClientReq.identity, a_cid);
Harald Weltec3632a72018-10-14 20:38:34 +0200123 if (client)
124 ASN_ALLOC_COPY(pdu->msg.choice.connectClientReq.clientSlot, client);
Harald Welte3aa901d2018-08-13 18:32:36 +0200125
126 return pdu;
127}
128
Harald Welte10f6c212018-09-24 14:55:55 +0200129RsproPDU_t *rspro_gen_ConnectClientRes(const struct app_comp_id *a_cid, e_ResultCode res)
130{
131 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
132 if (!pdu)
133 return NULL;
134 pdu->version = 2;
135 pdu->tag = 2342;
136 pdu->msg.present = RsproPDUchoice_PR_connectClientRes;
137 fill_comp_id(&pdu->msg.choice.connectClientRes.identity, a_cid);
138 pdu->msg.choice.connectClientRes.result = res;
139
140 return pdu;
141}
142
Harald Welte3aa901d2018-08-13 18:32:36 +0200143RsproPDU_t *rspro_gen_CreateMappingReq(const ClientSlot_t *client, const BankSlot_t *bank)
144{
145 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
146 if (!pdu)
147 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200148 pdu->version = 2;
Harald Welte3aa901d2018-08-13 18:32:36 +0200149 pdu->msg.present = RsproPDUchoice_PR_createMappingReq;
150 pdu->msg.choice.createMappingReq.client = *client;
151 pdu->msg.choice.createMappingReq.bank = *bank;
152
153 return pdu;
154}
155
Harald Weltec0a4ae42018-10-15 00:44:53 +0200156RsproPDU_t *rspro_gen_CreateMappingRes(e_ResultCode res)
157{
158 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
159 if (!pdu)
160 return NULL;
161 pdu->version = 2;
162 pdu->msg.present = RsproPDUchoice_PR_createMappingRes;
163 pdu->msg.choice.createMappingRes.result = res;
164
165 return pdu;
166}
167
168RsproPDU_t *rspro_gen_RemoveMappingReq(const ClientSlot_t *client, const BankSlot_t *bank)
169{
170 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
171 if (!pdu)
172 return NULL;
173 pdu->version = 2;
174 pdu->msg.present = RsproPDUchoice_PR_removeMappingReq;
175 pdu->msg.choice.removeMappingReq.client = *client;
176 pdu->msg.choice.removeMappingReq.bank = *bank;
177
178 return pdu;
179}
180
181RsproPDU_t *rspro_gen_RemoveMappingRes(e_ResultCode res)
182{
183 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
184 if (!pdu)
185 return NULL;
186 pdu->version = 2;
187 pdu->msg.present = RsproPDUchoice_PR_removeMappingRes;
188 pdu->msg.choice.removeMappingRes.result = res;
189
190 return pdu;
191}
192
Harald Welte371d0262018-08-16 15:23:58 +0200193RsproPDU_t *rspro_gen_ConfigClientReq(const ClientSlot_t *client, uint32_t ip, uint16_t port)
Harald Welte3aa901d2018-08-13 18:32:36 +0200194{
195 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
196 if (!pdu)
197 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200198 pdu->version = 2;
Harald Welte3aa901d2018-08-13 18:32:36 +0200199 pdu->msg.present = RsproPDUchoice_PR_configClientReq;
Harald Welte371d0262018-08-16 15:23:58 +0200200 pdu->msg.choice.configClientReq.clientSlot = *client;
Harald Welte3aa901d2018-08-13 18:32:36 +0200201 fill_ip4_port(&pdu->msg.choice.configClientReq.bankd, ip, port);
202
203 return pdu;
204}
205
206RsproPDU_t *rspro_gen_SetAtrReq(uint16_t client_id, uint16_t slot_nr, const uint8_t *atr,
207 unsigned int atr_len)
208{
209 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
210 if (!pdu)
211 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200212 pdu->version = 2;
Harald Welte3aa901d2018-08-13 18:32:36 +0200213 pdu->msg.present = RsproPDUchoice_PR_setAtrReq;
214 pdu->msg.choice.setAtrReq.slot.clientId = client_id;
215 pdu->msg.choice.setAtrReq.slot.slotNr = slot_nr;
216 OCTET_STRING_fromBuf(&pdu->msg.choice.setAtrReq.atr, (const char *)atr, atr_len);
217
218 return pdu;
219}
Harald Welte5d16b1c2018-09-23 19:25:46 +0200220
221RsproPDU_t *rspro_gen_TpduModem2Card(const ClientSlot_t *client, const BankSlot_t *bank,
222 const uint8_t *tpdu, unsigned int tpdu_len)
223{
224 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
225 if (!pdu)
226 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200227 pdu->version = 2;
Harald Welte5d16b1c2018-09-23 19:25:46 +0200228 pdu->msg.present = RsproPDUchoice_PR_tpduModemToCard;
Kévin Redon6811e4f2018-10-11 08:37:38 +0200229 OSMO_ASSERT(client);
Harald Welte5d16b1c2018-09-23 19:25:46 +0200230 pdu->msg.choice.tpduModemToCard.fromClientSlot = *client;
Kévin Redon6811e4f2018-10-11 08:37:38 +0200231 OSMO_ASSERT(bank);
Harald Welte5d16b1c2018-09-23 19:25:46 +0200232 pdu->msg.choice.tpduModemToCard.toBankSlot = *bank;
233 /* TODO: flags? */
234 OCTET_STRING_fromBuf(&pdu->msg.choice.tpduModemToCard.data, (const char *)tpdu, tpdu_len);
235
236 return pdu;
237}
238
239RsproPDU_t *rspro_gen_TpduCard2Modem(const BankSlot_t *bank, const ClientSlot_t *client,
240 const uint8_t *tpdu, unsigned int tpdu_len)
241{
242 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
243 if (!pdu)
244 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200245 pdu->version = 2;
Harald Welte5d16b1c2018-09-23 19:25:46 +0200246 pdu->msg.present = RsproPDUchoice_PR_tpduCardToModem;
Kévin Redon6811e4f2018-10-11 08:37:38 +0200247 OSMO_ASSERT(bank);
Harald Welte5d16b1c2018-09-23 19:25:46 +0200248 pdu->msg.choice.tpduCardToModem.fromBankSlot = *bank;
Kévin Redon6811e4f2018-10-11 08:37:38 +0200249 OSMO_ASSERT(client)
Harald Welte5d16b1c2018-09-23 19:25:46 +0200250 pdu->msg.choice.tpduCardToModem.toClientSlot = *client;
251 /* TODO: flags? */
252 OCTET_STRING_fromBuf(&pdu->msg.choice.tpduCardToModem.data, (const char *)tpdu, tpdu_len);
253
254 return pdu;
255}