📄 l2cap.c
字号:
mode = *h->val; set_mode(in, cid, mode); printf(" 0x%02x (%s)", mode, mode2str(mode)); } break; default: printf("Unknown (type %2.2x, len %d)", h->type & 0x7f, h->len); break; } if (h->type & 0x80) printf("] "); else printf(" "); } printf("\n");}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 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)); } conf_opt(level + 1, h->data, clen, frm->in, scid); } else { p_indent(level + 1, frm); printf("%s\n", confresult2str(result)); }}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));}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 echo_req(int level, l2cap_cmd_hdr *cmd, struct frame *frm){ if (p_filter(FILT_L2CAP)) return; printf("Echo req: dlen %d\n", btohs(cmd->len)); raw_dump(level, frm);}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 void info_opt(int level, int type, void *ptr, int len){ uint32_t mask; p_indent(level, 0); switch (type) { case 0x0001: printf("Connectionless MTU %d\n", get_val(ptr, len)); break; case 0x0002: mask = get_val(ptr, len); printf("Extended feature mask 0x%4.4x\n", mask); if (parser.flags & DUMP_VERBOSE) { if (mask & 0x01) { p_indent(level + 1, 0); printf("Flow control mode\n"); } if (mask & 0x02) { p_indent(level + 1, 0); printf("Retransmission mode\n"); } if (mask & 0x04) { p_indent(level + 1, 0); printf("Bi-directional QoS\n"); } } break; default: printf("Unknown (len %d)\n", len); break; }}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 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 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); } frm->ptr += btohs(hdr->len); frm->len -= btohs(hdr->len); } } 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 { uint8_t sar = (ctrl & 0xc000) >> 14; printf(" %s", sar2str(sar)); if (sar == 1) { uint16_t len; len = btohs(bt_get_unaligned((uint16_t *) frm->ptr)); frm->ptr += 2; frm->len -= 2; printf(" (len %d)", len); } printf(" TxSeq %d", (ctrl & 0x7e) >> 1); } printf(" ReqSeq %d", (ctrl & 0x3f00) >> 8); if (ctrl & 0x80) printf(" Retransmission Disable"); printf("\n"); } } switch (psm) { case 0x01: if (!p_filter(FILT_SDP)) sdp_dump(level + 1, frm); else raw_dump(level + 1, frm); break; case 0x03: if (!p_filter(FILT_RFCOMM)) rfcomm_dump(level, frm); else raw_dump(level + 1, frm); break; case 0x0f: if (!p_filter(FILT_BNEP)) bnep_dump(level, frm); else raw_dump(level + 1, frm); break; case 0x11: case 0x13: if (!p_filter(FILT_HIDP)) hidp_dump(level, frm); else raw_dump(level + 1, frm); break; case 0x19: if (!p_filter(FILT_AVDTP)) avdtp_dump(level, frm); else raw_dump(level + 1, frm); break; default: proto = get_proto(frm->handle, psm, 0); switch (proto) { case SDP_UUID_CMTP: if (!p_filter(FILT_CMTP)) cmtp_dump(level, frm); else raw_dump(level + 1, frm); break; case SDP_UUID_HARDCOPY_CONTROL_CHANNEL: if (!p_filter(FILT_HCRP)) hcrp_dump(level, frm); else raw_dump(level + 1, frm); break; default: if (p_filter(FILT_L2CAP)) break; raw_dump(level, frm); break; } break; } }}void l2cap_dump(int level, struct frame *frm){ struct frame *fr; l2cap_hdr *hdr; uint16_t dlen; if (frm->flags & ACL_START) { hdr = frm->ptr; dlen = btohs(hdr->len); if (frm->len == (dlen + L2CAP_HDR_SIZE)) { /* Complete frame */ l2cap_parse(level, frm); return; } if (!(fr = get_frame(frm->handle))) { fprintf(stderr, "Not enough connection handles\n"); raw_dump(level, frm); return; } if (fr->data) free(fr->data); if (!(fr->data = malloc(dlen + L2CAP_HDR_SIZE))) { perror("Can't allocate L2CAP reassembly buffer"); return; } memcpy(fr->data, frm->ptr, frm->len); fr->data_len = dlen + L2CAP_HDR_SIZE; fr->len = frm->len; fr->ptr = fr->data; fr->in = frm->in; fr->ts = frm->ts; fr->handle = frm->handle; fr->cid = frm->cid; fr->num = frm->num; fr->dlci = frm->dlci; fr->channel = frm->channel; } else { if (!(fr = get_frame(frm->handle))) { fprintf(stderr, "Not enough connection handles\n"); raw_dump(level, frm); return; } if (!fr->data) { /* Unexpected fragment */ raw_dump(level, frm); return; } if (frm->len > (fr->data_len - fr->len)) { /* Bad fragment */ raw_dump(level, frm); free(fr->data); fr->data = NULL; return; } memcpy(fr->data + fr->len, frm->ptr, frm->len); fr->len += frm->len; if (fr->len == fr->data_len) { /* Complete frame */ l2cap_parse(level, fr); free(fr->data); fr->data = NULL; return; } }}void l2cap_clear(uint16_t handle){ del_handle(handle);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -