1 #include "gw.h" /* override */
3 #include <linux/module.h>
4 #include <linux/kernel.h>
5 #include <linux/kthread.h>
6 #include <linux/sched.h>
7 #include <linux/delay.h>
8 #include <linux/wait.h>
9 #include <linux/netdevice.h>
10 #include <linux/socket.h>
11 #include <linux/net.h>
12 #include <linux/can/core.h>
13 #include <linux/can.h>
14 #include <net/rtnetlink.h>
17 MODULE_LICENSE( "GPL" );
19 static struct task_struct* eth_to_can, * can_to_eth;
20 static struct socket* udp_sock;
21 static struct socket* can_sock;
22 static struct net_device* can_dev;
27 struct in_addr dst_addr;
28 unsigned short dst_port;
29 struct hlist_node list;
35 struct hlist_node list;
38 HLIST_HEAD( can_eth_job );
39 HLIST_HEAD( eth_can_job );
43 struct can_filter filter;
46 struct in_addr dst_addr;
47 unsigned short dst_port;
50 /***********************
52 ***********************/
54 static int gw_udp_recv( void* data )
59 struct eth_can_gw* job;
60 struct hlist_node* pos;
63 vec.iov_len = sizeof(cf);
69 mh.msg_control = NULL;
70 mh.msg_controllen = 0;
75 if( kthread_should_stop() ) /* up() ?, recv is blocking */
77 kernel_recvmsg( udp_sock, &mh, &vec, 1, sizeof(cf), 0 ); /* todo: handle error */
78 printk( "received udp msg_id:%d\n", cf.can_id );
80 hlist_for_each_entry_rcu( job, pos, ð_can_job, list )
82 /* ToDo from filter */
83 gw_can_send( &cf, job->dst_if_idx );
91 inline static void gw_udp_send( struct can_frame* cf, struct in_addr ipaddr, u16 port )
94 struct sockaddr_in addr;
97 addr.sin_family = AF_INET;
98 addr.sin_port = htons( port );
99 addr.sin_addr = ipaddr;
102 mh.msg_namelen = sizeof( addr );
103 mh.msg_control = NULL;
104 mh.msg_controllen = 0;
108 vec.iov_len = sizeof( *cf );
110 kernel_sendmsg( udp_sock, &mh, &vec, 1, sizeof( *cf ) );
113 /***********************
115 ***********************/
117 static int gw_can_recv( void* data )
122 struct sockaddr_can ca;
123 struct can_eth_gw* job;
124 struct hlist_node* pos;
127 mh.msg_namelen = sizeof( ca );
128 mh.msg_control = NULL;
129 mh.msg_controllen = 0;
133 vec.iov_len = sizeof( cf );
137 if( kthread_should_stop() ) /**/
139 kernel_recvmsg( can_sock, &mh, &vec, 1, sizeof( cf ), 0 );
140 printk( "received can msg_id:%d, from:%d\n", cf.can_id, ca.can_ifindex );
142 hlist_for_each_entry_rcu( job, pos, &can_eth_job, list )
144 printk( KERN_INFO "%x\n", job->dst_addr );
145 if( job->src_if_idx == ca.can_ifindex )
146 gw_udp_send( &cf, job->dst_addr, job->dst_port );
154 inline static void gw_can_send( struct can_frame* cf, int ifidx )
158 struct sockaddr_can ca =
160 .can_family = AF_CAN,
165 mh.msg_namelen = sizeof( ca );
166 mh.msg_control = NULL;
167 mh.msg_controllen = 0;
171 vec.iov_len = sizeof( *cf );
173 kernel_sendmsg( can_sock, &mh, &vec, 1, sizeof( *cf ) );
178 static int cgw_create_job( struct sk_buff* skb, struct nlmsghdr* nlh,
181 struct nlattr* tb[ CGW_MAX+1 ];
184 struct can_eth_gw* cethgw = NULL;
185 struct eth_can_gw* ecangw = NULL;
188 if (nlmsg_len(nlh) < sizeof(*r))
192 if (r->can_family != AF_CAN)
193 return -EPFNOSUPPORT;
195 err = nlmsg_parse( nlh, sizeof( struct rtcanmsg ), tb, CGW_MAX, NULL );
198 printk( KERN_ERR "error: nlmsg_parse\n" );
202 /* so far we only support CAN -> CAN routings */
205 case CGW_TYPE_CAN_ETH_UDP:
206 printk( KERN_INFO "can:%d\n", *(int*)nla_data( tb[CGW_CAN_IF] ) );
207 printk( KERN_INFO "eth addr:%x\n", *(u32*)nla_data( tb[CGW_ETH_IP] ) );
208 printk( KERN_INFO "eth port:%hu\n", *(u16*)nla_data( tb[CGW_ETH_PORT] ) );
209 cethgw = kmalloc( sizeof(struct can_eth_gw), GFP_KERNEL );
212 printk( KERN_ERR "error: kmalloc\n" );
215 cethgw->src_if_idx = *(int*)nla_data( tb[CGW_CAN_IF] );
216 cethgw->dst_addr = *(struct in_addr*)nla_data( tb[CGW_ETH_IP] );
217 cethgw->dst_port = *(u16*)nla_data( tb[CGW_ETH_PORT] );
219 hlist_add_head_rcu( &cethgw->list, &can_eth_job );
221 case CGW_TYPE_ETH_CAN_UDP:
222 printk( KERN_INFO "can:%d\n", *(int*)nla_data( tb[CGW_CAN_IF] ) );
223 ecangw = kmalloc( sizeof(struct eth_can_gw), GFP_KERNEL );
226 printk( KERN_ERR "error: kmalloc\n" );
229 ecangw->dst_if_idx = *(int*)nla_data( tb[CGW_CAN_IF] );
230 hlist_add_head_rcu( &ecangw->list, ð_can_job );
233 /* ToDo undef operation */
240 /***********************
242 ***********************/
244 static int __init cangw_init( void )
246 struct sockaddr_in udp_addr;
247 struct sockaddr_can can_addr;
250 /* 1. create can socket and bind to it */
251 can_dev = dev_get_by_name( &init_net, "vcan0" ); /* net ns?, release counter! */
252 if( can_dev == NULL )
254 printk( KERN_ERR "error: vcan0 not found\n" );
257 ifidx = can_dev->ifindex;
260 if( sock_create_kern( PF_CAN, SOCK_RAW, CAN_RAW, &can_sock) != 0 )
262 printk( KERN_ERR "error: can_sock creation failed\n" );
266 can_addr.can_family = AF_CAN;
267 can_addr.can_ifindex = ifidx;
269 if( can_sock->ops->bind( can_sock, (struct sockaddr*) &can_addr, sizeof(can_addr) ) != 0 )
271 printk( KERN_ERR "can_sock bind failed\n" );
275 /* 2. create udp socket and bind to it */
276 if( sock_create_kern( PF_INET, SOCK_DGRAM, IPPROTO_UDP, &udp_sock ) != 0 )
278 printk( "error: udp_sock creation failed\n" );
279 sock_release( can_sock );
283 udp_addr.sin_family = AF_INET;
284 udp_addr.sin_port = htons( 10501 );
285 udp_addr.sin_addr.s_addr = INADDR_ANY;
287 if( udp_sock->ops->bind( udp_sock, (struct sockaddr*)&udp_addr, sizeof( udp_addr ) ) != 0 ) /* ref impl ?!? */
289 printk( "error: binding failed\n" );
290 sock_release( udp_sock );
291 sock_release( can_sock );
295 /* 3. subscribe to netlink */
296 //if( __rtnl_register( PF_CAN, RTM_GETROUTE, ) != 0 )
297 __rtnl_register( PF_CAN, RTM_NEWROUTE, cgw_create_job, NULL, NULL );
298 //__rtnl_register( PF_CAN, RTM_DELROUTE, )
301 eth_to_can = kthread_run( gw_udp_recv, NULL, "cangw" );
302 can_to_eth = kthread_run( gw_can_recv, NULL, "cangw" );
305 if( sock_create_kern( AF_CAN, SOCK_RAW, CAN_RAW, &can_sock ) != 0 )
307 printk( "error: can_sock creation failed\n" );
314 static void __exit cangw_exit( void )
316 sock_release( udp_sock );
317 sock_release( can_sock );
319 printk( "cangw: exit\n" );
320 //kthread_stop( ts );
323 module_init( cangw_init );
324 module_exit( cangw_exit );