l2control.c revision 121054
1251875Speter/* 2251875Speter * l2control.c 3251875Speter * 4251875Speter * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5251875Speter * All rights reserved. 6251875Speter * 7251875Speter * Redistribution and use in source and binary forms, with or without 8251875Speter * modification, are permitted provided that the following conditions 9251875Speter * are met: 10251875Speter * 1. Redistributions of source code must retain the above copyright 11251875Speter * notice, this list of conditions and the following disclaimer. 12251875Speter * 2. Redistributions in binary form must reproduce the above copyright 13251875Speter * notice, this list of conditions and the following disclaimer in the 14251875Speter * documentation and/or other materials provided with the distribution. 15251875Speter * 16251875Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17251875Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18251875Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19251875Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20251875Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21251875Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22251875Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23251875Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24251875Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25251875Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26251875Speter * SUCH DAMAGE. 27251875Speter * 28251875Speter * $Id: l2control.c,v 1.6 2003/09/05 00:38:25 max Exp $ 29251875Speter * $FreeBSD: head/usr.sbin/bluetooth/l2control/l2control.c 121054 2003-10-12 22:04:24Z emax $ 30251875Speter */ 31251875Speter 32251875Speter#include <assert.h> 33251875Speter#include <bluetooth.h> 34251875Speter#include <err.h> 35251875Speter#include <errno.h> 36251875Speter#include <stdio.h> 37251875Speter#include <stdlib.h> 38251875Speter#include <string.h> 39251875Speter#include <unistd.h> 40251875Speter#include "l2control.h" 41251875Speter 42251875Speter/* Prototypes */ 43251875Speterstatic int do_l2cap_command (bdaddr_p, int, char **); 44251875Speterstatic struct l2cap_command * find_l2cap_command (char const *, 45251875Speter struct l2cap_command *); 46251875Speterstatic void print_l2cap_command (struct l2cap_command *); 47251875Speterstatic void usage (void); 48251875Speter 49251875Speter/* Main */ 50251875Speter 51251875Speterint numeric_bdaddr = 0; 52251875Speter 53251875Speterint 54251875Spetermain(int argc, char *argv[]) 55251875Speter{ 56251875Speter int n; 57251875Speter bdaddr_t bdaddr; 58251875Speter 59251875Speter memset(&bdaddr, 0, sizeof(bdaddr)); 60251875Speter 61251875Speter /* Process command line arguments */ 62251875Speter while ((n = getopt(argc, argv, "a:nh")) != -1) { 63251875Speter switch (n) { 64251875Speter case 'a': 65251875Speter if (!bt_aton(optarg, &bdaddr)) { 66251875Speter struct hostent *he = NULL; 67251875Speter 68251875Speter if ((he = bt_gethostbyname(optarg)) == NULL) 69251875Speter errx(1, "%s: %s", optarg, hstrerror(h_errno)); 70251875Speter 71251875Speter memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); 72251875Speter } 73251875Speter break; 74251875Speter 75251875Speter case 'n': 76251875Speter numeric_bdaddr = 1; 77251875Speter break; 78251875Speter 79251875Speter case 'h': 80251875Speter default: 81251875Speter usage(); 82251875Speter break; 83251875Speter } 84251875Speter } 85251875Speter 86251875Speter argc -= optind; 87251875Speter argv += optind; 88251875Speter 89251875Speter if (*argv == NULL) 90251875Speter usage(); 91251875Speter 92251875Speter return (do_l2cap_command(&bdaddr, argc, argv)); 93251875Speter} /* main */ 94251875Speter 95251875Speter/* Execute commands */ 96251875Speterstatic int 97251875Speterdo_l2cap_command(bdaddr_p bdaddr, int argc, char **argv) 98251875Speter{ 99251875Speter char *cmd = argv[0]; 100251875Speter struct l2cap_command *c = NULL; 101251875Speter struct sockaddr_l2cap sa; 102251875Speter int s, e, help; 103251875Speter 104251875Speter help = 0; 105251875Speter if (strcasecmp(cmd, "help") == 0) { 106251875Speter argc --; 107251875Speter argv ++; 108251875Speter 109251875Speter if (argc <= 0) { 110251875Speter fprintf(stdout, "Supported commands:\n"); 111251875Speter print_l2cap_command(l2cap_commands); 112251875Speter fprintf(stdout, "\nFor more information use " \ 113251875Speter "'help command'\n"); 114251875Speter 115251875Speter return (OK); 116251875Speter } 117251875Speter 118251875Speter help = 1; 119251875Speter cmd = argv[0]; 120251875Speter } 121251875Speter 122251875Speter c = find_l2cap_command(cmd, l2cap_commands); 123251875Speter if (c == NULL) { 124251875Speter fprintf(stdout, "Unknown command: \"%s\"\n", cmd); 125251875Speter return (ERROR); 126251875Speter } 127251875Speter 128251875Speter if (!help) { 129251875Speter if (memcmp(bdaddr, NG_HCI_BDADDR_ANY, sizeof(*bdaddr)) == 0) 130251875Speter usage(); 131251875Speter 132251875Speter memset(&sa, 0, sizeof(sa)); 133251875Speter sa.l2cap_len = sizeof(sa); 134251875Speter sa.l2cap_family = AF_BLUETOOTH; 135251875Speter memcpy(&sa.l2cap_bdaddr, bdaddr, sizeof(sa.l2cap_bdaddr)); 136251875Speter 137251875Speter s = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_L2CAP); 138251875Speter if (s < 0) 139251875Speter err(1, "Could not create socket"); 140251875Speter 141251875Speter if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) 142251875Speter err(2, 143251875Speter"Could not bind socket, bdaddr=%s", bt_ntoa(&sa.l2cap_bdaddr, NULL)); 144251875Speter 145251875Speter e = 0x0ffff; 146251875Speter if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &e, sizeof(e)) < 0) 147251875Speter err(3, "Coult not setsockopt(RCVBUF, %d)", e); 148251875Speter 149251875Speter e = (c->handler)(s, -- argc, ++ argv); 150251875Speter 151251875Speter close(s); 152251875Speter } else 153251875Speter e = USAGE; 154251875Speter 155251875Speter switch (e) { 156251875Speter case OK: 157251875Speter case FAILED: 158251875Speter break; 159251875Speter 160251875Speter case ERROR: 161251875Speter fprintf(stdout, "Could not execute command \"%s\". %s\n", 162251875Speter cmd, strerror(errno)); 163251875Speter break; 164251875Speter 165251875Speter case USAGE: 166251875Speter fprintf(stdout, "Usage: %s\n%s\n", c->command, c->description); 167251875Speter break; 168251875Speter 169251875Speter default: assert(0); break; 170251875Speter } 171251875Speter 172251875Speter return (e); 173251875Speter} /* do_l2cap_command */ 174251875Speter 175251875Speter/* Try to find command in specified category */ 176251875Speterstatic struct l2cap_command * 177251875Speterfind_l2cap_command(char const *command, struct l2cap_command *category) 178251875Speter{ 179251875Speter struct l2cap_command *c = NULL; 180251875Speter 181251875Speter for (c = category; c->command != NULL; c++) { 182251875Speter char *c_end = strchr(c->command, ' '); 183251875Speter 184251875Speter if (c_end != NULL) { 185251875Speter int len = c_end - c->command; 186251875Speter 187251875Speter if (strncasecmp(command, c->command, len) == 0) 188251875Speter return (c); 189251875Speter } else if (strcasecmp(command, c->command) == 0) 190251875Speter return (c); 191251875Speter } 192251875Speter 193251875Speter return (NULL); 194251875Speter} /* find_l2cap_command */ 195251875Speter 196251875Speter/* Print commands in specified category */ 197251875Speterstatic void 198251875Speterprint_l2cap_command(struct l2cap_command *category) 199251875Speter{ 200251875Speter struct l2cap_command *c = NULL; 201251875Speter 202251875Speter for (c = category; c->command != NULL; c++) 203251875Speter fprintf(stdout, "\t%s\n", c->command); 204251875Speter} /* print_l2cap_command */ 205251875Speter 206251875Speter/* Usage */ 207251875Speterstatic void 208251875Speterusage(void) 209251875Speter{ 210251875Speter fprintf(stdout, "Usage: l2control -a BD_ADDR [-n] [-h] cmd [p1] [..]]\n"); 211251875Speter exit(255); 212251875Speter} /* usage */ 213251875Speter 214251875Speter