static inline void uih_frame(int level, struct frame *frm, long_frame_head *head) { uint32_t proto; if (!head->addr.server_chn) { mcc_frame(level, frm, head); } else { p_indent(level, frm); printf("RFCOMM(d): UIH: "); print_rfcomm_hdr(head, frm->ptr, frm->len); if (GET_PF(head->control)) { printf("credits %d\n", *(uint8_t *)(frm->ptr)); frm->ptr++; frm->len--; } else printf("\n"); frm->len--; frm->dlci = GET_DLCI(head->addr); frm->channel = head->addr.server_chn; proto = get_proto(frm->handle, RFCOMM_PSM, frm->channel); if (frm->len > 0) { switch (proto) { case SDP_UUID_OBEX: if (!p_filter(FILT_OBEX)) obex_dump(level + 1, frm); else raw_dump(level, frm); break; case SDP_UUID_LAN_ACCESS_PPP: case SDP_UUID_DIALUP_NETWORKING: if (!p_filter(FILT_PPP)) ppp_dump(level + 1, frm); else raw_dump(level, frm); break; default: if (p_filter(FILT_RFCOMM)) break; raw_dump(level, frm); break; } } } }
static inline void conf_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm) { l2cap_conf_rsp *h = frm->ptr; uint16_t scid = btohs(h->scid); uint16_t result = btohs(h->result); int clen = btohs(cmd->len) - L2CAP_CONF_RSP_SIZE; if (p_filter(FILT_L2CAP)) return; printf("Config rsp: scid 0x%4.4x flags 0x%2.2x result %d clen %d\n", scid, btohs(h->flags), result, clen); if (clen > 0) { if (result) { p_indent(level + 1, frm); printf("%s\n", confresult2str(result)); } if (result == 0x0003) conf_list(level + 1, h->data, clen); else conf_opt(level + 1, h->data, clen, frm->in, frm->handle, scid); } else { p_indent(level + 1, frm); printf("%s\n", confresult2str(result)); } }
static inline void echo_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm) { if (p_filter(FILT_L2CAP)) return; printf("Echo rsp: dlen %d\n", btohs(cmd->len)); raw_dump(level, frm); }
static inline void info_req(int level, l2cap_cmd_hdr *cmd, struct frame *frm) { l2cap_info_req *h = frm->ptr; if (p_filter(FILT_L2CAP)) return; printf("Info req: type %d\n", btohs(h->type)); }
static inline void disconn_req(int level, struct frame *frm) { l2cap_disconn_req *h = frm->ptr; if (p_filter(FILT_L2CAP)) return; printf("Disconn req: dcid 0x%4.4x scid 0x%4.4x\n", btohs(h->dcid), btohs(h->scid)); }
void cmtp_dump(int level, struct frame *frm) { struct frame *msg; uint8_t hdr, bid; uint16_t len; while (frm->len > 0) { hdr = p_get_u8(frm); bid = (hdr & 0x3c) >> 2; switch ((hdr & 0xc0) >> 6) { case 0x01: len = p_get_u8(frm); break; case 0x02: len = htons(p_get_u16(frm)); break; default: len = 0; break; } p_indent(level, frm); printf("CMTP: %s: id %d len %d\n", bst2str(hdr & 0x03), bid, len); switch (hdr & 0x03) { case 0x00: add_segment(bid, frm, len); msg = get_segment(bid, frm); if (!msg) break; if (!p_filter(FILT_CAPI)) capi_dump(level + 1, msg); else raw_dump(level, msg); free_segment(bid, frm); break; case 0x01: add_segment(bid, frm, len); break; default: free_segment(bid, frm); break; } frm->ptr += len; frm->len -= len; } }
static inline void conn_req(int level, struct frame *frm) { l2cap_conn_req *h = frm->ptr; uint16_t psm = btohs(h->psm); uint16_t scid = btohs(h->scid); add_cid(frm->in, frm->handle, scid, psm); if (p_filter(FILT_L2CAP)) return; printf("Connect req: psm %d scid 0x%4.4x\n", psm, scid); }
static inline void disconn_rsp(int level, struct frame *frm) { l2cap_disconn_rsp *h = frm->ptr; uint16_t dcid = btohs(h->dcid); uint16_t scid = btohs(h->scid); del_cid(frm->in, dcid, scid); if (p_filter(FILT_L2CAP)) return; printf("Disconn rsp: dcid 0x%4.4x scid 0x%4.4x\n", btohs(h->dcid), btohs(h->scid)); }
static inline void conf_req(int level, l2cap_cmd_hdr *cmd, struct frame *frm) { l2cap_conf_req *h = frm->ptr; uint16_t dcid = btohs(h->dcid); int clen = btohs(cmd->len) - L2CAP_CONF_REQ_SIZE; if (p_filter(FILT_L2CAP)) return; printf("Config req: dcid 0x%4.4x flags 0x%2.2x clen %d\n", dcid, btohs(h->flags), clen); if (clen > 0) conf_opt(level + 1, h->data, clen, frm->in, dcid); }
static inline void info_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm) { l2cap_info_rsp *h = frm->ptr; uint16_t type = btohs(h->type); uint16_t result = btohs(h->result); int ilen = btohs(cmd->len) - L2CAP_INFO_RSP_SIZE; if (p_filter(FILT_L2CAP)) return; printf("Info rsp: type %d result %d\n", type, result); if (ilen > 0) { info_opt(level + 1, type, h->data, ilen); } else { p_indent(level + 1, frm); printf("%s\n", inforesult2str(result)); } }
static inline void conn_rsp(int level, struct frame *frm) { l2cap_conn_rsp *h = frm->ptr; uint16_t scid = btohs(h->scid); uint16_t dcid = btohs(h->dcid); uint16_t result = btohs(h->result); uint16_t status = btohs(h->status); uint16_t psm; switch (h->result) { case L2CAP_CR_SUCCESS: if ((psm = get_psm(!frm->in, frm->handle, scid))) add_cid(frm->in, frm->handle, dcid, psm); break; case L2CAP_CR_PEND: break; default: del_cid(frm->in, dcid, scid); break; } if (p_filter(FILT_L2CAP)) return; printf("Connect rsp: dcid 0x%4.4x scid 0x%4.4x result %d status %d\n", dcid, scid, result, status); p_indent(level + 1, frm); printf("%s", connresult2str(result)); if (result == 0x0001) printf(" - %s\n", status2str(status)); else printf("\n"); }
void csr_dump(int level, struct frame *frm) { uint8_t desc, cid, type; uint16_t handle, master, addr; desc = CSR_U8(frm); cid = desc & 0x3f; switch (cid) { case 2: bccmd_dump(level, frm); break; case 20: type = CSR_U8(frm); if (!p_filter(FILT_LMP)) { switch (type) { case 0x0f: frm->handle = ((uint8_t *) frm->ptr)[17]; frm->master = 0; frm->len--; lmp_dump(level, frm); return; case 0x10: frm->handle = ((uint8_t *) frm->ptr)[17]; frm->master = 1; frm->len--; lmp_dump(level, frm); return; case 0x12: handle = CSR_U16(frm); master = CSR_U16(frm); addr = CSR_U16(frm); p_indent(level, frm); printf("FHS: handle %d addr %d (%s)\n", handle, addr, master ? "master" : "slave"); if (!master) { char addr[18]; p_ba2str((bdaddr_t *) frm->ptr, addr); p_indent(level + 1, frm); printf("bdaddr %s class " "0x%2.2x%2.2x%2.2x\n", addr, ((uint8_t *) frm->ptr)[8], ((uint8_t *) frm->ptr)[7], ((uint8_t *) frm->ptr)[6]); } return; case 0x7b: p_indent(level, frm); printf("LMP(r): duplicate (same SEQN)\n"); return; } } p_indent(level, frm); printf("CSR: Debug (type 0x%2.2x)\n", type); raw_dump(level, frm); break; default: p_indent(level, frm); printf("CSR: %s (channel %d)%s\n", cid2str(cid), cid, frag2str(desc)); raw_dump(level, frm); break; } }
static void l2cap_parse(int level, struct frame *frm) { l2cap_hdr *hdr = (void *)frm->ptr; uint16_t dlen = btohs(hdr->len); uint16_t cid = btohs(hdr->cid); uint16_t psm; frm->ptr += L2CAP_HDR_SIZE; frm->len -= L2CAP_HDR_SIZE; if (cid == 0x1) { /* Signaling channel */ while (frm->len >= L2CAP_CMD_HDR_SIZE) { l2cap_cmd_hdr *hdr = frm->ptr; frm->ptr += L2CAP_CMD_HDR_SIZE; frm->len -= L2CAP_CMD_HDR_SIZE; if (!p_filter(FILT_L2CAP)) { p_indent(level, frm); printf("L2CAP(s): "); } switch (hdr->code) { case L2CAP_COMMAND_REJ: command_rej(level, frm); break; case L2CAP_CONN_REQ: conn_req(level, frm); break; case L2CAP_CONN_RSP: conn_rsp(level, frm); break; case L2CAP_CONF_REQ: conf_req(level, hdr, frm); break; case L2CAP_CONF_RSP: conf_rsp(level, hdr, frm); break; case L2CAP_DISCONN_REQ: disconn_req(level, frm); break; case L2CAP_DISCONN_RSP: disconn_rsp(level, frm); break; case L2CAP_ECHO_REQ: echo_req(level, hdr, frm); break; case L2CAP_ECHO_RSP: echo_rsp(level, hdr, frm); break; case L2CAP_INFO_REQ: info_req(level, hdr, frm); break; case L2CAP_INFO_RSP: info_rsp(level, hdr, frm); break; default: if (p_filter(FILT_L2CAP)) break; printf("code 0x%2.2x ident %d len %d\n", hdr->code, hdr->ident, btohs(hdr->len)); raw_dump(level, frm); } if (frm->len > btohs(hdr->len)) { frm->len -= btohs(hdr->len); frm->ptr += btohs(hdr->len); } else frm->len = 0; } } else if (cid == 0x2) { /* Connectionless channel */ if (p_filter(FILT_L2CAP)) return; psm = btohs(bt_get_unaligned((uint16_t *) frm->ptr)); frm->ptr += 2; frm->len -= 2; p_indent(level, frm); printf("L2CAP(c): len %d psm %d\n", dlen, psm); raw_dump(level, frm); } else { /* Connection oriented channel */ uint8_t mode = get_mode(!frm->in, cid); uint16_t psm = get_psm(!frm->in, cid); uint16_t ctrl = 0, fcs = 0; uint32_t proto; frm->cid = cid; frm->num = get_num(!frm->in, cid); if (mode > 0) { ctrl = btohs(bt_get_unaligned((uint16_t *) frm->ptr)); frm->ptr += 2; frm->len -= 4; fcs = btohs(bt_get_unaligned((uint16_t *) (frm->ptr + frm->len))); } if (!p_filter(FILT_L2CAP)) { p_indent(level, frm); printf("L2CAP(d): cid 0x%4.4x len %d", cid, dlen); if (mode > 0) printf(" ctrl 0x%4.4x fcs 0x%4.4x", ctrl, fcs); printf(" [psm %d]\n", psm); level++; if (mode > 0) { p_indent(level, frm); printf("%s:", ctrl & 0x01 ? "S-frame" : "I-frame"); if (ctrl & 0x01) { printf(" %s", supervisory2str((ctrl & 0x0c) >> 2)); } else {