/* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2012 Tieto Poland * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "parser.h" #define PADDING4(x) ((4 - ((x) & 0x03)) & 0x03) #define SAP_CONNECT_REQ 0x00 #define SAP_CONNECT_RESP 0x01 #define SAP_DISCONNECT_REQ 0x02 #define SAP_DISCONNECT_RESP 0x03 #define SAP_DISCONNECT_IND 0x04 #define SAP_TRANSFER_APDU_REQ 0x05 #define SAP_TRANSFER_APDU_RESP 0x06 #define SAP_TRANSFER_ATR_REQ 0x07 #define SAP_TRANSFER_ATR_RESP 0x08 #define SAP_POWER_SIM_OFF_REQ 0x09 #define SAP_POWER_SIM_OFF_RESP 0x0A #define SAP_POWER_SIM_ON_REQ 0x0B #define SAP_POWER_SIM_ON_RESP 0x0C #define SAP_RESET_SIM_REQ 0x0D #define SAP_RESET_SIM_RESP 0x0E #define SAP_TRANSFER_CARD_READER_STATUS_REQ 0x0F #define SAP_TRANSFER_CARD_READER_STATUS_RESP 0x10 #define SAP_STATUS_IND 0x11 #define SAP_ERROR_RESP 0x12 #define SAP_SET_TRANSPORT_PROTOCOL_REQ 0x13 #define SAP_SET_TRANSPORT_PROTOCOL_RESP 0x14 #define SAP_PARAM_ID_MAX_MSG_SIZE 0x00 #define SAP_PARAM_ID_CONN_STATUS 0x01 #define SAP_PARAM_ID_RESULT_CODE 0x02 #define SAP_PARAM_ID_DISCONNECT_IND 0x03 #define SAP_PARAM_ID_COMMAND_APDU 0x04 #define SAP_PARAM_ID_COMMAND_APDU7816 0x10 #define SAP_PARAM_ID_RESPONSE_APDU 0x05 #define SAP_PARAM_ID_ATR 0x06 #define SAP_PARAM_ID_CARD_READER_STATUS 0x07 #define SAP_PARAM_ID_STATUS_CHANGE 0x08 #define SAP_PARAM_ID_TRANSPORT_PROTOCOL 0x09 #define SAP_STATUS_OK 0x00 #define SAP_STATUS_CONNECTION_FAILED 0x01 #define SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED 0x02 #define SAP_STATUS_MAX_MSG_SIZE_TOO_SMALL 0x03 #define SAP_STATUS_OK_ONGOING_CALL 0x04 #define SAP_DISCONNECTION_TYPE_GRACEFUL 0x00 #define SAP_DISCONNECTION_TYPE_IMMEDIATE 0x01 #define SAP_DISCONNECTION_TYPE_CLIENT 0xFF #define SAP_RESULT_OK 0x00 #define SAP_RESULT_ERROR_NO_REASON 0x01 #define SAP_RESULT_ERROR_NOT_ACCESSIBLE 0x02 #define SAP_RESULT_ERROR_POWERED_OFF 0x03 #define SAP_RESULT_ERROR_CARD_REMOVED 0x04 #define SAP_RESULT_ERROR_POWERED_ON 0x05 #define SAP_RESULT_ERROR_NO_DATA 0x06 #define SAP_RESULT_NOT_SUPPORTED 0x07 #define SAP_STATUS_CHANGE_UNKNOWN_ERROR 0x00 #define SAP_STATUS_CHANGE_CARD_RESET 0x01 #define SAP_STATUS_CHANGE_CARD_NOT_ACCESSIBLE 0x02 #define SAP_STATUS_CHANGE_CARD_REMOVED 0x03 #define SAP_STATUS_CHANGE_CARD_INSERTED 0x04 #define SAP_STATUS_CHANGE_CARD_RECOVERED 0x05 #define SAP_TRANSPORT_PROTOCOL_T0 0x00 #define SAP_TRANSPORT_PROTOCOL_T1 0x01 static const char *msg2str(uint8_t msg) { switch (msg) { case SAP_CONNECT_REQ: return "Connect Req"; case SAP_CONNECT_RESP: return "Connect Resp"; case SAP_DISCONNECT_REQ: return "Disconnect Req"; case SAP_DISCONNECT_RESP: return "Disconnect Resp"; case SAP_DISCONNECT_IND: return "Disconnect Ind"; case SAP_TRANSFER_APDU_REQ: return "Transfer APDU Req"; case SAP_TRANSFER_APDU_RESP: return "Transfer APDU Resp"; case SAP_TRANSFER_ATR_REQ: return "Transfer ATR Req"; case SAP_TRANSFER_ATR_RESP: return "Transfer ATR Resp"; case SAP_POWER_SIM_OFF_REQ: return "Power SIM Off Req"; case SAP_POWER_SIM_OFF_RESP: return "Power SIM Off Resp"; case SAP_POWER_SIM_ON_REQ: return "Power SIM On Req"; case SAP_POWER_SIM_ON_RESP: return "Power SIM On Resp"; case SAP_RESET_SIM_REQ: return "Reset SIM Req"; case SAP_RESET_SIM_RESP: return "Reset SIM Resp"; case SAP_TRANSFER_CARD_READER_STATUS_REQ: return "Transfer Card Reader Status Req"; case SAP_TRANSFER_CARD_READER_STATUS_RESP: return "Transfer Card Reader Status Resp"; case SAP_STATUS_IND: return "Status Ind"; case SAP_ERROR_RESP: return "Error Resp"; case SAP_SET_TRANSPORT_PROTOCOL_REQ: return "Set Transport Protocol Req"; case SAP_SET_TRANSPORT_PROTOCOL_RESP: return "Set Transport Protocol Resp"; default: return "Reserved"; } } static const char *param2str(uint8_t param) { switch (param) { case SAP_PARAM_ID_MAX_MSG_SIZE: return "MaxMsgSize"; case SAP_PARAM_ID_CONN_STATUS: return "ConnectionStatus"; case SAP_PARAM_ID_RESULT_CODE: return "ResultCode"; case SAP_PARAM_ID_DISCONNECT_IND: return "DisconnectionType"; case SAP_PARAM_ID_COMMAND_APDU: return "CommandAPDU"; case SAP_PARAM_ID_COMMAND_APDU7816: return "CommandAPDU7816"; case SAP_PARAM_ID_RESPONSE_APDU: return "ResponseAPDU"; case SAP_PARAM_ID_ATR: return "ATR"; case SAP_PARAM_ID_CARD_READER_STATUS: return "CardReaderStatus"; case SAP_PARAM_ID_STATUS_CHANGE: return "StatusChange"; case SAP_PARAM_ID_TRANSPORT_PROTOCOL: return "TransportProtocol"; default: return "Reserved"; } } static const char *status2str(uint8_t status) { switch (status) { case SAP_STATUS_OK: return "OK, Server can fulfill requirements"; case SAP_STATUS_CONNECTION_FAILED: return "Error, Server unable to establish connection"; case SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED: return "Error, Server does not support maximum message size"; case SAP_STATUS_MAX_MSG_SIZE_TOO_SMALL: return "Error, maximum message size by Client is too small"; case SAP_STATUS_OK_ONGOING_CALL: return "OK, ongoing call"; default: return "Reserved"; } } static const char *disctype2str(uint8_t disctype) { switch (disctype) { case SAP_DISCONNECTION_TYPE_GRACEFUL: return "Graceful"; case SAP_DISCONNECTION_TYPE_IMMEDIATE: return "Immediate"; default: return "Reserved"; } } static const char *result2str(uint8_t result) { switch (result) { case SAP_RESULT_OK: return "OK, request processed correctly"; case SAP_RESULT_ERROR_NO_REASON: return "Error, no reason defined"; case SAP_RESULT_ERROR_NOT_ACCESSIBLE: return "Error, card not accessible"; case SAP_RESULT_ERROR_POWERED_OFF: return "Error, card (already) powered off"; case SAP_RESULT_ERROR_CARD_REMOVED: return "Error, card removed"; case SAP_RESULT_ERROR_POWERED_ON: return "Error, card already powered on"; case SAP_RESULT_ERROR_NO_DATA: return "Error, data not available"; case SAP_RESULT_NOT_SUPPORTED: return "Error, not supported"; default: return "Reserved"; } } static const char *statuschg2str(uint8_t statuschg) { switch (statuschg) { case SAP_STATUS_CHANGE_UNKNOWN_ERROR: return "Unknown Error"; case SAP_STATUS_CHANGE_CARD_RESET: return "Card reset"; case SAP_STATUS_CHANGE_CARD_NOT_ACCESSIBLE: return "Card not accessible"; case SAP_STATUS_CHANGE_CARD_REMOVED: return "Card removed"; case SAP_STATUS_CHANGE_CARD_INSERTED: return "Card inserted"; case SAP_STATUS_CHANGE_CARD_RECOVERED: return "Card recovered"; default: return "Reserved"; } } static const char *prot2str(uint8_t prot) { switch (prot) { case SAP_TRANSPORT_PROTOCOL_T0: return "T=0"; case SAP_TRANSPORT_PROTOCOL_T1: return "T=1"; default: return "Reserved"; } } static void parse_parameters(int level, struct frame *frm) { uint8_t param; uint16_t len; uint8_t pv8; while (frm->len > 3) { p_indent(level, frm); param = get_u8(frm); get_u8(frm); len = get_u16(frm); printf("%s (0x%02x) len %d = ", param2str(param), param, len); switch (param) { case SAP_PARAM_ID_MAX_MSG_SIZE: printf("%d\n", get_u16(frm)); break; case SAP_PARAM_ID_CONN_STATUS: pv8 = get_u8(frm); printf("0x%02x (%s)\n", pv8, status2str(pv8)); break; case SAP_PARAM_ID_RESULT_CODE: case SAP_PARAM_ID_CARD_READER_STATUS: pv8 = get_u8(frm); printf("0x%02x (%s)\n", pv8, result2str(pv8)); break; case SAP_PARAM_ID_DISCONNECT_IND: pv8 = get_u8(frm); printf("0x%02x (%s)\n", pv8, disctype2str(pv8)); break; case SAP_PARAM_ID_STATUS_CHANGE: pv8 = get_u8(frm); printf("0x%02x (%s)\n", pv8, statuschg2str(pv8)); break; case SAP_PARAM_ID_TRANSPORT_PROTOCOL: pv8 = get_u8(frm); printf("0x%02x (%s)\n", pv8, prot2str(pv8)); break; default: printf("\n"); raw_ndump(level + 1, frm, len); frm->ptr += len; frm->len -= len; } /* Skip padding */ frm->ptr += PADDING4(len); frm->len -= PADDING4(len); } } void sap_dump(int level, struct frame *frm) { uint8_t msg, params; msg = get_u8(frm); params = get_u8(frm); /* Skip reserved field */ get_u16(frm); p_indent(level, frm); printf("SAP: %s: params %d\n", msg2str(msg), params); parse_parameters(level, frm); }