X-Git-Url: https://git.jankratochvil.net/?p=gnokii.git;a=blobdiff_plain;f=Docs%2Fdevelopers%2Fother%2Fsniffs%2Firda%2Ftools%2Fintercept%2Firda_intercept.c;fp=Docs%2Fdevelopers%2Fother%2Fsniffs%2Firda%2Ftools%2Fintercept%2Firda_intercept.c;h=1381418ab6950b3d54f0cd0d5f0f48afab3660b8;hp=0000000000000000000000000000000000000000;hb=2e0972b02d101bb0d8e9d3e15d2ac80def491a63;hpb=cc37b87508c91b5d4f21fd4bbc298104ae7de1dc diff --git a/Docs/developers/other/sniffs/irda/tools/intercept/irda_intercept.c b/Docs/developers/other/sniffs/irda/tools/intercept/irda_intercept.c new file mode 100644 index 0000000..1381418 --- /dev/null +++ b/Docs/developers/other/sniffs/irda/tools/intercept/irda_intercept.c @@ -0,0 +1,613 @@ +/********************************************************************* + * + * Filename: irda_intercept.c + * Version: + * Description: intercept irda-traffic incl. negotation and write + * output to a file + * Status: Experimental. + * Author: Thomas Schneider + * Created at: + * Modified at: + * Modified by: Thomas Schneider + * + * Copyright (c) 1999 Thomas Schneider, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * IN NO EVENT SHALL THOMAS SCHNEIDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THOMAS SCHNEIDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THOMAS SCHNEIDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER + * IS ON AN "AS IS" BASIS, AND THOMAS SCHNEIDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + * MODIFICATIONS. + * + * This material is provided "AS-IS" and at no charge. + * + ********************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../include/irda.h" +#include "../include/irlap.h" +#include "../fcs/fcs.h" + +#define INIT_BAUDRATE B9600 + +#define _POSIX_SOURCE 1 /* POSIX compliant source */ + +#define INITIAL_TIMEOUT 15 +#define DEFAULT_TIMEOUT 5 + +#define OUTFILE_SUFFIX ".trc" +#define DEFAULT_OUTFILE "out"OUTFILE_SUFFIX + +static int initfdflags = -1; /* Initial file descriptor flags */ +static struct termios old_port_sets; /* old port-termios for restore */ + +int port_fd; + +NEGOTATION_PARAM negotation_param; +CONNECTION connection; + +static speed_t speed_list[8] = { B2400, B9600, B19200, B38400, + B57600, B115200, B576000, B1152000 }; +static const char *speed_name[] = { "2400", "9600", "19200", "38400", + "57600", "115200", "576000", "1152000"}; + +/* + * negotation + * ---------- + * - in negotation set new device speed + */ +void negotation ( IRLAP_FRAME * irlap_frame ) +{ + BYTE cmd = irlap_frame -> a & 0x01; + speed_t new_speed = 0; + int i = 0; + int m = 0; + struct termios set; + BYTE tmp = 0; + + /* + * snrm-frame + * ---------- + * - 4 src + * - 4 dest + * - 1 new connection address + * - 1 pi + * - 1 pl + * - [pl] pv + * ua-frame + * -------- + * - 4 src + * - 4 dest + * - 1 pi + * - 1 pl + * - [pl] pv + */ + + if ( cmd ) { + /* + * SNRM - CMD + * ---------- + * - in IrLAP (V. 1.1) page 27 + * - U32 : src-dev-adr + * - U32 : dest-dev-adr + * - U8 : connection address + * - start of neg. params + */ + if ( irlap_frame -> info_length < ( IRLAP_NEG_SNRM_PARAM_OFF +3 ) ) { + printf ("\t==> IrLAP: in SNRM-CMD no Info! <==\n"); + } else { + memcpy ( &connection.p_src_adr, + &(irlap_frame -> info[IRLAP_SNRM_SRC_ADR]), + sizeof(connection.p_src_adr)); + memcpy ( &connection.s_src_adr, + &(irlap_frame -> info[IRLAP_SNRM_DEST_ADR]), + sizeof(connection.s_src_adr)); + connection.conn_adr = irlap_frame -> info[IRLAP_SNRM_CONN_ADR]; + if ( irlap_frame -> info[IRLAP_NEG_SNRM_PARAM_OFF] == + IRLAP_NEG_BPS_PI ) { + /* really bps-parameter-identifier */ + if ( irlap_frame -> info[IRLAP_NEG_SNRM_PARAM_OFF + 1] == 1 ) { + negotation_param.baud_rate_master = + irlap_frame -> info [IRLAP_NEG_SNRM_PARAM_OFF + 2]; + negotation_param.state = NEG_WAIT_FOR_UA; + } else { + printf ("\t==> IrLAP: SNRM-CMD: speed in 2 bytes! <==\n"); + printf ("\t\t==> IrLAP: my max. speed is 115.2 kbps! <==\n"); + negotation_param.baud_rate_master = + irlap_frame -> info [IRLAP_NEG_SNRM_PARAM_OFF + 3]; + } + } else { + printf ("\t==> IrLAP: SNRM-CMD: " + "No baud rate dictate in 1. byte! <==\n"); + } + } + } else { + /* UA -rsp */ + negotation_param.baud_rate_client = irlap_frame -> info [10]; + negotation_param.state = NEG_UA_OK; + + /* now compute the new speed */ + tmp = + negotation_param.baud_rate_master & negotation_param.baud_rate_client; + if ( tmp & 0x01 ) { + new_speed = speed_list[i]; + m = 0; + } + for ( i=1; i < 7; i++) { + tmp = tmp >> 1; + if ( tmp & 0x01 ) { + new_speed = speed_list[i]; + m = i; + } + } + if ( m > 5 ) { + /* not defined as B... on my system */ + printf ("Sorry: Required speed (%s baud) not supported!\n", + speed_name[m]); + } else { + printf ("New speed is: %s\n", speed_name[m]); + /* now set the new speed */ + tcgetattr (port_fd, &set); + cfsetospeed(&set, new_speed); + cfsetispeed(&set, new_speed); + tcsetattr(port_fd, TCSANOW, &set); + tcgetattr(port_fd, &set); + if ( (cfgetospeed(&set) != new_speed) || + (cfgetispeed(&set) != new_speed) ) { + printf ("New speed is not set!\n"); + } + } + } +} + +/* + * decode_irlap_frame + * ------------------ + * - decode the irlap-c-field + */ +void decode_irlap_frame ( IRLAP_FRAME * irlap_frame) +{ + BYTE cmd = irlap_frame -> a & 0x01; + BYTE poll = irlap_frame -> c & (IRLAP_PF_BIT_MASK); + BYTE adr = (irlap_frame -> a) >> 1; + + switch ( irlap_frame -> c & IRLAP_C_MASK ) { + case IRLAP_U_FRAME: + printf ("U-Frame:\tAdr: %02X Nr: %02X ", adr, + (irlap_frame -> c & 0xE0) >> 5); + printf ("P/F: %X \t\t", poll >> 4); + switch (irlap_frame -> c & IRLAP_PF_BIT_CLR_MASK ) { + case IRLAP_SNRM_RNRM: + /* SNRM cmd/RNRM response */ + if ( cmd ) { + printf ("SNRM cmd\n"); + switch (connection.irlap_state) { + case IRLAP_DISC: + printf ("\t==> IrLAP in DISC but SNRM-CMD? <==\n"); + break; + case IRLAP_NDM: + printf ("\t==> Start IrLAP - negotation <==\n"); + negotation ( irlap_frame ); + break; + case IRLAP_NRM: + printf ("\t==> IrLAP in NRM but SNRM-CMD? <==\n"); + break; + default: + printf ("\t==> IrLAP in not defined state but SNRM-CMD? <==\n"); + } + } else { + printf ("RNRM response\n"); + } + break; + case IRLAP_DISC_RD: + /* DISC cmd/RD response */ + if ( cmd ) { + printf ("DISC cmd\n"); + } else { + printf ("RD response\n"); + } + break; + case IRLAP_UI_UI: + /* UI cmd/UI response */ + if ( cmd ) { + printf ("UI cmd\n"); + } else { + printf ("UI response\n"); + } + break; + case IRLAP_XID_CMD: + /* XID cmd */ + printf ("XID cmd\n"); + if ( connection.irlap_state == IRLAP_DISC ) { + connection.irlap_state = IRLAP_NDM; + printf ("\t==> Set IrLAP-state to:" + "NDM (normal disconnected mode) <==\n"); + } + break; + case IRLAP_TEST_TEST: + /* Test cmd/response */ + if ( cmd ) { + printf ("TEST cmd\n"); + } else { + printf ("TEST response\n"); + } + break; + case IRLAP_UA_RSP: + /* UA response */ + printf ("UA response\n"); + switch (connection.irlap_state) { + case IRLAP_DISC: + printf ("\t==> IrLAP in DISC but UA-RESPONSE? <==\n"); + break; + case IRLAP_NDM: + if ( negotation_param.state == NEG_WAIT_FOR_UA ) { + printf ("\t==> Continue IrLAP - negotation! <==\n"); + negotation ( irlap_frame ); + } else { + printf ("\t==> IrLAP in NDM but not wait for negotation! <==\n"); + } + break; + case IRLAP_NRM: + printf ("\t==> UA: IrLAP was/is in NRM ... <==\n"); + break; + default: + printf ("\t==> IrLAP in not defined state but UA-RESPONSE? <==\n"); + } + break; + case IRLAP_FRMR_RSP: + /* FRMR response */ + printf ("FRMR response\n"); + break; + case IRLAP_DM_RSP: + /* DM response */ + printf ("DM response\n"); + break; + case IRLAP_XID_RSP: + /* XID response */ + printf ("XID response\n"); + break; + default: + /* unknown cmd/response */ + printf ("Unknown IrLAP-U-Frame\n"); + } /* end of irlap-u-frames */ + break; + case IRLAP_S_FRAME: + printf ("S-Frame:\tAdr: %02X Nr: %02X ", adr, + (irlap_frame -> c & 0xE0) >> 5); + printf ("P/F: %X \t\t", poll >> 4); + switch ( irlap_frame -> c & + (IRLAP_PF_BIT_CLR_MASK & IRLAP_Nr_CLR_MASK) ) { + case IRLAP_RR: + /* RR command/response */ + if ( cmd ) { + printf ("RR cmd\n"); + } else { + printf ("RR response\n"); + } + break; + case IRLAP_RNR: + /* RNR cmd/response */ + printf ("RNR cmd/response\n"); + break; + case IRLAP_REJ: + /* REJ cmd/response */ + printf ("REJ cmd/response\n"); + break; + case IRLAP_SREJ: + /* SREJ cmd/response */ + printf ("SREJ cmd/response\n"); + break; + default: + /* unknown cmd/response */ + printf ("Unknown IrLAP-S-Frame\n"); + } /* end of irlap-s-frames */ + break; + default: + printf ("I-Frame:\tAdr: %02X Nr: %02X ", adr, + (irlap_frame -> c & 0xE0) >> 5); + printf ("\tP/F: %X\t", poll >> 4); + printf ("Ns: %02X \t", (irlap_frame -> c & 0x0E) >> 1); + printf ("Information\n"); + } +} + +/* unwrap_raw_frame + * ---------------- + * - put raw-frame-datas in irlap-frame + */ +void unwrap_raw_frame ( RAW_FRAME * raw_frame ) +{ + IRLAP_FRAME irlap_frame; + BYTE * info_ptr; + + bzero ( &irlap_frame, sizeof(irlap_frame) ); + + irlap_frame.a = raw_frame -> buf[IRLAP_A_OFF]; + irlap_frame.c = raw_frame -> buf[IRLAP_C_OFF]; + irlap_frame.fcs = raw_frame -> buf [(raw_frame -> length) -2] << 8; + irlap_frame.fcs |= raw_frame -> buf [(raw_frame -> length) -1]; + + irlap_frame.info_length = raw_frame -> length - + IRLAP_A_LENGTH - IRLAP_C_LENGTH - IRLAP_FCS_LENGTH; + + info_ptr = g_malloc ( irlap_frame.info_length * sizeof (BYTE) ); + memcpy ( info_ptr, &(raw_frame -> buf[IRLAP_I_OFF]), + irlap_frame.info_length); + irlap_frame.info = info_ptr; + decode_irlap_frame ( &irlap_frame ); + g_free(info_ptr); + + printf ("IrLAP: FCS: %04X \n\n", irlap_frame.fcs ); + +} + +/* + * cleanup_termios + * --------------- + * - call on some signals from signalhandler + * - before end set the original setting + */ +void cleanup_termios ( int signal ) +{ + tcsetattr(port_fd, TCSANOW, &old_port_sets); + exit (0); +} + +/* + * init_port + * --------- + * - get original port-settings and store it + * - set new port-settings + */ +void init_port ( void ) +{ + struct termios new_port_sets; + + /* get the original settings and store it for restore */ + tcgetattr( port_fd, &old_port_sets); + + /* init new settings */ + bzero(&new_port_sets, sizeof(new_port_sets)); + new_port_sets.c_cflag = INIT_BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; + new_port_sets.c_iflag = IGNBRK | IGNPAR; + new_port_sets.c_oflag = 0; + + /* set input mode (non-canonical, no echo,...) */ + new_port_sets.c_lflag = 0; + + /* inter-character timer unused x0.1s */ + new_port_sets.c_cc[VTIME] = 0; + /* blocking read until 5 chars received */ + new_port_sets.c_cc[VMIN] = 1; + + /* set the port now */ + tcflush(port_fd, TCIFLUSH); + tcsetattr(port_fd, TCSANOW, &new_port_sets); +} + +/* + * main + * ---- + * - output-file and port open + * - get/set port settings + * - dataread-loop + */ +int main( int argc, char * argv[] ) +{ + struct sigaction sact; /* signalhandle */ + GString *outfile_name = g_string_new(DEFAULT_OUTFILE); /* outfile name */ + FILE *outfile; /* outfile FILE */ + fd_set ready; /* for select */ + struct timeval timeout; /* select-timeout */ + int no_timeout = 1; /* timeout reached */ + int nr_read = 0; /* byte readed */ + unsigned char in_buffer[255]; /* temp. buffer */ + RAW_FRAME raw_frame; /* a raw frame */ + int is_inframe = FALSE; /* loop in frame */ + int frame_complete = FALSE; /* frame complete */ + int done = 0; /* loop control */ + int i = 0; /* for-index */ + int nr_of_bytes = 0; /* total bytes */ + int nr_of_frames = 0; /* total frames */ + int irlap_bytes = 0; /* w/o BOF etc. */ + BYTE must_escaped = FALSE; /* after CE = 0x07 */ + U16 fcsrx = INIT_FCS; /* for fcs-comput. */ + BYTE nr_esc = 0; /* nr of CE's */ +//CONNECT_STATISTIC statistic; /* statistic */ +//OUTPUT_PARAMS output_params; /* output-control */ + + /* + * Open the serial device + */ + if ( (port_fd = open( MODEMDEVICE, O_NONBLOCK | O_RDWR)) < 0 ) { + printf ( "Failed to open %s!\n", MODEMDEVICE); + exit(1); + } + + /* + * get/set device fd flags + */ + if ( (initfdflags = fcntl( port_fd, F_GETFL)) == -1 ) { + printf ( "Couldn't get device fd flags for: %s!", MODEMDEVICE); + exit(1); + } + initfdflags &= ~O_NONBLOCK; + fcntl( port_fd, F_SETFL, initfdflags); + + init_port(); + + /* + * set signal-handler + */ + sact.sa_handler = cleanup_termios; + sigaction( SIGHUP, &sact, NULL); + sigaction( SIGINT, &sact, NULL); + sigaction( SIGPIPE, &sact, NULL); + sigaction( SIGTERM, &sact, NULL); + + /* + * Set device for non-blocking reads. + */ + if ( fcntl( port_fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) { + printf ("Couldn't set device to non-blocking mode (%s)!\n", MODEMDEVICE); + exit(1); + } + + /* + * output-file-handling + */ + if ( argc < 2 ) { + printf ("Use default OutPutFile: %s\n", outfile_name -> str); + } else { + g_string_assign(outfile_name, argv[1]); + g_string_append(outfile_name, OUTFILE_SUFFIX); + printf ("Use OutPutFile: %s\n", outfile_name -> str); + } + if ( (outfile = fopen( outfile_name -> str, "wb")) == NULL ) { + printf ("Failed to open OutPutFile: %s\n", outfile_name -> str); + exit (1); + } + + /* + * initial timeout + * --------------- + * - wait 15 seconds + */ + timeout.tv_sec = INITIAL_TIMEOUT; + timeout.tv_usec = 0; + + /* + * init raw-frame, negotation-struct, connection + */ + bzero(&raw_frame, sizeof(raw_frame)); + bzero(&negotation_param, sizeof(negotation_param)); + bzero(&connection, sizeof(connection)); + + /* hope we have no irda traffic in moment */ + connection.irlap_state = IRLAP_DISC; + + /* + * now make the data-read-loop + */ + do { + FD_ZERO(&ready); + FD_SET(port_fd, &ready); + no_timeout = select(port_fd + 1, &ready, NULL, NULL, &timeout); + if ( FD_ISSET(port_fd, &ready) ) { + /* data on port - returns after 16 chars have been input */ + nr_read = read(port_fd, in_buffer, 16); + nr_of_bytes = nr_of_bytes + nr_read; + if ( nr_read >= 1 ) { + /* write all readed bytes to file */ + fwrite( in_buffer, 1, nr_read, outfile); + /* process every single byte */ + for (i=0; i < nr_read; i++) { + if (raw_frame.length < (4096-1) ) { + switch ( in_buffer[i] ) { + case IRLAP_XBOF: + if ( is_inframe ) { + /* + * no - its not a XBOF we are inside a frame + * broadcast in xid for example + */ + irlap_bytes++; + fcsrx = IR_FCS(fcsrx, in_buffer[i]); + is_inframe = TRUE; + raw_frame.buf[raw_frame.length] = in_buffer[i]; + } + break; + case IRLAP_BOF: + is_inframe = TRUE; + break; + case IRLAP_EOF: + frame_complete = TRUE; + is_inframe = FALSE; + break; + case IRLAP_CE: + must_escaped = TRUE; + is_inframe = TRUE; + nr_esc++; + break; + default: + is_inframe = TRUE; + if ( must_escaped ) { + fcsrx = IR_FCS(fcsrx, (in_buffer[i] ^ IRLAP_ESC_MASK) ); + raw_frame.buf[raw_frame.length] = + (in_buffer[i]^IRLAP_ESC_MASK); + must_escaped = FALSE; + } else { + fcsrx = IR_FCS(fcsrx, in_buffer[i]); + raw_frame.buf[raw_frame.length] = in_buffer[i]; + } + irlap_bytes++; + } + raw_frame.length = irlap_bytes; + if ( frame_complete ) { + /* now raw-frame is complete */ + if ( fcsrx != GOOD_FCS ) { + printf (" **** !!! FCS-ERROR !!! ****\n"); + } else { + unwrap_raw_frame ( &raw_frame ); + } + nr_of_frames++; + /* reset all to defaults */ + raw_frame.length = 0; + raw_frame.a_offset = 0; + frame_complete = FALSE; + fcsrx = INIT_FCS; + nr_esc = 0; + irlap_bytes = 0; + } + } + } + } else { + printf ("No data to read - why?\n"); + done = 1; + } + } + /* + * reset timeout - wait 5 seconds + */ + timeout.tv_sec = DEFAULT_TIMEOUT; + timeout.tv_usec = 0; + if ( ! no_timeout ) { + printf ("TimeOut!\nConnection summary:\n-------------------\n"); + printf ("Total nr of received bytes : %i\n", nr_of_bytes); + printf ("Total nr of received frames: %i\n", nr_of_frames); + done = 1; + } + } while ( ! done ); + + g_string_free(outfile_name, TRUE); + fclose (outfile); + tcsetattr(port_fd, TCSANOW, &old_port_sets); + exit(0); +}