+++ /dev/null
-/*********************************************************************
- *
- * Filename: irda_intercept.c
- * Version:
- * Description: intercept irda-traffic incl. negotation and write
- * output to a file
- * Status: Experimental.
- * Author: Thomas Schneider <nok-trace-men@dev-thomynet.de>
- * Created at:
- * Modified at:
- * Modified by: Thomas Schneider <nok-trace-men@dev-thomynet.de>
- *
- * 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 <sys/time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <signal.h>
-#include <glib.h>
-#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);
-}