diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2013-12-30 23:34:18 -0800 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2013-12-30 23:35:23 -0800 |
commit | 98921e1bd50814e781de9e6c7274d2231dd1bb0f (patch) | |
tree | e7dffeb5e7b43a5eee837e6d1d86645c9e2db675 /tools/btproxy.c | |
parent | 15097d34e1fa1ecdbd90fe1beaf0870528cf8bbd (diff) | |
download | bluez-98921e1bd50814e781de9e6c7274d2231dd1bb0f.tar.gz |
tools: Add support for connecting to proxying servers
Diffstat (limited to 'tools/btproxy.c')
-rw-r--r-- | tools/btproxy.c | 168 |
1 files changed, 137 insertions, 31 deletions
diff --git a/tools/btproxy.c b/tools/btproxy.c index 139788d31..537d794b8 100644 --- a/tools/btproxy.c +++ b/tools/btproxy.c @@ -105,13 +105,13 @@ static void channel_callback(int fd, uint32_t events, void *user_data) } len = read(channel_fd, buf, sizeof(buf)); - if (len < 1) { + if (len < 0) { fprintf(stderr, "Failed to read channel packet\n"); return; } written = write(client_fd, buf, len); - if (written < 1) { + if (written < 0) { fprintf(stderr, "Failed to write to unix socket\n"); return; } @@ -135,13 +135,16 @@ static void client_callback(int fd, uint32_t events, void *user_data) len = read(client_fd, client_buffer + client_length, sizeof(client_buffer) - client_length); - if (len < 1) { + if (len < 0) { fprintf(stderr, "Failed to read client packet\n"); return; } client_length += len; + if (client_length < 1) + return; + switch (client_buffer[0]) { case BT_H4_CMD_PKT: { @@ -176,8 +179,24 @@ static void client_callback(int fd, uint32_t events, void *user_data) pktlen = 1 + sizeof(*hdr) + hdr->dlen; } break; + case BT_H4_EVT_PKT: + { + struct bt_hci_evt_hdr *hdr; + + if (client_length < 1 + sizeof(*hdr)) + return; + + hdr = (void *) (client_buffer + 1); + pktlen = 1 + sizeof(*hdr) + hdr->plen; + } + break; + case 0xff: + client_length = 0; + return; default: - fprintf(stderr, "Received wrong packet type\n"); + fprintf(stderr, "Received wrong packet type 0x%02x\n", + client_buffer[0]); + client_length = 0; return; } @@ -289,7 +308,7 @@ static int open_unix(const char *path) return fd; } -static int open_tcp(unsigned int port) +static int open_tcp(const char *address, unsigned int port) { struct sockaddr_in addr; int fd, opt = 1; @@ -304,7 +323,7 @@ static int open_tcp(unsigned int port) memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_addr.s_addr = inet_addr(address); addr.sin_port = htons(port); if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { @@ -322,6 +341,53 @@ static int open_tcp(unsigned int port) return fd; } +static int connect_tcp(const char *address, unsigned int port) +{ + struct sockaddr_in addr; + int fd; + + fd = socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (fd < 0) { + perror("Failed to open TCP client socket"); + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(address); + addr.sin_port = htons(port); + + if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + perror("Failed to connect TCP client socket"); + close(fd); + return -1; + } + + return fd; +} + +static int open_vhci(uint8_t type) +{ + uint8_t create_req[2] = { 0xff, type }; + ssize_t written; + int fd; + + fd = open("/dev/vhci", O_RDWR | O_CLOEXEC); + if (fd < 0) { + perror("Failed to open /dev/vhci device"); + return -1; + } + + written = write(fd, create_req, sizeof(create_req)); + if (written < 0) { + perror("Failed to set device type"); + close(fd); + return -1; + } + + return fd; +} + static void signal_callback(int signum, void *user_data) { switch (signum) { @@ -338,15 +404,19 @@ static void usage(void) "Usage:\n"); printf("\tbtproxy [options]\n"); printf("options:\n" - "\t-u, --unix [unixpath] Use unix server\n" - "\t-p, --port [port] Use TCP server\n" - "\t-i, --index <num> Use specified controller\n" - "\t-h, --help Show help options\n"); + "\t-c, --connect <address> Connect to server\n" + "\t-l, --listen [address] Use TCP server\n" + "\t-u, --unix [path] Use Unix server\n" + "\t-p, --port <port> Use specified TCP port\n" + "\t-i, --index <num> Use specified controller\n" + "\t-h, --help Show help options\n"); } static const struct option main_options[] = { + { "connect", required_argument, NULL, 'c' }, + { "listen", optional_argument, NULL, 'l' }, { "unix", optional_argument, NULL, 'u' }, - { "port", optional_argument, NULL, 'p' }, + { "port", required_argument, NULL, 'p' }, { "index", required_argument, NULL, 'i' }, { "version", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, @@ -355,31 +425,39 @@ static const struct option main_options[] = { int main(int argc, char *argv[]) { - const char *unixpath = NULL; - unsigned short tcpport = 0; + const char *connect_address = NULL; + const char *server_address = NULL; + const char *unix_path = NULL; + unsigned short tcp_port = 0xb1ee; const char *str; sigset_t mask; for (;;) { int opt; - opt = getopt_long(argc, argv, "u::p::i:vh", + opt = getopt_long(argc, argv, "c:l::u::p:i:vh", main_options, NULL); if (opt < 0) break; switch (opt) { - case 'u': + case 'c': + connect_address = optarg; + break; + case 'l': if (optarg) - unixpath = optarg; + server_address = optarg; else - unixpath = "/tmp/bt-server-bredr"; + server_address = "0.0.0.0"; break; - case 'p': + case 'u': if (optarg) - tcpport = atoi(optarg); + unix_path = optarg; else - tcpport = 0xb1ee; + unix_path = "/tmp/bt-server-bredr"; + break; + case 'p': + tcp_port = atoi(optarg); break; case 'i': if (strlen(optarg) > 3 && !strncmp(optarg, "hci", 3)) @@ -416,19 +494,47 @@ int main(int argc, char *argv[]) mainloop_set_signal(&mask, signal_callback, NULL, NULL); - if (unixpath) - server_fd = open_unix(unixpath); - else if (tcpport > 0) - server_fd = open_tcp(tcpport); - else { - fprintf(stderr, "Missing emulator device\n"); - return EXIT_FAILURE; - } + if (connect_address) { + printf("Connecting to %s:%u\n", connect_address, tcp_port); - if (server_fd < 0) - return EXIT_FAILURE; + client_fd = connect_tcp(connect_address, tcp_port); + if (client_fd < 0) + return EXIT_FAILURE; + + mainloop_add_fd(client_fd, EPOLLIN, client_callback, + NULL, NULL); + + printf("Opening virtual device\n"); + + channel_fd = open_vhci(0x00); + if (channel_fd < 0) { + close(client_fd); + return EXIT_FAILURE; + } - mainloop_add_fd(server_fd, EPOLLIN, server_callback, NULL, NULL); + mainloop_add_fd(channel_fd, EPOLLIN, channel_callback, + NULL, NULL); + } else { + if (unix_path) { + printf("Listening on %s\n", unix_path); + + server_fd = open_unix(unix_path); + } else if (server_address) { + printf("Listening on %s:%u\n", server_address, + tcp_port); + + server_fd = open_tcp(server_address, tcp_port); + } else { + fprintf(stderr, "Missing emulator device\n"); + return EXIT_FAILURE; + } + + if (server_fd < 0) + return EXIT_FAILURE; + + mainloop_add_fd(server_fd, EPOLLIN, server_callback, + NULL, NULL); + } return mainloop_run(); } |