static int cegw_thread_start(void *data);
static int cegw_thread_stop(void);
+static int cegw_thread_recv_udp(void *data);
+static int cegw_thread_recv_can(void *data);
+
enum __cegw_state {
CEGW_RUN,
CEGW_STOP,
static int cegw_state = CEGW_STOP;
static struct socket *can_sock = NULL, *udp_sock = NULL;
+static struct socket *s_can = NULL, *s_eth = NULL;
static struct task_struct *eth_to_can = NULL, *can_to_eth = NULL;
static struct notifier_block notifier;
unsigned short port;
struct cegw_setting* set;
int err = 0;
+ int fd_eth, fd_can;
if (nlmsg_len(nlh) < sizeof(*r))
return -EINVAL;
return err;
}
+ fd_eth = *(int*)nla_data(tb[CEGW_ETH_SOCK]);
+ fd_can = *(int*)nla_data(tb[CEGW_CAN_SOCK]);
+
+ printk( "cegw: sock=%i,%i\n", fd_eth, fd_can );
+
+ s_can = sockfd_lookup( fd_can, &err );
+ s_eth = sockfd_lookup( fd_eth, &err );
+
+ if( s_can == NULL || s_eth == NULL )
+ {
+ printk( "error: socket look-up failed\n" );
+ return 0;
+ }
+
+ struct can_frame greet;
+ greet.can_id = 0;
+ greet.can_dlc = 4;
+ greet.data[0] = 7;
+
+ //cegw_can_send( s_can, &greet, *(int*)nla_data(tb[CEGW_CAN_IFINDEX]) );
+ kthread_run(cegw_thread_recv_udp, NULL, "canethgw");
+ kthread_run(cegw_thread_recv_can, NULL, "canethgw");
+ /*
if (tb[CEGW_CMD_INFO] == NULL) {
pr_devel("canethgw: CEGW_CMD_INFO is missing in rtmsg\n");
return -EINVAL;
}
+ */
+ return 0;
switch (*(int*)nla_data(tb[CEGW_CMD_INFO])) {
case CEGW_LISTEN:
if (!tb[CEGW_ETH_IP] || !tb[CEGW_ETH_PORT]) {
return NOTIFY_DONE;
}
-/**
- * cegw_thread_start - start working threads
- * @data: (struct cegw_setting *) with new listening address
- *
- * Two threads are started. One is serving udp->can routing and the other
- * can->udp.
- */
-static int cegw_thread_start(void *data)
+static int cegw_thread_recv_udp(void *data)
{
- struct sockaddr_in udp_addr;
- struct sockaddr_can can_addr;
- struct cegw_setting *set;
-
- set = (struct cegw_setting *)data;
-
- can_addr.can_family = AF_CAN;
- can_addr.can_ifindex = 0;
+ struct can_frame cf;
+ struct kvec vec;
+ struct msghdr mh;
+ struct sockaddr_in sa;
+ struct hlist_node* pos;
+ int can_ifidx;
+ int recv_size;
- udp_addr.sin_family = AF_INET;
- udp_addr.sin_port = htons(set->eth_port);
- udp_addr.sin_addr = set->eth_ip;
+ memset(&mh, 0, sizeof(mh));
+ mh.msg_name = &sa;
+ mh.msg_namelen = sizeof(sa);
+ mh.msg_control = NULL;
+ mh.msg_controllen = 0;
+ mh.msg_flags = 0;
- kfree(data);
- mutex_lock(&cegw_mutex);
- if (cegw_state == CEGW_EXIT)
- goto out_err;
+ printk( "udp receiving\n" );
- /* stops threads if exist */
- cegw_thread_stop();
+ while( 1 )
+ {
+ vec.iov_base = &cf;
+ vec.iov_len = sizeof(cf);
- /* create and bind sockets */
- if (sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &udp_sock)
- != 0) {
- printk(KERN_ERR "canethgw: udp socket creation failed\n");
- goto out_err;
+ recv_size = kernel_recvmsg(s_eth, &mh, &vec, 1,
+ sizeof(cf), 0);
+ printk("udp status=%i\n", recv_size);
}
- if (sock_create_kern(PF_CAN, SOCK_RAW, CAN_RAW, &can_sock) != 0) {
- printk(KERN_ERR "canethgw: can socket creation failed\n");
- sock_release(udp_sock);
- goto out_err;
- }
+ return 0;
+}
- if (kernel_bind(udp_sock, (struct sockaddr*)&udp_addr,
- sizeof(udp_addr)) != 0) {
- printk(KERN_ERR "canethgw: udp socket binding failed\n");
- sock_release(udp_sock);
- sock_release(can_sock);
- goto out_err;
- }
+static int cegw_thread_recv_can(void *data)
+{
+ struct can_frame cf;
+ struct kvec vec;
+ struct msghdr mh;
+ struct sockaddr_can ca;
+ struct hlist_node* pos;
+ int can_ifidx;
+ int recv_size;
- if (kernel_bind(can_sock, (struct sockaddr*) &can_addr,
- sizeof(can_addr)) != 0) {
- printk(KERN_ERR "canethgw: can socket binding failed\n");
- kernel_sock_shutdown(udp_sock, SHUT_RDWR);
- sock_release(udp_sock);
- sock_release(can_sock);
- goto out_err;
- }
+ memset(&mh, 0, sizeof(mh));
+ mh.msg_name = &ca;
+ mh.msg_namelen = sizeof(ca);
+ mh.msg_control = NULL;
+ mh.msg_controllen = 0;
+ mh.msg_flags = 0;
- /* start threads */
- cegw_state = CEGW_RUN;
+ printk( "can receiving\n" );
- eth_to_can = kthread_create(cegw_udp2can, NULL, "canethgw");
- if (IS_ERR(eth_to_can)) {
- cegw_state = CEGW_STOP;
- sock_release(udp_sock);
- sock_release(can_sock);
- goto out_err;
- }
- get_task_struct(eth_to_can);
- wake_up_process(eth_to_can);
-
- can_to_eth = kthread_create(cegw_can2udp, NULL, "canethgw");
- if (IS_ERR(can_to_eth)) {
- cegw_state = CEGW_STOP;
- kernel_sock_shutdown(udp_sock, SHUT_RDWR);
- kthread_stop(eth_to_can);
- sock_release(udp_sock);
- sock_release(can_sock);
- goto out_err;
+ while( 1 )
+ {
+ vec.iov_base = &cf;
+ vec.iov_len = sizeof(cf);
+
+ recv_size = kernel_recvmsg(s_can, &mh, &vec, 1,
+ sizeof(cf), 0);
+ printk("can status=%i\n", recv_size);
}
- get_task_struct(can_to_eth);
- wake_up_process(can_to_eth);
- mutex_unlock(&cegw_mutex);
- pr_devel("threads are running\n");
return 0;
-out_err:
- mutex_unlock(&cegw_mutex);
- return -1;
}
/**
unsigned short eth_listen_port;
};
-struct cegw_nlmsg
+struct cegw_nlmsg
{
struct nlmsghdr nh;
struct rtmsg rt;
unsigned int cegw_errno = 0;
-enum
+enum
{
CEGW_ERR_UNKNOWN,
CEGW_ERR_IF_UNSPEC,
char* delim = NULL;
char addrstr[16];
int addrlen;
-
+
if( (delim = strchr( in, ':' )) == NULL )
{
cegw_errno = CEGW_ERR_COLON;
char* read_iftype( char* in, int* iftype )
{
char* ret = in+4;
-
+
if( strncmp( "udp@", optarg, 4 ) == 0 )
{
*iftype = IF_ETH_UDP;
*iftype = IF_CAN;
return ret;
}
-
+
cegw_errno = CEGW_ERR_IF_TYPE;
return NULL;
}
{
req->nh.nlmsg_type = RTM_GETROUTE;
req->nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
-
+
return 0;
}
struct rtattr* rta;
int len;
struct list_item li;
+ int gw_can_sock = 0;
+ int gw_eth_sock = 0;
+ struct sockaddr_in gw_eth_addr;
+ struct sockaddr_can gw_can_addr;
+ struct in_addr addr;
memset( &d, 0, sizeof(d) );
- struct option long_opt[] =
- {
- { "add" , 0, NULL, 'A' },
- { "flush" , 0, NULL, 'F' },
- { "list" , 0, NULL, 'L' },
- { "listen", 1, NULL, 'l' },
- { 0, 0, 0, 0 }
- };
-
- while( 1 )
- {
- opt = getopt_long( argc, argv, "AFLl:s:d:", long_opt, NULL );
- if( opt == -1 )
- break;
+ /* create sockets for gateway */
+ gw_eth_sock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
+ gw_can_sock = socket( PF_CAN, SOCK_RAW, CAN_RAW );
- switch( opt )
- {
- case 'A':
- cmd |= CEGW_CMD_ADD;
- break;
- case 'F':
- cmd |= CEGW_CMD_FLUSH;
- break;
- case 'L':
- cmd |= CEGW_CMD_LIST;
- break;
- case 'l':
- cmd |= CEGW_CMD_LISTEN;
- if( (optstr = read_iftype( optarg, &tmp )) == NULL )
- {
- perr( "'--listen'" );
- return -1;
- }
- if( tmp != IF_ETH_UDP )
- {
- perr( "'--listen' expects udp interface" );
- return -1;
- }
- if( read_addrport( optstr, &d.eth_listen_addr, &d.eth_listen_port ) )
- {
- perr( "'--listen'" );
- return -1;
- }
- break;
- case 's':
- if( read_if( optarg, &d.src_if, &d ) != 0 )
- {
- perr( "'-s'" );
- return -1;
- }
- break;
- case 'd':
- if( read_if( optarg, &d.dst_if, &d ) != 0 )
- {
- perr( "'-d'" );
- return -1;
- }
- break;
- case '?':
- return -1;
- break;
- default:
- perr( "unknown option" );
- return -1;
- break;
- }
- }
+ if( gw_eth_sock == -1 )
+ fprintf( stderr, "error: udp socket for gw creation failed\n" );
+ if( gw_can_sock == -1 )
+ fprintf( stderr, "error: can socket for gw creation failed\n" );
+
+ gw_eth_addr.sin_family = AF_INET;
+ gw_eth_addr.sin_port = htons( 10501 );
+ gw_eth_addr.sin_addr.s_addr = INADDR_ANY;
+
+ gw_can_addr.can_family = AF_CAN;
+ gw_can_addr.can_ifindex = 0;
+
+ if( bind( gw_eth_sock, (struct sockaddr*)&gw_eth_addr, sizeof(gw_eth_addr) ) != 0 )
+ fprintf( stderr, "error: eth binding\n" );
+ if( bind( gw_can_sock, (struct sockaddr*)&gw_can_addr, sizeof(gw_can_addr) ) )
+ fprintf( stderr, "error: can binding\n" );
+
+ printf( "sockets created (%i,%i)\n", gw_can_sock, gw_eth_sock );
/* prepare netlink message */
req.nh.nlmsg_len = NLMSG_LENGTH( sizeof(struct rtmsg) );
- //req.nh.nlmsg_type;
+ req.nh.nlmsg_type = RTM_NEWROUTE;
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
req.nh.nlmsg_seq = 0;
req.nh.nlmsg_pid = 0; /* ? */
memset( &req.rt, 0, sizeof(req.rt) );
req.rt.rtm_family = AF_CAN;
- switch( cmd )
- {
- case 0:
- perr( "command not specified" );
- return -1;
- break;
- case CEGW_CMD_ADD:
- if( cegw_add( &req, &d ) != 0 )
- {
- perr( "'--add'" );
- return -1;
- }
- break;
- case CEGW_CMD_FLUSH:
- cegw_flush( &req, &d );
- break;
- case CEGW_CMD_LIST:
- cegw_list( &req, &d );
- break;
- case CEGW_CMD_LISTEN:
- cegw_listen( &req, &d );
- break;
- default:
- perr( "command mismatch" );
- break;
- }
+ addattr32( &req.nh, sizeof(req), CEGW_CAN_SOCK, gw_can_sock );
+ addattr32( &req.nh, sizeof(req), CEGW_ETH_SOCK, gw_eth_sock );
+ addattr32( &req.nh, sizeof(req), CEGW_CAN_IFINDEX, if_nametoindex("vcan0") );
/* send over netlink socket */
s = socket( PF_NETLINK, SOCK_RAW, NETLINK_ROUTE ); /* chck */
-
+
memset( &nladdr, 0, sizeof(nladdr) );
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pad = 0;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
- err = sendto( s, &req, req.nh.nlmsg_len, 0,
+ err = sendto( s, &req, req.nh.nlmsg_len, 0,
(struct sockaddr*)&nladdr, sizeof(nladdr) );
if( err < 0 )
{
perror( "netlink sendto" );
return -1;
}
-
+
/* recv */
rsize = recv( s, &rxbuf, sizeof(rxbuf), 0 );
if( rsize < 0 )
}
nlh = (struct nlmsghdr*)rxbuf;
+ /* REMOVE */
+ sleep( 2 );
+ //printf( "closing sockets\n" );
+ //shutdown( gw_eth_sock, SHUT_RDWR );
+ shutdown( gw_can_sock, SHUT_RDWR );
+ //close( gw_can_sock );
+ //close( gw_eth_sock );
+
if( nlh->nlmsg_type == NLMSG_ERROR )
{
rte = (struct nlmsgerr*)NLMSG_DATA( nlh );