blob: 1db5ceb84dc559888aee64103ecbf3f5201b5fa8 [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 Welte3aa901d2018-08-13 18:32:36 +020011struct msgb *rspro_msgb_alloc(void)
12{
13 return msgb_alloc_headroom(1024, 8, "RSPRO");
14}
15
16/*! BER-Encode an RSPRO message into msgb.
17 * \param[in] pdu Structure describing RSPRO PDU. Is freed by this function on success
18 * \returns callee-allocated message buffer containing encoded RSPRO PDU; NULL on error.
19 */
20struct msgb *rspro_enc_msg(RsproPDU_t *pdu)
21{
22 struct msgb *msg = rspro_msgb_alloc();
23 asn_enc_rval_t rval;
24
25 if (!msg)
26 return NULL;
27
28 rval = der_encode_to_buffer(&asn_DEF_RsproPDU, pdu, msgb_data(msg), msgb_length(msg));
29 if (rval.encoded < 0) {
30 return NULL;
31 }
32 msgb_put(msg, rval.encoded/8);
33
34 ASN_STRUCT_FREE(asn_DEF_RsproPDU, pdu);
35
36 return msg;
37}
38
39/* consumes 'msg' _if_ it is successful */
40RsproPDU_t *rspro_dec_msg(struct msgb *msg)
41{
42 RsproPDU_t *pdu;
43 asn_dec_rval_t rval;
44
45 rval = ber_decode(NULL, &asn_DEF_RsproPDU, (void **) &pdu, msgb_data(msg), msgb_length(msg));
46 if (rval.code != RC_OK) {
47 /* FIXME */
48 return NULL;
49 }
50
51 msgb_free(msg);
52
53 return pdu;
54}
55
Harald Welte3aa901d2018-08-13 18:32:36 +020056static void fill_comp_id(ComponentIdentity_t *out, const struct app_comp_id *in)
57{
Harald Welte137c4402018-08-17 21:25:56 +020058 out->type = in->type;
Harald Welte3aa901d2018-08-13 18:32:36 +020059 OCTET_STRING_fromString(&out->name, in->name);
60 OCTET_STRING_fromString(&out->software, in->software);
61 OCTET_STRING_fromString(&out->swVersion, in->sw_version);
62 if (strlen(in->hw_manufacturer))
63 out->hwManufacturer = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName,
64 in->hw_manufacturer, -1);
65 if (strlen(in->hw_model))
66 out->hwModel = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->hw_model, -1);
67 if (strlen(in->hw_serial_nr))
68 out->hwSerialNr = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->hw_serial_nr, -1);
69 if (strlen(in->hw_version))
70 out->hwVersion = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->hw_version, -1);
71 if (strlen(in->fw_version))
72 out->fwVersion = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->fw_version, -1);
73}
74
75static void fill_ip4_port(IpPort_t *out, uint32_t ip, uint16_t port)
76{
77 uint32_t ip_n = htonl(ip);
78 out->ip.present = IpAddress_PR_ipv4;
79 OCTET_STRING_fromBuf(&out->ip.choice.ipv4, (const char *) &ip_n, 4);
80 out->port = htons(port);
81}
82
83
84RsproPDU_t *rspro_gen_ConnectBankReq(const struct app_comp_id *a_cid,
85 uint16_t bank_id, uint16_t num_slots)
86{
87 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
88 if (!pdu)
89 return NULL;
90 pdu->msg.present = RsproPDUchoice_PR_connectBankReq;
91 fill_comp_id(&pdu->msg.choice.connectBankReq.identity, a_cid);
92 pdu->msg.choice.connectBankReq.bankId = bank_id;
93 pdu->msg.choice.connectBankReq.numberOfSlots = num_slots;
94
95 return pdu;
96}
97
98RsproPDU_t *rspro_gen_ConnectClientReq(const struct app_comp_id *a_cid)
99{
100 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
101 if (!pdu)
102 return NULL;
103 pdu->msg.present = RsproPDUchoice_PR_connectClientReq;
104 fill_comp_id(&pdu->msg.choice.connectClientReq.identity, a_cid);
105
106 return pdu;
107}
108
109RsproPDU_t *rspro_gen_CreateMappingReq(const ClientSlot_t *client, const BankSlot_t *bank)
110{
111 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
112 if (!pdu)
113 return NULL;
114 pdu->msg.present = RsproPDUchoice_PR_createMappingReq;
115 pdu->msg.choice.createMappingReq.client = *client;
116 pdu->msg.choice.createMappingReq.bank = *bank;
117
118 return pdu;
119}
120
Harald Welte371d0262018-08-16 15:23:58 +0200121RsproPDU_t *rspro_gen_ConfigClientReq(const ClientSlot_t *client, uint32_t ip, uint16_t port)
Harald Welte3aa901d2018-08-13 18:32:36 +0200122{
123 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
124 if (!pdu)
125 return NULL;
126 pdu->msg.present = RsproPDUchoice_PR_configClientReq;
Harald Welte371d0262018-08-16 15:23:58 +0200127 pdu->msg.choice.configClientReq.clientSlot = *client;
Harald Welte3aa901d2018-08-13 18:32:36 +0200128 fill_ip4_port(&pdu->msg.choice.configClientReq.bankd, ip, port);
129
130 return pdu;
131}
132
133RsproPDU_t *rspro_gen_SetAtrReq(uint16_t client_id, uint16_t slot_nr, const uint8_t *atr,
134 unsigned int atr_len)
135{
136 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
137 if (!pdu)
138 return NULL;
139 pdu->msg.present = RsproPDUchoice_PR_setAtrReq;
140 pdu->msg.choice.setAtrReq.slot.clientId = client_id;
141 pdu->msg.choice.setAtrReq.slot.slotNr = slot_nr;
142 OCTET_STRING_fromBuf(&pdu->msg.choice.setAtrReq.atr, (const char *)atr, atr_len);
143
144 return pdu;
145}