From d57fdaf62fa1ce7e8573404206903ad281ff889c Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Thu, 30 May 2013 23:53:43 +0200 Subject: [PATCH] beginning of hmsniff, a small HomeMatic sniffer/dissector --- .gitignore | 3 + Makefile | 13 ++-- hmsniff.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 4 deletions(-) create mode 100644 hmsniff.c diff --git a/.gitignore b/.gitignore index 2056e43..097ebd3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ hmcfgusb.o hmland hmland.d hmland.o +hmsniff +hmsniff.d +hmsniff.o diff --git a/Makefile b/Makefile index b82aa23..74d4217 100644 --- a/Makefile +++ b/Makefile @@ -2,16 +2,21 @@ CFLAGS=-MMD -O2 -Wall -I/opt/local/include -g LDFLAGS=-L/opt/local/lib -lusb-1.0 -lm CC=gcc -OBJS=hmcfgusb.o hmland.o +HMLAN_OBJS=hmcfgusb.o hmland.o +HMSNIFF_OBJS=hmcfgusb.o hmsniff.o -all: hmland +OBJS=$(HMLAN_OBJS) $(HMSNIFF_OBJS) + +all: hmland hmsniff DEPEND=$(OBJS:.o=.d) -include $(DEPEND) -hmland: $(OBJS) +hmland: $(HMLAN_OBJS) + +hmsniff: $(HMSNIFF_OBJS) clean: - rm -f $(OBJS) $(DEPEND) hmland + rm -f $(HMLAN_OBJS) $(HMSNIFF_OBJS) $(DEPEND) hmland hmsniff .PHONY: all clean diff --git a/hmsniff.c b/hmsniff.c new file mode 100644 index 0000000..6260cb6 --- /dev/null +++ b/hmsniff.c @@ -0,0 +1,183 @@ +/* HM-sniffer for HM-CFG-USB + * + * Copyright (c) 2013 Michael Gernoth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hexdump.h" +#include "hmcfgusb.h" + +/* See HMConfig.pm */ +char *hm_message_types(uint8_t type) +{ + switch(type) { + case 0x00: + return "Device Info"; + break; + case 0x01: + return "Configuration"; + break; + case 0x02: + return "Acknowledge"; + break; + case 0x03: + return "AES"; + break; + case 0x04: + return "AES-Key"; + break; + case 0x10: + return "Information"; + break; + case 0x11: + return "SET"; + break; + case 0x12: + return "HAVE_DATA"; + break; + case 0x3e: + return "Switch"; + break; + case 0x3f: + return "Timestamp"; + break; + case 0x40: + return "Remote"; + break; + case 0x41: + return "Sensor"; + break; + case 0x53: + return "Water sensor"; + break; + case 0x58: + return "Climate event"; + break; + case 0x70: + return "Weather event"; + break; + default: + return "?"; + break; + } +} + +static void dissect_hm(uint8_t *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) { + printf("%02X", buf[i]); + } + printf("\n"); + printf("Packet information:\n"); + printf("\tLength: %u\n", buf[0]); + printf("\tMessage ID: %u\n", buf[1]); + printf("\tSender: %02x%02x%02x\n", buf[4], buf[5], buf[6]); + printf("\tReceiver: %02x%02x%02x\n", buf[7], buf[8], buf[9]); + printf("\tControl Byte: 0x%02x\n", buf[2]); + printf("\t\tFlags: "); + if (buf[2] & (1 << 0)) printf("WAKEUP "); + if (buf[2] & (1 << 1)) printf("WAKEMEUP "); + if (buf[2] & (1 << 2)) printf("BCAST "); + if (buf[2] & (1 << 3)) printf("? "); + if (buf[2] & (1 << 4)) printf("BURST "); + if (buf[2] & (1 << 5)) printf("BIDI "); + if (buf[2] & (1 << 6)) printf("RPTED "); + if (buf[2] & (1 << 7)) printf("RPTEN "); + printf("\n"); + printf("\tMessage type: %s (0x%02x)\n", hm_message_types(buf[3]), buf[3]); + printf("\tMesage: "); + for (i = 10; i < len; i++) { + printf("%02X", buf[i]); + } + printf("\n"); + + printf("\n"); + +} + +static void parse_hmcfgusb(uint8_t *buf, int buf_len, void *data) +{ + if (buf_len < 1) + return; + + switch(buf[0]) { + case 'E': + dissect_hm(buf + 13, buf[13] + 1); + break; + case 'H': + case 'R': + case 'I': + break; + default: + hexdump(buf, buf_len, "Unknown> "); + break; + } +} + + +int main(int argc, char **argv) +{ + struct hmcfgusb_dev *dev; + int quit = 0; + + hmcfgusb_set_debug(0); + + dev = hmcfgusb_init(parse_hmcfgusb, NULL); + if (!dev) { + fprintf(stderr, "Can't initialize HM-CFG-USB!\n"); + return EXIT_FAILURE; + } + + hmcfgusb_send(dev, (unsigned char*)"A\00\00\00", 3, 1); + + while(!quit) { + int fd; + + fd = hmcfgusb_poll(dev, 3600); + if (fd >= 0) { + fprintf(stderr, "activity on unknown fd %d!\n", fd); + continue; + } else if (fd == -1) { + if (errno) { + perror("hmcfgusb_poll"); + quit = 1; + } + } + } + + hmcfgusb_close(dev); + return EXIT_SUCCESS; +} -- 2.39.2