Blame monitor/ellisys.c

Packit 34410b
/*
Packit 34410b
 *
Packit 34410b
 *  BlueZ - Bluetooth protocol stack for Linux
Packit 34410b
 *
Packit 34410b
 *  Copyright (C) 2011-2014  Intel Corporation
Packit 34410b
 *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
Packit 34410b
 *
Packit 34410b
 *
Packit 34410b
 *  This library is free software; you can redistribute it and/or
Packit 34410b
 *  modify it under the terms of the GNU Lesser General Public
Packit 34410b
 *  License as published by the Free Software Foundation; either
Packit 34410b
 *  version 2.1 of the License, or (at your option) any later version.
Packit 34410b
 *
Packit 34410b
 *  This library is distributed in the hope that it will be useful,
Packit 34410b
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 34410b
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 34410b
 *  Lesser General Public License for more details.
Packit 34410b
 *
Packit 34410b
 *  You should have received a copy of the GNU Lesser General Public
Packit 34410b
 *  License along with this library; if not, write to the Free Software
Packit 34410b
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
Packit 34410b
 *
Packit 34410b
 */
Packit 34410b
Packit 34410b
#ifdef HAVE_CONFIG_H
Packit 34410b
#include <config.h>
Packit 34410b
#endif
Packit 34410b
Packit 34410b
#define _GNU_SOURCE
Packit 34410b
#include <stdio.h>
Packit 34410b
#include <unistd.h>
Packit 34410b
#include <string.h>
Packit 34410b
#include <time.h>
Packit 34410b
#include <sys/time.h>
Packit 34410b
#include <sys/socket.h>
Packit 34410b
#include <sys/uio.h>
Packit 34410b
Packit 34410b
#include <netdb.h>
Packit 34410b
#include <arpa/inet.h>
Packit 34410b
Packit 34410b
#include "src/shared/btsnoop.h"
Packit 34410b
#include "ellisys.h"
Packit 34410b
Packit 34410b
static int ellisys_fd = -1;
Packit 34410b
static uint16_t ellisys_index = 0xffff;
Packit 34410b
Packit 34410b
void ellisys_enable(const char *server, uint16_t port)
Packit 34410b
{
Packit 34410b
	struct sockaddr_in addr;
Packit 34410b
	int fd;
Packit 34410b
Packit 34410b
	if (ellisys_fd >= 0) {
Packit 34410b
		fprintf(stderr, "Ellisys injection already enabled\n");
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
Packit 34410b
	if (fd < 0) {
Packit 34410b
		perror("Failed to open UDP injection socket");
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	memset(&addr, 0, sizeof(addr));
Packit 34410b
	addr.sin_family = AF_INET;
Packit 34410b
	addr.sin_addr.s_addr = inet_addr(server);
Packit 34410b
	addr.sin_port = htons(port);
Packit 34410b
Packit 34410b
	if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
Packit 34410b
		perror("Failed to connect UDP injection socket");
Packit 34410b
		close(fd);
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	ellisys_fd = fd;
Packit 34410b
}
Packit 34410b
Packit 34410b
void ellisys_inject_hci(struct timeval *tv, uint16_t index, uint16_t opcode,
Packit 34410b
					const void *data, uint16_t size)
Packit 34410b
{
Packit 34410b
	uint8_t msg[] = {
Packit 34410b
		/* HCI Injection Service, Version 1 */
Packit 34410b
		0x02, 0x00, 0x01,
Packit 34410b
		/* DateTimeNs Object */
Packit 34410b
		0x02, 0x00, 0x00, 0x00, 0x00,
Packit 34410b
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Packit 34410b
		/* Bitrate Object, 12000000 bps */
Packit 34410b
		0x80, 0x00, 0x1b, 0x37, 0x4b,
Packit 34410b
		/* HCI Packet Type Object */
Packit 34410b
		0x81, 0x00,
Packit 34410b
		/* HCI Packet Data Object */
Packit 34410b
		0x82
Packit 34410b
	};
Packit 34410b
	long nsec;
Packit 34410b
	time_t t;
Packit 34410b
	struct tm tm;
Packit 34410b
	struct iovec iov[2];
Packit 34410b
	int iovcnt;
Packit 34410b
Packit 34410b
	if (!tv)
Packit 34410b
		return;
Packit 34410b
Packit 34410b
	if (ellisys_fd < 0)
Packit 34410b
		return;
Packit 34410b
Packit 34410b
	if (ellisys_index == 0xffff)
Packit 34410b
		ellisys_index = index;
Packit 34410b
Packit 34410b
	if (index != ellisys_index)
Packit 34410b
		return;
Packit 34410b
Packit 34410b
	t = tv->tv_sec;
Packit 34410b
	localtime_r(&t, &tm;;
Packit 34410b
Packit 34410b
	nsec = ((tm.tm_sec + (tm.tm_min * 60) +
Packit 34410b
			(tm.tm_hour * 3600)) * 1000000l + tv->tv_usec) * 1000l;
Packit 34410b
Packit 34410b
	msg[4]  = (1900 + tm.tm_year) & 0xff;
Packit 34410b
	msg[5]  = (1900 + tm.tm_year) >> 8;
Packit 34410b
	msg[6]  = (tm.tm_mon + 1) & 0xff;
Packit 34410b
	msg[7]  = tm.tm_mday & 0xff;
Packit 34410b
	msg[8]  = (nsec & 0x0000000000ffl);
Packit 34410b
	msg[9]  = (nsec & 0x00000000ff00l) >> 8;
Packit 34410b
	msg[10] = (nsec & 0x000000ff0000l) >> 16;
Packit 34410b
	msg[11] = (nsec & 0x0000ff000000l) >> 24;
Packit 34410b
	msg[12] = (nsec & 0x00ff00000000l) >> 32;
Packit 34410b
	msg[13] = (nsec & 0xff0000000000l) >> 40;
Packit 34410b
Packit 34410b
	switch (opcode) {
Packit 34410b
	case BTSNOOP_OPCODE_COMMAND_PKT:
Packit 34410b
		msg[20] = 0x01;
Packit 34410b
		break;
Packit 34410b
	case BTSNOOP_OPCODE_EVENT_PKT:
Packit 34410b
		msg[20] = 0x84;
Packit 34410b
		break;
Packit 34410b
	case BTSNOOP_OPCODE_ACL_TX_PKT:
Packit 34410b
		msg[20] = 0x02;
Packit 34410b
		break;
Packit 34410b
	case BTSNOOP_OPCODE_ACL_RX_PKT:
Packit 34410b
		msg[20] = 0x82;
Packit 34410b
		break;
Packit 34410b
	case BTSNOOP_OPCODE_SCO_TX_PKT:
Packit 34410b
		msg[20] = 0x03;
Packit 34410b
		break;
Packit 34410b
	case BTSNOOP_OPCODE_SCO_RX_PKT:
Packit 34410b
		msg[20] = 0x83;
Packit 34410b
		break;
Packit 34410b
	default:
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	iov[0].iov_base = msg;
Packit 34410b
	iov[0].iov_len  = sizeof(msg);
Packit 34410b
Packit 34410b
	if (size > 0) {
Packit 34410b
		iov[1].iov_base = (void *) data;
Packit 34410b
		iov[1].iov_len  = size;
Packit 34410b
		iovcnt = 2;
Packit 34410b
	} else
Packit 34410b
		iovcnt = 1;
Packit 34410b
Packit 34410b
	if (writev(ellisys_fd, iov, iovcnt) < 0)
Packit 34410b
		perror("Failed to send Ellisys injection packet");
Packit 34410b
}