📄 sdptool.c
字号:
/* Service Discovery Protocol (SDP) Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>, Stephen Crane <steve.crane@rococosoft.com> Based on original SDP implementation by Nokia Corporation. Copyright (C) 2001,2002 Nokia Corporation. Original author Guruprasad Krishnamurthy <guruprasad.krishnamurthy@nokia.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED.*//* * $Id: sdptool.c,v 1.61 2003/07/27 18:15:22 holtmann Exp $ */#include <stdlib.h>#include <stdio.h>#include <getopt.h>#include <errno.h>#include "sdp.h"#include "sdp_lib.h"/* Pass args to the inquiry/search handler */struct search_context { char *svc; /* Service */ uuid_t group; /* Browse group */ int tree; /* Display full attribute tree */ uint32_t handle; /* Service record handle */};typedef int (*handler_t)(bdaddr_t *bdaddr, struct search_context *arg);static char UUID_str[MAX_LEN_UUID_STR];static bdaddr_t interface;/* listattr.c */extern void sdp_printf_service_attr(sdp_record_t *rec);/* setattr.c */extern int cmd_setattr(int argc, char **argv);extern int cmd_setseq(int argc, char **argv);#define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, 0)) != -1)/* * Convert a string to a BDADDR, with a few "enhancements" - Jean II */int estr2ba(char *str, bdaddr_t *ba){ /* Only trap "local", "any" is already dealt with */ if(!strcmp(str, "local")) { bacpy(ba, BDADDR_LOCAL); return 0; } return str2ba(str, ba);}static void print_service_class(void *value, void *userData){ char ServiceClassUUID_str[MAX_LEN_SERVICECLASS_UUID_STR]; uuid_t *uuid = (uuid_t *)value; sdp_uuid2strn(uuid, UUID_str, MAX_LEN_UUID_STR); sdp_svclass_uuid2strn(uuid, ServiceClassUUID_str, MAX_LEN_SERVICECLASS_UUID_STR); printf(" \"%s\" (0x%s)\n", ServiceClassUUID_str, UUID_str);}static void print_service_desc(void *value, void *user){ char str[MAX_LEN_PROTOCOL_UUID_STR]; sdp_data_t *p = (sdp_data_t *)value, *s; int i = 0, proto = 0; for (; p; p = p->next, i++) { switch (p->dtd) { case SDP_UUID16: case SDP_UUID32: case SDP_UUID128: sdp_uuid2strn(&p->val.uuid, UUID_str, MAX_LEN_UUID_STR); sdp_proto_uuid2strn(&p->val.uuid, str, sizeof(str)); proto = sdp_uuid_to_proto(&p->val.uuid); printf(" \"%s\" (0x%s)\n", str, UUID_str); break; case SDP_UINT8: if (proto == RFCOMM_UUID) printf(" Channel: %d\n", p->val.uint8); else printf(" uint8: 0x%x\n", p->val.uint8); break; case SDP_UINT16: if (proto == L2CAP_UUID) { if (i == 1) printf(" PSM: %d\n", p->val.uint16); else printf(" Version: 0x%04x\n", p->val.uint16); } else if (proto == BNEP_UUID) if (i == 1) printf(" Version: 0x%04x\n", p->val.uint16); else printf(" uint16: 0x%x\n", p->val.uint16); else printf(" uint16: 0x%x\n", p->val.uint16); break; case SDP_SEQ16: printf(" SEQ16:"); for (s = p->val.dataseq; s; s = s->next) printf(" %x", s->val.uint16); printf("\n"); break; case SDP_SEQ8: printf(" SEQ8:"); for (s = p->val.dataseq; s; s = s->next) printf(" %x", s->val.uint8); printf("\n"); break; default: printf(" FIXME: dtd=0%x\n", p->dtd); break; } }}void print_lang_attr(void *value, void *user){ sdp_lang_attr_t *lang = (sdp_lang_attr_t *)value; printf(" code_ISO639: 0x%02x\n", lang->code_ISO639); printf(" encoding: 0x%02x\n", lang->encoding); printf(" base_offset: 0x%02x\n", lang->base_offset);}void print_access_protos(value, userData){ sdp_list_t *protDescSeq = (sdp_list_t *)value; sdp_list_foreach(protDescSeq, print_service_desc, 0);}void print_profile_desc(void *value, void *userData){ sdp_profile_desc_t *desc = (sdp_profile_desc_t *)value; char str[MAX_LEN_PROFILEDESCRIPTOR_UUID_STR]; sdp_uuid2strn(&desc->uuid, UUID_str, MAX_LEN_UUID_STR); sdp_profile_uuid2strn(&desc->uuid, str, MAX_LEN_PROFILEDESCRIPTOR_UUID_STR); printf(" \"%s\" (0x%s)\n", str, UUID_str); if (desc->version) printf(" Version: 0x%04x\n", desc->version);}/* * Parse a SDP record in user friendly form. */void print_service_attr(sdp_record_t *rec){ sdp_list_t *list = 0, *proto = 0; sdp_record_print(rec); printf("Service RecHandle: 0x%x\n", rec->handle); if (sdp_get_service_classes(rec, &list) == 0) { printf("Service Class ID List:\n"); sdp_list_foreach(list, print_service_class, 0); sdp_list_free(list, free); } if (sdp_get_access_protos(rec, &proto) == 0) { printf("Protocol Descriptor List:\n"); sdp_list_foreach(proto, print_access_protos, 0); sdp_list_free(proto, (sdp_free_func_t)sdp_data_free); } if (sdp_get_lang_attr(rec, &list) == 0) { printf("Language Base Attr List:\n"); sdp_list_foreach(list, print_lang_attr, 0); sdp_list_free(list, free); } if (sdp_get_profile_descs(rec, &list) == 0) { printf("Profile Descriptor List:\n"); sdp_list_foreach(list, print_profile_desc, 0); sdp_list_free(list, free); }}/* * Support for Service (de)registration */typedef struct { char *name; char *provider; char *desc; unsigned int class; unsigned int profile; unsigned int channel;} svc_info_t;static int add_sp(sdp_session_t *session, svc_info_t *si){ sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto; uuid_t root_uuid, sp_uuid, l2cap, rfcomm; sdp_profile_desc_t profile; sdp_record_t record; uint8_t u8 = si->channel? si->channel: 1; sdp_data_t *channel; int ret = 0; memset((void *)&record, 0, sizeof(sdp_record_t)); record.handle = 0xffffffff; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); sdp_list_free(root, 0); sdp_uuid16_create(&sp_uuid, SERIAL_PORT_SVCLASS_ID); svclass_id = sdp_list_append(0, &sp_uuid); sdp_set_service_classes(&record, svclass_id); sdp_list_free(svclass_id, 0); sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID); profile.version = 0x0100; profiles = sdp_list_append(0, &profile); sdp_set_profile_descs(&record, profiles); sdp_list_free(profiles, 0); sdp_uuid16_create(&l2cap, L2CAP_UUID); proto[0] = sdp_list_append(0, &l2cap); apseq = sdp_list_append(0, proto[0]); sdp_uuid16_create(&rfcomm, RFCOMM_UUID); proto[1] = sdp_list_append(0, &rfcomm); channel = sdp_data_alloc(SDP_UINT8, &u8); proto[1] = sdp_list_append(proto[1], channel); apseq = sdp_list_append(apseq, proto[1]); aproto = sdp_list_append(0, apseq); sdp_set_access_protos(&record, aproto); sdp_set_info_attr(&record, "Serial Port", 0, 0); if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { printf("Service Record registration failed\n"); ret = -1; goto end; } printf("Serial Port service registered\n");end: sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); return ret;}static int add_dun(sdp_session_t *session, svc_info_t *si){ sdp_list_t *svclass_id, *pfseq, *apseq, *root, *aproto; uuid_t rootu, dun, gn, l2cap, rfcomm; sdp_profile_desc_t profile; sdp_list_t *proto[2]; sdp_record_t record; uint8_t u8 = si->channel? si->channel: 1; sdp_data_t *channel; int ret = 0; memset((void *)&record, 0, sizeof(sdp_record_t)); record.handle = 0xffffffff; sdp_uuid16_create(&rootu, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &rootu); sdp_set_browse_groups(&record, root); sdp_uuid16_create(&dun, DIALUP_NET_SVCLASS_ID); svclass_id = sdp_list_append(0, &dun); sdp_uuid16_create(&gn, GENERIC_NETWORKING_SVCLASS_ID); svclass_id = sdp_list_append(svclass_id, &gn); sdp_set_service_classes(&record, svclass_id); sdp_uuid16_create(&profile.uuid, DIALUP_NET_PROFILE_ID); profile.version = 0x0100; pfseq = sdp_list_append(0, &profile); sdp_set_profile_descs(&record, pfseq); sdp_uuid16_create(&l2cap, L2CAP_UUID); proto[0] = sdp_list_append(0, &l2cap); apseq = sdp_list_append(0, proto[0]); sdp_uuid16_create(&rfcomm, RFCOMM_UUID); proto[1] = sdp_list_append(0, &rfcomm); channel = sdp_data_alloc(SDP_UINT8, &u8); proto[1] = sdp_list_append(proto[1], channel); apseq = sdp_list_append(apseq, proto[1]); aproto = sdp_list_append(0, apseq); sdp_set_access_protos(&record, aproto); sdp_set_info_attr(&record, "Dial-Up Networking", 0, 0); if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { printf("Service Record registration failed\n"); ret = -1; goto end; } printf("Dial-Up Networking service registered\n");end: sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); return ret;}static int add_lan(sdp_session_t *session, svc_info_t *si){ sdp_list_t *svclass_id, *pfseq, *apseq, *root; uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; sdp_profile_desc_t profile; sdp_list_t *aproto, *proto[2]; sdp_record_t record; uint8_t u8 = si->channel? si->channel: 2; sdp_data_t *channel; int ret = 0; memset((void *)&record, 0, sizeof(sdp_record_t)); record.handle = 0xffffffff; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); sdp_uuid16_create(&svclass_uuid, LAN_ACCESS_SVCLASS_ID); svclass_id = sdp_list_append(0, &svclass_uuid); sdp_set_service_classes(&record, svclass_id); sdp_uuid16_create(&profile.uuid, LAN_ACCESS_PROFILE_ID); profile.version = 0x0100; pfseq = sdp_list_append(0, &profile); sdp_set_profile_descs(&record, pfseq); sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); proto[0] = sdp_list_append(0, &l2cap_uuid); apseq = sdp_list_append(0, proto[0]); sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); proto[1] = sdp_list_append(0, &rfcomm_uuid); channel = sdp_data_alloc(SDP_UINT8, &u8); proto[1] = sdp_list_append(proto[1], channel); apseq = sdp_list_append(apseq, proto[1]); aproto = sdp_list_append(0, apseq); sdp_set_access_protos(&record, aproto); sdp_set_info_attr(&record, "LAN Access over PPP", 0, 0); if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { printf("Service Record registration failed\n"); ret = -1; goto end; } printf("LAN Access service registered\n");end: sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); return ret;}static int add_headset(sdp_session_t *session, svc_info_t *si){ sdp_list_t *svclass_id, *pfseq, *apseq, *root; uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid; sdp_profile_desc_t profile; sdp_list_t *aproto, *proto[2]; sdp_record_t record; uint8_t u8 = si->channel? si->channel: 5; sdp_data_t *channel; int ret = 0; memset((void *)&record, 0, sizeof(sdp_record_t)); record.handle = 0xffffffff; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); sdp_uuid16_create(&svclass_uuid, HEADSET_SVCLASS_ID); svclass_id = sdp_list_append(0, &svclass_uuid); sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID); svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid); sdp_set_service_classes(&record, svclass_id); sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID); profile.version = 0x0100; pfseq = sdp_list_append(0, &profile); sdp_set_profile_descs(&record, pfseq); sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); proto[0] = sdp_list_append(0, &l2cap_uuid); apseq = sdp_list_append(0, proto[0]); sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); proto[1] = sdp_list_append(0, &rfcomm_uuid); channel = sdp_data_alloc(SDP_UINT8, &u8); proto[1] = sdp_list_append(proto[1], channel); apseq = sdp_list_append(apseq, proto[1]); aproto = sdp_list_append(0, apseq); sdp_set_access_protos(&record, aproto); sdp_set_info_attr(&record, "Headset", 0, 0); if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { printf("Service Record registration failed\n"); ret = -1; goto end; } printf("Headset service registered\n");end: sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); return ret;}static int add_fax(sdp_session_t *session, svc_info_t *si){ sdp_list_t *svclass_id, *pfseq, *apseq, *root; uuid_t root_uuid, fax_uuid, tel_uuid, l2cap_uuid, rfcomm_uuid; sdp_profile_desc_t profile; sdp_list_t *aproto, *proto[2]; sdp_record_t record; uint8_t u8 = si->channel? si->channel: 3; sdp_data_t *channel; int ret = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -