blob: db36aab920fcd20cd1ea962150d0180e34505239 [file] [log] [blame]
Harald Welte1200c822020-02-13 20:43:27 +01001#include <errno.h>
2#include <unistd.h>
3
4#include <osmocom/core/select.h>
5
6#include "client.h"
7
8/* This is a remsim-client with an interactive 'shell', where the user
9 * can type in C-APDUs in hex formats, which will be sent to the bankd /
10 * SIM-card. Responses received from SIM Card via bankd will be printed
11 * in return. */
12
13
14/***********************************************************************
15 * Incoming RSPRO messages from bank-daemon (SIM card)
16 ***********************************************************************/
17
18static int bankd_handle_tpduCardToModem(struct bankd_client *bc, const RsproPDU_t *pdu)
19{
20 OSMO_ASSERT(pdu);
21 OSMO_ASSERT(RsproPDUchoice_PR_tpduCardToModem == pdu->msg.present);
22
23 const struct TpduCardToModem *card2modem = &pdu->msg.choice.tpduCardToModem;
24
25 printf("R-APDU: %s\n", osmo_hexdump(card2modem->data.buf, card2modem->data.size));
26
27 return 0;
28}
29
30static int bankd_handle_setAtrReq(struct bankd_client *bc, const RsproPDU_t *pdu)
31{
32 RsproPDU_t *resp;
33
34 OSMO_ASSERT(pdu);
35 OSMO_ASSERT(RsproPDUchoice_PR_setAtrReq == pdu->msg.present);
36
37 printf("SET_ATR: %s\n", osmo_hexdump(pdu->msg.choice.setAtrReq.atr.buf,
38 pdu->msg.choice.setAtrReq.atr.size));
39
40 resp = rspro_gen_SetAtrRes(ResultCode_ok);
41 if (!resp)
42 return -ENOMEM;
43 server_conn_send_rspro(&bc->bankd_conn, resp);
44
45 return 0;
46}
47
48
49int client_user_bankd_handle_rx(struct rspro_server_conn *bankdc, const RsproPDU_t *pdu)
50{
51 switch (pdu->msg.present) {
52 case RsproPDUchoice_PR_tpduCardToModem:
53 bankd_handle_tpduCardToModem(g_client, pdu);
54 break;
55 case RsproPDUchoice_PR_setAtrReq:
56 bankd_handle_setAtrReq(g_client, pdu);
57 break;
58 default:
59 OSMO_ASSERT(0);
60 }
61 return 0;
62}
63
64/***********************************************************************
65 * Incoming command from the user application (stdin shell in our case)
66 ***********************************************************************/
67
68struct stdin_state {
69 struct osmo_fd ofd;
70 struct msgb *rx_msg;
71};
72
73/* called every time a command on stdin was received */
74static void handle_stdin_command(struct stdin_state *ss, char *cmd)
75{
76 RsproPDU_t *pdu;
77 BankSlot_t bslot;
78 uint8_t buf[1024];
79 int rc;
80
81 bank_slot2rspro(&bslot, &g_client->bankd_slot);
82
83 OSMO_ASSERT(ss->rx_msg);
84
85 printf("stdin: `%s'\n", cmd);
86
87 if (!strcasecmp(cmd, "RESET")) {
88 /* reset the [remote] card */
89 pdu = rspro_gen_ClientSlotStatusInd(g_client->srv_conn.clslot, &bslot,
90 true, false, false, true);
91 server_conn_send_rspro(&g_client->bankd_conn, pdu);
92 } else {
93 /* we assume the user has entered a C-APDU as hex string. parse + send */
94 rc = osmo_hexparse(cmd, buf, sizeof(buf));
95 if (rc < 0) {
96 fprintf(stderr, "ERROR parsing C-APDU `%s'!\n", cmd);
97 return;
98 }
99 if (!g_client->srv_conn.clslot) {
100 fprintf(stderr, "Cannot send command; no client slot\n");
101 return;
102 }
103
104 /* Send CMD APDU to [remote] card */
105 pdu = rspro_gen_TpduModem2Card(g_client->srv_conn.clslot, &bslot, buf, rc);
106 server_conn_send_rspro(&g_client->bankd_conn, pdu);
107 }
108}
109
110/* call-back function for stdin read. Gather bytes in buffer until CR/LF received */
111static int stdin_fd_cb(struct osmo_fd *ofd, unsigned int what)
112{
113 struct stdin_state *ss = ofd->data;
114 char *cur;
115 int rc, i;
116
117 OSMO_ASSERT(what & OSMO_FD_READ);
118
119 if (!ss->rx_msg) {
120 ss->rx_msg = msgb_alloc(1024, "stdin");
121 OSMO_ASSERT(ss->rx_msg);
122 }
123
124 cur = (char *) ss->rx_msg->tail;
125 rc = read(ofd->fd, cur, msgb_tailroom(ss->rx_msg));
126 if (rc < 0)
127 return rc;
128 msgb_put(ss->rx_msg, rc);
129
130 for (i = 0; i < rc; i++) {
131 if (cur[i] == '\r' || cur[i] == '\n') {
132 cur[i] = '\0';
133 /* dispatch the command */
134 handle_stdin_command(ss, cur);
135 /* FIXME: possibly other commands */
136 msgb_free(ss->rx_msg);
137 ss->rx_msg = NULL;
138 }
139 }
140
141 return 0;
142}
143
144
145
146/* main function */
147int client_user_main(struct bankd_client *g_client)
148{
149 struct stdin_state ss;
150
151 /* register stdin file descriptor with osmocom select loop abstraction */
152 memset(&ss, 0, sizeof(ss));
153 osmo_fd_setup(&ss.ofd, fileno(stdin), OSMO_FD_READ, &stdin_fd_cb, &ss, 0);
154 osmo_fd_register(&ss.ofd);
155
156 while (1) {
157 osmo_select_main(0);
158 }
159}