1878ed226SJulian Elischer /* 2878ed226SJulian Elischer * l2control.c 3878ed226SJulian Elischer * 4878ed226SJulian Elischer * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5878ed226SJulian Elischer * All rights reserved. 6878ed226SJulian Elischer * 7878ed226SJulian Elischer * Redistribution and use in source and binary forms, with or without 8878ed226SJulian Elischer * modification, are permitted provided that the following conditions 9878ed226SJulian Elischer * are met: 10878ed226SJulian Elischer * 1. Redistributions of source code must retain the above copyright 11878ed226SJulian Elischer * notice, this list of conditions and the following disclaimer. 12878ed226SJulian Elischer * 2. Redistributions in binary form must reproduce the above copyright 13878ed226SJulian Elischer * notice, this list of conditions and the following disclaimer in the 14878ed226SJulian Elischer * documentation and/or other materials provided with the distribution. 15878ed226SJulian Elischer * 16878ed226SJulian Elischer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17878ed226SJulian Elischer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18878ed226SJulian Elischer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19878ed226SJulian Elischer * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20878ed226SJulian Elischer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21878ed226SJulian Elischer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22878ed226SJulian Elischer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23878ed226SJulian Elischer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24878ed226SJulian Elischer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25878ed226SJulian Elischer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26878ed226SJulian Elischer * SUCH DAMAGE. 27878ed226SJulian Elischer * 280986ab12SMaksim Yevmenkin * $Id: l2control.c,v 1.6 2003/09/05 00:38:25 max Exp $ 29878ed226SJulian Elischer * $FreeBSD$ 30878ed226SJulian Elischer */ 31878ed226SJulian Elischer 32878ed226SJulian Elischer #include <assert.h> 330986ab12SMaksim Yevmenkin #include <bluetooth.h> 34878ed226SJulian Elischer #include <err.h> 35878ed226SJulian Elischer #include <errno.h> 36878ed226SJulian Elischer #include <stdio.h> 37878ed226SJulian Elischer #include <stdlib.h> 38878ed226SJulian Elischer #include <string.h> 39878ed226SJulian Elischer #include <unistd.h> 40878ed226SJulian Elischer #include "l2control.h" 41878ed226SJulian Elischer 42878ed226SJulian Elischer /* Prototypes */ 43878ed226SJulian Elischer static int do_l2cap_command (bdaddr_p, int, char **); 44878ed226SJulian Elischer static struct l2cap_command * find_l2cap_command (char const *, 45878ed226SJulian Elischer struct l2cap_command *); 46878ed226SJulian Elischer static void print_l2cap_command (struct l2cap_command *); 47878ed226SJulian Elischer static void usage (void); 48878ed226SJulian Elischer 49878ed226SJulian Elischer /* Main */ 500986ab12SMaksim Yevmenkin 510986ab12SMaksim Yevmenkin int numeric_bdaddr = 0; 520986ab12SMaksim Yevmenkin 53878ed226SJulian Elischer int 54878ed226SJulian Elischer main(int argc, char *argv[]) 55878ed226SJulian Elischer { 56878ed226SJulian Elischer int n; 57878ed226SJulian Elischer bdaddr_t bdaddr; 58878ed226SJulian Elischer 59878ed226SJulian Elischer memset(&bdaddr, 0, sizeof(bdaddr)); 60878ed226SJulian Elischer 61878ed226SJulian Elischer /* Process command line arguments */ 620986ab12SMaksim Yevmenkin while ((n = getopt(argc, argv, "a:nh")) != -1) { 63878ed226SJulian Elischer switch (n) { 640986ab12SMaksim Yevmenkin case 'a': 650986ab12SMaksim Yevmenkin if (!bt_aton(optarg, &bdaddr)) { 660986ab12SMaksim Yevmenkin struct hostent *he = NULL; 67878ed226SJulian Elischer 680986ab12SMaksim Yevmenkin if ((he = bt_gethostbyname(optarg)) == NULL) 690986ab12SMaksim Yevmenkin errx(1, "%s: %s", optarg, hstrerror(h_errno)); 700986ab12SMaksim Yevmenkin 710986ab12SMaksim Yevmenkin memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); 72878ed226SJulian Elischer } 730986ab12SMaksim Yevmenkin break; 74878ed226SJulian Elischer 750986ab12SMaksim Yevmenkin case 'n': 760986ab12SMaksim Yevmenkin numeric_bdaddr = 1; 770986ab12SMaksim Yevmenkin break; 78878ed226SJulian Elischer 791a63eb31SJulian Elischer case 'h': 80878ed226SJulian Elischer default: 81878ed226SJulian Elischer usage(); 82878ed226SJulian Elischer break; 83878ed226SJulian Elischer } 84878ed226SJulian Elischer } 85878ed226SJulian Elischer 86878ed226SJulian Elischer argc -= optind; 87878ed226SJulian Elischer argv += optind; 88878ed226SJulian Elischer 89878ed226SJulian Elischer if (*argv == NULL) 90878ed226SJulian Elischer usage(); 91878ed226SJulian Elischer 92878ed226SJulian Elischer return (do_l2cap_command(&bdaddr, argc, argv)); 93878ed226SJulian Elischer } /* main */ 94878ed226SJulian Elischer 95878ed226SJulian Elischer /* Execute commands */ 96878ed226SJulian Elischer static int 97878ed226SJulian Elischer do_l2cap_command(bdaddr_p bdaddr, int argc, char **argv) 98878ed226SJulian Elischer { 99878ed226SJulian Elischer char *cmd = argv[0]; 100878ed226SJulian Elischer struct l2cap_command *c = NULL; 101878ed226SJulian Elischer struct sockaddr_l2cap sa; 102878ed226SJulian Elischer int s, e, help; 103878ed226SJulian Elischer 104878ed226SJulian Elischer help = 0; 105878ed226SJulian Elischer if (strcasecmp(cmd, "help") == 0) { 106878ed226SJulian Elischer argc --; 107878ed226SJulian Elischer argv ++; 108878ed226SJulian Elischer 109878ed226SJulian Elischer if (argc <= 0) { 110878ed226SJulian Elischer fprintf(stdout, "Supported commands:\n"); 111878ed226SJulian Elischer print_l2cap_command(l2cap_commands); 112878ed226SJulian Elischer fprintf(stdout, "\nFor more information use " \ 113878ed226SJulian Elischer "'help command'\n"); 114878ed226SJulian Elischer 115878ed226SJulian Elischer return (OK); 116878ed226SJulian Elischer } 117878ed226SJulian Elischer 118878ed226SJulian Elischer help = 1; 119878ed226SJulian Elischer cmd = argv[0]; 120878ed226SJulian Elischer } 121878ed226SJulian Elischer 122878ed226SJulian Elischer c = find_l2cap_command(cmd, l2cap_commands); 123878ed226SJulian Elischer if (c == NULL) { 124878ed226SJulian Elischer fprintf(stdout, "Unknown command: \"%s\"\n", cmd); 125878ed226SJulian Elischer return (ERROR); 126878ed226SJulian Elischer } 127878ed226SJulian Elischer 128878ed226SJulian Elischer if (!help) { 129878ed226SJulian Elischer if (memcmp(bdaddr, NG_HCI_BDADDR_ANY, sizeof(*bdaddr)) == 0) 130878ed226SJulian Elischer usage(); 131878ed226SJulian Elischer 132878ed226SJulian Elischer memset(&sa, 0, sizeof(sa)); 133878ed226SJulian Elischer sa.l2cap_len = sizeof(sa); 134878ed226SJulian Elischer sa.l2cap_family = AF_BLUETOOTH; 135878ed226SJulian Elischer memcpy(&sa.l2cap_bdaddr, bdaddr, sizeof(sa.l2cap_bdaddr)); 136878ed226SJulian Elischer 137878ed226SJulian Elischer s = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_L2CAP); 138878ed226SJulian Elischer if (s < 0) 139878ed226SJulian Elischer err(1, "Could not create socket"); 140878ed226SJulian Elischer 141878ed226SJulian Elischer if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) 142878ed226SJulian Elischer err(2, 1430986ab12SMaksim Yevmenkin "Could not bind socket, bdaddr=%s", bt_ntoa(&sa.l2cap_bdaddr, NULL)); 144878ed226SJulian Elischer 145878ed226SJulian Elischer e = 0x0ffff; 146878ed226SJulian Elischer if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &e, sizeof(e)) < 0) 147878ed226SJulian Elischer err(3, "Coult not setsockopt(RCVBUF, %d)", e); 148878ed226SJulian Elischer 149878ed226SJulian Elischer e = (c->handler)(s, -- argc, ++ argv); 150878ed226SJulian Elischer 151878ed226SJulian Elischer close(s); 152878ed226SJulian Elischer } else 153878ed226SJulian Elischer e = USAGE; 154878ed226SJulian Elischer 155878ed226SJulian Elischer switch (e) { 156878ed226SJulian Elischer case OK: 157878ed226SJulian Elischer case FAILED: 158878ed226SJulian Elischer break; 159878ed226SJulian Elischer 160878ed226SJulian Elischer case ERROR: 161878ed226SJulian Elischer fprintf(stdout, "Could not execute command \"%s\". %s\n", 162878ed226SJulian Elischer cmd, strerror(errno)); 163878ed226SJulian Elischer break; 164878ed226SJulian Elischer 165878ed226SJulian Elischer case USAGE: 166878ed226SJulian Elischer fprintf(stdout, "Usage: %s\n%s\n", c->command, c->description); 167878ed226SJulian Elischer break; 168878ed226SJulian Elischer 169878ed226SJulian Elischer default: assert(0); break; 170878ed226SJulian Elischer } 171878ed226SJulian Elischer 172878ed226SJulian Elischer return (e); 173878ed226SJulian Elischer } /* do_l2cap_command */ 174878ed226SJulian Elischer 175878ed226SJulian Elischer /* Try to find command in specified category */ 176878ed226SJulian Elischer static struct l2cap_command * 177878ed226SJulian Elischer find_l2cap_command(char const *command, struct l2cap_command *category) 178878ed226SJulian Elischer { 179878ed226SJulian Elischer struct l2cap_command *c = NULL; 180878ed226SJulian Elischer 181878ed226SJulian Elischer for (c = category; c->command != NULL; c++) { 182878ed226SJulian Elischer char *c_end = strchr(c->command, ' '); 183878ed226SJulian Elischer 184878ed226SJulian Elischer if (c_end != NULL) { 185878ed226SJulian Elischer int len = c_end - c->command; 186878ed226SJulian Elischer 187878ed226SJulian Elischer if (strncasecmp(command, c->command, len) == 0) 188878ed226SJulian Elischer return (c); 189878ed226SJulian Elischer } else if (strcasecmp(command, c->command) == 0) 190878ed226SJulian Elischer return (c); 191878ed226SJulian Elischer } 192878ed226SJulian Elischer 193878ed226SJulian Elischer return (NULL); 194878ed226SJulian Elischer } /* find_l2cap_command */ 195878ed226SJulian Elischer 1960986ab12SMaksim Yevmenkin /* Print commands in specified category */ 197878ed226SJulian Elischer static void 198878ed226SJulian Elischer print_l2cap_command(struct l2cap_command *category) 199878ed226SJulian Elischer { 200878ed226SJulian Elischer struct l2cap_command *c = NULL; 201878ed226SJulian Elischer 202878ed226SJulian Elischer for (c = category; c->command != NULL; c++) 203878ed226SJulian Elischer fprintf(stdout, "\t%s\n", c->command); 204878ed226SJulian Elischer } /* print_l2cap_command */ 205878ed226SJulian Elischer 206878ed226SJulian Elischer /* Usage */ 207878ed226SJulian Elischer static void 208878ed226SJulian Elischer usage(void) 209878ed226SJulian Elischer { 210*9c6d3b9fSMaksim Yevmenkin fprintf(stderr, "Usage: l2control [-hn] -a local cmd [params ..]\n"); 211*9c6d3b9fSMaksim Yevmenkin fprintf(stderr, "Where:\n"); 212*9c6d3b9fSMaksim Yevmenkin fprintf(stderr, " -a local Specify local device to connect to\n"); 213*9c6d3b9fSMaksim Yevmenkin fprintf(stderr, " -h Display this message\n"); 214*9c6d3b9fSMaksim Yevmenkin fprintf(stderr, " -n Show addresses as numbers\n"); 215*9c6d3b9fSMaksim Yevmenkin fprintf(stderr, " cmd Supported command " \ 216*9c6d3b9fSMaksim Yevmenkin "(see l2control help)\n"); 217*9c6d3b9fSMaksim Yevmenkin fprintf(stderr, " params Optional command parameters\n"); 218878ed226SJulian Elischer exit(255); 219878ed226SJulian Elischer } /* usage */ 220878ed226SJulian Elischer 221