11de7b4b8SPedro F. Giffuni /*- 20986ab12SMaksim Yevmenkin * sdpcontrol.c 30986ab12SMaksim Yevmenkin * 4*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 51de7b4b8SPedro F. Giffuni * 60986ab12SMaksim Yevmenkin * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> 70986ab12SMaksim Yevmenkin * All rights reserved. 80986ab12SMaksim Yevmenkin * 90986ab12SMaksim Yevmenkin * Redistribution and use in source and binary forms, with or without 100986ab12SMaksim Yevmenkin * modification, are permitted provided that the following conditions 110986ab12SMaksim Yevmenkin * are met: 120986ab12SMaksim Yevmenkin * 1. Redistributions of source code must retain the above copyright 130986ab12SMaksim Yevmenkin * notice, this list of conditions and the following disclaimer. 140986ab12SMaksim Yevmenkin * 2. Redistributions in binary form must reproduce the above copyright 150986ab12SMaksim Yevmenkin * notice, this list of conditions and the following disclaimer in the 160986ab12SMaksim Yevmenkin * documentation and/or other materials provided with the distribution. 170986ab12SMaksim Yevmenkin * 180986ab12SMaksim Yevmenkin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 190986ab12SMaksim Yevmenkin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 200986ab12SMaksim Yevmenkin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 210986ab12SMaksim Yevmenkin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 220986ab12SMaksim Yevmenkin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 230986ab12SMaksim Yevmenkin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 240986ab12SMaksim Yevmenkin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 250986ab12SMaksim Yevmenkin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 260986ab12SMaksim Yevmenkin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 270986ab12SMaksim Yevmenkin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 280986ab12SMaksim Yevmenkin * SUCH DAMAGE. 290986ab12SMaksim Yevmenkin * 300986ab12SMaksim Yevmenkin * $Id: sdpcontrol.c,v 1.1 2003/09/08 02:27:27 max Exp $ 310986ab12SMaksim Yevmenkin * $FreeBSD$ 320986ab12SMaksim Yevmenkin */ 330986ab12SMaksim Yevmenkin 340986ab12SMaksim Yevmenkin #include <assert.h> 358d6f425dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED 360986ab12SMaksim Yevmenkin #include <bluetooth.h> 370986ab12SMaksim Yevmenkin #include <err.h> 380986ab12SMaksim Yevmenkin #include <errno.h> 390986ab12SMaksim Yevmenkin #include <sdp.h> 400986ab12SMaksim Yevmenkin #include <stdio.h> 410986ab12SMaksim Yevmenkin #include <stdlib.h> 420986ab12SMaksim Yevmenkin #include <string.h> 430986ab12SMaksim Yevmenkin #include <unistd.h> 440986ab12SMaksim Yevmenkin #include "sdpcontrol.h" 450986ab12SMaksim Yevmenkin 460986ab12SMaksim Yevmenkin /* Prototypes */ 47a4b187faSMaksim Yevmenkin static int do_sdp_command (bdaddr_p, char const *, int, 48a4b187faSMaksim Yevmenkin int, char **); 490986ab12SMaksim Yevmenkin static struct sdp_command * find_sdp_command (char const *, 500986ab12SMaksim Yevmenkin struct sdp_command *); 510986ab12SMaksim Yevmenkin static void print_sdp_command (struct sdp_command *); 520986ab12SMaksim Yevmenkin static void usage (void); 530986ab12SMaksim Yevmenkin 540986ab12SMaksim Yevmenkin /* Main */ 550986ab12SMaksim Yevmenkin int 560986ab12SMaksim Yevmenkin main(int argc, char *argv[]) 570986ab12SMaksim Yevmenkin { 58a4b187faSMaksim Yevmenkin char const *control = SDP_LOCAL_PATH; 59a4b187faSMaksim Yevmenkin int n, local; 600986ab12SMaksim Yevmenkin bdaddr_t bdaddr; 610986ab12SMaksim Yevmenkin 620986ab12SMaksim Yevmenkin memset(&bdaddr, 0, sizeof(bdaddr)); 6307be7a6cSMaksim Yevmenkin local = 0; 640986ab12SMaksim Yevmenkin 650986ab12SMaksim Yevmenkin /* Process command line arguments */ 66a4b187faSMaksim Yevmenkin while ((n = getopt(argc, argv, "a:c:lh")) != -1) { 670986ab12SMaksim Yevmenkin switch (n) { 68a4b187faSMaksim Yevmenkin case 'a': /* bdaddr */ 690986ab12SMaksim Yevmenkin if (!bt_aton(optarg, &bdaddr)) { 700986ab12SMaksim Yevmenkin struct hostent *he = NULL; 710986ab12SMaksim Yevmenkin 720986ab12SMaksim Yevmenkin if ((he = bt_gethostbyname(optarg)) == NULL) 730986ab12SMaksim Yevmenkin errx(1, "%s: %s", optarg, hstrerror(h_errno)); 740986ab12SMaksim Yevmenkin 750986ab12SMaksim Yevmenkin memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); 760986ab12SMaksim Yevmenkin } 770986ab12SMaksim Yevmenkin break; 780986ab12SMaksim Yevmenkin 79a4b187faSMaksim Yevmenkin case 'c': /* control socket */ 80a4b187faSMaksim Yevmenkin control = optarg; 81a4b187faSMaksim Yevmenkin break; 82a4b187faSMaksim Yevmenkin 83a4b187faSMaksim Yevmenkin case 'l': /* local sdpd */ 84a4b187faSMaksim Yevmenkin local = 1; 85a4b187faSMaksim Yevmenkin break; 86a4b187faSMaksim Yevmenkin 870986ab12SMaksim Yevmenkin case 'h': 880986ab12SMaksim Yevmenkin default: 890986ab12SMaksim Yevmenkin usage(); 900986ab12SMaksim Yevmenkin /* NOT REACHED */ 910986ab12SMaksim Yevmenkin } 920986ab12SMaksim Yevmenkin } 930986ab12SMaksim Yevmenkin 940986ab12SMaksim Yevmenkin argc -= optind; 950986ab12SMaksim Yevmenkin argv += optind; 960986ab12SMaksim Yevmenkin 970986ab12SMaksim Yevmenkin if (*argv == NULL) 980986ab12SMaksim Yevmenkin usage(); 990986ab12SMaksim Yevmenkin 100a4b187faSMaksim Yevmenkin return (do_sdp_command(&bdaddr, control, local, argc, argv)); 1010986ab12SMaksim Yevmenkin } 1020986ab12SMaksim Yevmenkin 1030986ab12SMaksim Yevmenkin /* Execute commands */ 1040986ab12SMaksim Yevmenkin static int 105a4b187faSMaksim Yevmenkin do_sdp_command(bdaddr_p bdaddr, char const *control, int local, 106a4b187faSMaksim Yevmenkin int argc, char **argv) 1070986ab12SMaksim Yevmenkin { 1080986ab12SMaksim Yevmenkin char *cmd = argv[0]; 1090986ab12SMaksim Yevmenkin struct sdp_command *c = NULL; 1100986ab12SMaksim Yevmenkin void *xs = NULL; 1110986ab12SMaksim Yevmenkin int e, help; 1120986ab12SMaksim Yevmenkin 1130986ab12SMaksim Yevmenkin help = 0; 1140986ab12SMaksim Yevmenkin if (strcasecmp(cmd, "help") == 0) { 1150986ab12SMaksim Yevmenkin argc --; 1160986ab12SMaksim Yevmenkin argv ++; 1170986ab12SMaksim Yevmenkin 1180986ab12SMaksim Yevmenkin if (argc <= 0) { 1190986ab12SMaksim Yevmenkin fprintf(stdout, "Supported commands:\n"); 1200986ab12SMaksim Yevmenkin print_sdp_command(sdp_commands); 1210986ab12SMaksim Yevmenkin fprintf(stdout, "\nFor more information use " \ 1220986ab12SMaksim Yevmenkin "'help command'\n"); 1230986ab12SMaksim Yevmenkin 1240986ab12SMaksim Yevmenkin return (OK); 1250986ab12SMaksim Yevmenkin } 1260986ab12SMaksim Yevmenkin 1270986ab12SMaksim Yevmenkin help = 1; 1280986ab12SMaksim Yevmenkin cmd = argv[0]; 1290986ab12SMaksim Yevmenkin } 1300986ab12SMaksim Yevmenkin 1310986ab12SMaksim Yevmenkin c = find_sdp_command(cmd, sdp_commands); 1320986ab12SMaksim Yevmenkin if (c == NULL) { 1330986ab12SMaksim Yevmenkin fprintf(stdout, "Unknown command: \"%s\"\n", cmd); 1340986ab12SMaksim Yevmenkin return (ERROR); 1350986ab12SMaksim Yevmenkin } 1360986ab12SMaksim Yevmenkin 1370986ab12SMaksim Yevmenkin if (!help) { 138a4b187faSMaksim Yevmenkin if (!local) { 1390986ab12SMaksim Yevmenkin if (memcmp(bdaddr, NG_HCI_BDADDR_ANY, sizeof(*bdaddr)) == 0) 1400986ab12SMaksim Yevmenkin usage(); 1410986ab12SMaksim Yevmenkin 142a4b187faSMaksim Yevmenkin xs = sdp_open(NG_HCI_BDADDR_ANY, bdaddr); 143a4b187faSMaksim Yevmenkin } else 144a4b187faSMaksim Yevmenkin xs = sdp_open_local(control); 1450986ab12SMaksim Yevmenkin 146a4b187faSMaksim Yevmenkin if (xs == NULL) 147a4b187faSMaksim Yevmenkin errx(1, "Could not create SDP session object"); 1480986ab12SMaksim Yevmenkin if (sdp_error(xs) == 0) 1490986ab12SMaksim Yevmenkin e = (c->handler)(xs, -- argc, ++ argv); 1500986ab12SMaksim Yevmenkin else 1510986ab12SMaksim Yevmenkin e = ERROR; 1520986ab12SMaksim Yevmenkin } else 1530986ab12SMaksim Yevmenkin e = USAGE; 1540986ab12SMaksim Yevmenkin 1550986ab12SMaksim Yevmenkin switch (e) { 1560986ab12SMaksim Yevmenkin case OK: 1570986ab12SMaksim Yevmenkin case FAILED: 1580986ab12SMaksim Yevmenkin break; 1590986ab12SMaksim Yevmenkin 1600986ab12SMaksim Yevmenkin case ERROR: 1610986ab12SMaksim Yevmenkin fprintf(stdout, "Could not execute command \"%s\". %s\n", 1620986ab12SMaksim Yevmenkin cmd, strerror(sdp_error(xs))); 1630986ab12SMaksim Yevmenkin break; 1640986ab12SMaksim Yevmenkin 1650986ab12SMaksim Yevmenkin case USAGE: 1660986ab12SMaksim Yevmenkin fprintf(stdout, "Usage: %s\n%s\n", c->command, c->description); 1670986ab12SMaksim Yevmenkin break; 1680986ab12SMaksim Yevmenkin 1690986ab12SMaksim Yevmenkin default: assert(0); break; 1700986ab12SMaksim Yevmenkin } 1710986ab12SMaksim Yevmenkin 1720986ab12SMaksim Yevmenkin sdp_close(xs); 1730986ab12SMaksim Yevmenkin 1740986ab12SMaksim Yevmenkin return (e); 1750986ab12SMaksim Yevmenkin } /* do_sdp_command */ 1760986ab12SMaksim Yevmenkin 1770986ab12SMaksim Yevmenkin /* Try to find command in specified category */ 1780986ab12SMaksim Yevmenkin static struct sdp_command * 1790986ab12SMaksim Yevmenkin find_sdp_command(char const *command, struct sdp_command *category) 1800986ab12SMaksim Yevmenkin { 1810986ab12SMaksim Yevmenkin struct sdp_command *c = NULL; 1820986ab12SMaksim Yevmenkin 1830986ab12SMaksim Yevmenkin for (c = category; c->command != NULL; c++) { 1840986ab12SMaksim Yevmenkin char *c_end = strchr(c->command, ' '); 1850986ab12SMaksim Yevmenkin 1860986ab12SMaksim Yevmenkin if (c_end != NULL) { 1870986ab12SMaksim Yevmenkin int len = c_end - c->command; 1880986ab12SMaksim Yevmenkin 1890986ab12SMaksim Yevmenkin if (strncasecmp(command, c->command, len) == 0) 1900986ab12SMaksim Yevmenkin return (c); 1910986ab12SMaksim Yevmenkin } else if (strcasecmp(command, c->command) == 0) 1920986ab12SMaksim Yevmenkin return (c); 1930986ab12SMaksim Yevmenkin } 1940986ab12SMaksim Yevmenkin 1950986ab12SMaksim Yevmenkin return (NULL); 1960986ab12SMaksim Yevmenkin } /* find_sdp_command */ 1970986ab12SMaksim Yevmenkin 1980986ab12SMaksim Yevmenkin /* Print commands in specified category */ 1990986ab12SMaksim Yevmenkin static void 2000986ab12SMaksim Yevmenkin print_sdp_command(struct sdp_command *category) 2010986ab12SMaksim Yevmenkin { 2020986ab12SMaksim Yevmenkin struct sdp_command *c = NULL; 2030986ab12SMaksim Yevmenkin 2040986ab12SMaksim Yevmenkin for (c = category; c->command != NULL; c++) 2050986ab12SMaksim Yevmenkin fprintf(stdout, "\t%s\n", c->command); 2060986ab12SMaksim Yevmenkin } /* print_sdp_command */ 2070986ab12SMaksim Yevmenkin 2080986ab12SMaksim Yevmenkin /* Usage */ 2090986ab12SMaksim Yevmenkin static void 2100986ab12SMaksim Yevmenkin usage(void) 2110986ab12SMaksim Yevmenkin { 212a4b187faSMaksim Yevmenkin fprintf(stderr, 213a4b187faSMaksim Yevmenkin "Usage: sdpcontrol options command\n" \ 214a4b187faSMaksim Yevmenkin "Where options are:\n" 2152aa65cf7SMaksim Yevmenkin " -a address address to connect to\n" \ 216a4b187faSMaksim Yevmenkin " -c path path to the control socket (default is %s)\n" \ 217a4b187faSMaksim Yevmenkin " -h display usage and quit\n" \ 218a4b187faSMaksim Yevmenkin " -l connect to the local SDP server via control socket\n" \ 219a4b187faSMaksim Yevmenkin " command one of the supported commands\n", SDP_LOCAL_PATH); 2200986ab12SMaksim Yevmenkin exit(255); 2210986ab12SMaksim Yevmenkin } /* usage */ 2220986ab12SMaksim Yevmenkin 223