+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <linux/can.h>
+#include <linux/can/raw.h>
+#include <poll.h>
+
+#define GW_POLL_ETH 0
+#define GW_POLL_CAN 1
+
+int sock_udp;
+int sock_can;
+
+void send_to_can()
+{
+ struct can_frame cf;
+ read( sock_udp, &cf, sizeof(cf) );
+ write( sock_can, &cf, sizeof(cf) );
+
+ printf( "sending to can\n" );
+}
+
+void send_to_eth()
+{
+ struct can_frame cf;
+ struct sockaddr_in udp_dest;
+
+ udp_dest.sin_family = AF_INET;
+ udp_dest.sin_addr.s_addr = inet_addr("127.0.0.1");
+ udp_dest.sin_port = htons(10502);
+
+ read( sock_can, &cf, sizeof(cf) );
+ sendto( sock_udp, &cf, sizeof(cf), 0, (struct sockaddr*) &udp_dest, sizeof(udp_dest) );
+ //write( sock_eth, &cf, sizeof(cf) );
+
+ printf( "sending to eth\n" );
+}
+
+int main( int argc, char* argv[] )
+{
+ struct sockaddr_in udp_addr;
+ struct sockaddr_can can_addr;
+ struct ifreq ifr;
+ struct pollfd pfd[2];
+
+ if( argc != 2 )
+ {
+ printf( "usage example: %s can1\n", argv[0] );
+ return -1;
+ }
+
+ /* udp socket */
+ sock_udp = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
+ if( sock_udp < 0 )
+ {
+ fprintf( stderr, "error: socket(), udp\n" );
+ goto gw_error;
+ }
+
+ udp_addr.sin_family = AF_INET;
+ udp_addr.sin_port = htons(10501);
+ udp_addr.sin_addr.s_addr = INADDR_ANY;
+
+ if( bind( sock_udp, (struct sockaddr*) &udp_addr, sizeof(udp_addr) ) < 0 )
+ {
+ fprintf( stderr, "error: bind(), udp\n" );
+ close( sock_udp );
+ goto gw_error;
+ }
+
+ /* can socket*/
+ sock_can = socket( PF_CAN, SOCK_RAW, CAN_RAW );
+ if( sock_can < 0 )
+ {
+ fprintf( stderr, "error: socket(), can\n");
+ close( sock_can );
+ goto gw_error;
+ }
+
+ strcpy( ifr.ifr_name, argv[1] );
+ if( ioctl( sock_can, SIOCGIFINDEX, &ifr ) < 0 )
+ {
+ fprintf( stderr, "error: ioctl(), get if index\n" );
+ goto gw_error;
+ }
+
+ can_addr.can_family = AF_CAN;
+ can_addr.can_ifindex = ifr.ifr_ifindex;
+// setsockopt( sock_can, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0 ); /*?!?*/
+
+ if( bind( sock_can, (struct sockaddr*) &can_addr, sizeof(can_addr) ) < 0 )
+ {
+ fprintf( stderr, "error: bind(), can" );
+ goto gw_error;
+ }
+
+ /* poll */
+ pfd[GW_POLL_ETH].fd = sock_udp;
+ pfd[GW_POLL_ETH].events = POLLIN | POLLPRI;
+ pfd[GW_POLL_ETH].revents = 0;
+
+ pfd[GW_POLL_CAN].fd = sock_can;
+ pfd[GW_POLL_CAN].events = POLLIN | POLLPRI;
+ pfd[GW_POLL_CAN].revents = 0;
+
+/*
+ unsigned char buf[1];
+ struct can_frame cf;
+ printf( "block\n" );
+ read( sock_can, &cf, sizeof(cf) ); again, return 0
+ printf( "can read\n" );
+*/
+
+ while(1)
+ {
+ printf( "polling\n" );
+ int polret = poll( pfd, 2, -1 );
+ if( polret <= 0 )
+ {
+ fprintf( stderr, "error: poll returned 0\n" );
+ }
+
+ if( pfd[GW_POLL_ETH].revents != 0 )
+ {
+ send_to_can();
+ }
+ if( pfd[GW_POLL_CAN].revents != 0 )
+ {
+ send_to_eth();
+ }
+
+ pfd[GW_POLL_ETH].revents = 0;
+ pfd[GW_POLL_CAN].revents = 0;
+ }
+
+ return 0;
+gw_error:
+ return -1;
+}
+