#include <unistd.h>
#include <netinet/in.h>
#include <signal.h>
+#include <getopt.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <poll.h>
+#include "readif.h"
+#include "cegwerr.h"
+
+/**
+ * ToDo:
+ * [ ] print usage
+ */
+//#define GW_DEBUG
+#ifdef GW_DEBUG
+#define printdbg(x) printf(x)
+#else
+#define printdbg(x)
+#endif
#define GW_POLL_ETH 0
#define GW_POLL_CAN 1
-/**/
-#define GW_IF_BIT 1
-#define GW_SRC_PORT_BIT 2
-#define GW_DEST_PORT_BIT 4
-#define GW_FILTER_BIT 8
+
+#define GW_FLAG_SRC 1
+#define GW_FLAG_DST 2
+#define GW_FLAG_LISTEN 4
+#define GW_FLAG_FILTER 8
unsigned int opt_flag = 0;
int sock_udp;
struct sockaddr_in udp_dest;
/**
- *
+ * filter_check
* @return true if frame should be dropped
*/
bool filter_check( struct can_frame* cf )
{
- if( !(opt_flag & GW_FILTER_BIT) )
+ if( !(opt_flag & GW_FLAG_FILTER) )
return false;
return ( (cf->can_id & flt.can_mask) == (flt.can_id & flt.can_mask) );
void send_to_can()
{
struct can_frame cf;
+
read( sock_udp, &cf, sizeof(cf) );
- if( !filter_check( &cf ) )
+ if( filter_check( &cf ) )
{
- printf( "filter: drop\n" );
+ printdbg( "filter: drop\n" );
return;
}
write( sock_can, &cf, sizeof(cf) );
- printf( "sending to can\n" );
+ printdbg( "eth -> can\n" );
}
void send_to_eth()
read( sock_can, &cf, sizeof(cf) );
- if( !filter_check( &cf ) )
+ if( filter_check( &cf ) )
{
- printf( "filter: drop\n" );
+ printdbg( "filter: drop\n" );
return;
}
sendto( sock_udp, &cf, sizeof(cf), 0, (struct sockaddr*) &udp_dest, sizeof(udp_dest) );
- printf( "sending to eth\n" );
+ printdbg( "can -> eth\n" );
}
void signal_exit( int sig )
{
struct sockaddr_in udp_addr;
struct sockaddr_can can_addr;
- struct ifreq ifr;
struct pollfd pfd[2];
int polret;
int opt;
- int src_port = 0, dest_port = 0;
+ struct cegw_if ceif[2], iflisten;
+ struct cegw_if* ifcan,* ifeth;
flt.can_id = 0;
flt.can_mask = 0;
- while( (opt = getopt( argc, argv, "s:d:f:i:" )) != -1 )
+ struct option longopt[] =
+ {
+ {"listen", 1, NULL, 'l'},
+ { 0, 0, 0, 0 }
+ };
+
+ while( (opt = getopt_long( argc, argv, "s:d:l:f:i:", longopt, NULL )) != -1 )
{
switch( opt )
{
case 's':
- src_port = atoi( optarg );
- opt_flag |= GW_SRC_PORT_BIT;
+ if( read_if(optarg, &ceif[0]) != 0 )
+ {
+ perr( "'-s'" );
+ return -1;
+ }
+ opt_flag |= GW_FLAG_SRC;
break;
case 'd':
- dest_port = atoi( optarg );
- opt_flag |= GW_DEST_PORT_BIT;
+ if( read_if(optarg, &ceif[1]) != 0 )
+ {
+ perr( "'-d'" );
+ return -1;
+ }
+ opt_flag |= GW_FLAG_DST;
+ break;
+ case 'l':
+ if( read_if(optarg, &iflisten) != 0 )
+ {
+ perr( "'-l'" );
+ return -1;
+ }
+ if( iflisten.type != IF_ETH_UDP )
+ {
+ perr( "'-l' udp interface expected" );
+ return -1;
+ }
+ opt_flag |= GW_FLAG_LISTEN;
break;
case 'f':
if( sscanf( optarg, "%x:%x", &flt.can_id,
&flt.can_mask ) != 2 )
{
- fprintf( stderr, "error:\
- bad filter format\n");
- goto gw_error;
+ perr( "bad filter format");
+ return -1;
}
- opt_flag |= GW_FILTER_BIT;
+ opt_flag |= GW_FLAG_FILTER;
break;
- case 'i':
- ifr.ifr_ifindex = if_nametoindex( optarg );
- if( ifr.ifr_ifindex == 0 )
- {
- fprintf( stderr, "error: if_nametoindex\n" );
- goto gw_error;
- }
- opt_flag |= GW_IF_BIT;
+ case '?':
+ return -1;
break;
}
}
- if( !((opt_flag & GW_SRC_PORT_BIT) && (opt_flag & GW_DEST_PORT_BIT)
- && (opt_flag & GW_DEST_PORT_BIT)) )
+ if( !((opt_flag & GW_FLAG_SRC) && (opt_flag & GW_FLAG_DST)
+ && (opt_flag & GW_FLAG_LISTEN)) )
+ {
+ perr( "'s', 'd' and 'l' are mandatory" );
+ /* ToDo: usage? */
+ return -1;
+ }
+
+ if( !(ceif[0].type == IF_CAN && ceif[1].type == IF_ETH_UDP) &&
+ !(ceif[0].type == IF_ETH_UDP && ceif[1].type == IF_CAN ) )
{
- fprintf( stdout, "bad usage, example -i vcan0 -s 10501 -d 10502 -f 007:00000007\n" );
+ perr( "'-s' and '-d' should be different interface type" );
return -1;
}
+ if( ceif[0].type == IF_CAN )
+ {
+ ifcan = &ceif[0];
+ ifeth = &ceif[1];
+ } else
+ {
+ ifcan = &ceif[1];
+ ifeth = &ceif[0];
+ }
+
signal( SIGINT, signal_exit );
/* prepare udp destination */
udp_dest.sin_family = AF_INET;
- udp_dest.sin_addr.s_addr = inet_addr("127.0.0.1");
- udp_dest.sin_port = htons(dest_port);
+ udp_dest.sin_port = htons(ifeth->eth.port);
+ udp_dest.sin_addr = ifeth->eth.ip;
/* udp socket */
sock_udp = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
if( sock_udp < 0 )
{
- fprintf( stderr, "error: socket(), udp\n" );
- goto gw_error;
+ perr( "udp socket creation failed" );
+ return -1;
}
udp_addr.sin_family = AF_INET;
- udp_addr.sin_port = htons(src_port);
- udp_addr.sin_addr.s_addr = INADDR_ANY;
+ udp_addr.sin_port = htons(iflisten.eth.port);
+ udp_addr.sin_addr = iflisten.eth.ip;
if( bind( sock_udp, (struct sockaddr*) &udp_addr, sizeof(udp_addr) ) < 0 )
{
- fprintf( stderr, "error: bind(), udp\n" );
+ perr( "udp socket binding failed" );
close( sock_udp );
- goto gw_error;
+ return -1;
}
/* can socket */
sock_can = socket( PF_CAN, SOCK_RAW, CAN_RAW );
if( sock_can < 0 )
{
- fprintf( stderr, "error: socket(), can\n");
+ perr( "can socket creation failed");
close( sock_can );
- goto gw_error;
+ return -1;
}
can_addr.can_family = AF_CAN;
- can_addr.can_ifindex = ifr.ifr_ifindex;
+ can_addr.can_ifindex = ifcan->can.ifindex;
if( bind( sock_can, (struct sockaddr*) &can_addr, sizeof(can_addr) ) < 0 )
{
- fprintf( stderr, "error: bind(), can" );
- goto gw_error;
+ perr( "can socket binding failed" );
+ return -1;
}
/* poll */
pfd[GW_POLL_CAN].events = POLLIN | POLLPRI;
pfd[GW_POLL_CAN].revents = 0;
- while(1)
+ printf( "canethgw is running\n" );
+
+ while( 1 )
{
- printf( "polling\n" );
+ printdbg( "polling\n" );
polret = poll( pfd, 2, -1 );
- if( polret <= 0 )
+ if( polret < 0 )
{
- fprintf( stderr, "error: poll returned 0\n" );
- goto gw_clean;
+ perr( "poll(..) failed" );
+ close( sock_udp );
+ close( sock_can );
+ return -1;
}
if( pfd[GW_POLL_ETH].revents != 0 )
}
return 0;
-gw_clean:
- close( sock_udp );
- close( sock_can );
-gw_error:
- return -1;
}