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/if_arp.h>
12 #include <linux/net.h>
13 #include <linux/netdevice.h>
14 #include <linux/can/core.h>
15 #include <linux/can.h>
16 #include <net/rtnetlink.h>
19 #include <linux/completion.h>
20 #include <linux/mutex.h>
21 #include <net/inet_common.h>
23 MODULE_LICENSE( "GPL" );
25 static int cegw_udp_can( void* data );
26 inline static void cegw_udp_send( struct socket* udp_sock, struct can_frame* cf, struct in_addr ipaddr, u16 port );
27 static int cegw_can_udp( void* data );
28 inline static void cegw_can_send( struct socket* can_sock, struct can_frame* cf, int ifindex );
29 static int cegw_thread_start( void* data );
30 static int cegw_thread_stop( void );
42 struct in_addr eth_ip;
43 unsigned short eth_port;
44 struct hlist_node list;
49 struct in_addr eth_ip;
50 unsigned short eth_port;
53 static int cegw_state = CEGW_STOP;
54 static struct socket* can_sock = NULL, * udp_sock = NULL;
55 static struct task_struct* eth_to_can = NULL, * can_to_eth = NULL;
56 static struct notifier_block notifier;
58 HLIST_HEAD( cegw_rule_can_eth );
59 HLIST_HEAD( cegw_rule_eth_can );
60 DEFINE_MUTEX( cegw_mutex );
62 inline static void cegw_udp_send( struct socket* udp_sock, struct can_frame* cf, struct in_addr ipaddr, u16 port )
65 struct sockaddr_in addr;
68 addr.sin_family = AF_INET;
69 addr.sin_port = htons( port );
70 addr.sin_addr = ipaddr;
73 mh.msg_namelen = sizeof( addr );
74 mh.msg_control = NULL;
75 mh.msg_controllen = 0;
79 vec.iov_len = sizeof( *cf );
81 kernel_sendmsg( udp_sock, &mh, &vec, 1, sizeof( *cf ) );
84 inline static void cegw_can_send( struct socket* can_sock, struct can_frame* cf, int ifindex )
88 struct sockaddr_can addr;
90 addr.can_family = AF_CAN;
91 addr.can_ifindex = ifindex;
94 mh.msg_namelen = sizeof( addr );
95 mh.msg_control = NULL;
96 mh.msg_controllen = 0;
100 vec.iov_len = sizeof( *cf );
102 kernel_sendmsg( can_sock, &mh, &vec, 1, sizeof( *cf ) );
106 * cegw_udp_can - performs udp->can routing
107 * This function is run as a thread.
109 static int cegw_udp_can( void* data )
114 struct cegw_rule* rule;
115 struct hlist_node* pos;
123 mh.msg_control = NULL;
124 mh.msg_controllen = 0;
129 if( cegw_state == CEGW_STOP )
132 vec.iov_len = sizeof(cf);
133 recv_size = kernel_recvmsg( udp_sock, &mh, &vec, 1, sizeof(cf), 0 );
134 /* recv_size == 0 when shutting down */
135 if( recv_size != sizeof(cf) || recv_size == 0 )
138 } else if( recv_size < 0 )
143 hlist_for_each_entry_rcu( rule, pos, &cegw_rule_eth_can, list )
146 can_ifidx = rule->can_ifindex;
148 /* ToDo: from filter */
149 cegw_can_send( can_sock, &cf, can_ifidx );
157 * cegw_can_udp - performs can->udp routing
159 static int cegw_can_udp( void* data )
164 struct sockaddr_can ca;
165 struct cegw_rule* rule;
166 struct hlist_node* pos;
167 struct in_addr eth_ip;
172 mh.msg_namelen = sizeof( ca );
173 mh.msg_control = NULL;
174 mh.msg_controllen = 0;
179 if( cegw_state == CEGW_STOP )
182 vec.iov_len = sizeof( cf );
184 recv_size = kernel_recvmsg( can_sock, &mh, &vec, 1, sizeof( cf ), 0 );
185 if( recv_size != sizeof(cf) || recv_size == 0 )
188 } else if( recv_size < 0 )
193 hlist_for_each_entry_rcu( rule, pos, &cegw_rule_can_eth, list )
196 eth_ip = rule->eth_ip;
197 eth_port = rule->eth_port;
199 if( rule->can_ifindex == ca.can_ifindex )
200 cegw_udp_send( udp_sock, &cf, eth_ip, eth_port );
207 static int cegw_newroute( struct sk_buff* skb, struct nlmsghdr* nlh, void* arg )
209 struct nlattr* tb[ CEGW_MAX+1 ];
210 struct cegw_rule* rule = NULL;
215 struct cegw_setting* set;
218 if( nlmsg_len(nlh) < sizeof(*r) )
221 r = nlmsg_data( nlh );
223 if( r->rtm_family != AF_CAN )
224 return -EPFNOSUPPORT;
226 err = nlmsg_parse( nlh, sizeof(*r), tb, CEGW_MAX, NULL );
229 pr_devel( "canethgw: nlmsg_parse error\n" );
233 if( tb[CEGW_CMD_INFO] == NULL )
235 pr_devel( "canethgw: CEGW_CMD_INFO is missing in rtmsg\n" );
239 switch( *(int*)nla_data( tb[CEGW_CMD_INFO] ) )
242 if( !tb[CEGW_ETH_IP] || !tb[CEGW_ETH_PORT] )
244 pr_devel( "canethgw: missing attribute for CEGW_LISTEN\n" );
248 /* ToDo: valid listen address */
249 set = kmalloc( sizeof(*set), GFP_KERNEL );
250 set->eth_ip = *(struct in_addr*)nla_data( tb[CEGW_ETH_IP] );
251 set->eth_port = *(unsigned short*)nla_data( tb[CEGW_ETH_PORT] );
252 kthread_run( cegw_thread_start, set, "canethgw" );
254 case CEGW_RULE_CAN_ETH:
255 if( !tb[CEGW_ETH_IP] || !tb[CEGW_ETH_PORT] || !tb[CEGW_CAN_IFINDEX] )
257 pr_devel( "canethgw: missing attribute for CEGW_RULE_CAN_ETH\n" );
261 ifindex = *(int*)nla_data( tb[CEGW_CAN_IFINDEX] );
262 ip = *(struct in_addr*)nla_data( tb[CEGW_ETH_IP] );
263 port = *(unsigned short*)nla_data( tb[CEGW_ETH_PORT] );
264 pr_devel( "canethgw: new can->eth rule - (%d)->(%x:%hu)\n", ifindex, ip.s_addr, port );
266 rule = kmalloc( sizeof(struct cegw_rule), GFP_KERNEL );
272 rule->can_ifindex = ifindex;
274 rule->eth_port = port;
276 hlist_add_head_rcu( &rule->list, &cegw_rule_can_eth );
278 case CEGW_RULE_ETH_CAN:
279 if( !tb[CEGW_ETH_IP] || !tb[CEGW_ETH_PORT] || !tb[CEGW_CAN_IFINDEX] )
281 pr_devel( "canethgw: missing attribute for CEGW_RULE_ETH_CAN\n" );
285 ifindex = *(int*)nla_data( tb[CEGW_CAN_IFINDEX] );
286 ip = *(struct in_addr*)nla_data( tb[CEGW_ETH_IP] );
287 port = *(unsigned short*)nla_data( tb[CEGW_ETH_PORT] );
288 pr_devel( "canethgw: new eth->can rule - (%x:%hu)->(%d)\n", ip.s_addr, port, ifindex );
290 rule = kmalloc( sizeof(struct cegw_rule), GFP_KERNEL );
296 rule->can_ifindex = ifindex;
298 rule->eth_port = port;
300 hlist_add_head_rcu( &rule->list, &cegw_rule_eth_can );
303 pr_devel( "canethgw: unknown CEGW_CMD_INFO\n" );
310 static void cegw_flush( void )
312 struct cegw_rule* rule;
313 struct hlist_node* pos,* n;
315 hlist_for_each_entry_safe( rule, pos, n, &cegw_rule_can_eth, list )
317 hlist_del( &rule->list );
320 hlist_for_each_entry_safe( rule, pos, n, &cegw_rule_eth_can, list )
322 hlist_del( &rule->list );
327 static int cegw_delroute( struct sk_buff* skb, struct nlmsghdr* nlh, void* arg )
330 struct nlattr* tb[ CEGW_MAX+1 ];
333 if( nlmsg_len(nlh) < sizeof(*r) )
336 r = nlmsg_data( nlh );
338 if( r->rtm_family != AF_CAN )
339 return -EPFNOSUPPORT;
341 err = nlmsg_parse( nlh, sizeof(struct rtmsg), tb, CEGW_MAX, NULL );
345 if( tb[CEGW_CMD_INFO] == NULL )
347 pr_devel( "canethgw: CEGW_CMD_INFO is missing in rtmsg\n" );
351 if( *(int*)nla_data( tb[CEGW_CMD_INFO] ) != CEGW_FLUSH )
361 static int cegw_put_rule( struct sk_buff* skb, int type, struct cegw_rule* rule )
366 struct nlmsghdr* nlh;
368 ifindex = rule->can_ifindex;
370 port = rule->eth_port;
372 nlh = nlmsg_put( skb, 0, 0, 0, 0, 0 );
377 if( nla_put( skb, CEGW_TYPE, sizeof(type), &type ) < 0 )
380 nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN( sizeof(type) );
383 if( nla_put( skb, CEGW_CAN_IFINDEX, sizeof(ifindex), &ifindex ) < 0 )
386 nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN( sizeof(ifindex) );
389 if( nla_put( skb, CEGW_ETH_IP, sizeof(ip), &ip) < 0 )
392 nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN( sizeof(ip) );
395 if( nla_put( skb, CEGW_ETH_PORT, sizeof(port), &port ) < 0 )
398 nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN( sizeof(port) );
403 nlmsg_cancel( skb, nlh );
407 static int cegw_getroute( struct sk_buff* skb, struct netlink_callback* cb )
409 struct cegw_rule* rule;
410 struct hlist_node* pos;
412 int s_idx = cb->args[0];
414 /* ToDo: skb max size */
417 hlist_for_each_entry_rcu( rule, pos, &cegw_rule_eth_can, list )
422 if( cegw_put_rule( skb, CEGW_RULE_ETH_CAN, rule ) < 0 )
430 hlist_for_each_entry_rcu( rule, pos, &cegw_rule_can_eth, list )
435 if( cegw_put_rule( skb, CEGW_RULE_CAN_ETH, rule ) < 0 )
449 static int cegw_notifier( struct notifier_block* nb, unsigned long msg, void* data )
451 struct net_device* dev = (struct net_device*)data;
452 struct cegw_rule* rule;
453 struct hlist_node* pos,* n;
455 if( !net_eq(dev_net(dev), &init_net) )
457 if( dev->type != ARPHRD_CAN )
460 if( msg == NETDEV_UNREGISTER )
462 hlist_for_each_entry_safe( rule, pos, n, &cegw_rule_eth_can, list )
464 if( rule->can_ifindex == dev->ifindex )
466 hlist_del( &rule->list );
471 hlist_for_each_entry_safe( rule, pos, n, &cegw_rule_can_eth, list )
473 if( rule->can_ifindex == dev->ifindex )
475 hlist_del( &rule->list );
485 * cegw_thread_start - start working threads
486 * Two threads are started. One is serving udp->can routing and the other
489 * @return 0 on success, -1 otherwise
491 static int cegw_thread_start( void* data )
493 struct sockaddr_in udp_addr;
494 struct sockaddr_can can_addr;
495 struct cegw_setting* set;
497 set = (struct cegw_setting*)data;
499 can_addr.can_family = AF_CAN;
500 can_addr.can_ifindex = 0;
502 udp_addr.sin_family = AF_INET;
503 udp_addr.sin_port = htons( set->eth_port );
504 udp_addr.sin_addr = set->eth_ip;
507 mutex_lock( &cegw_mutex );
508 if( cegw_state == CEGW_EXIT )
510 /* stops threads if exist */
513 /* create and bind sockets */
514 if( sock_create_kern( PF_INET, SOCK_DGRAM, IPPROTO_UDP, &udp_sock) != 0 )
516 printk( KERN_ERR "canethgw: udp socket creation failed\n" );
520 if( sock_create_kern( PF_CAN, SOCK_RAW, CAN_RAW, &can_sock) != 0 )
522 printk( KERN_ERR "canethgw: can socket creation failed\n" );
526 if( kernel_bind( udp_sock, (struct sockaddr*)&udp_addr, sizeof( udp_addr ) ) != 0 )
528 printk( KERN_ERR "canethgw: udp socket binding failed\n" );
529 sock_release( udp_sock );
530 sock_release( can_sock );
534 if( kernel_bind( can_sock, (struct sockaddr*) &can_addr, sizeof(can_addr) ) != 0 )
536 printk( KERN_ERR "canethgw: can socket binding failed\n" );
537 kernel_sock_shutdown( udp_sock, SHUT_RDWR );
538 sock_release( udp_sock );
539 sock_release( can_sock );
544 cegw_state = CEGW_RUN;
546 eth_to_can = kthread_create( cegw_udp_can, NULL, "canethgw" );
547 if( IS_ERR( eth_to_can ) )
549 cegw_state = CEGW_STOP;
550 sock_release( udp_sock );
551 sock_release( can_sock );
554 get_task_struct( eth_to_can );
555 wake_up_process( eth_to_can );
557 can_to_eth = kthread_create( cegw_can_udp, NULL, "canethgw" );
558 if( IS_ERR( can_to_eth ) )
560 cegw_state = CEGW_STOP;
561 kernel_sock_shutdown( udp_sock, SHUT_RDWR );
562 kthread_stop( eth_to_can );
563 sock_release( udp_sock );
564 sock_release( can_sock );
567 /* ToDo: free this? */
568 get_task_struct( can_to_eth );
569 wake_up_process( can_to_eth );
571 mutex_unlock( &cegw_mutex );
572 pr_devel( "threads are running\n" );
578 * Waits for threads to stop. Does nothing if cegw_state == CEGW_STOP.
582 static int cegw_thread_stop( void )
585 struct sock* sk = NULL;
587 if( cegw_state == CEGW_STOP )
590 cegw_state = CEGW_STOP;
591 /* shut down socket */
595 sk->sk_shutdown |= how;
596 sk->sk_state_change( sk );
599 kernel_sock_shutdown( udp_sock, SHUT_RDWR );
601 /* wait for return to reuse port if restart */
602 kthread_stop( eth_to_can );
603 kthread_stop( can_to_eth );
604 sock_release( udp_sock );
605 sock_release( can_sock );
612 static int __init cegw_init( void )
614 notifier.notifier_call = cegw_notifier;
615 register_netdevice_notifier( ¬ifier );
617 /* subscribe to netlink */
618 rtnl_register( PF_CAN, RTM_GETROUTE, NULL, cegw_getroute, NULL );
619 rtnl_register( PF_CAN, RTM_NEWROUTE, cegw_newroute, NULL, NULL );
620 rtnl_register( PF_CAN, RTM_DELROUTE, cegw_delroute, NULL, NULL );
625 static void __exit cegw_exit( void )
627 /* ToDo: effect on cangw? */
628 rtnl_unregister_all( PF_CAN );
630 /* wait for rtnl callbacks */
634 mutex_lock( &cegw_mutex );
636 cegw_state = CEGW_EXIT;
637 mutex_unlock( &cegw_mutex );
639 unregister_netdevice_notifier( ¬ifier );
643 module_init( cegw_init );
644 module_exit( cegw_exit );