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