#include <stdlib.h>
#include <libgen.h>
#include <string.h>
-#include <unistd.h>
+#include <getopt.h>
#include <errno.h>
#include <sys/socket.h>
#include <net/if.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <arpa/inet.h>
-#include <gw.h>
+#include <linux/can.h>
+#include <linux/types.h>
+#include "canethgw.h"
/**
* ToDo
- * - refactor error messages
- * */
+ * [ ] refactor error messages
+ * [ ] start/stop listening
+ * [ ] remove routing job
+ * [ ] recv netlink reponse
+ *
+ */
+
+#define CMD_STOP_LISTEN 1
+#define CMD_START_LISTEN 2
+#define CMD_ADD_RULE 4
enum {
IF_UNDEF,
IF_ETH_UDP
};
+
+/**
+ * parses @in for eth address, valid input is
+ * e.g. udp@127.0.0.1:10502 or can@vcan0
+ *
+ * @param[out] addr ip address
+ * @param[out] port transport layer port
+ * @return 0 on success
+ */
int read_addr_port( char* in, struct in_addr* addr, unsigned short* port )
{
char* delim = NULL;
int src_if = 0, dst_if = 0;
int can_ifidx = 0;
int tmp = 0;
- int have_listen = 0;
+ int cmd = 0;
struct in_addr eth_addr;
unsigned short eth_port;
struct in_addr eth_listen_addr;
char opt;
struct sockaddr_nl nladdr;
int err = 0;
+
+ struct option long_opt[] =
+ {
+ { "start-listen", 1, NULL, 'l' },
+ { "stop-listen" , 1, NULL, 'k' },
+ { 0, 0, 0, 0 }
+ };
struct {
struct nlmsghdr nh;
char buf[600]; /* enough? */
} req;
- while( (opt = getopt( argc, argv, "As:d:l:" )) != -1 )
+ while( 1 )
{
+ opt = getopt_long( argc, argv, "As:d:", long_opt, NULL );
+ if( opt == -1 )
+ break;
+
switch( opt )
{
case 's':
+ cmd |= CMD_ADD_RULE;
if( (optstr = read_iftype( optarg, &src_if )) == NULL )
{
fprintf( stderr, "error: bad input format\n" );
}
break;
case 'd':
+ cmd |= CMD_ADD_RULE;
if( (optstr = read_iftype( optarg, &dst_if )) == NULL )
{
fprintf( stderr, "error: bad input format\n" );
}
break;
case 'l':
+ cmd |= CMD_START_LISTEN;
if( (optstr = read_iftype( optarg, &tmp )) == NULL )
{
fprintf( stderr, "error: -l bad input format\n" );
}
read_addr_port( optstr, ð_listen_addr, ð_listen_port ); /*chk*/
+ case 'k':
+ cmd |= CMD_STOP_LISTEN;
+ break;
+ case '?':
+ break;
default:
fprintf( stderr, "error: unknown option\n" );
break;
}
/* 2. do check on arguments */
- if( (src_if == 0 || dst_if == 0) || (src_if == dst_if) )
+ if( cmd & CMD_ADD_RULE )
{
- fprintf( stderr, "error: source or destination not specified\n" );
- return -1;
- }
+ if( (src_if == 0 || dst_if == 0) || (src_if == dst_if) )
+ {
+ fprintf( stderr, "error: source or destination not specified\n" );
+ return -1;
+ }
- if( src_if == dst_if )
- {
- fprintf( stderr, "error: source and destination same interface type\n" );
+ if( src_if == dst_if )
+ {
+ fprintf( stderr, "error: source and destination same interface type\n" );
+ }
}
/* 3. prepare netlink message */
req.nh.nlmsg_pid = 0; /* ? */
req.rtcan.can_family = AF_CAN;
- req.rtcan.gwtype = (src_if == IF_CAN) ? CGW_TYPE_CAN_ETH_UDP : CGW_TYPE_ETH_CAN_UDP;
req.rtcan.flags = 0;
-
- addattr_l( &req.nh, sizeof(req), CGW_CAN_IF, &can_ifidx, sizeof(can_ifidx) );
- switch( req.rtcan.gwtype )
+
+ if( cmd & CMD_ADD_RULE )
{
- case CGW_TYPE_CAN_ETH_UDP:
- addattr_l( &req.nh, sizeof(req), CGW_ETH_IP, ð_addr, sizeof(eth_addr) );
- addattr_l( &req.nh, sizeof(req), CGW_ETH_PORT, ð_port, sizeof(eth_port) );
- break;
- case CGW_TYPE_ETH_CAN_UDP:
- break;
- default:
- break;
+ req.rtcan.gwtype = (src_if == IF_CAN) ? CGW_TYPE_CAN_ETH_UDP : CGW_TYPE_ETH_CAN_UDP;
+ addattr_l( &req.nh, sizeof(req), CGW_CAN_IF, &can_ifidx, sizeof(can_ifidx) );
+ switch( req.rtcan.gwtype )
+ {
+ case CGW_TYPE_CAN_ETH_UDP:
+ addattr_l( &req.nh, sizeof(req), CGW_ETH_IP, ð_addr, sizeof(eth_addr) );
+ addattr_l( &req.nh, sizeof(req), CGW_ETH_PORT, ð_port, sizeof(eth_port) );
+ break;
+ case CGW_TYPE_ETH_CAN_UDP:
+ break;
+ default:
+ break;
+ }
}
- if( have_listen )
+ if( cmd & CMD_START_LISTEN )
{
+ req.rtcan.gwtype = CGW_TYPE_CONFIG;
addattr_l( &req.nh, sizeof(req), CGW_LISTEN_IP, ð_listen_addr, sizeof(eth_listen_addr) );
addattr_l( &req.nh, sizeof(req), CGW_LISTEN_PORT, ð_listen_port, sizeof(eth_listen_port) );
+ printf( "start listen: %x, %hu\n", eth_listen_addr, eth_listen_port );
}
/* 4. send over netlink socket */
syntax_error:
return -1;
}
+