/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * cansniffer.c - volatile CAN content visualizer * * Copyright (c) 2002-2007 Volkswagen Group Electronic Research * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Volkswagen nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * Alternatively, provided that this notice is retained in full, this * software may be distributed under the terms of the GNU General * Public License ("GPL") version 2, in which case the provisions of the * GPL apply INSTEAD OF those given above. * * The provided data structures and external interfaces from this code * are not restricted to be used by modules with a GPL compatible license. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * Send feedback to * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "terminal.h" #define SETFNAME "sniffset." #define SETFDFNAME "sniffset_fd." #define FNAME_MAX_LEN 40 #define ANYDEV "any" #define MAX_SLOTS 2048 #define CANFD_OFF 0 /* set to OFF */ #define CANFD_ON 1 /* set to ON */ #define CANFD_AUTO 2 /* unspecified => check for first received frame */ /* flags */ #define ENABLE 1 /* by filter or user */ #define DISPLAY 2 /* is on the screen */ #define UPDATE 4 /* needs to be printed on the screen */ #define CLRSCR 8 /* clear screen in next loop */ /* flags testing & setting */ #define is_set(id, flag) (sniftab[id].flags & flag) #define is_clr(id, flag) (!(sniftab[id].flags & flag)) #define do_set(id, flag) (sniftab[id].flags |= flag) #define do_clr(id, flag) (sniftab[id].flags &= ~flag) /* time defaults */ #define TIMEOUT 500 /* in 10ms */ #define HOLD 100 /* in 10ms */ #define LOOP 20 /* in 10ms */ #define ATTCOLOR ATTBOLD FGRED #define LDL " | " /* long delimiter */ #define SDL "|" /* short delimiter for binary on 80 chars terminal */ #define CC_SEP '#' /* interface name separator for Classical CAN */ #define FD_SEP '*' /* interface name separator for CAN FD */ static struct snif { int flags; long hold; long timeout; struct timeval laststamp; struct timeval currstamp; struct canfd_frame last; struct canfd_frame current; struct canfd_frame marker; struct canfd_frame notch; } sniftab[MAX_SLOTS]; extern int optind, opterr, optopt; static int idx; static int running = 1; static int clearscreen = 1; static int print_eff; static int print_ascii = 1; static int notch; static int max_dlen = CAN_MAX_DLEN; static long timeout = TIMEOUT; static long hold = HOLD; static long loop = LOOP; static long canfd_mode = CANFD_AUTO; static unsigned char binary; static unsigned char binary8; static unsigned char binary_gap; static unsigned char color; static unsigned char name_sep = CC_SEP; static char *interface; static char *vdl = LDL; /* variable delimiter */ static char *ldl = LDL; /* long delimiter */ void print_snifline(int slot); int handle_keyb(void); int handle_frame(int fd, long currcms); int handle_timeo(long currcms); int writesettings(char* name); int readsettings(char* name); int sniftab_index(canid_t id); void switchvdl(char *delim) { /* reduce delimiter size for EFF IDs in binary display of up to 8 data bytes payload to fit into 80 chars per line */ if (binary8) vdl = delim; } int comp(const void *elem1, const void *elem2) { unsigned long f = ((struct snif*)elem1)->current.can_id; unsigned long s = ((struct snif*)elem2)->current.can_id; if (f > s) return 1; if (f < s) return -1; return 0; } void print_usage(char *prg) { const char manual [] = { "commands that can be entered at runtime:\n" " q - quit\n" " b - toggle binary / HEX-ASCII output\n" " 8 - toggle binary / HEX-ASCII output (small for EFF on 80 chars)\n" " B - toggle binary with gap / HEX-ASCII output (exceeds 80 chars!)\n" " c - toggle color mode\n" " @ - toggle ASCII output (disabled for CAN FD by default)\n" " - force a clear screen\n" " # - notch currently marked/changed bits (can be used repeatedly)\n" " * - clear notched marked\n" " rMYNAME - read settings file (filter/notch)\n" " wMYNAME - write settings file (filter/notch)\n" " a - enable 'a'll SFF CAN-IDs to sniff\n" " n - enable 'n'one SFF CAN-IDs to sniff\n" " A - enable 'A'll EFF CAN-IDs to sniff\n" " N - enable 'N'one EFF CAN-IDs to sniff\n" " +FILTER - add CAN-IDs to sniff\n" " -FILTER - remove CAN-IDs to sniff\n" "\n" "FILTER can be a single CAN-ID or a CAN-ID/Bitmask:\n" "\n" " single SFF 11 bit IDs:\n" " +1F5 - add SFF CAN-ID 0x1F5\n" " -42E - remove SFF CAN-ID 0x42E\n" "\n" " single EFF 29 bit IDs:\n" " +18FEDF55 - add EFF CAN-ID 0x18FEDF55\n" " -00000090 - remove EFF CAN-ID 0x00000090\n" "\n" " CAN-ID/Bitmask SFF:\n" " -42E7FF - remove SFF CAN-ID 0x42E (using Bitmask)\n" " -500700 - remove SFF CAN-IDs 0x500 - 0x5FF\n" " +400600 - add SFF CAN-IDs 0x400 - 0x5FF\n" " +000000 - add all SFF CAN-IDs\n" " -000000 - remove all SFF CAN-IDs\n" "\n" " CAN-ID/Bitmask EFF:\n" " -0000000000000000 - remove all EFF CAN-IDs\n" " +12345678000000FF - add EFF CAN IDs xxxxxx78\n" " +0000000000000000 - add all EFF CAN-IDs\n" "\n" "if (id & filter) == (sniff-id & filter) the action (+/-) is performed,\n" "which is quite easy when the filter is 000 resp. 00000000 for EFF.\n" "\n" }; fprintf(stderr, "%s - volatile CAN content visualizer.\n", prg); fprintf(stderr, "\nUsage: %s [can-interface]\n", prg); fprintf(stderr, "Options:\n"); fprintf(stderr, " -q (quiet - all IDs deactivated)\n"); fprintf(stderr, " -r (read %sname from file)\n", SETFNAME); fprintf(stderr, " -e (fix extended frame format output - no auto detect)\n"); fprintf(stderr, " -b (start with binary mode)\n"); fprintf(stderr, " -8 (start with binary mode - for EFF on 80 chars)\n"); fprintf(stderr, " -B (start with binary mode with gap - exceeds 80 chars!)\n"); fprintf(stderr, " -c (color changes)\n"); fprintf(stderr, " -f (CAN FD mode: 0 = OFF, 1 = ON, 2 = auto detect, default: %d)\n", CANFD_AUTO); fprintf(stderr, " -t