static int find_service_channel(bdaddr_t *adapter, bdaddr_t *device, int only_gnapplet, uint16_t svclass_id) { int i, channel = -1; char name[64]; void *ss = NULL; uint32_t attrs[] = { SDP_ATTR_RANGE( SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST), SDP_ATTR_RANGE( SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET), }; /* Buffer for the attributes */ static uint8_t buffer[NRECS * attrs_len][BSIZE]; /* SDP attributes */ static sdp_attr_t values[NRECS * attrs_len]; /* Initialize attribute values array */ for (i = 0; i < values_len; i ++) { values[i].flags = SDP_ATTR_INVALID; values[i].attr = 0; values[i].vlen = BSIZE; values[i].value = buffer[i]; } if ((ss = sdp_open(adapter, device)) == NULL) return -1; if (sdp_error(ss) != 0) goto end; if (sdp_search(ss, 1, &svclass_id, attrs_len, attrs, values_len, values) != 0) goto end; for (i = 0; i < values_len; i++) { union { uint8_t uint8; uint16_t uint16; uint32_t uint32; uint64_t uint64; int128_t int128; } value; uint8_t *start, *end; uint32_t type, len; if (values[i].flags != SDP_ATTR_OK) break; start = values[i].value; end = values[i].value + values[i].vlen; switch (values[i].attr) { case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST: SDP_GET8(type, start); switch (type) { case SDP_DATA_SEQ8: SDP_GET8(len, start); break; case SDP_DATA_SEQ16: SDP_GET16(len, start); break; case SDP_DATA_SEQ32: SDP_GET32(len, start); break; default: goto end; break; } SDP_GET8(type, start); switch (type) { case SDP_DATA_SEQ8: SDP_GET8(len, start); break; case SDP_DATA_SEQ16: SDP_GET16(len, start); break; case SDP_DATA_SEQ32: SDP_GET32(len, start); break; default: goto end; } while (start < end) { SDP_GET8(type, start); switch (type) { case SDP_DATA_UUID16: SDP_GET16(value.uint16, start); break; case SDP_DATA_UUID32: SDP_GET32(value.uint32, start); break; case SDP_DATA_UUID128: SDP_GET_UUID128(&value.int128, start); break; default: goto end; } if (value.uint16 == 3) { SDP_GET8(type, start); switch (type) { case SDP_DATA_UINT8: case SDP_DATA_INT8: SDP_GET8(value.uint8, start); channel = value.uint8; break; case SDP_DATA_UINT16: case SDP_DATA_INT16: SDP_GET16(value.uint16, start); channel = value.uint16; break; case SDP_DATA_UINT32: case SDP_DATA_INT32: SDP_GET32(value.uint32, start); channel = value.uint32; break; default: goto end; } } else { SDP_GET8(type, start); switch (type) { case SDP_DATA_SEQ8: case SDP_DATA_UINT8: case SDP_DATA_INT8: case SDP_DATA_BOOL: SDP_GET8(value.uint8, start); break; case SDP_DATA_SEQ16: case SDP_DATA_UINT16: case SDP_DATA_INT16: case SDP_DATA_UUID16: SDP_GET16(value.uint16, start); break; case SDP_DATA_SEQ32: case SDP_DATA_UINT32: case SDP_DATA_INT32: case SDP_DATA_UUID32: SDP_GET32(value.uint32, start); break; case SDP_DATA_UINT64: case SDP_DATA_INT64: SDP_GET64(value.uint64, start); break; case SDP_DATA_UINT128: case SDP_DATA_INT128: SDP_GET128(&value.int128, start); break; default: goto end; } } } start += len; break; case SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET: if (channel == -1) break; SDP_GET8(type, start); switch (type) { case SDP_DATA_STR8: case SDP_DATA_URL8: SDP_GET8(len, start); snprintf(name, sizeof(name), "%*.*s", len, len, (char *) start); start += len; break; case SDP_DATA_STR16: case SDP_DATA_URL16: SDP_GET16(len, start); snprintf(name, sizeof(name), "%*.*s", len, len, (char *) start); start += len; break; case SDP_DATA_STR32: case SDP_DATA_URL32: SDP_GET32(len, start); snprintf(name, sizeof(name), "%*.*s", len, len, (char *) start); start += len; break; default: goto end; } if (name == NULL) break; if (only_gnapplet != 0) { if (strcmp(name, "gnapplet") == 0) goto end; else { channel = -1; break; } } if (strstr(name, "Nokia PC Suite") != NULL) { channel = -1; break; } if (strstr(name, "Bluetooth Serial Port") != NULL) { channel = -1; break; } if (strstr(name, "m-Router Connectivity") != NULL) { channel = -1; break; } goto end; } } end: sdp_close(ss); return channel; }
static void print_protocol_descriptor(uint8_t const *start, uint8_t const *end) { union { uint8_t uint8; uint16_t uint16; uint32_t uint32; uint64_t uint64; int128_t int128; } value; uint32_t type, len, param; /* Get Protocol UUID */ SDP_GET8(type, start); switch (type) { case SDP_DATA_UUID16: SDP_GET16(value.uint16, start); fprintf(stdout, "\t%s (%#4.4x)\n", sdp_uuid2desc(value.uint16), value.uint16); break; case SDP_DATA_UUID32: SDP_GET32(value.uint32, start); fprintf(stdout, "\t%#8.8x\n", value.uint32); break; case SDP_DATA_UUID128: SDP_GET_UUID128(&value.int128, start); fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", ntohl(*(uint32_t *)&value.int128.b[0]), ntohs(*(uint16_t *)&value.int128.b[4]), ntohs(*(uint16_t *)&value.int128.b[6]), ntohs(*(uint16_t *)&value.int128.b[8]), ntohs(*(uint16_t *)&value.int128.b[10]), ntohl(*(uint32_t *)&value.int128.b[12])); break; default: fprintf(stderr, "Invalid Protocol Descriptor. " \ "Not a UUID, type=%#x\n", type); return; /* NOT REACHED */ } /* Protocol specific parameters */ for (param = 1; start < end; param ++) { fprintf(stdout, "\t\tProtocol specific parameter #%d: ", param); SDP_GET8(type, start); switch (type) { case SDP_DATA_NIL: fprintf(stdout, "nil\n"); break; case SDP_DATA_UINT8: case SDP_DATA_INT8: case SDP_DATA_BOOL: SDP_GET8(value.uint8, start); fprintf(stdout, "u/int8/bool %u\n", value.uint8); break; case SDP_DATA_UINT16: case SDP_DATA_INT16: case SDP_DATA_UUID16: SDP_GET16(value.uint16, start); fprintf(stdout, "u/int/uuid16 %u\n", value.uint16); break; case SDP_DATA_UINT32: case SDP_DATA_INT32: case SDP_DATA_UUID32: SDP_GET32(value.uint32, start); fprintf(stdout, "u/int/uuid32 %u\n", value.uint32); break; case SDP_DATA_UINT64: case SDP_DATA_INT64: SDP_GET64(value.uint64, start); fprintf(stdout, "u/int64 %ju\n", value.uint64); break; case SDP_DATA_UINT128: case SDP_DATA_INT128: SDP_GET128(&value.int128, start); fprintf(stdout, "u/int128 %#8.8x%8.8x%8.8x%8.8x\n", *(uint32_t *)&value.int128.b[0], *(uint32_t *)&value.int128.b[4], *(uint32_t *)&value.int128.b[8], *(uint32_t *)&value.int128.b[12]); break; case SDP_DATA_UUID128: SDP_GET_UUID128(&value.int128, start); fprintf(stdout, "uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", ntohl(*(uint32_t *)&value.int128.b[0]), ntohs(*(uint16_t *)&value.int128.b[4]), ntohs(*(uint16_t *)&value.int128.b[6]), ntohs(*(uint16_t *)&value.int128.b[8]), ntohs(*(uint16_t *)&value.int128.b[10]), ntohl(*(uint32_t *)&value.int128.b[12])); break; case SDP_DATA_STR8: case SDP_DATA_URL8: SDP_GET8(len, start); fprintf(stdout, "%*.*s\n", len, len, (char *) start); start += len; break; case SDP_DATA_STR16: case SDP_DATA_URL16: SDP_GET16(len, start); fprintf(stdout, "%*.*s\n", len, len, (char *) start); start += len; break; case SDP_DATA_STR32: case SDP_DATA_URL32: SDP_GET32(len, start); fprintf(stdout, "%*.*s\n", len, len, (char *) start); start += len; break; case SDP_DATA_SEQ8: case SDP_DATA_ALT8: SDP_GET8(len, start); for (; len > 0; start ++, len --) fprintf(stdout, "%#2.2x ", *start); fprintf(stdout, "\n"); break; case SDP_DATA_SEQ16: case SDP_DATA_ALT16: SDP_GET16(len, start); for (; len > 0; start ++, len --) fprintf(stdout, "%#2.2x ", *start); fprintf(stdout, "\n"); break; case SDP_DATA_SEQ32: case SDP_DATA_ALT32: SDP_GET32(len, start); for (; len > 0; start ++, len --) fprintf(stdout, "%#2.2x ", *start); fprintf(stdout, "\n"); break; default: fprintf(stderr, "Invalid Protocol Descriptor. " \ "Unknown data type: %#02x\n", type); return; /* NOT REACHED */ } } } /* print_protocol_descriptor */
void sdp_print(uint32_t level, uint8_t const *start, uint8_t const *end) { union { int8_t int8; int16_t int16; int32_t int32; int64_t int64; int128_t int128; uint8_t uint8; uint16_t uint16; uint32_t uint32; uint64_t uint64; } value; uint8_t type; uint32_t i; if (start == NULL || end == NULL) return; while (start < end) { for (i = 0; i < level; i++) printf("\t"); SDP_GET8(type, start); switch (type) { case SDP_DATA_NIL: printf("nil\n"); break; case SDP_DATA_UINT8: SDP_GET8(value.uint8, start); printf("uint8 %u\n", value.uint8); break; case SDP_DATA_UINT16: SDP_GET16(value.uint16, start); printf("uint16 %u\n", value.uint16); break; case SDP_DATA_UINT32: SDP_GET32(value.uint32, start); printf("uint32 %u\n", value.uint32); break; case SDP_DATA_UINT64: SDP_GET64(value.uint64, start); printf("uint64 %ju\n", value.uint64); break; case SDP_DATA_UINT128: case SDP_DATA_INT128: SDP_GET128(&value.int128, start); printf("u/int128 %#8.8x%8.8x%8.8x%8.8x\n", *(uint32_t *)&value.int128.b[0], *(uint32_t *)&value.int128.b[4], *(uint32_t *)&value.int128.b[8], *(uint32_t *)&value.int128.b[12]); break; case SDP_DATA_UUID128: SDP_GET_UUID128(&value.int128, start); printf("uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", ntohl(*(uint32_t *)&value.int128.b[0]), ntohs(*(uint16_t *)&value.int128.b[4]), ntohs(*(uint16_t *)&value.int128.b[6]), ntohs(*(uint16_t *)&value.int128.b[8]), ntohs(*(uint16_t *)&value.int128.b[10]), ntohl(*(uint32_t *)&value.int128.b[12])); break; case SDP_DATA_INT8: SDP_GET8(value.int8, start); printf("int8 %d\n", value.int8); break; case SDP_DATA_INT16: SDP_GET16(value.int16, start); printf("int16 %d\n", value.int16); break; case SDP_DATA_INT32: SDP_GET32(value.int32, start); printf("int32 %d\n", value.int32); break; case SDP_DATA_INT64: SDP_GET64(value.int64, start); printf("int64 %ju\n", value.int64); break; case SDP_DATA_UUID16: SDP_GET16(value.uint16, start); printf("uuid16 %#4.4x - %s\n", value.uint16, sdp_uuid2desc(value.uint16)); break; case SDP_DATA_UUID32: SDP_GET32(value.uint32, start); printf("uuid32 %#8.8x\n", value.uint32); break; case SDP_DATA_STR8: SDP_GET8(value.uint8, start); printf("str8 %*.*s\n", value.uint8, value.uint8, start); start += value.uint8; break; case SDP_DATA_STR16: SDP_GET16(value.uint16, start); printf("str16 %*.*s\n", value.uint16, value.uint16, start); start += value.uint16; break; case SDP_DATA_STR32: SDP_GET32(value.uint32, start); printf("str32 %*.*s\n", value.uint32, value.uint32, start); start += value.uint32; break; case SDP_DATA_BOOL: SDP_GET8(value.uint8, start); printf("bool %d\n", value.uint8); break; case SDP_DATA_SEQ8: SDP_GET8(value.uint8, start); printf("seq8 %d\n", value.uint8); sdp_print(level + 1, start, start + value.uint8); start += value.uint8; break; case SDP_DATA_SEQ16: SDP_GET16(value.uint16, start); printf("seq16 %d\n", value.uint16); sdp_print(level + 1, start, start + value.uint16); start += value.uint16; break; case SDP_DATA_SEQ32: SDP_GET32(value.uint32, start); printf("seq32 %d\n", value.uint32); sdp_print(level + 1, start, start + value.uint32); start += value.uint32; break; case SDP_DATA_ALT8: SDP_GET8(value.uint8, start); printf("alt8 %d\n", value.uint8); sdp_print(level + 1, start, start + value.uint8); start += value.uint8; break; case SDP_DATA_ALT16: SDP_GET16(value.uint16, start); printf("alt16 %d\n", value.uint16); sdp_print(level + 1, start, start + value.uint16); start += value.uint16; break; case SDP_DATA_ALT32: SDP_GET32(value.uint32, start); printf("alt32 %d\n", value.uint32); sdp_print(level + 1, start, start + value.uint32); start += value.uint32; break; case SDP_DATA_URL8: SDP_GET8(value.uint8, start); printf("url8 %*.*s\n", value.uint8, value.uint8, start); start += value.uint8; break; case SDP_DATA_URL16: SDP_GET16(value.uint16, start); printf("url16 %*.*s\n", value.uint16, value.uint16, start); start += value.uint16; break; case SDP_DATA_URL32: SDP_GET32(value.uint32, start); printf("url32 %*.*s\n", value.uint32, value.uint32, start); start += value.uint32; break; default: printf("unknown data type: %#02x\n", *start ++); break; } } }