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