1107120Sjulian/* 2107120Sjulian * l2control.c 3107120Sjulian * 4107120Sjulian * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5107120Sjulian * All rights reserved. 6107120Sjulian * 7107120Sjulian * Redistribution and use in source and binary forms, with or without 8107120Sjulian * modification, are permitted provided that the following conditions 9107120Sjulian * are met: 10107120Sjulian * 1. Redistributions of source code must retain the above copyright 11107120Sjulian * notice, this list of conditions and the following disclaimer. 12107120Sjulian * 2. Redistributions in binary form must reproduce the above copyright 13107120Sjulian * notice, this list of conditions and the following disclaimer in the 14107120Sjulian * documentation and/or other materials provided with the distribution. 15107120Sjulian * 16107120Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17107120Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18107120Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19107120Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20107120Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21107120Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22107120Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23107120Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24107120Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25107120Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26107120Sjulian * SUCH DAMAGE. 27107120Sjulian * 28121054Semax * $Id: l2control.c,v 1.6 2003/09/05 00:38:25 max Exp $ 29107120Sjulian * $FreeBSD$ 30107120Sjulian */ 31107120Sjulian 32107120Sjulian#include <assert.h> 33121054Semax#include <bluetooth.h> 34107120Sjulian#include <err.h> 35107120Sjulian#include <errno.h> 36107120Sjulian#include <stdio.h> 37107120Sjulian#include <stdlib.h> 38107120Sjulian#include <string.h> 39107120Sjulian#include <unistd.h> 40107120Sjulian#include "l2control.h" 41107120Sjulian 42107120Sjulian/* Prototypes */ 43107120Sjulianstatic int do_l2cap_command (bdaddr_p, int, char **); 44107120Sjulianstatic struct l2cap_command * find_l2cap_command (char const *, 45107120Sjulian struct l2cap_command *); 46107120Sjulianstatic void print_l2cap_command (struct l2cap_command *); 47107120Sjulianstatic void usage (void); 48107120Sjulian 49107120Sjulian/* Main */ 50121054Semax 51121054Semaxint numeric_bdaddr = 0; 52121054Semax 53107120Sjulianint 54107120Sjulianmain(int argc, char *argv[]) 55107120Sjulian{ 56107120Sjulian int n; 57107120Sjulian bdaddr_t bdaddr; 58107120Sjulian 59107120Sjulian memset(&bdaddr, 0, sizeof(bdaddr)); 60107120Sjulian 61107120Sjulian /* Process command line arguments */ 62121054Semax while ((n = getopt(argc, argv, "a:nh")) != -1) { 63107120Sjulian switch (n) { 64121054Semax case 'a': 65121054Semax if (!bt_aton(optarg, &bdaddr)) { 66121054Semax struct hostent *he = NULL; 67107120Sjulian 68121054Semax if ((he = bt_gethostbyname(optarg)) == NULL) 69121054Semax errx(1, "%s: %s", optarg, hstrerror(h_errno)); 70121054Semax 71121054Semax memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); 72107120Sjulian } 73121054Semax break; 74107120Sjulian 75121054Semax case 'n': 76121054Semax numeric_bdaddr = 1; 77121054Semax break; 78107120Sjulian 79114879Sjulian case 'h': 80107120Sjulian default: 81107120Sjulian usage(); 82107120Sjulian break; 83107120Sjulian } 84107120Sjulian } 85107120Sjulian 86107120Sjulian argc -= optind; 87107120Sjulian argv += optind; 88107120Sjulian 89107120Sjulian if (*argv == NULL) 90107120Sjulian usage(); 91107120Sjulian 92107120Sjulian return (do_l2cap_command(&bdaddr, argc, argv)); 93107120Sjulian} /* main */ 94107120Sjulian 95107120Sjulian/* Execute commands */ 96107120Sjulianstatic int 97107120Sjuliando_l2cap_command(bdaddr_p bdaddr, int argc, char **argv) 98107120Sjulian{ 99107120Sjulian char *cmd = argv[0]; 100107120Sjulian struct l2cap_command *c = NULL; 101107120Sjulian struct sockaddr_l2cap sa; 102107120Sjulian int s, e, help; 103107120Sjulian 104107120Sjulian help = 0; 105107120Sjulian if (strcasecmp(cmd, "help") == 0) { 106107120Sjulian argc --; 107107120Sjulian argv ++; 108107120Sjulian 109107120Sjulian if (argc <= 0) { 110107120Sjulian fprintf(stdout, "Supported commands:\n"); 111107120Sjulian print_l2cap_command(l2cap_commands); 112107120Sjulian fprintf(stdout, "\nFor more information use " \ 113107120Sjulian "'help command'\n"); 114107120Sjulian 115107120Sjulian return (OK); 116107120Sjulian } 117107120Sjulian 118107120Sjulian help = 1; 119107120Sjulian cmd = argv[0]; 120107120Sjulian } 121107120Sjulian 122107120Sjulian c = find_l2cap_command(cmd, l2cap_commands); 123107120Sjulian if (c == NULL) { 124107120Sjulian fprintf(stdout, "Unknown command: \"%s\"\n", cmd); 125107120Sjulian return (ERROR); 126107120Sjulian } 127107120Sjulian 128107120Sjulian if (!help) { 129107120Sjulian if (memcmp(bdaddr, NG_HCI_BDADDR_ANY, sizeof(*bdaddr)) == 0) 130107120Sjulian usage(); 131107120Sjulian 132107120Sjulian memset(&sa, 0, sizeof(sa)); 133107120Sjulian sa.l2cap_len = sizeof(sa); 134107120Sjulian sa.l2cap_family = AF_BLUETOOTH; 135107120Sjulian memcpy(&sa.l2cap_bdaddr, bdaddr, sizeof(sa.l2cap_bdaddr)); 136107120Sjulian 137107120Sjulian s = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_L2CAP); 138107120Sjulian if (s < 0) 139107120Sjulian err(1, "Could not create socket"); 140107120Sjulian 141107120Sjulian if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) 142107120Sjulian err(2, 143121054Semax"Could not bind socket, bdaddr=%s", bt_ntoa(&sa.l2cap_bdaddr, NULL)); 144107120Sjulian 145107120Sjulian e = 0x0ffff; 146107120Sjulian if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &e, sizeof(e)) < 0) 147107120Sjulian err(3, "Coult not setsockopt(RCVBUF, %d)", e); 148107120Sjulian 149107120Sjulian e = (c->handler)(s, -- argc, ++ argv); 150107120Sjulian 151107120Sjulian close(s); 152107120Sjulian } else 153107120Sjulian e = USAGE; 154107120Sjulian 155107120Sjulian switch (e) { 156107120Sjulian case OK: 157107120Sjulian case FAILED: 158107120Sjulian break; 159107120Sjulian 160107120Sjulian case ERROR: 161107120Sjulian fprintf(stdout, "Could not execute command \"%s\". %s\n", 162107120Sjulian cmd, strerror(errno)); 163107120Sjulian break; 164107120Sjulian 165107120Sjulian case USAGE: 166107120Sjulian fprintf(stdout, "Usage: %s\n%s\n", c->command, c->description); 167107120Sjulian break; 168107120Sjulian 169107120Sjulian default: assert(0); break; 170107120Sjulian } 171107120Sjulian 172107120Sjulian return (e); 173107120Sjulian} /* do_l2cap_command */ 174107120Sjulian 175107120Sjulian/* Try to find command in specified category */ 176107120Sjulianstatic struct l2cap_command * 177107120Sjulianfind_l2cap_command(char const *command, struct l2cap_command *category) 178107120Sjulian{ 179107120Sjulian struct l2cap_command *c = NULL; 180107120Sjulian 181107120Sjulian for (c = category; c->command != NULL; c++) { 182107120Sjulian char *c_end = strchr(c->command, ' '); 183107120Sjulian 184107120Sjulian if (c_end != NULL) { 185107120Sjulian int len = c_end - c->command; 186107120Sjulian 187107120Sjulian if (strncasecmp(command, c->command, len) == 0) 188107120Sjulian return (c); 189107120Sjulian } else if (strcasecmp(command, c->command) == 0) 190107120Sjulian return (c); 191107120Sjulian } 192107120Sjulian 193107120Sjulian return (NULL); 194107120Sjulian} /* find_l2cap_command */ 195107120Sjulian 196121054Semax/* Print commands in specified category */ 197107120Sjulianstatic void 198107120Sjulianprint_l2cap_command(struct l2cap_command *category) 199107120Sjulian{ 200107120Sjulian struct l2cap_command *c = NULL; 201107120Sjulian 202107120Sjulian for (c = category; c->command != NULL; c++) 203107120Sjulian fprintf(stdout, "\t%s\n", c->command); 204107120Sjulian} /* print_l2cap_command */ 205107120Sjulian 206107120Sjulian/* Usage */ 207107120Sjulianstatic void 208107120Sjulianusage(void) 209107120Sjulian{ 210220840Semax fprintf(stderr, "Usage: l2control [-hn] -a local cmd [params ..]\n"); 211220840Semax fprintf(stderr, "Where:\n"); 212220840Semax fprintf(stderr, " -a local Specify local device to connect to\n"); 213220840Semax fprintf(stderr, " -h Display this message\n"); 214220840Semax fprintf(stderr, " -n Show addresses as numbers\n"); 215220840Semax fprintf(stderr, " cmd Supported command " \ 216220840Semax "(see l2control help)\n"); 217220840Semax fprintf(stderr, " params Optional command parameters\n"); 218107120Sjulian exit(255); 219107120Sjulian} /* usage */ 220107120Sjulian 221